ALSA: hda/realtek - Fix auto-mute with HP+LO configuration
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / sound / pci / hda / patch_realtek.c
blob95e1ff3276338e0c5c0719bce37955e857eb1edd
1 /*
2 * Universal Interface for Intel High Definition Audio Codec
4 * HD audio interface patch for ALC 260/880/882 codecs
6 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
8 * Takashi Iwai <tiwai@suse.de>
9 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <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 <sound/jack.h>
32 #include "hda_codec.h"
33 #include "hda_local.h"
34 #include "hda_beep.h"
36 #define ALC880_FRONT_EVENT 0x01
37 #define ALC880_DCVOL_EVENT 0x02
38 #define ALC880_HP_EVENT 0x04
39 #define ALC880_MIC_EVENT 0x08
41 /* ALC880 board config type */
42 enum {
43 ALC880_3ST,
44 ALC880_3ST_DIG,
45 ALC880_5ST,
46 ALC880_5ST_DIG,
47 ALC880_W810,
48 ALC880_Z71V,
49 ALC880_6ST,
50 ALC880_6ST_DIG,
51 ALC880_F1734,
52 ALC880_ASUS,
53 ALC880_ASUS_DIG,
54 ALC880_ASUS_W1V,
55 ALC880_ASUS_DIG2,
56 ALC880_FUJITSU,
57 ALC880_UNIWILL_DIG,
58 ALC880_UNIWILL,
59 ALC880_UNIWILL_P53,
60 ALC880_CLEVO,
61 ALC880_TCL_S700,
62 ALC880_LG,
63 ALC880_LG_LW,
64 ALC880_MEDION_RIM,
65 #ifdef CONFIG_SND_DEBUG
66 ALC880_TEST,
67 #endif
68 ALC880_AUTO,
69 ALC880_MODEL_LAST /* last tag */
72 /* ALC260 models */
73 enum {
74 ALC260_BASIC,
75 ALC260_HP,
76 ALC260_HP_DC7600,
77 ALC260_HP_3013,
78 ALC260_FUJITSU_S702X,
79 ALC260_ACER,
80 ALC260_WILL,
81 ALC260_REPLACER_672V,
82 ALC260_FAVORIT100,
83 #ifdef CONFIG_SND_DEBUG
84 ALC260_TEST,
85 #endif
86 ALC260_AUTO,
87 ALC260_MODEL_LAST /* last tag */
90 /* ALC262 models */
91 enum {
92 ALC262_BASIC,
93 ALC262_HIPPO,
94 ALC262_HIPPO_1,
95 ALC262_FUJITSU,
96 ALC262_HP_BPC,
97 ALC262_HP_BPC_D7000_WL,
98 ALC262_HP_BPC_D7000_WF,
99 ALC262_HP_TC_T5735,
100 ALC262_HP_RP5700,
101 ALC262_BENQ_ED8,
102 ALC262_SONY_ASSAMD,
103 ALC262_BENQ_T31,
104 ALC262_ULTRA,
105 ALC262_LENOVO_3000,
106 ALC262_NEC,
107 ALC262_TOSHIBA_S06,
108 ALC262_TOSHIBA_RX1,
109 ALC262_TYAN,
110 ALC262_AUTO,
111 ALC262_MODEL_LAST /* last tag */
114 /* ALC268 models */
115 enum {
116 ALC267_QUANTA_IL1,
117 ALC268_3ST,
118 ALC268_TOSHIBA,
119 ALC268_ACER,
120 ALC268_ACER_DMIC,
121 ALC268_ACER_ASPIRE_ONE,
122 ALC268_DELL,
123 ALC268_ZEPTO,
124 #ifdef CONFIG_SND_DEBUG
125 ALC268_TEST,
126 #endif
127 ALC268_AUTO,
128 ALC268_MODEL_LAST /* last tag */
131 /* ALC269 models */
132 enum {
133 ALC269_BASIC,
134 ALC269_QUANTA_FL1,
135 ALC269_AMIC,
136 ALC269_DMIC,
137 ALC269VB_AMIC,
138 ALC269VB_DMIC,
139 ALC269_FUJITSU,
140 ALC269_LIFEBOOK,
141 ALC271_ACER,
142 ALC269_AUTO,
143 ALC269_MODEL_LAST /* last tag */
146 /* ALC861 models */
147 enum {
148 ALC861_3ST,
149 ALC660_3ST,
150 ALC861_3ST_DIG,
151 ALC861_6ST_DIG,
152 ALC861_UNIWILL_M31,
153 ALC861_TOSHIBA,
154 ALC861_ASUS,
155 ALC861_ASUS_LAPTOP,
156 ALC861_AUTO,
157 ALC861_MODEL_LAST,
160 /* ALC861-VD models */
161 enum {
162 ALC660VD_3ST,
163 ALC660VD_3ST_DIG,
164 ALC660VD_ASUS_V1S,
165 ALC861VD_3ST,
166 ALC861VD_3ST_DIG,
167 ALC861VD_6ST_DIG,
168 ALC861VD_LENOVO,
169 ALC861VD_DALLAS,
170 ALC861VD_HP,
171 ALC861VD_AUTO,
172 ALC861VD_MODEL_LAST,
175 /* ALC662 models */
176 enum {
177 ALC662_3ST_2ch_DIG,
178 ALC662_3ST_6ch_DIG,
179 ALC662_3ST_6ch,
180 ALC662_5ST_DIG,
181 ALC662_LENOVO_101E,
182 ALC662_ASUS_EEEPC_P701,
183 ALC662_ASUS_EEEPC_EP20,
184 ALC663_ASUS_M51VA,
185 ALC663_ASUS_G71V,
186 ALC663_ASUS_H13,
187 ALC663_ASUS_G50V,
188 ALC662_ECS,
189 ALC663_ASUS_MODE1,
190 ALC662_ASUS_MODE2,
191 ALC663_ASUS_MODE3,
192 ALC663_ASUS_MODE4,
193 ALC663_ASUS_MODE5,
194 ALC663_ASUS_MODE6,
195 ALC663_ASUS_MODE7,
196 ALC663_ASUS_MODE8,
197 ALC272_DELL,
198 ALC272_DELL_ZM1,
199 ALC272_SAMSUNG_NC10,
200 ALC662_AUTO,
201 ALC662_MODEL_LAST,
204 /* ALC882 models */
205 enum {
206 ALC882_3ST_DIG,
207 ALC882_6ST_DIG,
208 ALC882_ARIMA,
209 ALC882_W2JC,
210 ALC882_TARGA,
211 ALC882_ASUS_A7J,
212 ALC882_ASUS_A7M,
213 ALC885_MACPRO,
214 ALC885_MBA21,
215 ALC885_MBP3,
216 ALC885_MB5,
217 ALC885_MACMINI3,
218 ALC885_IMAC24,
219 ALC885_IMAC91,
220 ALC883_3ST_2ch_DIG,
221 ALC883_3ST_6ch_DIG,
222 ALC883_3ST_6ch,
223 ALC883_6ST_DIG,
224 ALC883_TARGA_DIG,
225 ALC883_TARGA_2ch_DIG,
226 ALC883_TARGA_8ch_DIG,
227 ALC883_ACER,
228 ALC883_ACER_ASPIRE,
229 ALC888_ACER_ASPIRE_4930G,
230 ALC888_ACER_ASPIRE_6530G,
231 ALC888_ACER_ASPIRE_8930G,
232 ALC888_ACER_ASPIRE_7730G,
233 ALC883_MEDION,
234 ALC883_MEDION_WIM2160,
235 ALC883_LAPTOP_EAPD,
236 ALC883_LENOVO_101E_2ch,
237 ALC883_LENOVO_NB0763,
238 ALC888_LENOVO_MS7195_DIG,
239 ALC888_LENOVO_SKY,
240 ALC883_HAIER_W66,
241 ALC888_3ST_HP,
242 ALC888_6ST_DELL,
243 ALC883_MITAC,
244 ALC883_CLEVO_M540R,
245 ALC883_CLEVO_M720,
246 ALC883_FUJITSU_PI2515,
247 ALC888_FUJITSU_XA3530,
248 ALC883_3ST_6ch_INTEL,
249 ALC889A_INTEL,
250 ALC889_INTEL,
251 ALC888_ASUS_M90V,
252 ALC888_ASUS_EEE1601,
253 ALC889A_MB31,
254 ALC1200_ASUS_P5Q,
255 ALC883_SONY_VAIO_TT,
256 ALC882_AUTO,
257 ALC882_MODEL_LAST,
260 /* ALC680 models */
261 enum {
262 ALC680_BASE,
263 ALC680_AUTO,
264 ALC680_MODEL_LAST,
267 /* for GPIO Poll */
268 #define GPIO_MASK 0x03
270 /* extra amp-initialization sequence types */
271 enum {
272 ALC_INIT_NONE,
273 ALC_INIT_DEFAULT,
274 ALC_INIT_GPIO1,
275 ALC_INIT_GPIO2,
276 ALC_INIT_GPIO3,
279 struct alc_mic_route {
280 hda_nid_t pin;
281 unsigned char mux_idx;
282 unsigned char amix_idx;
285 #define MUX_IDX_UNDEF ((unsigned char)-1)
287 struct alc_customize_define {
288 unsigned int sku_cfg;
289 unsigned char port_connectivity;
290 unsigned char check_sum;
291 unsigned char customization;
292 unsigned char external_amp;
293 unsigned int enable_pcbeep:1;
294 unsigned int platform_type:1;
295 unsigned int swap:1;
296 unsigned int override:1;
297 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
300 struct alc_fixup;
302 struct alc_multi_io {
303 hda_nid_t pin; /* multi-io widget pin NID */
304 hda_nid_t dac; /* DAC to be connected */
305 unsigned int ctl_in; /* cached input-pin control value */
308 enum {
309 ALC_AUTOMUTE_PIN, /* change the pin control */
310 ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */
311 ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
314 struct alc_spec {
315 /* codec parameterization */
316 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
317 unsigned int num_mixers;
318 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
319 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
321 const struct hda_verb *init_verbs[10]; /* initialization verbs
322 * don't forget NULL
323 * termination!
325 unsigned int num_init_verbs;
327 char stream_name_analog[32]; /* analog PCM stream */
328 const struct hda_pcm_stream *stream_analog_playback;
329 const struct hda_pcm_stream *stream_analog_capture;
330 const struct hda_pcm_stream *stream_analog_alt_playback;
331 const struct hda_pcm_stream *stream_analog_alt_capture;
333 char stream_name_digital[32]; /* digital PCM stream */
334 const struct hda_pcm_stream *stream_digital_playback;
335 const struct hda_pcm_stream *stream_digital_capture;
337 /* playback */
338 struct hda_multi_out multiout; /* playback set-up
339 * max_channels, dacs must be set
340 * dig_out_nid and hp_nid are optional
342 hda_nid_t alt_dac_nid;
343 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
344 int dig_out_type;
346 /* capture */
347 unsigned int num_adc_nids;
348 const hda_nid_t *adc_nids;
349 const hda_nid_t *capsrc_nids;
350 hda_nid_t dig_in_nid; /* digital-in NID; optional */
352 /* capture setup for dynamic dual-adc switch */
353 unsigned int cur_adc_idx;
354 hda_nid_t cur_adc;
355 unsigned int cur_adc_stream_tag;
356 unsigned int cur_adc_format;
358 /* capture source */
359 unsigned int num_mux_defs;
360 const struct hda_input_mux *input_mux;
361 unsigned int cur_mux[3];
362 struct alc_mic_route ext_mic;
363 struct alc_mic_route dock_mic;
364 struct alc_mic_route int_mic;
366 /* channel model */
367 const struct hda_channel_mode *channel_mode;
368 int num_channel_mode;
369 int need_dac_fix;
370 int const_channel_count;
371 int ext_channel_count;
373 /* PCM information */
374 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
376 /* dynamic controls, init_verbs and input_mux */
377 struct auto_pin_cfg autocfg;
378 struct alc_customize_define cdefine;
379 struct snd_array kctls;
380 struct hda_input_mux private_imux[3];
381 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
382 hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
383 hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
385 /* hooks */
386 void (*init_hook)(struct hda_codec *codec);
387 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
388 #ifdef CONFIG_SND_HDA_POWER_SAVE
389 void (*power_hook)(struct hda_codec *codec);
390 #endif
391 void (*shutup)(struct hda_codec *codec);
393 /* for pin sensing */
394 unsigned int jack_present: 1;
395 unsigned int line_jack_present:1;
396 unsigned int master_mute:1;
397 unsigned int auto_mic:1;
398 unsigned int automute:1; /* HP automute enabled */
399 unsigned int detect_line:1; /* Line-out detection enabled */
400 unsigned int automute_lines:1; /* automute line-out as well; NOP when automute_hp_lo isn't set */
401 unsigned int automute_hp_lo:1; /* both HP and LO available */
403 /* other flags */
404 unsigned int no_analog :1; /* digital I/O only */
405 unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
406 unsigned int single_input_src:1;
408 /* auto-mute control */
409 int automute_mode;
410 hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
412 int init_amp;
413 int codec_variant; /* flag for other variants */
415 /* for virtual master */
416 hda_nid_t vmaster_nid;
417 #ifdef CONFIG_SND_HDA_POWER_SAVE
418 struct hda_loopback_check loopback;
419 #endif
421 /* for PLL fix */
422 hda_nid_t pll_nid;
423 unsigned int pll_coef_idx, pll_coef_bit;
425 /* fix-up list */
426 int fixup_id;
427 const struct alc_fixup *fixup_list;
428 const char *fixup_name;
430 /* multi-io */
431 int multi_ios;
432 struct alc_multi_io multi_io[4];
436 * configuration template - to be copied to the spec instance
438 struct alc_config_preset {
439 const struct snd_kcontrol_new *mixers[5]; /* should be identical size
440 * with spec
442 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
443 const struct hda_verb *init_verbs[5];
444 unsigned int num_dacs;
445 const hda_nid_t *dac_nids;
446 hda_nid_t dig_out_nid; /* optional */
447 hda_nid_t hp_nid; /* optional */
448 const hda_nid_t *slave_dig_outs;
449 unsigned int num_adc_nids;
450 const hda_nid_t *adc_nids;
451 const hda_nid_t *capsrc_nids;
452 hda_nid_t dig_in_nid;
453 unsigned int num_channel_mode;
454 const struct hda_channel_mode *channel_mode;
455 int need_dac_fix;
456 int const_channel_count;
457 unsigned int num_mux_defs;
458 const struct hda_input_mux *input_mux;
459 void (*unsol_event)(struct hda_codec *, unsigned int);
460 void (*setup)(struct hda_codec *);
461 void (*init_hook)(struct hda_codec *);
462 #ifdef CONFIG_SND_HDA_POWER_SAVE
463 const struct hda_amp_list *loopbacks;
464 void (*power_hook)(struct hda_codec *codec);
465 #endif
470 * input MUX handling
472 static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
473 struct snd_ctl_elem_info *uinfo)
475 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
476 struct alc_spec *spec = codec->spec;
477 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
478 if (mux_idx >= spec->num_mux_defs)
479 mux_idx = 0;
480 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
481 mux_idx = 0;
482 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
485 static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
486 struct snd_ctl_elem_value *ucontrol)
488 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
489 struct alc_spec *spec = codec->spec;
490 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
492 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
493 return 0;
496 static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
497 struct snd_ctl_elem_value *ucontrol)
499 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
500 struct alc_spec *spec = codec->spec;
501 const struct hda_input_mux *imux;
502 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
503 unsigned int mux_idx;
504 hda_nid_t nid = spec->capsrc_nids ?
505 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
506 unsigned int type;
508 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
509 imux = &spec->input_mux[mux_idx];
510 if (!imux->num_items && mux_idx > 0)
511 imux = &spec->input_mux[0];
513 type = get_wcaps_type(get_wcaps(codec, nid));
514 if (type == AC_WID_AUD_MIX) {
515 /* Matrix-mixer style (e.g. ALC882) */
516 unsigned int *cur_val = &spec->cur_mux[adc_idx];
517 unsigned int i, idx;
519 idx = ucontrol->value.enumerated.item[0];
520 if (idx >= imux->num_items)
521 idx = imux->num_items - 1;
522 if (*cur_val == idx)
523 return 0;
524 for (i = 0; i < imux->num_items; i++) {
525 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
526 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
527 imux->items[i].index,
528 HDA_AMP_MUTE, v);
530 *cur_val = idx;
531 return 1;
532 } else {
533 /* MUX style (e.g. ALC880) */
534 return snd_hda_input_mux_put(codec, imux, ucontrol, nid,
535 &spec->cur_mux[adc_idx]);
540 * channel mode setting
542 static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
543 struct snd_ctl_elem_info *uinfo)
545 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
546 struct alc_spec *spec = codec->spec;
547 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
548 spec->num_channel_mode);
551 static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
552 struct snd_ctl_elem_value *ucontrol)
554 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
555 struct alc_spec *spec = codec->spec;
556 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
557 spec->num_channel_mode,
558 spec->ext_channel_count);
561 static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
562 struct snd_ctl_elem_value *ucontrol)
564 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
565 struct alc_spec *spec = codec->spec;
566 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
567 spec->num_channel_mode,
568 &spec->ext_channel_count);
569 if (err >= 0 && !spec->const_channel_count) {
570 spec->multiout.max_channels = spec->ext_channel_count;
571 if (spec->need_dac_fix)
572 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
574 return err;
578 * Control the mode of pin widget settings via the mixer. "pc" is used
579 * instead of "%" to avoid consequences of accidentally treating the % as
580 * being part of a format specifier. Maximum allowed length of a value is
581 * 63 characters plus NULL terminator.
583 * Note: some retasking pin complexes seem to ignore requests for input
584 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
585 * are requested. Therefore order this list so that this behaviour will not
586 * cause problems when mixer clients move through the enum sequentially.
587 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
588 * March 2006.
590 static const char * const alc_pin_mode_names[] = {
591 "Mic 50pc bias", "Mic 80pc bias",
592 "Line in", "Line out", "Headphone out",
594 static const unsigned char alc_pin_mode_values[] = {
595 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
597 /* The control can present all 5 options, or it can limit the options based
598 * in the pin being assumed to be exclusively an input or an output pin. In
599 * addition, "input" pins may or may not process the mic bias option
600 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
601 * accept requests for bias as of chip versions up to March 2006) and/or
602 * wiring in the computer.
604 #define ALC_PIN_DIR_IN 0x00
605 #define ALC_PIN_DIR_OUT 0x01
606 #define ALC_PIN_DIR_INOUT 0x02
607 #define ALC_PIN_DIR_IN_NOMICBIAS 0x03
608 #define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
610 /* Info about the pin modes supported by the different pin direction modes.
611 * For each direction the minimum and maximum values are given.
613 static const signed char alc_pin_mode_dir_info[5][2] = {
614 { 0, 2 }, /* ALC_PIN_DIR_IN */
615 { 3, 4 }, /* ALC_PIN_DIR_OUT */
616 { 0, 4 }, /* ALC_PIN_DIR_INOUT */
617 { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */
618 { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */
620 #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
621 #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
622 #define alc_pin_mode_n_items(_dir) \
623 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
625 static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
626 struct snd_ctl_elem_info *uinfo)
628 unsigned int item_num = uinfo->value.enumerated.item;
629 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
631 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
632 uinfo->count = 1;
633 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
635 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
636 item_num = alc_pin_mode_min(dir);
637 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
638 return 0;
641 static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
642 struct snd_ctl_elem_value *ucontrol)
644 unsigned int i;
645 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
646 hda_nid_t nid = kcontrol->private_value & 0xffff;
647 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
648 long *valp = ucontrol->value.integer.value;
649 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
650 AC_VERB_GET_PIN_WIDGET_CONTROL,
651 0x00);
653 /* Find enumerated value for current pinctl setting */
654 i = alc_pin_mode_min(dir);
655 while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
656 i++;
657 *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
658 return 0;
661 static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
662 struct snd_ctl_elem_value *ucontrol)
664 signed int change;
665 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
666 hda_nid_t nid = kcontrol->private_value & 0xffff;
667 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
668 long val = *ucontrol->value.integer.value;
669 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
670 AC_VERB_GET_PIN_WIDGET_CONTROL,
671 0x00);
673 if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
674 val = alc_pin_mode_min(dir);
676 change = pinctl != alc_pin_mode_values[val];
677 if (change) {
678 /* Set pin mode to that requested */
679 snd_hda_codec_write_cache(codec, nid, 0,
680 AC_VERB_SET_PIN_WIDGET_CONTROL,
681 alc_pin_mode_values[val]);
683 /* Also enable the retasking pin's input/output as required
684 * for the requested pin mode. Enum values of 2 or less are
685 * input modes.
687 * Dynamically switching the input/output buffers probably
688 * reduces noise slightly (particularly on input) so we'll
689 * do it. However, having both input and output buffers
690 * enabled simultaneously doesn't seem to be problematic if
691 * this turns out to be necessary in the future.
693 if (val <= 2) {
694 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
695 HDA_AMP_MUTE, HDA_AMP_MUTE);
696 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
697 HDA_AMP_MUTE, 0);
698 } else {
699 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
700 HDA_AMP_MUTE, HDA_AMP_MUTE);
701 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
702 HDA_AMP_MUTE, 0);
705 return change;
708 #define ALC_PIN_MODE(xname, nid, dir) \
709 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
710 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
711 .info = alc_pin_mode_info, \
712 .get = alc_pin_mode_get, \
713 .put = alc_pin_mode_put, \
714 .private_value = nid | (dir<<16) }
716 /* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged
717 * together using a mask with more than one bit set. This control is
718 * currently used only by the ALC260 test model. At this stage they are not
719 * needed for any "production" models.
721 #ifdef CONFIG_SND_DEBUG
722 #define alc_gpio_data_info snd_ctl_boolean_mono_info
724 static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
725 struct snd_ctl_elem_value *ucontrol)
727 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
728 hda_nid_t nid = kcontrol->private_value & 0xffff;
729 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
730 long *valp = ucontrol->value.integer.value;
731 unsigned int val = snd_hda_codec_read(codec, nid, 0,
732 AC_VERB_GET_GPIO_DATA, 0x00);
734 *valp = (val & mask) != 0;
735 return 0;
737 static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
738 struct snd_ctl_elem_value *ucontrol)
740 signed int change;
741 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
742 hda_nid_t nid = kcontrol->private_value & 0xffff;
743 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
744 long val = *ucontrol->value.integer.value;
745 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
746 AC_VERB_GET_GPIO_DATA,
747 0x00);
749 /* Set/unset the masked GPIO bit(s) as needed */
750 change = (val == 0 ? 0 : mask) != (gpio_data & mask);
751 if (val == 0)
752 gpio_data &= ~mask;
753 else
754 gpio_data |= mask;
755 snd_hda_codec_write_cache(codec, nid, 0,
756 AC_VERB_SET_GPIO_DATA, gpio_data);
758 return change;
760 #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
761 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
762 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
763 .info = alc_gpio_data_info, \
764 .get = alc_gpio_data_get, \
765 .put = alc_gpio_data_put, \
766 .private_value = nid | (mask<<16) }
767 #endif /* CONFIG_SND_DEBUG */
769 /* A switch control to allow the enabling of the digital IO pins on the
770 * ALC260. This is incredibly simplistic; the intention of this control is
771 * to provide something in the test model allowing digital outputs to be
772 * identified if present. If models are found which can utilise these
773 * outputs a more complete mixer control can be devised for those models if
774 * necessary.
776 #ifdef CONFIG_SND_DEBUG
777 #define alc_spdif_ctrl_info snd_ctl_boolean_mono_info
779 static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
780 struct snd_ctl_elem_value *ucontrol)
782 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
783 hda_nid_t nid = kcontrol->private_value & 0xffff;
784 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
785 long *valp = ucontrol->value.integer.value;
786 unsigned int val = snd_hda_codec_read(codec, nid, 0,
787 AC_VERB_GET_DIGI_CONVERT_1, 0x00);
789 *valp = (val & mask) != 0;
790 return 0;
792 static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
793 struct snd_ctl_elem_value *ucontrol)
795 signed int change;
796 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
797 hda_nid_t nid = kcontrol->private_value & 0xffff;
798 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
799 long val = *ucontrol->value.integer.value;
800 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
801 AC_VERB_GET_DIGI_CONVERT_1,
802 0x00);
804 /* Set/unset the masked control bit(s) as needed */
805 change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
806 if (val==0)
807 ctrl_data &= ~mask;
808 else
809 ctrl_data |= mask;
810 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
811 ctrl_data);
813 return change;
815 #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
816 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
817 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
818 .info = alc_spdif_ctrl_info, \
819 .get = alc_spdif_ctrl_get, \
820 .put = alc_spdif_ctrl_put, \
821 .private_value = nid | (mask<<16) }
822 #endif /* CONFIG_SND_DEBUG */
824 /* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
825 * Again, this is only used in the ALC26x test models to help identify when
826 * the EAPD line must be asserted for features to work.
828 #ifdef CONFIG_SND_DEBUG
829 #define alc_eapd_ctrl_info snd_ctl_boolean_mono_info
831 static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
832 struct snd_ctl_elem_value *ucontrol)
834 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
835 hda_nid_t nid = kcontrol->private_value & 0xffff;
836 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
837 long *valp = ucontrol->value.integer.value;
838 unsigned int val = snd_hda_codec_read(codec, nid, 0,
839 AC_VERB_GET_EAPD_BTLENABLE, 0x00);
841 *valp = (val & mask) != 0;
842 return 0;
845 static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
846 struct snd_ctl_elem_value *ucontrol)
848 int change;
849 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
850 hda_nid_t nid = kcontrol->private_value & 0xffff;
851 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
852 long val = *ucontrol->value.integer.value;
853 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
854 AC_VERB_GET_EAPD_BTLENABLE,
855 0x00);
857 /* Set/unset the masked control bit(s) as needed */
858 change = (!val ? 0 : mask) != (ctrl_data & mask);
859 if (!val)
860 ctrl_data &= ~mask;
861 else
862 ctrl_data |= mask;
863 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
864 ctrl_data);
866 return change;
869 #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
870 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
871 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
872 .info = alc_eapd_ctrl_info, \
873 .get = alc_eapd_ctrl_get, \
874 .put = alc_eapd_ctrl_put, \
875 .private_value = nid | (mask<<16) }
876 #endif /* CONFIG_SND_DEBUG */
879 * set up the input pin config (depending on the given auto-pin type)
881 static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
882 int auto_pin_type)
884 unsigned int val = PIN_IN;
886 if (auto_pin_type == AUTO_PIN_MIC) {
887 unsigned int pincap;
888 unsigned int oldval;
889 oldval = snd_hda_codec_read(codec, nid, 0,
890 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
891 pincap = snd_hda_query_pin_caps(codec, nid);
892 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
893 /* if the default pin setup is vref50, we give it priority */
894 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
895 val = PIN_VREF80;
896 else if (pincap & AC_PINCAP_VREF_50)
897 val = PIN_VREF50;
898 else if (pincap & AC_PINCAP_VREF_100)
899 val = PIN_VREF100;
900 else if (pincap & AC_PINCAP_VREF_GRD)
901 val = PIN_VREFGRD;
903 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
906 static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec)
908 struct alc_spec *spec = codec->spec;
909 struct auto_pin_cfg *cfg = &spec->autocfg;
911 if (!cfg->line_outs) {
912 while (cfg->line_outs < AUTO_CFG_MAX_OUTS &&
913 cfg->line_out_pins[cfg->line_outs])
914 cfg->line_outs++;
916 if (!cfg->speaker_outs) {
917 while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS &&
918 cfg->speaker_pins[cfg->speaker_outs])
919 cfg->speaker_outs++;
921 if (!cfg->hp_outs) {
922 while (cfg->hp_outs < AUTO_CFG_MAX_OUTS &&
923 cfg->hp_pins[cfg->hp_outs])
924 cfg->hp_outs++;
930 static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
932 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
933 return;
934 spec->mixers[spec->num_mixers++] = mix;
937 static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
939 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
940 return;
941 spec->init_verbs[spec->num_init_verbs++] = verb;
945 * set up from the preset table
947 static void setup_preset(struct hda_codec *codec,
948 const struct alc_config_preset *preset)
950 struct alc_spec *spec = codec->spec;
951 int i;
953 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
954 add_mixer(spec, preset->mixers[i]);
955 spec->cap_mixer = preset->cap_mixer;
956 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
957 i++)
958 add_verb(spec, preset->init_verbs[i]);
960 spec->channel_mode = preset->channel_mode;
961 spec->num_channel_mode = preset->num_channel_mode;
962 spec->need_dac_fix = preset->need_dac_fix;
963 spec->const_channel_count = preset->const_channel_count;
965 if (preset->const_channel_count)
966 spec->multiout.max_channels = preset->const_channel_count;
967 else
968 spec->multiout.max_channels = spec->channel_mode[0].channels;
969 spec->ext_channel_count = spec->channel_mode[0].channels;
971 spec->multiout.num_dacs = preset->num_dacs;
972 spec->multiout.dac_nids = preset->dac_nids;
973 spec->multiout.dig_out_nid = preset->dig_out_nid;
974 spec->multiout.slave_dig_outs = preset->slave_dig_outs;
975 spec->multiout.hp_nid = preset->hp_nid;
977 spec->num_mux_defs = preset->num_mux_defs;
978 if (!spec->num_mux_defs)
979 spec->num_mux_defs = 1;
980 spec->input_mux = preset->input_mux;
982 spec->num_adc_nids = preset->num_adc_nids;
983 spec->adc_nids = preset->adc_nids;
984 spec->capsrc_nids = preset->capsrc_nids;
985 spec->dig_in_nid = preset->dig_in_nid;
987 spec->unsol_event = preset->unsol_event;
988 spec->init_hook = preset->init_hook;
989 #ifdef CONFIG_SND_HDA_POWER_SAVE
990 spec->power_hook = preset->power_hook;
991 spec->loopback.amplist = preset->loopbacks;
992 #endif
994 if (preset->setup)
995 preset->setup(codec);
997 alc_fixup_autocfg_pin_nums(codec);
1000 /* Enable GPIO mask and set output */
1001 static const struct hda_verb alc_gpio1_init_verbs[] = {
1002 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
1003 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
1004 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
1008 static const struct hda_verb alc_gpio2_init_verbs[] = {
1009 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
1010 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
1011 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
1015 static const struct hda_verb alc_gpio3_init_verbs[] = {
1016 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
1017 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
1018 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
1023 * Fix hardware PLL issue
1024 * On some codecs, the analog PLL gating control must be off while
1025 * the default value is 1.
1027 static void alc_fix_pll(struct hda_codec *codec)
1029 struct alc_spec *spec = codec->spec;
1030 unsigned int val;
1032 if (!spec->pll_nid)
1033 return;
1034 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
1035 spec->pll_coef_idx);
1036 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
1037 AC_VERB_GET_PROC_COEF, 0);
1038 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
1039 spec->pll_coef_idx);
1040 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
1041 val & ~(1 << spec->pll_coef_bit));
1044 static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
1045 unsigned int coef_idx, unsigned int coef_bit)
1047 struct alc_spec *spec = codec->spec;
1048 spec->pll_nid = nid;
1049 spec->pll_coef_idx = coef_idx;
1050 spec->pll_coef_bit = coef_bit;
1051 alc_fix_pll(codec);
1054 static int alc_init_jacks(struct hda_codec *codec)
1056 #ifdef CONFIG_SND_HDA_INPUT_JACK
1057 struct alc_spec *spec = codec->spec;
1058 int err;
1059 unsigned int hp_nid = spec->autocfg.hp_pins[0];
1060 unsigned int mic_nid = spec->ext_mic.pin;
1061 unsigned int dock_nid = spec->dock_mic.pin;
1063 if (hp_nid) {
1064 err = snd_hda_input_jack_add(codec, hp_nid,
1065 SND_JACK_HEADPHONE, NULL);
1066 if (err < 0)
1067 return err;
1068 snd_hda_input_jack_report(codec, hp_nid);
1071 if (mic_nid) {
1072 err = snd_hda_input_jack_add(codec, mic_nid,
1073 SND_JACK_MICROPHONE, NULL);
1074 if (err < 0)
1075 return err;
1076 snd_hda_input_jack_report(codec, mic_nid);
1078 if (dock_nid) {
1079 err = snd_hda_input_jack_add(codec, dock_nid,
1080 SND_JACK_MICROPHONE, NULL);
1081 if (err < 0)
1082 return err;
1083 snd_hda_input_jack_report(codec, dock_nid);
1085 #endif /* CONFIG_SND_HDA_INPUT_JACK */
1086 return 0;
1089 static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
1091 int i, present = 0;
1093 for (i = 0; i < num_pins; i++) {
1094 hda_nid_t nid = pins[i];
1095 if (!nid)
1096 break;
1097 snd_hda_input_jack_report(codec, nid);
1098 present |= snd_hda_jack_detect(codec, nid);
1100 return present;
1103 static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
1104 bool mute, bool hp_out)
1106 struct alc_spec *spec = codec->spec;
1107 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
1108 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
1109 int i;
1111 for (i = 0; i < num_pins; i++) {
1112 hda_nid_t nid = pins[i];
1113 if (!nid)
1114 break;
1115 switch (spec->automute_mode) {
1116 case ALC_AUTOMUTE_PIN:
1117 snd_hda_codec_write(codec, nid, 0,
1118 AC_VERB_SET_PIN_WIDGET_CONTROL,
1119 pin_bits);
1120 break;
1121 case ALC_AUTOMUTE_AMP:
1122 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1123 HDA_AMP_MUTE, mute_bits);
1124 break;
1125 case ALC_AUTOMUTE_MIXER:
1126 nid = spec->automute_mixer_nid[i];
1127 if (!nid)
1128 break;
1129 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
1130 HDA_AMP_MUTE, mute_bits);
1131 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
1132 HDA_AMP_MUTE, mute_bits);
1133 break;
1138 /* Toggle internal speakers muting */
1139 static void update_speakers(struct hda_codec *codec)
1141 struct alc_spec *spec = codec->spec;
1142 int on;
1144 /* Control HP pins/amps depending on master_mute state;
1145 * in general, HP pins/amps control should be enabled in all cases,
1146 * but currently set only for master_mute, just to be safe
1148 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
1149 spec->autocfg.hp_pins, spec->master_mute, true);
1151 if (!spec->automute)
1152 on = 0;
1153 else
1154 on = spec->jack_present | spec->line_jack_present;
1155 on |= spec->master_mute;
1156 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
1157 spec->autocfg.speaker_pins, on, false);
1159 /* toggle line-out mutes if needed, too */
1160 /* if LO is a copy of either HP or Speaker, don't need to handle it */
1161 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
1162 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
1163 return;
1164 if (!spec->automute || (spec->automute_hp_lo && !spec->automute_lines))
1165 on = 0;
1166 else
1167 on = spec->jack_present;
1168 on |= spec->master_mute;
1169 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
1170 spec->autocfg.line_out_pins, on, false);
1173 static void alc_hp_automute(struct hda_codec *codec)
1175 struct alc_spec *spec = codec->spec;
1177 if (!spec->automute)
1178 return;
1179 spec->jack_present =
1180 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
1181 spec->autocfg.hp_pins);
1182 update_speakers(codec);
1185 static void alc_line_automute(struct hda_codec *codec)
1187 struct alc_spec *spec = codec->spec;
1189 if (!spec->automute || !spec->detect_line)
1190 return;
1191 spec->line_jack_present =
1192 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
1193 spec->autocfg.line_out_pins);
1194 update_speakers(codec);
1197 static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
1198 hda_nid_t nid)
1200 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
1201 int i, nums;
1203 nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
1204 for (i = 0; i < nums; i++)
1205 if (conn[i] == nid)
1206 return i;
1207 return -1;
1210 /* switch the current ADC according to the jack state */
1211 static void alc_dual_mic_adc_auto_switch(struct hda_codec *codec)
1213 struct alc_spec *spec = codec->spec;
1214 unsigned int present;
1215 hda_nid_t new_adc;
1217 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
1218 if (present)
1219 spec->cur_adc_idx = 1;
1220 else
1221 spec->cur_adc_idx = 0;
1222 new_adc = spec->adc_nids[spec->cur_adc_idx];
1223 if (spec->cur_adc && spec->cur_adc != new_adc) {
1224 /* stream is running, let's swap the current ADC */
1225 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
1226 spec->cur_adc = new_adc;
1227 snd_hda_codec_setup_stream(codec, new_adc,
1228 spec->cur_adc_stream_tag, 0,
1229 spec->cur_adc_format);
1233 static void alc_mic_automute(struct hda_codec *codec)
1235 struct alc_spec *spec = codec->spec;
1236 struct alc_mic_route *dead1, *dead2, *alive;
1237 unsigned int present, type;
1238 hda_nid_t cap_nid;
1240 if (!spec->auto_mic)
1241 return;
1242 if (!spec->int_mic.pin || !spec->ext_mic.pin)
1243 return;
1244 if (snd_BUG_ON(!spec->adc_nids))
1245 return;
1247 if (spec->dual_adc_switch) {
1248 alc_dual_mic_adc_auto_switch(codec);
1249 return;
1252 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
1254 alive = &spec->int_mic;
1255 dead1 = &spec->ext_mic;
1256 dead2 = &spec->dock_mic;
1258 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
1259 if (present) {
1260 alive = &spec->ext_mic;
1261 dead1 = &spec->int_mic;
1262 dead2 = &spec->dock_mic;
1264 if (!present && spec->dock_mic.pin > 0) {
1265 present = snd_hda_jack_detect(codec, spec->dock_mic.pin);
1266 if (present) {
1267 alive = &spec->dock_mic;
1268 dead1 = &spec->int_mic;
1269 dead2 = &spec->ext_mic;
1271 snd_hda_input_jack_report(codec, spec->dock_mic.pin);
1274 type = get_wcaps_type(get_wcaps(codec, cap_nid));
1275 if (type == AC_WID_AUD_MIX) {
1276 /* Matrix-mixer style (e.g. ALC882) */
1277 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1278 alive->mux_idx,
1279 HDA_AMP_MUTE, 0);
1280 if (dead1->pin > 0)
1281 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1282 dead1->mux_idx,
1283 HDA_AMP_MUTE, HDA_AMP_MUTE);
1284 if (dead2->pin > 0)
1285 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1286 dead2->mux_idx,
1287 HDA_AMP_MUTE, HDA_AMP_MUTE);
1288 } else {
1289 /* MUX style (e.g. ALC880) */
1290 snd_hda_codec_write_cache(codec, cap_nid, 0,
1291 AC_VERB_SET_CONNECT_SEL,
1292 alive->mux_idx);
1294 snd_hda_input_jack_report(codec, spec->ext_mic.pin);
1296 /* FIXME: analog mixer */
1299 /* unsolicited event for HP jack sensing */
1300 static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
1302 if (codec->vendor_id == 0x10ec0880)
1303 res >>= 28;
1304 else
1305 res >>= 26;
1306 switch (res) {
1307 case ALC880_HP_EVENT:
1308 alc_hp_automute(codec);
1309 break;
1310 case ALC880_FRONT_EVENT:
1311 alc_line_automute(codec);
1312 break;
1313 case ALC880_MIC_EVENT:
1314 alc_mic_automute(codec);
1315 break;
1319 static void alc_inithook(struct hda_codec *codec)
1321 alc_hp_automute(codec);
1322 alc_line_automute(codec);
1323 alc_mic_automute(codec);
1326 /* additional initialization for ALC888 variants */
1327 static void alc888_coef_init(struct hda_codec *codec)
1329 unsigned int tmp;
1331 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
1332 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
1333 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1334 if ((tmp & 0xf0) == 0x20)
1335 /* alc888S-VC */
1336 snd_hda_codec_read(codec, 0x20, 0,
1337 AC_VERB_SET_PROC_COEF, 0x830);
1338 else
1339 /* alc888-VB */
1340 snd_hda_codec_read(codec, 0x20, 0,
1341 AC_VERB_SET_PROC_COEF, 0x3030);
1344 static void alc889_coef_init(struct hda_codec *codec)
1346 unsigned int tmp;
1348 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1349 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
1350 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1351 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
1354 /* turn on/off EAPD control (only if available) */
1355 static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
1357 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
1358 return;
1359 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
1360 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
1361 on ? 2 : 0);
1364 /* turn on/off EAPD controls of the codec */
1365 static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
1367 /* We currently only handle front, HP */
1368 switch (codec->vendor_id) {
1369 case 0x10ec0260:
1370 set_eapd(codec, 0x0f, on);
1371 set_eapd(codec, 0x10, on);
1372 break;
1373 case 0x10ec0262:
1374 case 0x10ec0267:
1375 case 0x10ec0268:
1376 case 0x10ec0269:
1377 case 0x10ec0270:
1378 case 0x10ec0272:
1379 case 0x10ec0660:
1380 case 0x10ec0662:
1381 case 0x10ec0663:
1382 case 0x10ec0665:
1383 case 0x10ec0862:
1384 case 0x10ec0889:
1385 case 0x10ec0892:
1386 set_eapd(codec, 0x14, on);
1387 set_eapd(codec, 0x15, on);
1388 break;
1392 /* generic shutup callback;
1393 * just turning off EPAD and a little pause for avoiding pop-noise
1395 static void alc_eapd_shutup(struct hda_codec *codec)
1397 alc_auto_setup_eapd(codec, false);
1398 msleep(200);
1401 static void alc_auto_init_amp(struct hda_codec *codec, int type)
1403 unsigned int tmp;
1405 switch (type) {
1406 case ALC_INIT_GPIO1:
1407 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
1408 break;
1409 case ALC_INIT_GPIO2:
1410 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
1411 break;
1412 case ALC_INIT_GPIO3:
1413 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
1414 break;
1415 case ALC_INIT_DEFAULT:
1416 alc_auto_setup_eapd(codec, true);
1417 switch (codec->vendor_id) {
1418 case 0x10ec0260:
1419 snd_hda_codec_write(codec, 0x1a, 0,
1420 AC_VERB_SET_COEF_INDEX, 7);
1421 tmp = snd_hda_codec_read(codec, 0x1a, 0,
1422 AC_VERB_GET_PROC_COEF, 0);
1423 snd_hda_codec_write(codec, 0x1a, 0,
1424 AC_VERB_SET_COEF_INDEX, 7);
1425 snd_hda_codec_write(codec, 0x1a, 0,
1426 AC_VERB_SET_PROC_COEF,
1427 tmp | 0x2010);
1428 break;
1429 case 0x10ec0262:
1430 case 0x10ec0880:
1431 case 0x10ec0882:
1432 case 0x10ec0883:
1433 case 0x10ec0885:
1434 case 0x10ec0887:
1435 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
1436 alc889_coef_init(codec);
1437 break;
1438 case 0x10ec0888:
1439 alc888_coef_init(codec);
1440 break;
1441 #if 0 /* XXX: This may cause the silent output on speaker on some machines */
1442 case 0x10ec0267:
1443 case 0x10ec0268:
1444 snd_hda_codec_write(codec, 0x20, 0,
1445 AC_VERB_SET_COEF_INDEX, 7);
1446 tmp = snd_hda_codec_read(codec, 0x20, 0,
1447 AC_VERB_GET_PROC_COEF, 0);
1448 snd_hda_codec_write(codec, 0x20, 0,
1449 AC_VERB_SET_COEF_INDEX, 7);
1450 snd_hda_codec_write(codec, 0x20, 0,
1451 AC_VERB_SET_PROC_COEF,
1452 tmp | 0x3000);
1453 break;
1454 #endif /* XXX */
1456 break;
1460 static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
1461 struct snd_ctl_elem_info *uinfo)
1463 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1464 struct alc_spec *spec = codec->spec;
1465 static const char * const texts2[] = {
1466 "Disabled", "Enabled"
1468 static const char * const texts3[] = {
1469 "Disabled", "Speaker Only", "Line-Out+Speaker"
1471 const char * const *texts;
1473 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1474 uinfo->count = 1;
1475 if (spec->automute_hp_lo) {
1476 uinfo->value.enumerated.items = 3;
1477 texts = texts3;
1478 } else {
1479 uinfo->value.enumerated.items = 2;
1480 texts = texts2;
1482 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1483 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1484 strcpy(uinfo->value.enumerated.name,
1485 texts[uinfo->value.enumerated.item]);
1486 return 0;
1489 static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
1490 struct snd_ctl_elem_value *ucontrol)
1492 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1493 struct alc_spec *spec = codec->spec;
1494 unsigned int val;
1495 if (!spec->automute)
1496 val = 0;
1497 else if (!spec->automute_hp_lo || !spec->automute_lines)
1498 val = 1;
1499 else
1500 val = 2;
1501 ucontrol->value.enumerated.item[0] = val;
1502 return 0;
1505 static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
1506 struct snd_ctl_elem_value *ucontrol)
1508 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1509 struct alc_spec *spec = codec->spec;
1511 switch (ucontrol->value.enumerated.item[0]) {
1512 case 0:
1513 if (!spec->automute)
1514 return 0;
1515 spec->automute = 0;
1516 break;
1517 case 1:
1518 if (spec->automute &&
1519 (!spec->automute_hp_lo || !spec->automute_lines))
1520 return 0;
1521 spec->automute = 1;
1522 spec->automute_lines = 0;
1523 break;
1524 case 2:
1525 if (!spec->automute_hp_lo)
1526 return -EINVAL;
1527 if (spec->automute && spec->automute_lines)
1528 return 0;
1529 spec->automute = 1;
1530 spec->automute_lines = 1;
1531 break;
1532 default:
1533 return -EINVAL;
1535 update_speakers(codec);
1536 return 1;
1539 static const struct snd_kcontrol_new alc_automute_mode_enum = {
1540 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1541 .name = "Auto-Mute Mode",
1542 .info = alc_automute_mode_info,
1543 .get = alc_automute_mode_get,
1544 .put = alc_automute_mode_put,
1547 static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec);
1549 static int alc_add_automute_mode_enum(struct hda_codec *codec)
1551 struct alc_spec *spec = codec->spec;
1552 struct snd_kcontrol_new *knew;
1554 knew = alc_kcontrol_new(spec);
1555 if (!knew)
1556 return -ENOMEM;
1557 *knew = alc_automute_mode_enum;
1558 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
1559 if (!knew->name)
1560 return -ENOMEM;
1561 return 0;
1564 static void alc_init_auto_hp(struct hda_codec *codec)
1566 struct alc_spec *spec = codec->spec;
1567 struct auto_pin_cfg *cfg = &spec->autocfg;
1568 int present = 0;
1569 int i;
1571 if (cfg->hp_pins[0])
1572 present++;
1573 if (cfg->line_out_pins[0])
1574 present++;
1575 if (cfg->speaker_pins[0])
1576 present++;
1577 if (present < 2) /* need two different output types */
1578 return;
1579 if (present == 3)
1580 spec->automute_hp_lo = 1; /* both HP and LO automute */
1582 if (!cfg->speaker_pins[0] &&
1583 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1584 memcpy(cfg->speaker_pins, cfg->line_out_pins,
1585 sizeof(cfg->speaker_pins));
1586 cfg->speaker_outs = cfg->line_outs;
1589 if (!cfg->hp_pins[0] &&
1590 cfg->line_out_type == AUTO_PIN_HP_OUT) {
1591 memcpy(cfg->hp_pins, cfg->line_out_pins,
1592 sizeof(cfg->hp_pins));
1593 cfg->hp_outs = cfg->line_outs;
1596 for (i = 0; i < cfg->hp_outs; i++) {
1597 hda_nid_t nid = cfg->hp_pins[i];
1598 if (!is_jack_detectable(codec, nid))
1599 continue;
1600 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
1601 nid);
1602 snd_hda_codec_write_cache(codec, nid, 0,
1603 AC_VERB_SET_UNSOLICITED_ENABLE,
1604 AC_USRSP_EN | ALC880_HP_EVENT);
1605 spec->automute = 1;
1606 spec->automute_mode = ALC_AUTOMUTE_PIN;
1608 if (spec->automute && cfg->line_out_pins[0] &&
1609 cfg->speaker_pins[0] &&
1610 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
1611 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
1612 for (i = 0; i < cfg->line_outs; i++) {
1613 hda_nid_t nid = cfg->line_out_pins[i];
1614 if (!is_jack_detectable(codec, nid))
1615 continue;
1616 snd_printdd("realtek: Enable Line-Out auto-muting "
1617 "on NID 0x%x\n", nid);
1618 snd_hda_codec_write_cache(codec, nid, 0,
1619 AC_VERB_SET_UNSOLICITED_ENABLE,
1620 AC_USRSP_EN | ALC880_FRONT_EVENT);
1621 spec->detect_line = 1;
1623 spec->automute_lines = spec->detect_line;
1626 if (spec->automute) {
1627 /* create a control for automute mode */
1628 alc_add_automute_mode_enum(codec);
1629 spec->unsol_event = alc_sku_unsol_event;
1633 static void alc_init_auto_mic(struct hda_codec *codec)
1635 struct alc_spec *spec = codec->spec;
1636 struct auto_pin_cfg *cfg = &spec->autocfg;
1637 hda_nid_t fixed, ext, dock;
1638 int i;
1640 fixed = ext = dock = 0;
1641 for (i = 0; i < cfg->num_inputs; i++) {
1642 hda_nid_t nid = cfg->inputs[i].pin;
1643 unsigned int defcfg;
1644 defcfg = snd_hda_codec_get_pincfg(codec, nid);
1645 switch (snd_hda_get_input_pin_attr(defcfg)) {
1646 case INPUT_PIN_ATTR_INT:
1647 if (fixed)
1648 return; /* already occupied */
1649 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1650 return; /* invalid type */
1651 fixed = nid;
1652 break;
1653 case INPUT_PIN_ATTR_UNUSED:
1654 return; /* invalid entry */
1655 case INPUT_PIN_ATTR_DOCK:
1656 if (dock)
1657 return; /* already occupied */
1658 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1659 return; /* invalid type */
1660 dock = nid;
1661 break;
1662 default:
1663 if (ext)
1664 return; /* already occupied */
1665 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1666 return; /* invalid type */
1667 ext = nid;
1668 break;
1671 if (!ext && dock) {
1672 ext = dock;
1673 dock = 0;
1675 if (!ext || !fixed)
1676 return;
1677 if (!is_jack_detectable(codec, ext))
1678 return; /* no unsol support */
1679 if (dock && !is_jack_detectable(codec, dock))
1680 return; /* no unsol support */
1681 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1682 ext, fixed, dock);
1683 spec->ext_mic.pin = ext;
1684 spec->dock_mic.pin = dock;
1685 spec->int_mic.pin = fixed;
1686 spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1687 spec->dock_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1688 spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1689 spec->auto_mic = 1;
1690 snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0,
1691 AC_VERB_SET_UNSOLICITED_ENABLE,
1692 AC_USRSP_EN | ALC880_MIC_EVENT);
1693 spec->unsol_event = alc_sku_unsol_event;
1696 /* Could be any non-zero and even value. When used as fixup, tells
1697 * the driver to ignore any present sku defines.
1699 #define ALC_FIXUP_SKU_IGNORE (2)
1701 static int alc_auto_parse_customize_define(struct hda_codec *codec)
1703 unsigned int ass, tmp, i;
1704 unsigned nid = 0;
1705 struct alc_spec *spec = codec->spec;
1707 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1709 if (spec->cdefine.fixup) {
1710 ass = spec->cdefine.sku_cfg;
1711 if (ass == ALC_FIXUP_SKU_IGNORE)
1712 return -1;
1713 goto do_sku;
1716 ass = codec->subsystem_id & 0xffff;
1717 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
1718 goto do_sku;
1720 nid = 0x1d;
1721 if (codec->vendor_id == 0x10ec0260)
1722 nid = 0x17;
1723 ass = snd_hda_codec_get_pincfg(codec, nid);
1725 if (!(ass & 1)) {
1726 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1727 codec->chip_name, ass);
1728 return -1;
1731 /* check sum */
1732 tmp = 0;
1733 for (i = 1; i < 16; i++) {
1734 if ((ass >> i) & 1)
1735 tmp++;
1737 if (((ass >> 16) & 0xf) != tmp)
1738 return -1;
1740 spec->cdefine.port_connectivity = ass >> 30;
1741 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1742 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1743 spec->cdefine.customization = ass >> 8;
1744 do_sku:
1745 spec->cdefine.sku_cfg = ass;
1746 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1747 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1748 spec->cdefine.swap = (ass & 0x2) >> 1;
1749 spec->cdefine.override = ass & 0x1;
1751 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1752 nid, spec->cdefine.sku_cfg);
1753 snd_printd("SKU: port_connectivity=0x%x\n",
1754 spec->cdefine.port_connectivity);
1755 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1756 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1757 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1758 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1759 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1760 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1761 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1763 return 0;
1766 /* check subsystem ID and set up device-specific initialization;
1767 * return 1 if initialized, 0 if invalid SSID
1769 /* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1770 * 31 ~ 16 : Manufacture ID
1771 * 15 ~ 8 : SKU ID
1772 * 7 ~ 0 : Assembly ID
1773 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1775 static int alc_subsystem_id(struct hda_codec *codec,
1776 hda_nid_t porta, hda_nid_t porte,
1777 hda_nid_t portd, hda_nid_t porti)
1779 unsigned int ass, tmp, i;
1780 unsigned nid;
1781 struct alc_spec *spec = codec->spec;
1783 if (spec->cdefine.fixup) {
1784 ass = spec->cdefine.sku_cfg;
1785 if (ass == ALC_FIXUP_SKU_IGNORE)
1786 return 0;
1787 goto do_sku;
1790 ass = codec->subsystem_id & 0xffff;
1791 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1792 goto do_sku;
1794 /* invalid SSID, check the special NID pin defcfg instead */
1796 * 31~30 : port connectivity
1797 * 29~21 : reserve
1798 * 20 : PCBEEP input
1799 * 19~16 : Check sum (15:1)
1800 * 15~1 : Custom
1801 * 0 : override
1803 nid = 0x1d;
1804 if (codec->vendor_id == 0x10ec0260)
1805 nid = 0x17;
1806 ass = snd_hda_codec_get_pincfg(codec, nid);
1807 snd_printd("realtek: No valid SSID, "
1808 "checking pincfg 0x%08x for NID 0x%x\n",
1809 ass, nid);
1810 if (!(ass & 1))
1811 return 0;
1812 if ((ass >> 30) != 1) /* no physical connection */
1813 return 0;
1815 /* check sum */
1816 tmp = 0;
1817 for (i = 1; i < 16; i++) {
1818 if ((ass >> i) & 1)
1819 tmp++;
1821 if (((ass >> 16) & 0xf) != tmp)
1822 return 0;
1823 do_sku:
1824 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1825 ass & 0xffff, codec->vendor_id);
1827 * 0 : override
1828 * 1 : Swap Jack
1829 * 2 : 0 --> Desktop, 1 --> Laptop
1830 * 3~5 : External Amplifier control
1831 * 7~6 : Reserved
1833 tmp = (ass & 0x38) >> 3; /* external Amp control */
1834 switch (tmp) {
1835 case 1:
1836 spec->init_amp = ALC_INIT_GPIO1;
1837 break;
1838 case 3:
1839 spec->init_amp = ALC_INIT_GPIO2;
1840 break;
1841 case 7:
1842 spec->init_amp = ALC_INIT_GPIO3;
1843 break;
1844 case 5:
1845 default:
1846 spec->init_amp = ALC_INIT_DEFAULT;
1847 break;
1850 /* is laptop or Desktop and enable the function "Mute internal speaker
1851 * when the external headphone out jack is plugged"
1853 if (!(ass & 0x8000))
1854 return 1;
1856 * 10~8 : Jack location
1857 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1858 * 14~13: Resvered
1859 * 15 : 1 --> enable the function "Mute internal speaker
1860 * when the external headphone out jack is plugged"
1862 if (!spec->autocfg.hp_pins[0]) {
1863 hda_nid_t nid;
1864 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1865 if (tmp == 0)
1866 nid = porta;
1867 else if (tmp == 1)
1868 nid = porte;
1869 else if (tmp == 2)
1870 nid = portd;
1871 else if (tmp == 3)
1872 nid = porti;
1873 else
1874 return 1;
1875 for (i = 0; i < spec->autocfg.line_outs; i++)
1876 if (spec->autocfg.line_out_pins[i] == nid)
1877 return 1;
1878 spec->autocfg.hp_pins[0] = nid;
1880 return 1;
1883 static void alc_ssid_check(struct hda_codec *codec,
1884 hda_nid_t porta, hda_nid_t porte,
1885 hda_nid_t portd, hda_nid_t porti)
1887 if (!alc_subsystem_id(codec, porta, porte, portd, porti)) {
1888 struct alc_spec *spec = codec->spec;
1889 snd_printd("realtek: "
1890 "Enable default setup for auto mode as fallback\n");
1891 spec->init_amp = ALC_INIT_DEFAULT;
1894 alc_init_auto_hp(codec);
1895 alc_init_auto_mic(codec);
1899 * Fix-up pin default configurations and add default verbs
1902 struct alc_pincfg {
1903 hda_nid_t nid;
1904 u32 val;
1907 struct alc_model_fixup {
1908 const int id;
1909 const char *name;
1912 struct alc_fixup {
1913 int type;
1914 bool chained;
1915 int chain_id;
1916 union {
1917 unsigned int sku;
1918 const struct alc_pincfg *pins;
1919 const struct hda_verb *verbs;
1920 void (*func)(struct hda_codec *codec,
1921 const struct alc_fixup *fix,
1922 int action);
1923 } v;
1926 enum {
1927 ALC_FIXUP_INVALID,
1928 ALC_FIXUP_SKU,
1929 ALC_FIXUP_PINS,
1930 ALC_FIXUP_VERBS,
1931 ALC_FIXUP_FUNC,
1934 enum {
1935 ALC_FIXUP_ACT_PRE_PROBE,
1936 ALC_FIXUP_ACT_PROBE,
1937 ALC_FIXUP_ACT_INIT,
1940 static void alc_apply_fixup(struct hda_codec *codec, int action)
1942 struct alc_spec *spec = codec->spec;
1943 int id = spec->fixup_id;
1944 #ifdef CONFIG_SND_DEBUG_VERBOSE
1945 const char *modelname = spec->fixup_name;
1946 #endif
1947 int depth = 0;
1949 if (!spec->fixup_list)
1950 return;
1952 while (id >= 0) {
1953 const struct alc_fixup *fix = spec->fixup_list + id;
1954 const struct alc_pincfg *cfg;
1956 switch (fix->type) {
1957 case ALC_FIXUP_SKU:
1958 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1959 break;;
1960 snd_printdd(KERN_INFO "hda_codec: %s: "
1961 "Apply sku override for %s\n",
1962 codec->chip_name, modelname);
1963 spec->cdefine.sku_cfg = fix->v.sku;
1964 spec->cdefine.fixup = 1;
1965 break;
1966 case ALC_FIXUP_PINS:
1967 cfg = fix->v.pins;
1968 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1969 break;
1970 snd_printdd(KERN_INFO "hda_codec: %s: "
1971 "Apply pincfg for %s\n",
1972 codec->chip_name, modelname);
1973 for (; cfg->nid; cfg++)
1974 snd_hda_codec_set_pincfg(codec, cfg->nid,
1975 cfg->val);
1976 break;
1977 case ALC_FIXUP_VERBS:
1978 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1979 break;
1980 snd_printdd(KERN_INFO "hda_codec: %s: "
1981 "Apply fix-verbs for %s\n",
1982 codec->chip_name, modelname);
1983 add_verb(codec->spec, fix->v.verbs);
1984 break;
1985 case ALC_FIXUP_FUNC:
1986 if (!fix->v.func)
1987 break;
1988 snd_printdd(KERN_INFO "hda_codec: %s: "
1989 "Apply fix-func for %s\n",
1990 codec->chip_name, modelname);
1991 fix->v.func(codec, fix, action);
1992 break;
1993 default:
1994 snd_printk(KERN_ERR "hda_codec: %s: "
1995 "Invalid fixup type %d\n",
1996 codec->chip_name, fix->type);
1997 break;
1999 if (!fix->chained)
2000 break;
2001 if (++depth > 10)
2002 break;
2003 id = fix->chain_id;
2007 static void alc_pick_fixup(struct hda_codec *codec,
2008 const struct alc_model_fixup *models,
2009 const struct snd_pci_quirk *quirk,
2010 const struct alc_fixup *fixlist)
2012 struct alc_spec *spec = codec->spec;
2013 int id = -1;
2014 const char *name = NULL;
2016 if (codec->modelname && models) {
2017 while (models->name) {
2018 if (!strcmp(codec->modelname, models->name)) {
2019 id = models->id;
2020 name = models->name;
2021 break;
2023 models++;
2026 if (id < 0) {
2027 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
2028 if (quirk) {
2029 id = quirk->value;
2030 #ifdef CONFIG_SND_DEBUG_VERBOSE
2031 name = quirk->name;
2032 #endif
2036 spec->fixup_id = id;
2037 if (id >= 0) {
2038 spec->fixup_list = fixlist;
2039 spec->fixup_name = name;
2043 static int alc_read_coef_idx(struct hda_codec *codec,
2044 unsigned int coef_idx)
2046 unsigned int val;
2047 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
2048 coef_idx);
2049 val = snd_hda_codec_read(codec, 0x20, 0,
2050 AC_VERB_GET_PROC_COEF, 0);
2051 return val;
2054 static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
2055 unsigned int coef_val)
2057 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
2058 coef_idx);
2059 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
2060 coef_val);
2063 /* set right pin controls for digital I/O */
2064 static void alc_auto_init_digital(struct hda_codec *codec)
2066 struct alc_spec *spec = codec->spec;
2067 int i;
2068 hda_nid_t pin;
2070 for (i = 0; i < spec->autocfg.dig_outs; i++) {
2071 pin = spec->autocfg.dig_out_pins[i];
2072 if (pin) {
2073 snd_hda_codec_write(codec, pin, 0,
2074 AC_VERB_SET_PIN_WIDGET_CONTROL,
2075 PIN_OUT);
2078 pin = spec->autocfg.dig_in_pin;
2079 if (pin)
2080 snd_hda_codec_write(codec, pin, 0,
2081 AC_VERB_SET_PIN_WIDGET_CONTROL,
2082 PIN_IN);
2085 /* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
2086 static void alc_auto_parse_digital(struct hda_codec *codec)
2088 struct alc_spec *spec = codec->spec;
2089 int i, err;
2090 hda_nid_t dig_nid;
2092 /* support multiple SPDIFs; the secondary is set up as a slave */
2093 for (i = 0; i < spec->autocfg.dig_outs; i++) {
2094 err = snd_hda_get_connections(codec,
2095 spec->autocfg.dig_out_pins[i],
2096 &dig_nid, 1);
2097 if (err < 0)
2098 continue;
2099 if (!i) {
2100 spec->multiout.dig_out_nid = dig_nid;
2101 spec->dig_out_type = spec->autocfg.dig_out_type[0];
2102 } else {
2103 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
2104 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
2105 break;
2106 spec->slave_dig_outs[i - 1] = dig_nid;
2110 if (spec->autocfg.dig_in_pin) {
2111 dig_nid = codec->start_nid;
2112 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
2113 unsigned int wcaps = get_wcaps(codec, dig_nid);
2114 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
2115 continue;
2116 if (!(wcaps & AC_WCAP_DIGITAL))
2117 continue;
2118 if (!(wcaps & AC_WCAP_CONN_LIST))
2119 continue;
2120 err = get_connection_index(codec, dig_nid,
2121 spec->autocfg.dig_in_pin);
2122 if (err >= 0) {
2123 spec->dig_in_nid = dig_nid;
2124 break;
2131 * ALC888
2135 * 2ch mode
2137 static const struct hda_verb alc888_4ST_ch2_intel_init[] = {
2138 /* Mic-in jack as mic in */
2139 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2140 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2141 /* Line-in jack as Line in */
2142 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2143 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2144 /* Line-Out as Front */
2145 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
2146 { } /* end */
2150 * 4ch mode
2152 static const struct hda_verb alc888_4ST_ch4_intel_init[] = {
2153 /* Mic-in jack as mic in */
2154 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2155 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2156 /* Line-in jack as Surround */
2157 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2158 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2159 /* Line-Out as Front */
2160 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
2161 { } /* end */
2165 * 6ch mode
2167 static const struct hda_verb alc888_4ST_ch6_intel_init[] = {
2168 /* Mic-in jack as CLFE */
2169 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2170 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2171 /* Line-in jack as Surround */
2172 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2173 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2174 /* Line-Out as CLFE (workaround because Mic-in is not loud enough) */
2175 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
2176 { } /* end */
2180 * 8ch mode
2182 static const struct hda_verb alc888_4ST_ch8_intel_init[] = {
2183 /* Mic-in jack as CLFE */
2184 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2185 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2186 /* Line-in jack as Surround */
2187 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2188 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2189 /* Line-Out as Side */
2190 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
2191 { } /* end */
2194 static const struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
2195 { 2, alc888_4ST_ch2_intel_init },
2196 { 4, alc888_4ST_ch4_intel_init },
2197 { 6, alc888_4ST_ch6_intel_init },
2198 { 8, alc888_4ST_ch8_intel_init },
2202 * ALC888 Fujitsu Siemens Amillo xa3530
2205 static const struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
2206 /* Front Mic: set to PIN_IN (empty by default) */
2207 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2208 /* Connect Internal HP to Front */
2209 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2210 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2211 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
2212 /* Connect Bass HP to Front */
2213 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2214 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2215 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2216 /* Connect Line-Out side jack (SPDIF) to Side */
2217 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2218 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2219 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
2220 /* Connect Mic jack to CLFE */
2221 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2222 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2223 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
2224 /* Connect Line-in jack to Surround */
2225 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2226 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2227 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
2228 /* Connect HP out jack to Front */
2229 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2230 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2231 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
2232 /* Enable unsolicited event for HP jack and Line-out jack */
2233 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2234 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2238 static void alc889_automute_setup(struct hda_codec *codec)
2240 struct alc_spec *spec = codec->spec;
2242 spec->autocfg.hp_pins[0] = 0x15;
2243 spec->autocfg.speaker_pins[0] = 0x14;
2244 spec->autocfg.speaker_pins[1] = 0x16;
2245 spec->autocfg.speaker_pins[2] = 0x17;
2246 spec->autocfg.speaker_pins[3] = 0x19;
2247 spec->autocfg.speaker_pins[4] = 0x1a;
2248 spec->automute = 1;
2249 spec->automute_mode = ALC_AUTOMUTE_AMP;
2252 static void alc889_intel_init_hook(struct hda_codec *codec)
2254 alc889_coef_init(codec);
2255 alc_hp_automute(codec);
2258 static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
2260 struct alc_spec *spec = codec->spec;
2262 spec->autocfg.hp_pins[0] = 0x17; /* line-out */
2263 spec->autocfg.hp_pins[1] = 0x1b; /* hp */
2264 spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
2265 spec->autocfg.speaker_pins[1] = 0x15; /* bass */
2266 spec->automute = 1;
2267 spec->automute_mode = ALC_AUTOMUTE_AMP;
2271 * ALC888 Acer Aspire 4930G model
2274 static const struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
2275 /* Front Mic: set to PIN_IN (empty by default) */
2276 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2277 /* Unselect Front Mic by default in input mixer 3 */
2278 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
2279 /* Enable unsolicited event for HP jack */
2280 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2281 /* Connect Internal HP to front */
2282 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2283 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2284 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
2285 /* Connect HP out to front */
2286 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2287 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2288 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2289 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
2294 * ALC888 Acer Aspire 6530G model
2297 static const struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
2298 /* Route to built-in subwoofer as well as speakers */
2299 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2300 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2301 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2302 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2303 /* Bias voltage on for external mic port */
2304 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
2305 /* Front Mic: set to PIN_IN (empty by default) */
2306 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2307 /* Unselect Front Mic by default in input mixer 3 */
2308 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
2309 /* Enable unsolicited event for HP jack */
2310 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2311 /* Enable speaker output */
2312 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2313 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2314 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
2315 /* Enable headphone output */
2316 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
2317 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2318 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2319 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
2324 *ALC888 Acer Aspire 7730G model
2327 static const struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
2328 /* Bias voltage on for external mic port */
2329 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
2330 /* Front Mic: set to PIN_IN (empty by default) */
2331 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2332 /* Unselect Front Mic by default in input mixer 3 */
2333 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
2334 /* Enable unsolicited event for HP jack */
2335 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2336 /* Enable speaker output */
2337 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2338 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2339 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
2340 /* Enable headphone output */
2341 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
2342 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2343 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2344 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
2345 /*Enable internal subwoofer */
2346 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2347 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2348 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
2349 {0x17, AC_VERB_SET_EAPD_BTLENABLE, 2},
2354 * ALC889 Acer Aspire 8930G model
2357 static const struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
2358 /* Front Mic: set to PIN_IN (empty by default) */
2359 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2360 /* Unselect Front Mic by default in input mixer 3 */
2361 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
2362 /* Enable unsolicited event for HP jack */
2363 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2364 /* Connect Internal Front to Front */
2365 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2366 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2367 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
2368 /* Connect Internal Rear to Rear */
2369 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2370 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2371 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
2372 /* Connect Internal CLFE to CLFE */
2373 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2374 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2375 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
2376 /* Connect HP out to Front */
2377 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
2378 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2379 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2380 /* Enable all DACs */
2381 /* DAC DISABLE/MUTE 1? */
2382 /* setting bits 1-5 disables DAC nids 0x02-0x06 apparently. Init=0x38 */
2383 {0x20, AC_VERB_SET_COEF_INDEX, 0x03},
2384 {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
2385 /* DAC DISABLE/MUTE 2? */
2386 /* some bit here disables the other DACs. Init=0x4900 */
2387 {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
2388 {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
2389 /* DMIC fix
2390 * This laptop has a stereo digital microphone. The mics are only 1cm apart
2391 * which makes the stereo useless. However, either the mic or the ALC889
2392 * makes the signal become a difference/sum signal instead of standard
2393 * stereo, which is annoying. So instead we flip this bit which makes the
2394 * codec replicate the sum signal to both channels, turning it into a
2395 * normal mono mic.
2397 /* DMIC_CONTROL? Init value = 0x0001 */
2398 {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
2399 {0x20, AC_VERB_SET_PROC_COEF, 0x0003},
2403 static const struct hda_input_mux alc888_2_capture_sources[2] = {
2404 /* Front mic only available on one ADC */
2406 .num_items = 4,
2407 .items = {
2408 { "Mic", 0x0 },
2409 { "Line", 0x2 },
2410 { "CD", 0x4 },
2411 { "Front Mic", 0xb },
2415 .num_items = 3,
2416 .items = {
2417 { "Mic", 0x0 },
2418 { "Line", 0x2 },
2419 { "CD", 0x4 },
2424 static const struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
2425 /* Interal mic only available on one ADC */
2427 .num_items = 5,
2428 .items = {
2429 { "Mic", 0x0 },
2430 { "Line In", 0x2 },
2431 { "CD", 0x4 },
2432 { "Input Mix", 0xa },
2433 { "Internal Mic", 0xb },
2437 .num_items = 4,
2438 .items = {
2439 { "Mic", 0x0 },
2440 { "Line In", 0x2 },
2441 { "CD", 0x4 },
2442 { "Input Mix", 0xa },
2447 static const struct hda_input_mux alc889_capture_sources[3] = {
2448 /* Digital mic only available on first "ADC" */
2450 .num_items = 5,
2451 .items = {
2452 { "Mic", 0x0 },
2453 { "Line", 0x2 },
2454 { "CD", 0x4 },
2455 { "Front Mic", 0xb },
2456 { "Input Mix", 0xa },
2460 .num_items = 4,
2461 .items = {
2462 { "Mic", 0x0 },
2463 { "Line", 0x2 },
2464 { "CD", 0x4 },
2465 { "Input Mix", 0xa },
2469 .num_items = 4,
2470 .items = {
2471 { "Mic", 0x0 },
2472 { "Line", 0x2 },
2473 { "CD", 0x4 },
2474 { "Input Mix", 0xa },
2479 static const struct snd_kcontrol_new alc888_base_mixer[] = {
2480 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2481 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2482 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2483 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2484 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
2485 HDA_OUTPUT),
2486 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2487 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2488 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2489 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2490 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
2491 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2492 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2493 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2494 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2495 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2496 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
2497 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2498 { } /* end */
2501 static const struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
2502 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2503 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2504 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2505 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2506 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
2507 HDA_OUTPUT),
2508 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2509 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2510 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2511 HDA_CODEC_VOLUME_MONO("Internal LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT),
2512 HDA_BIND_MUTE_MONO("Internal LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT),
2513 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2514 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2515 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2516 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2517 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2518 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
2519 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2520 { } /* end */
2523 static const struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
2524 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2525 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2526 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2527 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2528 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
2529 HDA_OUTPUT),
2530 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2531 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2532 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2533 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2534 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2535 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2536 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
2537 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2538 { } /* end */
2542 static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
2544 struct alc_spec *spec = codec->spec;
2546 spec->autocfg.hp_pins[0] = 0x15;
2547 spec->autocfg.speaker_pins[0] = 0x14;
2548 spec->autocfg.speaker_pins[1] = 0x16;
2549 spec->autocfg.speaker_pins[2] = 0x17;
2550 spec->automute = 1;
2551 spec->automute_mode = ALC_AUTOMUTE_AMP;
2554 static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
2556 struct alc_spec *spec = codec->spec;
2558 spec->autocfg.hp_pins[0] = 0x15;
2559 spec->autocfg.speaker_pins[0] = 0x14;
2560 spec->autocfg.speaker_pins[1] = 0x16;
2561 spec->autocfg.speaker_pins[2] = 0x17;
2562 spec->automute = 1;
2563 spec->automute_mode = ALC_AUTOMUTE_AMP;
2566 static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
2568 struct alc_spec *spec = codec->spec;
2570 spec->autocfg.hp_pins[0] = 0x15;
2571 spec->autocfg.speaker_pins[0] = 0x14;
2572 spec->autocfg.speaker_pins[1] = 0x16;
2573 spec->autocfg.speaker_pins[2] = 0x17;
2574 spec->automute = 1;
2575 spec->automute_mode = ALC_AUTOMUTE_AMP;
2578 static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
2580 struct alc_spec *spec = codec->spec;
2582 spec->autocfg.hp_pins[0] = 0x15;
2583 spec->autocfg.speaker_pins[0] = 0x14;
2584 spec->autocfg.speaker_pins[1] = 0x16;
2585 spec->autocfg.speaker_pins[2] = 0x1b;
2586 spec->automute = 1;
2587 spec->automute_mode = ALC_AUTOMUTE_AMP;
2591 * ALC880 3-stack model
2593 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
2594 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
2595 * F-Mic = 0x1b, HP = 0x19
2598 static const hda_nid_t alc880_dac_nids[4] = {
2599 /* front, rear, clfe, rear_surr */
2600 0x02, 0x05, 0x04, 0x03
2603 static const hda_nid_t alc880_adc_nids[3] = {
2604 /* ADC0-2 */
2605 0x07, 0x08, 0x09,
2608 /* The datasheet says the node 0x07 is connected from inputs,
2609 * but it shows zero connection in the real implementation on some devices.
2610 * Note: this is a 915GAV bug, fixed on 915GLV
2612 static const hda_nid_t alc880_adc_nids_alt[2] = {
2613 /* ADC1-2 */
2614 0x08, 0x09,
2617 #define ALC880_DIGOUT_NID 0x06
2618 #define ALC880_DIGIN_NID 0x0a
2620 static const struct hda_input_mux alc880_capture_source = {
2621 .num_items = 4,
2622 .items = {
2623 { "Mic", 0x0 },
2624 { "Front Mic", 0x3 },
2625 { "Line", 0x2 },
2626 { "CD", 0x4 },
2630 /* channel source setting (2/6 channel selection for 3-stack) */
2631 /* 2ch mode */
2632 static const struct hda_verb alc880_threestack_ch2_init[] = {
2633 /* set line-in to input, mute it */
2634 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2635 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2636 /* set mic-in to input vref 80%, mute it */
2637 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2638 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2639 { } /* end */
2642 /* 6ch mode */
2643 static const struct hda_verb alc880_threestack_ch6_init[] = {
2644 /* set line-in to output, unmute it */
2645 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2646 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2647 /* set mic-in to output, unmute it */
2648 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2649 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2650 { } /* end */
2653 static const struct hda_channel_mode alc880_threestack_modes[2] = {
2654 { 2, alc880_threestack_ch2_init },
2655 { 6, alc880_threestack_ch6_init },
2658 static const struct snd_kcontrol_new alc880_three_stack_mixer[] = {
2659 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2660 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2661 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2662 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
2663 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2664 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2665 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2666 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2667 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2668 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2669 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2670 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2671 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2672 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2673 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
2674 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
2675 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
2677 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2678 .name = "Channel Mode",
2679 .info = alc_ch_mode_info,
2680 .get = alc_ch_mode_get,
2681 .put = alc_ch_mode_put,
2683 { } /* end */
2686 /* capture mixer elements */
2687 static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
2688 struct snd_ctl_elem_info *uinfo)
2690 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2691 struct alc_spec *spec = codec->spec;
2692 int err;
2694 mutex_lock(&codec->control_mutex);
2695 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
2696 HDA_INPUT);
2697 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
2698 mutex_unlock(&codec->control_mutex);
2699 return err;
2702 static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
2703 unsigned int size, unsigned int __user *tlv)
2705 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2706 struct alc_spec *spec = codec->spec;
2707 int err;
2709 mutex_lock(&codec->control_mutex);
2710 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
2711 HDA_INPUT);
2712 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
2713 mutex_unlock(&codec->control_mutex);
2714 return err;
2717 typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
2718 struct snd_ctl_elem_value *ucontrol);
2720 static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
2721 struct snd_ctl_elem_value *ucontrol,
2722 getput_call_t func, bool check_adc_switch)
2724 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2725 struct alc_spec *spec = codec->spec;
2726 int i, err = 0;
2728 mutex_lock(&codec->control_mutex);
2729 if (check_adc_switch && spec->dual_adc_switch) {
2730 for (i = 0; i < spec->num_adc_nids; i++) {
2731 kcontrol->private_value =
2732 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
2733 3, 0, HDA_INPUT);
2734 err = func(kcontrol, ucontrol);
2735 if (err < 0)
2736 goto error;
2738 } else {
2739 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2740 kcontrol->private_value =
2741 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
2742 3, 0, HDA_INPUT);
2743 err = func(kcontrol, ucontrol);
2745 error:
2746 mutex_unlock(&codec->control_mutex);
2747 return err;
2750 static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
2751 struct snd_ctl_elem_value *ucontrol)
2753 return alc_cap_getput_caller(kcontrol, ucontrol,
2754 snd_hda_mixer_amp_volume_get, false);
2757 static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
2758 struct snd_ctl_elem_value *ucontrol)
2760 return alc_cap_getput_caller(kcontrol, ucontrol,
2761 snd_hda_mixer_amp_volume_put, true);
2764 /* capture mixer elements */
2765 #define alc_cap_sw_info snd_ctl_boolean_stereo_info
2767 static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
2768 struct snd_ctl_elem_value *ucontrol)
2770 return alc_cap_getput_caller(kcontrol, ucontrol,
2771 snd_hda_mixer_amp_switch_get, false);
2774 static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
2775 struct snd_ctl_elem_value *ucontrol)
2777 return alc_cap_getput_caller(kcontrol, ucontrol,
2778 snd_hda_mixer_amp_switch_put, true);
2781 #define _DEFINE_CAPMIX(num) \
2783 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2784 .name = "Capture Switch", \
2785 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
2786 .count = num, \
2787 .info = alc_cap_sw_info, \
2788 .get = alc_cap_sw_get, \
2789 .put = alc_cap_sw_put, \
2790 }, \
2792 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2793 .name = "Capture Volume", \
2794 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2795 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
2796 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
2797 .count = num, \
2798 .info = alc_cap_vol_info, \
2799 .get = alc_cap_vol_get, \
2800 .put = alc_cap_vol_put, \
2801 .tlv = { .c = alc_cap_vol_tlv }, \
2804 #define _DEFINE_CAPSRC(num) \
2806 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2807 /* .name = "Capture Source", */ \
2808 .name = "Input Source", \
2809 .count = num, \
2810 .info = alc_mux_enum_info, \
2811 .get = alc_mux_enum_get, \
2812 .put = alc_mux_enum_put, \
2815 #define DEFINE_CAPMIX(num) \
2816 static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
2817 _DEFINE_CAPMIX(num), \
2818 _DEFINE_CAPSRC(num), \
2819 { } /* end */ \
2822 #define DEFINE_CAPMIX_NOSRC(num) \
2823 static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
2824 _DEFINE_CAPMIX(num), \
2825 { } /* end */ \
2828 /* up to three ADCs */
2829 DEFINE_CAPMIX(1);
2830 DEFINE_CAPMIX(2);
2831 DEFINE_CAPMIX(3);
2832 DEFINE_CAPMIX_NOSRC(1);
2833 DEFINE_CAPMIX_NOSRC(2);
2834 DEFINE_CAPMIX_NOSRC(3);
2837 * ALC880 5-stack model
2839 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
2840 * Side = 0x02 (0xd)
2841 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
2842 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
2845 /* additional mixers to alc880_three_stack_mixer */
2846 static const struct snd_kcontrol_new alc880_five_stack_mixer[] = {
2847 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2848 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
2849 { } /* end */
2852 /* channel source setting (6/8 channel selection for 5-stack) */
2853 /* 6ch mode */
2854 static const struct hda_verb alc880_fivestack_ch6_init[] = {
2855 /* set line-in to input, mute it */
2856 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2857 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2858 { } /* end */
2861 /* 8ch mode */
2862 static const struct hda_verb alc880_fivestack_ch8_init[] = {
2863 /* set line-in to output, unmute it */
2864 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2865 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2866 { } /* end */
2869 static const struct hda_channel_mode alc880_fivestack_modes[2] = {
2870 { 6, alc880_fivestack_ch6_init },
2871 { 8, alc880_fivestack_ch8_init },
2876 * ALC880 6-stack model
2878 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
2879 * Side = 0x05 (0x0f)
2880 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
2881 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
2884 static const hda_nid_t alc880_6st_dac_nids[4] = {
2885 /* front, rear, clfe, rear_surr */
2886 0x02, 0x03, 0x04, 0x05
2889 static const struct hda_input_mux alc880_6stack_capture_source = {
2890 .num_items = 4,
2891 .items = {
2892 { "Mic", 0x0 },
2893 { "Front Mic", 0x1 },
2894 { "Line", 0x2 },
2895 { "CD", 0x4 },
2899 /* fixed 8-channels */
2900 static const struct hda_channel_mode alc880_sixstack_modes[1] = {
2901 { 8, NULL },
2904 static const struct snd_kcontrol_new alc880_six_stack_mixer[] = {
2905 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2906 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2907 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2908 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2909 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2910 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2911 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2912 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2913 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2914 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
2915 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2916 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2917 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2918 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2919 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2920 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2921 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2922 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
2924 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2925 .name = "Channel Mode",
2926 .info = alc_ch_mode_info,
2927 .get = alc_ch_mode_get,
2928 .put = alc_ch_mode_put,
2930 { } /* end */
2935 * ALC880 W810 model
2937 * W810 has rear IO for:
2938 * Front (DAC 02)
2939 * Surround (DAC 03)
2940 * Center/LFE (DAC 04)
2941 * Digital out (06)
2943 * The system also has a pair of internal speakers, and a headphone jack.
2944 * These are both connected to Line2 on the codec, hence to DAC 02.
2946 * There is a variable resistor to control the speaker or headphone
2947 * volume. This is a hardware-only device without a software API.
2949 * Plugging headphones in will disable the internal speakers. This is
2950 * implemented in hardware, not via the driver using jack sense. In
2951 * a similar fashion, plugging into the rear socket marked "front" will
2952 * disable both the speakers and headphones.
2954 * For input, there's a microphone jack, and an "audio in" jack.
2955 * These may not do anything useful with this driver yet, because I
2956 * haven't setup any initialization verbs for these yet...
2959 static const hda_nid_t alc880_w810_dac_nids[3] = {
2960 /* front, rear/surround, clfe */
2961 0x02, 0x03, 0x04
2964 /* fixed 6 channels */
2965 static const struct hda_channel_mode alc880_w810_modes[1] = {
2966 { 6, NULL }
2969 /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
2970 static const struct snd_kcontrol_new alc880_w810_base_mixer[] = {
2971 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2972 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2973 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2974 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2975 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2976 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2977 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2978 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2979 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
2980 { } /* end */
2985 * Z710V model
2987 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
2988 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
2989 * Line = 0x1a
2992 static const hda_nid_t alc880_z71v_dac_nids[1] = {
2993 0x02
2995 #define ALC880_Z71V_HP_DAC 0x03
2997 /* fixed 2 channels */
2998 static const struct hda_channel_mode alc880_2_jack_modes[1] = {
2999 { 2, NULL }
3002 static const struct snd_kcontrol_new alc880_z71v_mixer[] = {
3003 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3004 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3005 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3006 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
3007 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3008 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3009 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3010 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3011 { } /* end */
3016 * ALC880 F1734 model
3018 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
3019 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
3022 static const hda_nid_t alc880_f1734_dac_nids[1] = {
3023 0x03
3025 #define ALC880_F1734_HP_DAC 0x02
3027 static const struct snd_kcontrol_new alc880_f1734_mixer[] = {
3028 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3029 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
3030 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3031 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
3032 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3033 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3034 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3035 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3036 { } /* end */
3039 static const struct hda_input_mux alc880_f1734_capture_source = {
3040 .num_items = 2,
3041 .items = {
3042 { "Mic", 0x1 },
3043 { "CD", 0x4 },
3049 * ALC880 ASUS model
3051 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
3052 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
3053 * Mic = 0x18, Line = 0x1a
3056 #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
3057 #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
3059 static const struct snd_kcontrol_new alc880_asus_mixer[] = {
3060 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3061 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3062 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3063 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
3064 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3065 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3066 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3067 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3068 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3069 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3070 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3071 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3072 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3073 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3075 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3076 .name = "Channel Mode",
3077 .info = alc_ch_mode_info,
3078 .get = alc_ch_mode_get,
3079 .put = alc_ch_mode_put,
3081 { } /* end */
3085 * ALC880 ASUS W1V model
3087 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
3088 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
3089 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
3092 /* additional mixers to alc880_asus_mixer */
3093 static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
3094 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
3095 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
3096 { } /* end */
3099 /* TCL S700 */
3100 static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
3101 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3102 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
3103 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
3104 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
3105 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
3106 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
3107 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
3108 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3109 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3110 { } /* end */
3113 /* Uniwill */
3114 static const struct snd_kcontrol_new alc880_uniwill_mixer[] = {
3115 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3116 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
3117 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3118 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
3119 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3120 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3121 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3122 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3123 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3124 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3125 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3126 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3127 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3128 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3129 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3130 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3132 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3133 .name = "Channel Mode",
3134 .info = alc_ch_mode_info,
3135 .get = alc_ch_mode_get,
3136 .put = alc_ch_mode_put,
3138 { } /* end */
3141 static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
3142 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3143 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
3144 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3145 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
3146 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3147 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3148 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3149 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3150 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3151 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3152 { } /* end */
3155 static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
3156 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3157 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
3158 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3159 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
3160 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3161 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3162 { } /* end */
3166 * virtual master controls
3170 * slave controls for virtual master
3172 static const char * const alc_slave_vols[] = {
3173 "Front Playback Volume",
3174 "Surround Playback Volume",
3175 "Center Playback Volume",
3176 "LFE Playback Volume",
3177 "Side Playback Volume",
3178 "Headphone Playback Volume",
3179 "Speaker Playback Volume",
3180 "Mono Playback Volume",
3181 "Line-Out Playback Volume",
3182 NULL,
3185 static const char * const alc_slave_sws[] = {
3186 "Front Playback Switch",
3187 "Surround Playback Switch",
3188 "Center Playback Switch",
3189 "LFE Playback Switch",
3190 "Side Playback Switch",
3191 "Headphone Playback Switch",
3192 "Speaker Playback Switch",
3193 "Mono Playback Switch",
3194 "IEC958 Playback Switch",
3195 "Line-Out Playback Switch",
3196 NULL,
3200 * build control elements
3203 #define NID_MAPPING (-1)
3205 #define SUBDEV_SPEAKER_ (0 << 6)
3206 #define SUBDEV_HP_ (1 << 6)
3207 #define SUBDEV_LINE_ (2 << 6)
3208 #define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
3209 #define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
3210 #define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
3212 static void alc_free_kctls(struct hda_codec *codec);
3214 #ifdef CONFIG_SND_HDA_INPUT_BEEP
3215 /* additional beep mixers; the actual parameters are overwritten at build */
3216 static const struct snd_kcontrol_new alc_beep_mixer[] = {
3217 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
3218 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
3219 { } /* end */
3221 #endif
3223 static int alc_build_controls(struct hda_codec *codec)
3225 struct alc_spec *spec = codec->spec;
3226 struct snd_kcontrol *kctl = NULL;
3227 const struct snd_kcontrol_new *knew;
3228 int i, j, err;
3229 unsigned int u;
3230 hda_nid_t nid;
3232 for (i = 0; i < spec->num_mixers; i++) {
3233 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
3234 if (err < 0)
3235 return err;
3237 if (spec->cap_mixer) {
3238 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
3239 if (err < 0)
3240 return err;
3242 if (spec->multiout.dig_out_nid) {
3243 err = snd_hda_create_spdif_out_ctls(codec,
3244 spec->multiout.dig_out_nid);
3245 if (err < 0)
3246 return err;
3247 if (!spec->no_analog) {
3248 err = snd_hda_create_spdif_share_sw(codec,
3249 &spec->multiout);
3250 if (err < 0)
3251 return err;
3252 spec->multiout.share_spdif = 1;
3255 if (spec->dig_in_nid) {
3256 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
3257 if (err < 0)
3258 return err;
3261 #ifdef CONFIG_SND_HDA_INPUT_BEEP
3262 /* create beep controls if needed */
3263 if (spec->beep_amp) {
3264 const struct snd_kcontrol_new *knew;
3265 for (knew = alc_beep_mixer; knew->name; knew++) {
3266 struct snd_kcontrol *kctl;
3267 kctl = snd_ctl_new1(knew, codec);
3268 if (!kctl)
3269 return -ENOMEM;
3270 kctl->private_value = spec->beep_amp;
3271 err = snd_hda_ctl_add(codec, 0, kctl);
3272 if (err < 0)
3273 return err;
3276 #endif
3278 /* if we have no master control, let's create it */
3279 if (!spec->no_analog &&
3280 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
3281 unsigned int vmaster_tlv[4];
3282 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
3283 HDA_OUTPUT, vmaster_tlv);
3284 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
3285 vmaster_tlv, alc_slave_vols);
3286 if (err < 0)
3287 return err;
3289 if (!spec->no_analog &&
3290 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
3291 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
3292 NULL, alc_slave_sws);
3293 if (err < 0)
3294 return err;
3297 /* assign Capture Source enums to NID */
3298 if (spec->capsrc_nids || spec->adc_nids) {
3299 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
3300 if (!kctl)
3301 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
3302 for (i = 0; kctl && i < kctl->count; i++) {
3303 const hda_nid_t *nids = spec->capsrc_nids;
3304 if (!nids)
3305 nids = spec->adc_nids;
3306 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
3307 if (err < 0)
3308 return err;
3311 if (spec->cap_mixer) {
3312 const char *kname = kctl ? kctl->id.name : NULL;
3313 for (knew = spec->cap_mixer; knew->name; knew++) {
3314 if (kname && strcmp(knew->name, kname) == 0)
3315 continue;
3316 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
3317 for (i = 0; kctl && i < kctl->count; i++) {
3318 err = snd_hda_add_nid(codec, kctl, i,
3319 spec->adc_nids[i]);
3320 if (err < 0)
3321 return err;
3326 /* other nid->control mapping */
3327 for (i = 0; i < spec->num_mixers; i++) {
3328 for (knew = spec->mixers[i]; knew->name; knew++) {
3329 if (knew->iface != NID_MAPPING)
3330 continue;
3331 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
3332 if (kctl == NULL)
3333 continue;
3334 u = knew->subdevice;
3335 for (j = 0; j < 4; j++, u >>= 8) {
3336 nid = u & 0x3f;
3337 if (nid == 0)
3338 continue;
3339 switch (u & 0xc0) {
3340 case SUBDEV_SPEAKER_:
3341 nid = spec->autocfg.speaker_pins[nid];
3342 break;
3343 case SUBDEV_LINE_:
3344 nid = spec->autocfg.line_out_pins[nid];
3345 break;
3346 case SUBDEV_HP_:
3347 nid = spec->autocfg.hp_pins[nid];
3348 break;
3349 default:
3350 continue;
3352 err = snd_hda_add_nid(codec, kctl, 0, nid);
3353 if (err < 0)
3354 return err;
3356 u = knew->private_value;
3357 for (j = 0; j < 4; j++, u >>= 8) {
3358 nid = u & 0xff;
3359 if (nid == 0)
3360 continue;
3361 err = snd_hda_add_nid(codec, kctl, 0, nid);
3362 if (err < 0)
3363 return err;
3368 alc_free_kctls(codec); /* no longer needed */
3370 return 0;
3375 * initialize the codec volumes, etc
3379 * generic initialization of ADC, input mixers and output mixers
3381 static const struct hda_verb alc880_volume_init_verbs[] = {
3383 * Unmute ADC0-2 and set the default input to mic-in
3385 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3386 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3387 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3388 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3389 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3390 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3392 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3393 * mixer widget
3394 * Note: PASD motherboards uses the Line In 2 as the input for front
3395 * panel mic (mic 2)
3397 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3398 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3399 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3400 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3401 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3402 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3403 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3404 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
3407 * Set up output mixers (0x0c - 0x0f)
3409 /* set vol=0 to output mixers */
3410 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3411 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3412 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3413 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3414 /* set up input amps for analog loopback */
3415 /* Amp Indices: DAC = 0, mixer = 1 */
3416 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3417 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3418 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3419 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3420 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3421 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3422 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3423 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3429 * 3-stack pin configuration:
3430 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
3432 static const struct hda_verb alc880_pin_3stack_init_verbs[] = {
3434 * preset connection lists of input pins
3435 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
3437 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
3438 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3439 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
3442 * Set pin mode and muting
3444 /* set front pin widgets 0x14 for output */
3445 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3446 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3447 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3448 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3449 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3450 /* Mic2 (as headphone out) for HP output */
3451 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3452 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3453 /* Line In pin widget for input */
3454 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3455 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3456 /* Line2 (as front mic) pin widget for input and vref at 80% */
3457 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3458 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3459 /* CD pin widget for input */
3460 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3466 * 5-stack pin configuration:
3467 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
3468 * line-in/side = 0x1a, f-mic = 0x1b
3470 static const struct hda_verb alc880_pin_5stack_init_verbs[] = {
3472 * preset connection lists of input pins
3473 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
3475 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3476 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
3479 * Set pin mode and muting
3481 /* set pin widgets 0x14-0x17 for output */
3482 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3483 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3484 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3485 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3486 /* unmute pins for output (no gain on this amp) */
3487 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3488 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3489 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3490 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3492 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3493 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3494 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3495 /* Mic2 (as headphone out) for HP output */
3496 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3497 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3498 /* Line In pin widget for input */
3499 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3500 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3501 /* Line2 (as front mic) pin widget for input and vref at 80% */
3502 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3503 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3504 /* CD pin widget for input */
3505 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3511 * W810 pin configuration:
3512 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
3514 static const struct hda_verb alc880_pin_w810_init_verbs[] = {
3515 /* hphone/speaker input selector: front DAC */
3516 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
3518 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3519 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3520 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3521 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3522 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3523 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3525 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3526 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3532 * Z71V pin configuration:
3533 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
3535 static const struct hda_verb alc880_pin_z71v_init_verbs[] = {
3536 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3537 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3538 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3539 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3541 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3542 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3543 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3544 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3550 * 6-stack pin configuration:
3551 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
3552 * f-mic = 0x19, line = 0x1a, HP = 0x1b
3554 static const struct hda_verb alc880_pin_6stack_init_verbs[] = {
3555 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3557 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3558 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3559 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3560 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3561 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3562 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3563 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3564 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3566 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3567 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3568 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3569 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3570 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3571 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3572 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3573 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3574 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3580 * Uniwill pin configuration:
3581 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
3582 * line = 0x1a
3584 static const struct hda_verb alc880_uniwill_init_verbs[] = {
3585 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3587 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3588 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3589 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3590 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3591 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3592 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3593 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3594 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3595 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3596 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3597 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3598 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3599 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3600 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3602 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3603 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3604 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3605 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3606 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3607 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3608 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
3609 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
3610 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3612 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3613 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
3619 * Uniwill P53
3620 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
3622 static const struct hda_verb alc880_uniwill_p53_init_verbs[] = {
3623 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3625 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3626 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3627 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3628 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3629 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3630 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3631 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3632 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3633 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3634 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3635 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3636 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3638 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3639 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3640 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3641 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3642 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3643 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3645 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3646 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
3651 static const struct hda_verb alc880_beep_init_verbs[] = {
3652 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
3656 /* auto-toggle front mic */
3657 static void alc88x_simple_mic_automute(struct hda_codec *codec)
3659 unsigned int present;
3660 unsigned char bits;
3662 present = snd_hda_jack_detect(codec, 0x18);
3663 bits = present ? HDA_AMP_MUTE : 0;
3664 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
3667 static void alc880_uniwill_setup(struct hda_codec *codec)
3669 struct alc_spec *spec = codec->spec;
3671 spec->autocfg.hp_pins[0] = 0x14;
3672 spec->autocfg.speaker_pins[0] = 0x15;
3673 spec->autocfg.speaker_pins[0] = 0x16;
3674 spec->automute = 1;
3675 spec->automute_mode = ALC_AUTOMUTE_AMP;
3678 static void alc880_uniwill_init_hook(struct hda_codec *codec)
3680 alc_hp_automute(codec);
3681 alc88x_simple_mic_automute(codec);
3684 static void alc880_uniwill_unsol_event(struct hda_codec *codec,
3685 unsigned int res)
3687 /* Looks like the unsol event is incompatible with the standard
3688 * definition. 4bit tag is placed at 28 bit!
3690 switch (res >> 28) {
3691 case ALC880_MIC_EVENT:
3692 alc88x_simple_mic_automute(codec);
3693 break;
3694 default:
3695 alc_sku_unsol_event(codec, res);
3696 break;
3700 static void alc880_uniwill_p53_setup(struct hda_codec *codec)
3702 struct alc_spec *spec = codec->spec;
3704 spec->autocfg.hp_pins[0] = 0x14;
3705 spec->autocfg.speaker_pins[0] = 0x15;
3706 spec->automute = 1;
3707 spec->automute_mode = ALC_AUTOMUTE_AMP;
3710 static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
3712 unsigned int present;
3714 present = snd_hda_codec_read(codec, 0x21, 0,
3715 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
3716 present &= HDA_AMP_VOLMASK;
3717 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
3718 HDA_AMP_VOLMASK, present);
3719 snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
3720 HDA_AMP_VOLMASK, present);
3723 static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
3724 unsigned int res)
3726 /* Looks like the unsol event is incompatible with the standard
3727 * definition. 4bit tag is placed at 28 bit!
3729 if ((res >> 28) == ALC880_DCVOL_EVENT)
3730 alc880_uniwill_p53_dcvol_automute(codec);
3731 else
3732 alc_sku_unsol_event(codec, res);
3736 * F1734 pin configuration:
3737 * HP = 0x14, speaker-out = 0x15, mic = 0x18
3739 static const struct hda_verb alc880_pin_f1734_init_verbs[] = {
3740 {0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
3741 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
3742 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
3743 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
3744 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
3746 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3747 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3748 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3749 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3751 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3752 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3753 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
3754 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3755 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3756 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3757 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3758 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3759 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3761 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
3762 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
3768 * ASUS pin configuration:
3769 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
3771 static const struct hda_verb alc880_pin_asus_init_verbs[] = {
3772 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
3773 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
3774 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
3775 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
3777 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3778 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3779 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3780 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3781 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3782 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3783 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3784 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3786 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3787 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3788 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3789 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3790 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3791 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3792 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3793 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3794 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3799 /* Enable GPIO mask and set output */
3800 #define alc880_gpio1_init_verbs alc_gpio1_init_verbs
3801 #define alc880_gpio2_init_verbs alc_gpio2_init_verbs
3802 #define alc880_gpio3_init_verbs alc_gpio3_init_verbs
3804 /* Clevo m520g init */
3805 static const struct hda_verb alc880_pin_clevo_init_verbs[] = {
3806 /* headphone output */
3807 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
3808 /* line-out */
3809 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3810 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3811 /* Line-in */
3812 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3813 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3814 /* CD */
3815 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3816 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3817 /* Mic1 (rear panel) */
3818 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3819 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3820 /* Mic2 (front panel) */
3821 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3822 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3823 /* headphone */
3824 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3825 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3826 /* change to EAPD mode */
3827 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3828 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3833 static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
3834 /* change to EAPD mode */
3835 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3836 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3838 /* Headphone output */
3839 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3840 /* Front output*/
3841 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3842 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
3844 /* Line In pin widget for input */
3845 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3846 /* CD pin widget for input */
3847 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3848 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3849 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3851 /* change to EAPD mode */
3852 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3853 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
3859 * LG m1 express dual
3861 * Pin assignment:
3862 * Rear Line-In/Out (blue): 0x14
3863 * Build-in Mic-In: 0x15
3864 * Speaker-out: 0x17
3865 * HP-Out (green): 0x1b
3866 * Mic-In/Out (red): 0x19
3867 * SPDIF-Out: 0x1e
3870 /* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
3871 static const hda_nid_t alc880_lg_dac_nids[3] = {
3872 0x05, 0x02, 0x03
3875 /* seems analog CD is not working */
3876 static const struct hda_input_mux alc880_lg_capture_source = {
3877 .num_items = 3,
3878 .items = {
3879 { "Mic", 0x1 },
3880 { "Line", 0x5 },
3881 { "Internal Mic", 0x6 },
3885 /* 2,4,6 channel modes */
3886 static const struct hda_verb alc880_lg_ch2_init[] = {
3887 /* set line-in and mic-in to input */
3888 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
3889 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
3893 static const struct hda_verb alc880_lg_ch4_init[] = {
3894 /* set line-in to out and mic-in to input */
3895 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3896 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
3900 static const struct hda_verb alc880_lg_ch6_init[] = {
3901 /* set line-in and mic-in to output */
3902 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3903 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3907 static const struct hda_channel_mode alc880_lg_ch_modes[3] = {
3908 { 2, alc880_lg_ch2_init },
3909 { 4, alc880_lg_ch4_init },
3910 { 6, alc880_lg_ch6_init },
3913 static const struct snd_kcontrol_new alc880_lg_mixer[] = {
3914 HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3915 HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
3916 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3917 HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
3918 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
3919 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
3920 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
3921 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
3922 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3923 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3924 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
3925 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
3926 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
3927 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
3929 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3930 .name = "Channel Mode",
3931 .info = alc_ch_mode_info,
3932 .get = alc_ch_mode_get,
3933 .put = alc_ch_mode_put,
3935 { } /* end */
3938 static const struct hda_verb alc880_lg_init_verbs[] = {
3939 /* set capture source to mic-in */
3940 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3941 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3942 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3943 /* mute all amp mixer inputs */
3944 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
3945 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3946 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
3947 /* line-in to input */
3948 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3949 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3950 /* built-in mic */
3951 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3952 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3953 /* speaker-out */
3954 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3955 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3956 /* mic-in to input */
3957 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
3958 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3959 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3960 /* HP-out */
3961 {0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
3962 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3963 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3964 /* jack sense */
3965 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3969 /* toggle speaker-output according to the hp-jack state */
3970 static void alc880_lg_setup(struct hda_codec *codec)
3972 struct alc_spec *spec = codec->spec;
3974 spec->autocfg.hp_pins[0] = 0x1b;
3975 spec->autocfg.speaker_pins[0] = 0x17;
3976 spec->automute = 1;
3977 spec->automute_mode = ALC_AUTOMUTE_AMP;
3981 * LG LW20
3983 * Pin assignment:
3984 * Speaker-out: 0x14
3985 * Mic-In: 0x18
3986 * Built-in Mic-In: 0x19
3987 * Line-In: 0x1b
3988 * HP-Out: 0x1a
3989 * SPDIF-Out: 0x1e
3992 static const struct hda_input_mux alc880_lg_lw_capture_source = {
3993 .num_items = 3,
3994 .items = {
3995 { "Mic", 0x0 },
3996 { "Internal Mic", 0x1 },
3997 { "Line In", 0x2 },
4001 #define alc880_lg_lw_modes alc880_threestack_modes
4003 static const struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
4004 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4005 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4006 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
4007 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
4008 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
4009 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
4010 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
4011 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
4012 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4013 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4014 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
4015 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4016 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
4017 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
4019 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4020 .name = "Channel Mode",
4021 .info = alc_ch_mode_info,
4022 .get = alc_ch_mode_get,
4023 .put = alc_ch_mode_put,
4025 { } /* end */
4028 static const struct hda_verb alc880_lg_lw_init_verbs[] = {
4029 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
4030 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
4031 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
4033 /* set capture source to mic-in */
4034 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4035 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4036 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4037 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4038 /* speaker-out */
4039 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4040 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4041 /* HP-out */
4042 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4043 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4044 /* mic-in to input */
4045 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4046 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4047 /* built-in mic */
4048 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4049 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4050 /* jack sense */
4051 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
4055 /* toggle speaker-output according to the hp-jack state */
4056 static void alc880_lg_lw_setup(struct hda_codec *codec)
4058 struct alc_spec *spec = codec->spec;
4060 spec->autocfg.hp_pins[0] = 0x1b;
4061 spec->autocfg.speaker_pins[0] = 0x14;
4062 spec->automute = 1;
4063 spec->automute_mode = ALC_AUTOMUTE_AMP;
4066 static const struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
4067 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4068 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
4069 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
4070 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4071 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
4072 HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
4073 { } /* end */
4076 static const struct hda_input_mux alc880_medion_rim_capture_source = {
4077 .num_items = 2,
4078 .items = {
4079 { "Mic", 0x0 },
4080 { "Internal Mic", 0x1 },
4084 static const struct hda_verb alc880_medion_rim_init_verbs[] = {
4085 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
4087 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4088 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4090 /* Mic1 (rear panel) pin widget for input and vref at 80% */
4091 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4092 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4093 /* Mic2 (as headphone out) for HP output */
4094 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4095 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4096 /* Internal Speaker */
4097 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4098 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4100 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
4101 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
4103 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
4107 /* toggle speaker-output according to the hp-jack state */
4108 static void alc880_medion_rim_automute(struct hda_codec *codec)
4110 struct alc_spec *spec = codec->spec;
4111 alc_hp_automute(codec);
4112 /* toggle EAPD */
4113 if (spec->jack_present)
4114 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
4115 else
4116 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
4119 static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
4120 unsigned int res)
4122 /* Looks like the unsol event is incompatible with the standard
4123 * definition. 4bit tag is placed at 28 bit!
4125 if ((res >> 28) == ALC880_HP_EVENT)
4126 alc880_medion_rim_automute(codec);
4129 static void alc880_medion_rim_setup(struct hda_codec *codec)
4131 struct alc_spec *spec = codec->spec;
4133 spec->autocfg.hp_pins[0] = 0x14;
4134 spec->autocfg.speaker_pins[0] = 0x1b;
4135 spec->automute = 1;
4136 spec->automute_mode = ALC_AUTOMUTE_AMP;
4139 #ifdef CONFIG_SND_HDA_POWER_SAVE
4140 static const struct hda_amp_list alc880_loopbacks[] = {
4141 { 0x0b, HDA_INPUT, 0 },
4142 { 0x0b, HDA_INPUT, 1 },
4143 { 0x0b, HDA_INPUT, 2 },
4144 { 0x0b, HDA_INPUT, 3 },
4145 { 0x0b, HDA_INPUT, 4 },
4146 { } /* end */
4149 static const struct hda_amp_list alc880_lg_loopbacks[] = {
4150 { 0x0b, HDA_INPUT, 1 },
4151 { 0x0b, HDA_INPUT, 6 },
4152 { 0x0b, HDA_INPUT, 7 },
4153 { } /* end */
4155 #endif
4158 * Common callbacks
4161 static void alc_init_special_input_src(struct hda_codec *codec);
4163 static int alc_init(struct hda_codec *codec)
4165 struct alc_spec *spec = codec->spec;
4166 unsigned int i;
4168 alc_fix_pll(codec);
4169 alc_auto_init_amp(codec, spec->init_amp);
4171 for (i = 0; i < spec->num_init_verbs; i++)
4172 snd_hda_sequence_write(codec, spec->init_verbs[i]);
4173 alc_init_special_input_src(codec);
4175 if (spec->init_hook)
4176 spec->init_hook(codec);
4178 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
4180 hda_call_check_power_status(codec, 0x01);
4181 return 0;
4184 static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
4186 struct alc_spec *spec = codec->spec;
4188 if (spec->unsol_event)
4189 spec->unsol_event(codec, res);
4192 #ifdef CONFIG_SND_HDA_POWER_SAVE
4193 static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
4195 struct alc_spec *spec = codec->spec;
4196 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
4198 #endif
4201 * Analog playback callbacks
4203 static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
4204 struct hda_codec *codec,
4205 struct snd_pcm_substream *substream)
4207 struct alc_spec *spec = codec->spec;
4208 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
4209 hinfo);
4212 static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4213 struct hda_codec *codec,
4214 unsigned int stream_tag,
4215 unsigned int format,
4216 struct snd_pcm_substream *substream)
4218 struct alc_spec *spec = codec->spec;
4219 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
4220 stream_tag, format, substream);
4223 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4224 struct hda_codec *codec,
4225 struct snd_pcm_substream *substream)
4227 struct alc_spec *spec = codec->spec;
4228 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
4232 * Digital out
4234 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
4235 struct hda_codec *codec,
4236 struct snd_pcm_substream *substream)
4238 struct alc_spec *spec = codec->spec;
4239 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
4242 static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4243 struct hda_codec *codec,
4244 unsigned int stream_tag,
4245 unsigned int format,
4246 struct snd_pcm_substream *substream)
4248 struct alc_spec *spec = codec->spec;
4249 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
4250 stream_tag, format, substream);
4253 static int alc880_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4254 struct hda_codec *codec,
4255 struct snd_pcm_substream *substream)
4257 struct alc_spec *spec = codec->spec;
4258 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
4261 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
4262 struct hda_codec *codec,
4263 struct snd_pcm_substream *substream)
4265 struct alc_spec *spec = codec->spec;
4266 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
4270 * Analog capture
4272 static int alc880_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4273 struct hda_codec *codec,
4274 unsigned int stream_tag,
4275 unsigned int format,
4276 struct snd_pcm_substream *substream)
4278 struct alc_spec *spec = codec->spec;
4280 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
4281 stream_tag, 0, format);
4282 return 0;
4285 static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4286 struct hda_codec *codec,
4287 struct snd_pcm_substream *substream)
4289 struct alc_spec *spec = codec->spec;
4291 snd_hda_codec_cleanup_stream(codec,
4292 spec->adc_nids[substream->number + 1]);
4293 return 0;
4296 /* analog capture with dynamic dual-adc changes */
4297 static int dualmic_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4298 struct hda_codec *codec,
4299 unsigned int stream_tag,
4300 unsigned int format,
4301 struct snd_pcm_substream *substream)
4303 struct alc_spec *spec = codec->spec;
4304 spec->cur_adc = spec->adc_nids[spec->cur_adc_idx];
4305 spec->cur_adc_stream_tag = stream_tag;
4306 spec->cur_adc_format = format;
4307 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
4308 return 0;
4311 static int dualmic_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4312 struct hda_codec *codec,
4313 struct snd_pcm_substream *substream)
4315 struct alc_spec *spec = codec->spec;
4316 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
4317 spec->cur_adc = 0;
4318 return 0;
4321 static const struct hda_pcm_stream dualmic_pcm_analog_capture = {
4322 .substreams = 1,
4323 .channels_min = 2,
4324 .channels_max = 2,
4325 .nid = 0, /* fill later */
4326 .ops = {
4327 .prepare = dualmic_capture_pcm_prepare,
4328 .cleanup = dualmic_capture_pcm_cleanup
4334 static const struct hda_pcm_stream alc880_pcm_analog_playback = {
4335 .substreams = 1,
4336 .channels_min = 2,
4337 .channels_max = 8,
4338 /* NID is set in alc_build_pcms */
4339 .ops = {
4340 .open = alc880_playback_pcm_open,
4341 .prepare = alc880_playback_pcm_prepare,
4342 .cleanup = alc880_playback_pcm_cleanup
4346 static const struct hda_pcm_stream alc880_pcm_analog_capture = {
4347 .substreams = 1,
4348 .channels_min = 2,
4349 .channels_max = 2,
4350 /* NID is set in alc_build_pcms */
4353 static const struct hda_pcm_stream alc880_pcm_analog_alt_playback = {
4354 .substreams = 1,
4355 .channels_min = 2,
4356 .channels_max = 2,
4357 /* NID is set in alc_build_pcms */
4360 static const struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
4361 .substreams = 2, /* can be overridden */
4362 .channels_min = 2,
4363 .channels_max = 2,
4364 /* NID is set in alc_build_pcms */
4365 .ops = {
4366 .prepare = alc880_alt_capture_pcm_prepare,
4367 .cleanup = alc880_alt_capture_pcm_cleanup
4371 static const struct hda_pcm_stream alc880_pcm_digital_playback = {
4372 .substreams = 1,
4373 .channels_min = 2,
4374 .channels_max = 2,
4375 /* NID is set in alc_build_pcms */
4376 .ops = {
4377 .open = alc880_dig_playback_pcm_open,
4378 .close = alc880_dig_playback_pcm_close,
4379 .prepare = alc880_dig_playback_pcm_prepare,
4380 .cleanup = alc880_dig_playback_pcm_cleanup
4384 static const struct hda_pcm_stream alc880_pcm_digital_capture = {
4385 .substreams = 1,
4386 .channels_min = 2,
4387 .channels_max = 2,
4388 /* NID is set in alc_build_pcms */
4391 /* Used by alc_build_pcms to flag that a PCM has no playback stream */
4392 static const struct hda_pcm_stream alc_pcm_null_stream = {
4393 .substreams = 0,
4394 .channels_min = 0,
4395 .channels_max = 0,
4398 static int alc_build_pcms(struct hda_codec *codec)
4400 struct alc_spec *spec = codec->spec;
4401 struct hda_pcm *info = spec->pcm_rec;
4402 int i;
4404 codec->num_pcms = 1;
4405 codec->pcm_info = info;
4407 if (spec->no_analog)
4408 goto skip_analog;
4410 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
4411 "%s Analog", codec->chip_name);
4412 info->name = spec->stream_name_analog;
4414 if (spec->stream_analog_playback) {
4415 if (snd_BUG_ON(!spec->multiout.dac_nids))
4416 return -EINVAL;
4417 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
4418 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
4420 if (spec->stream_analog_capture) {
4421 if (snd_BUG_ON(!spec->adc_nids))
4422 return -EINVAL;
4423 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
4424 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
4427 if (spec->channel_mode) {
4428 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
4429 for (i = 0; i < spec->num_channel_mode; i++) {
4430 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
4431 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
4436 skip_analog:
4437 /* SPDIF for stream index #1 */
4438 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
4439 snprintf(spec->stream_name_digital,
4440 sizeof(spec->stream_name_digital),
4441 "%s Digital", codec->chip_name);
4442 codec->num_pcms = 2;
4443 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
4444 info = spec->pcm_rec + 1;
4445 info->name = spec->stream_name_digital;
4446 if (spec->dig_out_type)
4447 info->pcm_type = spec->dig_out_type;
4448 else
4449 info->pcm_type = HDA_PCM_TYPE_SPDIF;
4450 if (spec->multiout.dig_out_nid &&
4451 spec->stream_digital_playback) {
4452 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
4453 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
4455 if (spec->dig_in_nid &&
4456 spec->stream_digital_capture) {
4457 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
4458 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
4460 /* FIXME: do we need this for all Realtek codec models? */
4461 codec->spdif_status_reset = 1;
4464 if (spec->no_analog)
4465 return 0;
4467 /* If the use of more than one ADC is requested for the current
4468 * model, configure a second analog capture-only PCM.
4470 /* Additional Analaog capture for index #2 */
4471 if ((spec->alt_dac_nid && spec->stream_analog_alt_playback) ||
4472 (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture)) {
4473 codec->num_pcms = 3;
4474 info = spec->pcm_rec + 2;
4475 info->name = spec->stream_name_analog;
4476 if (spec->alt_dac_nid) {
4477 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
4478 *spec->stream_analog_alt_playback;
4479 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
4480 spec->alt_dac_nid;
4481 } else {
4482 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
4483 alc_pcm_null_stream;
4484 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
4486 if (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture) {
4487 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
4488 *spec->stream_analog_alt_capture;
4489 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
4490 spec->adc_nids[1];
4491 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
4492 spec->num_adc_nids - 1;
4493 } else {
4494 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
4495 alc_pcm_null_stream;
4496 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
4500 return 0;
4503 static inline void alc_shutup(struct hda_codec *codec)
4505 struct alc_spec *spec = codec->spec;
4507 if (spec && spec->shutup)
4508 spec->shutup(codec);
4509 snd_hda_shutup_pins(codec);
4512 static void alc_free_kctls(struct hda_codec *codec)
4514 struct alc_spec *spec = codec->spec;
4516 if (spec->kctls.list) {
4517 struct snd_kcontrol_new *kctl = spec->kctls.list;
4518 int i;
4519 for (i = 0; i < spec->kctls.used; i++)
4520 kfree(kctl[i].name);
4522 snd_array_free(&spec->kctls);
4525 static void alc_free(struct hda_codec *codec)
4527 struct alc_spec *spec = codec->spec;
4529 if (!spec)
4530 return;
4532 alc_shutup(codec);
4533 snd_hda_input_jack_free(codec);
4534 alc_free_kctls(codec);
4535 kfree(spec);
4536 snd_hda_detach_beep_device(codec);
4539 #ifdef CONFIG_SND_HDA_POWER_SAVE
4540 static void alc_power_eapd(struct hda_codec *codec)
4542 alc_auto_setup_eapd(codec, false);
4545 static int alc_suspend(struct hda_codec *codec, pm_message_t state)
4547 struct alc_spec *spec = codec->spec;
4548 alc_shutup(codec);
4549 if (spec && spec->power_hook)
4550 spec->power_hook(codec);
4551 return 0;
4553 #endif
4555 #ifdef SND_HDA_NEEDS_RESUME
4556 static int alc_resume(struct hda_codec *codec)
4558 msleep(150); /* to avoid pop noise */
4559 codec->patch_ops.init(codec);
4560 snd_hda_codec_resume_amp(codec);
4561 snd_hda_codec_resume_cache(codec);
4562 hda_call_check_power_status(codec, 0x01);
4563 return 0;
4565 #endif
4569 static const struct hda_codec_ops alc_patch_ops = {
4570 .build_controls = alc_build_controls,
4571 .build_pcms = alc_build_pcms,
4572 .init = alc_init,
4573 .free = alc_free,
4574 .unsol_event = alc_unsol_event,
4575 #ifdef SND_HDA_NEEDS_RESUME
4576 .resume = alc_resume,
4577 #endif
4578 #ifdef CONFIG_SND_HDA_POWER_SAVE
4579 .suspend = alc_suspend,
4580 .check_power_status = alc_check_power_status,
4581 #endif
4582 .reboot_notify = alc_shutup,
4585 /* replace the codec chip_name with the given string */
4586 static int alc_codec_rename(struct hda_codec *codec, const char *name)
4588 kfree(codec->chip_name);
4589 codec->chip_name = kstrdup(name, GFP_KERNEL);
4590 if (!codec->chip_name) {
4591 alc_free(codec);
4592 return -ENOMEM;
4594 return 0;
4598 * Test configuration for debugging
4600 * Almost all inputs/outputs are enabled. I/O pins can be configured via
4601 * enum controls.
4603 #ifdef CONFIG_SND_DEBUG
4604 static const hda_nid_t alc880_test_dac_nids[4] = {
4605 0x02, 0x03, 0x04, 0x05
4608 static const struct hda_input_mux alc880_test_capture_source = {
4609 .num_items = 7,
4610 .items = {
4611 { "In-1", 0x0 },
4612 { "In-2", 0x1 },
4613 { "In-3", 0x2 },
4614 { "In-4", 0x3 },
4615 { "CD", 0x4 },
4616 { "Front", 0x5 },
4617 { "Surround", 0x6 },
4621 static const struct hda_channel_mode alc880_test_modes[4] = {
4622 { 2, NULL },
4623 { 4, NULL },
4624 { 6, NULL },
4625 { 8, NULL },
4628 static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
4629 struct snd_ctl_elem_info *uinfo)
4631 static const char * const texts[] = {
4632 "N/A", "Line Out", "HP Out",
4633 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
4635 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4636 uinfo->count = 1;
4637 uinfo->value.enumerated.items = 8;
4638 if (uinfo->value.enumerated.item >= 8)
4639 uinfo->value.enumerated.item = 7;
4640 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
4641 return 0;
4644 static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
4645 struct snd_ctl_elem_value *ucontrol)
4647 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4648 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4649 unsigned int pin_ctl, item = 0;
4651 pin_ctl = snd_hda_codec_read(codec, nid, 0,
4652 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4653 if (pin_ctl & AC_PINCTL_OUT_EN) {
4654 if (pin_ctl & AC_PINCTL_HP_EN)
4655 item = 2;
4656 else
4657 item = 1;
4658 } else if (pin_ctl & AC_PINCTL_IN_EN) {
4659 switch (pin_ctl & AC_PINCTL_VREFEN) {
4660 case AC_PINCTL_VREF_HIZ: item = 3; break;
4661 case AC_PINCTL_VREF_50: item = 4; break;
4662 case AC_PINCTL_VREF_GRD: item = 5; break;
4663 case AC_PINCTL_VREF_80: item = 6; break;
4664 case AC_PINCTL_VREF_100: item = 7; break;
4667 ucontrol->value.enumerated.item[0] = item;
4668 return 0;
4671 static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
4672 struct snd_ctl_elem_value *ucontrol)
4674 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4675 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4676 static const unsigned int ctls[] = {
4677 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
4678 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
4679 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
4680 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
4681 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
4682 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
4684 unsigned int old_ctl, new_ctl;
4686 old_ctl = snd_hda_codec_read(codec, nid, 0,
4687 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4688 new_ctl = ctls[ucontrol->value.enumerated.item[0]];
4689 if (old_ctl != new_ctl) {
4690 int val;
4691 snd_hda_codec_write_cache(codec, nid, 0,
4692 AC_VERB_SET_PIN_WIDGET_CONTROL,
4693 new_ctl);
4694 val = ucontrol->value.enumerated.item[0] >= 3 ?
4695 HDA_AMP_MUTE : 0;
4696 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
4697 HDA_AMP_MUTE, val);
4698 return 1;
4700 return 0;
4703 static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
4704 struct snd_ctl_elem_info *uinfo)
4706 static const char * const texts[] = {
4707 "Front", "Surround", "CLFE", "Side"
4709 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4710 uinfo->count = 1;
4711 uinfo->value.enumerated.items = 4;
4712 if (uinfo->value.enumerated.item >= 4)
4713 uinfo->value.enumerated.item = 3;
4714 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
4715 return 0;
4718 static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
4719 struct snd_ctl_elem_value *ucontrol)
4721 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4722 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4723 unsigned int sel;
4725 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
4726 ucontrol->value.enumerated.item[0] = sel & 3;
4727 return 0;
4730 static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
4731 struct snd_ctl_elem_value *ucontrol)
4733 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4734 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4735 unsigned int sel;
4737 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
4738 if (ucontrol->value.enumerated.item[0] != sel) {
4739 sel = ucontrol->value.enumerated.item[0] & 3;
4740 snd_hda_codec_write_cache(codec, nid, 0,
4741 AC_VERB_SET_CONNECT_SEL, sel);
4742 return 1;
4744 return 0;
4747 #define PIN_CTL_TEST(xname,nid) { \
4748 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4749 .name = xname, \
4750 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
4751 .info = alc_test_pin_ctl_info, \
4752 .get = alc_test_pin_ctl_get, \
4753 .put = alc_test_pin_ctl_put, \
4754 .private_value = nid \
4757 #define PIN_SRC_TEST(xname,nid) { \
4758 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4759 .name = xname, \
4760 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
4761 .info = alc_test_pin_src_info, \
4762 .get = alc_test_pin_src_get, \
4763 .put = alc_test_pin_src_put, \
4764 .private_value = nid \
4767 static const struct snd_kcontrol_new alc880_test_mixer[] = {
4768 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4769 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
4770 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
4771 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
4772 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4773 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
4774 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
4775 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
4776 PIN_CTL_TEST("Front Pin Mode", 0x14),
4777 PIN_CTL_TEST("Surround Pin Mode", 0x15),
4778 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
4779 PIN_CTL_TEST("Side Pin Mode", 0x17),
4780 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
4781 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
4782 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
4783 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
4784 PIN_SRC_TEST("In-1 Pin Source", 0x18),
4785 PIN_SRC_TEST("In-2 Pin Source", 0x19),
4786 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
4787 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
4788 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
4789 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
4790 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
4791 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
4792 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
4793 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
4794 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
4795 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
4796 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
4797 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
4799 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4800 .name = "Channel Mode",
4801 .info = alc_ch_mode_info,
4802 .get = alc_ch_mode_get,
4803 .put = alc_ch_mode_put,
4805 { } /* end */
4808 static const struct hda_verb alc880_test_init_verbs[] = {
4809 /* Unmute inputs of 0x0c - 0x0f */
4810 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4811 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4812 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4813 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4814 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4815 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4816 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4817 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4818 /* Vol output for 0x0c-0x0f */
4819 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4820 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4821 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4822 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4823 /* Set output pins 0x14-0x17 */
4824 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4825 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4826 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4827 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4828 /* Unmute output pins 0x14-0x17 */
4829 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4830 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4831 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4832 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4833 /* Set input pins 0x18-0x1c */
4834 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4835 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4836 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4837 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4838 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4839 /* Mute input pins 0x18-0x1b */
4840 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4841 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4842 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4843 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4844 /* ADC set up */
4845 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4846 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4847 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4848 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4849 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4850 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4851 /* Analog input/passthru */
4852 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4853 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4854 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4855 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4856 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4859 #endif
4864 static const char * const alc880_models[ALC880_MODEL_LAST] = {
4865 [ALC880_3ST] = "3stack",
4866 [ALC880_TCL_S700] = "tcl",
4867 [ALC880_3ST_DIG] = "3stack-digout",
4868 [ALC880_CLEVO] = "clevo",
4869 [ALC880_5ST] = "5stack",
4870 [ALC880_5ST_DIG] = "5stack-digout",
4871 [ALC880_W810] = "w810",
4872 [ALC880_Z71V] = "z71v",
4873 [ALC880_6ST] = "6stack",
4874 [ALC880_6ST_DIG] = "6stack-digout",
4875 [ALC880_ASUS] = "asus",
4876 [ALC880_ASUS_W1V] = "asus-w1v",
4877 [ALC880_ASUS_DIG] = "asus-dig",
4878 [ALC880_ASUS_DIG2] = "asus-dig2",
4879 [ALC880_UNIWILL_DIG] = "uniwill",
4880 [ALC880_UNIWILL_P53] = "uniwill-p53",
4881 [ALC880_FUJITSU] = "fujitsu",
4882 [ALC880_F1734] = "F1734",
4883 [ALC880_LG] = "lg",
4884 [ALC880_LG_LW] = "lg-lw",
4885 [ALC880_MEDION_RIM] = "medion",
4886 #ifdef CONFIG_SND_DEBUG
4887 [ALC880_TEST] = "test",
4888 #endif
4889 [ALC880_AUTO] = "auto",
4892 static const struct snd_pci_quirk alc880_cfg_tbl[] = {
4893 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
4894 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
4895 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
4896 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
4897 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
4898 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
4899 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
4900 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
4901 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
4902 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
4903 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
4904 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
4905 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
4906 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
4907 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
4908 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
4909 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
4910 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
4911 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
4912 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
4913 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
4914 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
4915 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
4916 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
4917 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
4918 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
4919 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
4920 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
4921 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
4922 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
4923 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
4924 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
4925 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
4926 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
4927 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
4928 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
4929 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
4930 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
4931 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
4932 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734),
4933 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
4934 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
4935 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
4936 SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
4937 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
4938 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
4939 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
4940 SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
4941 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734),
4942 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
4943 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
4944 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
4945 SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
4946 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
4947 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
4948 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
4949 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
4950 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
4951 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
4952 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
4953 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
4954 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
4955 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
4956 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
4957 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
4958 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
4959 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
4960 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
4961 /* default Intel */
4962 SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
4963 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
4964 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
4969 * ALC880 codec presets
4971 static const struct alc_config_preset alc880_presets[] = {
4972 [ALC880_3ST] = {
4973 .mixers = { alc880_three_stack_mixer },
4974 .init_verbs = { alc880_volume_init_verbs,
4975 alc880_pin_3stack_init_verbs },
4976 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4977 .dac_nids = alc880_dac_nids,
4978 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4979 .channel_mode = alc880_threestack_modes,
4980 .need_dac_fix = 1,
4981 .input_mux = &alc880_capture_source,
4983 [ALC880_3ST_DIG] = {
4984 .mixers = { alc880_three_stack_mixer },
4985 .init_verbs = { alc880_volume_init_verbs,
4986 alc880_pin_3stack_init_verbs },
4987 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4988 .dac_nids = alc880_dac_nids,
4989 .dig_out_nid = ALC880_DIGOUT_NID,
4990 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4991 .channel_mode = alc880_threestack_modes,
4992 .need_dac_fix = 1,
4993 .input_mux = &alc880_capture_source,
4995 [ALC880_TCL_S700] = {
4996 .mixers = { alc880_tcl_s700_mixer },
4997 .init_verbs = { alc880_volume_init_verbs,
4998 alc880_pin_tcl_S700_init_verbs,
4999 alc880_gpio2_init_verbs },
5000 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5001 .dac_nids = alc880_dac_nids,
5002 .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
5003 .num_adc_nids = 1, /* single ADC */
5004 .hp_nid = 0x03,
5005 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
5006 .channel_mode = alc880_2_jack_modes,
5007 .input_mux = &alc880_capture_source,
5009 [ALC880_5ST] = {
5010 .mixers = { alc880_three_stack_mixer,
5011 alc880_five_stack_mixer},
5012 .init_verbs = { alc880_volume_init_verbs,
5013 alc880_pin_5stack_init_verbs },
5014 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5015 .dac_nids = alc880_dac_nids,
5016 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
5017 .channel_mode = alc880_fivestack_modes,
5018 .input_mux = &alc880_capture_source,
5020 [ALC880_5ST_DIG] = {
5021 .mixers = { alc880_three_stack_mixer,
5022 alc880_five_stack_mixer },
5023 .init_verbs = { alc880_volume_init_verbs,
5024 alc880_pin_5stack_init_verbs },
5025 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5026 .dac_nids = alc880_dac_nids,
5027 .dig_out_nid = ALC880_DIGOUT_NID,
5028 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
5029 .channel_mode = alc880_fivestack_modes,
5030 .input_mux = &alc880_capture_source,
5032 [ALC880_6ST] = {
5033 .mixers = { alc880_six_stack_mixer },
5034 .init_verbs = { alc880_volume_init_verbs,
5035 alc880_pin_6stack_init_verbs },
5036 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
5037 .dac_nids = alc880_6st_dac_nids,
5038 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
5039 .channel_mode = alc880_sixstack_modes,
5040 .input_mux = &alc880_6stack_capture_source,
5042 [ALC880_6ST_DIG] = {
5043 .mixers = { alc880_six_stack_mixer },
5044 .init_verbs = { alc880_volume_init_verbs,
5045 alc880_pin_6stack_init_verbs },
5046 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
5047 .dac_nids = alc880_6st_dac_nids,
5048 .dig_out_nid = ALC880_DIGOUT_NID,
5049 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
5050 .channel_mode = alc880_sixstack_modes,
5051 .input_mux = &alc880_6stack_capture_source,
5053 [ALC880_W810] = {
5054 .mixers = { alc880_w810_base_mixer },
5055 .init_verbs = { alc880_volume_init_verbs,
5056 alc880_pin_w810_init_verbs,
5057 alc880_gpio2_init_verbs },
5058 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
5059 .dac_nids = alc880_w810_dac_nids,
5060 .dig_out_nid = ALC880_DIGOUT_NID,
5061 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
5062 .channel_mode = alc880_w810_modes,
5063 .input_mux = &alc880_capture_source,
5065 [ALC880_Z71V] = {
5066 .mixers = { alc880_z71v_mixer },
5067 .init_verbs = { alc880_volume_init_verbs,
5068 alc880_pin_z71v_init_verbs },
5069 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
5070 .dac_nids = alc880_z71v_dac_nids,
5071 .dig_out_nid = ALC880_DIGOUT_NID,
5072 .hp_nid = 0x03,
5073 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
5074 .channel_mode = alc880_2_jack_modes,
5075 .input_mux = &alc880_capture_source,
5077 [ALC880_F1734] = {
5078 .mixers = { alc880_f1734_mixer },
5079 .init_verbs = { alc880_volume_init_verbs,
5080 alc880_pin_f1734_init_verbs },
5081 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
5082 .dac_nids = alc880_f1734_dac_nids,
5083 .hp_nid = 0x02,
5084 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
5085 .channel_mode = alc880_2_jack_modes,
5086 .input_mux = &alc880_f1734_capture_source,
5087 .unsol_event = alc880_uniwill_p53_unsol_event,
5088 .setup = alc880_uniwill_p53_setup,
5089 .init_hook = alc_hp_automute,
5091 [ALC880_ASUS] = {
5092 .mixers = { alc880_asus_mixer },
5093 .init_verbs = { alc880_volume_init_verbs,
5094 alc880_pin_asus_init_verbs,
5095 alc880_gpio1_init_verbs },
5096 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5097 .dac_nids = alc880_asus_dac_nids,
5098 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
5099 .channel_mode = alc880_asus_modes,
5100 .need_dac_fix = 1,
5101 .input_mux = &alc880_capture_source,
5103 [ALC880_ASUS_DIG] = {
5104 .mixers = { alc880_asus_mixer },
5105 .init_verbs = { alc880_volume_init_verbs,
5106 alc880_pin_asus_init_verbs,
5107 alc880_gpio1_init_verbs },
5108 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5109 .dac_nids = alc880_asus_dac_nids,
5110 .dig_out_nid = ALC880_DIGOUT_NID,
5111 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
5112 .channel_mode = alc880_asus_modes,
5113 .need_dac_fix = 1,
5114 .input_mux = &alc880_capture_source,
5116 [ALC880_ASUS_DIG2] = {
5117 .mixers = { alc880_asus_mixer },
5118 .init_verbs = { alc880_volume_init_verbs,
5119 alc880_pin_asus_init_verbs,
5120 alc880_gpio2_init_verbs }, /* use GPIO2 */
5121 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5122 .dac_nids = alc880_asus_dac_nids,
5123 .dig_out_nid = ALC880_DIGOUT_NID,
5124 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
5125 .channel_mode = alc880_asus_modes,
5126 .need_dac_fix = 1,
5127 .input_mux = &alc880_capture_source,
5129 [ALC880_ASUS_W1V] = {
5130 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
5131 .init_verbs = { alc880_volume_init_verbs,
5132 alc880_pin_asus_init_verbs,
5133 alc880_gpio1_init_verbs },
5134 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5135 .dac_nids = alc880_asus_dac_nids,
5136 .dig_out_nid = ALC880_DIGOUT_NID,
5137 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
5138 .channel_mode = alc880_asus_modes,
5139 .need_dac_fix = 1,
5140 .input_mux = &alc880_capture_source,
5142 [ALC880_UNIWILL_DIG] = {
5143 .mixers = { alc880_asus_mixer },
5144 .init_verbs = { alc880_volume_init_verbs,
5145 alc880_pin_asus_init_verbs },
5146 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5147 .dac_nids = alc880_asus_dac_nids,
5148 .dig_out_nid = ALC880_DIGOUT_NID,
5149 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
5150 .channel_mode = alc880_asus_modes,
5151 .need_dac_fix = 1,
5152 .input_mux = &alc880_capture_source,
5154 [ALC880_UNIWILL] = {
5155 .mixers = { alc880_uniwill_mixer },
5156 .init_verbs = { alc880_volume_init_verbs,
5157 alc880_uniwill_init_verbs },
5158 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5159 .dac_nids = alc880_asus_dac_nids,
5160 .dig_out_nid = ALC880_DIGOUT_NID,
5161 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
5162 .channel_mode = alc880_threestack_modes,
5163 .need_dac_fix = 1,
5164 .input_mux = &alc880_capture_source,
5165 .unsol_event = alc880_uniwill_unsol_event,
5166 .setup = alc880_uniwill_setup,
5167 .init_hook = alc880_uniwill_init_hook,
5169 [ALC880_UNIWILL_P53] = {
5170 .mixers = { alc880_uniwill_p53_mixer },
5171 .init_verbs = { alc880_volume_init_verbs,
5172 alc880_uniwill_p53_init_verbs },
5173 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5174 .dac_nids = alc880_asus_dac_nids,
5175 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
5176 .channel_mode = alc880_threestack_modes,
5177 .input_mux = &alc880_capture_source,
5178 .unsol_event = alc880_uniwill_p53_unsol_event,
5179 .setup = alc880_uniwill_p53_setup,
5180 .init_hook = alc_hp_automute,
5182 [ALC880_FUJITSU] = {
5183 .mixers = { alc880_fujitsu_mixer },
5184 .init_verbs = { alc880_volume_init_verbs,
5185 alc880_uniwill_p53_init_verbs,
5186 alc880_beep_init_verbs },
5187 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5188 .dac_nids = alc880_dac_nids,
5189 .dig_out_nid = ALC880_DIGOUT_NID,
5190 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
5191 .channel_mode = alc880_2_jack_modes,
5192 .input_mux = &alc880_capture_source,
5193 .unsol_event = alc880_uniwill_p53_unsol_event,
5194 .setup = alc880_uniwill_p53_setup,
5195 .init_hook = alc_hp_automute,
5197 [ALC880_CLEVO] = {
5198 .mixers = { alc880_three_stack_mixer },
5199 .init_verbs = { alc880_volume_init_verbs,
5200 alc880_pin_clevo_init_verbs },
5201 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5202 .dac_nids = alc880_dac_nids,
5203 .hp_nid = 0x03,
5204 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
5205 .channel_mode = alc880_threestack_modes,
5206 .need_dac_fix = 1,
5207 .input_mux = &alc880_capture_source,
5209 [ALC880_LG] = {
5210 .mixers = { alc880_lg_mixer },
5211 .init_verbs = { alc880_volume_init_verbs,
5212 alc880_lg_init_verbs },
5213 .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
5214 .dac_nids = alc880_lg_dac_nids,
5215 .dig_out_nid = ALC880_DIGOUT_NID,
5216 .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
5217 .channel_mode = alc880_lg_ch_modes,
5218 .need_dac_fix = 1,
5219 .input_mux = &alc880_lg_capture_source,
5220 .unsol_event = alc_sku_unsol_event,
5221 .setup = alc880_lg_setup,
5222 .init_hook = alc_hp_automute,
5223 #ifdef CONFIG_SND_HDA_POWER_SAVE
5224 .loopbacks = alc880_lg_loopbacks,
5225 #endif
5227 [ALC880_LG_LW] = {
5228 .mixers = { alc880_lg_lw_mixer },
5229 .init_verbs = { alc880_volume_init_verbs,
5230 alc880_lg_lw_init_verbs },
5231 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5232 .dac_nids = alc880_dac_nids,
5233 .dig_out_nid = ALC880_DIGOUT_NID,
5234 .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
5235 .channel_mode = alc880_lg_lw_modes,
5236 .input_mux = &alc880_lg_lw_capture_source,
5237 .unsol_event = alc_sku_unsol_event,
5238 .setup = alc880_lg_lw_setup,
5239 .init_hook = alc_hp_automute,
5241 [ALC880_MEDION_RIM] = {
5242 .mixers = { alc880_medion_rim_mixer },
5243 .init_verbs = { alc880_volume_init_verbs,
5244 alc880_medion_rim_init_verbs,
5245 alc_gpio2_init_verbs },
5246 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5247 .dac_nids = alc880_dac_nids,
5248 .dig_out_nid = ALC880_DIGOUT_NID,
5249 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
5250 .channel_mode = alc880_2_jack_modes,
5251 .input_mux = &alc880_medion_rim_capture_source,
5252 .unsol_event = alc880_medion_rim_unsol_event,
5253 .setup = alc880_medion_rim_setup,
5254 .init_hook = alc880_medion_rim_automute,
5256 #ifdef CONFIG_SND_DEBUG
5257 [ALC880_TEST] = {
5258 .mixers = { alc880_test_mixer },
5259 .init_verbs = { alc880_test_init_verbs },
5260 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
5261 .dac_nids = alc880_test_dac_nids,
5262 .dig_out_nid = ALC880_DIGOUT_NID,
5263 .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
5264 .channel_mode = alc880_test_modes,
5265 .input_mux = &alc880_test_capture_source,
5267 #endif
5271 * Automatic parse of I/O pins from the BIOS configuration
5274 enum {
5275 ALC_CTL_WIDGET_VOL,
5276 ALC_CTL_WIDGET_MUTE,
5277 ALC_CTL_BIND_MUTE,
5279 static const struct snd_kcontrol_new alc880_control_templates[] = {
5280 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
5281 HDA_CODEC_MUTE(NULL, 0, 0, 0),
5282 HDA_BIND_MUTE(NULL, 0, 0, 0),
5285 static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
5287 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
5288 return snd_array_new(&spec->kctls);
5291 /* add dynamic controls */
5292 static int add_control(struct alc_spec *spec, int type, const char *name,
5293 int cidx, unsigned long val)
5295 struct snd_kcontrol_new *knew;
5297 knew = alc_kcontrol_new(spec);
5298 if (!knew)
5299 return -ENOMEM;
5300 *knew = alc880_control_templates[type];
5301 knew->name = kstrdup(name, GFP_KERNEL);
5302 if (!knew->name)
5303 return -ENOMEM;
5304 knew->index = cidx;
5305 if (get_amp_nid_(val))
5306 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
5307 knew->private_value = val;
5308 return 0;
5311 static int add_control_with_pfx(struct alc_spec *spec, int type,
5312 const char *pfx, const char *dir,
5313 const char *sfx, int cidx, unsigned long val)
5315 char name[32];
5316 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
5317 return add_control(spec, type, name, cidx, val);
5320 #define add_pb_vol_ctrl(spec, type, pfx, val) \
5321 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
5322 #define add_pb_sw_ctrl(spec, type, pfx, val) \
5323 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
5324 #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
5325 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
5326 #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
5327 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
5329 #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
5330 #define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
5331 #define alc880_is_multi_pin(nid) ((nid) >= 0x18)
5332 #define alc880_multi_pin_idx(nid) ((nid) - 0x18)
5333 #define alc880_idx_to_dac(nid) ((nid) + 0x02)
5334 #define alc880_dac_to_idx(nid) ((nid) - 0x02)
5335 #define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
5336 #define alc880_idx_to_selector(nid) ((nid) + 0x10)
5337 #define ALC880_PIN_CD_NID 0x1c
5339 /* fill in the dac_nids table from the parsed pin configuration */
5340 static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
5341 const struct auto_pin_cfg *cfg)
5343 hda_nid_t nid;
5344 int assigned[4];
5345 int i, j;
5347 memset(assigned, 0, sizeof(assigned));
5348 spec->multiout.dac_nids = spec->private_dac_nids;
5350 /* check the pins hardwired to audio widget */
5351 for (i = 0; i < cfg->line_outs; i++) {
5352 nid = cfg->line_out_pins[i];
5353 if (alc880_is_fixed_pin(nid)) {
5354 int idx = alc880_fixed_pin_idx(nid);
5355 spec->private_dac_nids[i] = alc880_idx_to_dac(idx);
5356 assigned[idx] = 1;
5359 /* left pins can be connect to any audio widget */
5360 for (i = 0; i < cfg->line_outs; i++) {
5361 nid = cfg->line_out_pins[i];
5362 if (alc880_is_fixed_pin(nid))
5363 continue;
5364 /* search for an empty channel */
5365 for (j = 0; j < cfg->line_outs; j++) {
5366 if (!assigned[j]) {
5367 spec->private_dac_nids[i] =
5368 alc880_idx_to_dac(j);
5369 assigned[j] = 1;
5370 break;
5374 spec->multiout.num_dacs = cfg->line_outs;
5375 return 0;
5378 static const char *alc_get_line_out_pfx(struct alc_spec *spec,
5379 bool can_be_master)
5381 struct auto_pin_cfg *cfg = &spec->autocfg;
5383 if (cfg->line_outs == 1 && !spec->multi_ios &&
5384 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
5385 return "Master";
5387 switch (cfg->line_out_type) {
5388 case AUTO_PIN_SPEAKER_OUT:
5389 if (cfg->line_outs == 1)
5390 return "Speaker";
5391 break;
5392 case AUTO_PIN_HP_OUT:
5393 return "Headphone";
5394 default:
5395 if (cfg->line_outs == 1 && !spec->multi_ios)
5396 return "PCM";
5397 break;
5399 return NULL;
5402 /* add playback controls from the parsed DAC table */
5403 static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
5404 const struct auto_pin_cfg *cfg)
5406 static const char * const chname[4] = {
5407 "Front", "Surround", NULL /*CLFE*/, "Side"
5409 const char *pfx = alc_get_line_out_pfx(spec, false);
5410 hda_nid_t nid;
5411 int i, err, noutputs;
5413 noutputs = cfg->line_outs;
5414 if (spec->multi_ios > 0)
5415 noutputs += spec->multi_ios;
5417 for (i = 0; i < noutputs; i++) {
5418 if (!spec->multiout.dac_nids[i])
5419 continue;
5420 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
5421 if (!pfx && i == 2) {
5422 /* Center/LFE */
5423 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
5424 "Center",
5425 HDA_COMPOSE_AMP_VAL(nid, 1, 0,
5426 HDA_OUTPUT));
5427 if (err < 0)
5428 return err;
5429 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
5430 "LFE",
5431 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
5432 HDA_OUTPUT));
5433 if (err < 0)
5434 return err;
5435 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
5436 "Center",
5437 HDA_COMPOSE_AMP_VAL(nid, 1, 2,
5438 HDA_INPUT));
5439 if (err < 0)
5440 return err;
5441 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
5442 "LFE",
5443 HDA_COMPOSE_AMP_VAL(nid, 2, 2,
5444 HDA_INPUT));
5445 if (err < 0)
5446 return err;
5447 } else {
5448 const char *name = pfx;
5449 int index = i;
5450 if (!name) {
5451 name = chname[i];
5452 index = 0;
5454 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
5455 name, index,
5456 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
5457 HDA_OUTPUT));
5458 if (err < 0)
5459 return err;
5460 err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
5461 name, index,
5462 HDA_COMPOSE_AMP_VAL(nid, 3, 2,
5463 HDA_INPUT));
5464 if (err < 0)
5465 return err;
5468 return 0;
5471 /* add playback controls for speaker and HP outputs */
5472 static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
5473 const char *pfx)
5475 hda_nid_t nid;
5476 int err;
5478 if (!pin)
5479 return 0;
5481 if (alc880_is_fixed_pin(pin)) {
5482 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
5483 /* specify the DAC as the extra output */
5484 if (!spec->multiout.hp_nid)
5485 spec->multiout.hp_nid = nid;
5486 else
5487 spec->multiout.extra_out_nid[0] = nid;
5488 /* control HP volume/switch on the output mixer amp */
5489 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
5490 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
5491 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
5492 if (err < 0)
5493 return err;
5494 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
5495 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
5496 if (err < 0)
5497 return err;
5498 } else if (alc880_is_multi_pin(pin)) {
5499 /* set manual connection */
5500 /* we have only a switch on HP-out PIN */
5501 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
5502 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
5503 if (err < 0)
5504 return err;
5506 return 0;
5509 /* create input playback/capture controls for the given pin */
5510 static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
5511 const char *ctlname, int ctlidx,
5512 int idx, hda_nid_t mix_nid)
5514 int err;
5516 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
5517 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
5518 if (err < 0)
5519 return err;
5520 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
5521 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
5522 if (err < 0)
5523 return err;
5524 return 0;
5527 static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
5529 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
5530 return (pincap & AC_PINCAP_IN) != 0;
5533 /* create playback/capture controls for input pins */
5534 static int alc_auto_create_input_ctls(struct hda_codec *codec,
5535 const struct auto_pin_cfg *cfg,
5536 hda_nid_t mixer,
5537 hda_nid_t cap1, hda_nid_t cap2)
5539 struct alc_spec *spec = codec->spec;
5540 struct hda_input_mux *imux = &spec->private_imux[0];
5541 int i, err, idx, type_idx = 0;
5542 const char *prev_label = NULL;
5544 for (i = 0; i < cfg->num_inputs; i++) {
5545 hda_nid_t pin;
5546 const char *label;
5548 pin = cfg->inputs[i].pin;
5549 if (!alc_is_input_pin(codec, pin))
5550 continue;
5552 label = hda_get_autocfg_input_label(codec, cfg, i);
5553 if (prev_label && !strcmp(label, prev_label))
5554 type_idx++;
5555 else
5556 type_idx = 0;
5557 prev_label = label;
5559 if (mixer) {
5560 idx = get_connection_index(codec, mixer, pin);
5561 if (idx >= 0) {
5562 err = new_analog_input(spec, pin,
5563 label, type_idx,
5564 idx, mixer);
5565 if (err < 0)
5566 return err;
5570 if (!cap1)
5571 continue;
5572 idx = get_connection_index(codec, cap1, pin);
5573 if (idx < 0 && cap2)
5574 idx = get_connection_index(codec, cap2, pin);
5575 if (idx >= 0)
5576 snd_hda_add_imux_item(imux, label, idx, NULL);
5578 return 0;
5581 static int alc880_auto_create_input_ctls(struct hda_codec *codec,
5582 const struct auto_pin_cfg *cfg)
5584 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x08, 0x09);
5587 static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
5588 unsigned int pin_type)
5590 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5591 pin_type);
5592 /* unmute pin */
5593 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
5594 AMP_OUT_UNMUTE);
5597 static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
5598 hda_nid_t nid, int pin_type,
5599 int dac_idx)
5601 alc_set_pin_output(codec, nid, pin_type);
5602 /* need the manual connection? */
5603 if (alc880_is_multi_pin(nid)) {
5604 struct alc_spec *spec = codec->spec;
5605 int idx = alc880_multi_pin_idx(nid);
5606 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
5607 AC_VERB_SET_CONNECT_SEL,
5608 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
5612 static int get_pin_type(int line_out_type)
5614 if (line_out_type == AUTO_PIN_HP_OUT)
5615 return PIN_HP;
5616 else
5617 return PIN_OUT;
5620 static void alc880_auto_init_multi_out(struct hda_codec *codec)
5622 struct alc_spec *spec = codec->spec;
5623 int i;
5625 for (i = 0; i < spec->autocfg.line_outs; i++) {
5626 hda_nid_t nid = spec->autocfg.line_out_pins[i];
5627 int pin_type = get_pin_type(spec->autocfg.line_out_type);
5628 alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);
5632 static void alc880_auto_init_extra_out(struct hda_codec *codec)
5634 struct alc_spec *spec = codec->spec;
5635 hda_nid_t pin;
5637 pin = spec->autocfg.speaker_pins[0];
5638 if (pin) /* connect to front */
5639 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
5640 pin = spec->autocfg.hp_pins[0];
5641 if (pin) /* connect to front */
5642 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
5645 static void alc880_auto_init_analog_input(struct hda_codec *codec)
5647 struct alc_spec *spec = codec->spec;
5648 struct auto_pin_cfg *cfg = &spec->autocfg;
5649 int i;
5651 for (i = 0; i < cfg->num_inputs; i++) {
5652 hda_nid_t nid = cfg->inputs[i].pin;
5653 if (alc_is_input_pin(codec, nid)) {
5654 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
5655 if (nid != ALC880_PIN_CD_NID &&
5656 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
5657 snd_hda_codec_write(codec, nid, 0,
5658 AC_VERB_SET_AMP_GAIN_MUTE,
5659 AMP_OUT_MUTE);
5664 static void alc880_auto_init_input_src(struct hda_codec *codec)
5666 struct alc_spec *spec = codec->spec;
5667 int c;
5669 for (c = 0; c < spec->num_adc_nids; c++) {
5670 unsigned int mux_idx;
5671 const struct hda_input_mux *imux;
5672 mux_idx = c >= spec->num_mux_defs ? 0 : c;
5673 imux = &spec->input_mux[mux_idx];
5674 if (!imux->num_items && mux_idx > 0)
5675 imux = &spec->input_mux[0];
5676 if (imux)
5677 snd_hda_codec_write(codec, spec->adc_nids[c], 0,
5678 AC_VERB_SET_CONNECT_SEL,
5679 imux->items[0].index);
5683 static int alc_auto_add_multi_channel_mode(struct hda_codec *codec);
5685 /* parse the BIOS configuration and set up the alc_spec */
5686 /* return 1 if successful, 0 if the proper config is not found,
5687 * or a negative error code
5689 static int alc880_parse_auto_config(struct hda_codec *codec)
5691 struct alc_spec *spec = codec->spec;
5692 int err;
5693 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
5695 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
5696 alc880_ignore);
5697 if (err < 0)
5698 return err;
5699 if (!spec->autocfg.line_outs)
5700 return 0; /* can't find valid BIOS pin config */
5702 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
5703 if (err < 0)
5704 return err;
5705 err = alc_auto_add_multi_channel_mode(codec);
5706 if (err < 0)
5707 return err;
5708 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
5709 if (err < 0)
5710 return err;
5711 err = alc880_auto_create_extra_out(spec,
5712 spec->autocfg.speaker_pins[0],
5713 "Speaker");
5714 if (err < 0)
5715 return err;
5716 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
5717 "Headphone");
5718 if (err < 0)
5719 return err;
5720 err = alc880_auto_create_input_ctls(codec, &spec->autocfg);
5721 if (err < 0)
5722 return err;
5724 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
5726 alc_auto_parse_digital(codec);
5728 if (spec->kctls.list)
5729 add_mixer(spec, spec->kctls.list);
5731 add_verb(spec, alc880_volume_init_verbs);
5733 spec->num_mux_defs = 1;
5734 spec->input_mux = &spec->private_imux[0];
5736 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
5738 return 1;
5741 /* additional initialization for auto-configuration model */
5742 static void alc880_auto_init(struct hda_codec *codec)
5744 struct alc_spec *spec = codec->spec;
5745 alc880_auto_init_multi_out(codec);
5746 alc880_auto_init_extra_out(codec);
5747 alc880_auto_init_analog_input(codec);
5748 alc880_auto_init_input_src(codec);
5749 alc_auto_init_digital(codec);
5750 if (spec->unsol_event)
5751 alc_inithook(codec);
5754 /* check the ADC/MUX contains all input pins; some ADC/MUX contains only
5755 * one of two digital mic pins, e.g. on ALC272
5757 static void fixup_automic_adc(struct hda_codec *codec)
5759 struct alc_spec *spec = codec->spec;
5760 int i;
5762 for (i = 0; i < spec->num_adc_nids; i++) {
5763 hda_nid_t cap = spec->capsrc_nids ?
5764 spec->capsrc_nids[i] : spec->adc_nids[i];
5765 int iidx, eidx;
5767 iidx = get_connection_index(codec, cap, spec->int_mic.pin);
5768 if (iidx < 0)
5769 continue;
5770 eidx = get_connection_index(codec, cap, spec->ext_mic.pin);
5771 if (eidx < 0)
5772 continue;
5773 spec->int_mic.mux_idx = iidx;
5774 spec->ext_mic.mux_idx = eidx;
5775 if (spec->capsrc_nids)
5776 spec->capsrc_nids += i;
5777 spec->adc_nids += i;
5778 spec->num_adc_nids = 1;
5779 /* optional dock-mic */
5780 eidx = get_connection_index(codec, cap, spec->dock_mic.pin);
5781 if (eidx < 0)
5782 spec->dock_mic.pin = 0;
5783 else
5784 spec->dock_mic.mux_idx = eidx;
5785 return;
5787 snd_printd(KERN_INFO "hda_codec: %s: "
5788 "No ADC/MUX containing both 0x%x and 0x%x pins\n",
5789 codec->chip_name, spec->int_mic.pin, spec->ext_mic.pin);
5790 spec->auto_mic = 0; /* disable auto-mic to be sure */
5793 /* select or unmute the given capsrc route */
5794 static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
5795 int idx)
5797 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
5798 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
5799 HDA_AMP_MUTE, 0);
5800 } else {
5801 snd_hda_codec_write_cache(codec, cap, 0,
5802 AC_VERB_SET_CONNECT_SEL, idx);
5806 /* set the default connection to that pin */
5807 static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
5809 struct alc_spec *spec = codec->spec;
5810 int i;
5812 if (!pin)
5813 return 0;
5814 for (i = 0; i < spec->num_adc_nids; i++) {
5815 hda_nid_t cap = spec->capsrc_nids ?
5816 spec->capsrc_nids[i] : spec->adc_nids[i];
5817 int idx;
5819 idx = get_connection_index(codec, cap, pin);
5820 if (idx < 0)
5821 continue;
5822 select_or_unmute_capsrc(codec, cap, idx);
5823 return i; /* return the found index */
5825 return -1; /* not found */
5828 /* choose the ADC/MUX containing the input pin and initialize the setup */
5829 static void fixup_single_adc(struct hda_codec *codec)
5831 struct alc_spec *spec = codec->spec;
5832 struct auto_pin_cfg *cfg = &spec->autocfg;
5833 int i;
5835 /* search for the input pin; there must be only one */
5836 if (cfg->num_inputs != 1)
5837 return;
5838 i = init_capsrc_for_pin(codec, cfg->inputs[0].pin);
5839 if (i >= 0) {
5840 /* use only this ADC */
5841 if (spec->capsrc_nids)
5842 spec->capsrc_nids += i;
5843 spec->adc_nids += i;
5844 spec->num_adc_nids = 1;
5845 spec->single_input_src = 1;
5849 /* initialize dual adcs */
5850 static void fixup_dual_adc_switch(struct hda_codec *codec)
5852 struct alc_spec *spec = codec->spec;
5853 init_capsrc_for_pin(codec, spec->ext_mic.pin);
5854 init_capsrc_for_pin(codec, spec->dock_mic.pin);
5855 init_capsrc_for_pin(codec, spec->int_mic.pin);
5858 /* initialize some special cases for input sources */
5859 static void alc_init_special_input_src(struct hda_codec *codec)
5861 struct alc_spec *spec = codec->spec;
5862 if (spec->dual_adc_switch)
5863 fixup_dual_adc_switch(codec);
5864 else if (spec->single_input_src)
5865 init_capsrc_for_pin(codec, spec->autocfg.inputs[0].pin);
5868 static void set_capture_mixer(struct hda_codec *codec)
5870 struct alc_spec *spec = codec->spec;
5871 static const struct snd_kcontrol_new *caps[2][3] = {
5872 { alc_capture_mixer_nosrc1,
5873 alc_capture_mixer_nosrc2,
5874 alc_capture_mixer_nosrc3 },
5875 { alc_capture_mixer1,
5876 alc_capture_mixer2,
5877 alc_capture_mixer3 },
5879 if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
5880 int mux = 0;
5881 int num_adcs = spec->num_adc_nids;
5882 if (spec->dual_adc_switch)
5883 num_adcs = 1;
5884 else if (spec->auto_mic)
5885 fixup_automic_adc(codec);
5886 else if (spec->input_mux) {
5887 if (spec->input_mux->num_items > 1)
5888 mux = 1;
5889 else if (spec->input_mux->num_items == 1)
5890 fixup_single_adc(codec);
5892 spec->cap_mixer = caps[mux][num_adcs - 1];
5896 /* fill adc_nids (and capsrc_nids) containing all active input pins */
5897 static void fillup_priv_adc_nids(struct hda_codec *codec, const hda_nid_t *nids,
5898 int num_nids)
5900 struct alc_spec *spec = codec->spec;
5901 struct auto_pin_cfg *cfg = &spec->autocfg;
5902 int n;
5903 hda_nid_t fallback_adc = 0, fallback_cap = 0;
5905 for (n = 0; n < num_nids; n++) {
5906 hda_nid_t adc, cap;
5907 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
5908 int nconns, i, j;
5910 adc = nids[n];
5911 if (get_wcaps_type(get_wcaps(codec, adc)) != AC_WID_AUD_IN)
5912 continue;
5913 cap = adc;
5914 nconns = snd_hda_get_connections(codec, cap, conn,
5915 ARRAY_SIZE(conn));
5916 if (nconns == 1) {
5917 cap = conn[0];
5918 nconns = snd_hda_get_connections(codec, cap, conn,
5919 ARRAY_SIZE(conn));
5921 if (nconns <= 0)
5922 continue;
5923 if (!fallback_adc) {
5924 fallback_adc = adc;
5925 fallback_cap = cap;
5927 for (i = 0; i < cfg->num_inputs; i++) {
5928 hda_nid_t nid = cfg->inputs[i].pin;
5929 for (j = 0; j < nconns; j++) {
5930 if (conn[j] == nid)
5931 break;
5933 if (j >= nconns)
5934 break;
5936 if (i >= cfg->num_inputs) {
5937 int num_adcs = spec->num_adc_nids;
5938 spec->private_adc_nids[num_adcs] = adc;
5939 spec->private_capsrc_nids[num_adcs] = cap;
5940 spec->num_adc_nids++;
5941 spec->adc_nids = spec->private_adc_nids;
5942 if (adc != cap)
5943 spec->capsrc_nids = spec->private_capsrc_nids;
5946 if (!spec->num_adc_nids) {
5947 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
5948 " using fallback 0x%x\n",
5949 codec->chip_name, fallback_adc);
5950 spec->private_adc_nids[0] = fallback_adc;
5951 spec->adc_nids = spec->private_adc_nids;
5952 if (fallback_adc != fallback_cap) {
5953 spec->private_capsrc_nids[0] = fallback_cap;
5954 spec->capsrc_nids = spec->private_adc_nids;
5959 #ifdef CONFIG_SND_HDA_INPUT_BEEP
5960 #define set_beep_amp(spec, nid, idx, dir) \
5961 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
5963 static const struct snd_pci_quirk beep_white_list[] = {
5964 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
5965 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
5966 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
5967 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
5968 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
5972 static inline int has_cdefine_beep(struct hda_codec *codec)
5974 struct alc_spec *spec = codec->spec;
5975 const struct snd_pci_quirk *q;
5976 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
5977 if (q)
5978 return q->value;
5979 return spec->cdefine.enable_pcbeep;
5981 #else
5982 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
5983 #define has_cdefine_beep(codec) 0
5984 #endif
5987 * OK, here we have finally the patch for ALC880
5990 static int patch_alc880(struct hda_codec *codec)
5992 struct alc_spec *spec;
5993 int board_config;
5994 int err;
5996 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5997 if (spec == NULL)
5998 return -ENOMEM;
6000 codec->spec = spec;
6002 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
6003 alc880_models,
6004 alc880_cfg_tbl);
6005 if (board_config < 0) {
6006 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
6007 codec->chip_name);
6008 board_config = ALC880_AUTO;
6011 if (board_config == ALC880_AUTO) {
6012 /* automatic parse from the BIOS config */
6013 err = alc880_parse_auto_config(codec);
6014 if (err < 0) {
6015 alc_free(codec);
6016 return err;
6017 } else if (!err) {
6018 printk(KERN_INFO
6019 "hda_codec: Cannot set up configuration "
6020 "from BIOS. Using 3-stack mode...\n");
6021 board_config = ALC880_3ST;
6025 err = snd_hda_attach_beep_device(codec, 0x1);
6026 if (err < 0) {
6027 alc_free(codec);
6028 return err;
6031 if (board_config != ALC880_AUTO)
6032 setup_preset(codec, &alc880_presets[board_config]);
6034 spec->stream_analog_playback = &alc880_pcm_analog_playback;
6035 spec->stream_analog_capture = &alc880_pcm_analog_capture;
6036 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
6038 spec->stream_digital_playback = &alc880_pcm_digital_playback;
6039 spec->stream_digital_capture = &alc880_pcm_digital_capture;
6041 if (!spec->adc_nids && spec->input_mux) {
6042 /* check whether NID 0x07 is valid */
6043 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
6044 /* get type */
6045 wcap = get_wcaps_type(wcap);
6046 if (wcap != AC_WID_AUD_IN) {
6047 spec->adc_nids = alc880_adc_nids_alt;
6048 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
6049 } else {
6050 spec->adc_nids = alc880_adc_nids;
6051 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
6054 set_capture_mixer(codec);
6055 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
6057 spec->vmaster_nid = 0x0c;
6059 codec->patch_ops = alc_patch_ops;
6060 if (board_config == ALC880_AUTO)
6061 spec->init_hook = alc880_auto_init;
6062 #ifdef CONFIG_SND_HDA_POWER_SAVE
6063 if (!spec->loopback.amplist)
6064 spec->loopback.amplist = alc880_loopbacks;
6065 #endif
6067 return 0;
6072 * ALC260 support
6075 static const hda_nid_t alc260_dac_nids[1] = {
6076 /* front */
6077 0x02,
6080 static const hda_nid_t alc260_adc_nids[1] = {
6081 /* ADC0 */
6082 0x04,
6085 static const hda_nid_t alc260_adc_nids_alt[1] = {
6086 /* ADC1 */
6087 0x05,
6090 /* NIDs used when simultaneous access to both ADCs makes sense. Note that
6091 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
6093 static const hda_nid_t alc260_dual_adc_nids[2] = {
6094 /* ADC0, ADC1 */
6095 0x04, 0x05
6098 #define ALC260_DIGOUT_NID 0x03
6099 #define ALC260_DIGIN_NID 0x06
6101 static const struct hda_input_mux alc260_capture_source = {
6102 .num_items = 4,
6103 .items = {
6104 { "Mic", 0x0 },
6105 { "Front Mic", 0x1 },
6106 { "Line", 0x2 },
6107 { "CD", 0x4 },
6111 /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
6112 * headphone jack and the internal CD lines since these are the only pins at
6113 * which audio can appear. For flexibility, also allow the option of
6114 * recording the mixer output on the second ADC (ADC0 doesn't have a
6115 * connection to the mixer output).
6117 static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
6119 .num_items = 3,
6120 .items = {
6121 { "Mic/Line", 0x0 },
6122 { "CD", 0x4 },
6123 { "Headphone", 0x2 },
6127 .num_items = 4,
6128 .items = {
6129 { "Mic/Line", 0x0 },
6130 { "CD", 0x4 },
6131 { "Headphone", 0x2 },
6132 { "Mixer", 0x5 },
6138 /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
6139 * the Fujitsu S702x, but jacks are marked differently.
6141 static const struct hda_input_mux alc260_acer_capture_sources[2] = {
6143 .num_items = 4,
6144 .items = {
6145 { "Mic", 0x0 },
6146 { "Line", 0x2 },
6147 { "CD", 0x4 },
6148 { "Headphone", 0x5 },
6152 .num_items = 5,
6153 .items = {
6154 { "Mic", 0x0 },
6155 { "Line", 0x2 },
6156 { "CD", 0x4 },
6157 { "Headphone", 0x6 },
6158 { "Mixer", 0x5 },
6163 /* Maxdata Favorit 100XS */
6164 static const struct hda_input_mux alc260_favorit100_capture_sources[2] = {
6166 .num_items = 2,
6167 .items = {
6168 { "Line/Mic", 0x0 },
6169 { "CD", 0x4 },
6173 .num_items = 3,
6174 .items = {
6175 { "Line/Mic", 0x0 },
6176 { "CD", 0x4 },
6177 { "Mixer", 0x5 },
6183 * This is just place-holder, so there's something for alc_build_pcms to look
6184 * at when it calculates the maximum number of channels. ALC260 has no mixer
6185 * element which allows changing the channel mode, so the verb list is
6186 * never used.
6188 static const struct hda_channel_mode alc260_modes[1] = {
6189 { 2, NULL },
6193 /* Mixer combinations
6195 * basic: base_output + input + pc_beep + capture
6196 * HP: base_output + input + capture_alt
6197 * HP_3013: hp_3013 + input + capture
6198 * fujitsu: fujitsu + capture
6199 * acer: acer + capture
6202 static const struct snd_kcontrol_new alc260_base_output_mixer[] = {
6203 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6204 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
6205 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6206 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
6207 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
6208 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
6209 { } /* end */
6212 static const struct snd_kcontrol_new alc260_input_mixer[] = {
6213 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6214 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
6215 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
6216 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
6217 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
6218 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
6219 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
6220 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
6221 { } /* end */
6224 /* update HP, line and mono out pins according to the master switch */
6225 static void alc260_hp_master_update(struct hda_codec *codec)
6227 update_speakers(codec);
6230 static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
6231 struct snd_ctl_elem_value *ucontrol)
6233 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
6234 struct alc_spec *spec = codec->spec;
6235 *ucontrol->value.integer.value = !spec->master_mute;
6236 return 0;
6239 static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
6240 struct snd_ctl_elem_value *ucontrol)
6242 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
6243 struct alc_spec *spec = codec->spec;
6244 int val = !*ucontrol->value.integer.value;
6246 if (val == spec->master_mute)
6247 return 0;
6248 spec->master_mute = val;
6249 alc260_hp_master_update(codec);
6250 return 1;
6253 static const struct snd_kcontrol_new alc260_hp_output_mixer[] = {
6255 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6256 .name = "Master Playback Switch",
6257 .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
6258 .info = snd_ctl_boolean_mono_info,
6259 .get = alc260_hp_master_sw_get,
6260 .put = alc260_hp_master_sw_put,
6262 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6263 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
6264 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6265 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
6266 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
6267 HDA_OUTPUT),
6268 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT),
6269 { } /* end */
6272 static const struct hda_verb alc260_hp_unsol_verbs[] = {
6273 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6277 static void alc260_hp_setup(struct hda_codec *codec)
6279 struct alc_spec *spec = codec->spec;
6281 spec->autocfg.hp_pins[0] = 0x0f;
6282 spec->autocfg.speaker_pins[0] = 0x10;
6283 spec->autocfg.speaker_pins[1] = 0x11;
6284 spec->automute = 1;
6285 spec->automute_mode = ALC_AUTOMUTE_PIN;
6288 static const struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
6290 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6291 .name = "Master Playback Switch",
6292 .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
6293 .info = snd_ctl_boolean_mono_info,
6294 .get = alc260_hp_master_sw_get,
6295 .put = alc260_hp_master_sw_put,
6297 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6298 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
6299 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
6300 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
6301 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6302 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6303 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
6304 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
6305 { } /* end */
6308 static void alc260_hp_3013_setup(struct hda_codec *codec)
6310 struct alc_spec *spec = codec->spec;
6312 spec->autocfg.hp_pins[0] = 0x15;
6313 spec->autocfg.speaker_pins[0] = 0x10;
6314 spec->autocfg.speaker_pins[1] = 0x11;
6315 spec->automute = 1;
6316 spec->automute_mode = ALC_AUTOMUTE_PIN;
6319 static const struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
6320 .ops = &snd_hda_bind_vol,
6321 .values = {
6322 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_OUTPUT),
6323 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
6324 HDA_COMPOSE_AMP_VAL(0x0a, 3, 0, HDA_OUTPUT),
6329 static const struct hda_bind_ctls alc260_dc7600_bind_switch = {
6330 .ops = &snd_hda_bind_sw,
6331 .values = {
6332 HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
6333 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
6338 static const struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
6339 HDA_BIND_VOL("Master Playback Volume", &alc260_dc7600_bind_master_vol),
6340 HDA_BIND_SW("LineOut Playback Switch", &alc260_dc7600_bind_switch),
6341 HDA_CODEC_MUTE("Speaker Playback Switch", 0x0f, 0x0, HDA_OUTPUT),
6342 HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
6343 { } /* end */
6346 static const struct hda_verb alc260_hp_3013_unsol_verbs[] = {
6347 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6351 static void alc260_hp_3012_setup(struct hda_codec *codec)
6353 struct alc_spec *spec = codec->spec;
6355 spec->autocfg.hp_pins[0] = 0x10;
6356 spec->autocfg.speaker_pins[0] = 0x0f;
6357 spec->autocfg.speaker_pins[1] = 0x11;
6358 spec->autocfg.speaker_pins[2] = 0x15;
6359 spec->automute = 1;
6360 spec->automute_mode = ALC_AUTOMUTE_PIN;
6363 /* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
6364 * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
6366 static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
6367 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6368 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
6369 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
6370 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6371 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
6372 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
6373 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
6374 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
6375 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6376 HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
6377 { } /* end */
6380 /* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current
6381 * versions of the ALC260 don't act on requests to enable mic bias from NID
6382 * 0x0f (used to drive the headphone jack in these laptops). The ALC260
6383 * datasheet doesn't mention this restriction. At this stage it's not clear
6384 * whether this behaviour is intentional or is a hardware bug in chip
6385 * revisions available in early 2006. Therefore for now allow the
6386 * "Headphone Jack Mode" control to span all choices, but if it turns out
6387 * that the lack of mic bias for this NID is intentional we could change the
6388 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
6390 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
6391 * don't appear to make the mic bias available from the "line" jack, even
6392 * though the NID used for this jack (0x14) can supply it. The theory is
6393 * that perhaps Acer have included blocking capacitors between the ALC260
6394 * and the output jack. If this turns out to be the case for all such
6395 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
6396 * to ALC_PIN_DIR_INOUT_NOMICBIAS.
6398 * The C20x Tablet series have a mono internal speaker which is controlled
6399 * via the chip's Mono sum widget and pin complex, so include the necessary
6400 * controls for such models. On models without a "mono speaker" the control
6401 * won't do anything.
6403 static const struct snd_kcontrol_new alc260_acer_mixer[] = {
6404 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6405 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
6406 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
6407 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
6408 HDA_OUTPUT),
6409 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
6410 HDA_INPUT),
6411 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6412 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
6413 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
6414 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
6415 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
6416 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
6417 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
6418 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
6419 { } /* end */
6422 /* Maxdata Favorit 100XS: one output and one input (0x12) jack
6424 static const struct snd_kcontrol_new alc260_favorit100_mixer[] = {
6425 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6426 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
6427 ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
6428 HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
6429 HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
6430 ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
6431 { } /* end */
6434 /* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
6435 * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17.
6437 static const struct snd_kcontrol_new alc260_will_mixer[] = {
6438 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6439 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
6440 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
6441 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
6442 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
6443 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
6444 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
6445 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
6446 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6447 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
6448 { } /* end */
6451 /* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
6452 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
6454 static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
6455 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6456 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
6457 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
6458 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
6459 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
6460 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
6461 HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
6462 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
6463 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
6464 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
6465 { } /* end */
6469 * initialization verbs
6471 static const struct hda_verb alc260_init_verbs[] = {
6472 /* Line In pin widget for input */
6473 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6474 /* CD pin widget for input */
6475 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6476 /* Mic1 (rear panel) pin widget for input and vref at 80% */
6477 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
6478 /* Mic2 (front panel) pin widget for input and vref at 80% */
6479 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
6480 /* LINE-2 is used for line-out in rear */
6481 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6482 /* select line-out */
6483 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
6484 /* LINE-OUT pin */
6485 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6486 /* enable HP */
6487 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6488 /* enable Mono */
6489 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6490 /* mute capture amp left and right */
6491 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6492 /* set connection select to line in (default select for this ADC) */
6493 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
6494 /* mute capture amp left and right */
6495 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6496 /* set connection select to line in (default select for this ADC) */
6497 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
6498 /* set vol=0 Line-Out mixer amp left and right */
6499 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6500 /* unmute pin widget amp left and right (no gain on this amp) */
6501 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6502 /* set vol=0 HP mixer amp left and right */
6503 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6504 /* unmute pin widget amp left and right (no gain on this amp) */
6505 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6506 /* set vol=0 Mono mixer amp left and right */
6507 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6508 /* unmute pin widget amp left and right (no gain on this amp) */
6509 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6510 /* unmute LINE-2 out pin */
6511 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6512 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
6513 * Line In 2 = 0x03
6515 /* mute analog inputs */
6516 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6517 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6518 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6519 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6520 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
6521 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
6522 /* mute Front out path */
6523 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6524 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6525 /* mute Headphone out path */
6526 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6527 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6528 /* mute Mono out path */
6529 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6530 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6534 #if 0 /* should be identical with alc260_init_verbs? */
6535 static const struct hda_verb alc260_hp_init_verbs[] = {
6536 /* Headphone and output */
6537 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6538 /* mono output */
6539 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6540 /* Mic1 (rear panel) pin widget for input and vref at 80% */
6541 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6542 /* Mic2 (front panel) pin widget for input and vref at 80% */
6543 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6544 /* Line In pin widget for input */
6545 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6546 /* Line-2 pin widget for output */
6547 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6548 /* CD pin widget for input */
6549 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6550 /* unmute amp left and right */
6551 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
6552 /* set connection select to line in (default select for this ADC) */
6553 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
6554 /* unmute Line-Out mixer amp left and right (volume = 0) */
6555 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
6556 /* mute pin widget amp left and right (no gain on this amp) */
6557 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6558 /* unmute HP mixer amp left and right (volume = 0) */
6559 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
6560 /* mute pin widget amp left and right (no gain on this amp) */
6561 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6562 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
6563 * Line In 2 = 0x03
6565 /* mute analog inputs */
6566 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6567 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6568 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6569 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6570 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
6571 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
6572 /* Unmute Front out path */
6573 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6574 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6575 /* Unmute Headphone out path */
6576 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6577 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6578 /* Unmute Mono out path */
6579 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6580 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6583 #endif
6585 static const struct hda_verb alc260_hp_3013_init_verbs[] = {
6586 /* Line out and output */
6587 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6588 /* mono output */
6589 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6590 /* Mic1 (rear panel) pin widget for input and vref at 80% */
6591 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6592 /* Mic2 (front panel) pin widget for input and vref at 80% */
6593 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6594 /* Line In pin widget for input */
6595 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6596 /* Headphone pin widget for output */
6597 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6598 /* CD pin widget for input */
6599 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6600 /* unmute amp left and right */
6601 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
6602 /* set connection select to line in (default select for this ADC) */
6603 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
6604 /* unmute Line-Out mixer amp left and right (volume = 0) */
6605 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
6606 /* mute pin widget amp left and right (no gain on this amp) */
6607 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6608 /* unmute HP mixer amp left and right (volume = 0) */
6609 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
6610 /* mute pin widget amp left and right (no gain on this amp) */
6611 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6612 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
6613 * Line In 2 = 0x03
6615 /* mute analog inputs */
6616 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6617 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6618 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6619 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6620 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
6621 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
6622 /* Unmute Front out path */
6623 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6624 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6625 /* Unmute Headphone out path */
6626 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6627 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6628 /* Unmute Mono out path */
6629 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6630 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6634 /* Initialisation sequence for ALC260 as configured in Fujitsu S702x
6635 * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
6636 * audio = 0x16, internal speaker = 0x10.
6638 static const struct hda_verb alc260_fujitsu_init_verbs[] = {
6639 /* Disable all GPIOs */
6640 {0x01, AC_VERB_SET_GPIO_MASK, 0},
6641 /* Internal speaker is connected to headphone pin */
6642 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6643 /* Headphone/Line-out jack connects to Line1 pin; make it an output */
6644 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6645 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
6646 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6647 /* Ensure all other unused pins are disabled and muted. */
6648 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6649 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6650 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6651 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6652 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6653 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6654 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6655 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6657 /* Disable digital (SPDIF) pins */
6658 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6659 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6661 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
6662 * when acting as an output.
6664 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6666 /* Start with output sum widgets muted and their output gains at min */
6667 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6668 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6669 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6670 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6671 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6672 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6673 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6674 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6675 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6677 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
6678 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6679 /* Unmute Line1 pin widget output buffer since it starts as an output.
6680 * If the pin mode is changed by the user the pin mode control will
6681 * take care of enabling the pin's input/output buffers as needed.
6682 * Therefore there's no need to enable the input buffer at this
6683 * stage.
6685 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6686 /* Unmute input buffer of pin widget used for Line-in (no equiv
6687 * mixer ctrl)
6689 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6691 /* Mute capture amp left and right */
6692 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6693 /* Set ADC connection select to match default mixer setting - line
6694 * in (on mic1 pin)
6696 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6698 /* Do the same for the second ADC: mute capture input amp and
6699 * set ADC connection to line in (on mic1 pin)
6701 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6702 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6704 /* Mute all inputs to mixer widget (even unconnected ones) */
6705 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6706 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6707 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6708 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6709 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6710 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6711 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6712 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6717 /* Initialisation sequence for ALC260 as configured in Acer TravelMate and
6718 * similar laptops (adapted from Fujitsu init verbs).
6720 static const struct hda_verb alc260_acer_init_verbs[] = {
6721 /* On TravelMate laptops, GPIO 0 enables the internal speaker and
6722 * the headphone jack. Turn this on and rely on the standard mute
6723 * methods whenever the user wants to turn these outputs off.
6725 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
6726 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6727 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
6728 /* Internal speaker/Headphone jack is connected to Line-out pin */
6729 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6730 /* Internal microphone/Mic jack is connected to Mic1 pin */
6731 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
6732 /* Line In jack is connected to Line1 pin */
6733 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6734 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
6735 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6736 /* Ensure all other unused pins are disabled and muted. */
6737 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6738 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6739 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6740 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6741 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6742 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6743 /* Disable digital (SPDIF) pins */
6744 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6745 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6747 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
6748 * bus when acting as outputs.
6750 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
6751 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6753 /* Start with output sum widgets muted and their output gains at min */
6754 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6755 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6756 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6757 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6758 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6759 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6760 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6761 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6762 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6764 /* Unmute Line-out pin widget amp left and right
6765 * (no equiv mixer ctrl)
6767 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6768 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */
6769 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6770 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
6771 * inputs. If the pin mode is changed by the user the pin mode control
6772 * will take care of enabling the pin's input/output buffers as needed.
6773 * Therefore there's no need to enable the input buffer at this
6774 * stage.
6776 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6777 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6779 /* Mute capture amp left and right */
6780 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6781 /* Set ADC connection select to match default mixer setting - mic
6782 * (on mic1 pin)
6784 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6786 /* Do similar with the second ADC: mute capture input amp and
6787 * set ADC connection to mic to match ALSA's default state.
6789 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6790 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6792 /* Mute all inputs to mixer widget (even unconnected ones) */
6793 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6794 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6795 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6796 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6797 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6798 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6799 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6800 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6805 /* Initialisation sequence for Maxdata Favorit 100XS
6806 * (adapted from Acer init verbs).
6808 static const struct hda_verb alc260_favorit100_init_verbs[] = {
6809 /* GPIO 0 enables the output jack.
6810 * Turn this on and rely on the standard mute
6811 * methods whenever the user wants to turn these outputs off.
6813 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
6814 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6815 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
6816 /* Line/Mic input jack is connected to Mic1 pin */
6817 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
6818 /* Ensure all other unused pins are disabled and muted. */
6819 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6820 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6821 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6822 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6823 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6824 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6825 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6826 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6827 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6828 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6829 /* Disable digital (SPDIF) pins */
6830 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6831 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6833 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
6834 * bus when acting as outputs.
6836 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
6837 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6839 /* Start with output sum widgets muted and their output gains at min */
6840 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6841 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6842 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6843 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6844 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6845 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6846 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6847 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6848 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6850 /* Unmute Line-out pin widget amp left and right
6851 * (no equiv mixer ctrl)
6853 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6854 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
6855 * inputs. If the pin mode is changed by the user the pin mode control
6856 * will take care of enabling the pin's input/output buffers as needed.
6857 * Therefore there's no need to enable the input buffer at this
6858 * stage.
6860 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6862 /* Mute capture amp left and right */
6863 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6864 /* Set ADC connection select to match default mixer setting - mic
6865 * (on mic1 pin)
6867 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6869 /* Do similar with the second ADC: mute capture input amp and
6870 * set ADC connection to mic to match ALSA's default state.
6872 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6873 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6875 /* Mute all inputs to mixer widget (even unconnected ones) */
6876 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6877 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6878 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6879 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6880 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6881 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6882 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6883 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6888 static const struct hda_verb alc260_will_verbs[] = {
6889 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6890 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
6891 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
6892 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
6893 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
6894 {0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
6898 static const struct hda_verb alc260_replacer_672v_verbs[] = {
6899 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
6900 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
6901 {0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
6903 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
6904 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6905 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
6907 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6911 /* toggle speaker-output according to the hp-jack state */
6912 static void alc260_replacer_672v_automute(struct hda_codec *codec)
6914 unsigned int present;
6916 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
6917 present = snd_hda_jack_detect(codec, 0x0f);
6918 if (present) {
6919 snd_hda_codec_write_cache(codec, 0x01, 0,
6920 AC_VERB_SET_GPIO_DATA, 1);
6921 snd_hda_codec_write_cache(codec, 0x0f, 0,
6922 AC_VERB_SET_PIN_WIDGET_CONTROL,
6923 PIN_HP);
6924 } else {
6925 snd_hda_codec_write_cache(codec, 0x01, 0,
6926 AC_VERB_SET_GPIO_DATA, 0);
6927 snd_hda_codec_write_cache(codec, 0x0f, 0,
6928 AC_VERB_SET_PIN_WIDGET_CONTROL,
6929 PIN_OUT);
6933 static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
6934 unsigned int res)
6936 if ((res >> 26) == ALC880_HP_EVENT)
6937 alc260_replacer_672v_automute(codec);
6940 static const struct hda_verb alc260_hp_dc7600_verbs[] = {
6941 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
6942 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
6943 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6944 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6945 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6946 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6947 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
6948 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6949 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6950 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6954 /* Test configuration for debugging, modelled after the ALC880 test
6955 * configuration.
6957 #ifdef CONFIG_SND_DEBUG
6958 static const hda_nid_t alc260_test_dac_nids[1] = {
6959 0x02,
6961 static const hda_nid_t alc260_test_adc_nids[2] = {
6962 0x04, 0x05,
6964 /* For testing the ALC260, each input MUX needs its own definition since
6965 * the signal assignments are different. This assumes that the first ADC
6966 * is NID 0x04.
6968 static const struct hda_input_mux alc260_test_capture_sources[2] = {
6970 .num_items = 7,
6971 .items = {
6972 { "MIC1 pin", 0x0 },
6973 { "MIC2 pin", 0x1 },
6974 { "LINE1 pin", 0x2 },
6975 { "LINE2 pin", 0x3 },
6976 { "CD pin", 0x4 },
6977 { "LINE-OUT pin", 0x5 },
6978 { "HP-OUT pin", 0x6 },
6982 .num_items = 8,
6983 .items = {
6984 { "MIC1 pin", 0x0 },
6985 { "MIC2 pin", 0x1 },
6986 { "LINE1 pin", 0x2 },
6987 { "LINE2 pin", 0x3 },
6988 { "CD pin", 0x4 },
6989 { "Mixer", 0x5 },
6990 { "LINE-OUT pin", 0x6 },
6991 { "HP-OUT pin", 0x7 },
6995 static const struct snd_kcontrol_new alc260_test_mixer[] = {
6996 /* Output driver widgets */
6997 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
6998 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
6999 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
7000 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
7001 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
7002 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
7004 /* Modes for retasking pin widgets
7005 * Note: the ALC260 doesn't seem to act on requests to enable mic
7006 * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't
7007 * mention this restriction. At this stage it's not clear whether
7008 * this behaviour is intentional or is a hardware bug in chip
7009 * revisions available at least up until early 2006. Therefore for
7010 * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
7011 * choices, but if it turns out that the lack of mic bias for these
7012 * NIDs is intentional we could change their modes from
7013 * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
7015 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
7016 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
7017 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
7018 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
7019 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
7020 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
7022 /* Loopback mixer controls */
7023 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
7024 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
7025 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
7026 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
7027 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
7028 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
7029 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
7030 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
7031 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
7032 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
7033 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
7034 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
7035 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
7036 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
7038 /* Controls for GPIO pins, assuming they are configured as outputs */
7039 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
7040 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
7041 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
7042 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
7044 /* Switches to allow the digital IO pins to be enabled. The datasheet
7045 * is ambigious as to which NID is which; testing on laptops which
7046 * make this output available should provide clarification.
7048 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
7049 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
7051 /* A switch allowing EAPD to be enabled. Some laptops seem to use
7052 * this output to turn on an external amplifier.
7054 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
7055 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
7057 { } /* end */
7059 static const struct hda_verb alc260_test_init_verbs[] = {
7060 /* Enable all GPIOs as outputs with an initial value of 0 */
7061 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
7062 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
7063 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
7065 /* Enable retasking pins as output, initially without power amp */
7066 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7067 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7068 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7069 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7070 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7071 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7073 /* Disable digital (SPDIF) pins initially, but users can enable
7074 * them via a mixer switch. In the case of SPDIF-out, this initverb
7075 * payload also sets the generation to 0, output to be in "consumer"
7076 * PCM format, copyright asserted, no pre-emphasis and no validity
7077 * control.
7079 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
7080 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
7082 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
7083 * OUT1 sum bus when acting as an output.
7085 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
7086 {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
7087 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
7088 {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
7090 /* Start with output sum widgets muted and their output gains at min */
7091 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7092 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7093 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7094 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7095 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7096 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7097 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7098 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7099 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7101 /* Unmute retasking pin widget output buffers since the default
7102 * state appears to be output. As the pin mode is changed by the
7103 * user the pin mode control will take care of enabling the pin's
7104 * input/output buffers as needed.
7106 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7107 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7108 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7109 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7110 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7111 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7112 /* Also unmute the mono-out pin widget */
7113 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7115 /* Mute capture amp left and right */
7116 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7117 /* Set ADC connection select to match default mixer setting (mic1
7118 * pin)
7120 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
7122 /* Do the same for the second ADC: mute capture input amp and
7123 * set ADC connection to mic1 pin
7125 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7126 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
7128 /* Mute all inputs to mixer widget (even unconnected ones) */
7129 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
7130 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
7131 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
7132 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
7133 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
7134 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
7135 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
7136 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
7140 #endif
7142 #define alc260_pcm_analog_playback alc880_pcm_analog_alt_playback
7143 #define alc260_pcm_analog_capture alc880_pcm_analog_capture
7145 #define alc260_pcm_digital_playback alc880_pcm_digital_playback
7146 #define alc260_pcm_digital_capture alc880_pcm_digital_capture
7149 * for BIOS auto-configuration
7152 static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
7153 const char *pfx, int *vol_bits)
7155 hda_nid_t nid_vol;
7156 unsigned long vol_val, sw_val;
7157 int err;
7159 if (nid >= 0x0f && nid < 0x11) {
7160 nid_vol = nid - 0x7;
7161 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
7162 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
7163 } else if (nid == 0x11) {
7164 nid_vol = nid - 0x7;
7165 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
7166 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
7167 } else if (nid >= 0x12 && nid <= 0x15) {
7168 nid_vol = 0x08;
7169 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
7170 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
7171 } else
7172 return 0; /* N/A */
7174 if (!(*vol_bits & (1 << nid_vol))) {
7175 /* first control for the volume widget */
7176 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
7177 if (err < 0)
7178 return err;
7179 *vol_bits |= (1 << nid_vol);
7181 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
7182 if (err < 0)
7183 return err;
7184 return 1;
7187 /* add playback controls from the parsed DAC table */
7188 static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
7189 const struct auto_pin_cfg *cfg)
7191 hda_nid_t nid;
7192 int err;
7193 int vols = 0;
7195 spec->multiout.num_dacs = 1;
7196 spec->multiout.dac_nids = spec->private_dac_nids;
7197 spec->private_dac_nids[0] = 0x02;
7199 nid = cfg->line_out_pins[0];
7200 if (nid) {
7201 const char *pfx;
7202 if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
7203 pfx = "Master";
7204 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
7205 pfx = "Speaker";
7206 else
7207 pfx = "Front";
7208 err = alc260_add_playback_controls(spec, nid, pfx, &vols);
7209 if (err < 0)
7210 return err;
7213 nid = cfg->speaker_pins[0];
7214 if (nid) {
7215 err = alc260_add_playback_controls(spec, nid, "Speaker", &vols);
7216 if (err < 0)
7217 return err;
7220 nid = cfg->hp_pins[0];
7221 if (nid) {
7222 err = alc260_add_playback_controls(spec, nid, "Headphone",
7223 &vols);
7224 if (err < 0)
7225 return err;
7227 return 0;
7230 /* create playback/capture controls for input pins */
7231 static int alc260_auto_create_input_ctls(struct hda_codec *codec,
7232 const struct auto_pin_cfg *cfg)
7234 return alc_auto_create_input_ctls(codec, cfg, 0x07, 0x04, 0x05);
7237 static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
7238 hda_nid_t nid, int pin_type,
7239 int sel_idx)
7241 alc_set_pin_output(codec, nid, pin_type);
7242 /* need the manual connection? */
7243 if (nid >= 0x12) {
7244 int idx = nid - 0x12;
7245 snd_hda_codec_write(codec, idx + 0x0b, 0,
7246 AC_VERB_SET_CONNECT_SEL, sel_idx);
7250 static void alc260_auto_init_multi_out(struct hda_codec *codec)
7252 struct alc_spec *spec = codec->spec;
7253 hda_nid_t nid;
7255 nid = spec->autocfg.line_out_pins[0];
7256 if (nid) {
7257 int pin_type = get_pin_type(spec->autocfg.line_out_type);
7258 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
7261 nid = spec->autocfg.speaker_pins[0];
7262 if (nid)
7263 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
7265 nid = spec->autocfg.hp_pins[0];
7266 if (nid)
7267 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
7270 #define ALC260_PIN_CD_NID 0x16
7271 static void alc260_auto_init_analog_input(struct hda_codec *codec)
7273 struct alc_spec *spec = codec->spec;
7274 struct auto_pin_cfg *cfg = &spec->autocfg;
7275 int i;
7277 for (i = 0; i < cfg->num_inputs; i++) {
7278 hda_nid_t nid = cfg->inputs[i].pin;
7279 if (nid >= 0x12) {
7280 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
7281 if (nid != ALC260_PIN_CD_NID &&
7282 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
7283 snd_hda_codec_write(codec, nid, 0,
7284 AC_VERB_SET_AMP_GAIN_MUTE,
7285 AMP_OUT_MUTE);
7290 #define alc260_auto_init_input_src alc880_auto_init_input_src
7293 * generic initialization of ADC, input mixers and output mixers
7295 static const struct hda_verb alc260_volume_init_verbs[] = {
7297 * Unmute ADC0-1 and set the default input to mic-in
7299 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
7300 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7301 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
7302 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7304 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
7305 * mixer widget
7306 * Note: PASD motherboards uses the Line In 2 as the input for
7307 * front panel mic (mic 2)
7309 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
7310 /* mute analog inputs */
7311 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7312 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7313 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7314 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7315 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7318 * Set up output mixers (0x08 - 0x0a)
7320 /* set vol=0 to output mixers */
7321 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7322 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7323 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7324 /* set up input amps for analog loopback */
7325 /* Amp Indices: DAC = 0, mixer = 1 */
7326 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7327 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7328 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7329 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7330 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7331 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7336 static int alc260_parse_auto_config(struct hda_codec *codec)
7338 struct alc_spec *spec = codec->spec;
7339 int err;
7340 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
7342 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
7343 alc260_ignore);
7344 if (err < 0)
7345 return err;
7346 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
7347 if (err < 0)
7348 return err;
7349 if (!spec->kctls.list)
7350 return 0; /* can't find valid BIOS pin config */
7351 err = alc260_auto_create_input_ctls(codec, &spec->autocfg);
7352 if (err < 0)
7353 return err;
7355 spec->multiout.max_channels = 2;
7357 if (spec->autocfg.dig_outs)
7358 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
7359 if (spec->kctls.list)
7360 add_mixer(spec, spec->kctls.list);
7362 add_verb(spec, alc260_volume_init_verbs);
7364 spec->num_mux_defs = 1;
7365 spec->input_mux = &spec->private_imux[0];
7367 alc_ssid_check(codec, 0x10, 0x15, 0x0f, 0);
7369 return 1;
7372 /* additional initialization for auto-configuration model */
7373 static void alc260_auto_init(struct hda_codec *codec)
7375 struct alc_spec *spec = codec->spec;
7376 alc260_auto_init_multi_out(codec);
7377 alc260_auto_init_analog_input(codec);
7378 alc260_auto_init_input_src(codec);
7379 alc_auto_init_digital(codec);
7380 if (spec->unsol_event)
7381 alc_inithook(codec);
7384 #ifdef CONFIG_SND_HDA_POWER_SAVE
7385 static const struct hda_amp_list alc260_loopbacks[] = {
7386 { 0x07, HDA_INPUT, 0 },
7387 { 0x07, HDA_INPUT, 1 },
7388 { 0x07, HDA_INPUT, 2 },
7389 { 0x07, HDA_INPUT, 3 },
7390 { 0x07, HDA_INPUT, 4 },
7391 { } /* end */
7393 #endif
7396 * Pin config fixes
7398 enum {
7399 PINFIX_HP_DC5750,
7402 static const struct alc_fixup alc260_fixups[] = {
7403 [PINFIX_HP_DC5750] = {
7404 .type = ALC_FIXUP_PINS,
7405 .v.pins = (const struct alc_pincfg[]) {
7406 { 0x11, 0x90130110 }, /* speaker */
7412 static const struct snd_pci_quirk alc260_fixup_tbl[] = {
7413 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
7418 * ALC260 configurations
7420 static const char * const alc260_models[ALC260_MODEL_LAST] = {
7421 [ALC260_BASIC] = "basic",
7422 [ALC260_HP] = "hp",
7423 [ALC260_HP_3013] = "hp-3013",
7424 [ALC260_HP_DC7600] = "hp-dc7600",
7425 [ALC260_FUJITSU_S702X] = "fujitsu",
7426 [ALC260_ACER] = "acer",
7427 [ALC260_WILL] = "will",
7428 [ALC260_REPLACER_672V] = "replacer",
7429 [ALC260_FAVORIT100] = "favorit100",
7430 #ifdef CONFIG_SND_DEBUG
7431 [ALC260_TEST] = "test",
7432 #endif
7433 [ALC260_AUTO] = "auto",
7436 static const struct snd_pci_quirk alc260_cfg_tbl[] = {
7437 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
7438 SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
7439 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
7440 SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
7441 SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
7442 SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_AUTO), /* no quirk */
7443 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
7444 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
7445 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_DC7600),
7446 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
7447 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
7448 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
7449 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
7450 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
7451 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
7452 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
7453 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
7454 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
7455 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
7456 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
7460 static const struct alc_config_preset alc260_presets[] = {
7461 [ALC260_BASIC] = {
7462 .mixers = { alc260_base_output_mixer,
7463 alc260_input_mixer },
7464 .init_verbs = { alc260_init_verbs },
7465 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7466 .dac_nids = alc260_dac_nids,
7467 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
7468 .adc_nids = alc260_dual_adc_nids,
7469 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7470 .channel_mode = alc260_modes,
7471 .input_mux = &alc260_capture_source,
7473 [ALC260_HP] = {
7474 .mixers = { alc260_hp_output_mixer,
7475 alc260_input_mixer },
7476 .init_verbs = { alc260_init_verbs,
7477 alc260_hp_unsol_verbs },
7478 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7479 .dac_nids = alc260_dac_nids,
7480 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
7481 .adc_nids = alc260_adc_nids_alt,
7482 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7483 .channel_mode = alc260_modes,
7484 .input_mux = &alc260_capture_source,
7485 .unsol_event = alc_sku_unsol_event,
7486 .setup = alc260_hp_setup,
7487 .init_hook = alc_inithook,
7489 [ALC260_HP_DC7600] = {
7490 .mixers = { alc260_hp_dc7600_mixer,
7491 alc260_input_mixer },
7492 .init_verbs = { alc260_init_verbs,
7493 alc260_hp_dc7600_verbs },
7494 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7495 .dac_nids = alc260_dac_nids,
7496 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
7497 .adc_nids = alc260_adc_nids_alt,
7498 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7499 .channel_mode = alc260_modes,
7500 .input_mux = &alc260_capture_source,
7501 .unsol_event = alc_sku_unsol_event,
7502 .setup = alc260_hp_3012_setup,
7503 .init_hook = alc_inithook,
7505 [ALC260_HP_3013] = {
7506 .mixers = { alc260_hp_3013_mixer,
7507 alc260_input_mixer },
7508 .init_verbs = { alc260_hp_3013_init_verbs,
7509 alc260_hp_3013_unsol_verbs },
7510 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7511 .dac_nids = alc260_dac_nids,
7512 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
7513 .adc_nids = alc260_adc_nids_alt,
7514 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7515 .channel_mode = alc260_modes,
7516 .input_mux = &alc260_capture_source,
7517 .unsol_event = alc_sku_unsol_event,
7518 .setup = alc260_hp_3013_setup,
7519 .init_hook = alc_inithook,
7521 [ALC260_FUJITSU_S702X] = {
7522 .mixers = { alc260_fujitsu_mixer },
7523 .init_verbs = { alc260_fujitsu_init_verbs },
7524 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7525 .dac_nids = alc260_dac_nids,
7526 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
7527 .adc_nids = alc260_dual_adc_nids,
7528 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7529 .channel_mode = alc260_modes,
7530 .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
7531 .input_mux = alc260_fujitsu_capture_sources,
7533 [ALC260_ACER] = {
7534 .mixers = { alc260_acer_mixer },
7535 .init_verbs = { alc260_acer_init_verbs },
7536 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7537 .dac_nids = alc260_dac_nids,
7538 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
7539 .adc_nids = alc260_dual_adc_nids,
7540 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7541 .channel_mode = alc260_modes,
7542 .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
7543 .input_mux = alc260_acer_capture_sources,
7545 [ALC260_FAVORIT100] = {
7546 .mixers = { alc260_favorit100_mixer },
7547 .init_verbs = { alc260_favorit100_init_verbs },
7548 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7549 .dac_nids = alc260_dac_nids,
7550 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
7551 .adc_nids = alc260_dual_adc_nids,
7552 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7553 .channel_mode = alc260_modes,
7554 .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
7555 .input_mux = alc260_favorit100_capture_sources,
7557 [ALC260_WILL] = {
7558 .mixers = { alc260_will_mixer },
7559 .init_verbs = { alc260_init_verbs, alc260_will_verbs },
7560 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7561 .dac_nids = alc260_dac_nids,
7562 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
7563 .adc_nids = alc260_adc_nids,
7564 .dig_out_nid = ALC260_DIGOUT_NID,
7565 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7566 .channel_mode = alc260_modes,
7567 .input_mux = &alc260_capture_source,
7569 [ALC260_REPLACER_672V] = {
7570 .mixers = { alc260_replacer_672v_mixer },
7571 .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
7572 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7573 .dac_nids = alc260_dac_nids,
7574 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
7575 .adc_nids = alc260_adc_nids,
7576 .dig_out_nid = ALC260_DIGOUT_NID,
7577 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7578 .channel_mode = alc260_modes,
7579 .input_mux = &alc260_capture_source,
7580 .unsol_event = alc260_replacer_672v_unsol_event,
7581 .init_hook = alc260_replacer_672v_automute,
7583 #ifdef CONFIG_SND_DEBUG
7584 [ALC260_TEST] = {
7585 .mixers = { alc260_test_mixer },
7586 .init_verbs = { alc260_test_init_verbs },
7587 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
7588 .dac_nids = alc260_test_dac_nids,
7589 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
7590 .adc_nids = alc260_test_adc_nids,
7591 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7592 .channel_mode = alc260_modes,
7593 .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
7594 .input_mux = alc260_test_capture_sources,
7596 #endif
7599 static int patch_alc260(struct hda_codec *codec)
7601 struct alc_spec *spec;
7602 int err, board_config;
7604 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
7605 if (spec == NULL)
7606 return -ENOMEM;
7608 codec->spec = spec;
7610 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
7611 alc260_models,
7612 alc260_cfg_tbl);
7613 if (board_config < 0) {
7614 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
7615 codec->chip_name);
7616 board_config = ALC260_AUTO;
7619 if (board_config == ALC260_AUTO) {
7620 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
7621 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
7624 if (board_config == ALC260_AUTO) {
7625 /* automatic parse from the BIOS config */
7626 err = alc260_parse_auto_config(codec);
7627 if (err < 0) {
7628 alc_free(codec);
7629 return err;
7630 } else if (!err) {
7631 printk(KERN_INFO
7632 "hda_codec: Cannot set up configuration "
7633 "from BIOS. Using base mode...\n");
7634 board_config = ALC260_BASIC;
7638 err = snd_hda_attach_beep_device(codec, 0x1);
7639 if (err < 0) {
7640 alc_free(codec);
7641 return err;
7644 if (board_config != ALC260_AUTO)
7645 setup_preset(codec, &alc260_presets[board_config]);
7647 spec->stream_analog_playback = &alc260_pcm_analog_playback;
7648 spec->stream_analog_capture = &alc260_pcm_analog_capture;
7649 spec->stream_analog_alt_capture = &alc260_pcm_analog_capture;
7651 spec->stream_digital_playback = &alc260_pcm_digital_playback;
7652 spec->stream_digital_capture = &alc260_pcm_digital_capture;
7654 if (!spec->adc_nids && spec->input_mux) {
7655 /* check whether NID 0x04 is valid */
7656 unsigned int wcap = get_wcaps(codec, 0x04);
7657 wcap = get_wcaps_type(wcap);
7658 /* get type */
7659 if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
7660 spec->adc_nids = alc260_adc_nids_alt;
7661 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
7662 } else {
7663 spec->adc_nids = alc260_adc_nids;
7664 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
7667 set_capture_mixer(codec);
7668 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
7670 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
7672 spec->vmaster_nid = 0x08;
7674 codec->patch_ops = alc_patch_ops;
7675 if (board_config == ALC260_AUTO)
7676 spec->init_hook = alc260_auto_init;
7677 spec->shutup = alc_eapd_shutup;
7678 #ifdef CONFIG_SND_HDA_POWER_SAVE
7679 if (!spec->loopback.amplist)
7680 spec->loopback.amplist = alc260_loopbacks;
7681 #endif
7683 return 0;
7688 * ALC882/883/885/888/889 support
7690 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
7691 * configuration. Each pin widget can choose any input DACs and a mixer.
7692 * Each ADC is connected from a mixer of all inputs. This makes possible
7693 * 6-channel independent captures.
7695 * In addition, an independent DAC for the multi-playback (not used in this
7696 * driver yet).
7698 #define ALC882_DIGOUT_NID 0x06
7699 #define ALC882_DIGIN_NID 0x0a
7700 #define ALC883_DIGOUT_NID ALC882_DIGOUT_NID
7701 #define ALC883_DIGIN_NID ALC882_DIGIN_NID
7702 #define ALC1200_DIGOUT_NID 0x10
7705 static const struct hda_channel_mode alc882_ch_modes[1] = {
7706 { 8, NULL }
7709 /* DACs */
7710 static const hda_nid_t alc882_dac_nids[4] = {
7711 /* front, rear, clfe, rear_surr */
7712 0x02, 0x03, 0x04, 0x05
7714 #define alc883_dac_nids alc882_dac_nids
7716 /* ADCs */
7717 #define alc882_adc_nids alc880_adc_nids
7718 #define alc882_adc_nids_alt alc880_adc_nids_alt
7719 #define alc883_adc_nids alc882_adc_nids_alt
7720 static const hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
7721 static const hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
7722 #define alc889_adc_nids alc880_adc_nids
7724 static const hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
7725 static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
7726 #define alc883_capsrc_nids alc882_capsrc_nids_alt
7727 static const hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
7728 #define alc889_capsrc_nids alc882_capsrc_nids
7730 /* input MUX */
7731 /* FIXME: should be a matrix-type input source selection */
7733 static const struct hda_input_mux alc882_capture_source = {
7734 .num_items = 4,
7735 .items = {
7736 { "Mic", 0x0 },
7737 { "Front Mic", 0x1 },
7738 { "Line", 0x2 },
7739 { "CD", 0x4 },
7743 #define alc883_capture_source alc882_capture_source
7745 static const struct hda_input_mux alc889_capture_source = {
7746 .num_items = 3,
7747 .items = {
7748 { "Front Mic", 0x0 },
7749 { "Mic", 0x3 },
7750 { "Line", 0x2 },
7754 static const struct hda_input_mux mb5_capture_source = {
7755 .num_items = 3,
7756 .items = {
7757 { "Mic", 0x1 },
7758 { "Line", 0x7 },
7759 { "CD", 0x4 },
7763 static const struct hda_input_mux macmini3_capture_source = {
7764 .num_items = 2,
7765 .items = {
7766 { "Line", 0x2 },
7767 { "CD", 0x4 },
7771 static const struct hda_input_mux alc883_3stack_6ch_intel = {
7772 .num_items = 4,
7773 .items = {
7774 { "Mic", 0x1 },
7775 { "Front Mic", 0x0 },
7776 { "Line", 0x2 },
7777 { "CD", 0x4 },
7781 static const struct hda_input_mux alc883_lenovo_101e_capture_source = {
7782 .num_items = 2,
7783 .items = {
7784 { "Mic", 0x1 },
7785 { "Line", 0x2 },
7789 static const struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
7790 .num_items = 4,
7791 .items = {
7792 { "Mic", 0x0 },
7793 { "Internal Mic", 0x1 },
7794 { "Line", 0x2 },
7795 { "CD", 0x4 },
7799 static const struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
7800 .num_items = 2,
7801 .items = {
7802 { "Mic", 0x0 },
7803 { "Internal Mic", 0x1 },
7807 static const struct hda_input_mux alc883_lenovo_sky_capture_source = {
7808 .num_items = 3,
7809 .items = {
7810 { "Mic", 0x0 },
7811 { "Front Mic", 0x1 },
7812 { "Line", 0x4 },
7816 static const struct hda_input_mux alc883_asus_eee1601_capture_source = {
7817 .num_items = 2,
7818 .items = {
7819 { "Mic", 0x0 },
7820 { "Line", 0x2 },
7824 static const struct hda_input_mux alc889A_mb31_capture_source = {
7825 .num_items = 2,
7826 .items = {
7827 { "Mic", 0x0 },
7828 /* Front Mic (0x01) unused */
7829 { "Line", 0x2 },
7830 /* Line 2 (0x03) unused */
7831 /* CD (0x04) unused? */
7835 static const struct hda_input_mux alc889A_imac91_capture_source = {
7836 .num_items = 2,
7837 .items = {
7838 { "Mic", 0x01 },
7839 { "Line", 0x2 }, /* Not sure! */
7844 * 2ch mode
7846 static const struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
7847 { 2, NULL }
7851 * 2ch mode
7853 static const struct hda_verb alc882_3ST_ch2_init[] = {
7854 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7855 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7856 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7857 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7858 { } /* end */
7862 * 4ch mode
7864 static const struct hda_verb alc882_3ST_ch4_init[] = {
7865 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7866 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7867 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7868 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7869 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7870 { } /* end */
7874 * 6ch mode
7876 static const struct hda_verb alc882_3ST_ch6_init[] = {
7877 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7878 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7879 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7880 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7881 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7882 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7883 { } /* end */
7886 static const struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
7887 { 2, alc882_3ST_ch2_init },
7888 { 4, alc882_3ST_ch4_init },
7889 { 6, alc882_3ST_ch6_init },
7892 #define alc883_3ST_6ch_modes alc882_3ST_6ch_modes
7895 * 2ch mode
7897 static const struct hda_verb alc883_3ST_ch2_clevo_init[] = {
7898 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
7899 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7900 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7901 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7902 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7903 { } /* end */
7907 * 4ch mode
7909 static const struct hda_verb alc883_3ST_ch4_clevo_init[] = {
7910 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7911 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7912 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7913 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7914 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7915 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7916 { } /* end */
7920 * 6ch mode
7922 static const struct hda_verb alc883_3ST_ch6_clevo_init[] = {
7923 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7924 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7925 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7926 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7927 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7928 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7929 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7930 { } /* end */
7933 static const struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
7934 { 2, alc883_3ST_ch2_clevo_init },
7935 { 4, alc883_3ST_ch4_clevo_init },
7936 { 6, alc883_3ST_ch6_clevo_init },
7941 * 6ch mode
7943 static const struct hda_verb alc882_sixstack_ch6_init[] = {
7944 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7945 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7946 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7947 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7948 { } /* end */
7952 * 8ch mode
7954 static const struct hda_verb alc882_sixstack_ch8_init[] = {
7955 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7956 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7957 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7958 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7959 { } /* end */
7962 static const struct hda_channel_mode alc882_sixstack_modes[2] = {
7963 { 6, alc882_sixstack_ch6_init },
7964 { 8, alc882_sixstack_ch8_init },
7968 /* Macbook Air 2,1 */
7970 static const struct hda_channel_mode alc885_mba21_ch_modes[1] = {
7971 { 2, NULL },
7975 * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
7979 * 2ch mode
7981 static const struct hda_verb alc885_mbp_ch2_init[] = {
7982 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7983 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7984 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7985 { } /* end */
7989 * 4ch mode
7991 static const struct hda_verb alc885_mbp_ch4_init[] = {
7992 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7993 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7994 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7995 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7996 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7997 { } /* end */
8000 static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
8001 { 2, alc885_mbp_ch2_init },
8002 { 4, alc885_mbp_ch4_init },
8006 * 2ch
8007 * Speakers/Woofer/HP = Front
8008 * LineIn = Input
8010 static const struct hda_verb alc885_mb5_ch2_init[] = {
8011 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8012 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8013 { } /* end */
8017 * 6ch mode
8018 * Speakers/HP = Front
8019 * Woofer = LFE
8020 * LineIn = Surround
8022 static const struct hda_verb alc885_mb5_ch6_init[] = {
8023 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8024 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8025 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
8026 { } /* end */
8029 static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
8030 { 2, alc885_mb5_ch2_init },
8031 { 6, alc885_mb5_ch6_init },
8034 #define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes
8037 * 2ch mode
8039 static const struct hda_verb alc883_4ST_ch2_init[] = {
8040 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8041 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8042 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8043 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8044 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
8045 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8046 { } /* end */
8050 * 4ch mode
8052 static const struct hda_verb alc883_4ST_ch4_init[] = {
8053 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8054 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8055 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8056 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8057 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8058 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8059 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8060 { } /* end */
8064 * 6ch mode
8066 static const struct hda_verb alc883_4ST_ch6_init[] = {
8067 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8068 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8069 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8070 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8071 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
8072 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8073 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8074 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8075 { } /* end */
8079 * 8ch mode
8081 static const struct hda_verb alc883_4ST_ch8_init[] = {
8082 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8083 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8084 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
8085 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8086 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8087 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
8088 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8089 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8090 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8091 { } /* end */
8094 static const struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
8095 { 2, alc883_4ST_ch2_init },
8096 { 4, alc883_4ST_ch4_init },
8097 { 6, alc883_4ST_ch6_init },
8098 { 8, alc883_4ST_ch8_init },
8103 * 2ch mode
8105 static const struct hda_verb alc883_3ST_ch2_intel_init[] = {
8106 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8107 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8108 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
8109 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8110 { } /* end */
8114 * 4ch mode
8116 static const struct hda_verb alc883_3ST_ch4_intel_init[] = {
8117 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8118 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8119 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8120 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8121 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8122 { } /* end */
8126 * 6ch mode
8128 static const struct hda_verb alc883_3ST_ch6_intel_init[] = {
8129 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8130 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8131 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
8132 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8133 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8134 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8135 { } /* end */
8138 static const struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
8139 { 2, alc883_3ST_ch2_intel_init },
8140 { 4, alc883_3ST_ch4_intel_init },
8141 { 6, alc883_3ST_ch6_intel_init },
8145 * 2ch mode
8147 static const struct hda_verb alc889_ch2_intel_init[] = {
8148 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
8149 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
8150 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
8151 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00 },
8152 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
8153 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8154 { } /* end */
8158 * 6ch mode
8160 static const struct hda_verb alc889_ch6_intel_init[] = {
8161 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
8162 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
8163 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
8164 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
8165 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
8166 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8167 { } /* end */
8171 * 8ch mode
8173 static const struct hda_verb alc889_ch8_intel_init[] = {
8174 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
8175 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
8176 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
8177 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
8178 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x03 },
8179 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8180 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8181 { } /* end */
8184 static const struct hda_channel_mode alc889_8ch_intel_modes[3] = {
8185 { 2, alc889_ch2_intel_init },
8186 { 6, alc889_ch6_intel_init },
8187 { 8, alc889_ch8_intel_init },
8191 * 6ch mode
8193 static const struct hda_verb alc883_sixstack_ch6_init[] = {
8194 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8195 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8196 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8197 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8198 { } /* end */
8202 * 8ch mode
8204 static const struct hda_verb alc883_sixstack_ch8_init[] = {
8205 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8206 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8207 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8208 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8209 { } /* end */
8212 static const struct hda_channel_mode alc883_sixstack_modes[2] = {
8213 { 6, alc883_sixstack_ch6_init },
8214 { 8, alc883_sixstack_ch8_init },
8218 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
8219 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
8221 static const struct snd_kcontrol_new alc882_base_mixer[] = {
8222 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8223 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8224 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8225 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8226 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8227 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8228 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8229 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8230 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8231 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
8232 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8233 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8234 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8235 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8236 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8237 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8238 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
8239 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8240 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8241 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
8242 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8243 { } /* end */
8246 /* Macbook Air 2,1 same control for HP and internal Speaker */
8248 static const struct snd_kcontrol_new alc885_mba21_mixer[] = {
8249 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8250 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
8255 static const struct snd_kcontrol_new alc885_mbp3_mixer[] = {
8256 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8257 HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
8258 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
8259 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
8260 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
8261 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8262 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8263 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
8264 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
8265 HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
8266 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
8267 { } /* end */
8270 static const struct snd_kcontrol_new alc885_mb5_mixer[] = {
8271 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8272 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
8273 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
8274 HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
8275 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
8276 HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
8277 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
8278 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
8279 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
8280 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
8281 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
8282 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
8283 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
8284 HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT),
8285 { } /* end */
8288 static const struct snd_kcontrol_new alc885_macmini3_mixer[] = {
8289 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8290 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
8291 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
8292 HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
8293 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
8294 HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
8295 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
8296 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
8297 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
8298 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
8299 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
8300 { } /* end */
8303 static const struct snd_kcontrol_new alc885_imac91_mixer[] = {
8304 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8305 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
8306 { } /* end */
8310 static const struct snd_kcontrol_new alc882_w2jc_mixer[] = {
8311 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8312 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8313 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8314 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8315 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8316 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8317 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8318 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
8319 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8320 { } /* end */
8323 static const struct snd_kcontrol_new alc882_targa_mixer[] = {
8324 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8325 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8326 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8327 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8328 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8329 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8330 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8331 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8332 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8333 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
8334 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8335 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8336 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
8337 { } /* end */
8340 /* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
8341 * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
8343 static const struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
8344 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8345 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8346 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8347 HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),
8348 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8349 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8350 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8351 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8352 HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),
8353 HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
8354 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8355 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8356 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
8357 { } /* end */
8360 static const struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
8361 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8362 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8363 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8364 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8365 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8366 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8367 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8368 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8369 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
8370 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8371 { } /* end */
8374 static const struct snd_kcontrol_new alc882_chmode_mixer[] = {
8376 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8377 .name = "Channel Mode",
8378 .info = alc_ch_mode_info,
8379 .get = alc_ch_mode_get,
8380 .put = alc_ch_mode_put,
8382 { } /* end */
8385 static const struct hda_verb alc882_base_init_verbs[] = {
8386 /* Front mixer: unmute input/output amp left and right (volume = 0) */
8387 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8388 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8389 /* Rear mixer */
8390 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8391 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8392 /* CLFE mixer */
8393 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8394 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8395 /* Side mixer */
8396 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8397 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8399 /* Front Pin: output 0 (0x0c) */
8400 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8401 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8402 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8403 /* Rear Pin: output 1 (0x0d) */
8404 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8405 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8406 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
8407 /* CLFE Pin: output 2 (0x0e) */
8408 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8409 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8410 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
8411 /* Side Pin: output 3 (0x0f) */
8412 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8413 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8414 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
8415 /* Mic (rear) pin: input vref at 80% */
8416 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8417 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8418 /* Front Mic pin: input vref at 80% */
8419 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8420 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8421 /* Line In pin: input */
8422 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8423 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8424 /* Line-2 In: Headphone output (output 0 - 0x0c) */
8425 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8426 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8427 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
8428 /* CD pin widget for input */
8429 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8431 /* FIXME: use matrix-type input source selection */
8432 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
8433 /* Input mixer2 */
8434 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8435 /* Input mixer3 */
8436 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8437 /* ADC2: mute amp left and right */
8438 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8439 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8440 /* ADC3: mute amp left and right */
8441 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8442 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8447 static const struct hda_verb alc882_adc1_init_verbs[] = {
8448 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
8449 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8450 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8451 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8452 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8453 /* ADC1: mute amp left and right */
8454 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8455 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8459 static const struct hda_verb alc882_eapd_verbs[] = {
8460 /* change to EAPD mode */
8461 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
8462 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
8466 static const struct hda_verb alc889_eapd_verbs[] = {
8467 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
8468 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
8472 static const struct hda_verb alc_hp15_unsol_verbs[] = {
8473 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
8474 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8478 static const struct hda_verb alc885_init_verbs[] = {
8479 /* Front mixer: unmute input/output amp left and right (volume = 0) */
8480 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8481 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8482 /* Rear mixer */
8483 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8484 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8485 /* CLFE mixer */
8486 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8487 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8488 /* Side mixer */
8489 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8490 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8492 /* Front HP Pin: output 0 (0x0c) */
8493 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8494 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8495 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8496 /* Front Pin: output 0 (0x0c) */
8497 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8498 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8499 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8500 /* Rear Pin: output 1 (0x0d) */
8501 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8502 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8503 {0x19, AC_VERB_SET_CONNECT_SEL, 0x01},
8504 /* CLFE Pin: output 2 (0x0e) */
8505 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8506 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8507 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
8508 /* Side Pin: output 3 (0x0f) */
8509 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8510 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8511 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
8512 /* Mic (rear) pin: input vref at 80% */
8513 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8514 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8515 /* Front Mic pin: input vref at 80% */
8516 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8517 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8518 /* Line In pin: input */
8519 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8520 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8522 /* Mixer elements: 0x18, , 0x1a, 0x1b */
8523 /* Input mixer1 */
8524 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8525 /* Input mixer2 */
8526 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8527 /* Input mixer3 */
8528 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8529 /* ADC2: mute amp left and right */
8530 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8531 /* ADC3: mute amp left and right */
8532 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8537 static const struct hda_verb alc885_init_input_verbs[] = {
8538 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8539 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8540 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8545 /* Unmute Selector 24h and set the default input to front mic */
8546 static const struct hda_verb alc889_init_input_verbs[] = {
8547 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
8548 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8553 #define alc883_init_verbs alc882_base_init_verbs
8555 /* Mac Pro test */
8556 static const struct snd_kcontrol_new alc882_macpro_mixer[] = {
8557 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8558 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8559 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
8560 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
8561 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
8562 /* FIXME: this looks suspicious...
8563 HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x02, HDA_INPUT),
8564 HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x02, HDA_INPUT),
8566 { } /* end */
8569 static const struct hda_verb alc882_macpro_init_verbs[] = {
8570 /* Front mixer: unmute input/output amp left and right (volume = 0) */
8571 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8572 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8573 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8574 /* Front Pin: output 0 (0x0c) */
8575 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8576 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8577 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8578 /* Front Mic pin: input vref at 80% */
8579 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8580 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8581 /* Speaker: output */
8582 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8583 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8584 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
8585 /* Headphone output (output 0 - 0x0c) */
8586 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8587 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8588 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8590 /* FIXME: use matrix-type input source selection */
8591 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
8592 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
8593 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8594 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8595 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8596 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8597 /* Input mixer2 */
8598 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8599 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8600 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8601 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8602 /* Input mixer3 */
8603 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8604 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8605 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8606 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8607 /* ADC1: mute amp left and right */
8608 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8609 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8610 /* ADC2: mute amp left and right */
8611 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8612 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8613 /* ADC3: mute amp left and right */
8614 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8615 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8620 /* Macbook 5,1 */
8621 static const struct hda_verb alc885_mb5_init_verbs[] = {
8622 /* DACs */
8623 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8624 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8625 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8626 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8627 /* Front mixer */
8628 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8629 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8630 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8631 /* Surround mixer */
8632 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8633 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8634 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8635 /* LFE mixer */
8636 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8637 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8638 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8639 /* HP mixer */
8640 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8641 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8642 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8643 /* Front Pin (0x0c) */
8644 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8645 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8646 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8647 /* LFE Pin (0x0e) */
8648 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8649 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8650 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
8651 /* HP Pin (0x0f) */
8652 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8653 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8654 {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
8655 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8656 /* Front Mic pin: input vref at 80% */
8657 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8658 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8659 /* Line In pin */
8660 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8661 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8663 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
8664 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
8665 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
8669 /* Macmini 3,1 */
8670 static const struct hda_verb alc885_macmini3_init_verbs[] = {
8671 /* DACs */
8672 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8673 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8674 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8675 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8676 /* Front mixer */
8677 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8678 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8679 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8680 /* Surround mixer */
8681 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8682 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8683 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8684 /* LFE mixer */
8685 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8686 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8687 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8688 /* HP mixer */
8689 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8690 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8691 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8692 /* Front Pin (0x0c) */
8693 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8694 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8695 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8696 /* LFE Pin (0x0e) */
8697 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8698 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8699 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
8700 /* HP Pin (0x0f) */
8701 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8702 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8703 {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
8704 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8705 /* Line In pin */
8706 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8707 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8709 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8710 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8711 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8712 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8717 static const struct hda_verb alc885_mba21_init_verbs[] = {
8718 /*Internal and HP Speaker Mixer*/
8719 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8720 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8721 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8722 /*Internal Speaker Pin (0x0c)*/
8723 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
8724 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8725 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8726 /* HP Pin: output 0 (0x0e) */
8727 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
8728 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8729 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8730 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
8731 /* Line in (is hp when jack connected)*/
8732 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
8733 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8739 /* Macbook Pro rev3 */
8740 static const struct hda_verb alc885_mbp3_init_verbs[] = {
8741 /* Front mixer: unmute input/output amp left and right (volume = 0) */
8742 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8743 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8744 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8745 /* Rear mixer */
8746 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8747 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8748 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8749 /* HP mixer */
8750 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8751 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8752 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8753 /* Front Pin: output 0 (0x0c) */
8754 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8755 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8756 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8757 /* HP Pin: output 0 (0x0e) */
8758 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
8759 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8760 {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
8761 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8762 /* Mic (rear) pin: input vref at 80% */
8763 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8764 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8765 /* Front Mic pin: input vref at 80% */
8766 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8767 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8768 /* Line In pin: use output 1 when in LineOut mode */
8769 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8770 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8771 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
8773 /* FIXME: use matrix-type input source selection */
8774 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
8775 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
8776 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8777 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8778 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8779 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8780 /* Input mixer2 */
8781 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8782 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8783 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8784 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8785 /* Input mixer3 */
8786 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8787 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8788 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8789 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8790 /* ADC1: mute amp left and right */
8791 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8792 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8793 /* ADC2: mute amp left and right */
8794 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8795 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8796 /* ADC3: mute amp left and right */
8797 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8798 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8803 /* iMac 9,1 */
8804 static const struct hda_verb alc885_imac91_init_verbs[] = {
8805 /* Internal Speaker Pin (0x0c) */
8806 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
8807 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8808 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8809 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
8810 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8811 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
8812 /* HP Pin: Rear */
8813 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8814 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8815 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8816 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
8817 /* Line in Rear */
8818 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
8819 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8820 /* Front Mic pin: input vref at 80% */
8821 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8822 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8823 /* Rear mixer */
8824 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8825 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8826 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8827 /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
8828 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8829 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8830 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8831 /* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
8832 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8833 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8834 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8835 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8836 /* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
8837 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8838 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8839 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8840 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8841 /* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
8842 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8843 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8844 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8845 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8846 /* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
8847 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8848 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8849 /* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
8850 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8851 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8852 /* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
8853 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8854 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8858 /* iMac 24 mixer. */
8859 static const struct snd_kcontrol_new alc885_imac24_mixer[] = {
8860 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8861 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
8862 { } /* end */
8865 /* iMac 24 init verbs. */
8866 static const struct hda_verb alc885_imac24_init_verbs[] = {
8867 /* Internal speakers: output 0 (0x0c) */
8868 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8869 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8870 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8871 /* Internal speakers: output 0 (0x0c) */
8872 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8873 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8874 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
8875 /* Headphone: output 0 (0x0c) */
8876 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8877 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8878 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8879 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8880 /* Front Mic: input vref at 80% */
8881 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8882 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8886 /* Toggle speaker-output according to the hp-jack state */
8887 static void alc885_imac24_setup(struct hda_codec *codec)
8889 struct alc_spec *spec = codec->spec;
8891 spec->autocfg.hp_pins[0] = 0x14;
8892 spec->autocfg.speaker_pins[0] = 0x18;
8893 spec->autocfg.speaker_pins[1] = 0x1a;
8894 spec->automute = 1;
8895 spec->automute_mode = ALC_AUTOMUTE_AMP;
8898 #define alc885_mb5_setup alc885_imac24_setup
8899 #define alc885_macmini3_setup alc885_imac24_setup
8901 /* Macbook Air 2,1 */
8902 static void alc885_mba21_setup(struct hda_codec *codec)
8904 struct alc_spec *spec = codec->spec;
8906 spec->autocfg.hp_pins[0] = 0x14;
8907 spec->autocfg.speaker_pins[0] = 0x18;
8908 spec->automute = 1;
8909 spec->automute_mode = ALC_AUTOMUTE_AMP;
8914 static void alc885_mbp3_setup(struct hda_codec *codec)
8916 struct alc_spec *spec = codec->spec;
8918 spec->autocfg.hp_pins[0] = 0x15;
8919 spec->autocfg.speaker_pins[0] = 0x14;
8920 spec->automute = 1;
8921 spec->automute_mode = ALC_AUTOMUTE_AMP;
8924 static void alc885_imac91_setup(struct hda_codec *codec)
8926 struct alc_spec *spec = codec->spec;
8928 spec->autocfg.hp_pins[0] = 0x14;
8929 spec->autocfg.speaker_pins[0] = 0x18;
8930 spec->autocfg.speaker_pins[1] = 0x1a;
8931 spec->automute = 1;
8932 spec->automute_mode = ALC_AUTOMUTE_AMP;
8935 static const struct hda_verb alc882_targa_verbs[] = {
8936 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8937 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8939 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8940 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8942 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
8943 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
8944 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8946 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8947 { } /* end */
8950 /* toggle speaker-output according to the hp-jack state */
8951 static void alc882_targa_automute(struct hda_codec *codec)
8953 struct alc_spec *spec = codec->spec;
8954 alc_hp_automute(codec);
8955 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
8956 spec->jack_present ? 1 : 3);
8959 static void alc882_targa_setup(struct hda_codec *codec)
8961 struct alc_spec *spec = codec->spec;
8963 spec->autocfg.hp_pins[0] = 0x14;
8964 spec->autocfg.speaker_pins[0] = 0x1b;
8965 spec->automute = 1;
8966 spec->automute_mode = ALC_AUTOMUTE_AMP;
8969 static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
8971 if ((res >> 26) == ALC880_HP_EVENT)
8972 alc882_targa_automute(codec);
8975 static const struct hda_verb alc882_asus_a7j_verbs[] = {
8976 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8977 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8979 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8980 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8981 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8983 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8984 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8985 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8987 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
8988 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
8989 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8990 { } /* end */
8993 static const struct hda_verb alc882_asus_a7m_verbs[] = {
8994 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8995 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8997 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8998 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8999 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9001 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
9002 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
9003 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
9005 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
9006 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
9007 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
9008 { } /* end */
9011 static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
9013 unsigned int gpiostate, gpiomask, gpiodir;
9015 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
9016 AC_VERB_GET_GPIO_DATA, 0);
9018 if (!muted)
9019 gpiostate |= (1 << pin);
9020 else
9021 gpiostate &= ~(1 << pin);
9023 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
9024 AC_VERB_GET_GPIO_MASK, 0);
9025 gpiomask |= (1 << pin);
9027 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
9028 AC_VERB_GET_GPIO_DIRECTION, 0);
9029 gpiodir |= (1 << pin);
9032 snd_hda_codec_write(codec, codec->afg, 0,
9033 AC_VERB_SET_GPIO_MASK, gpiomask);
9034 snd_hda_codec_write(codec, codec->afg, 0,
9035 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
9037 msleep(1);
9039 snd_hda_codec_write(codec, codec->afg, 0,
9040 AC_VERB_SET_GPIO_DATA, gpiostate);
9043 /* set up GPIO at initialization */
9044 static void alc885_macpro_init_hook(struct hda_codec *codec)
9046 alc882_gpio_mute(codec, 0, 0);
9047 alc882_gpio_mute(codec, 1, 0);
9050 /* set up GPIO and update auto-muting at initialization */
9051 static void alc885_imac24_init_hook(struct hda_codec *codec)
9053 alc885_macpro_init_hook(codec);
9054 alc_hp_automute(codec);
9058 * generic initialization of ADC, input mixers and output mixers
9060 static const struct hda_verb alc883_auto_init_verbs[] = {
9062 * Unmute ADC0-2 and set the default input to mic-in
9064 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
9065 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9066 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
9067 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9070 * Set up output mixers (0x0c - 0x0f)
9072 /* set vol=0 to output mixers */
9073 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9074 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9075 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9076 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9077 /* set up input amps for analog loopback */
9078 /* Amp Indices: DAC = 0, mixer = 1 */
9079 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9080 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9081 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9082 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9083 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9084 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9085 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9086 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9087 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9088 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9090 /* FIXME: use matrix-type input source selection */
9091 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
9092 /* Input mixer2 */
9093 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9094 /* Input mixer3 */
9095 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9099 /* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
9100 static const struct hda_verb alc889A_mb31_ch2_init[] = {
9101 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
9102 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
9103 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
9104 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
9105 { } /* end */
9108 /* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
9109 static const struct hda_verb alc889A_mb31_ch4_init[] = {
9110 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
9111 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
9112 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
9113 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
9114 { } /* end */
9117 /* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
9118 static const struct hda_verb alc889A_mb31_ch5_init[] = {
9119 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */
9120 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
9121 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
9122 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
9123 { } /* end */
9126 /* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
9127 static const struct hda_verb alc889A_mb31_ch6_init[] = {
9128 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */
9129 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */
9130 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
9131 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
9132 { } /* end */
9135 static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
9136 { 2, alc889A_mb31_ch2_init },
9137 { 4, alc889A_mb31_ch4_init },
9138 { 5, alc889A_mb31_ch5_init },
9139 { 6, alc889A_mb31_ch6_init },
9142 static const struct hda_verb alc883_medion_eapd_verbs[] = {
9143 /* eanable EAPD on medion laptop */
9144 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
9145 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
9149 #define alc883_base_mixer alc882_base_mixer
9151 static const struct snd_kcontrol_new alc883_mitac_mixer[] = {
9152 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9153 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9154 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
9155 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9156 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9157 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9158 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9159 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9160 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9161 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9162 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9163 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
9164 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9165 { } /* end */
9168 static const struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
9169 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9170 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
9171 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9172 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
9173 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9174 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9175 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9176 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9177 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
9178 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9179 { } /* end */
9182 static const struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
9183 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9184 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
9185 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9186 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
9187 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9188 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9189 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9190 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9191 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
9192 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9193 { } /* end */
9196 static const struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
9197 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9198 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9199 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9200 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9201 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9202 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9203 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9204 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9205 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9206 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9207 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9208 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
9209 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9210 { } /* end */
9213 static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
9214 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9215 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9216 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9217 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9218 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
9219 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9220 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9221 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9222 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9223 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9224 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9225 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9226 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9227 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9228 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9229 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9230 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9231 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
9232 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9233 { } /* end */
9236 static const struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
9237 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9238 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9239 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9240 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9241 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
9242 HDA_OUTPUT),
9243 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9244 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9245 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9246 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9247 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9248 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9249 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9250 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9251 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9252 HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
9253 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9254 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9255 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT),
9256 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9257 { } /* end */
9260 static const struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
9261 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9262 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9263 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9264 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9265 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
9266 HDA_OUTPUT),
9267 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9268 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9269 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9270 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
9271 HDA_BIND_MUTE("Speaker Playback Switch", 0x0f, 2, HDA_INPUT),
9272 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9273 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9274 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9275 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
9276 HDA_CODEC_VOLUME("Mic Boost Volume", 0x1b, 0, HDA_INPUT),
9277 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
9278 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9279 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT),
9280 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9281 { } /* end */
9284 static const struct snd_kcontrol_new alc883_fivestack_mixer[] = {
9285 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9286 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9287 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9288 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9289 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
9290 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9291 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9292 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9293 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9294 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9295 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9296 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9297 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9298 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9299 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9300 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9301 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9302 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
9303 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9304 { } /* end */
9307 static const struct snd_kcontrol_new alc883_targa_mixer[] = {
9308 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9309 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9310 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9311 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9312 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9313 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9314 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
9315 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9316 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9317 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9318 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9319 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9320 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9321 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9322 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9323 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9324 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9325 { } /* end */
9328 static const struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
9329 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9330 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9331 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9332 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9333 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9334 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9335 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9336 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9337 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9338 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9339 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
9340 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9341 { } /* end */
9344 static const struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
9345 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
9346 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
9347 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9348 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
9349 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9350 { } /* end */
9353 static const struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
9354 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9355 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9356 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9357 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
9358 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9359 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9360 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9361 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9362 { } /* end */
9365 static const struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
9366 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9367 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
9368 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9369 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9370 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9371 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9372 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9373 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9374 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9375 { } /* end */
9378 static const struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
9379 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9380 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9381 HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9382 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
9383 HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT),
9384 HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT),
9385 { } /* end */
9388 static const struct hda_verb alc883_medion_wim2160_verbs[] = {
9389 /* Unmute front mixer */
9390 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9391 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9393 /* Set speaker pin to front mixer */
9394 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9396 /* Init headphone pin */
9397 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9398 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9399 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
9400 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9402 { } /* end */
9405 /* toggle speaker-output according to the hp-jack state */
9406 static void alc883_medion_wim2160_setup(struct hda_codec *codec)
9408 struct alc_spec *spec = codec->spec;
9410 spec->autocfg.hp_pins[0] = 0x1a;
9411 spec->autocfg.speaker_pins[0] = 0x15;
9412 spec->automute = 1;
9413 spec->automute_mode = ALC_AUTOMUTE_AMP;
9416 static const struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
9417 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9418 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9419 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9420 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9421 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9422 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9423 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9424 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9425 { } /* end */
9428 static const struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
9429 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9430 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
9431 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9432 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9433 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9434 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9435 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9436 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9437 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9438 { } /* end */
9441 static const struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
9442 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9443 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9444 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
9445 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
9446 HDA_CODEC_VOLUME_MONO("Center Playback Volume",
9447 0x0d, 1, 0x0, HDA_OUTPUT),
9448 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
9449 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
9450 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
9451 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
9452 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
9453 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9454 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9455 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9456 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9457 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9458 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9459 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9460 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9461 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
9462 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9463 { } /* end */
9466 static const struct snd_kcontrol_new alc889A_mb31_mixer[] = {
9467 /* Output mixers */
9468 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
9469 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
9470 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
9471 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
9472 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00,
9473 HDA_OUTPUT),
9474 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT),
9475 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT),
9476 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT),
9477 /* Output switches */
9478 HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT),
9479 HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT),
9480 HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT),
9481 /* Boost mixers */
9482 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
9483 HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
9484 /* Input mixers */
9485 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
9486 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
9487 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9488 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9489 { } /* end */
9492 static const struct snd_kcontrol_new alc883_vaiott_mixer[] = {
9493 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9494 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9495 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9496 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9497 HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
9498 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9499 { } /* end */
9502 static const struct hda_bind_ctls alc883_bind_cap_vol = {
9503 .ops = &snd_hda_bind_vol,
9504 .values = {
9505 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
9506 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
9511 static const struct hda_bind_ctls alc883_bind_cap_switch = {
9512 .ops = &snd_hda_bind_sw,
9513 .values = {
9514 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
9515 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
9520 static const struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
9521 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9522 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9523 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9524 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9525 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9526 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9527 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9528 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9529 { } /* end */
9532 static const struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
9533 HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
9534 HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
9536 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9537 /* .name = "Capture Source", */
9538 .name = "Input Source",
9539 .count = 1,
9540 .info = alc_mux_enum_info,
9541 .get = alc_mux_enum_get,
9542 .put = alc_mux_enum_put,
9544 { } /* end */
9547 static const struct snd_kcontrol_new alc883_chmode_mixer[] = {
9549 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9550 .name = "Channel Mode",
9551 .info = alc_ch_mode_info,
9552 .get = alc_ch_mode_get,
9553 .put = alc_ch_mode_put,
9555 { } /* end */
9558 /* toggle speaker-output according to the hp-jack state */
9559 static void alc883_mitac_setup(struct hda_codec *codec)
9561 struct alc_spec *spec = codec->spec;
9563 spec->autocfg.hp_pins[0] = 0x15;
9564 spec->autocfg.speaker_pins[0] = 0x14;
9565 spec->autocfg.speaker_pins[1] = 0x17;
9566 spec->automute = 1;
9567 spec->automute_mode = ALC_AUTOMUTE_AMP;
9570 static const struct hda_verb alc883_mitac_verbs[] = {
9571 /* HP */
9572 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9573 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9574 /* Subwoofer */
9575 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
9576 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9578 /* enable unsolicited event */
9579 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9580 /* {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, */
9582 { } /* end */
9585 static const struct hda_verb alc883_clevo_m540r_verbs[] = {
9586 /* HP */
9587 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9588 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9589 /* Int speaker */
9590 /*{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},*/
9592 /* enable unsolicited event */
9594 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9595 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
9598 { } /* end */
9601 static const struct hda_verb alc883_clevo_m720_verbs[] = {
9602 /* HP */
9603 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9604 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9605 /* Int speaker */
9606 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
9607 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9609 /* enable unsolicited event */
9610 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9611 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
9613 { } /* end */
9616 static const struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
9617 /* HP */
9618 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9619 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9620 /* Subwoofer */
9621 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
9622 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9624 /* enable unsolicited event */
9625 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9627 { } /* end */
9630 static const struct hda_verb alc883_targa_verbs[] = {
9631 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9632 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9634 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9635 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9637 /* Connect Line-Out side jack (SPDIF) to Side */
9638 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9639 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9640 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
9641 /* Connect Mic jack to CLFE */
9642 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9643 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9644 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
9645 /* Connect Line-in jack to Surround */
9646 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9647 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9648 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
9649 /* Connect HP out jack to Front */
9650 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9651 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9652 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9654 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9656 { } /* end */
9659 static const struct hda_verb alc883_lenovo_101e_verbs[] = {
9660 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9661 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},
9662 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},
9663 { } /* end */
9666 static const struct hda_verb alc883_lenovo_nb0763_verbs[] = {
9667 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9668 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9669 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9670 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9671 { } /* end */
9674 static const struct hda_verb alc888_lenovo_ms7195_verbs[] = {
9675 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9676 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9677 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9678 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN},
9679 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9680 { } /* end */
9683 static const struct hda_verb alc883_haier_w66_verbs[] = {
9684 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9685 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9687 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9689 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9690 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9691 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9692 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9693 { } /* end */
9696 static const struct hda_verb alc888_lenovo_sky_verbs[] = {
9697 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9698 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9699 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9700 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9701 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9702 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9703 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
9704 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9705 { } /* end */
9708 static const struct hda_verb alc888_6st_dell_verbs[] = {
9709 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9713 static const struct hda_verb alc883_vaiott_verbs[] = {
9714 /* HP */
9715 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9716 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9718 /* enable unsolicited event */
9719 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9721 { } /* end */
9724 static void alc888_3st_hp_setup(struct hda_codec *codec)
9726 struct alc_spec *spec = codec->spec;
9728 spec->autocfg.hp_pins[0] = 0x1b;
9729 spec->autocfg.speaker_pins[0] = 0x14;
9730 spec->autocfg.speaker_pins[1] = 0x16;
9731 spec->autocfg.speaker_pins[2] = 0x18;
9732 spec->automute = 1;
9733 spec->automute_mode = ALC_AUTOMUTE_AMP;
9736 static const struct hda_verb alc888_3st_hp_verbs[] = {
9737 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
9738 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */
9739 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */
9740 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9741 { } /* end */
9745 * 2ch mode
9747 static const struct hda_verb alc888_3st_hp_2ch_init[] = {
9748 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
9749 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9750 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
9751 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9752 { } /* end */
9756 * 4ch mode
9758 static const struct hda_verb alc888_3st_hp_4ch_init[] = {
9759 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
9760 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9761 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9762 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9763 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
9764 { } /* end */
9768 * 6ch mode
9770 static const struct hda_verb alc888_3st_hp_6ch_init[] = {
9771 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9772 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9773 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
9774 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9775 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9776 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
9777 { } /* end */
9780 static const struct hda_channel_mode alc888_3st_hp_modes[3] = {
9781 { 2, alc888_3st_hp_2ch_init },
9782 { 4, alc888_3st_hp_4ch_init },
9783 { 6, alc888_3st_hp_6ch_init },
9786 static void alc888_lenovo_ms7195_setup(struct hda_codec *codec)
9788 struct alc_spec *spec = codec->spec;
9790 spec->autocfg.hp_pins[0] = 0x1b;
9791 spec->autocfg.line_out_pins[0] = 0x14;
9792 spec->autocfg.speaker_pins[0] = 0x15;
9793 spec->automute = 1;
9794 spec->automute_mode = ALC_AUTOMUTE_AMP;
9797 /* toggle speaker-output according to the hp-jack state */
9798 static void alc883_lenovo_nb0763_setup(struct hda_codec *codec)
9800 struct alc_spec *spec = codec->spec;
9802 spec->autocfg.hp_pins[0] = 0x14;
9803 spec->autocfg.speaker_pins[0] = 0x15;
9804 spec->automute = 1;
9805 spec->automute_mode = ALC_AUTOMUTE_AMP;
9808 /* toggle speaker-output according to the hp-jack state */
9809 #define alc883_targa_init_hook alc882_targa_init_hook
9810 #define alc883_targa_unsol_event alc882_targa_unsol_event
9812 static void alc883_clevo_m720_setup(struct hda_codec *codec)
9814 struct alc_spec *spec = codec->spec;
9816 spec->autocfg.hp_pins[0] = 0x15;
9817 spec->autocfg.speaker_pins[0] = 0x14;
9818 spec->automute = 1;
9819 spec->automute_mode = ALC_AUTOMUTE_AMP;
9822 static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
9824 alc_hp_automute(codec);
9825 alc88x_simple_mic_automute(codec);
9828 static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
9829 unsigned int res)
9831 switch (res >> 26) {
9832 case ALC880_MIC_EVENT:
9833 alc88x_simple_mic_automute(codec);
9834 break;
9835 default:
9836 alc_sku_unsol_event(codec, res);
9837 break;
9841 /* toggle speaker-output according to the hp-jack state */
9842 static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
9844 struct alc_spec *spec = codec->spec;
9846 spec->autocfg.hp_pins[0] = 0x14;
9847 spec->autocfg.speaker_pins[0] = 0x15;
9848 spec->automute = 1;
9849 spec->automute_mode = ALC_AUTOMUTE_AMP;
9852 static void alc883_haier_w66_setup(struct hda_codec *codec)
9854 struct alc_spec *spec = codec->spec;
9856 spec->autocfg.hp_pins[0] = 0x1b;
9857 spec->autocfg.speaker_pins[0] = 0x14;
9858 spec->automute = 1;
9859 spec->automute_mode = ALC_AUTOMUTE_AMP;
9862 static void alc883_lenovo_101e_setup(struct hda_codec *codec)
9864 struct alc_spec *spec = codec->spec;
9866 spec->autocfg.hp_pins[0] = 0x1b;
9867 spec->autocfg.line_out_pins[0] = 0x14;
9868 spec->autocfg.speaker_pins[0] = 0x15;
9869 spec->automute = 1;
9870 spec->detect_line = 1;
9871 spec->automute_lines = 1;
9872 spec->automute_mode = ALC_AUTOMUTE_AMP;
9875 /* toggle speaker-output according to the hp-jack state */
9876 static void alc883_acer_aspire_setup(struct hda_codec *codec)
9878 struct alc_spec *spec = codec->spec;
9880 spec->autocfg.hp_pins[0] = 0x14;
9881 spec->autocfg.speaker_pins[0] = 0x15;
9882 spec->autocfg.speaker_pins[1] = 0x16;
9883 spec->automute = 1;
9884 spec->automute_mode = ALC_AUTOMUTE_AMP;
9887 static const struct hda_verb alc883_acer_eapd_verbs[] = {
9888 /* HP Pin: output 0 (0x0c) */
9889 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9890 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9891 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9892 /* Front Pin: output 0 (0x0c) */
9893 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9894 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9895 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9896 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
9897 /* eanable EAPD on medion laptop */
9898 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
9899 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
9900 /* enable unsolicited event */
9901 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9905 static void alc888_6st_dell_setup(struct hda_codec *codec)
9907 struct alc_spec *spec = codec->spec;
9909 spec->autocfg.hp_pins[0] = 0x1b;
9910 spec->autocfg.speaker_pins[0] = 0x14;
9911 spec->autocfg.speaker_pins[1] = 0x15;
9912 spec->autocfg.speaker_pins[2] = 0x16;
9913 spec->autocfg.speaker_pins[3] = 0x17;
9914 spec->automute = 1;
9915 spec->automute_mode = ALC_AUTOMUTE_AMP;
9918 static void alc888_lenovo_sky_setup(struct hda_codec *codec)
9920 struct alc_spec *spec = codec->spec;
9922 spec->autocfg.hp_pins[0] = 0x1b;
9923 spec->autocfg.speaker_pins[0] = 0x14;
9924 spec->autocfg.speaker_pins[1] = 0x15;
9925 spec->autocfg.speaker_pins[2] = 0x16;
9926 spec->autocfg.speaker_pins[3] = 0x17;
9927 spec->autocfg.speaker_pins[4] = 0x1a;
9928 spec->automute = 1;
9929 spec->automute_mode = ALC_AUTOMUTE_AMP;
9932 static void alc883_vaiott_setup(struct hda_codec *codec)
9934 struct alc_spec *spec = codec->spec;
9936 spec->autocfg.hp_pins[0] = 0x15;
9937 spec->autocfg.speaker_pins[0] = 0x14;
9938 spec->autocfg.speaker_pins[1] = 0x17;
9939 spec->automute = 1;
9940 spec->automute_mode = ALC_AUTOMUTE_AMP;
9943 static const struct hda_verb alc888_asus_m90v_verbs[] = {
9944 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9945 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9946 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9947 /* enable unsolicited event */
9948 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9949 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
9950 { } /* end */
9953 static void alc883_mode2_setup(struct hda_codec *codec)
9955 struct alc_spec *spec = codec->spec;
9957 spec->autocfg.hp_pins[0] = 0x1b;
9958 spec->autocfg.speaker_pins[0] = 0x14;
9959 spec->autocfg.speaker_pins[1] = 0x15;
9960 spec->autocfg.speaker_pins[2] = 0x16;
9961 spec->ext_mic.pin = 0x18;
9962 spec->int_mic.pin = 0x19;
9963 spec->ext_mic.mux_idx = 0;
9964 spec->int_mic.mux_idx = 1;
9965 spec->auto_mic = 1;
9966 spec->automute = 1;
9967 spec->automute_mode = ALC_AUTOMUTE_AMP;
9970 static const struct hda_verb alc888_asus_eee1601_verbs[] = {
9971 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9972 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9973 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9974 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9975 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9976 {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
9977 {0x20, AC_VERB_SET_PROC_COEF, 0x0838},
9978 /* enable unsolicited event */
9979 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9980 { } /* end */
9983 static void alc883_eee1601_inithook(struct hda_codec *codec)
9985 struct alc_spec *spec = codec->spec;
9987 spec->autocfg.hp_pins[0] = 0x14;
9988 spec->autocfg.speaker_pins[0] = 0x1b;
9989 alc_hp_automute(codec);
9992 static const struct hda_verb alc889A_mb31_verbs[] = {
9993 /* Init rear pin (used as headphone output) */
9994 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */
9995 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */
9996 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9997 /* Init line pin (used as output in 4ch and 6ch mode) */
9998 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Connect to CLFE */
9999 /* Init line 2 pin (used as headphone out by default) */
10000 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Use as input */
10001 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */
10002 { } /* end */
10005 /* Mute speakers according to the headphone jack state */
10006 static void alc889A_mb31_automute(struct hda_codec *codec)
10008 unsigned int present;
10010 /* Mute only in 2ch or 4ch mode */
10011 if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
10012 == 0x00) {
10013 present = snd_hda_jack_detect(codec, 0x15);
10014 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
10015 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
10016 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
10017 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
10021 static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
10023 if ((res >> 26) == ALC880_HP_EVENT)
10024 alc889A_mb31_automute(codec);
10028 #ifdef CONFIG_SND_HDA_POWER_SAVE
10029 #define alc882_loopbacks alc880_loopbacks
10030 #endif
10032 /* pcm configuration: identical with ALC880 */
10033 #define alc882_pcm_analog_playback alc880_pcm_analog_playback
10034 #define alc882_pcm_analog_capture alc880_pcm_analog_capture
10035 #define alc882_pcm_digital_playback alc880_pcm_digital_playback
10036 #define alc882_pcm_digital_capture alc880_pcm_digital_capture
10038 static const hda_nid_t alc883_slave_dig_outs[] = {
10039 ALC1200_DIGOUT_NID, 0,
10042 static const hda_nid_t alc1200_slave_dig_outs[] = {
10043 ALC883_DIGOUT_NID, 0,
10047 * configuration and preset
10049 static const char * const alc882_models[ALC882_MODEL_LAST] = {
10050 [ALC882_3ST_DIG] = "3stack-dig",
10051 [ALC882_6ST_DIG] = "6stack-dig",
10052 [ALC882_ARIMA] = "arima",
10053 [ALC882_W2JC] = "w2jc",
10054 [ALC882_TARGA] = "targa",
10055 [ALC882_ASUS_A7J] = "asus-a7j",
10056 [ALC882_ASUS_A7M] = "asus-a7m",
10057 [ALC885_MACPRO] = "macpro",
10058 [ALC885_MB5] = "mb5",
10059 [ALC885_MACMINI3] = "macmini3",
10060 [ALC885_MBA21] = "mba21",
10061 [ALC885_MBP3] = "mbp3",
10062 [ALC885_IMAC24] = "imac24",
10063 [ALC885_IMAC91] = "imac91",
10064 [ALC883_3ST_2ch_DIG] = "3stack-2ch-dig",
10065 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig",
10066 [ALC883_3ST_6ch] = "3stack-6ch",
10067 [ALC883_6ST_DIG] = "alc883-6stack-dig",
10068 [ALC883_TARGA_DIG] = "targa-dig",
10069 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
10070 [ALC883_TARGA_8ch_DIG] = "targa-8ch-dig",
10071 [ALC883_ACER] = "acer",
10072 [ALC883_ACER_ASPIRE] = "acer-aspire",
10073 [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g",
10074 [ALC888_ACER_ASPIRE_6530G] = "acer-aspire-6530g",
10075 [ALC888_ACER_ASPIRE_8930G] = "acer-aspire-8930g",
10076 [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g",
10077 [ALC883_MEDION] = "medion",
10078 [ALC883_MEDION_WIM2160] = "medion-wim2160",
10079 [ALC883_LAPTOP_EAPD] = "laptop-eapd",
10080 [ALC883_LENOVO_101E_2ch] = "lenovo-101e",
10081 [ALC883_LENOVO_NB0763] = "lenovo-nb0763",
10082 [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
10083 [ALC888_LENOVO_SKY] = "lenovo-sky",
10084 [ALC883_HAIER_W66] = "haier-w66",
10085 [ALC888_3ST_HP] = "3stack-hp",
10086 [ALC888_6ST_DELL] = "6stack-dell",
10087 [ALC883_MITAC] = "mitac",
10088 [ALC883_CLEVO_M540R] = "clevo-m540r",
10089 [ALC883_CLEVO_M720] = "clevo-m720",
10090 [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
10091 [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
10092 [ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel",
10093 [ALC889A_INTEL] = "intel-alc889a",
10094 [ALC889_INTEL] = "intel-x58",
10095 [ALC1200_ASUS_P5Q] = "asus-p5q",
10096 [ALC889A_MB31] = "mb31",
10097 [ALC883_SONY_VAIO_TT] = "sony-vaio-tt",
10098 [ALC882_AUTO] = "auto",
10101 static const struct snd_pci_quirk alc882_cfg_tbl[] = {
10102 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
10104 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
10105 SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
10106 SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE),
10107 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
10108 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
10109 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
10110 SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
10111 ALC888_ACER_ASPIRE_4930G),
10112 SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
10113 ALC888_ACER_ASPIRE_4930G),
10114 SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
10115 ALC888_ACER_ASPIRE_8930G),
10116 SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
10117 ALC888_ACER_ASPIRE_8930G),
10118 SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO),
10119 SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO),
10120 SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
10121 ALC888_ACER_ASPIRE_6530G),
10122 SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
10123 ALC888_ACER_ASPIRE_6530G),
10124 SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
10125 ALC888_ACER_ASPIRE_7730G),
10126 /* default Acer -- disabled as it causes more problems.
10127 * model=auto should work fine now
10129 /* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */
10131 SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
10133 SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavilion", ALC883_6ST_DIG),
10134 SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
10135 SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
10136 SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
10137 SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
10138 SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
10140 SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
10141 SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
10142 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
10143 SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
10144 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
10145 SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
10146 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
10147 SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
10148 SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
10149 SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
10150 SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
10152 SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT),
10153 SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
10154 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
10155 SND_PCI_QUIRK(0x1071, 0x8227, "Mitac 82801H", ALC883_MITAC),
10156 SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
10157 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
10158 SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
10159 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
10160 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
10162 SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
10163 SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
10164 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
10165 SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */
10166 SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
10167 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
10168 SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
10169 SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
10170 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
10171 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
10172 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
10173 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
10174 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
10175 SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
10176 SND_PCI_QUIRK(0x1462, 0x42cd, "MSI", ALC883_TARGA_DIG),
10177 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
10178 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
10179 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
10180 SND_PCI_QUIRK(0x1462, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG),
10181 SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG),
10182 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
10183 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
10184 SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
10185 SND_PCI_QUIRK(0x1462, 0x7260, "MSI 7260", ALC883_TARGA_DIG),
10186 SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
10187 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
10188 SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
10189 SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
10190 SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG),
10191 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
10192 SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
10194 SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
10195 SND_PCI_QUIRK(0x1558, 0x0571, "Clevo laptop M570U", ALC883_3ST_6ch_DIG),
10196 SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
10197 SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
10198 SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R),
10199 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
10200 SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
10201 /* SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), */
10202 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
10203 SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
10204 ALC883_FUJITSU_PI2515),
10205 SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx",
10206 ALC888_FUJITSU_XA3530),
10207 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
10208 SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
10209 SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
10210 SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
10211 SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY),
10212 SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
10213 SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
10214 SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
10216 SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
10217 SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
10218 SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC),
10219 SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
10220 SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
10221 SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
10222 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG),
10227 /* codec SSID table for Intel Mac */
10228 static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
10229 SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
10230 SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
10231 SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
10232 SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_MACPRO),
10233 SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
10234 SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
10235 SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
10236 SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
10237 SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_ASUS_A7M),
10238 SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3),
10239 SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21),
10240 SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
10241 SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
10242 SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
10243 SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
10244 SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
10245 SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5),
10246 /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
10247 * so apparently no perfect solution yet
10249 SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
10250 SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
10251 SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
10252 {} /* terminator */
10255 static const struct alc_config_preset alc882_presets[] = {
10256 [ALC882_3ST_DIG] = {
10257 .mixers = { alc882_base_mixer },
10258 .init_verbs = { alc882_base_init_verbs,
10259 alc882_adc1_init_verbs },
10260 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10261 .dac_nids = alc882_dac_nids,
10262 .dig_out_nid = ALC882_DIGOUT_NID,
10263 .dig_in_nid = ALC882_DIGIN_NID,
10264 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
10265 .channel_mode = alc882_ch_modes,
10266 .need_dac_fix = 1,
10267 .input_mux = &alc882_capture_source,
10269 [ALC882_6ST_DIG] = {
10270 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
10271 .init_verbs = { alc882_base_init_verbs,
10272 alc882_adc1_init_verbs },
10273 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10274 .dac_nids = alc882_dac_nids,
10275 .dig_out_nid = ALC882_DIGOUT_NID,
10276 .dig_in_nid = ALC882_DIGIN_NID,
10277 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
10278 .channel_mode = alc882_sixstack_modes,
10279 .input_mux = &alc882_capture_source,
10281 [ALC882_ARIMA] = {
10282 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
10283 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
10284 alc882_eapd_verbs },
10285 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10286 .dac_nids = alc882_dac_nids,
10287 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
10288 .channel_mode = alc882_sixstack_modes,
10289 .input_mux = &alc882_capture_source,
10291 [ALC882_W2JC] = {
10292 .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
10293 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
10294 alc882_eapd_verbs, alc880_gpio1_init_verbs },
10295 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10296 .dac_nids = alc882_dac_nids,
10297 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
10298 .channel_mode = alc880_threestack_modes,
10299 .need_dac_fix = 1,
10300 .input_mux = &alc882_capture_source,
10301 .dig_out_nid = ALC882_DIGOUT_NID,
10303 [ALC885_MBA21] = {
10304 .mixers = { alc885_mba21_mixer },
10305 .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
10306 .num_dacs = 2,
10307 .dac_nids = alc882_dac_nids,
10308 .channel_mode = alc885_mba21_ch_modes,
10309 .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
10310 .input_mux = &alc882_capture_source,
10311 .unsol_event = alc_sku_unsol_event,
10312 .setup = alc885_mba21_setup,
10313 .init_hook = alc_hp_automute,
10315 [ALC885_MBP3] = {
10316 .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
10317 .init_verbs = { alc885_mbp3_init_verbs,
10318 alc880_gpio1_init_verbs },
10319 .num_dacs = 2,
10320 .dac_nids = alc882_dac_nids,
10321 .hp_nid = 0x04,
10322 .channel_mode = alc885_mbp_4ch_modes,
10323 .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
10324 .input_mux = &alc882_capture_source,
10325 .dig_out_nid = ALC882_DIGOUT_NID,
10326 .dig_in_nid = ALC882_DIGIN_NID,
10327 .unsol_event = alc_sku_unsol_event,
10328 .setup = alc885_mbp3_setup,
10329 .init_hook = alc_hp_automute,
10331 [ALC885_MB5] = {
10332 .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
10333 .init_verbs = { alc885_mb5_init_verbs,
10334 alc880_gpio1_init_verbs },
10335 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10336 .dac_nids = alc882_dac_nids,
10337 .channel_mode = alc885_mb5_6ch_modes,
10338 .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
10339 .input_mux = &mb5_capture_source,
10340 .dig_out_nid = ALC882_DIGOUT_NID,
10341 .dig_in_nid = ALC882_DIGIN_NID,
10342 .unsol_event = alc_sku_unsol_event,
10343 .setup = alc885_mb5_setup,
10344 .init_hook = alc_hp_automute,
10346 [ALC885_MACMINI3] = {
10347 .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
10348 .init_verbs = { alc885_macmini3_init_verbs,
10349 alc880_gpio1_init_verbs },
10350 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10351 .dac_nids = alc882_dac_nids,
10352 .channel_mode = alc885_macmini3_6ch_modes,
10353 .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
10354 .input_mux = &macmini3_capture_source,
10355 .dig_out_nid = ALC882_DIGOUT_NID,
10356 .dig_in_nid = ALC882_DIGIN_NID,
10357 .unsol_event = alc_sku_unsol_event,
10358 .setup = alc885_macmini3_setup,
10359 .init_hook = alc_hp_automute,
10361 [ALC885_MACPRO] = {
10362 .mixers = { alc882_macpro_mixer },
10363 .init_verbs = { alc882_macpro_init_verbs },
10364 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10365 .dac_nids = alc882_dac_nids,
10366 .dig_out_nid = ALC882_DIGOUT_NID,
10367 .dig_in_nid = ALC882_DIGIN_NID,
10368 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
10369 .channel_mode = alc882_ch_modes,
10370 .input_mux = &alc882_capture_source,
10371 .init_hook = alc885_macpro_init_hook,
10373 [ALC885_IMAC24] = {
10374 .mixers = { alc885_imac24_mixer },
10375 .init_verbs = { alc885_imac24_init_verbs },
10376 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10377 .dac_nids = alc882_dac_nids,
10378 .dig_out_nid = ALC882_DIGOUT_NID,
10379 .dig_in_nid = ALC882_DIGIN_NID,
10380 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
10381 .channel_mode = alc882_ch_modes,
10382 .input_mux = &alc882_capture_source,
10383 .unsol_event = alc_sku_unsol_event,
10384 .setup = alc885_imac24_setup,
10385 .init_hook = alc885_imac24_init_hook,
10387 [ALC885_IMAC91] = {
10388 .mixers = {alc885_imac91_mixer},
10389 .init_verbs = { alc885_imac91_init_verbs,
10390 alc880_gpio1_init_verbs },
10391 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10392 .dac_nids = alc882_dac_nids,
10393 .channel_mode = alc885_mba21_ch_modes,
10394 .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
10395 .input_mux = &alc889A_imac91_capture_source,
10396 .dig_out_nid = ALC882_DIGOUT_NID,
10397 .dig_in_nid = ALC882_DIGIN_NID,
10398 .unsol_event = alc_sku_unsol_event,
10399 .setup = alc885_imac91_setup,
10400 .init_hook = alc_hp_automute,
10402 [ALC882_TARGA] = {
10403 .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
10404 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
10405 alc880_gpio3_init_verbs, alc882_targa_verbs},
10406 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10407 .dac_nids = alc882_dac_nids,
10408 .dig_out_nid = ALC882_DIGOUT_NID,
10409 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
10410 .adc_nids = alc882_adc_nids,
10411 .capsrc_nids = alc882_capsrc_nids,
10412 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
10413 .channel_mode = alc882_3ST_6ch_modes,
10414 .need_dac_fix = 1,
10415 .input_mux = &alc882_capture_source,
10416 .unsol_event = alc_sku_unsol_event,
10417 .setup = alc882_targa_setup,
10418 .init_hook = alc882_targa_automute,
10420 [ALC882_ASUS_A7J] = {
10421 .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
10422 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
10423 alc882_asus_a7j_verbs},
10424 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10425 .dac_nids = alc882_dac_nids,
10426 .dig_out_nid = ALC882_DIGOUT_NID,
10427 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
10428 .adc_nids = alc882_adc_nids,
10429 .capsrc_nids = alc882_capsrc_nids,
10430 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
10431 .channel_mode = alc882_3ST_6ch_modes,
10432 .need_dac_fix = 1,
10433 .input_mux = &alc882_capture_source,
10435 [ALC882_ASUS_A7M] = {
10436 .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
10437 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
10438 alc882_eapd_verbs, alc880_gpio1_init_verbs,
10439 alc882_asus_a7m_verbs },
10440 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10441 .dac_nids = alc882_dac_nids,
10442 .dig_out_nid = ALC882_DIGOUT_NID,
10443 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
10444 .channel_mode = alc880_threestack_modes,
10445 .need_dac_fix = 1,
10446 .input_mux = &alc882_capture_source,
10448 [ALC883_3ST_2ch_DIG] = {
10449 .mixers = { alc883_3ST_2ch_mixer },
10450 .init_verbs = { alc883_init_verbs },
10451 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10452 .dac_nids = alc883_dac_nids,
10453 .dig_out_nid = ALC883_DIGOUT_NID,
10454 .dig_in_nid = ALC883_DIGIN_NID,
10455 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10456 .channel_mode = alc883_3ST_2ch_modes,
10457 .input_mux = &alc883_capture_source,
10459 [ALC883_3ST_6ch_DIG] = {
10460 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10461 .init_verbs = { alc883_init_verbs },
10462 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10463 .dac_nids = alc883_dac_nids,
10464 .dig_out_nid = ALC883_DIGOUT_NID,
10465 .dig_in_nid = ALC883_DIGIN_NID,
10466 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10467 .channel_mode = alc883_3ST_6ch_modes,
10468 .need_dac_fix = 1,
10469 .input_mux = &alc883_capture_source,
10471 [ALC883_3ST_6ch] = {
10472 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10473 .init_verbs = { alc883_init_verbs },
10474 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10475 .dac_nids = alc883_dac_nids,
10476 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10477 .channel_mode = alc883_3ST_6ch_modes,
10478 .need_dac_fix = 1,
10479 .input_mux = &alc883_capture_source,
10481 [ALC883_3ST_6ch_INTEL] = {
10482 .mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
10483 .init_verbs = { alc883_init_verbs },
10484 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10485 .dac_nids = alc883_dac_nids,
10486 .dig_out_nid = ALC883_DIGOUT_NID,
10487 .dig_in_nid = ALC883_DIGIN_NID,
10488 .slave_dig_outs = alc883_slave_dig_outs,
10489 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
10490 .channel_mode = alc883_3ST_6ch_intel_modes,
10491 .need_dac_fix = 1,
10492 .input_mux = &alc883_3stack_6ch_intel,
10494 [ALC889A_INTEL] = {
10495 .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
10496 .init_verbs = { alc885_init_verbs, alc885_init_input_verbs,
10497 alc_hp15_unsol_verbs },
10498 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10499 .dac_nids = alc883_dac_nids,
10500 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
10501 .adc_nids = alc889_adc_nids,
10502 .dig_out_nid = ALC883_DIGOUT_NID,
10503 .dig_in_nid = ALC883_DIGIN_NID,
10504 .slave_dig_outs = alc883_slave_dig_outs,
10505 .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
10506 .channel_mode = alc889_8ch_intel_modes,
10507 .capsrc_nids = alc889_capsrc_nids,
10508 .input_mux = &alc889_capture_source,
10509 .setup = alc889_automute_setup,
10510 .init_hook = alc_hp_automute,
10511 .unsol_event = alc_sku_unsol_event,
10512 .need_dac_fix = 1,
10514 [ALC889_INTEL] = {
10515 .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
10516 .init_verbs = { alc885_init_verbs, alc889_init_input_verbs,
10517 alc889_eapd_verbs, alc_hp15_unsol_verbs},
10518 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10519 .dac_nids = alc883_dac_nids,
10520 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
10521 .adc_nids = alc889_adc_nids,
10522 .dig_out_nid = ALC883_DIGOUT_NID,
10523 .dig_in_nid = ALC883_DIGIN_NID,
10524 .slave_dig_outs = alc883_slave_dig_outs,
10525 .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
10526 .channel_mode = alc889_8ch_intel_modes,
10527 .capsrc_nids = alc889_capsrc_nids,
10528 .input_mux = &alc889_capture_source,
10529 .setup = alc889_automute_setup,
10530 .init_hook = alc889_intel_init_hook,
10531 .unsol_event = alc_sku_unsol_event,
10532 .need_dac_fix = 1,
10534 [ALC883_6ST_DIG] = {
10535 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
10536 .init_verbs = { alc883_init_verbs },
10537 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10538 .dac_nids = alc883_dac_nids,
10539 .dig_out_nid = ALC883_DIGOUT_NID,
10540 .dig_in_nid = ALC883_DIGIN_NID,
10541 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10542 .channel_mode = alc883_sixstack_modes,
10543 .input_mux = &alc883_capture_source,
10545 [ALC883_TARGA_DIG] = {
10546 .mixers = { alc883_targa_mixer, alc883_chmode_mixer },
10547 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
10548 alc883_targa_verbs},
10549 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10550 .dac_nids = alc883_dac_nids,
10551 .dig_out_nid = ALC883_DIGOUT_NID,
10552 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10553 .channel_mode = alc883_3ST_6ch_modes,
10554 .need_dac_fix = 1,
10555 .input_mux = &alc883_capture_source,
10556 .unsol_event = alc883_targa_unsol_event,
10557 .setup = alc882_targa_setup,
10558 .init_hook = alc882_targa_automute,
10560 [ALC883_TARGA_2ch_DIG] = {
10561 .mixers = { alc883_targa_2ch_mixer},
10562 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
10563 alc883_targa_verbs},
10564 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10565 .dac_nids = alc883_dac_nids,
10566 .adc_nids = alc883_adc_nids_alt,
10567 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
10568 .capsrc_nids = alc883_capsrc_nids,
10569 .dig_out_nid = ALC883_DIGOUT_NID,
10570 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10571 .channel_mode = alc883_3ST_2ch_modes,
10572 .input_mux = &alc883_capture_source,
10573 .unsol_event = alc883_targa_unsol_event,
10574 .setup = alc882_targa_setup,
10575 .init_hook = alc882_targa_automute,
10577 [ALC883_TARGA_8ch_DIG] = {
10578 .mixers = { alc883_targa_mixer, alc883_targa_8ch_mixer,
10579 alc883_chmode_mixer },
10580 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
10581 alc883_targa_verbs },
10582 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10583 .dac_nids = alc883_dac_nids,
10584 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10585 .adc_nids = alc883_adc_nids_rev,
10586 .capsrc_nids = alc883_capsrc_nids_rev,
10587 .dig_out_nid = ALC883_DIGOUT_NID,
10588 .dig_in_nid = ALC883_DIGIN_NID,
10589 .num_channel_mode = ARRAY_SIZE(alc883_4ST_8ch_modes),
10590 .channel_mode = alc883_4ST_8ch_modes,
10591 .need_dac_fix = 1,
10592 .input_mux = &alc883_capture_source,
10593 .unsol_event = alc883_targa_unsol_event,
10594 .setup = alc882_targa_setup,
10595 .init_hook = alc882_targa_automute,
10597 [ALC883_ACER] = {
10598 .mixers = { alc883_base_mixer },
10599 /* On TravelMate laptops, GPIO 0 enables the internal speaker
10600 * and the headphone jack. Turn this on and rely on the
10601 * standard mute methods whenever the user wants to turn
10602 * these outputs off.
10604 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
10605 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10606 .dac_nids = alc883_dac_nids,
10607 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10608 .channel_mode = alc883_3ST_2ch_modes,
10609 .input_mux = &alc883_capture_source,
10611 [ALC883_ACER_ASPIRE] = {
10612 .mixers = { alc883_acer_aspire_mixer },
10613 .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
10614 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10615 .dac_nids = alc883_dac_nids,
10616 .dig_out_nid = ALC883_DIGOUT_NID,
10617 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10618 .channel_mode = alc883_3ST_2ch_modes,
10619 .input_mux = &alc883_capture_source,
10620 .unsol_event = alc_sku_unsol_event,
10621 .setup = alc883_acer_aspire_setup,
10622 .init_hook = alc_hp_automute,
10624 [ALC888_ACER_ASPIRE_4930G] = {
10625 .mixers = { alc888_acer_aspire_4930g_mixer,
10626 alc883_chmode_mixer },
10627 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10628 alc888_acer_aspire_4930g_verbs },
10629 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10630 .dac_nids = alc883_dac_nids,
10631 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10632 .adc_nids = alc883_adc_nids_rev,
10633 .capsrc_nids = alc883_capsrc_nids_rev,
10634 .dig_out_nid = ALC883_DIGOUT_NID,
10635 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10636 .channel_mode = alc883_3ST_6ch_modes,
10637 .need_dac_fix = 1,
10638 .const_channel_count = 6,
10639 .num_mux_defs =
10640 ARRAY_SIZE(alc888_2_capture_sources),
10641 .input_mux = alc888_2_capture_sources,
10642 .unsol_event = alc_sku_unsol_event,
10643 .setup = alc888_acer_aspire_4930g_setup,
10644 .init_hook = alc_hp_automute,
10646 [ALC888_ACER_ASPIRE_6530G] = {
10647 .mixers = { alc888_acer_aspire_6530_mixer },
10648 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10649 alc888_acer_aspire_6530g_verbs },
10650 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10651 .dac_nids = alc883_dac_nids,
10652 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10653 .adc_nids = alc883_adc_nids_rev,
10654 .capsrc_nids = alc883_capsrc_nids_rev,
10655 .dig_out_nid = ALC883_DIGOUT_NID,
10656 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10657 .channel_mode = alc883_3ST_2ch_modes,
10658 .num_mux_defs =
10659 ARRAY_SIZE(alc888_2_capture_sources),
10660 .input_mux = alc888_acer_aspire_6530_sources,
10661 .unsol_event = alc_sku_unsol_event,
10662 .setup = alc888_acer_aspire_6530g_setup,
10663 .init_hook = alc_hp_automute,
10665 [ALC888_ACER_ASPIRE_8930G] = {
10666 .mixers = { alc889_acer_aspire_8930g_mixer,
10667 alc883_chmode_mixer },
10668 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10669 alc889_acer_aspire_8930g_verbs,
10670 alc889_eapd_verbs},
10671 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10672 .dac_nids = alc883_dac_nids,
10673 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
10674 .adc_nids = alc889_adc_nids,
10675 .capsrc_nids = alc889_capsrc_nids,
10676 .dig_out_nid = ALC883_DIGOUT_NID,
10677 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10678 .channel_mode = alc883_3ST_6ch_modes,
10679 .need_dac_fix = 1,
10680 .const_channel_count = 6,
10681 .num_mux_defs =
10682 ARRAY_SIZE(alc889_capture_sources),
10683 .input_mux = alc889_capture_sources,
10684 .unsol_event = alc_sku_unsol_event,
10685 .setup = alc889_acer_aspire_8930g_setup,
10686 .init_hook = alc_hp_automute,
10687 #ifdef CONFIG_SND_HDA_POWER_SAVE
10688 .power_hook = alc_power_eapd,
10689 #endif
10691 [ALC888_ACER_ASPIRE_7730G] = {
10692 .mixers = { alc883_3ST_6ch_mixer,
10693 alc883_chmode_mixer },
10694 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10695 alc888_acer_aspire_7730G_verbs },
10696 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10697 .dac_nids = alc883_dac_nids,
10698 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10699 .adc_nids = alc883_adc_nids_rev,
10700 .capsrc_nids = alc883_capsrc_nids_rev,
10701 .dig_out_nid = ALC883_DIGOUT_NID,
10702 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10703 .channel_mode = alc883_3ST_6ch_modes,
10704 .need_dac_fix = 1,
10705 .const_channel_count = 6,
10706 .input_mux = &alc883_capture_source,
10707 .unsol_event = alc_sku_unsol_event,
10708 .setup = alc888_acer_aspire_7730g_setup,
10709 .init_hook = alc_hp_automute,
10711 [ALC883_MEDION] = {
10712 .mixers = { alc883_fivestack_mixer,
10713 alc883_chmode_mixer },
10714 .init_verbs = { alc883_init_verbs,
10715 alc883_medion_eapd_verbs },
10716 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10717 .dac_nids = alc883_dac_nids,
10718 .adc_nids = alc883_adc_nids_alt,
10719 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
10720 .capsrc_nids = alc883_capsrc_nids,
10721 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10722 .channel_mode = alc883_sixstack_modes,
10723 .input_mux = &alc883_capture_source,
10725 [ALC883_MEDION_WIM2160] = {
10726 .mixers = { alc883_medion_wim2160_mixer },
10727 .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs },
10728 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10729 .dac_nids = alc883_dac_nids,
10730 .dig_out_nid = ALC883_DIGOUT_NID,
10731 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
10732 .adc_nids = alc883_adc_nids,
10733 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10734 .channel_mode = alc883_3ST_2ch_modes,
10735 .input_mux = &alc883_capture_source,
10736 .unsol_event = alc_sku_unsol_event,
10737 .setup = alc883_medion_wim2160_setup,
10738 .init_hook = alc_hp_automute,
10740 [ALC883_LAPTOP_EAPD] = {
10741 .mixers = { alc883_base_mixer },
10742 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
10743 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10744 .dac_nids = alc883_dac_nids,
10745 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10746 .channel_mode = alc883_3ST_2ch_modes,
10747 .input_mux = &alc883_capture_source,
10749 [ALC883_CLEVO_M540R] = {
10750 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10751 .init_verbs = { alc883_init_verbs, alc883_clevo_m540r_verbs },
10752 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10753 .dac_nids = alc883_dac_nids,
10754 .dig_out_nid = ALC883_DIGOUT_NID,
10755 .dig_in_nid = ALC883_DIGIN_NID,
10756 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_clevo_modes),
10757 .channel_mode = alc883_3ST_6ch_clevo_modes,
10758 .need_dac_fix = 1,
10759 .input_mux = &alc883_capture_source,
10760 /* This machine has the hardware HP auto-muting, thus
10761 * we need no software mute via unsol event
10764 [ALC883_CLEVO_M720] = {
10765 .mixers = { alc883_clevo_m720_mixer },
10766 .init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
10767 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10768 .dac_nids = alc883_dac_nids,
10769 .dig_out_nid = ALC883_DIGOUT_NID,
10770 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10771 .channel_mode = alc883_3ST_2ch_modes,
10772 .input_mux = &alc883_capture_source,
10773 .unsol_event = alc883_clevo_m720_unsol_event,
10774 .setup = alc883_clevo_m720_setup,
10775 .init_hook = alc883_clevo_m720_init_hook,
10777 [ALC883_LENOVO_101E_2ch] = {
10778 .mixers = { alc883_lenovo_101e_2ch_mixer},
10779 .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
10780 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10781 .dac_nids = alc883_dac_nids,
10782 .adc_nids = alc883_adc_nids_alt,
10783 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
10784 .capsrc_nids = alc883_capsrc_nids,
10785 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10786 .channel_mode = alc883_3ST_2ch_modes,
10787 .input_mux = &alc883_lenovo_101e_capture_source,
10788 .setup = alc883_lenovo_101e_setup,
10789 .unsol_event = alc_sku_unsol_event,
10790 .init_hook = alc_inithook,
10792 [ALC883_LENOVO_NB0763] = {
10793 .mixers = { alc883_lenovo_nb0763_mixer },
10794 .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
10795 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10796 .dac_nids = alc883_dac_nids,
10797 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10798 .channel_mode = alc883_3ST_2ch_modes,
10799 .need_dac_fix = 1,
10800 .input_mux = &alc883_lenovo_nb0763_capture_source,
10801 .unsol_event = alc_sku_unsol_event,
10802 .setup = alc883_lenovo_nb0763_setup,
10803 .init_hook = alc_hp_automute,
10805 [ALC888_LENOVO_MS7195_DIG] = {
10806 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10807 .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
10808 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10809 .dac_nids = alc883_dac_nids,
10810 .dig_out_nid = ALC883_DIGOUT_NID,
10811 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10812 .channel_mode = alc883_3ST_6ch_modes,
10813 .need_dac_fix = 1,
10814 .input_mux = &alc883_capture_source,
10815 .unsol_event = alc_sku_unsol_event,
10816 .setup = alc888_lenovo_ms7195_setup,
10817 .init_hook = alc_inithook,
10819 [ALC883_HAIER_W66] = {
10820 .mixers = { alc883_targa_2ch_mixer},
10821 .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},
10822 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10823 .dac_nids = alc883_dac_nids,
10824 .dig_out_nid = ALC883_DIGOUT_NID,
10825 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10826 .channel_mode = alc883_3ST_2ch_modes,
10827 .input_mux = &alc883_capture_source,
10828 .unsol_event = alc_sku_unsol_event,
10829 .setup = alc883_haier_w66_setup,
10830 .init_hook = alc_hp_automute,
10832 [ALC888_3ST_HP] = {
10833 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10834 .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
10835 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10836 .dac_nids = alc883_dac_nids,
10837 .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
10838 .channel_mode = alc888_3st_hp_modes,
10839 .need_dac_fix = 1,
10840 .input_mux = &alc883_capture_source,
10841 .unsol_event = alc_sku_unsol_event,
10842 .setup = alc888_3st_hp_setup,
10843 .init_hook = alc_hp_automute,
10845 [ALC888_6ST_DELL] = {
10846 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
10847 .init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
10848 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10849 .dac_nids = alc883_dac_nids,
10850 .dig_out_nid = ALC883_DIGOUT_NID,
10851 .dig_in_nid = ALC883_DIGIN_NID,
10852 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10853 .channel_mode = alc883_sixstack_modes,
10854 .input_mux = &alc883_capture_source,
10855 .unsol_event = alc_sku_unsol_event,
10856 .setup = alc888_6st_dell_setup,
10857 .init_hook = alc_hp_automute,
10859 [ALC883_MITAC] = {
10860 .mixers = { alc883_mitac_mixer },
10861 .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
10862 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10863 .dac_nids = alc883_dac_nids,
10864 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10865 .channel_mode = alc883_3ST_2ch_modes,
10866 .input_mux = &alc883_capture_source,
10867 .unsol_event = alc_sku_unsol_event,
10868 .setup = alc883_mitac_setup,
10869 .init_hook = alc_hp_automute,
10871 [ALC883_FUJITSU_PI2515] = {
10872 .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
10873 .init_verbs = { alc883_init_verbs,
10874 alc883_2ch_fujitsu_pi2515_verbs},
10875 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10876 .dac_nids = alc883_dac_nids,
10877 .dig_out_nid = ALC883_DIGOUT_NID,
10878 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10879 .channel_mode = alc883_3ST_2ch_modes,
10880 .input_mux = &alc883_fujitsu_pi2515_capture_source,
10881 .unsol_event = alc_sku_unsol_event,
10882 .setup = alc883_2ch_fujitsu_pi2515_setup,
10883 .init_hook = alc_hp_automute,
10885 [ALC888_FUJITSU_XA3530] = {
10886 .mixers = { alc888_base_mixer, alc883_chmode_mixer },
10887 .init_verbs = { alc883_init_verbs,
10888 alc888_fujitsu_xa3530_verbs },
10889 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10890 .dac_nids = alc883_dac_nids,
10891 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10892 .adc_nids = alc883_adc_nids_rev,
10893 .capsrc_nids = alc883_capsrc_nids_rev,
10894 .dig_out_nid = ALC883_DIGOUT_NID,
10895 .num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes),
10896 .channel_mode = alc888_4ST_8ch_intel_modes,
10897 .num_mux_defs =
10898 ARRAY_SIZE(alc888_2_capture_sources),
10899 .input_mux = alc888_2_capture_sources,
10900 .unsol_event = alc_sku_unsol_event,
10901 .setup = alc888_fujitsu_xa3530_setup,
10902 .init_hook = alc_hp_automute,
10904 [ALC888_LENOVO_SKY] = {
10905 .mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
10906 .init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs},
10907 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10908 .dac_nids = alc883_dac_nids,
10909 .dig_out_nid = ALC883_DIGOUT_NID,
10910 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10911 .channel_mode = alc883_sixstack_modes,
10912 .need_dac_fix = 1,
10913 .input_mux = &alc883_lenovo_sky_capture_source,
10914 .unsol_event = alc_sku_unsol_event,
10915 .setup = alc888_lenovo_sky_setup,
10916 .init_hook = alc_hp_automute,
10918 [ALC888_ASUS_M90V] = {
10919 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10920 .init_verbs = { alc883_init_verbs, alc888_asus_m90v_verbs },
10921 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10922 .dac_nids = alc883_dac_nids,
10923 .dig_out_nid = ALC883_DIGOUT_NID,
10924 .dig_in_nid = ALC883_DIGIN_NID,
10925 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10926 .channel_mode = alc883_3ST_6ch_modes,
10927 .need_dac_fix = 1,
10928 .input_mux = &alc883_fujitsu_pi2515_capture_source,
10929 .unsol_event = alc_sku_unsol_event,
10930 .setup = alc883_mode2_setup,
10931 .init_hook = alc_inithook,
10933 [ALC888_ASUS_EEE1601] = {
10934 .mixers = { alc883_asus_eee1601_mixer },
10935 .cap_mixer = alc883_asus_eee1601_cap_mixer,
10936 .init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
10937 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10938 .dac_nids = alc883_dac_nids,
10939 .dig_out_nid = ALC883_DIGOUT_NID,
10940 .dig_in_nid = ALC883_DIGIN_NID,
10941 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10942 .channel_mode = alc883_3ST_2ch_modes,
10943 .need_dac_fix = 1,
10944 .input_mux = &alc883_asus_eee1601_capture_source,
10945 .unsol_event = alc_sku_unsol_event,
10946 .init_hook = alc883_eee1601_inithook,
10948 [ALC1200_ASUS_P5Q] = {
10949 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
10950 .init_verbs = { alc883_init_verbs },
10951 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10952 .dac_nids = alc883_dac_nids,
10953 .dig_out_nid = ALC1200_DIGOUT_NID,
10954 .dig_in_nid = ALC883_DIGIN_NID,
10955 .slave_dig_outs = alc1200_slave_dig_outs,
10956 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10957 .channel_mode = alc883_sixstack_modes,
10958 .input_mux = &alc883_capture_source,
10960 [ALC889A_MB31] = {
10961 .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer},
10962 .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs,
10963 alc880_gpio1_init_verbs },
10964 .adc_nids = alc883_adc_nids,
10965 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
10966 .capsrc_nids = alc883_capsrc_nids,
10967 .dac_nids = alc883_dac_nids,
10968 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10969 .channel_mode = alc889A_mb31_6ch_modes,
10970 .num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes),
10971 .input_mux = &alc889A_mb31_capture_source,
10972 .dig_out_nid = ALC883_DIGOUT_NID,
10973 .unsol_event = alc889A_mb31_unsol_event,
10974 .init_hook = alc889A_mb31_automute,
10976 [ALC883_SONY_VAIO_TT] = {
10977 .mixers = { alc883_vaiott_mixer },
10978 .init_verbs = { alc883_init_verbs, alc883_vaiott_verbs },
10979 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10980 .dac_nids = alc883_dac_nids,
10981 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10982 .channel_mode = alc883_3ST_2ch_modes,
10983 .input_mux = &alc883_capture_source,
10984 .unsol_event = alc_sku_unsol_event,
10985 .setup = alc883_vaiott_setup,
10986 .init_hook = alc_hp_automute,
10992 * Pin config fixes
10994 enum {
10995 PINFIX_ABIT_AW9D_MAX,
10996 PINFIX_LENOVO_Y530,
10997 PINFIX_PB_M5210,
10998 PINFIX_ACER_ASPIRE_7736,
11001 static const struct alc_fixup alc882_fixups[] = {
11002 [PINFIX_ABIT_AW9D_MAX] = {
11003 .type = ALC_FIXUP_PINS,
11004 .v.pins = (const struct alc_pincfg[]) {
11005 { 0x15, 0x01080104 }, /* side */
11006 { 0x16, 0x01011012 }, /* rear */
11007 { 0x17, 0x01016011 }, /* clfe */
11011 [PINFIX_LENOVO_Y530] = {
11012 .type = ALC_FIXUP_PINS,
11013 .v.pins = (const struct alc_pincfg[]) {
11014 { 0x15, 0x99130112 }, /* rear int speakers */
11015 { 0x16, 0x99130111 }, /* subwoofer */
11019 [PINFIX_PB_M5210] = {
11020 .type = ALC_FIXUP_VERBS,
11021 .v.verbs = (const struct hda_verb[]) {
11022 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
11026 [PINFIX_ACER_ASPIRE_7736] = {
11027 .type = ALC_FIXUP_SKU,
11028 .v.sku = ALC_FIXUP_SKU_IGNORE,
11032 static const struct snd_pci_quirk alc882_fixup_tbl[] = {
11033 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
11034 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
11035 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
11036 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
11041 * BIOS auto configuration
11043 static int alc882_auto_create_input_ctls(struct hda_codec *codec,
11044 const struct auto_pin_cfg *cfg)
11046 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x23, 0x22);
11049 static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
11050 hda_nid_t nid, int pin_type,
11051 hda_nid_t dac)
11053 int idx;
11055 /* set as output */
11056 alc_set_pin_output(codec, nid, pin_type);
11058 if (dac == 0x25)
11059 idx = 4;
11060 else if (dac >= 0x02 && dac <= 0x05)
11061 idx = dac - 2;
11062 else
11063 return;
11064 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
11067 static void alc882_auto_init_multi_out(struct hda_codec *codec)
11069 struct alc_spec *spec = codec->spec;
11070 int i;
11072 for (i = 0; i <= HDA_SIDE; i++) {
11073 hda_nid_t nid = spec->autocfg.line_out_pins[i];
11074 int pin_type = get_pin_type(spec->autocfg.line_out_type);
11075 if (nid)
11076 alc882_auto_set_output_and_unmute(codec, nid, pin_type,
11077 spec->multiout.dac_nids[i]);
11081 static void alc882_auto_init_hp_out(struct hda_codec *codec)
11083 struct alc_spec *spec = codec->spec;
11084 hda_nid_t pin, dac;
11085 int i;
11087 if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT) {
11088 for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
11089 pin = spec->autocfg.hp_pins[i];
11090 if (!pin)
11091 break;
11092 dac = spec->multiout.hp_nid;
11093 if (!dac)
11094 dac = spec->multiout.dac_nids[0]; /* to front */
11095 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
11099 if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT) {
11100 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
11101 pin = spec->autocfg.speaker_pins[i];
11102 if (!pin)
11103 break;
11104 dac = spec->multiout.extra_out_nid[0];
11105 if (!dac)
11106 dac = spec->multiout.dac_nids[0]; /* to front */
11107 alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
11112 static void alc882_auto_init_analog_input(struct hda_codec *codec)
11114 struct alc_spec *spec = codec->spec;
11115 struct auto_pin_cfg *cfg = &spec->autocfg;
11116 int i;
11118 for (i = 0; i < cfg->num_inputs; i++) {
11119 hda_nid_t nid = cfg->inputs[i].pin;
11120 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
11121 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
11122 snd_hda_codec_write(codec, nid, 0,
11123 AC_VERB_SET_AMP_GAIN_MUTE,
11124 AMP_OUT_MUTE);
11128 static void alc882_auto_init_input_src(struct hda_codec *codec)
11130 struct alc_spec *spec = codec->spec;
11131 int c;
11133 for (c = 0; c < spec->num_adc_nids; c++) {
11134 hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
11135 hda_nid_t nid = spec->capsrc_nids[c];
11136 unsigned int mux_idx;
11137 const struct hda_input_mux *imux;
11138 int conns, mute, idx, item;
11140 /* mute ADC */
11141 snd_hda_codec_write(codec, spec->adc_nids[c], 0,
11142 AC_VERB_SET_AMP_GAIN_MUTE,
11143 AMP_IN_MUTE(0));
11145 conns = snd_hda_get_connections(codec, nid, conn_list,
11146 ARRAY_SIZE(conn_list));
11147 if (conns < 0)
11148 continue;
11149 mux_idx = c >= spec->num_mux_defs ? 0 : c;
11150 imux = &spec->input_mux[mux_idx];
11151 if (!imux->num_items && mux_idx > 0)
11152 imux = &spec->input_mux[0];
11153 for (idx = 0; idx < conns; idx++) {
11154 /* if the current connection is the selected one,
11155 * unmute it as default - otherwise mute it
11157 mute = AMP_IN_MUTE(idx);
11158 for (item = 0; item < imux->num_items; item++) {
11159 if (imux->items[item].index == idx) {
11160 if (spec->cur_mux[c] == item)
11161 mute = AMP_IN_UNMUTE(idx);
11162 break;
11165 /* check if we have a selector or mixer
11166 * we could check for the widget type instead, but
11167 * just check for Amp-In presence (in case of mixer
11168 * without amp-in there is something wrong, this
11169 * function shouldn't be used or capsrc nid is wrong)
11171 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
11172 snd_hda_codec_write(codec, nid, 0,
11173 AC_VERB_SET_AMP_GAIN_MUTE,
11174 mute);
11175 else if (mute != AMP_IN_MUTE(idx))
11176 snd_hda_codec_write(codec, nid, 0,
11177 AC_VERB_SET_CONNECT_SEL,
11178 idx);
11183 /* add mic boosts if needed */
11184 static int alc_auto_add_mic_boost(struct hda_codec *codec)
11186 struct alc_spec *spec = codec->spec;
11187 struct auto_pin_cfg *cfg = &spec->autocfg;
11188 int i, err;
11189 int type_idx = 0;
11190 hda_nid_t nid;
11191 const char *prev_label = NULL;
11193 for (i = 0; i < cfg->num_inputs; i++) {
11194 if (cfg->inputs[i].type > AUTO_PIN_MIC)
11195 break;
11196 nid = cfg->inputs[i].pin;
11197 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
11198 const char *label;
11199 char boost_label[32];
11201 label = hda_get_autocfg_input_label(codec, cfg, i);
11202 if (prev_label && !strcmp(label, prev_label))
11203 type_idx++;
11204 else
11205 type_idx = 0;
11206 prev_label = label;
11208 snprintf(boost_label, sizeof(boost_label),
11209 "%s Boost Volume", label);
11210 err = add_control(spec, ALC_CTL_WIDGET_VOL,
11211 boost_label, type_idx,
11212 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
11213 if (err < 0)
11214 return err;
11217 return 0;
11220 /* almost identical with ALC880 parser... */
11221 static int alc882_parse_auto_config(struct hda_codec *codec)
11223 struct alc_spec *spec = codec->spec;
11224 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
11225 int err;
11227 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
11228 alc882_ignore);
11229 if (err < 0)
11230 return err;
11231 if (!spec->autocfg.line_outs)
11232 return 0; /* can't find valid BIOS pin config */
11234 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
11235 if (err < 0)
11236 return err;
11237 err = alc_auto_add_multi_channel_mode(codec);
11238 if (err < 0)
11239 return err;
11240 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
11241 if (err < 0)
11242 return err;
11243 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
11244 "Headphone");
11245 if (err < 0)
11246 return err;
11247 err = alc880_auto_create_extra_out(spec,
11248 spec->autocfg.speaker_pins[0],
11249 "Speaker");
11250 if (err < 0)
11251 return err;
11252 err = alc882_auto_create_input_ctls(codec, &spec->autocfg);
11253 if (err < 0)
11254 return err;
11256 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
11258 alc_auto_parse_digital(codec);
11260 if (spec->kctls.list)
11261 add_mixer(spec, spec->kctls.list);
11263 add_verb(spec, alc883_auto_init_verbs);
11264 /* if ADC 0x07 is available, initialize it, too */
11265 if (get_wcaps_type(get_wcaps(codec, 0x07)) == AC_WID_AUD_IN)
11266 add_verb(spec, alc882_adc1_init_verbs);
11268 spec->num_mux_defs = 1;
11269 spec->input_mux = &spec->private_imux[0];
11271 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
11273 err = alc_auto_add_mic_boost(codec);
11274 if (err < 0)
11275 return err;
11277 return 1; /* config found */
11280 /* additional initialization for auto-configuration model */
11281 static void alc882_auto_init(struct hda_codec *codec)
11283 struct alc_spec *spec = codec->spec;
11284 alc882_auto_init_multi_out(codec);
11285 alc882_auto_init_hp_out(codec);
11286 alc882_auto_init_analog_input(codec);
11287 alc882_auto_init_input_src(codec);
11288 alc_auto_init_digital(codec);
11289 if (spec->unsol_event)
11290 alc_inithook(codec);
11293 static int patch_alc882(struct hda_codec *codec)
11295 struct alc_spec *spec;
11296 int err, board_config;
11298 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
11299 if (spec == NULL)
11300 return -ENOMEM;
11302 codec->spec = spec;
11304 switch (codec->vendor_id) {
11305 case 0x10ec0882:
11306 case 0x10ec0885:
11307 break;
11308 default:
11309 /* ALC883 and variants */
11310 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
11311 break;
11314 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
11315 alc882_models,
11316 alc882_cfg_tbl);
11318 if (board_config < 0 || board_config >= ALC882_MODEL_LAST)
11319 board_config = snd_hda_check_board_codec_sid_config(codec,
11320 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
11322 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
11323 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
11324 codec->chip_name);
11325 board_config = ALC882_AUTO;
11328 if (board_config == ALC882_AUTO) {
11329 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
11330 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
11333 alc_auto_parse_customize_define(codec);
11335 if (board_config == ALC882_AUTO) {
11336 /* automatic parse from the BIOS config */
11337 err = alc882_parse_auto_config(codec);
11338 if (err < 0) {
11339 alc_free(codec);
11340 return err;
11341 } else if (!err) {
11342 printk(KERN_INFO
11343 "hda_codec: Cannot set up configuration "
11344 "from BIOS. Using base mode...\n");
11345 board_config = ALC882_3ST_DIG;
11349 if (has_cdefine_beep(codec)) {
11350 err = snd_hda_attach_beep_device(codec, 0x1);
11351 if (err < 0) {
11352 alc_free(codec);
11353 return err;
11357 if (board_config != ALC882_AUTO)
11358 setup_preset(codec, &alc882_presets[board_config]);
11360 spec->stream_analog_playback = &alc882_pcm_analog_playback;
11361 spec->stream_analog_capture = &alc882_pcm_analog_capture;
11362 /* FIXME: setup DAC5 */
11363 /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
11364 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
11366 spec->stream_digital_playback = &alc882_pcm_digital_playback;
11367 spec->stream_digital_capture = &alc882_pcm_digital_capture;
11369 if (!spec->adc_nids && spec->input_mux) {
11370 int i, j;
11371 spec->num_adc_nids = 0;
11372 for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) {
11373 const struct hda_input_mux *imux = spec->input_mux;
11374 hda_nid_t cap;
11375 hda_nid_t items[16];
11376 hda_nid_t nid = alc882_adc_nids[i];
11377 unsigned int wcap = get_wcaps(codec, nid);
11378 /* get type */
11379 wcap = get_wcaps_type(wcap);
11380 if (wcap != AC_WID_AUD_IN)
11381 continue;
11382 spec->private_adc_nids[spec->num_adc_nids] = nid;
11383 err = snd_hda_get_connections(codec, nid, &cap, 1);
11384 if (err < 0)
11385 continue;
11386 err = snd_hda_get_connections(codec, cap, items,
11387 ARRAY_SIZE(items));
11388 if (err < 0)
11389 continue;
11390 for (j = 0; j < imux->num_items; j++)
11391 if (imux->items[j].index >= err)
11392 break;
11393 if (j < imux->num_items)
11394 continue;
11395 spec->private_capsrc_nids[spec->num_adc_nids] = cap;
11396 spec->num_adc_nids++;
11398 spec->adc_nids = spec->private_adc_nids;
11399 spec->capsrc_nids = spec->private_capsrc_nids;
11402 set_capture_mixer(codec);
11404 if (has_cdefine_beep(codec))
11405 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
11407 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
11409 spec->vmaster_nid = 0x0c;
11411 codec->patch_ops = alc_patch_ops;
11412 if (board_config == ALC882_AUTO)
11413 spec->init_hook = alc882_auto_init;
11415 alc_init_jacks(codec);
11416 #ifdef CONFIG_SND_HDA_POWER_SAVE
11417 if (!spec->loopback.amplist)
11418 spec->loopback.amplist = alc882_loopbacks;
11419 #endif
11421 return 0;
11426 * ALC262 support
11429 #define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
11430 #define ALC262_DIGIN_NID ALC880_DIGIN_NID
11432 #define alc262_dac_nids alc260_dac_nids
11433 #define alc262_adc_nids alc882_adc_nids
11434 #define alc262_adc_nids_alt alc882_adc_nids_alt
11435 #define alc262_capsrc_nids alc882_capsrc_nids
11436 #define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
11438 #define alc262_modes alc260_modes
11439 #define alc262_capture_source alc882_capture_source
11441 static const hda_nid_t alc262_dmic_adc_nids[1] = {
11442 /* ADC0 */
11443 0x09
11446 static const hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
11448 static const struct snd_kcontrol_new alc262_base_mixer[] = {
11449 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11450 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
11451 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11452 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11453 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11454 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11455 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11456 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11457 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11458 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11459 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11460 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
11461 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
11462 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11463 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
11464 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
11465 { } /* end */
11468 /* update HP, line and mono-out pins according to the master switch */
11469 #define alc262_hp_master_update alc260_hp_master_update
11471 static void alc262_hp_bpc_setup(struct hda_codec *codec)
11473 struct alc_spec *spec = codec->spec;
11475 spec->autocfg.hp_pins[0] = 0x1b;
11476 spec->autocfg.speaker_pins[0] = 0x16;
11477 spec->automute = 1;
11478 spec->automute_mode = ALC_AUTOMUTE_PIN;
11481 static void alc262_hp_wildwest_setup(struct hda_codec *codec)
11483 struct alc_spec *spec = codec->spec;
11485 spec->autocfg.hp_pins[0] = 0x15;
11486 spec->autocfg.speaker_pins[0] = 0x16;
11487 spec->automute = 1;
11488 spec->automute_mode = ALC_AUTOMUTE_PIN;
11491 #define alc262_hp_master_sw_get alc260_hp_master_sw_get
11492 #define alc262_hp_master_sw_put alc260_hp_master_sw_put
11494 #define ALC262_HP_MASTER_SWITCH \
11496 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
11497 .name = "Master Playback Switch", \
11498 .info = snd_ctl_boolean_mono_info, \
11499 .get = alc262_hp_master_sw_get, \
11500 .put = alc262_hp_master_sw_put, \
11501 }, \
11503 .iface = NID_MAPPING, \
11504 .name = "Master Playback Switch", \
11505 .private_value = 0x15 | (0x16 << 8) | (0x1b << 16), \
11509 static const struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
11510 ALC262_HP_MASTER_SWITCH,
11511 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11512 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11513 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
11514 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
11515 HDA_OUTPUT),
11516 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
11517 HDA_OUTPUT),
11518 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11519 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11520 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11521 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11522 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11523 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
11524 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11525 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11526 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11527 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11528 HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
11529 HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
11530 { } /* end */
11533 static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
11534 ALC262_HP_MASTER_SWITCH,
11535 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11536 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
11537 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11538 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11539 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
11540 HDA_OUTPUT),
11541 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
11542 HDA_OUTPUT),
11543 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
11544 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
11545 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x1a, 0, HDA_INPUT),
11546 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
11547 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
11548 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11549 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11550 { } /* end */
11553 static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
11554 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11555 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11556 HDA_CODEC_VOLUME("Rear Mic Boost Volume", 0x18, 0, HDA_INPUT),
11557 { } /* end */
11560 /* mute/unmute internal speaker according to the hp jack and mute state */
11561 static void alc262_hp_t5735_setup(struct hda_codec *codec)
11563 struct alc_spec *spec = codec->spec;
11565 spec->autocfg.hp_pins[0] = 0x15;
11566 spec->autocfg.speaker_pins[0] = 0x14;
11567 spec->automute = 1;
11568 spec->automute_mode = ALC_AUTOMUTE_PIN;
11571 static const struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
11572 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11573 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
11574 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11575 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11576 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11577 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11578 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11579 { } /* end */
11582 static const struct hda_verb alc262_hp_t5735_verbs[] = {
11583 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11584 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11586 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
11590 static const struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
11591 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11592 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
11593 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
11594 HDA_CODEC_MUTE("Speaker Playback Switch", 0x16, 0x0, HDA_OUTPUT),
11595 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
11596 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
11597 { } /* end */
11600 static const struct hda_verb alc262_hp_rp5700_verbs[] = {
11601 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11602 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11603 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11604 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11605 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11606 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11607 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
11608 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
11609 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
11610 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
11614 static const struct hda_input_mux alc262_hp_rp5700_capture_source = {
11615 .num_items = 1,
11616 .items = {
11617 { "Line", 0x1 },
11621 /* bind hp and internal speaker mute (with plug check) as master switch */
11622 #define alc262_hippo_master_update alc262_hp_master_update
11623 #define alc262_hippo_master_sw_get alc262_hp_master_sw_get
11624 #define alc262_hippo_master_sw_put alc262_hp_master_sw_put
11626 #define ALC262_HIPPO_MASTER_SWITCH \
11628 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
11629 .name = "Master Playback Switch", \
11630 .info = snd_ctl_boolean_mono_info, \
11631 .get = alc262_hippo_master_sw_get, \
11632 .put = alc262_hippo_master_sw_put, \
11633 }, \
11635 .iface = NID_MAPPING, \
11636 .name = "Master Playback Switch", \
11637 .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
11638 (SUBDEV_SPEAKER(0) << 16), \
11641 static const struct snd_kcontrol_new alc262_hippo_mixer[] = {
11642 ALC262_HIPPO_MASTER_SWITCH,
11643 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11644 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11645 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11646 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11647 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11648 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11649 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11650 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11651 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11652 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11653 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
11654 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11655 { } /* end */
11658 static const struct snd_kcontrol_new alc262_hippo1_mixer[] = {
11659 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11660 ALC262_HIPPO_MASTER_SWITCH,
11661 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11662 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11663 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11664 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11665 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11666 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11667 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11668 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11669 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11670 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
11671 { } /* end */
11674 /* mute/unmute internal speaker according to the hp jack and mute state */
11675 static void alc262_hippo_setup(struct hda_codec *codec)
11677 struct alc_spec *spec = codec->spec;
11679 spec->autocfg.hp_pins[0] = 0x15;
11680 spec->autocfg.speaker_pins[0] = 0x14;
11681 spec->automute = 1;
11682 spec->automute_mode = ALC_AUTOMUTE_AMP;
11685 static void alc262_hippo1_setup(struct hda_codec *codec)
11687 struct alc_spec *spec = codec->spec;
11689 spec->autocfg.hp_pins[0] = 0x1b;
11690 spec->autocfg.speaker_pins[0] = 0x14;
11691 spec->automute = 1;
11692 spec->automute_mode = ALC_AUTOMUTE_AMP;
11696 static const struct snd_kcontrol_new alc262_sony_mixer[] = {
11697 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11698 ALC262_HIPPO_MASTER_SWITCH,
11699 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11700 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11701 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11702 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11703 { } /* end */
11706 static const struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
11707 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11708 ALC262_HIPPO_MASTER_SWITCH,
11709 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11710 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11711 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11712 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11713 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11714 { } /* end */
11717 static const struct snd_kcontrol_new alc262_tyan_mixer[] = {
11718 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11719 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
11720 HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT),
11721 HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT),
11722 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11723 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11724 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11725 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11726 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11727 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11728 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11729 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
11730 { } /* end */
11733 static const struct hda_verb alc262_tyan_verbs[] = {
11734 /* Headphone automute */
11735 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11736 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11737 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11739 /* P11 AUX_IN, white 4-pin connector */
11740 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11741 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1},
11742 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93},
11743 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19},
11748 /* unsolicited event for HP jack sensing */
11749 static void alc262_tyan_setup(struct hda_codec *codec)
11751 struct alc_spec *spec = codec->spec;
11753 spec->autocfg.hp_pins[0] = 0x1b;
11754 spec->autocfg.speaker_pins[0] = 0x15;
11755 spec->automute = 1;
11756 spec->automute_mode = ALC_AUTOMUTE_AMP;
11760 #define alc262_capture_mixer alc882_capture_mixer
11761 #define alc262_capture_alt_mixer alc882_capture_alt_mixer
11764 * generic initialization of ADC, input mixers and output mixers
11766 static const struct hda_verb alc262_init_verbs[] = {
11768 * Unmute ADC0-2 and set the default input to mic-in
11770 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11771 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11772 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11773 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11774 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11775 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11777 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
11778 * mixer widget
11779 * Note: PASD motherboards uses the Line In 2 as the input for
11780 * front panel mic (mic 2)
11782 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
11783 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11784 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11785 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11786 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11787 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11790 * Set up output mixers (0x0c - 0x0e)
11792 /* set vol=0 to output mixers */
11793 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11794 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11795 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11796 /* set up input amps for analog loopback */
11797 /* Amp Indices: DAC = 0, mixer = 1 */
11798 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11799 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11800 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11801 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11802 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11803 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11805 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
11806 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11807 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
11808 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11809 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11810 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11812 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11813 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11814 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11815 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11816 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11818 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
11819 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
11821 /* FIXME: use matrix-type input source selection */
11822 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
11823 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
11824 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11825 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11826 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11827 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11828 /* Input mixer2 */
11829 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11830 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11831 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11832 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11833 /* Input mixer3 */
11834 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11835 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11836 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11837 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11842 static const struct hda_verb alc262_eapd_verbs[] = {
11843 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
11844 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
11848 static const struct hda_verb alc262_hippo1_unsol_verbs[] = {
11849 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11850 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11851 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11853 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11854 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11858 static const struct hda_verb alc262_sony_unsol_verbs[] = {
11859 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11860 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11861 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic
11863 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11864 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11868 static const struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
11869 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11870 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
11871 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11872 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11873 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11874 { } /* end */
11877 static const struct hda_verb alc262_toshiba_s06_verbs[] = {
11878 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11879 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11880 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11881 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11882 {0x22, AC_VERB_SET_CONNECT_SEL, 0x09},
11883 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11884 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
11885 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11889 static void alc262_toshiba_s06_setup(struct hda_codec *codec)
11891 struct alc_spec *spec = codec->spec;
11893 spec->autocfg.hp_pins[0] = 0x15;
11894 spec->autocfg.speaker_pins[0] = 0x14;
11895 spec->ext_mic.pin = 0x18;
11896 spec->ext_mic.mux_idx = 0;
11897 spec->int_mic.pin = 0x12;
11898 spec->int_mic.mux_idx = 9;
11899 spec->auto_mic = 1;
11900 spec->automute = 1;
11901 spec->automute_mode = ALC_AUTOMUTE_PIN;
11905 * nec model
11906 * 0x15 = headphone
11907 * 0x16 = internal speaker
11908 * 0x18 = external mic
11911 static const struct snd_kcontrol_new alc262_nec_mixer[] = {
11912 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
11913 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
11915 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11916 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11917 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11919 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11920 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11921 { } /* end */
11924 static const struct hda_verb alc262_nec_verbs[] = {
11925 /* Unmute Speaker */
11926 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11928 /* Headphone */
11929 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11930 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11932 /* External mic to headphone */
11933 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11934 /* External mic to speaker */
11935 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11940 * fujitsu model
11941 * 0x14 = headphone/spdif-out, 0x15 = internal speaker,
11942 * 0x1b = port replicator headphone out
11945 #define ALC_HP_EVENT ALC880_HP_EVENT
11947 static const struct hda_verb alc262_fujitsu_unsol_verbs[] = {
11948 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11949 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11950 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11951 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11955 static const struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
11956 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11957 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11961 static const struct hda_verb alc262_lenovo_3000_init_verbs[] = {
11962 /* Front Mic pin: input vref at 50% */
11963 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
11964 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11968 static const struct hda_input_mux alc262_fujitsu_capture_source = {
11969 .num_items = 3,
11970 .items = {
11971 { "Mic", 0x0 },
11972 { "Internal Mic", 0x1 },
11973 { "CD", 0x4 },
11977 static const struct hda_input_mux alc262_HP_capture_source = {
11978 .num_items = 5,
11979 .items = {
11980 { "Mic", 0x0 },
11981 { "Front Mic", 0x1 },
11982 { "Line", 0x2 },
11983 { "CD", 0x4 },
11984 { "AUX IN", 0x6 },
11988 static const struct hda_input_mux alc262_HP_D7000_capture_source = {
11989 .num_items = 4,
11990 .items = {
11991 { "Mic", 0x0 },
11992 { "Front Mic", 0x2 },
11993 { "Line", 0x1 },
11994 { "CD", 0x4 },
11998 static void alc262_fujitsu_setup(struct hda_codec *codec)
12000 struct alc_spec *spec = codec->spec;
12002 spec->autocfg.hp_pins[0] = 0x14;
12003 spec->autocfg.hp_pins[1] = 0x1b;
12004 spec->autocfg.speaker_pins[0] = 0x15;
12005 spec->automute = 1;
12006 spec->automute_mode = ALC_AUTOMUTE_AMP;
12009 /* bind volumes of both NID 0x0c and 0x0d */
12010 static const struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
12011 .ops = &snd_hda_bind_vol,
12012 .values = {
12013 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
12014 HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
12019 static const struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
12020 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
12022 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12023 .name = "Master Playback Switch",
12024 .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
12025 .info = snd_ctl_boolean_mono_info,
12026 .get = alc262_hp_master_sw_get,
12027 .put = alc262_hp_master_sw_put,
12030 .iface = NID_MAPPING,
12031 .name = "Master Playback Switch",
12032 .private_value = 0x1b,
12034 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
12035 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
12036 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
12037 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
12038 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
12039 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
12040 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
12041 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
12042 { } /* end */
12045 static void alc262_lenovo_3000_setup(struct hda_codec *codec)
12047 struct alc_spec *spec = codec->spec;
12049 spec->autocfg.hp_pins[0] = 0x1b;
12050 spec->autocfg.speaker_pins[0] = 0x14;
12051 spec->autocfg.speaker_pins[1] = 0x16;
12052 spec->automute = 1;
12053 spec->automute_mode = ALC_AUTOMUTE_AMP;
12056 static const struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
12057 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
12059 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12060 .name = "Master Playback Switch",
12061 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
12062 .info = snd_ctl_boolean_mono_info,
12063 .get = alc262_hp_master_sw_get,
12064 .put = alc262_hp_master_sw_put,
12066 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
12067 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
12068 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
12069 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
12070 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
12071 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
12072 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
12073 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
12074 { } /* end */
12077 static const struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
12078 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
12079 ALC262_HIPPO_MASTER_SWITCH,
12080 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
12081 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
12082 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
12083 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
12084 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
12085 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
12086 { } /* end */
12089 /* additional init verbs for Benq laptops */
12090 static const struct hda_verb alc262_EAPD_verbs[] = {
12091 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
12092 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
12096 static const struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
12097 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
12098 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12100 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
12101 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
12105 /* Samsung Q1 Ultra Vista model setup */
12106 static const struct snd_kcontrol_new alc262_ultra_mixer[] = {
12107 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
12108 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
12109 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
12110 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
12111 HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
12112 HDA_CODEC_VOLUME("Headphone Mic Boost Volume", 0x15, 0, HDA_INPUT),
12113 { } /* end */
12116 static const struct hda_verb alc262_ultra_verbs[] = {
12117 /* output mixer */
12118 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12119 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12120 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12121 /* speaker */
12122 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
12123 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12124 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12125 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
12126 /* HP */
12127 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12128 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12129 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12130 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
12131 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
12132 /* internal mic */
12133 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
12134 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12135 /* ADC, choose mic */
12136 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12137 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12138 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12139 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
12140 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
12141 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
12142 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
12143 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
12144 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
12145 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
12149 /* mute/unmute internal speaker according to the hp jack and mute state */
12150 static void alc262_ultra_automute(struct hda_codec *codec)
12152 struct alc_spec *spec = codec->spec;
12153 unsigned int mute;
12155 mute = 0;
12156 /* auto-mute only when HP is used as HP */
12157 if (!spec->cur_mux[0]) {
12158 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
12159 if (spec->jack_present)
12160 mute = HDA_AMP_MUTE;
12162 /* mute/unmute internal speaker */
12163 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
12164 HDA_AMP_MUTE, mute);
12165 /* mute/unmute HP */
12166 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
12167 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
12170 /* unsolicited event for HP jack sensing */
12171 static void alc262_ultra_unsol_event(struct hda_codec *codec,
12172 unsigned int res)
12174 if ((res >> 26) != ALC880_HP_EVENT)
12175 return;
12176 alc262_ultra_automute(codec);
12179 static const struct hda_input_mux alc262_ultra_capture_source = {
12180 .num_items = 2,
12181 .items = {
12182 { "Mic", 0x1 },
12183 { "Headphone", 0x7 },
12187 static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
12188 struct snd_ctl_elem_value *ucontrol)
12190 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
12191 struct alc_spec *spec = codec->spec;
12192 int ret;
12194 ret = alc_mux_enum_put(kcontrol, ucontrol);
12195 if (!ret)
12196 return 0;
12197 /* reprogram the HP pin as mic or HP according to the input source */
12198 snd_hda_codec_write_cache(codec, 0x15, 0,
12199 AC_VERB_SET_PIN_WIDGET_CONTROL,
12200 spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
12201 alc262_ultra_automute(codec); /* mute/unmute HP */
12202 return ret;
12205 static const struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
12206 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
12207 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
12209 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12210 .name = "Capture Source",
12211 .info = alc_mux_enum_info,
12212 .get = alc_mux_enum_get,
12213 .put = alc262_ultra_mux_enum_put,
12216 .iface = NID_MAPPING,
12217 .name = "Capture Source",
12218 .private_value = 0x15,
12220 { } /* end */
12223 /* We use two mixers depending on the output pin; 0x16 is a mono output
12224 * and thus it's bound with a different mixer.
12225 * This function returns which mixer amp should be used.
12227 static int alc262_check_volbit(hda_nid_t nid)
12229 if (!nid)
12230 return 0;
12231 else if (nid == 0x16)
12232 return 2;
12233 else
12234 return 1;
12237 static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
12238 const char *pfx, int *vbits, int idx)
12240 unsigned long val;
12241 int vbit;
12243 vbit = alc262_check_volbit(nid);
12244 if (!vbit)
12245 return 0;
12246 if (*vbits & vbit) /* a volume control for this mixer already there */
12247 return 0;
12248 *vbits |= vbit;
12249 if (vbit == 2)
12250 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
12251 else
12252 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
12253 return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, val);
12256 static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
12257 const char *pfx, int idx)
12259 unsigned long val;
12261 if (!nid)
12262 return 0;
12263 if (nid == 0x16)
12264 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
12265 else
12266 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
12267 return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, val);
12270 /* add playback controls from the parsed DAC table */
12271 static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
12272 const struct auto_pin_cfg *cfg)
12274 const char *pfx;
12275 int vbits;
12276 int i, err;
12278 spec->multiout.num_dacs = 1; /* only use one dac */
12279 spec->multiout.dac_nids = spec->private_dac_nids;
12280 spec->private_dac_nids[0] = 2;
12282 pfx = alc_get_line_out_pfx(spec, true);
12283 if (!pfx)
12284 pfx = "Front";
12285 for (i = 0; i < 2; i++) {
12286 err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i);
12287 if (err < 0)
12288 return err;
12289 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
12290 err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[i],
12291 "Speaker", i);
12292 if (err < 0)
12293 return err;
12295 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
12296 err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[i],
12297 "Headphone", i);
12298 if (err < 0)
12299 return err;
12303 vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
12304 alc262_check_volbit(cfg->speaker_pins[0]) |
12305 alc262_check_volbit(cfg->hp_pins[0]);
12306 if (vbits == 1 || vbits == 2)
12307 pfx = "Master"; /* only one mixer is used */
12308 vbits = 0;
12309 for (i = 0; i < 2; i++) {
12310 err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx,
12311 &vbits, i);
12312 if (err < 0)
12313 return err;
12314 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
12315 err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[i],
12316 "Speaker", &vbits, i);
12317 if (err < 0)
12318 return err;
12320 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
12321 err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[i],
12322 "Headphone", &vbits, i);
12323 if (err < 0)
12324 return err;
12327 return 0;
12330 #define alc262_auto_create_input_ctls \
12331 alc882_auto_create_input_ctls
12334 * generic initialization of ADC, input mixers and output mixers
12336 static const struct hda_verb alc262_volume_init_verbs[] = {
12338 * Unmute ADC0-2 and set the default input to mic-in
12340 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
12341 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12342 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
12343 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12344 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
12345 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12347 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
12348 * mixer widget
12349 * Note: PASD motherboards uses the Line In 2 as the input for
12350 * front panel mic (mic 2)
12352 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
12353 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12354 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12355 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
12356 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
12357 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
12360 * Set up output mixers (0x0c - 0x0f)
12362 /* set vol=0 to output mixers */
12363 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12364 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12365 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12367 /* set up input amps for analog loopback */
12368 /* Amp Indices: DAC = 0, mixer = 1 */
12369 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12370 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12371 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12372 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12373 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12374 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12376 /* FIXME: use matrix-type input source selection */
12377 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
12378 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
12379 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12380 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12381 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12382 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12383 /* Input mixer2 */
12384 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12385 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12386 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12387 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12388 /* Input mixer3 */
12389 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12390 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12391 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12392 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12397 static const struct hda_verb alc262_HP_BPC_init_verbs[] = {
12399 * Unmute ADC0-2 and set the default input to mic-in
12401 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
12402 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12403 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
12404 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12405 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
12406 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12408 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
12409 * mixer widget
12410 * Note: PASD motherboards uses the Line In 2 as the input for
12411 * front panel mic (mic 2)
12413 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
12414 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12415 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12416 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
12417 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
12418 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
12419 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
12420 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
12423 * Set up output mixers (0x0c - 0x0e)
12425 /* set vol=0 to output mixers */
12426 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12427 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12428 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12430 /* set up input amps for analog loopback */
12431 /* Amp Indices: DAC = 0, mixer = 1 */
12432 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12433 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12434 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12435 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12436 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12437 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12439 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12440 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12441 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12443 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12444 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12446 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
12447 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
12449 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12450 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12451 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12452 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12453 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12455 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12456 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12457 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12458 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12459 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12460 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12463 /* FIXME: use matrix-type input source selection */
12464 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 0b, 12 */
12465 /* Input mixer1: only unmute Mic */
12466 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12467 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
12468 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12469 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12470 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12471 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
12472 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
12473 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
12474 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
12475 /* Input mixer2 */
12476 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12477 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
12478 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12479 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12480 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12481 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
12482 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
12483 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
12484 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
12485 /* Input mixer3 */
12486 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12487 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
12488 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12489 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12490 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12491 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
12492 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
12493 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
12494 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
12496 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12501 static const struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
12503 * Unmute ADC0-2 and set the default input to mic-in
12505 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
12506 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12507 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
12508 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12509 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
12510 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12512 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
12513 * mixer widget
12514 * Note: PASD motherboards uses the Line In 2 as the input for front
12515 * panel mic (mic 2)
12517 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
12518 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12519 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12520 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
12521 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
12522 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
12523 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
12524 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
12525 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
12527 * Set up output mixers (0x0c - 0x0e)
12529 /* set vol=0 to output mixers */
12530 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12531 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12532 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12534 /* set up input amps for analog loopback */
12535 /* Amp Indices: DAC = 0, mixer = 1 */
12536 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12537 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12538 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12539 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12540 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12541 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12544 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */
12545 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */
12546 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */
12547 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */
12548 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
12549 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */
12550 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */
12552 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12553 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12555 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
12556 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
12558 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
12559 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12560 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12561 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
12562 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12563 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12565 /* FIXME: use matrix-type input source selection */
12566 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
12567 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
12568 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
12569 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
12570 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
12571 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
12572 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
12573 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
12574 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
12575 /* Input mixer2 */
12576 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12577 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
12578 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
12579 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
12580 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
12581 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
12582 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
12583 /* Input mixer3 */
12584 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12585 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
12586 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
12587 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
12588 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
12589 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
12590 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
12592 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12597 static const struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
12599 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Front Speaker */
12600 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12601 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
12603 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* MIC jack */
12604 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
12605 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
12606 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
12608 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP jack */
12609 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
12610 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
12615 * Pin config fixes
12617 enum {
12618 PINFIX_FSC_H270,
12619 PINFIX_HP_Z200,
12622 static const struct alc_fixup alc262_fixups[] = {
12623 [PINFIX_FSC_H270] = {
12624 .type = ALC_FIXUP_PINS,
12625 .v.pins = (const struct alc_pincfg[]) {
12626 { 0x14, 0x99130110 }, /* speaker */
12627 { 0x15, 0x0221142f }, /* front HP */
12628 { 0x1b, 0x0121141f }, /* rear HP */
12632 [PINFIX_HP_Z200] = {
12633 .type = ALC_FIXUP_PINS,
12634 .v.pins = (const struct alc_pincfg[]) {
12635 { 0x16, 0x99130120 }, /* internal speaker */
12641 static const struct snd_pci_quirk alc262_fixup_tbl[] = {
12642 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
12643 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
12648 #ifdef CONFIG_SND_HDA_POWER_SAVE
12649 #define alc262_loopbacks alc880_loopbacks
12650 #endif
12652 /* pcm configuration: identical with ALC880 */
12653 #define alc262_pcm_analog_playback alc880_pcm_analog_playback
12654 #define alc262_pcm_analog_capture alc880_pcm_analog_capture
12655 #define alc262_pcm_digital_playback alc880_pcm_digital_playback
12656 #define alc262_pcm_digital_capture alc880_pcm_digital_capture
12659 * BIOS auto configuration
12661 static int alc262_parse_auto_config(struct hda_codec *codec)
12663 struct alc_spec *spec = codec->spec;
12664 int err;
12665 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
12667 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
12668 alc262_ignore);
12669 if (err < 0)
12670 return err;
12671 if (!spec->autocfg.line_outs) {
12672 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
12673 spec->multiout.max_channels = 2;
12674 spec->no_analog = 1;
12675 goto dig_only;
12677 return 0; /* can't find valid BIOS pin config */
12679 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
12680 if (err < 0)
12681 return err;
12682 err = alc262_auto_create_input_ctls(codec, &spec->autocfg);
12683 if (err < 0)
12684 return err;
12686 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
12688 dig_only:
12689 alc_auto_parse_digital(codec);
12691 if (spec->kctls.list)
12692 add_mixer(spec, spec->kctls.list);
12694 add_verb(spec, alc262_volume_init_verbs);
12695 spec->num_mux_defs = 1;
12696 spec->input_mux = &spec->private_imux[0];
12698 err = alc_auto_add_mic_boost(codec);
12699 if (err < 0)
12700 return err;
12702 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
12704 return 1;
12707 #define alc262_auto_init_multi_out alc882_auto_init_multi_out
12708 #define alc262_auto_init_hp_out alc882_auto_init_hp_out
12709 #define alc262_auto_init_analog_input alc882_auto_init_analog_input
12710 #define alc262_auto_init_input_src alc882_auto_init_input_src
12713 /* init callback for auto-configuration model -- overriding the default init */
12714 static void alc262_auto_init(struct hda_codec *codec)
12716 struct alc_spec *spec = codec->spec;
12717 alc262_auto_init_multi_out(codec);
12718 alc262_auto_init_hp_out(codec);
12719 alc262_auto_init_analog_input(codec);
12720 alc262_auto_init_input_src(codec);
12721 alc_auto_init_digital(codec);
12722 if (spec->unsol_event)
12723 alc_inithook(codec);
12727 * configuration and preset
12729 static const char * const alc262_models[ALC262_MODEL_LAST] = {
12730 [ALC262_BASIC] = "basic",
12731 [ALC262_HIPPO] = "hippo",
12732 [ALC262_HIPPO_1] = "hippo_1",
12733 [ALC262_FUJITSU] = "fujitsu",
12734 [ALC262_HP_BPC] = "hp-bpc",
12735 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
12736 [ALC262_HP_TC_T5735] = "hp-tc-t5735",
12737 [ALC262_HP_RP5700] = "hp-rp5700",
12738 [ALC262_BENQ_ED8] = "benq",
12739 [ALC262_BENQ_T31] = "benq-t31",
12740 [ALC262_SONY_ASSAMD] = "sony-assamd",
12741 [ALC262_TOSHIBA_S06] = "toshiba-s06",
12742 [ALC262_TOSHIBA_RX1] = "toshiba-rx1",
12743 [ALC262_ULTRA] = "ultra",
12744 [ALC262_LENOVO_3000] = "lenovo-3000",
12745 [ALC262_NEC] = "nec",
12746 [ALC262_TYAN] = "tyan",
12747 [ALC262_AUTO] = "auto",
12750 static const struct snd_pci_quirk alc262_cfg_tbl[] = {
12751 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
12752 SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
12753 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
12754 ALC262_HP_BPC),
12755 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series",
12756 ALC262_HP_BPC),
12757 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1500, "HP z series",
12758 ALC262_HP_BPC),
12759 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200",
12760 ALC262_AUTO),
12761 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
12762 ALC262_HP_BPC),
12763 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
12764 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
12765 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
12766 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
12767 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
12768 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
12769 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
12770 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
12771 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
12772 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
12773 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
12774 SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735",
12775 ALC262_HP_TC_T5735),
12776 SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700),
12777 SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
12778 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
12779 SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
12780 SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */
12781 SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06),
12782 SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO),
12783 SND_PCI_QUIRK(0x104d, 0x9047, "Sony VAIO Type G", ALC262_AUTO),
12784 #if 0 /* disable the quirk since model=auto works better in recent versions */
12785 SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
12786 ALC262_SONY_ASSAMD),
12787 #endif
12788 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
12789 ALC262_TOSHIBA_RX1),
12790 SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
12791 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
12792 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
12793 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN),
12794 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
12795 ALC262_ULTRA),
12796 SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
12797 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
12798 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
12799 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
12800 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
12804 static const struct alc_config_preset alc262_presets[] = {
12805 [ALC262_BASIC] = {
12806 .mixers = { alc262_base_mixer },
12807 .init_verbs = { alc262_init_verbs },
12808 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12809 .dac_nids = alc262_dac_nids,
12810 .hp_nid = 0x03,
12811 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12812 .channel_mode = alc262_modes,
12813 .input_mux = &alc262_capture_source,
12815 [ALC262_HIPPO] = {
12816 .mixers = { alc262_hippo_mixer },
12817 .init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
12818 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12819 .dac_nids = alc262_dac_nids,
12820 .hp_nid = 0x03,
12821 .dig_out_nid = ALC262_DIGOUT_NID,
12822 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12823 .channel_mode = alc262_modes,
12824 .input_mux = &alc262_capture_source,
12825 .unsol_event = alc_sku_unsol_event,
12826 .setup = alc262_hippo_setup,
12827 .init_hook = alc_inithook,
12829 [ALC262_HIPPO_1] = {
12830 .mixers = { alc262_hippo1_mixer },
12831 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
12832 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12833 .dac_nids = alc262_dac_nids,
12834 .hp_nid = 0x02,
12835 .dig_out_nid = ALC262_DIGOUT_NID,
12836 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12837 .channel_mode = alc262_modes,
12838 .input_mux = &alc262_capture_source,
12839 .unsol_event = alc_sku_unsol_event,
12840 .setup = alc262_hippo1_setup,
12841 .init_hook = alc_inithook,
12843 [ALC262_FUJITSU] = {
12844 .mixers = { alc262_fujitsu_mixer },
12845 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
12846 alc262_fujitsu_unsol_verbs },
12847 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12848 .dac_nids = alc262_dac_nids,
12849 .hp_nid = 0x03,
12850 .dig_out_nid = ALC262_DIGOUT_NID,
12851 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12852 .channel_mode = alc262_modes,
12853 .input_mux = &alc262_fujitsu_capture_source,
12854 .unsol_event = alc_sku_unsol_event,
12855 .setup = alc262_fujitsu_setup,
12856 .init_hook = alc_inithook,
12858 [ALC262_HP_BPC] = {
12859 .mixers = { alc262_HP_BPC_mixer },
12860 .init_verbs = { alc262_HP_BPC_init_verbs },
12861 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12862 .dac_nids = alc262_dac_nids,
12863 .hp_nid = 0x03,
12864 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12865 .channel_mode = alc262_modes,
12866 .input_mux = &alc262_HP_capture_source,
12867 .unsol_event = alc_sku_unsol_event,
12868 .setup = alc262_hp_bpc_setup,
12869 .init_hook = alc_inithook,
12871 [ALC262_HP_BPC_D7000_WF] = {
12872 .mixers = { alc262_HP_BPC_WildWest_mixer },
12873 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
12874 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12875 .dac_nids = alc262_dac_nids,
12876 .hp_nid = 0x03,
12877 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12878 .channel_mode = alc262_modes,
12879 .input_mux = &alc262_HP_D7000_capture_source,
12880 .unsol_event = alc_sku_unsol_event,
12881 .setup = alc262_hp_wildwest_setup,
12882 .init_hook = alc_inithook,
12884 [ALC262_HP_BPC_D7000_WL] = {
12885 .mixers = { alc262_HP_BPC_WildWest_mixer,
12886 alc262_HP_BPC_WildWest_option_mixer },
12887 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
12888 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12889 .dac_nids = alc262_dac_nids,
12890 .hp_nid = 0x03,
12891 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12892 .channel_mode = alc262_modes,
12893 .input_mux = &alc262_HP_D7000_capture_source,
12894 .unsol_event = alc_sku_unsol_event,
12895 .setup = alc262_hp_wildwest_setup,
12896 .init_hook = alc_inithook,
12898 [ALC262_HP_TC_T5735] = {
12899 .mixers = { alc262_hp_t5735_mixer },
12900 .init_verbs = { alc262_init_verbs, alc262_hp_t5735_verbs },
12901 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12902 .dac_nids = alc262_dac_nids,
12903 .hp_nid = 0x03,
12904 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12905 .channel_mode = alc262_modes,
12906 .input_mux = &alc262_capture_source,
12907 .unsol_event = alc_sku_unsol_event,
12908 .setup = alc262_hp_t5735_setup,
12909 .init_hook = alc_inithook,
12911 [ALC262_HP_RP5700] = {
12912 .mixers = { alc262_hp_rp5700_mixer },
12913 .init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs },
12914 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12915 .dac_nids = alc262_dac_nids,
12916 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12917 .channel_mode = alc262_modes,
12918 .input_mux = &alc262_hp_rp5700_capture_source,
12920 [ALC262_BENQ_ED8] = {
12921 .mixers = { alc262_base_mixer },
12922 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
12923 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12924 .dac_nids = alc262_dac_nids,
12925 .hp_nid = 0x03,
12926 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12927 .channel_mode = alc262_modes,
12928 .input_mux = &alc262_capture_source,
12930 [ALC262_SONY_ASSAMD] = {
12931 .mixers = { alc262_sony_mixer },
12932 .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
12933 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12934 .dac_nids = alc262_dac_nids,
12935 .hp_nid = 0x02,
12936 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12937 .channel_mode = alc262_modes,
12938 .input_mux = &alc262_capture_source,
12939 .unsol_event = alc_sku_unsol_event,
12940 .setup = alc262_hippo_setup,
12941 .init_hook = alc_inithook,
12943 [ALC262_BENQ_T31] = {
12944 .mixers = { alc262_benq_t31_mixer },
12945 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
12946 alc_hp15_unsol_verbs },
12947 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12948 .dac_nids = alc262_dac_nids,
12949 .hp_nid = 0x03,
12950 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12951 .channel_mode = alc262_modes,
12952 .input_mux = &alc262_capture_source,
12953 .unsol_event = alc_sku_unsol_event,
12954 .setup = alc262_hippo_setup,
12955 .init_hook = alc_inithook,
12957 [ALC262_ULTRA] = {
12958 .mixers = { alc262_ultra_mixer },
12959 .cap_mixer = alc262_ultra_capture_mixer,
12960 .init_verbs = { alc262_ultra_verbs },
12961 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12962 .dac_nids = alc262_dac_nids,
12963 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12964 .channel_mode = alc262_modes,
12965 .input_mux = &alc262_ultra_capture_source,
12966 .adc_nids = alc262_adc_nids, /* ADC0 */
12967 .capsrc_nids = alc262_capsrc_nids,
12968 .num_adc_nids = 1, /* single ADC */
12969 .unsol_event = alc262_ultra_unsol_event,
12970 .init_hook = alc262_ultra_automute,
12972 [ALC262_LENOVO_3000] = {
12973 .mixers = { alc262_lenovo_3000_mixer },
12974 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
12975 alc262_lenovo_3000_unsol_verbs,
12976 alc262_lenovo_3000_init_verbs },
12977 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12978 .dac_nids = alc262_dac_nids,
12979 .hp_nid = 0x03,
12980 .dig_out_nid = ALC262_DIGOUT_NID,
12981 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12982 .channel_mode = alc262_modes,
12983 .input_mux = &alc262_fujitsu_capture_source,
12984 .unsol_event = alc_sku_unsol_event,
12985 .setup = alc262_lenovo_3000_setup,
12986 .init_hook = alc_inithook,
12988 [ALC262_NEC] = {
12989 .mixers = { alc262_nec_mixer },
12990 .init_verbs = { alc262_nec_verbs },
12991 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12992 .dac_nids = alc262_dac_nids,
12993 .hp_nid = 0x03,
12994 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12995 .channel_mode = alc262_modes,
12996 .input_mux = &alc262_capture_source,
12998 [ALC262_TOSHIBA_S06] = {
12999 .mixers = { alc262_toshiba_s06_mixer },
13000 .init_verbs = { alc262_init_verbs, alc262_toshiba_s06_verbs,
13001 alc262_eapd_verbs },
13002 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
13003 .capsrc_nids = alc262_dmic_capsrc_nids,
13004 .dac_nids = alc262_dac_nids,
13005 .adc_nids = alc262_dmic_adc_nids, /* ADC0 */
13006 .num_adc_nids = 1, /* single ADC */
13007 .dig_out_nid = ALC262_DIGOUT_NID,
13008 .num_channel_mode = ARRAY_SIZE(alc262_modes),
13009 .channel_mode = alc262_modes,
13010 .unsol_event = alc_sku_unsol_event,
13011 .setup = alc262_toshiba_s06_setup,
13012 .init_hook = alc_inithook,
13014 [ALC262_TOSHIBA_RX1] = {
13015 .mixers = { alc262_toshiba_rx1_mixer },
13016 .init_verbs = { alc262_init_verbs, alc262_toshiba_rx1_unsol_verbs },
13017 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
13018 .dac_nids = alc262_dac_nids,
13019 .hp_nid = 0x03,
13020 .num_channel_mode = ARRAY_SIZE(alc262_modes),
13021 .channel_mode = alc262_modes,
13022 .input_mux = &alc262_capture_source,
13023 .unsol_event = alc_sku_unsol_event,
13024 .setup = alc262_hippo_setup,
13025 .init_hook = alc_inithook,
13027 [ALC262_TYAN] = {
13028 .mixers = { alc262_tyan_mixer },
13029 .init_verbs = { alc262_init_verbs, alc262_tyan_verbs},
13030 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
13031 .dac_nids = alc262_dac_nids,
13032 .hp_nid = 0x02,
13033 .dig_out_nid = ALC262_DIGOUT_NID,
13034 .num_channel_mode = ARRAY_SIZE(alc262_modes),
13035 .channel_mode = alc262_modes,
13036 .input_mux = &alc262_capture_source,
13037 .unsol_event = alc_sku_unsol_event,
13038 .setup = alc262_tyan_setup,
13039 .init_hook = alc_hp_automute,
13043 static int patch_alc262(struct hda_codec *codec)
13045 struct alc_spec *spec;
13046 int board_config;
13047 int err;
13049 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
13050 if (spec == NULL)
13051 return -ENOMEM;
13053 codec->spec = spec;
13054 #if 0
13055 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
13056 * under-run
13059 int tmp;
13060 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
13061 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
13062 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
13063 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
13065 #endif
13066 alc_auto_parse_customize_define(codec);
13068 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
13070 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
13071 alc262_models,
13072 alc262_cfg_tbl);
13074 if (board_config < 0) {
13075 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
13076 codec->chip_name);
13077 board_config = ALC262_AUTO;
13080 if (board_config == ALC262_AUTO) {
13081 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
13082 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
13085 if (board_config == ALC262_AUTO) {
13086 /* automatic parse from the BIOS config */
13087 err = alc262_parse_auto_config(codec);
13088 if (err < 0) {
13089 alc_free(codec);
13090 return err;
13091 } else if (!err) {
13092 printk(KERN_INFO
13093 "hda_codec: Cannot set up configuration "
13094 "from BIOS. Using base mode...\n");
13095 board_config = ALC262_BASIC;
13099 if (!spec->no_analog && has_cdefine_beep(codec)) {
13100 err = snd_hda_attach_beep_device(codec, 0x1);
13101 if (err < 0) {
13102 alc_free(codec);
13103 return err;
13107 if (board_config != ALC262_AUTO)
13108 setup_preset(codec, &alc262_presets[board_config]);
13110 spec->stream_analog_playback = &alc262_pcm_analog_playback;
13111 spec->stream_analog_capture = &alc262_pcm_analog_capture;
13113 spec->stream_digital_playback = &alc262_pcm_digital_playback;
13114 spec->stream_digital_capture = &alc262_pcm_digital_capture;
13116 if (!spec->adc_nids && spec->input_mux) {
13117 int i;
13118 /* check whether the digital-mic has to be supported */
13119 for (i = 0; i < spec->input_mux->num_items; i++) {
13120 if (spec->input_mux->items[i].index >= 9)
13121 break;
13123 if (i < spec->input_mux->num_items) {
13124 /* use only ADC0 */
13125 spec->adc_nids = alc262_dmic_adc_nids;
13126 spec->num_adc_nids = 1;
13127 spec->capsrc_nids = alc262_dmic_capsrc_nids;
13128 } else {
13129 /* all analog inputs */
13130 /* check whether NID 0x07 is valid */
13131 unsigned int wcap = get_wcaps(codec, 0x07);
13133 /* get type */
13134 wcap = get_wcaps_type(wcap);
13135 if (wcap != AC_WID_AUD_IN) {
13136 spec->adc_nids = alc262_adc_nids_alt;
13137 spec->num_adc_nids =
13138 ARRAY_SIZE(alc262_adc_nids_alt);
13139 spec->capsrc_nids = alc262_capsrc_nids_alt;
13140 } else {
13141 spec->adc_nids = alc262_adc_nids;
13142 spec->num_adc_nids =
13143 ARRAY_SIZE(alc262_adc_nids);
13144 spec->capsrc_nids = alc262_capsrc_nids;
13148 if (!spec->cap_mixer && !spec->no_analog)
13149 set_capture_mixer(codec);
13150 if (!spec->no_analog && has_cdefine_beep(codec))
13151 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
13153 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
13155 spec->vmaster_nid = 0x0c;
13157 codec->patch_ops = alc_patch_ops;
13158 if (board_config == ALC262_AUTO)
13159 spec->init_hook = alc262_auto_init;
13160 spec->shutup = alc_eapd_shutup;
13162 alc_init_jacks(codec);
13163 #ifdef CONFIG_SND_HDA_POWER_SAVE
13164 if (!spec->loopback.amplist)
13165 spec->loopback.amplist = alc262_loopbacks;
13166 #endif
13168 return 0;
13172 * ALC268 channel source setting (2 channel)
13174 #define ALC268_DIGOUT_NID ALC880_DIGOUT_NID
13175 #define alc268_modes alc260_modes
13177 static const hda_nid_t alc268_dac_nids[2] = {
13178 /* front, hp */
13179 0x02, 0x03
13182 static const hda_nid_t alc268_adc_nids[2] = {
13183 /* ADC0-1 */
13184 0x08, 0x07
13187 static const hda_nid_t alc268_adc_nids_alt[1] = {
13188 /* ADC0 */
13189 0x08
13192 static const hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
13194 static const struct snd_kcontrol_new alc268_base_mixer[] = {
13195 /* output mixer control */
13196 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
13197 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13198 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
13199 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
13200 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13201 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
13202 HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
13206 static const struct snd_kcontrol_new alc268_toshiba_mixer[] = {
13207 /* output mixer control */
13208 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
13209 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
13210 ALC262_HIPPO_MASTER_SWITCH,
13211 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13212 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
13213 HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
13217 /* bind Beep switches of both NID 0x0f and 0x10 */
13218 static const struct hda_bind_ctls alc268_bind_beep_sw = {
13219 .ops = &snd_hda_bind_sw,
13220 .values = {
13221 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
13222 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
13227 static const struct snd_kcontrol_new alc268_beep_mixer[] = {
13228 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
13229 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
13233 static const struct hda_verb alc268_eapd_verbs[] = {
13234 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
13235 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
13239 /* Toshiba specific */
13240 static const struct hda_verb alc268_toshiba_verbs[] = {
13241 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13242 { } /* end */
13245 /* Acer specific */
13246 /* bind volumes of both NID 0x02 and 0x03 */
13247 static const struct hda_bind_ctls alc268_acer_bind_master_vol = {
13248 .ops = &snd_hda_bind_vol,
13249 .values = {
13250 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
13251 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
13256 static void alc268_acer_setup(struct hda_codec *codec)
13258 struct alc_spec *spec = codec->spec;
13260 spec->autocfg.hp_pins[0] = 0x14;
13261 spec->autocfg.speaker_pins[0] = 0x15;
13262 spec->automute = 1;
13263 spec->automute_mode = ALC_AUTOMUTE_AMP;
13266 #define alc268_acer_master_sw_get alc262_hp_master_sw_get
13267 #define alc268_acer_master_sw_put alc262_hp_master_sw_put
13269 static const struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
13270 /* output mixer control */
13271 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13273 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13274 .name = "Master Playback Switch",
13275 .subdevice = HDA_SUBDEV_NID_FLAG | 0x15,
13276 .info = snd_ctl_boolean_mono_info,
13277 .get = alc268_acer_master_sw_get,
13278 .put = alc268_acer_master_sw_put,
13280 HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
13284 static const struct snd_kcontrol_new alc268_acer_mixer[] = {
13285 /* output mixer control */
13286 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13288 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13289 .name = "Master Playback Switch",
13290 .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
13291 .info = snd_ctl_boolean_mono_info,
13292 .get = alc268_acer_master_sw_get,
13293 .put = alc268_acer_master_sw_put,
13295 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13296 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
13297 HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
13301 static const struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
13302 /* output mixer control */
13303 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13305 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13306 .name = "Master Playback Switch",
13307 .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
13308 .info = snd_ctl_boolean_mono_info,
13309 .get = alc268_acer_master_sw_get,
13310 .put = alc268_acer_master_sw_put,
13312 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13313 HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
13317 static const struct hda_verb alc268_acer_aspire_one_verbs[] = {
13318 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13319 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13320 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13321 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13322 {0x23, AC_VERB_SET_CONNECT_SEL, 0x06},
13323 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, 0xa017},
13327 static const struct hda_verb alc268_acer_verbs[] = {
13328 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
13329 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13330 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13331 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13332 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13333 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13334 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13338 /* unsolicited event for HP jack sensing */
13339 #define alc268_toshiba_setup alc262_hippo_setup
13341 static void alc268_acer_lc_setup(struct hda_codec *codec)
13343 struct alc_spec *spec = codec->spec;
13344 spec->autocfg.hp_pins[0] = 0x15;
13345 spec->autocfg.speaker_pins[0] = 0x14;
13346 spec->automute = 1;
13347 spec->automute_mode = ALC_AUTOMUTE_AMP;
13348 spec->ext_mic.pin = 0x18;
13349 spec->ext_mic.mux_idx = 0;
13350 spec->int_mic.pin = 0x12;
13351 spec->int_mic.mux_idx = 6;
13352 spec->auto_mic = 1;
13355 static const struct snd_kcontrol_new alc268_dell_mixer[] = {
13356 /* output mixer control */
13357 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13358 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13359 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13360 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
13361 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13362 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
13366 static const struct hda_verb alc268_dell_verbs[] = {
13367 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13368 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13369 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13370 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
13374 /* mute/unmute internal speaker according to the hp jack and mute state */
13375 static void alc268_dell_setup(struct hda_codec *codec)
13377 struct alc_spec *spec = codec->spec;
13379 spec->autocfg.hp_pins[0] = 0x15;
13380 spec->autocfg.speaker_pins[0] = 0x14;
13381 spec->ext_mic.pin = 0x18;
13382 spec->ext_mic.mux_idx = 0;
13383 spec->int_mic.pin = 0x19;
13384 spec->int_mic.mux_idx = 1;
13385 spec->auto_mic = 1;
13386 spec->automute = 1;
13387 spec->automute_mode = ALC_AUTOMUTE_PIN;
13390 static const struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
13391 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
13392 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13393 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
13394 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
13395 HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13396 HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
13397 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13398 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
13402 static const struct hda_verb alc267_quanta_il1_verbs[] = {
13403 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13404 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
13408 static void alc267_quanta_il1_setup(struct hda_codec *codec)
13410 struct alc_spec *spec = codec->spec;
13411 spec->autocfg.hp_pins[0] = 0x15;
13412 spec->autocfg.speaker_pins[0] = 0x14;
13413 spec->ext_mic.pin = 0x18;
13414 spec->ext_mic.mux_idx = 0;
13415 spec->int_mic.pin = 0x19;
13416 spec->int_mic.mux_idx = 1;
13417 spec->auto_mic = 1;
13418 spec->automute = 1;
13419 spec->automute_mode = ALC_AUTOMUTE_PIN;
13423 * generic initialization of ADC, input mixers and output mixers
13425 static const struct hda_verb alc268_base_init_verbs[] = {
13426 /* Unmute DAC0-1 and set vol = 0 */
13427 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13428 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13431 * Set up output mixers (0x0c - 0x0e)
13433 /* set vol=0 to output mixers */
13434 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13435 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
13437 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13438 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13440 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
13441 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
13442 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
13443 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13444 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13445 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13446 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13447 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13449 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13450 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13451 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13452 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13453 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13455 /* set PCBEEP vol = 0, mute connections */
13456 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13457 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13458 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13460 /* Unmute Selector 23h,24h and set the default input to mic-in */
13462 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
13463 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13464 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
13465 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13471 * generic initialization of ADC, input mixers and output mixers
13473 static const struct hda_verb alc268_volume_init_verbs[] = {
13474 /* set output DAC */
13475 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13476 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13478 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13479 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13480 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13481 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13482 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13484 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13485 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13486 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13488 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13489 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13491 /* set PCBEEP vol = 0, mute connections */
13492 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13493 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13494 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13499 static const struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
13500 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13501 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
13502 { } /* end */
13505 static const struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
13506 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13507 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
13508 _DEFINE_CAPSRC(1),
13509 { } /* end */
13512 static const struct snd_kcontrol_new alc268_capture_mixer[] = {
13513 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13514 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
13515 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
13516 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
13517 _DEFINE_CAPSRC(2),
13518 { } /* end */
13521 static const struct hda_input_mux alc268_capture_source = {
13522 .num_items = 4,
13523 .items = {
13524 { "Mic", 0x0 },
13525 { "Front Mic", 0x1 },
13526 { "Line", 0x2 },
13527 { "CD", 0x3 },
13531 static const struct hda_input_mux alc268_acer_capture_source = {
13532 .num_items = 3,
13533 .items = {
13534 { "Mic", 0x0 },
13535 { "Internal Mic", 0x1 },
13536 { "Line", 0x2 },
13540 static const struct hda_input_mux alc268_acer_dmic_capture_source = {
13541 .num_items = 3,
13542 .items = {
13543 { "Mic", 0x0 },
13544 { "Internal Mic", 0x6 },
13545 { "Line", 0x2 },
13549 #ifdef CONFIG_SND_DEBUG
13550 static const struct snd_kcontrol_new alc268_test_mixer[] = {
13551 /* Volume widgets */
13552 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13553 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13554 HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),
13555 HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),
13556 HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),
13557 HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),
13558 HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),
13559 HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),
13560 HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),
13561 HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),
13562 HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),
13563 HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),
13564 HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),
13565 /* The below appears problematic on some hardwares */
13566 /*HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),*/
13567 HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13568 HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),
13569 HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),
13570 HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),
13572 /* Modes for retasking pin widgets */
13573 ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),
13574 ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),
13575 ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),
13576 ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),
13578 /* Controls for GPIO pins, assuming they are configured as outputs */
13579 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
13580 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
13581 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
13582 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
13584 /* Switches to allow the digital SPDIF output pin to be enabled.
13585 * The ALC268 does not have an SPDIF input.
13587 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),
13589 /* A switch allowing EAPD to be enabled. Some laptops seem to use
13590 * this output to turn on an external amplifier.
13592 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
13593 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
13595 { } /* end */
13597 #endif
13599 /* create input playback/capture controls for the given pin */
13600 static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
13601 const char *ctlname, int idx)
13603 hda_nid_t dac;
13604 int err;
13606 switch (nid) {
13607 case 0x14:
13608 case 0x16:
13609 dac = 0x02;
13610 break;
13611 case 0x15:
13612 case 0x1a: /* ALC259/269 only */
13613 case 0x1b: /* ALC259/269 only */
13614 case 0x21: /* ALC269vb has this pin, too */
13615 dac = 0x03;
13616 break;
13617 default:
13618 snd_printd(KERN_WARNING "hda_codec: "
13619 "ignoring pin 0x%x as unknown\n", nid);
13620 return 0;
13622 if (spec->multiout.dac_nids[0] != dac &&
13623 spec->multiout.dac_nids[1] != dac) {
13624 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
13625 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
13626 HDA_OUTPUT));
13627 if (err < 0)
13628 return err;
13629 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
13632 if (nid != 0x16)
13633 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
13634 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
13635 else /* mono */
13636 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
13637 HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT));
13638 if (err < 0)
13639 return err;
13640 return 0;
13643 /* add playback controls from the parsed DAC table */
13644 static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
13645 const struct auto_pin_cfg *cfg)
13647 hda_nid_t nid;
13648 int err;
13650 spec->multiout.dac_nids = spec->private_dac_nids;
13652 nid = cfg->line_out_pins[0];
13653 if (nid) {
13654 const char *name;
13655 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
13656 name = "Speaker";
13657 else
13658 name = "Front";
13659 err = alc268_new_analog_output(spec, nid, name, 0);
13660 if (err < 0)
13661 return err;
13664 nid = cfg->speaker_pins[0];
13665 if (nid == 0x1d) {
13666 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, "Speaker",
13667 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
13668 if (err < 0)
13669 return err;
13670 } else if (nid) {
13671 err = alc268_new_analog_output(spec, nid, "Speaker", 0);
13672 if (err < 0)
13673 return err;
13675 nid = cfg->hp_pins[0];
13676 if (nid) {
13677 err = alc268_new_analog_output(spec, nid, "Headphone", 0);
13678 if (err < 0)
13679 return err;
13682 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
13683 if (nid == 0x16) {
13684 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, "Mono",
13685 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT));
13686 if (err < 0)
13687 return err;
13689 return 0;
13692 /* create playback/capture controls for input pins */
13693 static int alc268_auto_create_input_ctls(struct hda_codec *codec,
13694 const struct auto_pin_cfg *cfg)
13696 return alc_auto_create_input_ctls(codec, cfg, 0, 0x23, 0x24);
13699 static void alc268_auto_set_output_and_unmute(struct hda_codec *codec,
13700 hda_nid_t nid, int pin_type)
13702 int idx;
13704 alc_set_pin_output(codec, nid, pin_type);
13705 if (nid == 0x14 || nid == 0x16)
13706 idx = 0;
13707 else
13708 idx = 1;
13709 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
13712 static void alc268_auto_init_multi_out(struct hda_codec *codec)
13714 struct alc_spec *spec = codec->spec;
13715 int i;
13717 for (i = 0; i < spec->autocfg.line_outs; i++) {
13718 hda_nid_t nid = spec->autocfg.line_out_pins[i];
13719 int pin_type = get_pin_type(spec->autocfg.line_out_type);
13720 alc268_auto_set_output_and_unmute(codec, nid, pin_type);
13724 static void alc268_auto_init_hp_out(struct hda_codec *codec)
13726 struct alc_spec *spec = codec->spec;
13727 hda_nid_t pin;
13728 int i;
13730 for (i = 0; i < spec->autocfg.hp_outs; i++) {
13731 pin = spec->autocfg.hp_pins[i];
13732 alc268_auto_set_output_and_unmute(codec, pin, PIN_HP);
13734 for (i = 0; i < spec->autocfg.speaker_outs; i++) {
13735 pin = spec->autocfg.speaker_pins[i];
13736 alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT);
13738 if (spec->autocfg.mono_out_pin)
13739 snd_hda_codec_write(codec, spec->autocfg.mono_out_pin, 0,
13740 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
13743 static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
13745 struct alc_spec *spec = codec->spec;
13746 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
13747 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
13748 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
13749 unsigned int dac_vol1, dac_vol2;
13751 if (line_nid == 0x1d || speaker_nid == 0x1d) {
13752 snd_hda_codec_write(codec, speaker_nid, 0,
13753 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
13754 /* mute mixer inputs from 0x1d */
13755 snd_hda_codec_write(codec, 0x0f, 0,
13756 AC_VERB_SET_AMP_GAIN_MUTE,
13757 AMP_IN_UNMUTE(1));
13758 snd_hda_codec_write(codec, 0x10, 0,
13759 AC_VERB_SET_AMP_GAIN_MUTE,
13760 AMP_IN_UNMUTE(1));
13761 } else {
13762 /* unmute mixer inputs from 0x1d */
13763 snd_hda_codec_write(codec, 0x0f, 0,
13764 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
13765 snd_hda_codec_write(codec, 0x10, 0,
13766 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
13769 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */
13770 if (line_nid == 0x14)
13771 dac_vol2 = AMP_OUT_ZERO;
13772 else if (line_nid == 0x15)
13773 dac_vol1 = AMP_OUT_ZERO;
13774 if (hp_nid == 0x14)
13775 dac_vol2 = AMP_OUT_ZERO;
13776 else if (hp_nid == 0x15)
13777 dac_vol1 = AMP_OUT_ZERO;
13778 if (line_nid != 0x16 || hp_nid != 0x16 ||
13779 spec->autocfg.line_out_pins[1] != 0x16 ||
13780 spec->autocfg.line_out_pins[2] != 0x16)
13781 dac_vol1 = dac_vol2 = AMP_OUT_ZERO;
13783 snd_hda_codec_write(codec, 0x02, 0,
13784 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);
13785 snd_hda_codec_write(codec, 0x03, 0,
13786 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);
13789 /* pcm configuration: identical with ALC880 */
13790 #define alc268_pcm_analog_playback alc880_pcm_analog_playback
13791 #define alc268_pcm_analog_capture alc880_pcm_analog_capture
13792 #define alc268_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
13793 #define alc268_pcm_digital_playback alc880_pcm_digital_playback
13796 * BIOS auto configuration
13798 static int alc268_parse_auto_config(struct hda_codec *codec)
13800 struct alc_spec *spec = codec->spec;
13801 int err;
13802 static const hda_nid_t alc268_ignore[] = { 0 };
13804 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
13805 alc268_ignore);
13806 if (err < 0)
13807 return err;
13808 if (!spec->autocfg.line_outs) {
13809 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
13810 spec->multiout.max_channels = 2;
13811 spec->no_analog = 1;
13812 goto dig_only;
13814 return 0; /* can't find valid BIOS pin config */
13816 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
13817 if (err < 0)
13818 return err;
13819 err = alc268_auto_create_input_ctls(codec, &spec->autocfg);
13820 if (err < 0)
13821 return err;
13823 spec->multiout.max_channels = 2;
13825 dig_only:
13826 /* digital only support output */
13827 alc_auto_parse_digital(codec);
13828 if (spec->kctls.list)
13829 add_mixer(spec, spec->kctls.list);
13831 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d)
13832 add_mixer(spec, alc268_beep_mixer);
13834 add_verb(spec, alc268_volume_init_verbs);
13835 spec->num_mux_defs = 2;
13836 spec->input_mux = &spec->private_imux[0];
13838 err = alc_auto_add_mic_boost(codec);
13839 if (err < 0)
13840 return err;
13842 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
13844 return 1;
13847 #define alc268_auto_init_analog_input alc882_auto_init_analog_input
13848 #define alc268_auto_init_input_src alc882_auto_init_input_src
13850 /* init callback for auto-configuration model -- overriding the default init */
13851 static void alc268_auto_init(struct hda_codec *codec)
13853 struct alc_spec *spec = codec->spec;
13854 alc268_auto_init_multi_out(codec);
13855 alc268_auto_init_hp_out(codec);
13856 alc268_auto_init_mono_speaker_out(codec);
13857 alc268_auto_init_analog_input(codec);
13858 alc268_auto_init_input_src(codec);
13859 alc_auto_init_digital(codec);
13860 if (spec->unsol_event)
13861 alc_inithook(codec);
13865 * configuration and preset
13867 static const char * const alc268_models[ALC268_MODEL_LAST] = {
13868 [ALC267_QUANTA_IL1] = "quanta-il1",
13869 [ALC268_3ST] = "3stack",
13870 [ALC268_TOSHIBA] = "toshiba",
13871 [ALC268_ACER] = "acer",
13872 [ALC268_ACER_DMIC] = "acer-dmic",
13873 [ALC268_ACER_ASPIRE_ONE] = "acer-aspire",
13874 [ALC268_DELL] = "dell",
13875 [ALC268_ZEPTO] = "zepto",
13876 #ifdef CONFIG_SND_DEBUG
13877 [ALC268_TEST] = "test",
13878 #endif
13879 [ALC268_AUTO] = "auto",
13882 static const struct snd_pci_quirk alc268_cfg_tbl[] = {
13883 SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
13884 SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
13885 SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
13886 SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
13887 SND_PCI_QUIRK(0x1025, 0x0136, "Acer Aspire 5315", ALC268_ACER),
13888 SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
13889 ALC268_ACER_ASPIRE_ONE),
13890 SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
13891 SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO),
13892 SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
13893 "Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
13894 /* almost compatible with toshiba but with optional digital outs;
13895 * auto-probing seems working fine
13897 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP TX25xx series",
13898 ALC268_AUTO),
13899 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
13900 SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
13901 SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
13902 SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
13906 /* Toshiba laptops have no unique PCI SSID but only codec SSID */
13907 static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
13908 SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
13909 SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
13910 SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
13911 ALC268_TOSHIBA),
13915 static const struct alc_config_preset alc268_presets[] = {
13916 [ALC267_QUANTA_IL1] = {
13917 .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
13918 alc268_capture_nosrc_mixer },
13919 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13920 alc267_quanta_il1_verbs },
13921 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13922 .dac_nids = alc268_dac_nids,
13923 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13924 .adc_nids = alc268_adc_nids_alt,
13925 .hp_nid = 0x03,
13926 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13927 .channel_mode = alc268_modes,
13928 .unsol_event = alc_sku_unsol_event,
13929 .setup = alc267_quanta_il1_setup,
13930 .init_hook = alc_inithook,
13932 [ALC268_3ST] = {
13933 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
13934 alc268_beep_mixer },
13935 .init_verbs = { alc268_base_init_verbs },
13936 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13937 .dac_nids = alc268_dac_nids,
13938 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13939 .adc_nids = alc268_adc_nids_alt,
13940 .capsrc_nids = alc268_capsrc_nids,
13941 .hp_nid = 0x03,
13942 .dig_out_nid = ALC268_DIGOUT_NID,
13943 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13944 .channel_mode = alc268_modes,
13945 .input_mux = &alc268_capture_source,
13947 [ALC268_TOSHIBA] = {
13948 .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
13949 alc268_beep_mixer },
13950 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13951 alc268_toshiba_verbs },
13952 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13953 .dac_nids = alc268_dac_nids,
13954 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13955 .adc_nids = alc268_adc_nids_alt,
13956 .capsrc_nids = alc268_capsrc_nids,
13957 .hp_nid = 0x03,
13958 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13959 .channel_mode = alc268_modes,
13960 .input_mux = &alc268_capture_source,
13961 .unsol_event = alc_sku_unsol_event,
13962 .setup = alc268_toshiba_setup,
13963 .init_hook = alc_inithook,
13965 [ALC268_ACER] = {
13966 .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
13967 alc268_beep_mixer },
13968 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13969 alc268_acer_verbs },
13970 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13971 .dac_nids = alc268_dac_nids,
13972 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13973 .adc_nids = alc268_adc_nids_alt,
13974 .capsrc_nids = alc268_capsrc_nids,
13975 .hp_nid = 0x02,
13976 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13977 .channel_mode = alc268_modes,
13978 .input_mux = &alc268_acer_capture_source,
13979 .unsol_event = alc_sku_unsol_event,
13980 .setup = alc268_acer_setup,
13981 .init_hook = alc_inithook,
13983 [ALC268_ACER_DMIC] = {
13984 .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
13985 alc268_beep_mixer },
13986 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13987 alc268_acer_verbs },
13988 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13989 .dac_nids = alc268_dac_nids,
13990 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13991 .adc_nids = alc268_adc_nids_alt,
13992 .capsrc_nids = alc268_capsrc_nids,
13993 .hp_nid = 0x02,
13994 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13995 .channel_mode = alc268_modes,
13996 .input_mux = &alc268_acer_dmic_capture_source,
13997 .unsol_event = alc_sku_unsol_event,
13998 .setup = alc268_acer_setup,
13999 .init_hook = alc_inithook,
14001 [ALC268_ACER_ASPIRE_ONE] = {
14002 .mixers = { alc268_acer_aspire_one_mixer,
14003 alc268_beep_mixer,
14004 alc268_capture_nosrc_mixer },
14005 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
14006 alc268_acer_aspire_one_verbs },
14007 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
14008 .dac_nids = alc268_dac_nids,
14009 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
14010 .adc_nids = alc268_adc_nids_alt,
14011 .capsrc_nids = alc268_capsrc_nids,
14012 .hp_nid = 0x03,
14013 .num_channel_mode = ARRAY_SIZE(alc268_modes),
14014 .channel_mode = alc268_modes,
14015 .unsol_event = alc_sku_unsol_event,
14016 .setup = alc268_acer_lc_setup,
14017 .init_hook = alc_inithook,
14019 [ALC268_DELL] = {
14020 .mixers = { alc268_dell_mixer, alc268_beep_mixer,
14021 alc268_capture_nosrc_mixer },
14022 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
14023 alc268_dell_verbs },
14024 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
14025 .dac_nids = alc268_dac_nids,
14026 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
14027 .adc_nids = alc268_adc_nids_alt,
14028 .capsrc_nids = alc268_capsrc_nids,
14029 .hp_nid = 0x02,
14030 .num_channel_mode = ARRAY_SIZE(alc268_modes),
14031 .channel_mode = alc268_modes,
14032 .unsol_event = alc_sku_unsol_event,
14033 .setup = alc268_dell_setup,
14034 .init_hook = alc_inithook,
14036 [ALC268_ZEPTO] = {
14037 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
14038 alc268_beep_mixer },
14039 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
14040 alc268_toshiba_verbs },
14041 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
14042 .dac_nids = alc268_dac_nids,
14043 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
14044 .adc_nids = alc268_adc_nids_alt,
14045 .capsrc_nids = alc268_capsrc_nids,
14046 .hp_nid = 0x03,
14047 .dig_out_nid = ALC268_DIGOUT_NID,
14048 .num_channel_mode = ARRAY_SIZE(alc268_modes),
14049 .channel_mode = alc268_modes,
14050 .input_mux = &alc268_capture_source,
14051 .unsol_event = alc_sku_unsol_event,
14052 .setup = alc268_toshiba_setup,
14053 .init_hook = alc_inithook,
14055 #ifdef CONFIG_SND_DEBUG
14056 [ALC268_TEST] = {
14057 .mixers = { alc268_test_mixer, alc268_capture_mixer },
14058 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
14059 alc268_volume_init_verbs },
14060 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
14061 .dac_nids = alc268_dac_nids,
14062 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
14063 .adc_nids = alc268_adc_nids_alt,
14064 .capsrc_nids = alc268_capsrc_nids,
14065 .hp_nid = 0x03,
14066 .dig_out_nid = ALC268_DIGOUT_NID,
14067 .num_channel_mode = ARRAY_SIZE(alc268_modes),
14068 .channel_mode = alc268_modes,
14069 .input_mux = &alc268_capture_source,
14071 #endif
14074 static int patch_alc268(struct hda_codec *codec)
14076 struct alc_spec *spec;
14077 int board_config;
14078 int i, has_beep, err;
14080 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
14081 if (spec == NULL)
14082 return -ENOMEM;
14084 codec->spec = spec;
14086 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,
14087 alc268_models,
14088 alc268_cfg_tbl);
14090 if (board_config < 0 || board_config >= ALC268_MODEL_LAST)
14091 board_config = snd_hda_check_board_codec_sid_config(codec,
14092 ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
14094 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
14095 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
14096 codec->chip_name);
14097 board_config = ALC268_AUTO;
14100 if (board_config == ALC268_AUTO) {
14101 /* automatic parse from the BIOS config */
14102 err = alc268_parse_auto_config(codec);
14103 if (err < 0) {
14104 alc_free(codec);
14105 return err;
14106 } else if (!err) {
14107 printk(KERN_INFO
14108 "hda_codec: Cannot set up configuration "
14109 "from BIOS. Using base mode...\n");
14110 board_config = ALC268_3ST;
14114 if (board_config != ALC268_AUTO)
14115 setup_preset(codec, &alc268_presets[board_config]);
14117 spec->stream_analog_playback = &alc268_pcm_analog_playback;
14118 spec->stream_analog_capture = &alc268_pcm_analog_capture;
14119 spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;
14121 spec->stream_digital_playback = &alc268_pcm_digital_playback;
14123 has_beep = 0;
14124 for (i = 0; i < spec->num_mixers; i++) {
14125 if (spec->mixers[i] == alc268_beep_mixer) {
14126 has_beep = 1;
14127 break;
14131 if (has_beep) {
14132 err = snd_hda_attach_beep_device(codec, 0x1);
14133 if (err < 0) {
14134 alc_free(codec);
14135 return err;
14137 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
14138 /* override the amp caps for beep generator */
14139 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
14140 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
14141 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
14142 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
14143 (0 << AC_AMPCAP_MUTE_SHIFT));
14146 if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
14147 /* check whether NID 0x07 is valid */
14148 unsigned int wcap = get_wcaps(codec, 0x07);
14150 spec->capsrc_nids = alc268_capsrc_nids;
14151 /* get type */
14152 wcap = get_wcaps_type(wcap);
14153 if (spec->auto_mic ||
14154 wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
14155 spec->adc_nids = alc268_adc_nids_alt;
14156 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
14157 if (spec->auto_mic)
14158 fixup_automic_adc(codec);
14159 if (spec->auto_mic || spec->input_mux->num_items == 1)
14160 add_mixer(spec, alc268_capture_nosrc_mixer);
14161 else
14162 add_mixer(spec, alc268_capture_alt_mixer);
14163 } else {
14164 spec->adc_nids = alc268_adc_nids;
14165 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
14166 add_mixer(spec, alc268_capture_mixer);
14170 spec->vmaster_nid = 0x02;
14172 codec->patch_ops = alc_patch_ops;
14173 if (board_config == ALC268_AUTO)
14174 spec->init_hook = alc268_auto_init;
14175 spec->shutup = alc_eapd_shutup;
14177 alc_init_jacks(codec);
14179 return 0;
14183 * ALC269 channel source setting (2 channel)
14185 #define ALC269_DIGOUT_NID ALC880_DIGOUT_NID
14187 #define alc269_dac_nids alc260_dac_nids
14189 static const hda_nid_t alc269_adc_nids[1] = {
14190 /* ADC1 */
14191 0x08,
14194 static const hda_nid_t alc269_capsrc_nids[1] = {
14195 0x23,
14198 static const hda_nid_t alc269vb_adc_nids[1] = {
14199 /* ADC1 */
14200 0x09,
14203 static const hda_nid_t alc269vb_capsrc_nids[1] = {
14204 0x22,
14207 static const hda_nid_t alc269_adc_candidates[] = {
14208 0x08, 0x09, 0x07, 0x11,
14211 #define alc269_modes alc260_modes
14212 #define alc269_capture_source alc880_lg_lw_capture_source
14214 static const struct snd_kcontrol_new alc269_base_mixer[] = {
14215 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14216 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
14217 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
14218 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
14219 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
14220 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14221 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14222 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
14223 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
14224 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
14225 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
14226 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
14227 { } /* end */
14230 static const struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
14231 /* output mixer control */
14232 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
14234 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14235 .name = "Master Playback Switch",
14236 .subdevice = HDA_SUBDEV_AMP_FLAG,
14237 .info = snd_hda_mixer_amp_switch_info,
14238 .get = snd_hda_mixer_amp_switch_get,
14239 .put = alc268_acer_master_sw_put,
14240 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
14242 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
14243 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14244 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14245 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
14246 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
14247 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
14251 static const struct snd_kcontrol_new alc269_lifebook_mixer[] = {
14252 /* output mixer control */
14253 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
14255 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14256 .name = "Master Playback Switch",
14257 .subdevice = HDA_SUBDEV_AMP_FLAG,
14258 .info = snd_hda_mixer_amp_switch_info,
14259 .get = snd_hda_mixer_amp_switch_get,
14260 .put = alc268_acer_master_sw_put,
14261 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
14263 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
14264 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14265 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14266 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
14267 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
14268 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
14269 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
14270 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
14271 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x1b, 0, HDA_INPUT),
14275 static const struct snd_kcontrol_new alc269_laptop_mixer[] = {
14276 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
14277 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14278 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
14279 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
14280 { } /* end */
14283 static const struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
14284 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
14285 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14286 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
14287 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
14288 { } /* end */
14291 static const struct snd_kcontrol_new alc269_asus_mixer[] = {
14292 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14293 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x0, HDA_INPUT),
14294 { } /* end */
14297 /* capture mixer elements */
14298 static const struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
14299 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
14300 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
14301 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14302 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
14303 { } /* end */
14306 static const struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
14307 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
14308 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
14309 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14310 { } /* end */
14313 static const struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
14314 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
14315 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
14316 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14317 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
14318 { } /* end */
14321 static const struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
14322 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
14323 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
14324 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14325 { } /* end */
14328 /* FSC amilo */
14329 #define alc269_fujitsu_mixer alc269_laptop_mixer
14331 static const struct hda_verb alc269_quanta_fl1_verbs[] = {
14332 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
14333 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14334 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14335 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
14336 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14337 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14341 static const struct hda_verb alc269_lifebook_verbs[] = {
14342 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
14343 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
14344 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14345 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14346 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
14347 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14348 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14349 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
14350 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14351 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14355 /* toggle speaker-output according to the hp-jack state */
14356 static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
14358 alc_hp_automute(codec);
14360 snd_hda_codec_write(codec, 0x20, 0,
14361 AC_VERB_SET_COEF_INDEX, 0x0c);
14362 snd_hda_codec_write(codec, 0x20, 0,
14363 AC_VERB_SET_PROC_COEF, 0x680);
14365 snd_hda_codec_write(codec, 0x20, 0,
14366 AC_VERB_SET_COEF_INDEX, 0x0c);
14367 snd_hda_codec_write(codec, 0x20, 0,
14368 AC_VERB_SET_PROC_COEF, 0x480);
14371 #define alc269_lifebook_speaker_automute \
14372 alc269_quanta_fl1_speaker_automute
14374 static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
14376 unsigned int present_laptop;
14377 unsigned int present_dock;
14379 present_laptop = snd_hda_jack_detect(codec, 0x18);
14380 present_dock = snd_hda_jack_detect(codec, 0x1b);
14382 /* Laptop mic port overrides dock mic port, design decision */
14383 if (present_dock)
14384 snd_hda_codec_write(codec, 0x23, 0,
14385 AC_VERB_SET_CONNECT_SEL, 0x3);
14386 if (present_laptop)
14387 snd_hda_codec_write(codec, 0x23, 0,
14388 AC_VERB_SET_CONNECT_SEL, 0x0);
14389 if (!present_dock && !present_laptop)
14390 snd_hda_codec_write(codec, 0x23, 0,
14391 AC_VERB_SET_CONNECT_SEL, 0x1);
14394 static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
14395 unsigned int res)
14397 switch (res >> 26) {
14398 case ALC880_HP_EVENT:
14399 alc269_quanta_fl1_speaker_automute(codec);
14400 break;
14401 case ALC880_MIC_EVENT:
14402 alc_mic_automute(codec);
14403 break;
14407 static void alc269_lifebook_unsol_event(struct hda_codec *codec,
14408 unsigned int res)
14410 if ((res >> 26) == ALC880_HP_EVENT)
14411 alc269_lifebook_speaker_automute(codec);
14412 if ((res >> 26) == ALC880_MIC_EVENT)
14413 alc269_lifebook_mic_autoswitch(codec);
14416 static void alc269_quanta_fl1_setup(struct hda_codec *codec)
14418 struct alc_spec *spec = codec->spec;
14419 spec->autocfg.hp_pins[0] = 0x15;
14420 spec->autocfg.speaker_pins[0] = 0x14;
14421 spec->automute_mixer_nid[0] = 0x0c;
14422 spec->automute = 1;
14423 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14424 spec->ext_mic.pin = 0x18;
14425 spec->ext_mic.mux_idx = 0;
14426 spec->int_mic.pin = 0x19;
14427 spec->int_mic.mux_idx = 1;
14428 spec->auto_mic = 1;
14431 static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
14433 alc269_quanta_fl1_speaker_automute(codec);
14434 alc_mic_automute(codec);
14437 static void alc269_lifebook_setup(struct hda_codec *codec)
14439 struct alc_spec *spec = codec->spec;
14440 spec->autocfg.hp_pins[0] = 0x15;
14441 spec->autocfg.hp_pins[1] = 0x1a;
14442 spec->autocfg.speaker_pins[0] = 0x14;
14443 spec->automute_mixer_nid[0] = 0x0c;
14444 spec->automute = 1;
14445 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14448 static void alc269_lifebook_init_hook(struct hda_codec *codec)
14450 alc269_lifebook_speaker_automute(codec);
14451 alc269_lifebook_mic_autoswitch(codec);
14454 static const struct hda_verb alc269_laptop_dmic_init_verbs[] = {
14455 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
14456 {0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
14457 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14458 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
14459 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14460 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14461 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14465 static const struct hda_verb alc269_laptop_amic_init_verbs[] = {
14466 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
14467 {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
14468 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14469 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))},
14470 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14471 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14475 static const struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
14476 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
14477 {0x22, AC_VERB_SET_CONNECT_SEL, 0x06},
14478 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14479 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
14480 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14481 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14482 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14486 static const struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
14487 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
14488 {0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
14489 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14490 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
14491 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14492 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14493 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14497 static const struct hda_verb alc271_acer_dmic_verbs[] = {
14498 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
14499 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
14500 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14501 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14502 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14503 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14504 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00},
14505 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14506 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14507 {0x22, AC_VERB_SET_CONNECT_SEL, 6},
14511 static void alc269_laptop_amic_setup(struct hda_codec *codec)
14513 struct alc_spec *spec = codec->spec;
14514 spec->autocfg.hp_pins[0] = 0x15;
14515 spec->autocfg.speaker_pins[0] = 0x14;
14516 spec->automute_mixer_nid[0] = 0x0c;
14517 spec->automute = 1;
14518 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14519 spec->ext_mic.pin = 0x18;
14520 spec->ext_mic.mux_idx = 0;
14521 spec->int_mic.pin = 0x19;
14522 spec->int_mic.mux_idx = 1;
14523 spec->auto_mic = 1;
14526 static void alc269_laptop_dmic_setup(struct hda_codec *codec)
14528 struct alc_spec *spec = codec->spec;
14529 spec->autocfg.hp_pins[0] = 0x15;
14530 spec->autocfg.speaker_pins[0] = 0x14;
14531 spec->automute_mixer_nid[0] = 0x0c;
14532 spec->automute = 1;
14533 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14534 spec->ext_mic.pin = 0x18;
14535 spec->ext_mic.mux_idx = 0;
14536 spec->int_mic.pin = 0x12;
14537 spec->int_mic.mux_idx = 5;
14538 spec->auto_mic = 1;
14541 static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
14543 struct alc_spec *spec = codec->spec;
14544 spec->autocfg.hp_pins[0] = 0x21;
14545 spec->autocfg.speaker_pins[0] = 0x14;
14546 spec->automute_mixer_nid[0] = 0x0c;
14547 spec->automute = 1;
14548 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14549 spec->ext_mic.pin = 0x18;
14550 spec->ext_mic.mux_idx = 0;
14551 spec->int_mic.pin = 0x19;
14552 spec->int_mic.mux_idx = 1;
14553 spec->auto_mic = 1;
14556 static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
14558 struct alc_spec *spec = codec->spec;
14559 spec->autocfg.hp_pins[0] = 0x21;
14560 spec->autocfg.speaker_pins[0] = 0x14;
14561 spec->automute_mixer_nid[0] = 0x0c;
14562 spec->automute = 1;
14563 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14564 spec->ext_mic.pin = 0x18;
14565 spec->ext_mic.mux_idx = 0;
14566 spec->int_mic.pin = 0x12;
14567 spec->int_mic.mux_idx = 6;
14568 spec->auto_mic = 1;
14572 * generic initialization of ADC, input mixers and output mixers
14574 static const struct hda_verb alc269_init_verbs[] = {
14576 * Unmute ADC0 and set the default input to mic-in
14578 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14581 * Set up output mixers (0x02 - 0x03)
14583 /* set vol=0 to output mixers */
14584 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14585 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14587 /* set up input amps for analog loopback */
14588 /* Amp Indices: DAC = 0, mixer = 1 */
14589 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14590 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14591 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14592 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14593 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14594 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14596 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14597 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14598 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14599 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14600 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14601 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14602 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14604 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14605 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14607 /* FIXME: use Mux-type input source selection */
14608 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
14609 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
14610 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
14612 /* set EAPD */
14613 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
14617 static const struct hda_verb alc269vb_init_verbs[] = {
14619 * Unmute ADC0 and set the default input to mic-in
14621 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14624 * Set up output mixers (0x02 - 0x03)
14626 /* set vol=0 to output mixers */
14627 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14628 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14630 /* set up input amps for analog loopback */
14631 /* Amp Indices: DAC = 0, mixer = 1 */
14632 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14633 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14634 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14635 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14636 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14637 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14639 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14640 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14641 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14642 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14643 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14644 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14645 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14647 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14648 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14650 /* FIXME: use Mux-type input source selection */
14651 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
14652 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
14653 {0x22, AC_VERB_SET_CONNECT_SEL, 0x00},
14655 /* set EAPD */
14656 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
14660 #define alc269_auto_create_multi_out_ctls \
14661 alc268_auto_create_multi_out_ctls
14662 #define alc269_auto_create_input_ctls \
14663 alc268_auto_create_input_ctls
14665 #ifdef CONFIG_SND_HDA_POWER_SAVE
14666 #define alc269_loopbacks alc880_loopbacks
14667 #endif
14669 /* pcm configuration: identical with ALC880 */
14670 #define alc269_pcm_analog_playback alc880_pcm_analog_playback
14671 #define alc269_pcm_analog_capture alc880_pcm_analog_capture
14672 #define alc269_pcm_digital_playback alc880_pcm_digital_playback
14673 #define alc269_pcm_digital_capture alc880_pcm_digital_capture
14675 static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
14676 .substreams = 1,
14677 .channels_min = 2,
14678 .channels_max = 8,
14679 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
14680 /* NID is set in alc_build_pcms */
14681 .ops = {
14682 .open = alc880_playback_pcm_open,
14683 .prepare = alc880_playback_pcm_prepare,
14684 .cleanup = alc880_playback_pcm_cleanup
14688 static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
14689 .substreams = 1,
14690 .channels_min = 2,
14691 .channels_max = 2,
14692 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
14693 /* NID is set in alc_build_pcms */
14696 #ifdef CONFIG_SND_HDA_POWER_SAVE
14697 static int alc269_mic2_for_mute_led(struct hda_codec *codec)
14699 switch (codec->subsystem_id) {
14700 case 0x103c1586:
14701 return 1;
14703 return 0;
14706 static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
14708 /* update mute-LED according to the speaker mute state */
14709 if (nid == 0x01 || nid == 0x14) {
14710 int pinval;
14711 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
14712 HDA_AMP_MUTE)
14713 pinval = 0x24;
14714 else
14715 pinval = 0x20;
14716 /* mic2 vref pin is used for mute LED control */
14717 snd_hda_codec_update_cache(codec, 0x19, 0,
14718 AC_VERB_SET_PIN_WIDGET_CONTROL,
14719 pinval);
14721 return alc_check_power_status(codec, nid);
14723 #endif /* CONFIG_SND_HDA_POWER_SAVE */
14725 static int alc275_setup_dual_adc(struct hda_codec *codec)
14727 struct alc_spec *spec = codec->spec;
14729 if (codec->vendor_id != 0x10ec0275 || !spec->auto_mic)
14730 return 0;
14731 if ((spec->ext_mic.pin >= 0x18 && spec->int_mic.pin <= 0x13) ||
14732 (spec->ext_mic.pin <= 0x12 && spec->int_mic.pin >= 0x18)) {
14733 if (spec->ext_mic.pin <= 0x12) {
14734 spec->private_adc_nids[0] = 0x08;
14735 spec->private_adc_nids[1] = 0x11;
14736 spec->private_capsrc_nids[0] = 0x23;
14737 spec->private_capsrc_nids[1] = 0x22;
14738 } else {
14739 spec->private_adc_nids[0] = 0x11;
14740 spec->private_adc_nids[1] = 0x08;
14741 spec->private_capsrc_nids[0] = 0x22;
14742 spec->private_capsrc_nids[1] = 0x23;
14744 spec->adc_nids = spec->private_adc_nids;
14745 spec->capsrc_nids = spec->private_capsrc_nids;
14746 spec->num_adc_nids = 2;
14747 spec->dual_adc_switch = 1;
14748 snd_printdd("realtek: enabling dual ADC switchg (%02x:%02x)\n",
14749 spec->adc_nids[0], spec->adc_nids[1]);
14750 return 1;
14752 return 0;
14755 /* different alc269-variants */
14756 enum {
14757 ALC269_TYPE_NORMAL,
14758 ALC269_TYPE_ALC258,
14759 ALC269_TYPE_ALC259,
14760 ALC269_TYPE_ALC269VB,
14761 ALC269_TYPE_ALC270,
14762 ALC269_TYPE_ALC271X,
14766 * BIOS auto configuration
14768 static int alc269_parse_auto_config(struct hda_codec *codec)
14770 struct alc_spec *spec = codec->spec;
14771 int err;
14772 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
14774 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
14775 alc269_ignore);
14776 if (err < 0)
14777 return err;
14779 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
14780 if (err < 0)
14781 return err;
14782 if (spec->codec_variant == ALC269_TYPE_NORMAL)
14783 err = alc269_auto_create_input_ctls(codec, &spec->autocfg);
14784 else
14785 err = alc_auto_create_input_ctls(codec, &spec->autocfg, 0,
14786 0x22, 0);
14787 if (err < 0)
14788 return err;
14790 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
14792 alc_auto_parse_digital(codec);
14794 if (spec->kctls.list)
14795 add_mixer(spec, spec->kctls.list);
14797 if (spec->codec_variant != ALC269_TYPE_NORMAL) {
14798 add_verb(spec, alc269vb_init_verbs);
14799 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
14800 } else {
14801 add_verb(spec, alc269_init_verbs);
14802 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
14805 spec->num_mux_defs = 1;
14806 spec->input_mux = &spec->private_imux[0];
14808 if (!alc275_setup_dual_adc(codec))
14809 fillup_priv_adc_nids(codec, alc269_adc_candidates,
14810 sizeof(alc269_adc_candidates));
14812 err = alc_auto_add_mic_boost(codec);
14813 if (err < 0)
14814 return err;
14816 if (!spec->cap_mixer && !spec->no_analog)
14817 set_capture_mixer(codec);
14819 return 1;
14822 #define alc269_auto_init_multi_out alc268_auto_init_multi_out
14823 #define alc269_auto_init_hp_out alc268_auto_init_hp_out
14824 #define alc269_auto_init_analog_input alc882_auto_init_analog_input
14825 #define alc269_auto_init_input_src alc882_auto_init_input_src
14828 /* init callback for auto-configuration model -- overriding the default init */
14829 static void alc269_auto_init(struct hda_codec *codec)
14831 struct alc_spec *spec = codec->spec;
14832 alc269_auto_init_multi_out(codec);
14833 alc269_auto_init_hp_out(codec);
14834 alc269_auto_init_analog_input(codec);
14835 if (!spec->dual_adc_switch)
14836 alc269_auto_init_input_src(codec);
14837 alc_auto_init_digital(codec);
14838 if (spec->unsol_event)
14839 alc_inithook(codec);
14842 static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
14844 int val = alc_read_coef_idx(codec, 0x04);
14845 if (power_up)
14846 val |= 1 << 11;
14847 else
14848 val &= ~(1 << 11);
14849 alc_write_coef_idx(codec, 0x04, val);
14852 static void alc269_shutup(struct hda_codec *codec)
14854 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
14855 alc269_toggle_power_output(codec, 0);
14856 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
14857 alc269_toggle_power_output(codec, 0);
14858 msleep(150);
14862 #ifdef SND_HDA_NEEDS_RESUME
14863 static int alc269_resume(struct hda_codec *codec)
14865 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
14866 alc269_toggle_power_output(codec, 0);
14867 msleep(150);
14870 codec->patch_ops.init(codec);
14872 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
14873 alc269_toggle_power_output(codec, 1);
14874 msleep(200);
14877 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
14878 alc269_toggle_power_output(codec, 1);
14880 snd_hda_codec_resume_amp(codec);
14881 snd_hda_codec_resume_cache(codec);
14882 hda_call_check_power_status(codec, 0x01);
14883 return 0;
14885 #endif /* SND_HDA_NEEDS_RESUME */
14887 static void alc269_fixup_hweq(struct hda_codec *codec,
14888 const struct alc_fixup *fix, int action)
14890 int coef;
14892 if (action != ALC_FIXUP_ACT_INIT)
14893 return;
14894 coef = alc_read_coef_idx(codec, 0x1e);
14895 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
14898 static void alc271_fixup_dmic(struct hda_codec *codec,
14899 const struct alc_fixup *fix, int action)
14901 static const struct hda_verb verbs[] = {
14902 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
14903 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
14906 unsigned int cfg;
14908 if (strcmp(codec->chip_name, "ALC271X"))
14909 return;
14910 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
14911 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
14912 snd_hda_sequence_write(codec, verbs);
14915 enum {
14916 ALC269_FIXUP_SONY_VAIO,
14917 ALC275_FIXUP_SONY_VAIO_GPIO2,
14918 ALC269_FIXUP_DELL_M101Z,
14919 ALC269_FIXUP_SKU_IGNORE,
14920 ALC269_FIXUP_ASUS_G73JW,
14921 ALC269_FIXUP_LENOVO_EAPD,
14922 ALC275_FIXUP_SONY_HWEQ,
14923 ALC271_FIXUP_DMIC,
14926 static const struct alc_fixup alc269_fixups[] = {
14927 [ALC269_FIXUP_SONY_VAIO] = {
14928 .type = ALC_FIXUP_VERBS,
14929 .v.verbs = (const struct hda_verb[]) {
14930 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
14934 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
14935 .type = ALC_FIXUP_VERBS,
14936 .v.verbs = (const struct hda_verb[]) {
14937 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
14938 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
14939 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
14942 .chained = true,
14943 .chain_id = ALC269_FIXUP_SONY_VAIO
14945 [ALC269_FIXUP_DELL_M101Z] = {
14946 .type = ALC_FIXUP_VERBS,
14947 .v.verbs = (const struct hda_verb[]) {
14948 /* Enables internal speaker */
14949 {0x20, AC_VERB_SET_COEF_INDEX, 13},
14950 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
14954 [ALC269_FIXUP_SKU_IGNORE] = {
14955 .type = ALC_FIXUP_SKU,
14956 .v.sku = ALC_FIXUP_SKU_IGNORE,
14958 [ALC269_FIXUP_ASUS_G73JW] = {
14959 .type = ALC_FIXUP_PINS,
14960 .v.pins = (const struct alc_pincfg[]) {
14961 { 0x17, 0x99130111 }, /* subwoofer */
14965 [ALC269_FIXUP_LENOVO_EAPD] = {
14966 .type = ALC_FIXUP_VERBS,
14967 .v.verbs = (const struct hda_verb[]) {
14968 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
14972 [ALC275_FIXUP_SONY_HWEQ] = {
14973 .type = ALC_FIXUP_FUNC,
14974 .v.func = alc269_fixup_hweq,
14975 .chained = true,
14976 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
14978 [ALC271_FIXUP_DMIC] = {
14979 .type = ALC_FIXUP_FUNC,
14980 .v.func = alc271_fixup_dmic,
14984 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
14985 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
14986 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
14987 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
14988 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
14989 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
14990 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
14991 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
14992 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
14993 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
14994 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
14995 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
14996 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
14997 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
15003 * configuration and preset
15005 static const char * const alc269_models[ALC269_MODEL_LAST] = {
15006 [ALC269_BASIC] = "basic",
15007 [ALC269_QUANTA_FL1] = "quanta",
15008 [ALC269_AMIC] = "laptop-amic",
15009 [ALC269_DMIC] = "laptop-dmic",
15010 [ALC269_FUJITSU] = "fujitsu",
15011 [ALC269_LIFEBOOK] = "lifebook",
15012 [ALC269_AUTO] = "auto",
15015 static const struct snd_pci_quirk alc269_cfg_tbl[] = {
15016 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
15017 SND_PCI_QUIRK(0x1025, 0x047c, "ACER ZGA", ALC271_ACER),
15018 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
15019 ALC269_AMIC),
15020 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC),
15021 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC),
15022 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC),
15023 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC),
15024 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC),
15025 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC),
15026 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC),
15027 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC),
15028 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC),
15029 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269VB_AMIC),
15030 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC),
15031 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC),
15032 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC),
15033 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC),
15034 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC),
15035 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC),
15036 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC),
15037 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC),
15038 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC),
15039 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC),
15040 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC),
15041 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC),
15042 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC),
15043 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC),
15044 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC),
15045 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC),
15046 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC),
15047 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC),
15048 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
15049 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
15050 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
15051 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
15052 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
15053 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
15054 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
15055 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
15056 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
15057 ALC269_DMIC),
15058 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
15059 ALC269_DMIC),
15060 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
15061 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
15062 SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO),
15063 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
15064 SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
15065 SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
15066 SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_AMIC),
15067 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_AMIC),
15068 SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_DMIC),
15069 SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_DMIC),
15073 static const struct alc_config_preset alc269_presets[] = {
15074 [ALC269_BASIC] = {
15075 .mixers = { alc269_base_mixer },
15076 .init_verbs = { alc269_init_verbs },
15077 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15078 .dac_nids = alc269_dac_nids,
15079 .hp_nid = 0x03,
15080 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15081 .channel_mode = alc269_modes,
15082 .input_mux = &alc269_capture_source,
15084 [ALC269_QUANTA_FL1] = {
15085 .mixers = { alc269_quanta_fl1_mixer },
15086 .init_verbs = { alc269_init_verbs, alc269_quanta_fl1_verbs },
15087 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15088 .dac_nids = alc269_dac_nids,
15089 .hp_nid = 0x03,
15090 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15091 .channel_mode = alc269_modes,
15092 .input_mux = &alc269_capture_source,
15093 .unsol_event = alc269_quanta_fl1_unsol_event,
15094 .setup = alc269_quanta_fl1_setup,
15095 .init_hook = alc269_quanta_fl1_init_hook,
15097 [ALC269_AMIC] = {
15098 .mixers = { alc269_laptop_mixer },
15099 .cap_mixer = alc269_laptop_analog_capture_mixer,
15100 .init_verbs = { alc269_init_verbs,
15101 alc269_laptop_amic_init_verbs },
15102 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15103 .dac_nids = alc269_dac_nids,
15104 .hp_nid = 0x03,
15105 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15106 .channel_mode = alc269_modes,
15107 .unsol_event = alc_sku_unsol_event,
15108 .setup = alc269_laptop_amic_setup,
15109 .init_hook = alc_inithook,
15111 [ALC269_DMIC] = {
15112 .mixers = { alc269_laptop_mixer },
15113 .cap_mixer = alc269_laptop_digital_capture_mixer,
15114 .init_verbs = { alc269_init_verbs,
15115 alc269_laptop_dmic_init_verbs },
15116 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15117 .dac_nids = alc269_dac_nids,
15118 .hp_nid = 0x03,
15119 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15120 .channel_mode = alc269_modes,
15121 .unsol_event = alc_sku_unsol_event,
15122 .setup = alc269_laptop_dmic_setup,
15123 .init_hook = alc_inithook,
15125 [ALC269VB_AMIC] = {
15126 .mixers = { alc269vb_laptop_mixer },
15127 .cap_mixer = alc269vb_laptop_analog_capture_mixer,
15128 .init_verbs = { alc269vb_init_verbs,
15129 alc269vb_laptop_amic_init_verbs },
15130 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15131 .dac_nids = alc269_dac_nids,
15132 .hp_nid = 0x03,
15133 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15134 .channel_mode = alc269_modes,
15135 .unsol_event = alc_sku_unsol_event,
15136 .setup = alc269vb_laptop_amic_setup,
15137 .init_hook = alc_inithook,
15139 [ALC269VB_DMIC] = {
15140 .mixers = { alc269vb_laptop_mixer },
15141 .cap_mixer = alc269vb_laptop_digital_capture_mixer,
15142 .init_verbs = { alc269vb_init_verbs,
15143 alc269vb_laptop_dmic_init_verbs },
15144 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15145 .dac_nids = alc269_dac_nids,
15146 .hp_nid = 0x03,
15147 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15148 .channel_mode = alc269_modes,
15149 .unsol_event = alc_sku_unsol_event,
15150 .setup = alc269vb_laptop_dmic_setup,
15151 .init_hook = alc_inithook,
15153 [ALC269_FUJITSU] = {
15154 .mixers = { alc269_fujitsu_mixer },
15155 .cap_mixer = alc269_laptop_digital_capture_mixer,
15156 .init_verbs = { alc269_init_verbs,
15157 alc269_laptop_dmic_init_verbs },
15158 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15159 .dac_nids = alc269_dac_nids,
15160 .hp_nid = 0x03,
15161 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15162 .channel_mode = alc269_modes,
15163 .unsol_event = alc_sku_unsol_event,
15164 .setup = alc269_laptop_dmic_setup,
15165 .init_hook = alc_inithook,
15167 [ALC269_LIFEBOOK] = {
15168 .mixers = { alc269_lifebook_mixer },
15169 .init_verbs = { alc269_init_verbs, alc269_lifebook_verbs },
15170 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15171 .dac_nids = alc269_dac_nids,
15172 .hp_nid = 0x03,
15173 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15174 .channel_mode = alc269_modes,
15175 .input_mux = &alc269_capture_source,
15176 .unsol_event = alc269_lifebook_unsol_event,
15177 .setup = alc269_lifebook_setup,
15178 .init_hook = alc269_lifebook_init_hook,
15180 [ALC271_ACER] = {
15181 .mixers = { alc269_asus_mixer },
15182 .cap_mixer = alc269vb_laptop_digital_capture_mixer,
15183 .init_verbs = { alc269_init_verbs, alc271_acer_dmic_verbs },
15184 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15185 .dac_nids = alc269_dac_nids,
15186 .adc_nids = alc262_dmic_adc_nids,
15187 .num_adc_nids = ARRAY_SIZE(alc262_dmic_adc_nids),
15188 .capsrc_nids = alc262_dmic_capsrc_nids,
15189 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15190 .channel_mode = alc269_modes,
15191 .input_mux = &alc269_capture_source,
15192 .dig_out_nid = ALC880_DIGOUT_NID,
15193 .unsol_event = alc_sku_unsol_event,
15194 .setup = alc269vb_laptop_dmic_setup,
15195 .init_hook = alc_inithook,
15199 static int alc269_fill_coef(struct hda_codec *codec)
15201 int val;
15203 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
15204 alc_write_coef_idx(codec, 0xf, 0x960b);
15205 alc_write_coef_idx(codec, 0xe, 0x8817);
15208 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
15209 alc_write_coef_idx(codec, 0xf, 0x960b);
15210 alc_write_coef_idx(codec, 0xe, 0x8814);
15213 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
15214 val = alc_read_coef_idx(codec, 0x04);
15215 /* Power up output pin */
15216 alc_write_coef_idx(codec, 0x04, val | (1<<11));
15219 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
15220 val = alc_read_coef_idx(codec, 0xd);
15221 if ((val & 0x0c00) >> 10 != 0x1) {
15222 /* Capless ramp up clock control */
15223 alc_write_coef_idx(codec, 0xd, val | (1<<10));
15225 val = alc_read_coef_idx(codec, 0x17);
15226 if ((val & 0x01c0) >> 6 != 0x4) {
15227 /* Class D power on reset */
15228 alc_write_coef_idx(codec, 0x17, val | (1<<7));
15232 val = alc_read_coef_idx(codec, 0xd); /* Class D */
15233 alc_write_coef_idx(codec, 0xd, val | (1<<14));
15235 val = alc_read_coef_idx(codec, 0x4); /* HP */
15236 alc_write_coef_idx(codec, 0x4, val | (1<<11));
15238 return 0;
15241 static int patch_alc269(struct hda_codec *codec)
15243 struct alc_spec *spec;
15244 int board_config, coef;
15245 int err;
15247 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
15248 if (spec == NULL)
15249 return -ENOMEM;
15251 codec->spec = spec;
15253 alc_auto_parse_customize_define(codec);
15255 if (codec->vendor_id == 0x10ec0269) {
15256 coef = alc_read_coef_idx(codec, 0);
15257 if ((coef & 0x00f0) == 0x0010) {
15258 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
15259 spec->cdefine.platform_type == 1) {
15260 alc_codec_rename(codec, "ALC271X");
15261 spec->codec_variant = ALC269_TYPE_ALC271X;
15262 } else if ((coef & 0xf000) == 0x1000) {
15263 spec->codec_variant = ALC269_TYPE_ALC270;
15264 } else if ((coef & 0xf000) == 0x2000) {
15265 alc_codec_rename(codec, "ALC259");
15266 spec->codec_variant = ALC269_TYPE_ALC259;
15267 } else if ((coef & 0xf000) == 0x3000) {
15268 alc_codec_rename(codec, "ALC258");
15269 spec->codec_variant = ALC269_TYPE_ALC258;
15270 } else {
15271 alc_codec_rename(codec, "ALC269VB");
15272 spec->codec_variant = ALC269_TYPE_ALC269VB;
15274 } else
15275 alc_fix_pll_init(codec, 0x20, 0x04, 15);
15276 alc269_fill_coef(codec);
15279 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
15280 alc269_models,
15281 alc269_cfg_tbl);
15283 if (board_config < 0) {
15284 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
15285 codec->chip_name);
15286 board_config = ALC269_AUTO;
15289 if (board_config == ALC269_AUTO) {
15290 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
15291 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
15294 if (board_config == ALC269_AUTO) {
15295 /* automatic parse from the BIOS config */
15296 err = alc269_parse_auto_config(codec);
15297 if (err < 0) {
15298 alc_free(codec);
15299 return err;
15300 } else if (!err) {
15301 printk(KERN_INFO
15302 "hda_codec: Cannot set up configuration "
15303 "from BIOS. Using base mode...\n");
15304 board_config = ALC269_BASIC;
15308 if (has_cdefine_beep(codec)) {
15309 err = snd_hda_attach_beep_device(codec, 0x1);
15310 if (err < 0) {
15311 alc_free(codec);
15312 return err;
15316 if (board_config != ALC269_AUTO)
15317 setup_preset(codec, &alc269_presets[board_config]);
15319 if (board_config == ALC269_QUANTA_FL1) {
15320 /* Due to a hardware problem on Lenovo Ideadpad, we need to
15321 * fix the sample rate of analog I/O to 44.1kHz
15323 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
15324 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
15325 } else if (spec->dual_adc_switch) {
15326 spec->stream_analog_playback = &alc269_pcm_analog_playback;
15327 /* switch ADC dynamically */
15328 spec->stream_analog_capture = &dualmic_pcm_analog_capture;
15329 } else {
15330 spec->stream_analog_playback = &alc269_pcm_analog_playback;
15331 spec->stream_analog_capture = &alc269_pcm_analog_capture;
15333 spec->stream_digital_playback = &alc269_pcm_digital_playback;
15334 spec->stream_digital_capture = &alc269_pcm_digital_capture;
15336 if (!spec->adc_nids) { /* wasn't filled automatically? use default */
15337 if (spec->codec_variant == ALC269_TYPE_NORMAL) {
15338 spec->adc_nids = alc269_adc_nids;
15339 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
15340 spec->capsrc_nids = alc269_capsrc_nids;
15341 } else {
15342 spec->adc_nids = alc269vb_adc_nids;
15343 spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
15344 spec->capsrc_nids = alc269vb_capsrc_nids;
15348 if (!spec->cap_mixer)
15349 set_capture_mixer(codec);
15350 if (has_cdefine_beep(codec))
15351 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
15353 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
15355 spec->vmaster_nid = 0x02;
15357 codec->patch_ops = alc_patch_ops;
15358 #ifdef SND_HDA_NEEDS_RESUME
15359 codec->patch_ops.resume = alc269_resume;
15360 #endif
15361 if (board_config == ALC269_AUTO)
15362 spec->init_hook = alc269_auto_init;
15363 spec->shutup = alc269_shutup;
15365 alc_init_jacks(codec);
15366 #ifdef CONFIG_SND_HDA_POWER_SAVE
15367 if (!spec->loopback.amplist)
15368 spec->loopback.amplist = alc269_loopbacks;
15369 if (alc269_mic2_for_mute_led(codec))
15370 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
15371 #endif
15373 return 0;
15377 * ALC861 channel source setting (2/6 channel selection for 3-stack)
15381 * set the path ways for 2 channel output
15382 * need to set the codec line out and mic 1 pin widgets to inputs
15384 static const struct hda_verb alc861_threestack_ch2_init[] = {
15385 /* set pin widget 1Ah (line in) for input */
15386 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15387 /* set pin widget 18h (mic1/2) for input, for mic also enable
15388 * the vref
15390 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15392 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
15393 #if 0
15394 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
15395 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
15396 #endif
15397 { } /* end */
15400 * 6ch mode
15401 * need to set the codec line out and mic 1 pin widgets to outputs
15403 static const struct hda_verb alc861_threestack_ch6_init[] = {
15404 /* set pin widget 1Ah (line in) for output (Back Surround)*/
15405 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15406 /* set pin widget 18h (mic1) for output (CLFE)*/
15407 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15409 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
15410 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
15412 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
15413 #if 0
15414 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
15415 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
15416 #endif
15417 { } /* end */
15420 static const struct hda_channel_mode alc861_threestack_modes[2] = {
15421 { 2, alc861_threestack_ch2_init },
15422 { 6, alc861_threestack_ch6_init },
15424 /* Set mic1 as input and unmute the mixer */
15425 static const struct hda_verb alc861_uniwill_m31_ch2_init[] = {
15426 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15427 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
15428 { } /* end */
15430 /* Set mic1 as output and mute mixer */
15431 static const struct hda_verb alc861_uniwill_m31_ch4_init[] = {
15432 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15433 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
15434 { } /* end */
15437 static const struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
15438 { 2, alc861_uniwill_m31_ch2_init },
15439 { 4, alc861_uniwill_m31_ch4_init },
15442 /* Set mic1 and line-in as input and unmute the mixer */
15443 static const struct hda_verb alc861_asus_ch2_init[] = {
15444 /* set pin widget 1Ah (line in) for input */
15445 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15446 /* set pin widget 18h (mic1/2) for input, for mic also enable
15447 * the vref
15449 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15451 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
15452 #if 0
15453 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
15454 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
15455 #endif
15456 { } /* end */
15458 /* Set mic1 nad line-in as output and mute mixer */
15459 static const struct hda_verb alc861_asus_ch6_init[] = {
15460 /* set pin widget 1Ah (line in) for output (Back Surround)*/
15461 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15462 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
15463 /* set pin widget 18h (mic1) for output (CLFE)*/
15464 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15465 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
15466 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
15467 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
15469 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
15470 #if 0
15471 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
15472 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
15473 #endif
15474 { } /* end */
15477 static const struct hda_channel_mode alc861_asus_modes[2] = {
15478 { 2, alc861_asus_ch2_init },
15479 { 6, alc861_asus_ch6_init },
15482 /* patch-ALC861 */
15484 static const struct snd_kcontrol_new alc861_base_mixer[] = {
15485 /* output mixer control */
15486 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
15487 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
15488 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
15489 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
15490 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
15492 /*Input mixer control */
15493 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
15494 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
15495 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15496 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
15497 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
15498 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
15499 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
15500 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
15501 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
15502 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
15504 { } /* end */
15507 static const struct snd_kcontrol_new alc861_3ST_mixer[] = {
15508 /* output mixer control */
15509 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
15510 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
15511 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
15512 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
15513 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
15515 /* Input mixer control */
15516 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
15517 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
15518 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15519 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
15520 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
15521 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
15522 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
15523 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
15524 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
15525 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
15528 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15529 .name = "Channel Mode",
15530 .info = alc_ch_mode_info,
15531 .get = alc_ch_mode_get,
15532 .put = alc_ch_mode_put,
15533 .private_value = ARRAY_SIZE(alc861_threestack_modes),
15535 { } /* end */
15538 static const struct snd_kcontrol_new alc861_toshiba_mixer[] = {
15539 /* output mixer control */
15540 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
15541 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
15542 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
15544 { } /* end */
15547 static const struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
15548 /* output mixer control */
15549 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
15550 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
15551 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
15552 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
15553 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
15555 /* Input mixer control */
15556 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
15557 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
15558 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15559 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
15560 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
15561 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
15562 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
15563 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
15564 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
15565 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
15568 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15569 .name = "Channel Mode",
15570 .info = alc_ch_mode_info,
15571 .get = alc_ch_mode_get,
15572 .put = alc_ch_mode_put,
15573 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
15575 { } /* end */
15578 static const struct snd_kcontrol_new alc861_asus_mixer[] = {
15579 /* output mixer control */
15580 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
15581 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
15582 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
15583 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
15584 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
15586 /* Input mixer control */
15587 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
15588 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
15589 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15590 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
15591 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
15592 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
15593 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
15594 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
15595 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
15596 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
15599 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15600 .name = "Channel Mode",
15601 .info = alc_ch_mode_info,
15602 .get = alc_ch_mode_get,
15603 .put = alc_ch_mode_put,
15604 .private_value = ARRAY_SIZE(alc861_asus_modes),
15609 /* additional mixer */
15610 static const struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
15611 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15612 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
15617 * generic initialization of ADC, input mixers and output mixers
15619 static const struct hda_verb alc861_base_init_verbs[] = {
15621 * Unmute ADC0 and set the default input to mic-in
15623 /* port-A for surround (rear panel) */
15624 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15625 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
15626 /* port-B for mic-in (rear panel) with vref */
15627 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15628 /* port-C for line-in (rear panel) */
15629 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15630 /* port-D for Front */
15631 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15632 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15633 /* port-E for HP out (front panel) */
15634 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
15635 /* route front PCM to HP */
15636 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15637 /* port-F for mic-in (front panel) with vref */
15638 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15639 /* port-G for CLFE (rear panel) */
15640 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15641 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15642 /* port-H for side (rear panel) */
15643 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15644 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
15645 /* CD-in */
15646 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15647 /* route front mic to ADC1*/
15648 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15649 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15651 /* Unmute DAC0~3 & spdif out*/
15652 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15653 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15654 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15655 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15656 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15658 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15659 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15660 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15661 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15662 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15664 /* Unmute Stereo Mixer 15 */
15665 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15666 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15667 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15668 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
15670 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15671 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15672 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15673 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15674 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15675 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15676 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15677 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15678 /* hp used DAC 3 (Front) */
15679 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
15680 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15685 static const struct hda_verb alc861_threestack_init_verbs[] = {
15687 * Unmute ADC0 and set the default input to mic-in
15689 /* port-A for surround (rear panel) */
15690 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15691 /* port-B for mic-in (rear panel) with vref */
15692 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15693 /* port-C for line-in (rear panel) */
15694 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15695 /* port-D for Front */
15696 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15697 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15698 /* port-E for HP out (front panel) */
15699 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
15700 /* route front PCM to HP */
15701 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15702 /* port-F for mic-in (front panel) with vref */
15703 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15704 /* port-G for CLFE (rear panel) */
15705 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15706 /* port-H for side (rear panel) */
15707 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15708 /* CD-in */
15709 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15710 /* route front mic to ADC1*/
15711 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15712 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15713 /* Unmute DAC0~3 & spdif out*/
15714 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15715 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15716 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15717 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15718 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15720 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15721 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15722 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15723 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15724 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15726 /* Unmute Stereo Mixer 15 */
15727 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15728 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15729 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15730 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
15732 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15733 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15734 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15735 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15736 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15737 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15738 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15739 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15740 /* hp used DAC 3 (Front) */
15741 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
15742 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15746 static const struct hda_verb alc861_uniwill_m31_init_verbs[] = {
15748 * Unmute ADC0 and set the default input to mic-in
15750 /* port-A for surround (rear panel) */
15751 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15752 /* port-B for mic-in (rear panel) with vref */
15753 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15754 /* port-C for line-in (rear panel) */
15755 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15756 /* port-D for Front */
15757 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15758 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15759 /* port-E for HP out (front panel) */
15760 /* this has to be set to VREF80 */
15761 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15762 /* route front PCM to HP */
15763 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15764 /* port-F for mic-in (front panel) with vref */
15765 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15766 /* port-G for CLFE (rear panel) */
15767 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15768 /* port-H for side (rear panel) */
15769 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15770 /* CD-in */
15771 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15772 /* route front mic to ADC1*/
15773 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15774 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15775 /* Unmute DAC0~3 & spdif out*/
15776 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15777 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15778 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15779 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15780 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15782 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15783 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15784 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15785 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15786 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15788 /* Unmute Stereo Mixer 15 */
15789 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15790 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15791 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15792 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
15794 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15795 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15796 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15797 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15798 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15799 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15800 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15801 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15802 /* hp used DAC 3 (Front) */
15803 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
15804 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15808 static const struct hda_verb alc861_asus_init_verbs[] = {
15810 * Unmute ADC0 and set the default input to mic-in
15812 /* port-A for surround (rear panel)
15813 * according to codec#0 this is the HP jack
15815 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
15816 /* route front PCM to HP */
15817 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
15818 /* port-B for mic-in (rear panel) with vref */
15819 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15820 /* port-C for line-in (rear panel) */
15821 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15822 /* port-D for Front */
15823 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15824 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15825 /* port-E for HP out (front panel) */
15826 /* this has to be set to VREF80 */
15827 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15828 /* route front PCM to HP */
15829 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15830 /* port-F for mic-in (front panel) with vref */
15831 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15832 /* port-G for CLFE (rear panel) */
15833 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15834 /* port-H for side (rear panel) */
15835 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15836 /* CD-in */
15837 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15838 /* route front mic to ADC1*/
15839 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15840 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15841 /* Unmute DAC0~3 & spdif out*/
15842 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15843 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15844 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15845 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15846 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15847 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15848 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15849 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15850 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15851 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15853 /* Unmute Stereo Mixer 15 */
15854 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15855 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15856 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15857 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
15859 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15860 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15861 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15862 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15863 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15864 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15865 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15866 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15867 /* hp used DAC 3 (Front) */
15868 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
15869 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15873 /* additional init verbs for ASUS laptops */
15874 static const struct hda_verb alc861_asus_laptop_init_verbs[] = {
15875 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
15876 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
15881 * generic initialization of ADC, input mixers and output mixers
15883 static const struct hda_verb alc861_auto_init_verbs[] = {
15885 * Unmute ADC0 and set the default input to mic-in
15887 /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
15888 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15890 /* Unmute DAC0~3 & spdif out*/
15891 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15892 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15893 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15894 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15895 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15897 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15898 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15899 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15900 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15901 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15903 /* Unmute Stereo Mixer 15 */
15904 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15905 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15906 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15907 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
15909 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15910 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15911 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15912 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15913 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15914 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15915 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15916 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15918 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15919 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15920 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
15921 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
15922 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15923 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15924 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
15925 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
15927 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */
15932 static const struct hda_verb alc861_toshiba_init_verbs[] = {
15933 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
15938 /* toggle speaker-output according to the hp-jack state */
15939 static void alc861_toshiba_automute(struct hda_codec *codec)
15941 unsigned int present = snd_hda_jack_detect(codec, 0x0f);
15943 snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
15944 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
15945 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
15946 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
15949 static void alc861_toshiba_unsol_event(struct hda_codec *codec,
15950 unsigned int res)
15952 if ((res >> 26) == ALC880_HP_EVENT)
15953 alc861_toshiba_automute(codec);
15956 /* pcm configuration: identical with ALC880 */
15957 #define alc861_pcm_analog_playback alc880_pcm_analog_playback
15958 #define alc861_pcm_analog_capture alc880_pcm_analog_capture
15959 #define alc861_pcm_digital_playback alc880_pcm_digital_playback
15960 #define alc861_pcm_digital_capture alc880_pcm_digital_capture
15963 #define ALC861_DIGOUT_NID 0x07
15965 static const struct hda_channel_mode alc861_8ch_modes[1] = {
15966 { 8, NULL }
15969 static const hda_nid_t alc861_dac_nids[4] = {
15970 /* front, surround, clfe, side */
15971 0x03, 0x06, 0x05, 0x04
15974 static const hda_nid_t alc660_dac_nids[3] = {
15975 /* front, clfe, surround */
15976 0x03, 0x05, 0x06
15979 static const hda_nid_t alc861_adc_nids[1] = {
15980 /* ADC0-2 */
15981 0x08,
15984 static const struct hda_input_mux alc861_capture_source = {
15985 .num_items = 5,
15986 .items = {
15987 { "Mic", 0x0 },
15988 { "Front Mic", 0x3 },
15989 { "Line", 0x1 },
15990 { "CD", 0x4 },
15991 { "Mixer", 0x5 },
15995 static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
15997 struct alc_spec *spec = codec->spec;
15998 hda_nid_t mix, srcs[5];
15999 int i, j, num;
16001 if (snd_hda_get_connections(codec, pin, &mix, 1) != 1)
16002 return 0;
16003 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
16004 if (num < 0)
16005 return 0;
16006 for (i = 0; i < num; i++) {
16007 unsigned int type;
16008 type = get_wcaps_type(get_wcaps(codec, srcs[i]));
16009 if (type != AC_WID_AUD_OUT)
16010 continue;
16011 for (j = 0; j < spec->multiout.num_dacs; j++)
16012 if (spec->multiout.dac_nids[j] == srcs[i])
16013 break;
16014 if (j >= spec->multiout.num_dacs)
16015 return srcs[i];
16017 return 0;
16020 /* fill in the dac_nids table from the parsed pin configuration */
16021 static int alc861_auto_fill_dac_nids(struct hda_codec *codec,
16022 const struct auto_pin_cfg *cfg)
16024 struct alc_spec *spec = codec->spec;
16025 int i;
16026 hda_nid_t nid, dac;
16028 spec->multiout.dac_nids = spec->private_dac_nids;
16029 for (i = 0; i < cfg->line_outs; i++) {
16030 nid = cfg->line_out_pins[i];
16031 dac = alc861_look_for_dac(codec, nid);
16032 if (!dac)
16033 continue;
16034 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
16036 return 0;
16039 static int __alc861_create_out_sw(struct hda_codec *codec, const char *pfx,
16040 hda_nid_t nid, int idx, unsigned int chs)
16042 return __add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx, idx,
16043 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
16046 #define alc861_create_out_sw(codec, pfx, nid, chs) \
16047 __alc861_create_out_sw(codec, pfx, nid, 0, chs)
16049 /* add playback controls from the parsed DAC table */
16050 static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
16051 const struct auto_pin_cfg *cfg)
16053 struct alc_spec *spec = codec->spec;
16054 static const char * const chname[4] = {
16055 "Front", "Surround", NULL /*CLFE*/, "Side"
16057 const char *pfx = alc_get_line_out_pfx(spec, true);
16058 hda_nid_t nid;
16059 int i, err, noutputs;
16061 noutputs = cfg->line_outs;
16062 if (spec->multi_ios > 0)
16063 noutputs += spec->multi_ios;
16065 for (i = 0; i < noutputs; i++) {
16066 nid = spec->multiout.dac_nids[i];
16067 if (!nid)
16068 continue;
16069 if (!pfx && i == 2) {
16070 /* Center/LFE */
16071 err = alc861_create_out_sw(codec, "Center", nid, 1);
16072 if (err < 0)
16073 return err;
16074 err = alc861_create_out_sw(codec, "LFE", nid, 2);
16075 if (err < 0)
16076 return err;
16077 } else {
16078 const char *name = pfx;
16079 int index = i;
16080 if (!name) {
16081 name = chname[i];
16082 index = 0;
16084 err = __alc861_create_out_sw(codec, name, nid, index, 3);
16085 if (err < 0)
16086 return err;
16089 return 0;
16092 static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
16094 struct alc_spec *spec = codec->spec;
16095 int err;
16096 hda_nid_t nid;
16098 if (!pin)
16099 return 0;
16101 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
16102 nid = alc861_look_for_dac(codec, pin);
16103 if (nid) {
16104 err = alc861_create_out_sw(codec, "Headphone", nid, 3);
16105 if (err < 0)
16106 return err;
16107 spec->multiout.hp_nid = nid;
16110 return 0;
16113 /* create playback/capture controls for input pins */
16114 static int alc861_auto_create_input_ctls(struct hda_codec *codec,
16115 const struct auto_pin_cfg *cfg)
16117 return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x08, 0);
16120 static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
16121 hda_nid_t nid,
16122 int pin_type, hda_nid_t dac)
16124 hda_nid_t mix, srcs[5];
16125 int i, num;
16127 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
16128 pin_type);
16129 snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
16130 AMP_OUT_UNMUTE);
16131 if (snd_hda_get_connections(codec, nid, &mix, 1) != 1)
16132 return;
16133 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
16134 if (num < 0)
16135 return;
16136 for (i = 0; i < num; i++) {
16137 unsigned int mute;
16138 if (srcs[i] == dac || srcs[i] == 0x15)
16139 mute = AMP_IN_UNMUTE(i);
16140 else
16141 mute = AMP_IN_MUTE(i);
16142 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
16143 mute);
16147 static void alc861_auto_init_multi_out(struct hda_codec *codec)
16149 struct alc_spec *spec = codec->spec;
16150 int i;
16152 for (i = 0; i < spec->autocfg.line_outs; i++) {
16153 hda_nid_t nid = spec->autocfg.line_out_pins[i];
16154 int pin_type = get_pin_type(spec->autocfg.line_out_type);
16155 if (nid)
16156 alc861_auto_set_output_and_unmute(codec, nid, pin_type,
16157 spec->multiout.dac_nids[i]);
16161 static void alc861_auto_init_hp_out(struct hda_codec *codec)
16163 struct alc_spec *spec = codec->spec;
16165 if (spec->autocfg.hp_outs)
16166 alc861_auto_set_output_and_unmute(codec,
16167 spec->autocfg.hp_pins[0],
16168 PIN_HP,
16169 spec->multiout.hp_nid);
16170 if (spec->autocfg.speaker_outs)
16171 alc861_auto_set_output_and_unmute(codec,
16172 spec->autocfg.speaker_pins[0],
16173 PIN_OUT,
16174 spec->multiout.dac_nids[0]);
16177 static void alc861_auto_init_analog_input(struct hda_codec *codec)
16179 struct alc_spec *spec = codec->spec;
16180 struct auto_pin_cfg *cfg = &spec->autocfg;
16181 int i;
16183 for (i = 0; i < cfg->num_inputs; i++) {
16184 hda_nid_t nid = cfg->inputs[i].pin;
16185 if (nid >= 0x0c && nid <= 0x11)
16186 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
16190 /* parse the BIOS configuration and set up the alc_spec */
16191 /* return 1 if successful, 0 if the proper config is not found,
16192 * or a negative error code
16194 static int alc861_parse_auto_config(struct hda_codec *codec)
16196 struct alc_spec *spec = codec->spec;
16197 int err;
16198 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
16200 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
16201 alc861_ignore);
16202 if (err < 0)
16203 return err;
16204 if (!spec->autocfg.line_outs)
16205 return 0; /* can't find valid BIOS pin config */
16207 err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
16208 if (err < 0)
16209 return err;
16210 err = alc_auto_add_multi_channel_mode(codec);
16211 if (err < 0)
16212 return err;
16213 err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
16214 if (err < 0)
16215 return err;
16216 err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]);
16217 if (err < 0)
16218 return err;
16219 err = alc861_auto_create_input_ctls(codec, &spec->autocfg);
16220 if (err < 0)
16221 return err;
16223 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
16225 alc_auto_parse_digital(codec);
16227 if (spec->kctls.list)
16228 add_mixer(spec, spec->kctls.list);
16230 add_verb(spec, alc861_auto_init_verbs);
16232 spec->num_mux_defs = 1;
16233 spec->input_mux = &spec->private_imux[0];
16235 spec->adc_nids = alc861_adc_nids;
16236 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
16237 set_capture_mixer(codec);
16239 alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0);
16241 return 1;
16244 /* additional initialization for auto-configuration model */
16245 static void alc861_auto_init(struct hda_codec *codec)
16247 struct alc_spec *spec = codec->spec;
16248 alc861_auto_init_multi_out(codec);
16249 alc861_auto_init_hp_out(codec);
16250 alc861_auto_init_analog_input(codec);
16251 alc_auto_init_digital(codec);
16252 if (spec->unsol_event)
16253 alc_inithook(codec);
16256 #ifdef CONFIG_SND_HDA_POWER_SAVE
16257 static const struct hda_amp_list alc861_loopbacks[] = {
16258 { 0x15, HDA_INPUT, 0 },
16259 { 0x15, HDA_INPUT, 1 },
16260 { 0x15, HDA_INPUT, 2 },
16261 { 0x15, HDA_INPUT, 3 },
16262 { } /* end */
16264 #endif
16268 * configuration and preset
16270 static const char * const alc861_models[ALC861_MODEL_LAST] = {
16271 [ALC861_3ST] = "3stack",
16272 [ALC660_3ST] = "3stack-660",
16273 [ALC861_3ST_DIG] = "3stack-dig",
16274 [ALC861_6ST_DIG] = "6stack-dig",
16275 [ALC861_UNIWILL_M31] = "uniwill-m31",
16276 [ALC861_TOSHIBA] = "toshiba",
16277 [ALC861_ASUS] = "asus",
16278 [ALC861_ASUS_LAPTOP] = "asus-laptop",
16279 [ALC861_AUTO] = "auto",
16282 static const struct snd_pci_quirk alc861_cfg_tbl[] = {
16283 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
16284 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
16285 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
16286 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
16287 SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
16288 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
16289 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
16290 /* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
16291 * Any other models that need this preset?
16293 /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
16294 SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
16295 SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
16296 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
16297 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
16298 SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
16299 /* FIXME: the below seems conflict */
16300 /* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */
16301 SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
16302 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
16306 static const struct alc_config_preset alc861_presets[] = {
16307 [ALC861_3ST] = {
16308 .mixers = { alc861_3ST_mixer },
16309 .init_verbs = { alc861_threestack_init_verbs },
16310 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16311 .dac_nids = alc861_dac_nids,
16312 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
16313 .channel_mode = alc861_threestack_modes,
16314 .need_dac_fix = 1,
16315 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16316 .adc_nids = alc861_adc_nids,
16317 .input_mux = &alc861_capture_source,
16319 [ALC861_3ST_DIG] = {
16320 .mixers = { alc861_base_mixer },
16321 .init_verbs = { alc861_threestack_init_verbs },
16322 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16323 .dac_nids = alc861_dac_nids,
16324 .dig_out_nid = ALC861_DIGOUT_NID,
16325 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
16326 .channel_mode = alc861_threestack_modes,
16327 .need_dac_fix = 1,
16328 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16329 .adc_nids = alc861_adc_nids,
16330 .input_mux = &alc861_capture_source,
16332 [ALC861_6ST_DIG] = {
16333 .mixers = { alc861_base_mixer },
16334 .init_verbs = { alc861_base_init_verbs },
16335 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16336 .dac_nids = alc861_dac_nids,
16337 .dig_out_nid = ALC861_DIGOUT_NID,
16338 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
16339 .channel_mode = alc861_8ch_modes,
16340 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16341 .adc_nids = alc861_adc_nids,
16342 .input_mux = &alc861_capture_source,
16344 [ALC660_3ST] = {
16345 .mixers = { alc861_3ST_mixer },
16346 .init_verbs = { alc861_threestack_init_verbs },
16347 .num_dacs = ARRAY_SIZE(alc660_dac_nids),
16348 .dac_nids = alc660_dac_nids,
16349 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
16350 .channel_mode = alc861_threestack_modes,
16351 .need_dac_fix = 1,
16352 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16353 .adc_nids = alc861_adc_nids,
16354 .input_mux = &alc861_capture_source,
16356 [ALC861_UNIWILL_M31] = {
16357 .mixers = { alc861_uniwill_m31_mixer },
16358 .init_verbs = { alc861_uniwill_m31_init_verbs },
16359 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16360 .dac_nids = alc861_dac_nids,
16361 .dig_out_nid = ALC861_DIGOUT_NID,
16362 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
16363 .channel_mode = alc861_uniwill_m31_modes,
16364 .need_dac_fix = 1,
16365 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16366 .adc_nids = alc861_adc_nids,
16367 .input_mux = &alc861_capture_source,
16369 [ALC861_TOSHIBA] = {
16370 .mixers = { alc861_toshiba_mixer },
16371 .init_verbs = { alc861_base_init_verbs,
16372 alc861_toshiba_init_verbs },
16373 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16374 .dac_nids = alc861_dac_nids,
16375 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
16376 .channel_mode = alc883_3ST_2ch_modes,
16377 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16378 .adc_nids = alc861_adc_nids,
16379 .input_mux = &alc861_capture_source,
16380 .unsol_event = alc861_toshiba_unsol_event,
16381 .init_hook = alc861_toshiba_automute,
16383 [ALC861_ASUS] = {
16384 .mixers = { alc861_asus_mixer },
16385 .init_verbs = { alc861_asus_init_verbs },
16386 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16387 .dac_nids = alc861_dac_nids,
16388 .dig_out_nid = ALC861_DIGOUT_NID,
16389 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
16390 .channel_mode = alc861_asus_modes,
16391 .need_dac_fix = 1,
16392 .hp_nid = 0x06,
16393 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16394 .adc_nids = alc861_adc_nids,
16395 .input_mux = &alc861_capture_source,
16397 [ALC861_ASUS_LAPTOP] = {
16398 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
16399 .init_verbs = { alc861_asus_init_verbs,
16400 alc861_asus_laptop_init_verbs },
16401 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16402 .dac_nids = alc861_dac_nids,
16403 .dig_out_nid = ALC861_DIGOUT_NID,
16404 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
16405 .channel_mode = alc883_3ST_2ch_modes,
16406 .need_dac_fix = 1,
16407 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16408 .adc_nids = alc861_adc_nids,
16409 .input_mux = &alc861_capture_source,
16413 /* Pin config fixes */
16414 enum {
16415 PINFIX_FSC_AMILO_PI1505,
16418 static const struct alc_fixup alc861_fixups[] = {
16419 [PINFIX_FSC_AMILO_PI1505] = {
16420 .type = ALC_FIXUP_PINS,
16421 .v.pins = (const struct alc_pincfg[]) {
16422 { 0x0b, 0x0221101f }, /* HP */
16423 { 0x0f, 0x90170310 }, /* speaker */
16429 static const struct snd_pci_quirk alc861_fixup_tbl[] = {
16430 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
16434 static int patch_alc861(struct hda_codec *codec)
16436 struct alc_spec *spec;
16437 int board_config;
16438 int err;
16440 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
16441 if (spec == NULL)
16442 return -ENOMEM;
16444 codec->spec = spec;
16446 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
16447 alc861_models,
16448 alc861_cfg_tbl);
16450 if (board_config < 0) {
16451 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
16452 codec->chip_name);
16453 board_config = ALC861_AUTO;
16456 if (board_config == ALC861_AUTO) {
16457 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
16458 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
16461 if (board_config == ALC861_AUTO) {
16462 /* automatic parse from the BIOS config */
16463 err = alc861_parse_auto_config(codec);
16464 if (err < 0) {
16465 alc_free(codec);
16466 return err;
16467 } else if (!err) {
16468 printk(KERN_INFO
16469 "hda_codec: Cannot set up configuration "
16470 "from BIOS. Using base mode...\n");
16471 board_config = ALC861_3ST_DIG;
16475 err = snd_hda_attach_beep_device(codec, 0x23);
16476 if (err < 0) {
16477 alc_free(codec);
16478 return err;
16481 if (board_config != ALC861_AUTO)
16482 setup_preset(codec, &alc861_presets[board_config]);
16484 spec->stream_analog_playback = &alc861_pcm_analog_playback;
16485 spec->stream_analog_capture = &alc861_pcm_analog_capture;
16487 spec->stream_digital_playback = &alc861_pcm_digital_playback;
16488 spec->stream_digital_capture = &alc861_pcm_digital_capture;
16490 if (!spec->cap_mixer)
16491 set_capture_mixer(codec);
16492 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
16494 spec->vmaster_nid = 0x03;
16496 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
16498 codec->patch_ops = alc_patch_ops;
16499 if (board_config == ALC861_AUTO) {
16500 spec->init_hook = alc861_auto_init;
16501 #ifdef CONFIG_SND_HDA_POWER_SAVE
16502 spec->power_hook = alc_power_eapd;
16503 #endif
16505 #ifdef CONFIG_SND_HDA_POWER_SAVE
16506 if (!spec->loopback.amplist)
16507 spec->loopback.amplist = alc861_loopbacks;
16508 #endif
16510 return 0;
16514 * ALC861-VD support
16516 * Based on ALC882
16518 * In addition, an independent DAC
16520 #define ALC861VD_DIGOUT_NID 0x06
16522 static const hda_nid_t alc861vd_dac_nids[4] = {
16523 /* front, surr, clfe, side surr */
16524 0x02, 0x03, 0x04, 0x05
16527 /* dac_nids for ALC660vd are in a different order - according to
16528 * Realtek's driver.
16529 * This should probably result in a different mixer for 6stack models
16530 * of ALC660vd codecs, but for now there is only 3stack mixer
16531 * - and it is the same as in 861vd.
16532 * adc_nids in ALC660vd are (is) the same as in 861vd
16534 static const hda_nid_t alc660vd_dac_nids[3] = {
16535 /* front, rear, clfe, rear_surr */
16536 0x02, 0x04, 0x03
16539 static const hda_nid_t alc861vd_adc_nids[1] = {
16540 /* ADC0 */
16541 0x09,
16544 static const hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
16546 /* input MUX */
16547 /* FIXME: should be a matrix-type input source selection */
16548 static const struct hda_input_mux alc861vd_capture_source = {
16549 .num_items = 4,
16550 .items = {
16551 { "Mic", 0x0 },
16552 { "Front Mic", 0x1 },
16553 { "Line", 0x2 },
16554 { "CD", 0x4 },
16558 static const struct hda_input_mux alc861vd_dallas_capture_source = {
16559 .num_items = 2,
16560 .items = {
16561 { "Mic", 0x0 },
16562 { "Internal Mic", 0x1 },
16566 static const struct hda_input_mux alc861vd_hp_capture_source = {
16567 .num_items = 2,
16568 .items = {
16569 { "Front Mic", 0x0 },
16570 { "ATAPI Mic", 0x1 },
16575 * 2ch mode
16577 static const struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
16578 { 2, NULL }
16582 * 6ch mode
16584 static const struct hda_verb alc861vd_6stack_ch6_init[] = {
16585 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
16586 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16587 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16588 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16589 { } /* end */
16593 * 8ch mode
16595 static const struct hda_verb alc861vd_6stack_ch8_init[] = {
16596 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16597 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16598 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16599 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16600 { } /* end */
16603 static const struct hda_channel_mode alc861vd_6stack_modes[2] = {
16604 { 6, alc861vd_6stack_ch6_init },
16605 { 8, alc861vd_6stack_ch8_init },
16608 static const struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
16610 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16611 .name = "Channel Mode",
16612 .info = alc_ch_mode_info,
16613 .get = alc_ch_mode_get,
16614 .put = alc_ch_mode_put,
16616 { } /* end */
16619 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
16620 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
16622 static const struct snd_kcontrol_new alc861vd_6st_mixer[] = {
16623 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16624 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
16626 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16627 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
16629 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
16630 HDA_OUTPUT),
16631 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
16632 HDA_OUTPUT),
16633 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
16634 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
16636 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
16637 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
16639 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16641 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
16642 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16643 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16645 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
16646 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16647 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16649 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16650 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16652 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16653 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16655 { } /* end */
16658 static const struct snd_kcontrol_new alc861vd_3st_mixer[] = {
16659 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16660 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
16662 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16664 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
16665 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16666 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16668 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
16669 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16670 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16672 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16673 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16675 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16676 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16678 { } /* end */
16681 static const struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
16682 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16683 /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
16684 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
16686 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16688 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
16689 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16690 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16692 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
16693 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16694 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16696 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16697 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16699 { } /* end */
16702 /* Pin assignment: Speaker=0x14, HP = 0x15,
16703 * Mic=0x18, Internal Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
16705 static const struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
16706 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16707 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
16708 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16709 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
16710 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
16711 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16712 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16713 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
16714 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16715 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16716 { } /* end */
16719 /* Pin assignment: Speaker=0x14, Line-out = 0x15,
16720 * Front Mic=0x18, ATAPI Mic = 0x19,
16722 static const struct snd_kcontrol_new alc861vd_hp_mixer[] = {
16723 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16724 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
16725 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16726 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
16727 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16728 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16729 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16730 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16732 { } /* end */
16736 * generic initialization of ADC, input mixers and output mixers
16738 static const struct hda_verb alc861vd_volume_init_verbs[] = {
16740 * Unmute ADC0 and set the default input to mic-in
16742 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
16743 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16745 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
16746 * the analog-loopback mixer widget
16748 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
16749 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16750 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16751 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
16752 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
16753 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
16755 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
16756 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16757 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16758 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
16759 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
16762 * Set up output mixers (0x02 - 0x05)
16764 /* set vol=0 to output mixers */
16765 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16766 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16767 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16768 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16770 /* set up input amps for analog loopback */
16771 /* Amp Indices: DAC = 0, mixer = 1 */
16772 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16773 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16774 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16775 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16776 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16777 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16778 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16779 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16785 * 3-stack pin configuration:
16786 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
16788 static const struct hda_verb alc861vd_3stack_init_verbs[] = {
16790 * Set pin mode and muting
16792 /* set front pin widgets 0x14 for output */
16793 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16794 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16795 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
16797 /* Mic (rear) pin: input vref at 80% */
16798 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16799 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16800 /* Front Mic pin: input vref at 80% */
16801 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16802 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16803 /* Line In pin: input */
16804 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16805 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16806 /* Line-2 In: Headphone output (output 0 - 0x0c) */
16807 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16808 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16809 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
16810 /* CD pin widget for input */
16811 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16817 * 6-stack pin configuration:
16819 static const struct hda_verb alc861vd_6stack_init_verbs[] = {
16821 * Set pin mode and muting
16823 /* set front pin widgets 0x14 for output */
16824 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16825 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16826 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
16828 /* Rear Pin: output 1 (0x0d) */
16829 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16830 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16831 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
16832 /* CLFE Pin: output 2 (0x0e) */
16833 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16834 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16835 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
16836 /* Side Pin: output 3 (0x0f) */
16837 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16838 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16839 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
16841 /* Mic (rear) pin: input vref at 80% */
16842 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16843 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16844 /* Front Mic pin: input vref at 80% */
16845 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16846 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16847 /* Line In pin: input */
16848 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16849 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16850 /* Line-2 In: Headphone output (output 0 - 0x0c) */
16851 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16852 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16853 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
16854 /* CD pin widget for input */
16855 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16860 static const struct hda_verb alc861vd_eapd_verbs[] = {
16861 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
16865 static const struct hda_verb alc660vd_eapd_verbs[] = {
16866 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
16867 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
16871 static const struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
16872 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16873 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16874 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
16875 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16876 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16880 static void alc861vd_lenovo_setup(struct hda_codec *codec)
16882 struct alc_spec *spec = codec->spec;
16883 spec->autocfg.hp_pins[0] = 0x1b;
16884 spec->autocfg.speaker_pins[0] = 0x14;
16885 spec->automute = 1;
16886 spec->automute_mode = ALC_AUTOMUTE_AMP;
16889 static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
16891 alc_hp_automute(codec);
16892 alc88x_simple_mic_automute(codec);
16895 static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
16896 unsigned int res)
16898 switch (res >> 26) {
16899 case ALC880_MIC_EVENT:
16900 alc88x_simple_mic_automute(codec);
16901 break;
16902 default:
16903 alc_sku_unsol_event(codec, res);
16904 break;
16908 static const struct hda_verb alc861vd_dallas_verbs[] = {
16909 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16910 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16911 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16912 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16914 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16915 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16916 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16917 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16918 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16919 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16920 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16921 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16923 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16924 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16925 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16926 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16927 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16928 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16929 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16930 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16932 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
16933 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16934 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
16935 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16936 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16937 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16938 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16939 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16941 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16942 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
16943 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
16944 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
16946 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16947 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
16948 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16950 { } /* end */
16953 /* toggle speaker-output according to the hp-jack state */
16954 static void alc861vd_dallas_setup(struct hda_codec *codec)
16956 struct alc_spec *spec = codec->spec;
16958 spec->autocfg.hp_pins[0] = 0x15;
16959 spec->autocfg.speaker_pins[0] = 0x14;
16960 spec->automute = 1;
16961 spec->automute_mode = ALC_AUTOMUTE_AMP;
16964 #ifdef CONFIG_SND_HDA_POWER_SAVE
16965 #define alc861vd_loopbacks alc880_loopbacks
16966 #endif
16968 /* pcm configuration: identical with ALC880 */
16969 #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback
16970 #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture
16971 #define alc861vd_pcm_digital_playback alc880_pcm_digital_playback
16972 #define alc861vd_pcm_digital_capture alc880_pcm_digital_capture
16975 * configuration and preset
16977 static const char * const alc861vd_models[ALC861VD_MODEL_LAST] = {
16978 [ALC660VD_3ST] = "3stack-660",
16979 [ALC660VD_3ST_DIG] = "3stack-660-digout",
16980 [ALC660VD_ASUS_V1S] = "asus-v1s",
16981 [ALC861VD_3ST] = "3stack",
16982 [ALC861VD_3ST_DIG] = "3stack-digout",
16983 [ALC861VD_6ST_DIG] = "6stack-digout",
16984 [ALC861VD_LENOVO] = "lenovo",
16985 [ALC861VD_DALLAS] = "dallas",
16986 [ALC861VD_HP] = "hp",
16987 [ALC861VD_AUTO] = "auto",
16990 static const struct snd_pci_quirk alc861vd_cfg_tbl[] = {
16991 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
16992 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
16993 SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
16994 /*SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),*/ /* auto */
16995 SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S),
16996 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
16997 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
16998 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
16999 /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
17000 SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
17001 SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
17002 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
17003 SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
17004 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO),
17005 SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
17009 static const struct alc_config_preset alc861vd_presets[] = {
17010 [ALC660VD_3ST] = {
17011 .mixers = { alc861vd_3st_mixer },
17012 .init_verbs = { alc861vd_volume_init_verbs,
17013 alc861vd_3stack_init_verbs },
17014 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
17015 .dac_nids = alc660vd_dac_nids,
17016 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17017 .channel_mode = alc861vd_3stack_2ch_modes,
17018 .input_mux = &alc861vd_capture_source,
17020 [ALC660VD_3ST_DIG] = {
17021 .mixers = { alc861vd_3st_mixer },
17022 .init_verbs = { alc861vd_volume_init_verbs,
17023 alc861vd_3stack_init_verbs },
17024 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
17025 .dac_nids = alc660vd_dac_nids,
17026 .dig_out_nid = ALC861VD_DIGOUT_NID,
17027 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17028 .channel_mode = alc861vd_3stack_2ch_modes,
17029 .input_mux = &alc861vd_capture_source,
17031 [ALC861VD_3ST] = {
17032 .mixers = { alc861vd_3st_mixer },
17033 .init_verbs = { alc861vd_volume_init_verbs,
17034 alc861vd_3stack_init_verbs },
17035 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
17036 .dac_nids = alc861vd_dac_nids,
17037 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17038 .channel_mode = alc861vd_3stack_2ch_modes,
17039 .input_mux = &alc861vd_capture_source,
17041 [ALC861VD_3ST_DIG] = {
17042 .mixers = { alc861vd_3st_mixer },
17043 .init_verbs = { alc861vd_volume_init_verbs,
17044 alc861vd_3stack_init_verbs },
17045 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
17046 .dac_nids = alc861vd_dac_nids,
17047 .dig_out_nid = ALC861VD_DIGOUT_NID,
17048 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17049 .channel_mode = alc861vd_3stack_2ch_modes,
17050 .input_mux = &alc861vd_capture_source,
17052 [ALC861VD_6ST_DIG] = {
17053 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
17054 .init_verbs = { alc861vd_volume_init_verbs,
17055 alc861vd_6stack_init_verbs },
17056 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
17057 .dac_nids = alc861vd_dac_nids,
17058 .dig_out_nid = ALC861VD_DIGOUT_NID,
17059 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
17060 .channel_mode = alc861vd_6stack_modes,
17061 .input_mux = &alc861vd_capture_source,
17063 [ALC861VD_LENOVO] = {
17064 .mixers = { alc861vd_lenovo_mixer },
17065 .init_verbs = { alc861vd_volume_init_verbs,
17066 alc861vd_3stack_init_verbs,
17067 alc861vd_eapd_verbs,
17068 alc861vd_lenovo_unsol_verbs },
17069 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
17070 .dac_nids = alc660vd_dac_nids,
17071 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17072 .channel_mode = alc861vd_3stack_2ch_modes,
17073 .input_mux = &alc861vd_capture_source,
17074 .unsol_event = alc861vd_lenovo_unsol_event,
17075 .setup = alc861vd_lenovo_setup,
17076 .init_hook = alc861vd_lenovo_init_hook,
17078 [ALC861VD_DALLAS] = {
17079 .mixers = { alc861vd_dallas_mixer },
17080 .init_verbs = { alc861vd_dallas_verbs },
17081 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
17082 .dac_nids = alc861vd_dac_nids,
17083 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17084 .channel_mode = alc861vd_3stack_2ch_modes,
17085 .input_mux = &alc861vd_dallas_capture_source,
17086 .unsol_event = alc_sku_unsol_event,
17087 .setup = alc861vd_dallas_setup,
17088 .init_hook = alc_hp_automute,
17090 [ALC861VD_HP] = {
17091 .mixers = { alc861vd_hp_mixer },
17092 .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
17093 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
17094 .dac_nids = alc861vd_dac_nids,
17095 .dig_out_nid = ALC861VD_DIGOUT_NID,
17096 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17097 .channel_mode = alc861vd_3stack_2ch_modes,
17098 .input_mux = &alc861vd_hp_capture_source,
17099 .unsol_event = alc_sku_unsol_event,
17100 .setup = alc861vd_dallas_setup,
17101 .init_hook = alc_hp_automute,
17103 [ALC660VD_ASUS_V1S] = {
17104 .mixers = { alc861vd_lenovo_mixer },
17105 .init_verbs = { alc861vd_volume_init_verbs,
17106 alc861vd_3stack_init_verbs,
17107 alc861vd_eapd_verbs,
17108 alc861vd_lenovo_unsol_verbs },
17109 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
17110 .dac_nids = alc660vd_dac_nids,
17111 .dig_out_nid = ALC861VD_DIGOUT_NID,
17112 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17113 .channel_mode = alc861vd_3stack_2ch_modes,
17114 .input_mux = &alc861vd_capture_source,
17115 .unsol_event = alc861vd_lenovo_unsol_event,
17116 .setup = alc861vd_lenovo_setup,
17117 .init_hook = alc861vd_lenovo_init_hook,
17122 * BIOS auto configuration
17124 static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
17125 const struct auto_pin_cfg *cfg)
17127 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x22, 0);
17131 static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
17132 hda_nid_t nid, int pin_type, int dac_idx)
17134 alc_set_pin_output(codec, nid, pin_type);
17137 static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
17139 struct alc_spec *spec = codec->spec;
17140 int i;
17142 for (i = 0; i <= HDA_SIDE; i++) {
17143 hda_nid_t nid = spec->autocfg.line_out_pins[i];
17144 int pin_type = get_pin_type(spec->autocfg.line_out_type);
17145 if (nid)
17146 alc861vd_auto_set_output_and_unmute(codec, nid,
17147 pin_type, i);
17152 static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
17154 struct alc_spec *spec = codec->spec;
17155 hda_nid_t pin;
17157 pin = spec->autocfg.hp_pins[0];
17158 if (pin) /* connect to front and use dac 0 */
17159 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
17160 pin = spec->autocfg.speaker_pins[0];
17161 if (pin)
17162 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
17165 #define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID
17167 static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
17169 struct alc_spec *spec = codec->spec;
17170 struct auto_pin_cfg *cfg = &spec->autocfg;
17171 int i;
17173 for (i = 0; i < cfg->num_inputs; i++) {
17174 hda_nid_t nid = cfg->inputs[i].pin;
17175 if (alc_is_input_pin(codec, nid)) {
17176 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
17177 if (nid != ALC861VD_PIN_CD_NID &&
17178 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
17179 snd_hda_codec_write(codec, nid, 0,
17180 AC_VERB_SET_AMP_GAIN_MUTE,
17181 AMP_OUT_MUTE);
17186 #define alc861vd_auto_init_input_src alc882_auto_init_input_src
17188 #define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02)
17189 #define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)
17191 /* add playback controls from the parsed DAC table */
17192 /* Based on ALC880 version. But ALC861VD has separate,
17193 * different NIDs for mute/unmute switch and volume control */
17194 static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
17195 const struct auto_pin_cfg *cfg)
17197 static const char * const chname[4] = {
17198 "Front", "Surround", "CLFE", "Side"
17200 const char *pfx = alc_get_line_out_pfx(spec, true);
17201 hda_nid_t nid_v, nid_s;
17202 int i, err, noutputs;
17204 noutputs = cfg->line_outs;
17205 if (spec->multi_ios > 0)
17206 noutputs += spec->multi_ios;
17208 for (i = 0; i < noutputs; i++) {
17209 if (!spec->multiout.dac_nids[i])
17210 continue;
17211 nid_v = alc861vd_idx_to_mixer_vol(
17212 alc880_dac_to_idx(
17213 spec->multiout.dac_nids[i]));
17214 nid_s = alc861vd_idx_to_mixer_switch(
17215 alc880_dac_to_idx(
17216 spec->multiout.dac_nids[i]));
17218 if (!pfx && i == 2) {
17219 /* Center/LFE */
17220 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
17221 "Center",
17222 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
17223 HDA_OUTPUT));
17224 if (err < 0)
17225 return err;
17226 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
17227 "LFE",
17228 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
17229 HDA_OUTPUT));
17230 if (err < 0)
17231 return err;
17232 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
17233 "Center",
17234 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
17235 HDA_INPUT));
17236 if (err < 0)
17237 return err;
17238 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
17239 "LFE",
17240 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
17241 HDA_INPUT));
17242 if (err < 0)
17243 return err;
17244 } else {
17245 const char *name = pfx;
17246 int index = i;
17247 if (!name) {
17248 name = chname[i];
17249 index = 0;
17251 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
17252 name, index,
17253 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
17254 HDA_OUTPUT));
17255 if (err < 0)
17256 return err;
17257 err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
17258 name, index,
17259 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
17260 HDA_INPUT));
17261 if (err < 0)
17262 return err;
17265 return 0;
17268 /* add playback controls for speaker and HP outputs */
17269 /* Based on ALC880 version. But ALC861VD has separate,
17270 * different NIDs for mute/unmute switch and volume control */
17271 static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
17272 hda_nid_t pin, const char *pfx)
17274 hda_nid_t nid_v, nid_s;
17275 int err;
17277 if (!pin)
17278 return 0;
17280 if (alc880_is_fixed_pin(pin)) {
17281 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
17282 /* specify the DAC as the extra output */
17283 if (!spec->multiout.hp_nid)
17284 spec->multiout.hp_nid = nid_v;
17285 else
17286 spec->multiout.extra_out_nid[0] = nid_v;
17287 /* control HP volume/switch on the output mixer amp */
17288 nid_v = alc861vd_idx_to_mixer_vol(
17289 alc880_fixed_pin_idx(pin));
17290 nid_s = alc861vd_idx_to_mixer_switch(
17291 alc880_fixed_pin_idx(pin));
17293 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
17294 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
17295 if (err < 0)
17296 return err;
17297 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
17298 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
17299 if (err < 0)
17300 return err;
17301 } else if (alc880_is_multi_pin(pin)) {
17302 /* set manual connection */
17303 /* we have only a switch on HP-out PIN */
17304 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
17305 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
17306 if (err < 0)
17307 return err;
17309 return 0;
17312 /* parse the BIOS configuration and set up the alc_spec
17313 * return 1 if successful, 0 if the proper config is not found,
17314 * or a negative error code
17315 * Based on ALC880 version - had to change it to override
17316 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
17317 static int alc861vd_parse_auto_config(struct hda_codec *codec)
17319 struct alc_spec *spec = codec->spec;
17320 int err;
17321 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
17323 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
17324 alc861vd_ignore);
17325 if (err < 0)
17326 return err;
17327 if (!spec->autocfg.line_outs)
17328 return 0; /* can't find valid BIOS pin config */
17330 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
17331 if (err < 0)
17332 return err;
17333 err = alc_auto_add_multi_channel_mode(codec);
17334 if (err < 0)
17335 return err;
17336 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
17337 if (err < 0)
17338 return err;
17339 err = alc861vd_auto_create_extra_out(spec,
17340 spec->autocfg.speaker_pins[0],
17341 "Speaker");
17342 if (err < 0)
17343 return err;
17344 err = alc861vd_auto_create_extra_out(spec,
17345 spec->autocfg.hp_pins[0],
17346 "Headphone");
17347 if (err < 0)
17348 return err;
17349 err = alc861vd_auto_create_input_ctls(codec, &spec->autocfg);
17350 if (err < 0)
17351 return err;
17353 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
17355 alc_auto_parse_digital(codec);
17357 if (spec->kctls.list)
17358 add_mixer(spec, spec->kctls.list);
17360 add_verb(spec, alc861vd_volume_init_verbs);
17362 spec->num_mux_defs = 1;
17363 spec->input_mux = &spec->private_imux[0];
17365 err = alc_auto_add_mic_boost(codec);
17366 if (err < 0)
17367 return err;
17369 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
17371 return 1;
17374 /* additional initialization for auto-configuration model */
17375 static void alc861vd_auto_init(struct hda_codec *codec)
17377 struct alc_spec *spec = codec->spec;
17378 alc861vd_auto_init_multi_out(codec);
17379 alc861vd_auto_init_hp_out(codec);
17380 alc861vd_auto_init_analog_input(codec);
17381 alc861vd_auto_init_input_src(codec);
17382 alc_auto_init_digital(codec);
17383 if (spec->unsol_event)
17384 alc_inithook(codec);
17387 enum {
17388 ALC660VD_FIX_ASUS_GPIO1
17391 /* reset GPIO1 */
17392 static const struct alc_fixup alc861vd_fixups[] = {
17393 [ALC660VD_FIX_ASUS_GPIO1] = {
17394 .type = ALC_FIXUP_VERBS,
17395 .v.verbs = (const struct hda_verb[]) {
17396 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
17397 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
17398 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
17404 static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
17405 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
17409 static int patch_alc861vd(struct hda_codec *codec)
17411 struct alc_spec *spec;
17412 int err, board_config;
17414 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
17415 if (spec == NULL)
17416 return -ENOMEM;
17418 codec->spec = spec;
17420 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
17421 alc861vd_models,
17422 alc861vd_cfg_tbl);
17424 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
17425 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
17426 codec->chip_name);
17427 board_config = ALC861VD_AUTO;
17430 if (board_config == ALC861VD_AUTO) {
17431 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
17432 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
17435 if (board_config == ALC861VD_AUTO) {
17436 /* automatic parse from the BIOS config */
17437 err = alc861vd_parse_auto_config(codec);
17438 if (err < 0) {
17439 alc_free(codec);
17440 return err;
17441 } else if (!err) {
17442 printk(KERN_INFO
17443 "hda_codec: Cannot set up configuration "
17444 "from BIOS. Using base mode...\n");
17445 board_config = ALC861VD_3ST;
17449 err = snd_hda_attach_beep_device(codec, 0x23);
17450 if (err < 0) {
17451 alc_free(codec);
17452 return err;
17455 if (board_config != ALC861VD_AUTO)
17456 setup_preset(codec, &alc861vd_presets[board_config]);
17458 if (codec->vendor_id == 0x10ec0660) {
17459 /* always turn on EAPD */
17460 add_verb(spec, alc660vd_eapd_verbs);
17463 spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
17464 spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
17466 spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
17467 spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
17469 if (!spec->adc_nids) {
17470 spec->adc_nids = alc861vd_adc_nids;
17471 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
17473 if (!spec->capsrc_nids)
17474 spec->capsrc_nids = alc861vd_capsrc_nids;
17476 set_capture_mixer(codec);
17477 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
17479 spec->vmaster_nid = 0x02;
17481 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
17483 codec->patch_ops = alc_patch_ops;
17485 if (board_config == ALC861VD_AUTO)
17486 spec->init_hook = alc861vd_auto_init;
17487 spec->shutup = alc_eapd_shutup;
17488 #ifdef CONFIG_SND_HDA_POWER_SAVE
17489 if (!spec->loopback.amplist)
17490 spec->loopback.amplist = alc861vd_loopbacks;
17491 #endif
17493 return 0;
17497 * ALC662 support
17499 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
17500 * configuration. Each pin widget can choose any input DACs and a mixer.
17501 * Each ADC is connected from a mixer of all inputs. This makes possible
17502 * 6-channel independent captures.
17504 * In addition, an independent DAC for the multi-playback (not used in this
17505 * driver yet).
17507 #define ALC662_DIGOUT_NID 0x06
17508 #define ALC662_DIGIN_NID 0x0a
17510 static const hda_nid_t alc662_dac_nids[3] = {
17511 /* front, rear, clfe */
17512 0x02, 0x03, 0x04
17515 static const hda_nid_t alc272_dac_nids[2] = {
17516 0x02, 0x03
17519 static const hda_nid_t alc662_adc_nids[2] = {
17520 /* ADC1-2 */
17521 0x09, 0x08
17524 static const hda_nid_t alc272_adc_nids[1] = {
17525 /* ADC1-2 */
17526 0x08,
17529 static const hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
17530 static const hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
17533 /* input MUX */
17534 /* FIXME: should be a matrix-type input source selection */
17535 static const struct hda_input_mux alc662_capture_source = {
17536 .num_items = 4,
17537 .items = {
17538 { "Mic", 0x0 },
17539 { "Front Mic", 0x1 },
17540 { "Line", 0x2 },
17541 { "CD", 0x4 },
17545 static const struct hda_input_mux alc662_lenovo_101e_capture_source = {
17546 .num_items = 2,
17547 .items = {
17548 { "Mic", 0x1 },
17549 { "Line", 0x2 },
17553 static const struct hda_input_mux alc663_capture_source = {
17554 .num_items = 3,
17555 .items = {
17556 { "Mic", 0x0 },
17557 { "Front Mic", 0x1 },
17558 { "Line", 0x2 },
17562 #if 0 /* set to 1 for testing other input sources below */
17563 static const struct hda_input_mux alc272_nc10_capture_source = {
17564 .num_items = 16,
17565 .items = {
17566 { "Autoselect Mic", 0x0 },
17567 { "Internal Mic", 0x1 },
17568 { "In-0x02", 0x2 },
17569 { "In-0x03", 0x3 },
17570 { "In-0x04", 0x4 },
17571 { "In-0x05", 0x5 },
17572 { "In-0x06", 0x6 },
17573 { "In-0x07", 0x7 },
17574 { "In-0x08", 0x8 },
17575 { "In-0x09", 0x9 },
17576 { "In-0x0a", 0x0a },
17577 { "In-0x0b", 0x0b },
17578 { "In-0x0c", 0x0c },
17579 { "In-0x0d", 0x0d },
17580 { "In-0x0e", 0x0e },
17581 { "In-0x0f", 0x0f },
17584 #endif
17587 * 2ch mode
17589 static const struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
17590 { 2, NULL }
17594 * 2ch mode
17596 static const struct hda_verb alc662_3ST_ch2_init[] = {
17597 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
17598 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
17599 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
17600 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
17601 { } /* end */
17605 * 6ch mode
17607 static const struct hda_verb alc662_3ST_ch6_init[] = {
17608 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17609 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
17610 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
17611 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17612 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
17613 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
17614 { } /* end */
17617 static const struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
17618 { 2, alc662_3ST_ch2_init },
17619 { 6, alc662_3ST_ch6_init },
17623 * 2ch mode
17625 static const struct hda_verb alc662_sixstack_ch6_init[] = {
17626 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
17627 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
17628 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17629 { } /* end */
17633 * 6ch mode
17635 static const struct hda_verb alc662_sixstack_ch8_init[] = {
17636 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17637 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17638 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17639 { } /* end */
17642 static const struct hda_channel_mode alc662_5stack_modes[2] = {
17643 { 2, alc662_sixstack_ch6_init },
17644 { 6, alc662_sixstack_ch8_init },
17647 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
17648 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
17651 static const struct snd_kcontrol_new alc662_base_mixer[] = {
17652 /* output mixer control */
17653 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
17654 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
17655 HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
17656 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
17657 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
17658 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
17659 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
17660 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
17661 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17663 /*Input mixer control */
17664 HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
17665 HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
17666 HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
17667 HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
17668 HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
17669 HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
17670 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
17671 HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
17672 { } /* end */
17675 static const struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
17676 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17677 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
17678 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17679 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
17680 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
17681 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17682 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17683 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17684 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17685 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17686 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17687 { } /* end */
17690 static const struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
17691 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17692 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
17693 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17694 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
17695 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
17696 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
17697 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
17698 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
17699 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17700 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
17701 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
17702 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17703 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17704 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17705 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17706 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17707 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17708 { } /* end */
17711 static const struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
17712 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17713 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
17714 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17715 HDA_BIND_MUTE("Speaker Playback Switch", 0x03, 2, HDA_INPUT),
17716 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17717 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17718 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17719 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17720 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17721 { } /* end */
17724 static const struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
17725 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17726 ALC262_HIPPO_MASTER_SWITCH,
17728 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
17729 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17730 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17732 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
17733 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17734 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17735 { } /* end */
17738 static const struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
17739 ALC262_HIPPO_MASTER_SWITCH,
17740 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17741 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17742 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
17743 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
17744 HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),
17745 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17746 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17747 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17748 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17749 { } /* end */
17752 static const struct hda_bind_ctls alc663_asus_bind_master_vol = {
17753 .ops = &snd_hda_bind_vol,
17754 .values = {
17755 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
17756 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
17761 static const struct hda_bind_ctls alc663_asus_one_bind_switch = {
17762 .ops = &snd_hda_bind_sw,
17763 .values = {
17764 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17765 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
17770 static const struct snd_kcontrol_new alc663_m51va_mixer[] = {
17771 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17772 HDA_BIND_SW("Master Playback Switch", &alc663_asus_one_bind_switch),
17773 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17774 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17775 { } /* end */
17778 static const struct hda_bind_ctls alc663_asus_tree_bind_switch = {
17779 .ops = &snd_hda_bind_sw,
17780 .values = {
17781 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17782 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
17783 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
17788 static const struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
17789 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17790 HDA_BIND_SW("Master Playback Switch", &alc663_asus_tree_bind_switch),
17791 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17792 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17793 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17794 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17796 { } /* end */
17799 static const struct hda_bind_ctls alc663_asus_four_bind_switch = {
17800 .ops = &snd_hda_bind_sw,
17801 .values = {
17802 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17803 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
17804 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
17809 static const struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
17810 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17811 HDA_BIND_SW("Master Playback Switch", &alc663_asus_four_bind_switch),
17812 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17813 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17814 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17815 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17816 { } /* end */
17819 static const struct snd_kcontrol_new alc662_1bjd_mixer[] = {
17820 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17821 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
17822 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17823 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17824 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17825 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17826 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17827 { } /* end */
17830 static const struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
17831 .ops = &snd_hda_bind_vol,
17832 .values = {
17833 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
17834 HDA_COMPOSE_AMP_VAL(0x04, 3, 0, HDA_OUTPUT),
17839 static const struct hda_bind_ctls alc663_asus_two_bind_switch = {
17840 .ops = &snd_hda_bind_sw,
17841 .values = {
17842 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17843 HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT),
17848 static const struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
17849 HDA_BIND_VOL("Master Playback Volume",
17850 &alc663_asus_two_bind_master_vol),
17851 HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
17852 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17853 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17854 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17855 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17856 { } /* end */
17859 static const struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
17860 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17861 HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
17862 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17863 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
17864 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17865 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17866 { } /* end */
17869 static const struct snd_kcontrol_new alc663_g71v_mixer[] = {
17870 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17871 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
17872 HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17873 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
17874 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17876 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17877 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17878 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17879 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17880 { } /* end */
17883 static const struct snd_kcontrol_new alc663_g50v_mixer[] = {
17884 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17885 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
17886 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17888 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17889 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17890 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17891 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17892 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17893 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17894 { } /* end */
17897 static const struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
17898 .ops = &snd_hda_bind_sw,
17899 .values = {
17900 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17901 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
17902 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
17903 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
17904 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
17909 static const struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
17910 .ops = &snd_hda_bind_sw,
17911 .values = {
17912 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17913 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
17918 static const struct snd_kcontrol_new alc663_mode7_mixer[] = {
17919 HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
17920 HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
17921 HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
17922 HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17923 HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17924 HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17925 HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17926 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17927 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17928 { } /* end */
17931 static const struct snd_kcontrol_new alc663_mode8_mixer[] = {
17932 HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
17933 HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
17934 HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
17935 HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT),
17936 HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17937 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17938 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17939 { } /* end */
17943 static const struct snd_kcontrol_new alc662_chmode_mixer[] = {
17945 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
17946 .name = "Channel Mode",
17947 .info = alc_ch_mode_info,
17948 .get = alc_ch_mode_get,
17949 .put = alc_ch_mode_put,
17951 { } /* end */
17954 static const struct hda_verb alc662_init_verbs[] = {
17955 /* ADC: mute amp left and right */
17956 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17957 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
17959 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17960 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17961 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17962 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17963 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17964 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17966 /* Front Pin: output 0 (0x0c) */
17967 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17968 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17970 /* Rear Pin: output 1 (0x0d) */
17971 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17972 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17974 /* CLFE Pin: output 2 (0x0e) */
17975 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17976 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17978 /* Mic (rear) pin: input vref at 80% */
17979 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
17980 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
17981 /* Front Mic pin: input vref at 80% */
17982 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
17983 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
17984 /* Line In pin: input */
17985 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17986 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
17987 /* Line-2 In: Headphone output (output 0 - 0x0c) */
17988 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17989 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17990 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
17991 /* CD pin widget for input */
17992 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17994 /* FIXME: use matrix-type input source selection */
17995 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
17996 /* Input mixer */
17997 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17998 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
18003 static const struct hda_verb alc662_eapd_init_verbs[] = {
18004 /* always trun on EAPD */
18005 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
18006 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
18010 static const struct hda_verb alc662_sue_init_verbs[] = {
18011 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
18012 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
18016 static const struct hda_verb alc662_eeepc_sue_init_verbs[] = {
18017 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18018 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18022 /* Set Unsolicited Event*/
18023 static const struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
18024 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
18025 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18029 static const struct hda_verb alc663_m51va_init_verbs[] = {
18030 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18031 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18032 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18033 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18034 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18035 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18036 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
18037 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18038 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18042 static const struct hda_verb alc663_21jd_amic_init_verbs[] = {
18043 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18044 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18045 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18046 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18047 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
18048 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18049 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18053 static const struct hda_verb alc662_1bjd_amic_init_verbs[] = {
18054 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18055 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18056 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18057 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
18058 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18059 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
18060 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18061 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18065 static const struct hda_verb alc663_15jd_amic_init_verbs[] = {
18066 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18067 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18068 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18069 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18070 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
18071 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18072 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18076 static const struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
18077 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18078 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18079 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18080 {0x21, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Headphone */
18081 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18082 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18083 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Headphone */
18084 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18085 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
18086 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18087 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18088 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18092 static const struct hda_verb alc663_two_hp_amic_m2_init_verbs[] = {
18093 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18094 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18095 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18096 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18097 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18098 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18099 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18100 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18101 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
18102 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18103 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18104 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18108 static const struct hda_verb alc663_g71v_init_verbs[] = {
18109 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18110 /* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
18111 /* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
18113 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18114 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18115 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
18117 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
18118 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_MIC_EVENT},
18119 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
18123 static const struct hda_verb alc663_g50v_init_verbs[] = {
18124 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18125 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18126 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
18128 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18129 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18133 static const struct hda_verb alc662_ecs_init_verbs[] = {
18134 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
18135 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18136 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18137 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18141 static const struct hda_verb alc272_dell_zm1_init_verbs[] = {
18142 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18143 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18144 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18145 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18146 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18147 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18148 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18149 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18150 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
18151 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18152 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18156 static const struct hda_verb alc272_dell_init_verbs[] = {
18157 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18158 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18159 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18160 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18161 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18162 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18163 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18164 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18165 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
18166 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18167 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18171 static const struct hda_verb alc663_mode7_init_verbs[] = {
18172 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18173 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18174 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
18175 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18176 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18177 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18178 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
18179 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18180 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18181 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18182 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18183 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
18184 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18185 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18186 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18190 static const struct hda_verb alc663_mode8_init_verbs[] = {
18191 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18192 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18193 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18194 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
18195 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18196 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
18197 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18198 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18199 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18200 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18201 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18202 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18203 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
18204 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18205 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18206 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18210 static const struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
18211 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
18212 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
18213 { } /* end */
18216 static const struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
18217 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
18218 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
18219 { } /* end */
18222 static void alc662_lenovo_101e_setup(struct hda_codec *codec)
18224 struct alc_spec *spec = codec->spec;
18226 spec->autocfg.hp_pins[0] = 0x1b;
18227 spec->autocfg.line_out_pins[0] = 0x14;
18228 spec->autocfg.speaker_pins[0] = 0x15;
18229 spec->automute = 1;
18230 spec->detect_line = 1;
18231 spec->automute_lines = 1;
18232 spec->automute_mode = ALC_AUTOMUTE_AMP;
18235 static void alc662_eeepc_setup(struct hda_codec *codec)
18237 struct alc_spec *spec = codec->spec;
18239 alc262_hippo1_setup(codec);
18240 spec->ext_mic.pin = 0x18;
18241 spec->ext_mic.mux_idx = 0;
18242 spec->int_mic.pin = 0x19;
18243 spec->int_mic.mux_idx = 1;
18244 spec->auto_mic = 1;
18247 static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
18249 struct alc_spec *spec = codec->spec;
18251 spec->autocfg.hp_pins[0] = 0x14;
18252 spec->autocfg.speaker_pins[0] = 0x1b;
18253 spec->automute = 1;
18254 spec->automute_mode = ALC_AUTOMUTE_AMP;
18257 static void alc663_m51va_setup(struct hda_codec *codec)
18259 struct alc_spec *spec = codec->spec;
18260 spec->autocfg.hp_pins[0] = 0x21;
18261 spec->autocfg.speaker_pins[0] = 0x14;
18262 spec->automute_mixer_nid[0] = 0x0c;
18263 spec->automute = 1;
18264 spec->automute_mode = ALC_AUTOMUTE_MIXER;
18265 spec->ext_mic.pin = 0x18;
18266 spec->ext_mic.mux_idx = 0;
18267 spec->int_mic.pin = 0x12;
18268 spec->int_mic.mux_idx = 9;
18269 spec->auto_mic = 1;
18272 /* ***************** Mode1 ******************************/
18273 static void alc663_mode1_setup(struct hda_codec *codec)
18275 struct alc_spec *spec = codec->spec;
18276 spec->autocfg.hp_pins[0] = 0x21;
18277 spec->autocfg.speaker_pins[0] = 0x14;
18278 spec->automute_mixer_nid[0] = 0x0c;
18279 spec->automute = 1;
18280 spec->automute_mode = ALC_AUTOMUTE_MIXER;
18281 spec->ext_mic.pin = 0x18;
18282 spec->ext_mic.mux_idx = 0;
18283 spec->int_mic.pin = 0x19;
18284 spec->int_mic.mux_idx = 1;
18285 spec->auto_mic = 1;
18288 /* ***************** Mode2 ******************************/
18289 static void alc662_mode2_setup(struct hda_codec *codec)
18291 struct alc_spec *spec = codec->spec;
18292 spec->autocfg.hp_pins[0] = 0x1b;
18293 spec->autocfg.speaker_pins[0] = 0x14;
18294 spec->automute = 1;
18295 spec->automute_mode = ALC_AUTOMUTE_PIN;
18296 spec->ext_mic.pin = 0x18;
18297 spec->ext_mic.mux_idx = 0;
18298 spec->int_mic.pin = 0x19;
18299 spec->int_mic.mux_idx = 1;
18300 spec->auto_mic = 1;
18303 /* ***************** Mode3 ******************************/
18304 static void alc663_mode3_setup(struct hda_codec *codec)
18306 struct alc_spec *spec = codec->spec;
18307 spec->autocfg.hp_pins[0] = 0x21;
18308 spec->autocfg.hp_pins[0] = 0x15;
18309 spec->autocfg.speaker_pins[0] = 0x14;
18310 spec->automute = 1;
18311 spec->automute_mode = ALC_AUTOMUTE_PIN;
18312 spec->ext_mic.pin = 0x18;
18313 spec->ext_mic.mux_idx = 0;
18314 spec->int_mic.pin = 0x19;
18315 spec->int_mic.mux_idx = 1;
18316 spec->auto_mic = 1;
18319 /* ***************** Mode4 ******************************/
18320 static void alc663_mode4_setup(struct hda_codec *codec)
18322 struct alc_spec *spec = codec->spec;
18323 spec->autocfg.hp_pins[0] = 0x21;
18324 spec->autocfg.speaker_pins[0] = 0x14;
18325 spec->autocfg.speaker_pins[1] = 0x16;
18326 spec->automute_mixer_nid[0] = 0x0c;
18327 spec->automute_mixer_nid[1] = 0x0e;
18328 spec->automute = 1;
18329 spec->automute_mode = ALC_AUTOMUTE_MIXER;
18330 spec->ext_mic.pin = 0x18;
18331 spec->ext_mic.mux_idx = 0;
18332 spec->int_mic.pin = 0x19;
18333 spec->int_mic.mux_idx = 1;
18334 spec->auto_mic = 1;
18337 /* ***************** Mode5 ******************************/
18338 static void alc663_mode5_setup(struct hda_codec *codec)
18340 struct alc_spec *spec = codec->spec;
18341 spec->autocfg.hp_pins[0] = 0x15;
18342 spec->autocfg.speaker_pins[0] = 0x14;
18343 spec->autocfg.speaker_pins[1] = 0x16;
18344 spec->automute_mixer_nid[0] = 0x0c;
18345 spec->automute_mixer_nid[1] = 0x0e;
18346 spec->automute = 1;
18347 spec->automute_mode = ALC_AUTOMUTE_MIXER;
18348 spec->ext_mic.pin = 0x18;
18349 spec->ext_mic.mux_idx = 0;
18350 spec->int_mic.pin = 0x19;
18351 spec->int_mic.mux_idx = 1;
18352 spec->auto_mic = 1;
18355 /* ***************** Mode6 ******************************/
18356 static void alc663_mode6_setup(struct hda_codec *codec)
18358 struct alc_spec *spec = codec->spec;
18359 spec->autocfg.hp_pins[0] = 0x1b;
18360 spec->autocfg.hp_pins[0] = 0x15;
18361 spec->autocfg.speaker_pins[0] = 0x14;
18362 spec->automute_mixer_nid[0] = 0x0c;
18363 spec->automute = 1;
18364 spec->automute_mode = ALC_AUTOMUTE_MIXER;
18365 spec->ext_mic.pin = 0x18;
18366 spec->ext_mic.mux_idx = 0;
18367 spec->int_mic.pin = 0x19;
18368 spec->int_mic.mux_idx = 1;
18369 spec->auto_mic = 1;
18372 /* ***************** Mode7 ******************************/
18373 static void alc663_mode7_setup(struct hda_codec *codec)
18375 struct alc_spec *spec = codec->spec;
18376 spec->autocfg.hp_pins[0] = 0x1b;
18377 spec->autocfg.hp_pins[0] = 0x21;
18378 spec->autocfg.speaker_pins[0] = 0x14;
18379 spec->autocfg.speaker_pins[0] = 0x17;
18380 spec->automute = 1;
18381 spec->automute_mode = ALC_AUTOMUTE_PIN;
18382 spec->ext_mic.pin = 0x18;
18383 spec->ext_mic.mux_idx = 0;
18384 spec->int_mic.pin = 0x19;
18385 spec->int_mic.mux_idx = 1;
18386 spec->auto_mic = 1;
18389 /* ***************** Mode8 ******************************/
18390 static void alc663_mode8_setup(struct hda_codec *codec)
18392 struct alc_spec *spec = codec->spec;
18393 spec->autocfg.hp_pins[0] = 0x21;
18394 spec->autocfg.hp_pins[1] = 0x15;
18395 spec->autocfg.speaker_pins[0] = 0x14;
18396 spec->autocfg.speaker_pins[0] = 0x17;
18397 spec->automute = 1;
18398 spec->automute_mode = ALC_AUTOMUTE_PIN;
18399 spec->ext_mic.pin = 0x18;
18400 spec->ext_mic.mux_idx = 0;
18401 spec->int_mic.pin = 0x12;
18402 spec->int_mic.mux_idx = 9;
18403 spec->auto_mic = 1;
18406 static void alc663_g71v_setup(struct hda_codec *codec)
18408 struct alc_spec *spec = codec->spec;
18409 spec->autocfg.hp_pins[0] = 0x21;
18410 spec->autocfg.line_out_pins[0] = 0x15;
18411 spec->autocfg.speaker_pins[0] = 0x14;
18412 spec->automute = 1;
18413 spec->automute_mode = ALC_AUTOMUTE_AMP;
18414 spec->detect_line = 1;
18415 spec->automute_lines = 1;
18416 spec->ext_mic.pin = 0x18;
18417 spec->ext_mic.mux_idx = 0;
18418 spec->int_mic.pin = 0x12;
18419 spec->int_mic.mux_idx = 9;
18420 spec->auto_mic = 1;
18423 #define alc663_g50v_setup alc663_m51va_setup
18425 static const struct snd_kcontrol_new alc662_ecs_mixer[] = {
18426 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
18427 ALC262_HIPPO_MASTER_SWITCH,
18429 HDA_CODEC_VOLUME("Mic/LineIn Boost Volume", 0x18, 0, HDA_INPUT),
18430 HDA_CODEC_VOLUME("Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT),
18431 HDA_CODEC_MUTE("Mic/LineIn Playback Switch", 0x0b, 0x0, HDA_INPUT),
18433 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
18434 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
18435 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
18436 { } /* end */
18439 static const struct snd_kcontrol_new alc272_nc10_mixer[] = {
18440 /* Master Playback automatically created from Speaker and Headphone */
18441 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
18442 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
18443 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
18444 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
18446 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
18447 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
18448 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
18450 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
18451 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
18452 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
18453 { } /* end */
18456 #ifdef CONFIG_SND_HDA_POWER_SAVE
18457 #define alc662_loopbacks alc880_loopbacks
18458 #endif
18461 /* pcm configuration: identical with ALC880 */
18462 #define alc662_pcm_analog_playback alc880_pcm_analog_playback
18463 #define alc662_pcm_analog_capture alc880_pcm_analog_capture
18464 #define alc662_pcm_digital_playback alc880_pcm_digital_playback
18465 #define alc662_pcm_digital_capture alc880_pcm_digital_capture
18468 * configuration and preset
18470 static const char * const alc662_models[ALC662_MODEL_LAST] = {
18471 [ALC662_3ST_2ch_DIG] = "3stack-dig",
18472 [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig",
18473 [ALC662_3ST_6ch] = "3stack-6ch",
18474 [ALC662_5ST_DIG] = "5stack-dig",
18475 [ALC662_LENOVO_101E] = "lenovo-101e",
18476 [ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
18477 [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
18478 [ALC662_ECS] = "ecs",
18479 [ALC663_ASUS_M51VA] = "m51va",
18480 [ALC663_ASUS_G71V] = "g71v",
18481 [ALC663_ASUS_H13] = "h13",
18482 [ALC663_ASUS_G50V] = "g50v",
18483 [ALC663_ASUS_MODE1] = "asus-mode1",
18484 [ALC662_ASUS_MODE2] = "asus-mode2",
18485 [ALC663_ASUS_MODE3] = "asus-mode3",
18486 [ALC663_ASUS_MODE4] = "asus-mode4",
18487 [ALC663_ASUS_MODE5] = "asus-mode5",
18488 [ALC663_ASUS_MODE6] = "asus-mode6",
18489 [ALC663_ASUS_MODE7] = "asus-mode7",
18490 [ALC663_ASUS_MODE8] = "asus-mode8",
18491 [ALC272_DELL] = "dell",
18492 [ALC272_DELL_ZM1] = "dell-zm1",
18493 [ALC272_SAMSUNG_NC10] = "samsung-nc10",
18494 [ALC662_AUTO] = "auto",
18497 static const struct snd_pci_quirk alc662_cfg_tbl[] = {
18498 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
18499 SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL),
18500 SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
18501 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
18502 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
18503 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1),
18504 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
18505 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
18506 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
18507 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
18508 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1),
18509 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1),
18510 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
18511 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7),
18512 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7),
18513 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8),
18514 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3),
18515 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1),
18516 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
18517 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2),
18518 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1),
18519 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
18520 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
18521 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
18522 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
18523 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1),
18524 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
18525 SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
18526 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
18527 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
18528 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
18529 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
18530 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
18531 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC663_ASUS_MODE1),
18532 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
18533 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
18534 SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
18535 /*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/
18536 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
18537 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
18538 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1),
18539 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1),
18540 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1),
18541 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1),
18542 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
18543 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
18544 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
18545 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC663_ASUS_MODE1),
18546 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
18547 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
18548 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC663_ASUS_MODE1),
18549 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
18550 SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
18551 /*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/
18552 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
18553 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
18554 SND_PCI_QUIRK(0x1043, 0x19d3, "ASUS NB", ALC663_ASUS_M51VA),
18555 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
18556 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
18557 SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
18558 SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
18559 SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
18560 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
18561 SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
18562 ALC662_3ST_6ch_DIG),
18563 SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
18564 SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
18565 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
18566 ALC662_3ST_6ch_DIG),
18567 SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
18568 SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
18569 SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
18570 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
18571 SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
18572 ALC662_3ST_6ch_DIG),
18573 SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
18574 ALC663_ASUS_H13),
18575 SND_PCI_QUIRK(0x1991, 0x5628, "Ordissimo EVE", ALC662_LENOVO_101E),
18579 static const struct alc_config_preset alc662_presets[] = {
18580 [ALC662_3ST_2ch_DIG] = {
18581 .mixers = { alc662_3ST_2ch_mixer },
18582 .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
18583 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18584 .dac_nids = alc662_dac_nids,
18585 .dig_out_nid = ALC662_DIGOUT_NID,
18586 .dig_in_nid = ALC662_DIGIN_NID,
18587 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18588 .channel_mode = alc662_3ST_2ch_modes,
18589 .input_mux = &alc662_capture_source,
18591 [ALC662_3ST_6ch_DIG] = {
18592 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
18593 .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
18594 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18595 .dac_nids = alc662_dac_nids,
18596 .dig_out_nid = ALC662_DIGOUT_NID,
18597 .dig_in_nid = ALC662_DIGIN_NID,
18598 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18599 .channel_mode = alc662_3ST_6ch_modes,
18600 .need_dac_fix = 1,
18601 .input_mux = &alc662_capture_source,
18603 [ALC662_3ST_6ch] = {
18604 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
18605 .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
18606 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18607 .dac_nids = alc662_dac_nids,
18608 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18609 .channel_mode = alc662_3ST_6ch_modes,
18610 .need_dac_fix = 1,
18611 .input_mux = &alc662_capture_source,
18613 [ALC662_5ST_DIG] = {
18614 .mixers = { alc662_base_mixer, alc662_chmode_mixer },
18615 .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
18616 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18617 .dac_nids = alc662_dac_nids,
18618 .dig_out_nid = ALC662_DIGOUT_NID,
18619 .dig_in_nid = ALC662_DIGIN_NID,
18620 .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
18621 .channel_mode = alc662_5stack_modes,
18622 .input_mux = &alc662_capture_source,
18624 [ALC662_LENOVO_101E] = {
18625 .mixers = { alc662_lenovo_101e_mixer },
18626 .init_verbs = { alc662_init_verbs,
18627 alc662_eapd_init_verbs,
18628 alc662_sue_init_verbs },
18629 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18630 .dac_nids = alc662_dac_nids,
18631 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18632 .channel_mode = alc662_3ST_2ch_modes,
18633 .input_mux = &alc662_lenovo_101e_capture_source,
18634 .unsol_event = alc_sku_unsol_event,
18635 .setup = alc662_lenovo_101e_setup,
18636 .init_hook = alc_inithook,
18638 [ALC662_ASUS_EEEPC_P701] = {
18639 .mixers = { alc662_eeepc_p701_mixer },
18640 .init_verbs = { alc662_init_verbs,
18641 alc662_eapd_init_verbs,
18642 alc662_eeepc_sue_init_verbs },
18643 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18644 .dac_nids = alc662_dac_nids,
18645 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18646 .channel_mode = alc662_3ST_2ch_modes,
18647 .unsol_event = alc_sku_unsol_event,
18648 .setup = alc662_eeepc_setup,
18649 .init_hook = alc_inithook,
18651 [ALC662_ASUS_EEEPC_EP20] = {
18652 .mixers = { alc662_eeepc_ep20_mixer,
18653 alc662_chmode_mixer },
18654 .init_verbs = { alc662_init_verbs,
18655 alc662_eapd_init_verbs,
18656 alc662_eeepc_ep20_sue_init_verbs },
18657 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18658 .dac_nids = alc662_dac_nids,
18659 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18660 .channel_mode = alc662_3ST_6ch_modes,
18661 .input_mux = &alc662_lenovo_101e_capture_source,
18662 .unsol_event = alc_sku_unsol_event,
18663 .setup = alc662_eeepc_ep20_setup,
18664 .init_hook = alc_inithook,
18666 [ALC662_ECS] = {
18667 .mixers = { alc662_ecs_mixer },
18668 .init_verbs = { alc662_init_verbs,
18669 alc662_eapd_init_verbs,
18670 alc662_ecs_init_verbs },
18671 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18672 .dac_nids = alc662_dac_nids,
18673 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18674 .channel_mode = alc662_3ST_2ch_modes,
18675 .unsol_event = alc_sku_unsol_event,
18676 .setup = alc662_eeepc_setup,
18677 .init_hook = alc_inithook,
18679 [ALC663_ASUS_M51VA] = {
18680 .mixers = { alc663_m51va_mixer },
18681 .init_verbs = { alc662_init_verbs,
18682 alc662_eapd_init_verbs,
18683 alc663_m51va_init_verbs },
18684 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18685 .dac_nids = alc662_dac_nids,
18686 .dig_out_nid = ALC662_DIGOUT_NID,
18687 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18688 .channel_mode = alc662_3ST_2ch_modes,
18689 .unsol_event = alc_sku_unsol_event,
18690 .setup = alc663_m51va_setup,
18691 .init_hook = alc_inithook,
18693 [ALC663_ASUS_G71V] = {
18694 .mixers = { alc663_g71v_mixer },
18695 .init_verbs = { alc662_init_verbs,
18696 alc662_eapd_init_verbs,
18697 alc663_g71v_init_verbs },
18698 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18699 .dac_nids = alc662_dac_nids,
18700 .dig_out_nid = ALC662_DIGOUT_NID,
18701 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18702 .channel_mode = alc662_3ST_2ch_modes,
18703 .unsol_event = alc_sku_unsol_event,
18704 .setup = alc663_g71v_setup,
18705 .init_hook = alc_inithook,
18707 [ALC663_ASUS_H13] = {
18708 .mixers = { alc663_m51va_mixer },
18709 .init_verbs = { alc662_init_verbs,
18710 alc662_eapd_init_verbs,
18711 alc663_m51va_init_verbs },
18712 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18713 .dac_nids = alc662_dac_nids,
18714 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18715 .channel_mode = alc662_3ST_2ch_modes,
18716 .setup = alc663_m51va_setup,
18717 .unsol_event = alc_sku_unsol_event,
18718 .init_hook = alc_inithook,
18720 [ALC663_ASUS_G50V] = {
18721 .mixers = { alc663_g50v_mixer },
18722 .init_verbs = { alc662_init_verbs,
18723 alc662_eapd_init_verbs,
18724 alc663_g50v_init_verbs },
18725 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18726 .dac_nids = alc662_dac_nids,
18727 .dig_out_nid = ALC662_DIGOUT_NID,
18728 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18729 .channel_mode = alc662_3ST_6ch_modes,
18730 .input_mux = &alc663_capture_source,
18731 .unsol_event = alc_sku_unsol_event,
18732 .setup = alc663_g50v_setup,
18733 .init_hook = alc_inithook,
18735 [ALC663_ASUS_MODE1] = {
18736 .mixers = { alc663_m51va_mixer },
18737 .cap_mixer = alc662_auto_capture_mixer,
18738 .init_verbs = { alc662_init_verbs,
18739 alc662_eapd_init_verbs,
18740 alc663_21jd_amic_init_verbs },
18741 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18742 .hp_nid = 0x03,
18743 .dac_nids = alc662_dac_nids,
18744 .dig_out_nid = ALC662_DIGOUT_NID,
18745 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18746 .channel_mode = alc662_3ST_2ch_modes,
18747 .unsol_event = alc_sku_unsol_event,
18748 .setup = alc663_mode1_setup,
18749 .init_hook = alc_inithook,
18751 [ALC662_ASUS_MODE2] = {
18752 .mixers = { alc662_1bjd_mixer },
18753 .cap_mixer = alc662_auto_capture_mixer,
18754 .init_verbs = { alc662_init_verbs,
18755 alc662_eapd_init_verbs,
18756 alc662_1bjd_amic_init_verbs },
18757 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18758 .dac_nids = alc662_dac_nids,
18759 .dig_out_nid = ALC662_DIGOUT_NID,
18760 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18761 .channel_mode = alc662_3ST_2ch_modes,
18762 .unsol_event = alc_sku_unsol_event,
18763 .setup = alc662_mode2_setup,
18764 .init_hook = alc_inithook,
18766 [ALC663_ASUS_MODE3] = {
18767 .mixers = { alc663_two_hp_m1_mixer },
18768 .cap_mixer = alc662_auto_capture_mixer,
18769 .init_verbs = { alc662_init_verbs,
18770 alc662_eapd_init_verbs,
18771 alc663_two_hp_amic_m1_init_verbs },
18772 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18773 .hp_nid = 0x03,
18774 .dac_nids = alc662_dac_nids,
18775 .dig_out_nid = ALC662_DIGOUT_NID,
18776 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18777 .channel_mode = alc662_3ST_2ch_modes,
18778 .unsol_event = alc_sku_unsol_event,
18779 .setup = alc663_mode3_setup,
18780 .init_hook = alc_inithook,
18782 [ALC663_ASUS_MODE4] = {
18783 .mixers = { alc663_asus_21jd_clfe_mixer },
18784 .cap_mixer = alc662_auto_capture_mixer,
18785 .init_verbs = { alc662_init_verbs,
18786 alc662_eapd_init_verbs,
18787 alc663_21jd_amic_init_verbs},
18788 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18789 .hp_nid = 0x03,
18790 .dac_nids = alc662_dac_nids,
18791 .dig_out_nid = ALC662_DIGOUT_NID,
18792 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18793 .channel_mode = alc662_3ST_2ch_modes,
18794 .unsol_event = alc_sku_unsol_event,
18795 .setup = alc663_mode4_setup,
18796 .init_hook = alc_inithook,
18798 [ALC663_ASUS_MODE5] = {
18799 .mixers = { alc663_asus_15jd_clfe_mixer },
18800 .cap_mixer = alc662_auto_capture_mixer,
18801 .init_verbs = { alc662_init_verbs,
18802 alc662_eapd_init_verbs,
18803 alc663_15jd_amic_init_verbs },
18804 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18805 .hp_nid = 0x03,
18806 .dac_nids = alc662_dac_nids,
18807 .dig_out_nid = ALC662_DIGOUT_NID,
18808 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18809 .channel_mode = alc662_3ST_2ch_modes,
18810 .unsol_event = alc_sku_unsol_event,
18811 .setup = alc663_mode5_setup,
18812 .init_hook = alc_inithook,
18814 [ALC663_ASUS_MODE6] = {
18815 .mixers = { alc663_two_hp_m2_mixer },
18816 .cap_mixer = alc662_auto_capture_mixer,
18817 .init_verbs = { alc662_init_verbs,
18818 alc662_eapd_init_verbs,
18819 alc663_two_hp_amic_m2_init_verbs },
18820 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18821 .hp_nid = 0x03,
18822 .dac_nids = alc662_dac_nids,
18823 .dig_out_nid = ALC662_DIGOUT_NID,
18824 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18825 .channel_mode = alc662_3ST_2ch_modes,
18826 .unsol_event = alc_sku_unsol_event,
18827 .setup = alc663_mode6_setup,
18828 .init_hook = alc_inithook,
18830 [ALC663_ASUS_MODE7] = {
18831 .mixers = { alc663_mode7_mixer },
18832 .cap_mixer = alc662_auto_capture_mixer,
18833 .init_verbs = { alc662_init_verbs,
18834 alc662_eapd_init_verbs,
18835 alc663_mode7_init_verbs },
18836 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18837 .hp_nid = 0x03,
18838 .dac_nids = alc662_dac_nids,
18839 .dig_out_nid = ALC662_DIGOUT_NID,
18840 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18841 .channel_mode = alc662_3ST_2ch_modes,
18842 .unsol_event = alc_sku_unsol_event,
18843 .setup = alc663_mode7_setup,
18844 .init_hook = alc_inithook,
18846 [ALC663_ASUS_MODE8] = {
18847 .mixers = { alc663_mode8_mixer },
18848 .cap_mixer = alc662_auto_capture_mixer,
18849 .init_verbs = { alc662_init_verbs,
18850 alc662_eapd_init_verbs,
18851 alc663_mode8_init_verbs },
18852 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18853 .hp_nid = 0x03,
18854 .dac_nids = alc662_dac_nids,
18855 .dig_out_nid = ALC662_DIGOUT_NID,
18856 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18857 .channel_mode = alc662_3ST_2ch_modes,
18858 .unsol_event = alc_sku_unsol_event,
18859 .setup = alc663_mode8_setup,
18860 .init_hook = alc_inithook,
18862 [ALC272_DELL] = {
18863 .mixers = { alc663_m51va_mixer },
18864 .cap_mixer = alc272_auto_capture_mixer,
18865 .init_verbs = { alc662_init_verbs,
18866 alc662_eapd_init_verbs,
18867 alc272_dell_init_verbs },
18868 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18869 .dac_nids = alc272_dac_nids,
18870 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18871 .adc_nids = alc272_adc_nids,
18872 .num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
18873 .capsrc_nids = alc272_capsrc_nids,
18874 .channel_mode = alc662_3ST_2ch_modes,
18875 .unsol_event = alc_sku_unsol_event,
18876 .setup = alc663_m51va_setup,
18877 .init_hook = alc_inithook,
18879 [ALC272_DELL_ZM1] = {
18880 .mixers = { alc663_m51va_mixer },
18881 .cap_mixer = alc662_auto_capture_mixer,
18882 .init_verbs = { alc662_init_verbs,
18883 alc662_eapd_init_verbs,
18884 alc272_dell_zm1_init_verbs },
18885 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18886 .dac_nids = alc272_dac_nids,
18887 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18888 .adc_nids = alc662_adc_nids,
18889 .num_adc_nids = 1,
18890 .capsrc_nids = alc662_capsrc_nids,
18891 .channel_mode = alc662_3ST_2ch_modes,
18892 .unsol_event = alc_sku_unsol_event,
18893 .setup = alc663_m51va_setup,
18894 .init_hook = alc_inithook,
18896 [ALC272_SAMSUNG_NC10] = {
18897 .mixers = { alc272_nc10_mixer },
18898 .init_verbs = { alc662_init_verbs,
18899 alc662_eapd_init_verbs,
18900 alc663_21jd_amic_init_verbs },
18901 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18902 .dac_nids = alc272_dac_nids,
18903 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18904 .channel_mode = alc662_3ST_2ch_modes,
18905 /*.input_mux = &alc272_nc10_capture_source,*/
18906 .unsol_event = alc_sku_unsol_event,
18907 .setup = alc663_mode4_setup,
18908 .init_hook = alc_inithook,
18914 * BIOS auto configuration
18917 /* convert from MIX nid to DAC */
18918 static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
18920 hda_nid_t list[5];
18921 int i, num;
18923 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
18924 for (i = 0; i < num; i++) {
18925 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
18926 return list[i];
18928 return 0;
18931 /* go down to the selector widget before the mixer */
18932 static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
18934 hda_nid_t srcs[5];
18935 int num = snd_hda_get_connections(codec, pin, srcs,
18936 ARRAY_SIZE(srcs));
18937 if (num != 1 ||
18938 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
18939 return pin;
18940 return srcs[0];
18943 /* get MIX nid connected to the given pin targeted to DAC */
18944 static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
18945 hda_nid_t dac)
18947 hda_nid_t mix[5];
18948 int i, num;
18950 pin = alc_go_down_to_selector(codec, pin);
18951 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
18952 for (i = 0; i < num; i++) {
18953 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
18954 return mix[i];
18956 return 0;
18959 /* select the connection from pin to DAC if needed */
18960 static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
18961 hda_nid_t dac)
18963 hda_nid_t mix[5];
18964 int i, num;
18966 pin = alc_go_down_to_selector(codec, pin);
18967 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
18968 if (num < 2)
18969 return 0;
18970 for (i = 0; i < num; i++) {
18971 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
18972 snd_hda_codec_update_cache(codec, pin, 0,
18973 AC_VERB_SET_CONNECT_SEL, i);
18974 return 0;
18977 return 0;
18980 /* look for an empty DAC slot */
18981 static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
18983 struct alc_spec *spec = codec->spec;
18984 hda_nid_t srcs[5];
18985 int i, j, num;
18987 pin = alc_go_down_to_selector(codec, pin);
18988 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
18989 for (i = 0; i < num; i++) {
18990 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
18991 if (!nid)
18992 continue;
18993 for (j = 0; j < spec->multiout.num_dacs; j++)
18994 if (spec->multiout.dac_nids[j] == nid)
18995 break;
18996 if (j >= spec->multiout.num_dacs)
18997 return nid;
18999 return 0;
19002 /* fill in the dac_nids table from the parsed pin configuration */
19003 static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
19004 const struct auto_pin_cfg *cfg)
19006 struct alc_spec *spec = codec->spec;
19007 int i;
19008 hda_nid_t dac;
19010 spec->multiout.dac_nids = spec->private_dac_nids;
19011 for (i = 0; i < cfg->line_outs; i++) {
19012 dac = alc_auto_look_for_dac(codec, cfg->line_out_pins[i]);
19013 if (!dac)
19014 continue;
19015 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
19017 return 0;
19020 static inline int __alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
19021 hda_nid_t nid, int idx, unsigned int chs)
19023 return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx,
19024 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
19027 static inline int __alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
19028 hda_nid_t nid, int idx, unsigned int chs)
19030 return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx,
19031 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
19034 #define alc662_add_vol_ctl(spec, pfx, nid, chs) \
19035 __alc662_add_vol_ctl(spec, pfx, nid, 0, chs)
19036 #define alc662_add_sw_ctl(spec, pfx, nid, chs) \
19037 __alc662_add_sw_ctl(spec, pfx, nid, 0, chs)
19038 #define alc662_add_stereo_vol(spec, pfx, nid) \
19039 alc662_add_vol_ctl(spec, pfx, nid, 3)
19040 #define alc662_add_stereo_sw(spec, pfx, nid) \
19041 alc662_add_sw_ctl(spec, pfx, nid, 3)
19043 /* add playback controls from the parsed DAC table */
19044 static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
19045 const struct auto_pin_cfg *cfg)
19047 struct alc_spec *spec = codec->spec;
19048 static const char * const chname[4] = {
19049 "Front", "Surround", NULL /*CLFE*/, "Side"
19051 const char *pfx = alc_get_line_out_pfx(spec, true);
19052 hda_nid_t nid, mix, pin;
19053 int i, err, noutputs;
19055 noutputs = cfg->line_outs;
19056 if (spec->multi_ios > 0)
19057 noutputs += spec->multi_ios;
19059 for (i = 0; i < noutputs; i++) {
19060 nid = spec->multiout.dac_nids[i];
19061 if (!nid)
19062 continue;
19063 if (i >= cfg->line_outs)
19064 pin = spec->multi_io[i - 1].pin;
19065 else
19066 pin = cfg->line_out_pins[i];
19067 mix = alc_auto_dac_to_mix(codec, pin, nid);
19068 if (!mix)
19069 continue;
19070 if (!pfx && i == 2) {
19071 /* Center/LFE */
19072 err = alc662_add_vol_ctl(spec, "Center", nid, 1);
19073 if (err < 0)
19074 return err;
19075 err = alc662_add_vol_ctl(spec, "LFE", nid, 2);
19076 if (err < 0)
19077 return err;
19078 err = alc662_add_sw_ctl(spec, "Center", mix, 1);
19079 if (err < 0)
19080 return err;
19081 err = alc662_add_sw_ctl(spec, "LFE", mix, 2);
19082 if (err < 0)
19083 return err;
19084 } else {
19085 const char *name = pfx;
19086 int index = i;
19087 if (!name) {
19088 name = chname[i];
19089 index = 0;
19091 err = __alc662_add_vol_ctl(spec, name, nid, index, 3);
19092 if (err < 0)
19093 return err;
19094 err = __alc662_add_sw_ctl(spec, name, mix, index, 3);
19095 if (err < 0)
19096 return err;
19099 return 0;
19102 /* add playback controls for speaker and HP outputs */
19103 /* return DAC nid if any new DAC is assigned */
19104 static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
19105 const char *pfx)
19107 struct alc_spec *spec = codec->spec;
19108 hda_nid_t nid, mix;
19109 int err;
19111 if (!pin)
19112 return 0;
19113 nid = alc_auto_look_for_dac(codec, pin);
19114 if (!nid) {
19115 /* the corresponding DAC is already occupied */
19116 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
19117 return 0; /* no way */
19118 /* create a switch only */
19119 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
19120 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
19123 mix = alc_auto_dac_to_mix(codec, pin, nid);
19124 if (!mix)
19125 return 0;
19126 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
19127 if (err < 0)
19128 return err;
19129 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
19130 if (err < 0)
19131 return err;
19132 return nid;
19135 /* create playback/capture controls for input pins */
19136 #define alc662_auto_create_input_ctls \
19137 alc882_auto_create_input_ctls
19139 static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
19140 hda_nid_t nid, int pin_type,
19141 hda_nid_t dac)
19143 int i, num;
19144 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
19146 alc_set_pin_output(codec, nid, pin_type);
19147 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
19148 for (i = 0; i < num; i++) {
19149 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
19150 continue;
19151 /* need the manual connection? */
19152 if (num > 1)
19153 snd_hda_codec_write(codec, nid, 0,
19154 AC_VERB_SET_CONNECT_SEL, i);
19155 /* unmute mixer widget inputs */
19156 snd_hda_codec_write(codec, srcs[i], 0,
19157 AC_VERB_SET_AMP_GAIN_MUTE,
19158 AMP_IN_UNMUTE(0));
19159 snd_hda_codec_write(codec, srcs[i], 0,
19160 AC_VERB_SET_AMP_GAIN_MUTE,
19161 AMP_IN_UNMUTE(1));
19162 return;
19166 static void alc662_auto_init_multi_out(struct hda_codec *codec)
19168 struct alc_spec *spec = codec->spec;
19169 int pin_type = get_pin_type(spec->autocfg.line_out_type);
19170 int i;
19172 for (i = 0; i <= HDA_SIDE; i++) {
19173 hda_nid_t nid = spec->autocfg.line_out_pins[i];
19174 if (nid)
19175 alc662_auto_set_output_and_unmute(codec, nid, pin_type,
19176 spec->multiout.dac_nids[i]);
19180 static void alc662_auto_init_hp_out(struct hda_codec *codec)
19182 struct alc_spec *spec = codec->spec;
19183 hda_nid_t pin;
19185 pin = spec->autocfg.hp_pins[0];
19186 if (pin)
19187 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP,
19188 spec->multiout.hp_nid);
19189 pin = spec->autocfg.speaker_pins[0];
19190 if (pin)
19191 alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT,
19192 spec->multiout.extra_out_nid[0]);
19195 #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
19197 static void alc662_auto_init_analog_input(struct hda_codec *codec)
19199 struct alc_spec *spec = codec->spec;
19200 struct auto_pin_cfg *cfg = &spec->autocfg;
19201 int i;
19203 for (i = 0; i < cfg->num_inputs; i++) {
19204 hda_nid_t nid = cfg->inputs[i].pin;
19205 if (alc_is_input_pin(codec, nid)) {
19206 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
19207 if (nid != ALC662_PIN_CD_NID &&
19208 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
19209 snd_hda_codec_write(codec, nid, 0,
19210 AC_VERB_SET_AMP_GAIN_MUTE,
19211 AMP_OUT_MUTE);
19216 #define alc662_auto_init_input_src alc882_auto_init_input_src
19219 * multi-io helper
19221 static int alc_auto_fill_multi_ios(struct hda_codec *codec,
19222 unsigned int location)
19224 struct alc_spec *spec = codec->spec;
19225 struct auto_pin_cfg *cfg = &spec->autocfg;
19226 int type, i, num_pins = 0;
19228 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
19229 for (i = 0; i < cfg->num_inputs; i++) {
19230 hda_nid_t nid = cfg->inputs[i].pin;
19231 hda_nid_t dac;
19232 unsigned int defcfg, caps;
19233 if (cfg->inputs[i].type != type)
19234 continue;
19235 defcfg = snd_hda_codec_get_pincfg(codec, nid);
19236 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
19237 continue;
19238 if (location && get_defcfg_location(defcfg) != location)
19239 continue;
19240 caps = snd_hda_query_pin_caps(codec, nid);
19241 if (!(caps & AC_PINCAP_OUT))
19242 continue;
19243 dac = alc_auto_look_for_dac(codec, nid);
19244 if (!dac)
19245 continue;
19246 spec->multi_io[num_pins].pin = nid;
19247 spec->multi_io[num_pins].dac = dac;
19248 num_pins++;
19249 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
19252 spec->multiout.num_dacs = 1;
19253 if (num_pins < 2)
19254 return 0;
19255 return num_pins;
19258 static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
19259 struct snd_ctl_elem_info *uinfo)
19261 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
19262 struct alc_spec *spec = codec->spec;
19264 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
19265 uinfo->count = 1;
19266 uinfo->value.enumerated.items = spec->multi_ios + 1;
19267 if (uinfo->value.enumerated.item > spec->multi_ios)
19268 uinfo->value.enumerated.item = spec->multi_ios;
19269 sprintf(uinfo->value.enumerated.name, "%dch",
19270 (uinfo->value.enumerated.item + 1) * 2);
19271 return 0;
19274 static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
19275 struct snd_ctl_elem_value *ucontrol)
19277 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
19278 struct alc_spec *spec = codec->spec;
19279 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
19280 return 0;
19283 static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
19285 struct alc_spec *spec = codec->spec;
19286 hda_nid_t nid = spec->multi_io[idx].pin;
19288 if (!spec->multi_io[idx].ctl_in)
19289 spec->multi_io[idx].ctl_in =
19290 snd_hda_codec_read(codec, nid, 0,
19291 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
19292 if (output) {
19293 snd_hda_codec_update_cache(codec, nid, 0,
19294 AC_VERB_SET_PIN_WIDGET_CONTROL,
19295 PIN_OUT);
19296 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
19297 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
19298 HDA_AMP_MUTE, 0);
19299 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
19300 } else {
19301 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
19302 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
19303 HDA_AMP_MUTE, HDA_AMP_MUTE);
19304 snd_hda_codec_update_cache(codec, nid, 0,
19305 AC_VERB_SET_PIN_WIDGET_CONTROL,
19306 spec->multi_io[idx].ctl_in);
19308 return 0;
19311 static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
19312 struct snd_ctl_elem_value *ucontrol)
19314 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
19315 struct alc_spec *spec = codec->spec;
19316 int i, ch;
19318 ch = ucontrol->value.enumerated.item[0];
19319 if (ch < 0 || ch > spec->multi_ios)
19320 return -EINVAL;
19321 if (ch == (spec->ext_channel_count - 1) / 2)
19322 return 0;
19323 spec->ext_channel_count = (ch + 1) * 2;
19324 for (i = 0; i < spec->multi_ios; i++)
19325 alc_set_multi_io(codec, i, i < ch);
19326 spec->multiout.max_channels = spec->ext_channel_count;
19327 return 1;
19330 static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
19331 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
19332 .name = "Channel Mode",
19333 .info = alc_auto_ch_mode_info,
19334 .get = alc_auto_ch_mode_get,
19335 .put = alc_auto_ch_mode_put,
19338 static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
19340 struct alc_spec *spec = codec->spec;
19341 struct auto_pin_cfg *cfg = &spec->autocfg;
19342 unsigned int location, defcfg;
19343 int num_pins;
19345 if (cfg->line_outs != 1 ||
19346 cfg->line_out_type != AUTO_PIN_LINE_OUT)
19347 return 0;
19349 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
19350 location = get_defcfg_location(defcfg);
19352 num_pins = alc_auto_fill_multi_ios(codec, location);
19353 if (num_pins > 0) {
19354 struct snd_kcontrol_new *knew;
19356 knew = alc_kcontrol_new(spec);
19357 if (!knew)
19358 return -ENOMEM;
19359 *knew = alc_auto_channel_mode_enum;
19360 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
19361 if (!knew->name)
19362 return -ENOMEM;
19364 spec->multi_ios = num_pins;
19365 spec->ext_channel_count = 2;
19366 spec->multiout.num_dacs = num_pins + 1;
19368 return 0;
19371 static int alc662_parse_auto_config(struct hda_codec *codec)
19373 struct alc_spec *spec = codec->spec;
19374 int err;
19375 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
19377 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
19378 alc662_ignore);
19379 if (err < 0)
19380 return err;
19381 if (!spec->autocfg.line_outs)
19382 return 0; /* can't find valid BIOS pin config */
19384 err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
19385 if (err < 0)
19386 return err;
19387 err = alc_auto_add_multi_channel_mode(codec);
19388 if (err < 0)
19389 return err;
19390 err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
19391 if (err < 0)
19392 return err;
19393 err = alc662_auto_create_extra_out(codec,
19394 spec->autocfg.speaker_pins[0],
19395 "Speaker");
19396 if (err < 0)
19397 return err;
19398 if (err)
19399 spec->multiout.extra_out_nid[0] = err;
19400 err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
19401 "Headphone");
19402 if (err < 0)
19403 return err;
19404 if (err)
19405 spec->multiout.hp_nid = err;
19406 err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
19407 if (err < 0)
19408 return err;
19410 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
19412 alc_auto_parse_digital(codec);
19414 if (spec->kctls.list)
19415 add_mixer(spec, spec->kctls.list);
19417 spec->num_mux_defs = 1;
19418 spec->input_mux = &spec->private_imux[0];
19420 err = alc_auto_add_mic_boost(codec);
19421 if (err < 0)
19422 return err;
19424 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
19425 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
19426 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21);
19427 else
19428 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
19430 return 1;
19433 /* additional initialization for auto-configuration model */
19434 static void alc662_auto_init(struct hda_codec *codec)
19436 struct alc_spec *spec = codec->spec;
19437 alc662_auto_init_multi_out(codec);
19438 alc662_auto_init_hp_out(codec);
19439 alc662_auto_init_analog_input(codec);
19440 alc662_auto_init_input_src(codec);
19441 alc_auto_init_digital(codec);
19442 if (spec->unsol_event)
19443 alc_inithook(codec);
19446 static void alc272_fixup_mario(struct hda_codec *codec,
19447 const struct alc_fixup *fix, int action)
19449 if (action != ALC_FIXUP_ACT_PROBE)
19450 return;
19451 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
19452 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
19453 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
19454 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
19455 (0 << AC_AMPCAP_MUTE_SHIFT)))
19456 printk(KERN_WARNING
19457 "hda_codec: failed to override amp caps for NID 0x2\n");
19460 enum {
19461 ALC662_FIXUP_ASPIRE,
19462 ALC662_FIXUP_IDEAPAD,
19463 ALC272_FIXUP_MARIO,
19464 ALC662_FIXUP_CZC_P10T,
19465 ALC662_FIXUP_SKU_IGNORE,
19468 static const struct alc_fixup alc662_fixups[] = {
19469 [ALC662_FIXUP_ASPIRE] = {
19470 .type = ALC_FIXUP_PINS,
19471 .v.pins = (const struct alc_pincfg[]) {
19472 { 0x15, 0x99130112 }, /* subwoofer */
19476 [ALC662_FIXUP_IDEAPAD] = {
19477 .type = ALC_FIXUP_PINS,
19478 .v.pins = (const struct alc_pincfg[]) {
19479 { 0x17, 0x99130112 }, /* subwoofer */
19483 [ALC272_FIXUP_MARIO] = {
19484 .type = ALC_FIXUP_FUNC,
19485 .v.func = alc272_fixup_mario,
19487 [ALC662_FIXUP_CZC_P10T] = {
19488 .type = ALC_FIXUP_VERBS,
19489 .v.verbs = (const struct hda_verb[]) {
19490 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
19494 [ALC662_FIXUP_SKU_IGNORE] = {
19495 .type = ALC_FIXUP_SKU,
19496 .v.sku = ALC_FIXUP_SKU_IGNORE,
19500 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
19501 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
19502 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
19503 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
19504 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
19505 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
19506 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
19507 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
19511 static const struct alc_model_fixup alc662_fixup_models[] = {
19512 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
19517 static int patch_alc662(struct hda_codec *codec)
19519 struct alc_spec *spec;
19520 int err, board_config;
19521 int coef;
19523 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
19524 if (!spec)
19525 return -ENOMEM;
19527 codec->spec = spec;
19529 alc_auto_parse_customize_define(codec);
19531 alc_fix_pll_init(codec, 0x20, 0x04, 15);
19533 coef = alc_read_coef_idx(codec, 0);
19534 if (coef == 0x8020 || coef == 0x8011)
19535 alc_codec_rename(codec, "ALC661");
19536 else if (coef & (1 << 14) &&
19537 codec->bus->pci->subsystem_vendor == 0x1025 &&
19538 spec->cdefine.platform_type == 1)
19539 alc_codec_rename(codec, "ALC272X");
19540 else if (coef == 0x4011)
19541 alc_codec_rename(codec, "ALC656");
19543 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
19544 alc662_models,
19545 alc662_cfg_tbl);
19546 if (board_config < 0) {
19547 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
19548 codec->chip_name);
19549 board_config = ALC662_AUTO;
19552 if (board_config == ALC662_AUTO) {
19553 alc_pick_fixup(codec, alc662_fixup_models,
19554 alc662_fixup_tbl, alc662_fixups);
19555 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
19556 /* automatic parse from the BIOS config */
19557 err = alc662_parse_auto_config(codec);
19558 if (err < 0) {
19559 alc_free(codec);
19560 return err;
19561 } else if (!err) {
19562 printk(KERN_INFO
19563 "hda_codec: Cannot set up configuration "
19564 "from BIOS. Using base mode...\n");
19565 board_config = ALC662_3ST_2ch_DIG;
19569 if (has_cdefine_beep(codec)) {
19570 err = snd_hda_attach_beep_device(codec, 0x1);
19571 if (err < 0) {
19572 alc_free(codec);
19573 return err;
19577 if (board_config != ALC662_AUTO)
19578 setup_preset(codec, &alc662_presets[board_config]);
19580 spec->stream_analog_playback = &alc662_pcm_analog_playback;
19581 spec->stream_analog_capture = &alc662_pcm_analog_capture;
19583 spec->stream_digital_playback = &alc662_pcm_digital_playback;
19584 spec->stream_digital_capture = &alc662_pcm_digital_capture;
19586 if (!spec->adc_nids) {
19587 spec->adc_nids = alc662_adc_nids;
19588 spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
19590 if (!spec->capsrc_nids)
19591 spec->capsrc_nids = alc662_capsrc_nids;
19593 if (!spec->cap_mixer)
19594 set_capture_mixer(codec);
19596 if (has_cdefine_beep(codec)) {
19597 switch (codec->vendor_id) {
19598 case 0x10ec0662:
19599 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
19600 break;
19601 case 0x10ec0272:
19602 case 0x10ec0663:
19603 case 0x10ec0665:
19604 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
19605 break;
19606 case 0x10ec0273:
19607 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
19608 break;
19611 spec->vmaster_nid = 0x02;
19613 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
19615 codec->patch_ops = alc_patch_ops;
19616 if (board_config == ALC662_AUTO)
19617 spec->init_hook = alc662_auto_init;
19618 spec->shutup = alc_eapd_shutup;
19620 alc_init_jacks(codec);
19622 #ifdef CONFIG_SND_HDA_POWER_SAVE
19623 if (!spec->loopback.amplist)
19624 spec->loopback.amplist = alc662_loopbacks;
19625 #endif
19627 return 0;
19630 static int patch_alc888(struct hda_codec *codec)
19632 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
19633 kfree(codec->chip_name);
19634 if (codec->vendor_id == 0x10ec0887)
19635 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
19636 else
19637 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
19638 if (!codec->chip_name) {
19639 alc_free(codec);
19640 return -ENOMEM;
19642 return patch_alc662(codec);
19644 return patch_alc882(codec);
19647 static int patch_alc899(struct hda_codec *codec)
19649 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
19650 kfree(codec->chip_name);
19651 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
19653 return patch_alc882(codec);
19657 * ALC680 support
19659 #define ALC680_DIGIN_NID ALC880_DIGIN_NID
19660 #define ALC680_DIGOUT_NID ALC880_DIGOUT_NID
19661 #define alc680_modes alc260_modes
19663 static const hda_nid_t alc680_dac_nids[3] = {
19664 /* Lout1, Lout2, hp */
19665 0x02, 0x03, 0x04
19668 static const hda_nid_t alc680_adc_nids[3] = {
19669 /* ADC0-2 */
19670 /* DMIC, MIC, Line-in*/
19671 0x07, 0x08, 0x09
19675 * Analog capture ADC cgange
19677 static void alc680_rec_autoswitch(struct hda_codec *codec)
19679 struct alc_spec *spec = codec->spec;
19680 struct auto_pin_cfg *cfg = &spec->autocfg;
19681 int pin_found = 0;
19682 int type_found = AUTO_PIN_LAST;
19683 hda_nid_t nid;
19684 int i;
19686 for (i = 0; i < cfg->num_inputs; i++) {
19687 nid = cfg->inputs[i].pin;
19688 if (!is_jack_detectable(codec, nid))
19689 continue;
19690 if (snd_hda_jack_detect(codec, nid)) {
19691 if (cfg->inputs[i].type < type_found) {
19692 type_found = cfg->inputs[i].type;
19693 pin_found = nid;
19698 nid = 0x07;
19699 if (pin_found)
19700 snd_hda_get_connections(codec, pin_found, &nid, 1);
19702 if (nid != spec->cur_adc)
19703 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
19704 spec->cur_adc = nid;
19705 snd_hda_codec_setup_stream(codec, nid, spec->cur_adc_stream_tag, 0,
19706 spec->cur_adc_format);
19709 static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
19710 struct hda_codec *codec,
19711 unsigned int stream_tag,
19712 unsigned int format,
19713 struct snd_pcm_substream *substream)
19715 struct alc_spec *spec = codec->spec;
19717 spec->cur_adc = 0x07;
19718 spec->cur_adc_stream_tag = stream_tag;
19719 spec->cur_adc_format = format;
19721 alc680_rec_autoswitch(codec);
19722 return 0;
19725 static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
19726 struct hda_codec *codec,
19727 struct snd_pcm_substream *substream)
19729 snd_hda_codec_cleanup_stream(codec, 0x07);
19730 snd_hda_codec_cleanup_stream(codec, 0x08);
19731 snd_hda_codec_cleanup_stream(codec, 0x09);
19732 return 0;
19735 static const struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
19736 .substreams = 1, /* can be overridden */
19737 .channels_min = 2,
19738 .channels_max = 2,
19739 /* NID is set in alc_build_pcms */
19740 .ops = {
19741 .prepare = alc680_capture_pcm_prepare,
19742 .cleanup = alc680_capture_pcm_cleanup
19746 static const struct snd_kcontrol_new alc680_base_mixer[] = {
19747 /* output mixer control */
19748 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
19749 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
19750 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT),
19751 HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT),
19752 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x12, 0, HDA_INPUT),
19753 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
19754 HDA_CODEC_VOLUME("Line In Boost Volume", 0x19, 0, HDA_INPUT),
19758 static const struct hda_bind_ctls alc680_bind_cap_vol = {
19759 .ops = &snd_hda_bind_vol,
19760 .values = {
19761 HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
19762 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
19763 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
19768 static const struct hda_bind_ctls alc680_bind_cap_switch = {
19769 .ops = &snd_hda_bind_sw,
19770 .values = {
19771 HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
19772 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
19773 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
19778 static const struct snd_kcontrol_new alc680_master_capture_mixer[] = {
19779 HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol),
19780 HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch),
19781 { } /* end */
19785 * generic initialization of ADC, input mixers and output mixers
19787 static const struct hda_verb alc680_init_verbs[] = {
19788 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
19789 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
19790 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
19792 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
19793 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
19794 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
19795 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
19796 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
19797 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
19799 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19800 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19801 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19802 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19803 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19805 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
19806 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
19807 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
19812 /* toggle speaker-output according to the hp-jack state */
19813 static void alc680_base_setup(struct hda_codec *codec)
19815 struct alc_spec *spec = codec->spec;
19817 spec->autocfg.hp_pins[0] = 0x16;
19818 spec->autocfg.speaker_pins[0] = 0x14;
19819 spec->autocfg.speaker_pins[1] = 0x15;
19820 spec->autocfg.num_inputs = 2;
19821 spec->autocfg.inputs[0].pin = 0x18;
19822 spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
19823 spec->autocfg.inputs[1].pin = 0x19;
19824 spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
19825 spec->automute = 1;
19826 spec->automute_mode = ALC_AUTOMUTE_AMP;
19829 static void alc680_unsol_event(struct hda_codec *codec,
19830 unsigned int res)
19832 if ((res >> 26) == ALC880_HP_EVENT)
19833 alc_hp_automute(codec);
19834 if ((res >> 26) == ALC880_MIC_EVENT)
19835 alc680_rec_autoswitch(codec);
19838 static void alc680_inithook(struct hda_codec *codec)
19840 alc_hp_automute(codec);
19841 alc680_rec_autoswitch(codec);
19844 /* create input playback/capture controls for the given pin */
19845 static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
19846 const char *ctlname, int idx)
19848 hda_nid_t dac;
19849 int err;
19851 switch (nid) {
19852 case 0x14:
19853 dac = 0x02;
19854 break;
19855 case 0x15:
19856 dac = 0x03;
19857 break;
19858 case 0x16:
19859 dac = 0x04;
19860 break;
19861 default:
19862 return 0;
19864 if (spec->multiout.dac_nids[0] != dac &&
19865 spec->multiout.dac_nids[1] != dac) {
19866 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
19867 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
19868 HDA_OUTPUT));
19869 if (err < 0)
19870 return err;
19872 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
19873 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
19875 if (err < 0)
19876 return err;
19877 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
19880 return 0;
19883 /* add playback controls from the parsed DAC table */
19884 static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec,
19885 const struct auto_pin_cfg *cfg)
19887 hda_nid_t nid;
19888 int err;
19890 spec->multiout.dac_nids = spec->private_dac_nids;
19892 nid = cfg->line_out_pins[0];
19893 if (nid) {
19894 const char *name;
19895 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
19896 name = "Speaker";
19897 else
19898 name = "Front";
19899 err = alc680_new_analog_output(spec, nid, name, 0);
19900 if (err < 0)
19901 return err;
19904 nid = cfg->speaker_pins[0];
19905 if (nid) {
19906 err = alc680_new_analog_output(spec, nid, "Speaker", 0);
19907 if (err < 0)
19908 return err;
19910 nid = cfg->hp_pins[0];
19911 if (nid) {
19912 err = alc680_new_analog_output(spec, nid, "Headphone", 0);
19913 if (err < 0)
19914 return err;
19917 return 0;
19920 static void alc680_auto_set_output_and_unmute(struct hda_codec *codec,
19921 hda_nid_t nid, int pin_type)
19923 alc_set_pin_output(codec, nid, pin_type);
19926 static void alc680_auto_init_multi_out(struct hda_codec *codec)
19928 struct alc_spec *spec = codec->spec;
19929 hda_nid_t nid = spec->autocfg.line_out_pins[0];
19930 if (nid) {
19931 int pin_type = get_pin_type(spec->autocfg.line_out_type);
19932 alc680_auto_set_output_and_unmute(codec, nid, pin_type);
19936 static void alc680_auto_init_hp_out(struct hda_codec *codec)
19938 struct alc_spec *spec = codec->spec;
19939 hda_nid_t pin;
19941 pin = spec->autocfg.hp_pins[0];
19942 if (pin)
19943 alc680_auto_set_output_and_unmute(codec, pin, PIN_HP);
19944 pin = spec->autocfg.speaker_pins[0];
19945 if (pin)
19946 alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT);
19949 /* pcm configuration: identical with ALC880 */
19950 #define alc680_pcm_analog_playback alc880_pcm_analog_playback
19951 #define alc680_pcm_analog_capture alc880_pcm_analog_capture
19952 #define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
19953 #define alc680_pcm_digital_playback alc880_pcm_digital_playback
19954 #define alc680_pcm_digital_capture alc880_pcm_digital_capture
19957 * BIOS auto configuration
19959 static int alc680_parse_auto_config(struct hda_codec *codec)
19961 struct alc_spec *spec = codec->spec;
19962 int err;
19963 static const hda_nid_t alc680_ignore[] = { 0 };
19965 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
19966 alc680_ignore);
19967 if (err < 0)
19968 return err;
19970 if (!spec->autocfg.line_outs) {
19971 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
19972 spec->multiout.max_channels = 2;
19973 spec->no_analog = 1;
19974 goto dig_only;
19976 return 0; /* can't find valid BIOS pin config */
19978 err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg);
19979 if (err < 0)
19980 return err;
19982 spec->multiout.max_channels = 2;
19984 dig_only:
19985 /* digital only support output */
19986 alc_auto_parse_digital(codec);
19987 if (spec->kctls.list)
19988 add_mixer(spec, spec->kctls.list);
19990 add_verb(spec, alc680_init_verbs);
19992 err = alc_auto_add_mic_boost(codec);
19993 if (err < 0)
19994 return err;
19996 return 1;
19999 #define alc680_auto_init_analog_input alc882_auto_init_analog_input
20001 /* init callback for auto-configuration model -- overriding the default init */
20002 static void alc680_auto_init(struct hda_codec *codec)
20004 struct alc_spec *spec = codec->spec;
20005 alc680_auto_init_multi_out(codec);
20006 alc680_auto_init_hp_out(codec);
20007 alc680_auto_init_analog_input(codec);
20008 alc_auto_init_digital(codec);
20009 if (spec->unsol_event)
20010 alc_inithook(codec);
20014 * configuration and preset
20016 static const char * const alc680_models[ALC680_MODEL_LAST] = {
20017 [ALC680_BASE] = "base",
20018 [ALC680_AUTO] = "auto",
20021 static const struct snd_pci_quirk alc680_cfg_tbl[] = {
20022 SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
20026 static const struct alc_config_preset alc680_presets[] = {
20027 [ALC680_BASE] = {
20028 .mixers = { alc680_base_mixer },
20029 .cap_mixer = alc680_master_capture_mixer,
20030 .init_verbs = { alc680_init_verbs },
20031 .num_dacs = ARRAY_SIZE(alc680_dac_nids),
20032 .dac_nids = alc680_dac_nids,
20033 .dig_out_nid = ALC680_DIGOUT_NID,
20034 .num_channel_mode = ARRAY_SIZE(alc680_modes),
20035 .channel_mode = alc680_modes,
20036 .unsol_event = alc680_unsol_event,
20037 .setup = alc680_base_setup,
20038 .init_hook = alc680_inithook,
20043 static int patch_alc680(struct hda_codec *codec)
20045 struct alc_spec *spec;
20046 int board_config;
20047 int err;
20049 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
20050 if (spec == NULL)
20051 return -ENOMEM;
20053 codec->spec = spec;
20055 board_config = snd_hda_check_board_config(codec, ALC680_MODEL_LAST,
20056 alc680_models,
20057 alc680_cfg_tbl);
20059 if (board_config < 0 || board_config >= ALC680_MODEL_LAST) {
20060 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
20061 codec->chip_name);
20062 board_config = ALC680_AUTO;
20065 if (board_config == ALC680_AUTO) {
20066 /* automatic parse from the BIOS config */
20067 err = alc680_parse_auto_config(codec);
20068 if (err < 0) {
20069 alc_free(codec);
20070 return err;
20071 } else if (!err) {
20072 printk(KERN_INFO
20073 "hda_codec: Cannot set up configuration "
20074 "from BIOS. Using base mode...\n");
20075 board_config = ALC680_BASE;
20079 if (board_config != ALC680_AUTO)
20080 setup_preset(codec, &alc680_presets[board_config]);
20082 spec->stream_analog_playback = &alc680_pcm_analog_playback;
20083 spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
20084 spec->stream_digital_playback = &alc680_pcm_digital_playback;
20085 spec->stream_digital_capture = &alc680_pcm_digital_capture;
20087 if (!spec->adc_nids) {
20088 spec->adc_nids = alc680_adc_nids;
20089 spec->num_adc_nids = ARRAY_SIZE(alc680_adc_nids);
20092 if (!spec->cap_mixer)
20093 set_capture_mixer(codec);
20095 spec->vmaster_nid = 0x02;
20097 codec->patch_ops = alc_patch_ops;
20098 if (board_config == ALC680_AUTO)
20099 spec->init_hook = alc680_auto_init;
20101 return 0;
20105 * patch entries
20107 static const struct hda_codec_preset snd_hda_preset_realtek[] = {
20108 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
20109 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
20110 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
20111 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
20112 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
20113 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
20114 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
20115 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
20116 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
20117 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
20118 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
20119 .patch = patch_alc861 },
20120 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
20121 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
20122 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
20123 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
20124 .patch = patch_alc882 },
20125 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
20126 .patch = patch_alc662 },
20127 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
20128 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
20129 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
20130 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
20131 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
20132 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
20133 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
20134 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
20135 .patch = patch_alc882 },
20136 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
20137 .patch = patch_alc882 },
20138 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
20139 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
20140 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
20141 .patch = patch_alc882 },
20142 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
20143 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
20144 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
20145 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
20146 {} /* terminator */
20149 MODULE_ALIAS("snd-hda-codec-id:10ec*");
20151 MODULE_LICENSE("GPL");
20152 MODULE_DESCRIPTION("Realtek HD-audio codec");
20154 static struct hda_codec_preset_list realtek_list = {
20155 .preset = snd_hda_preset_realtek,
20156 .owner = THIS_MODULE,
20159 static int __init patch_realtek_init(void)
20161 return snd_hda_add_codec_preset(&realtek_list);
20164 static void __exit patch_realtek_exit(void)
20166 snd_hda_delete_codec_preset(&realtek_list);
20169 module_init(patch_realtek_init)
20170 module_exit(patch_realtek_exit)