ALSA: hda - Fix silent output on ASUS A6Rp
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / sound / pci / hda / patch_realtek.c
blobe683017b9437813d8984d56084200fd08e6a502e
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];
512 if (!imux->num_items)
513 return 0;
515 type = get_wcaps_type(get_wcaps(codec, nid));
516 if (type == AC_WID_AUD_MIX) {
517 /* Matrix-mixer style (e.g. ALC882) */
518 unsigned int *cur_val = &spec->cur_mux[adc_idx];
519 unsigned int i, idx;
521 idx = ucontrol->value.enumerated.item[0];
522 if (idx >= imux->num_items)
523 idx = imux->num_items - 1;
524 if (*cur_val == idx)
525 return 0;
526 for (i = 0; i < imux->num_items; i++) {
527 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
528 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
529 imux->items[i].index,
530 HDA_AMP_MUTE, v);
532 *cur_val = idx;
533 return 1;
534 } else {
535 /* MUX style (e.g. ALC880) */
536 return snd_hda_input_mux_put(codec, imux, ucontrol, nid,
537 &spec->cur_mux[adc_idx]);
542 * channel mode setting
544 static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
545 struct snd_ctl_elem_info *uinfo)
547 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
548 struct alc_spec *spec = codec->spec;
549 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
550 spec->num_channel_mode);
553 static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
554 struct snd_ctl_elem_value *ucontrol)
556 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
557 struct alc_spec *spec = codec->spec;
558 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
559 spec->num_channel_mode,
560 spec->ext_channel_count);
563 static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
564 struct snd_ctl_elem_value *ucontrol)
566 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
567 struct alc_spec *spec = codec->spec;
568 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
569 spec->num_channel_mode,
570 &spec->ext_channel_count);
571 if (err >= 0 && !spec->const_channel_count) {
572 spec->multiout.max_channels = spec->ext_channel_count;
573 if (spec->need_dac_fix)
574 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
576 return err;
580 * Control the mode of pin widget settings via the mixer. "pc" is used
581 * instead of "%" to avoid consequences of accidentally treating the % as
582 * being part of a format specifier. Maximum allowed length of a value is
583 * 63 characters plus NULL terminator.
585 * Note: some retasking pin complexes seem to ignore requests for input
586 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
587 * are requested. Therefore order this list so that this behaviour will not
588 * cause problems when mixer clients move through the enum sequentially.
589 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
590 * March 2006.
592 static const char * const alc_pin_mode_names[] = {
593 "Mic 50pc bias", "Mic 80pc bias",
594 "Line in", "Line out", "Headphone out",
596 static const unsigned char alc_pin_mode_values[] = {
597 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
599 /* The control can present all 5 options, or it can limit the options based
600 * in the pin being assumed to be exclusively an input or an output pin. In
601 * addition, "input" pins may or may not process the mic bias option
602 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
603 * accept requests for bias as of chip versions up to March 2006) and/or
604 * wiring in the computer.
606 #define ALC_PIN_DIR_IN 0x00
607 #define ALC_PIN_DIR_OUT 0x01
608 #define ALC_PIN_DIR_INOUT 0x02
609 #define ALC_PIN_DIR_IN_NOMICBIAS 0x03
610 #define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
612 /* Info about the pin modes supported by the different pin direction modes.
613 * For each direction the minimum and maximum values are given.
615 static const signed char alc_pin_mode_dir_info[5][2] = {
616 { 0, 2 }, /* ALC_PIN_DIR_IN */
617 { 3, 4 }, /* ALC_PIN_DIR_OUT */
618 { 0, 4 }, /* ALC_PIN_DIR_INOUT */
619 { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */
620 { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */
622 #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
623 #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
624 #define alc_pin_mode_n_items(_dir) \
625 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
627 static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
628 struct snd_ctl_elem_info *uinfo)
630 unsigned int item_num = uinfo->value.enumerated.item;
631 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
633 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
634 uinfo->count = 1;
635 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
637 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
638 item_num = alc_pin_mode_min(dir);
639 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
640 return 0;
643 static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
644 struct snd_ctl_elem_value *ucontrol)
646 unsigned int i;
647 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
648 hda_nid_t nid = kcontrol->private_value & 0xffff;
649 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
650 long *valp = ucontrol->value.integer.value;
651 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
652 AC_VERB_GET_PIN_WIDGET_CONTROL,
653 0x00);
655 /* Find enumerated value for current pinctl setting */
656 i = alc_pin_mode_min(dir);
657 while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
658 i++;
659 *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
660 return 0;
663 static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
664 struct snd_ctl_elem_value *ucontrol)
666 signed int change;
667 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
668 hda_nid_t nid = kcontrol->private_value & 0xffff;
669 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
670 long val = *ucontrol->value.integer.value;
671 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
672 AC_VERB_GET_PIN_WIDGET_CONTROL,
673 0x00);
675 if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
676 val = alc_pin_mode_min(dir);
678 change = pinctl != alc_pin_mode_values[val];
679 if (change) {
680 /* Set pin mode to that requested */
681 snd_hda_codec_write_cache(codec, nid, 0,
682 AC_VERB_SET_PIN_WIDGET_CONTROL,
683 alc_pin_mode_values[val]);
685 /* Also enable the retasking pin's input/output as required
686 * for the requested pin mode. Enum values of 2 or less are
687 * input modes.
689 * Dynamically switching the input/output buffers probably
690 * reduces noise slightly (particularly on input) so we'll
691 * do it. However, having both input and output buffers
692 * enabled simultaneously doesn't seem to be problematic if
693 * this turns out to be necessary in the future.
695 if (val <= 2) {
696 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
697 HDA_AMP_MUTE, HDA_AMP_MUTE);
698 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
699 HDA_AMP_MUTE, 0);
700 } else {
701 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
702 HDA_AMP_MUTE, HDA_AMP_MUTE);
703 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
704 HDA_AMP_MUTE, 0);
707 return change;
710 #define ALC_PIN_MODE(xname, nid, dir) \
711 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
712 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
713 .info = alc_pin_mode_info, \
714 .get = alc_pin_mode_get, \
715 .put = alc_pin_mode_put, \
716 .private_value = nid | (dir<<16) }
718 /* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged
719 * together using a mask with more than one bit set. This control is
720 * currently used only by the ALC260 test model. At this stage they are not
721 * needed for any "production" models.
723 #ifdef CONFIG_SND_DEBUG
724 #define alc_gpio_data_info snd_ctl_boolean_mono_info
726 static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
727 struct snd_ctl_elem_value *ucontrol)
729 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
730 hda_nid_t nid = kcontrol->private_value & 0xffff;
731 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
732 long *valp = ucontrol->value.integer.value;
733 unsigned int val = snd_hda_codec_read(codec, nid, 0,
734 AC_VERB_GET_GPIO_DATA, 0x00);
736 *valp = (val & mask) != 0;
737 return 0;
739 static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
740 struct snd_ctl_elem_value *ucontrol)
742 signed int change;
743 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
744 hda_nid_t nid = kcontrol->private_value & 0xffff;
745 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
746 long val = *ucontrol->value.integer.value;
747 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
748 AC_VERB_GET_GPIO_DATA,
749 0x00);
751 /* Set/unset the masked GPIO bit(s) as needed */
752 change = (val == 0 ? 0 : mask) != (gpio_data & mask);
753 if (val == 0)
754 gpio_data &= ~mask;
755 else
756 gpio_data |= mask;
757 snd_hda_codec_write_cache(codec, nid, 0,
758 AC_VERB_SET_GPIO_DATA, gpio_data);
760 return change;
762 #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
763 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
764 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
765 .info = alc_gpio_data_info, \
766 .get = alc_gpio_data_get, \
767 .put = alc_gpio_data_put, \
768 .private_value = nid | (mask<<16) }
769 #endif /* CONFIG_SND_DEBUG */
771 /* A switch control to allow the enabling of the digital IO pins on the
772 * ALC260. This is incredibly simplistic; the intention of this control is
773 * to provide something in the test model allowing digital outputs to be
774 * identified if present. If models are found which can utilise these
775 * outputs a more complete mixer control can be devised for those models if
776 * necessary.
778 #ifdef CONFIG_SND_DEBUG
779 #define alc_spdif_ctrl_info snd_ctl_boolean_mono_info
781 static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
782 struct snd_ctl_elem_value *ucontrol)
784 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
785 hda_nid_t nid = kcontrol->private_value & 0xffff;
786 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
787 long *valp = ucontrol->value.integer.value;
788 unsigned int val = snd_hda_codec_read(codec, nid, 0,
789 AC_VERB_GET_DIGI_CONVERT_1, 0x00);
791 *valp = (val & mask) != 0;
792 return 0;
794 static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
795 struct snd_ctl_elem_value *ucontrol)
797 signed int change;
798 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
799 hda_nid_t nid = kcontrol->private_value & 0xffff;
800 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
801 long val = *ucontrol->value.integer.value;
802 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
803 AC_VERB_GET_DIGI_CONVERT_1,
804 0x00);
806 /* Set/unset the masked control bit(s) as needed */
807 change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
808 if (val==0)
809 ctrl_data &= ~mask;
810 else
811 ctrl_data |= mask;
812 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
813 ctrl_data);
815 return change;
817 #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
818 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
819 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
820 .info = alc_spdif_ctrl_info, \
821 .get = alc_spdif_ctrl_get, \
822 .put = alc_spdif_ctrl_put, \
823 .private_value = nid | (mask<<16) }
824 #endif /* CONFIG_SND_DEBUG */
826 /* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
827 * Again, this is only used in the ALC26x test models to help identify when
828 * the EAPD line must be asserted for features to work.
830 #ifdef CONFIG_SND_DEBUG
831 #define alc_eapd_ctrl_info snd_ctl_boolean_mono_info
833 static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
834 struct snd_ctl_elem_value *ucontrol)
836 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
837 hda_nid_t nid = kcontrol->private_value & 0xffff;
838 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
839 long *valp = ucontrol->value.integer.value;
840 unsigned int val = snd_hda_codec_read(codec, nid, 0,
841 AC_VERB_GET_EAPD_BTLENABLE, 0x00);
843 *valp = (val & mask) != 0;
844 return 0;
847 static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
848 struct snd_ctl_elem_value *ucontrol)
850 int change;
851 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
852 hda_nid_t nid = kcontrol->private_value & 0xffff;
853 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
854 long val = *ucontrol->value.integer.value;
855 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
856 AC_VERB_GET_EAPD_BTLENABLE,
857 0x00);
859 /* Set/unset the masked control bit(s) as needed */
860 change = (!val ? 0 : mask) != (ctrl_data & mask);
861 if (!val)
862 ctrl_data &= ~mask;
863 else
864 ctrl_data |= mask;
865 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
866 ctrl_data);
868 return change;
871 #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
872 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
873 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
874 .info = alc_eapd_ctrl_info, \
875 .get = alc_eapd_ctrl_get, \
876 .put = alc_eapd_ctrl_put, \
877 .private_value = nid | (mask<<16) }
878 #endif /* CONFIG_SND_DEBUG */
881 * set up the input pin config (depending on the given auto-pin type)
883 static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
884 int auto_pin_type)
886 unsigned int val = PIN_IN;
888 if (auto_pin_type == AUTO_PIN_MIC) {
889 unsigned int pincap;
890 unsigned int oldval;
891 oldval = snd_hda_codec_read(codec, nid, 0,
892 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
893 pincap = snd_hda_query_pin_caps(codec, nid);
894 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
895 /* if the default pin setup is vref50, we give it priority */
896 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
897 val = PIN_VREF80;
898 else if (pincap & AC_PINCAP_VREF_50)
899 val = PIN_VREF50;
900 else if (pincap & AC_PINCAP_VREF_100)
901 val = PIN_VREF100;
902 else if (pincap & AC_PINCAP_VREF_GRD)
903 val = PIN_VREFGRD;
905 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
908 static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec)
910 struct alc_spec *spec = codec->spec;
911 struct auto_pin_cfg *cfg = &spec->autocfg;
913 if (!cfg->line_outs) {
914 while (cfg->line_outs < AUTO_CFG_MAX_OUTS &&
915 cfg->line_out_pins[cfg->line_outs])
916 cfg->line_outs++;
918 if (!cfg->speaker_outs) {
919 while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS &&
920 cfg->speaker_pins[cfg->speaker_outs])
921 cfg->speaker_outs++;
923 if (!cfg->hp_outs) {
924 while (cfg->hp_outs < AUTO_CFG_MAX_OUTS &&
925 cfg->hp_pins[cfg->hp_outs])
926 cfg->hp_outs++;
932 static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
934 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
935 return;
936 spec->mixers[spec->num_mixers++] = mix;
939 static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
941 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
942 return;
943 spec->init_verbs[spec->num_init_verbs++] = verb;
947 * set up from the preset table
949 static void setup_preset(struct hda_codec *codec,
950 const struct alc_config_preset *preset)
952 struct alc_spec *spec = codec->spec;
953 int i;
955 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
956 add_mixer(spec, preset->mixers[i]);
957 spec->cap_mixer = preset->cap_mixer;
958 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
959 i++)
960 add_verb(spec, preset->init_verbs[i]);
962 spec->channel_mode = preset->channel_mode;
963 spec->num_channel_mode = preset->num_channel_mode;
964 spec->need_dac_fix = preset->need_dac_fix;
965 spec->const_channel_count = preset->const_channel_count;
967 if (preset->const_channel_count)
968 spec->multiout.max_channels = preset->const_channel_count;
969 else
970 spec->multiout.max_channels = spec->channel_mode[0].channels;
971 spec->ext_channel_count = spec->channel_mode[0].channels;
973 spec->multiout.num_dacs = preset->num_dacs;
974 spec->multiout.dac_nids = preset->dac_nids;
975 spec->multiout.dig_out_nid = preset->dig_out_nid;
976 spec->multiout.slave_dig_outs = preset->slave_dig_outs;
977 spec->multiout.hp_nid = preset->hp_nid;
979 spec->num_mux_defs = preset->num_mux_defs;
980 if (!spec->num_mux_defs)
981 spec->num_mux_defs = 1;
982 spec->input_mux = preset->input_mux;
984 spec->num_adc_nids = preset->num_adc_nids;
985 spec->adc_nids = preset->adc_nids;
986 spec->capsrc_nids = preset->capsrc_nids;
987 spec->dig_in_nid = preset->dig_in_nid;
989 spec->unsol_event = preset->unsol_event;
990 spec->init_hook = preset->init_hook;
991 #ifdef CONFIG_SND_HDA_POWER_SAVE
992 spec->power_hook = preset->power_hook;
993 spec->loopback.amplist = preset->loopbacks;
994 #endif
996 if (preset->setup)
997 preset->setup(codec);
999 alc_fixup_autocfg_pin_nums(codec);
1002 /* Enable GPIO mask and set output */
1003 static const struct hda_verb alc_gpio1_init_verbs[] = {
1004 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
1005 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
1006 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
1010 static const struct hda_verb alc_gpio2_init_verbs[] = {
1011 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
1012 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
1013 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
1017 static const struct hda_verb alc_gpio3_init_verbs[] = {
1018 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
1019 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
1020 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
1025 * Fix hardware PLL issue
1026 * On some codecs, the analog PLL gating control must be off while
1027 * the default value is 1.
1029 static void alc_fix_pll(struct hda_codec *codec)
1031 struct alc_spec *spec = codec->spec;
1032 unsigned int val;
1034 if (!spec->pll_nid)
1035 return;
1036 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
1037 spec->pll_coef_idx);
1038 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
1039 AC_VERB_GET_PROC_COEF, 0);
1040 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
1041 spec->pll_coef_idx);
1042 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
1043 val & ~(1 << spec->pll_coef_bit));
1046 static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
1047 unsigned int coef_idx, unsigned int coef_bit)
1049 struct alc_spec *spec = codec->spec;
1050 spec->pll_nid = nid;
1051 spec->pll_coef_idx = coef_idx;
1052 spec->pll_coef_bit = coef_bit;
1053 alc_fix_pll(codec);
1056 static int alc_init_jacks(struct hda_codec *codec)
1058 #ifdef CONFIG_SND_HDA_INPUT_JACK
1059 struct alc_spec *spec = codec->spec;
1060 int err;
1061 unsigned int hp_nid = spec->autocfg.hp_pins[0];
1062 unsigned int mic_nid = spec->ext_mic.pin;
1063 unsigned int dock_nid = spec->dock_mic.pin;
1065 if (hp_nid) {
1066 err = snd_hda_input_jack_add(codec, hp_nid,
1067 SND_JACK_HEADPHONE, NULL);
1068 if (err < 0)
1069 return err;
1070 snd_hda_input_jack_report(codec, hp_nid);
1073 if (mic_nid) {
1074 err = snd_hda_input_jack_add(codec, mic_nid,
1075 SND_JACK_MICROPHONE, NULL);
1076 if (err < 0)
1077 return err;
1078 snd_hda_input_jack_report(codec, mic_nid);
1080 if (dock_nid) {
1081 err = snd_hda_input_jack_add(codec, dock_nid,
1082 SND_JACK_MICROPHONE, NULL);
1083 if (err < 0)
1084 return err;
1085 snd_hda_input_jack_report(codec, dock_nid);
1087 #endif /* CONFIG_SND_HDA_INPUT_JACK */
1088 return 0;
1091 static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
1093 int i, present = 0;
1095 for (i = 0; i < num_pins; i++) {
1096 hda_nid_t nid = pins[i];
1097 if (!nid)
1098 break;
1099 snd_hda_input_jack_report(codec, nid);
1100 present |= snd_hda_jack_detect(codec, nid);
1102 return present;
1105 static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
1106 bool mute, bool hp_out)
1108 struct alc_spec *spec = codec->spec;
1109 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
1110 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
1111 int i;
1113 for (i = 0; i < num_pins; i++) {
1114 hda_nid_t nid = pins[i];
1115 if (!nid)
1116 break;
1117 switch (spec->automute_mode) {
1118 case ALC_AUTOMUTE_PIN:
1119 snd_hda_codec_write(codec, nid, 0,
1120 AC_VERB_SET_PIN_WIDGET_CONTROL,
1121 pin_bits);
1122 break;
1123 case ALC_AUTOMUTE_AMP:
1124 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1125 HDA_AMP_MUTE, mute_bits);
1126 break;
1127 case ALC_AUTOMUTE_MIXER:
1128 nid = spec->automute_mixer_nid[i];
1129 if (!nid)
1130 break;
1131 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
1132 HDA_AMP_MUTE, mute_bits);
1133 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
1134 HDA_AMP_MUTE, mute_bits);
1135 break;
1140 /* Toggle internal speakers muting */
1141 static void update_speakers(struct hda_codec *codec)
1143 struct alc_spec *spec = codec->spec;
1144 int on;
1146 /* Control HP pins/amps depending on master_mute state;
1147 * in general, HP pins/amps control should be enabled in all cases,
1148 * but currently set only for master_mute, just to be safe
1150 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
1151 spec->autocfg.hp_pins, spec->master_mute, true);
1153 if (!spec->automute)
1154 on = 0;
1155 else
1156 on = spec->jack_present | spec->line_jack_present;
1157 on |= spec->master_mute;
1158 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
1159 spec->autocfg.speaker_pins, on, false);
1161 /* toggle line-out mutes if needed, too */
1162 /* if LO is a copy of either HP or Speaker, don't need to handle it */
1163 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
1164 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
1165 return;
1166 if (!spec->automute || (spec->automute_hp_lo && !spec->automute_lines))
1167 on = 0;
1168 else
1169 on = spec->jack_present;
1170 on |= spec->master_mute;
1171 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
1172 spec->autocfg.line_out_pins, on, false);
1175 static void alc_hp_automute(struct hda_codec *codec)
1177 struct alc_spec *spec = codec->spec;
1179 if (!spec->automute)
1180 return;
1181 spec->jack_present =
1182 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
1183 spec->autocfg.hp_pins);
1184 update_speakers(codec);
1187 static void alc_line_automute(struct hda_codec *codec)
1189 struct alc_spec *spec = codec->spec;
1191 if (!spec->automute || !spec->detect_line)
1192 return;
1193 spec->line_jack_present =
1194 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
1195 spec->autocfg.line_out_pins);
1196 update_speakers(codec);
1199 static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
1200 hda_nid_t nid)
1202 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
1203 int i, nums;
1205 nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
1206 for (i = 0; i < nums; i++)
1207 if (conn[i] == nid)
1208 return i;
1209 return -1;
1212 /* switch the current ADC according to the jack state */
1213 static void alc_dual_mic_adc_auto_switch(struct hda_codec *codec)
1215 struct alc_spec *spec = codec->spec;
1216 unsigned int present;
1217 hda_nid_t new_adc;
1219 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
1220 if (present)
1221 spec->cur_adc_idx = 1;
1222 else
1223 spec->cur_adc_idx = 0;
1224 new_adc = spec->adc_nids[spec->cur_adc_idx];
1225 if (spec->cur_adc && spec->cur_adc != new_adc) {
1226 /* stream is running, let's swap the current ADC */
1227 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
1228 spec->cur_adc = new_adc;
1229 snd_hda_codec_setup_stream(codec, new_adc,
1230 spec->cur_adc_stream_tag, 0,
1231 spec->cur_adc_format);
1235 static void alc_mic_automute(struct hda_codec *codec)
1237 struct alc_spec *spec = codec->spec;
1238 struct alc_mic_route *dead1, *dead2, *alive;
1239 unsigned int present, type;
1240 hda_nid_t cap_nid;
1242 if (!spec->auto_mic)
1243 return;
1244 if (!spec->int_mic.pin || !spec->ext_mic.pin)
1245 return;
1246 if (snd_BUG_ON(!spec->adc_nids))
1247 return;
1249 if (spec->dual_adc_switch) {
1250 alc_dual_mic_adc_auto_switch(codec);
1251 return;
1254 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
1256 alive = &spec->int_mic;
1257 dead1 = &spec->ext_mic;
1258 dead2 = &spec->dock_mic;
1260 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
1261 if (present) {
1262 alive = &spec->ext_mic;
1263 dead1 = &spec->int_mic;
1264 dead2 = &spec->dock_mic;
1266 if (!present && spec->dock_mic.pin > 0) {
1267 present = snd_hda_jack_detect(codec, spec->dock_mic.pin);
1268 if (present) {
1269 alive = &spec->dock_mic;
1270 dead1 = &spec->int_mic;
1271 dead2 = &spec->ext_mic;
1273 snd_hda_input_jack_report(codec, spec->dock_mic.pin);
1276 type = get_wcaps_type(get_wcaps(codec, cap_nid));
1277 if (type == AC_WID_AUD_MIX) {
1278 /* Matrix-mixer style (e.g. ALC882) */
1279 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1280 alive->mux_idx,
1281 HDA_AMP_MUTE, 0);
1282 if (dead1->pin > 0)
1283 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1284 dead1->mux_idx,
1285 HDA_AMP_MUTE, HDA_AMP_MUTE);
1286 if (dead2->pin > 0)
1287 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1288 dead2->mux_idx,
1289 HDA_AMP_MUTE, HDA_AMP_MUTE);
1290 } else {
1291 /* MUX style (e.g. ALC880) */
1292 snd_hda_codec_write_cache(codec, cap_nid, 0,
1293 AC_VERB_SET_CONNECT_SEL,
1294 alive->mux_idx);
1296 snd_hda_input_jack_report(codec, spec->ext_mic.pin);
1298 /* FIXME: analog mixer */
1301 /* unsolicited event for HP jack sensing */
1302 static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
1304 if (codec->vendor_id == 0x10ec0880)
1305 res >>= 28;
1306 else
1307 res >>= 26;
1308 switch (res) {
1309 case ALC880_HP_EVENT:
1310 alc_hp_automute(codec);
1311 break;
1312 case ALC880_FRONT_EVENT:
1313 alc_line_automute(codec);
1314 break;
1315 case ALC880_MIC_EVENT:
1316 alc_mic_automute(codec);
1317 break;
1321 static void alc_inithook(struct hda_codec *codec)
1323 alc_hp_automute(codec);
1324 alc_line_automute(codec);
1325 alc_mic_automute(codec);
1328 /* additional initialization for ALC888 variants */
1329 static void alc888_coef_init(struct hda_codec *codec)
1331 unsigned int tmp;
1333 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
1334 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
1335 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1336 if ((tmp & 0xf0) == 0x20)
1337 /* alc888S-VC */
1338 snd_hda_codec_read(codec, 0x20, 0,
1339 AC_VERB_SET_PROC_COEF, 0x830);
1340 else
1341 /* alc888-VB */
1342 snd_hda_codec_read(codec, 0x20, 0,
1343 AC_VERB_SET_PROC_COEF, 0x3030);
1346 static void alc889_coef_init(struct hda_codec *codec)
1348 unsigned int tmp;
1350 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1351 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
1352 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1353 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
1356 /* turn on/off EAPD control (only if available) */
1357 static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
1359 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
1360 return;
1361 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
1362 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
1363 on ? 2 : 0);
1366 /* turn on/off EAPD controls of the codec */
1367 static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
1369 /* We currently only handle front, HP */
1370 switch (codec->vendor_id) {
1371 case 0x10ec0260:
1372 set_eapd(codec, 0x0f, on);
1373 set_eapd(codec, 0x10, on);
1374 break;
1375 case 0x10ec0262:
1376 case 0x10ec0267:
1377 case 0x10ec0268:
1378 case 0x10ec0269:
1379 case 0x10ec0270:
1380 case 0x10ec0272:
1381 case 0x10ec0660:
1382 case 0x10ec0662:
1383 case 0x10ec0663:
1384 case 0x10ec0665:
1385 case 0x10ec0862:
1386 case 0x10ec0889:
1387 case 0x10ec0892:
1388 set_eapd(codec, 0x14, on);
1389 set_eapd(codec, 0x15, on);
1390 break;
1394 /* generic shutup callback;
1395 * just turning off EPAD and a little pause for avoiding pop-noise
1397 static void alc_eapd_shutup(struct hda_codec *codec)
1399 alc_auto_setup_eapd(codec, false);
1400 msleep(200);
1403 static void alc_auto_init_amp(struct hda_codec *codec, int type)
1405 unsigned int tmp;
1407 switch (type) {
1408 case ALC_INIT_GPIO1:
1409 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
1410 break;
1411 case ALC_INIT_GPIO2:
1412 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
1413 break;
1414 case ALC_INIT_GPIO3:
1415 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
1416 break;
1417 case ALC_INIT_DEFAULT:
1418 alc_auto_setup_eapd(codec, true);
1419 switch (codec->vendor_id) {
1420 case 0x10ec0260:
1421 snd_hda_codec_write(codec, 0x1a, 0,
1422 AC_VERB_SET_COEF_INDEX, 7);
1423 tmp = snd_hda_codec_read(codec, 0x1a, 0,
1424 AC_VERB_GET_PROC_COEF, 0);
1425 snd_hda_codec_write(codec, 0x1a, 0,
1426 AC_VERB_SET_COEF_INDEX, 7);
1427 snd_hda_codec_write(codec, 0x1a, 0,
1428 AC_VERB_SET_PROC_COEF,
1429 tmp | 0x2010);
1430 break;
1431 case 0x10ec0262:
1432 case 0x10ec0880:
1433 case 0x10ec0882:
1434 case 0x10ec0883:
1435 case 0x10ec0885:
1436 case 0x10ec0887:
1437 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
1438 alc889_coef_init(codec);
1439 break;
1440 case 0x10ec0888:
1441 alc888_coef_init(codec);
1442 break;
1443 #if 0 /* XXX: This may cause the silent output on speaker on some machines */
1444 case 0x10ec0267:
1445 case 0x10ec0268:
1446 snd_hda_codec_write(codec, 0x20, 0,
1447 AC_VERB_SET_COEF_INDEX, 7);
1448 tmp = snd_hda_codec_read(codec, 0x20, 0,
1449 AC_VERB_GET_PROC_COEF, 0);
1450 snd_hda_codec_write(codec, 0x20, 0,
1451 AC_VERB_SET_COEF_INDEX, 7);
1452 snd_hda_codec_write(codec, 0x20, 0,
1453 AC_VERB_SET_PROC_COEF,
1454 tmp | 0x3000);
1455 break;
1456 #endif /* XXX */
1458 break;
1462 static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
1463 struct snd_ctl_elem_info *uinfo)
1465 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1466 struct alc_spec *spec = codec->spec;
1467 static const char * const texts2[] = {
1468 "Disabled", "Enabled"
1470 static const char * const texts3[] = {
1471 "Disabled", "Speaker Only", "Line-Out+Speaker"
1473 const char * const *texts;
1475 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1476 uinfo->count = 1;
1477 if (spec->automute_hp_lo) {
1478 uinfo->value.enumerated.items = 3;
1479 texts = texts3;
1480 } else {
1481 uinfo->value.enumerated.items = 2;
1482 texts = texts2;
1484 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1485 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1486 strcpy(uinfo->value.enumerated.name,
1487 texts[uinfo->value.enumerated.item]);
1488 return 0;
1491 static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
1492 struct snd_ctl_elem_value *ucontrol)
1494 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1495 struct alc_spec *spec = codec->spec;
1496 unsigned int val;
1497 if (!spec->automute)
1498 val = 0;
1499 else if (!spec->automute_hp_lo || !spec->automute_lines)
1500 val = 1;
1501 else
1502 val = 2;
1503 ucontrol->value.enumerated.item[0] = val;
1504 return 0;
1507 static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
1508 struct snd_ctl_elem_value *ucontrol)
1510 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1511 struct alc_spec *spec = codec->spec;
1513 switch (ucontrol->value.enumerated.item[0]) {
1514 case 0:
1515 if (!spec->automute)
1516 return 0;
1517 spec->automute = 0;
1518 break;
1519 case 1:
1520 if (spec->automute &&
1521 (!spec->automute_hp_lo || !spec->automute_lines))
1522 return 0;
1523 spec->automute = 1;
1524 spec->automute_lines = 0;
1525 break;
1526 case 2:
1527 if (!spec->automute_hp_lo)
1528 return -EINVAL;
1529 if (spec->automute && spec->automute_lines)
1530 return 0;
1531 spec->automute = 1;
1532 spec->automute_lines = 1;
1533 break;
1534 default:
1535 return -EINVAL;
1537 update_speakers(codec);
1538 return 1;
1541 static const struct snd_kcontrol_new alc_automute_mode_enum = {
1542 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1543 .name = "Auto-Mute Mode",
1544 .info = alc_automute_mode_info,
1545 .get = alc_automute_mode_get,
1546 .put = alc_automute_mode_put,
1549 static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec);
1551 static int alc_add_automute_mode_enum(struct hda_codec *codec)
1553 struct alc_spec *spec = codec->spec;
1554 struct snd_kcontrol_new *knew;
1556 knew = alc_kcontrol_new(spec);
1557 if (!knew)
1558 return -ENOMEM;
1559 *knew = alc_automute_mode_enum;
1560 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
1561 if (!knew->name)
1562 return -ENOMEM;
1563 return 0;
1566 static void alc_init_auto_hp(struct hda_codec *codec)
1568 struct alc_spec *spec = codec->spec;
1569 struct auto_pin_cfg *cfg = &spec->autocfg;
1570 int present = 0;
1571 int i;
1573 if (cfg->hp_pins[0])
1574 present++;
1575 if (cfg->line_out_pins[0])
1576 present++;
1577 if (cfg->speaker_pins[0])
1578 present++;
1579 if (present < 2) /* need two different output types */
1580 return;
1581 if (present == 3)
1582 spec->automute_hp_lo = 1; /* both HP and LO automute */
1584 if (!cfg->speaker_pins[0] &&
1585 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1586 memcpy(cfg->speaker_pins, cfg->line_out_pins,
1587 sizeof(cfg->speaker_pins));
1588 cfg->speaker_outs = cfg->line_outs;
1591 if (!cfg->hp_pins[0] &&
1592 cfg->line_out_type == AUTO_PIN_HP_OUT) {
1593 memcpy(cfg->hp_pins, cfg->line_out_pins,
1594 sizeof(cfg->hp_pins));
1595 cfg->hp_outs = cfg->line_outs;
1598 for (i = 0; i < cfg->hp_outs; i++) {
1599 hda_nid_t nid = cfg->hp_pins[i];
1600 if (!is_jack_detectable(codec, nid))
1601 continue;
1602 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
1603 nid);
1604 snd_hda_codec_write_cache(codec, nid, 0,
1605 AC_VERB_SET_UNSOLICITED_ENABLE,
1606 AC_USRSP_EN | ALC880_HP_EVENT);
1607 spec->automute = 1;
1608 spec->automute_mode = ALC_AUTOMUTE_PIN;
1610 if (spec->automute && cfg->line_out_pins[0] &&
1611 cfg->speaker_pins[0] &&
1612 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
1613 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
1614 for (i = 0; i < cfg->line_outs; i++) {
1615 hda_nid_t nid = cfg->line_out_pins[i];
1616 if (!is_jack_detectable(codec, nid))
1617 continue;
1618 snd_printdd("realtek: Enable Line-Out auto-muting "
1619 "on NID 0x%x\n", nid);
1620 snd_hda_codec_write_cache(codec, nid, 0,
1621 AC_VERB_SET_UNSOLICITED_ENABLE,
1622 AC_USRSP_EN | ALC880_FRONT_EVENT);
1623 spec->detect_line = 1;
1625 spec->automute_lines = spec->detect_line;
1628 if (spec->automute) {
1629 /* create a control for automute mode */
1630 alc_add_automute_mode_enum(codec);
1631 spec->unsol_event = alc_sku_unsol_event;
1635 static void alc_init_auto_mic(struct hda_codec *codec)
1637 struct alc_spec *spec = codec->spec;
1638 struct auto_pin_cfg *cfg = &spec->autocfg;
1639 hda_nid_t fixed, ext, dock;
1640 int i;
1642 fixed = ext = dock = 0;
1643 for (i = 0; i < cfg->num_inputs; i++) {
1644 hda_nid_t nid = cfg->inputs[i].pin;
1645 unsigned int defcfg;
1646 defcfg = snd_hda_codec_get_pincfg(codec, nid);
1647 switch (snd_hda_get_input_pin_attr(defcfg)) {
1648 case INPUT_PIN_ATTR_INT:
1649 if (fixed)
1650 return; /* already occupied */
1651 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1652 return; /* invalid type */
1653 fixed = nid;
1654 break;
1655 case INPUT_PIN_ATTR_UNUSED:
1656 return; /* invalid entry */
1657 case INPUT_PIN_ATTR_DOCK:
1658 if (dock)
1659 return; /* already occupied */
1660 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1661 return; /* invalid type */
1662 dock = nid;
1663 break;
1664 default:
1665 if (ext)
1666 return; /* already occupied */
1667 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1668 return; /* invalid type */
1669 ext = nid;
1670 break;
1673 if (!ext && dock) {
1674 ext = dock;
1675 dock = 0;
1677 if (!ext || !fixed)
1678 return;
1679 if (!is_jack_detectable(codec, ext))
1680 return; /* no unsol support */
1681 if (dock && !is_jack_detectable(codec, dock))
1682 return; /* no unsol support */
1683 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1684 ext, fixed, dock);
1685 spec->ext_mic.pin = ext;
1686 spec->dock_mic.pin = dock;
1687 spec->int_mic.pin = fixed;
1688 spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1689 spec->dock_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1690 spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1691 spec->auto_mic = 1;
1692 snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0,
1693 AC_VERB_SET_UNSOLICITED_ENABLE,
1694 AC_USRSP_EN | ALC880_MIC_EVENT);
1695 spec->unsol_event = alc_sku_unsol_event;
1698 /* Could be any non-zero and even value. When used as fixup, tells
1699 * the driver to ignore any present sku defines.
1701 #define ALC_FIXUP_SKU_IGNORE (2)
1703 static int alc_auto_parse_customize_define(struct hda_codec *codec)
1705 unsigned int ass, tmp, i;
1706 unsigned nid = 0;
1707 struct alc_spec *spec = codec->spec;
1709 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1711 if (spec->cdefine.fixup) {
1712 ass = spec->cdefine.sku_cfg;
1713 if (ass == ALC_FIXUP_SKU_IGNORE)
1714 return -1;
1715 goto do_sku;
1718 ass = codec->subsystem_id & 0xffff;
1719 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
1720 goto do_sku;
1722 nid = 0x1d;
1723 if (codec->vendor_id == 0x10ec0260)
1724 nid = 0x17;
1725 ass = snd_hda_codec_get_pincfg(codec, nid);
1727 if (!(ass & 1)) {
1728 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1729 codec->chip_name, ass);
1730 return -1;
1733 /* check sum */
1734 tmp = 0;
1735 for (i = 1; i < 16; i++) {
1736 if ((ass >> i) & 1)
1737 tmp++;
1739 if (((ass >> 16) & 0xf) != tmp)
1740 return -1;
1742 spec->cdefine.port_connectivity = ass >> 30;
1743 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1744 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1745 spec->cdefine.customization = ass >> 8;
1746 do_sku:
1747 spec->cdefine.sku_cfg = ass;
1748 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1749 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1750 spec->cdefine.swap = (ass & 0x2) >> 1;
1751 spec->cdefine.override = ass & 0x1;
1753 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1754 nid, spec->cdefine.sku_cfg);
1755 snd_printd("SKU: port_connectivity=0x%x\n",
1756 spec->cdefine.port_connectivity);
1757 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1758 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1759 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1760 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1761 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1762 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1763 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1765 return 0;
1768 /* check subsystem ID and set up device-specific initialization;
1769 * return 1 if initialized, 0 if invalid SSID
1771 /* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1772 * 31 ~ 16 : Manufacture ID
1773 * 15 ~ 8 : SKU ID
1774 * 7 ~ 0 : Assembly ID
1775 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1777 static int alc_subsystem_id(struct hda_codec *codec,
1778 hda_nid_t porta, hda_nid_t porte,
1779 hda_nid_t portd, hda_nid_t porti)
1781 unsigned int ass, tmp, i;
1782 unsigned nid;
1783 struct alc_spec *spec = codec->spec;
1785 if (spec->cdefine.fixup) {
1786 ass = spec->cdefine.sku_cfg;
1787 if (ass == ALC_FIXUP_SKU_IGNORE)
1788 return 0;
1789 goto do_sku;
1792 ass = codec->subsystem_id & 0xffff;
1793 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1794 goto do_sku;
1796 /* invalid SSID, check the special NID pin defcfg instead */
1798 * 31~30 : port connectivity
1799 * 29~21 : reserve
1800 * 20 : PCBEEP input
1801 * 19~16 : Check sum (15:1)
1802 * 15~1 : Custom
1803 * 0 : override
1805 nid = 0x1d;
1806 if (codec->vendor_id == 0x10ec0260)
1807 nid = 0x17;
1808 ass = snd_hda_codec_get_pincfg(codec, nid);
1809 snd_printd("realtek: No valid SSID, "
1810 "checking pincfg 0x%08x for NID 0x%x\n",
1811 ass, nid);
1812 if (!(ass & 1))
1813 return 0;
1814 if ((ass >> 30) != 1) /* no physical connection */
1815 return 0;
1817 /* check sum */
1818 tmp = 0;
1819 for (i = 1; i < 16; i++) {
1820 if ((ass >> i) & 1)
1821 tmp++;
1823 if (((ass >> 16) & 0xf) != tmp)
1824 return 0;
1825 do_sku:
1826 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1827 ass & 0xffff, codec->vendor_id);
1829 * 0 : override
1830 * 1 : Swap Jack
1831 * 2 : 0 --> Desktop, 1 --> Laptop
1832 * 3~5 : External Amplifier control
1833 * 7~6 : Reserved
1835 tmp = (ass & 0x38) >> 3; /* external Amp control */
1836 switch (tmp) {
1837 case 1:
1838 spec->init_amp = ALC_INIT_GPIO1;
1839 break;
1840 case 3:
1841 spec->init_amp = ALC_INIT_GPIO2;
1842 break;
1843 case 7:
1844 spec->init_amp = ALC_INIT_GPIO3;
1845 break;
1846 case 5:
1847 default:
1848 spec->init_amp = ALC_INIT_DEFAULT;
1849 break;
1852 /* is laptop or Desktop and enable the function "Mute internal speaker
1853 * when the external headphone out jack is plugged"
1855 if (!(ass & 0x8000))
1856 return 1;
1858 * 10~8 : Jack location
1859 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1860 * 14~13: Resvered
1861 * 15 : 1 --> enable the function "Mute internal speaker
1862 * when the external headphone out jack is plugged"
1864 if (!spec->autocfg.hp_pins[0] &&
1865 !(spec->autocfg.line_out_pins[0] &&
1866 spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
1867 hda_nid_t nid;
1868 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1869 if (tmp == 0)
1870 nid = porta;
1871 else if (tmp == 1)
1872 nid = porte;
1873 else if (tmp == 2)
1874 nid = portd;
1875 else if (tmp == 3)
1876 nid = porti;
1877 else
1878 return 1;
1879 for (i = 0; i < spec->autocfg.line_outs; i++)
1880 if (spec->autocfg.line_out_pins[i] == nid)
1881 return 1;
1882 spec->autocfg.hp_pins[0] = nid;
1884 return 1;
1887 static void alc_ssid_check(struct hda_codec *codec,
1888 hda_nid_t porta, hda_nid_t porte,
1889 hda_nid_t portd, hda_nid_t porti)
1891 if (!alc_subsystem_id(codec, porta, porte, portd, porti)) {
1892 struct alc_spec *spec = codec->spec;
1893 snd_printd("realtek: "
1894 "Enable default setup for auto mode as fallback\n");
1895 spec->init_amp = ALC_INIT_DEFAULT;
1898 alc_init_auto_hp(codec);
1899 alc_init_auto_mic(codec);
1903 * Fix-up pin default configurations and add default verbs
1906 struct alc_pincfg {
1907 hda_nid_t nid;
1908 u32 val;
1911 struct alc_model_fixup {
1912 const int id;
1913 const char *name;
1916 struct alc_fixup {
1917 int type;
1918 bool chained;
1919 int chain_id;
1920 union {
1921 unsigned int sku;
1922 const struct alc_pincfg *pins;
1923 const struct hda_verb *verbs;
1924 void (*func)(struct hda_codec *codec,
1925 const struct alc_fixup *fix,
1926 int action);
1927 } v;
1930 enum {
1931 ALC_FIXUP_INVALID,
1932 ALC_FIXUP_SKU,
1933 ALC_FIXUP_PINS,
1934 ALC_FIXUP_VERBS,
1935 ALC_FIXUP_FUNC,
1938 enum {
1939 ALC_FIXUP_ACT_PRE_PROBE,
1940 ALC_FIXUP_ACT_PROBE,
1941 ALC_FIXUP_ACT_INIT,
1944 static void alc_apply_fixup(struct hda_codec *codec, int action)
1946 struct alc_spec *spec = codec->spec;
1947 int id = spec->fixup_id;
1948 #ifdef CONFIG_SND_DEBUG_VERBOSE
1949 const char *modelname = spec->fixup_name;
1950 #endif
1951 int depth = 0;
1953 if (!spec->fixup_list)
1954 return;
1956 while (id >= 0) {
1957 const struct alc_fixup *fix = spec->fixup_list + id;
1958 const struct alc_pincfg *cfg;
1960 switch (fix->type) {
1961 case ALC_FIXUP_SKU:
1962 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1963 break;;
1964 snd_printdd(KERN_INFO "hda_codec: %s: "
1965 "Apply sku override for %s\n",
1966 codec->chip_name, modelname);
1967 spec->cdefine.sku_cfg = fix->v.sku;
1968 spec->cdefine.fixup = 1;
1969 break;
1970 case ALC_FIXUP_PINS:
1971 cfg = fix->v.pins;
1972 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1973 break;
1974 snd_printdd(KERN_INFO "hda_codec: %s: "
1975 "Apply pincfg for %s\n",
1976 codec->chip_name, modelname);
1977 for (; cfg->nid; cfg++)
1978 snd_hda_codec_set_pincfg(codec, cfg->nid,
1979 cfg->val);
1980 break;
1981 case ALC_FIXUP_VERBS:
1982 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1983 break;
1984 snd_printdd(KERN_INFO "hda_codec: %s: "
1985 "Apply fix-verbs for %s\n",
1986 codec->chip_name, modelname);
1987 add_verb(codec->spec, fix->v.verbs);
1988 break;
1989 case ALC_FIXUP_FUNC:
1990 if (!fix->v.func)
1991 break;
1992 snd_printdd(KERN_INFO "hda_codec: %s: "
1993 "Apply fix-func for %s\n",
1994 codec->chip_name, modelname);
1995 fix->v.func(codec, fix, action);
1996 break;
1997 default:
1998 snd_printk(KERN_ERR "hda_codec: %s: "
1999 "Invalid fixup type %d\n",
2000 codec->chip_name, fix->type);
2001 break;
2003 if (!fix->chained)
2004 break;
2005 if (++depth > 10)
2006 break;
2007 id = fix->chain_id;
2011 static void alc_pick_fixup(struct hda_codec *codec,
2012 const struct alc_model_fixup *models,
2013 const struct snd_pci_quirk *quirk,
2014 const struct alc_fixup *fixlist)
2016 struct alc_spec *spec = codec->spec;
2017 int id = -1;
2018 const char *name = NULL;
2020 if (codec->modelname && models) {
2021 while (models->name) {
2022 if (!strcmp(codec->modelname, models->name)) {
2023 id = models->id;
2024 name = models->name;
2025 break;
2027 models++;
2030 if (id < 0) {
2031 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
2032 if (quirk) {
2033 id = quirk->value;
2034 #ifdef CONFIG_SND_DEBUG_VERBOSE
2035 name = quirk->name;
2036 #endif
2040 spec->fixup_id = id;
2041 if (id >= 0) {
2042 spec->fixup_list = fixlist;
2043 spec->fixup_name = name;
2047 static int alc_read_coef_idx(struct hda_codec *codec,
2048 unsigned int coef_idx)
2050 unsigned int val;
2051 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
2052 coef_idx);
2053 val = snd_hda_codec_read(codec, 0x20, 0,
2054 AC_VERB_GET_PROC_COEF, 0);
2055 return val;
2058 static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
2059 unsigned int coef_val)
2061 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
2062 coef_idx);
2063 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
2064 coef_val);
2067 /* set right pin controls for digital I/O */
2068 static void alc_auto_init_digital(struct hda_codec *codec)
2070 struct alc_spec *spec = codec->spec;
2071 int i;
2072 hda_nid_t pin;
2074 for (i = 0; i < spec->autocfg.dig_outs; i++) {
2075 pin = spec->autocfg.dig_out_pins[i];
2076 if (pin) {
2077 snd_hda_codec_write(codec, pin, 0,
2078 AC_VERB_SET_PIN_WIDGET_CONTROL,
2079 PIN_OUT);
2082 pin = spec->autocfg.dig_in_pin;
2083 if (pin)
2084 snd_hda_codec_write(codec, pin, 0,
2085 AC_VERB_SET_PIN_WIDGET_CONTROL,
2086 PIN_IN);
2089 /* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
2090 static void alc_auto_parse_digital(struct hda_codec *codec)
2092 struct alc_spec *spec = codec->spec;
2093 int i, err, nums;
2094 hda_nid_t dig_nid;
2096 /* support multiple SPDIFs; the secondary is set up as a slave */
2097 nums = 0;
2098 for (i = 0; i < spec->autocfg.dig_outs; i++) {
2099 err = snd_hda_get_connections(codec,
2100 spec->autocfg.dig_out_pins[i],
2101 &dig_nid, 1);
2102 if (err <= 0)
2103 continue;
2104 if (!nums) {
2105 spec->multiout.dig_out_nid = dig_nid;
2106 spec->dig_out_type = spec->autocfg.dig_out_type[0];
2107 } else {
2108 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
2109 if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
2110 break;
2111 spec->slave_dig_outs[nums - 1] = dig_nid;
2113 nums++;
2116 if (spec->autocfg.dig_in_pin) {
2117 dig_nid = codec->start_nid;
2118 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
2119 unsigned int wcaps = get_wcaps(codec, dig_nid);
2120 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
2121 continue;
2122 if (!(wcaps & AC_WCAP_DIGITAL))
2123 continue;
2124 if (!(wcaps & AC_WCAP_CONN_LIST))
2125 continue;
2126 err = get_connection_index(codec, dig_nid,
2127 spec->autocfg.dig_in_pin);
2128 if (err >= 0) {
2129 spec->dig_in_nid = dig_nid;
2130 break;
2137 * ALC888
2141 * 2ch mode
2143 static const struct hda_verb alc888_4ST_ch2_intel_init[] = {
2144 /* Mic-in jack as mic in */
2145 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2146 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2147 /* Line-in jack as Line in */
2148 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2149 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2150 /* Line-Out as Front */
2151 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
2152 { } /* end */
2156 * 4ch mode
2158 static const struct hda_verb alc888_4ST_ch4_intel_init[] = {
2159 /* Mic-in jack as mic in */
2160 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2161 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2162 /* Line-in jack as Surround */
2163 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2164 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2165 /* Line-Out as Front */
2166 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
2167 { } /* end */
2171 * 6ch mode
2173 static const struct hda_verb alc888_4ST_ch6_intel_init[] = {
2174 /* Mic-in jack as CLFE */
2175 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2176 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2177 /* Line-in jack as Surround */
2178 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2179 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2180 /* Line-Out as CLFE (workaround because Mic-in is not loud enough) */
2181 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
2182 { } /* end */
2186 * 8ch mode
2188 static const struct hda_verb alc888_4ST_ch8_intel_init[] = {
2189 /* Mic-in jack as CLFE */
2190 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2191 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2192 /* Line-in jack as Surround */
2193 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2194 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2195 /* Line-Out as Side */
2196 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
2197 { } /* end */
2200 static const struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
2201 { 2, alc888_4ST_ch2_intel_init },
2202 { 4, alc888_4ST_ch4_intel_init },
2203 { 6, alc888_4ST_ch6_intel_init },
2204 { 8, alc888_4ST_ch8_intel_init },
2208 * ALC888 Fujitsu Siemens Amillo xa3530
2211 static const struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
2212 /* Front Mic: set to PIN_IN (empty by default) */
2213 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2214 /* Connect Internal HP to Front */
2215 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2216 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2217 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
2218 /* Connect Bass HP to Front */
2219 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2220 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2221 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2222 /* Connect Line-Out side jack (SPDIF) to Side */
2223 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2224 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2225 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
2226 /* Connect Mic jack to CLFE */
2227 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2228 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2229 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
2230 /* Connect Line-in jack to Surround */
2231 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2232 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2233 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
2234 /* Connect HP out jack to Front */
2235 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2236 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2237 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
2238 /* Enable unsolicited event for HP jack and Line-out jack */
2239 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2240 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2244 static void alc889_automute_setup(struct hda_codec *codec)
2246 struct alc_spec *spec = codec->spec;
2248 spec->autocfg.hp_pins[0] = 0x15;
2249 spec->autocfg.speaker_pins[0] = 0x14;
2250 spec->autocfg.speaker_pins[1] = 0x16;
2251 spec->autocfg.speaker_pins[2] = 0x17;
2252 spec->autocfg.speaker_pins[3] = 0x19;
2253 spec->autocfg.speaker_pins[4] = 0x1a;
2254 spec->automute = 1;
2255 spec->automute_mode = ALC_AUTOMUTE_AMP;
2258 static void alc889_intel_init_hook(struct hda_codec *codec)
2260 alc889_coef_init(codec);
2261 alc_hp_automute(codec);
2264 static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
2266 struct alc_spec *spec = codec->spec;
2268 spec->autocfg.hp_pins[0] = 0x17; /* line-out */
2269 spec->autocfg.hp_pins[1] = 0x1b; /* hp */
2270 spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
2271 spec->autocfg.speaker_pins[1] = 0x15; /* bass */
2272 spec->automute = 1;
2273 spec->automute_mode = ALC_AUTOMUTE_AMP;
2277 * ALC888 Acer Aspire 4930G model
2280 static const struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
2281 /* Front Mic: set to PIN_IN (empty by default) */
2282 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2283 /* Unselect Front Mic by default in input mixer 3 */
2284 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
2285 /* Enable unsolicited event for HP jack */
2286 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2287 /* Connect Internal HP to front */
2288 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2289 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2290 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
2291 /* Connect HP out to front */
2292 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2293 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2294 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2295 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
2300 * ALC888 Acer Aspire 6530G model
2303 static const struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
2304 /* Route to built-in subwoofer as well as speakers */
2305 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2306 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2307 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2308 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2309 /* Bias voltage on for external mic port */
2310 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
2311 /* Front Mic: set to PIN_IN (empty by default) */
2312 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2313 /* Unselect Front Mic by default in input mixer 3 */
2314 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
2315 /* Enable unsolicited event for HP jack */
2316 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2317 /* Enable speaker output */
2318 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2319 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2320 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
2321 /* Enable headphone output */
2322 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
2323 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2324 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2325 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
2330 *ALC888 Acer Aspire 7730G model
2333 static const struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
2334 /* Bias voltage on for external mic port */
2335 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
2336 /* Front Mic: set to PIN_IN (empty by default) */
2337 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2338 /* Unselect Front Mic by default in input mixer 3 */
2339 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
2340 /* Enable unsolicited event for HP jack */
2341 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2342 /* Enable speaker output */
2343 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2344 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2345 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
2346 /* Enable headphone output */
2347 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
2348 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2349 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2350 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
2351 /*Enable internal subwoofer */
2352 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2353 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2354 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
2355 {0x17, AC_VERB_SET_EAPD_BTLENABLE, 2},
2360 * ALC889 Acer Aspire 8930G model
2363 static const struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
2364 /* Front Mic: set to PIN_IN (empty by default) */
2365 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2366 /* Unselect Front Mic by default in input mixer 3 */
2367 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
2368 /* Enable unsolicited event for HP jack */
2369 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
2370 /* Connect Internal Front to Front */
2371 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2372 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2373 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
2374 /* Connect Internal Rear to Rear */
2375 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2376 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2377 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
2378 /* Connect Internal CLFE to CLFE */
2379 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2380 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2381 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
2382 /* Connect HP out to Front */
2383 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
2384 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2385 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2386 /* Enable all DACs */
2387 /* DAC DISABLE/MUTE 1? */
2388 /* setting bits 1-5 disables DAC nids 0x02-0x06 apparently. Init=0x38 */
2389 {0x20, AC_VERB_SET_COEF_INDEX, 0x03},
2390 {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
2391 /* DAC DISABLE/MUTE 2? */
2392 /* some bit here disables the other DACs. Init=0x4900 */
2393 {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
2394 {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
2395 /* DMIC fix
2396 * This laptop has a stereo digital microphone. The mics are only 1cm apart
2397 * which makes the stereo useless. However, either the mic or the ALC889
2398 * makes the signal become a difference/sum signal instead of standard
2399 * stereo, which is annoying. So instead we flip this bit which makes the
2400 * codec replicate the sum signal to both channels, turning it into a
2401 * normal mono mic.
2403 /* DMIC_CONTROL? Init value = 0x0001 */
2404 {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
2405 {0x20, AC_VERB_SET_PROC_COEF, 0x0003},
2409 static const struct hda_input_mux alc888_2_capture_sources[2] = {
2410 /* Front mic only available on one ADC */
2412 .num_items = 4,
2413 .items = {
2414 { "Mic", 0x0 },
2415 { "Line", 0x2 },
2416 { "CD", 0x4 },
2417 { "Front Mic", 0xb },
2421 .num_items = 3,
2422 .items = {
2423 { "Mic", 0x0 },
2424 { "Line", 0x2 },
2425 { "CD", 0x4 },
2430 static const struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
2431 /* Interal mic only available on one ADC */
2433 .num_items = 5,
2434 .items = {
2435 { "Mic", 0x0 },
2436 { "Line In", 0x2 },
2437 { "CD", 0x4 },
2438 { "Input Mix", 0xa },
2439 { "Internal Mic", 0xb },
2443 .num_items = 4,
2444 .items = {
2445 { "Mic", 0x0 },
2446 { "Line In", 0x2 },
2447 { "CD", 0x4 },
2448 { "Input Mix", 0xa },
2453 static const struct hda_input_mux alc889_capture_sources[3] = {
2454 /* Digital mic only available on first "ADC" */
2456 .num_items = 5,
2457 .items = {
2458 { "Mic", 0x0 },
2459 { "Line", 0x2 },
2460 { "CD", 0x4 },
2461 { "Front Mic", 0xb },
2462 { "Input Mix", 0xa },
2466 .num_items = 4,
2467 .items = {
2468 { "Mic", 0x0 },
2469 { "Line", 0x2 },
2470 { "CD", 0x4 },
2471 { "Input Mix", 0xa },
2475 .num_items = 4,
2476 .items = {
2477 { "Mic", 0x0 },
2478 { "Line", 0x2 },
2479 { "CD", 0x4 },
2480 { "Input Mix", 0xa },
2485 static const struct snd_kcontrol_new alc888_base_mixer[] = {
2486 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2487 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2488 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2489 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2490 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
2491 HDA_OUTPUT),
2492 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2493 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2494 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2495 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2496 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
2497 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2498 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2499 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2500 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2501 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2502 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
2503 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2504 { } /* end */
2507 static const struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
2508 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2509 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2510 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2511 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2512 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
2513 HDA_OUTPUT),
2514 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2515 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2516 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2517 HDA_CODEC_VOLUME_MONO("Internal LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT),
2518 HDA_BIND_MUTE_MONO("Internal LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT),
2519 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2520 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2521 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2522 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2523 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2524 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
2525 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2526 { } /* end */
2529 static const struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
2530 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2531 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2532 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2533 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2534 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
2535 HDA_OUTPUT),
2536 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2537 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2538 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2539 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2540 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2541 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2542 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
2543 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2544 { } /* end */
2548 static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
2550 struct alc_spec *spec = codec->spec;
2552 spec->autocfg.hp_pins[0] = 0x15;
2553 spec->autocfg.speaker_pins[0] = 0x14;
2554 spec->autocfg.speaker_pins[1] = 0x16;
2555 spec->autocfg.speaker_pins[2] = 0x17;
2556 spec->automute = 1;
2557 spec->automute_mode = ALC_AUTOMUTE_AMP;
2560 static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
2562 struct alc_spec *spec = codec->spec;
2564 spec->autocfg.hp_pins[0] = 0x15;
2565 spec->autocfg.speaker_pins[0] = 0x14;
2566 spec->autocfg.speaker_pins[1] = 0x16;
2567 spec->autocfg.speaker_pins[2] = 0x17;
2568 spec->automute = 1;
2569 spec->automute_mode = ALC_AUTOMUTE_AMP;
2572 static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
2574 struct alc_spec *spec = codec->spec;
2576 spec->autocfg.hp_pins[0] = 0x15;
2577 spec->autocfg.speaker_pins[0] = 0x14;
2578 spec->autocfg.speaker_pins[1] = 0x16;
2579 spec->autocfg.speaker_pins[2] = 0x17;
2580 spec->automute = 1;
2581 spec->automute_mode = ALC_AUTOMUTE_AMP;
2584 static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
2586 struct alc_spec *spec = codec->spec;
2588 spec->autocfg.hp_pins[0] = 0x15;
2589 spec->autocfg.speaker_pins[0] = 0x14;
2590 spec->autocfg.speaker_pins[1] = 0x16;
2591 spec->autocfg.speaker_pins[2] = 0x1b;
2592 spec->automute = 1;
2593 spec->automute_mode = ALC_AUTOMUTE_AMP;
2597 * ALC880 3-stack model
2599 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
2600 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
2601 * F-Mic = 0x1b, HP = 0x19
2604 static const hda_nid_t alc880_dac_nids[4] = {
2605 /* front, rear, clfe, rear_surr */
2606 0x02, 0x05, 0x04, 0x03
2609 static const hda_nid_t alc880_adc_nids[3] = {
2610 /* ADC0-2 */
2611 0x07, 0x08, 0x09,
2614 /* The datasheet says the node 0x07 is connected from inputs,
2615 * but it shows zero connection in the real implementation on some devices.
2616 * Note: this is a 915GAV bug, fixed on 915GLV
2618 static const hda_nid_t alc880_adc_nids_alt[2] = {
2619 /* ADC1-2 */
2620 0x08, 0x09,
2623 #define ALC880_DIGOUT_NID 0x06
2624 #define ALC880_DIGIN_NID 0x0a
2626 static const struct hda_input_mux alc880_capture_source = {
2627 .num_items = 4,
2628 .items = {
2629 { "Mic", 0x0 },
2630 { "Front Mic", 0x3 },
2631 { "Line", 0x2 },
2632 { "CD", 0x4 },
2636 /* channel source setting (2/6 channel selection for 3-stack) */
2637 /* 2ch mode */
2638 static const struct hda_verb alc880_threestack_ch2_init[] = {
2639 /* set line-in to input, mute it */
2640 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2641 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2642 /* set mic-in to input vref 80%, mute it */
2643 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2644 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2645 { } /* end */
2648 /* 6ch mode */
2649 static const struct hda_verb alc880_threestack_ch6_init[] = {
2650 /* set line-in to output, unmute it */
2651 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2652 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2653 /* set mic-in to output, unmute it */
2654 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2655 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2656 { } /* end */
2659 static const struct hda_channel_mode alc880_threestack_modes[2] = {
2660 { 2, alc880_threestack_ch2_init },
2661 { 6, alc880_threestack_ch6_init },
2664 static const struct snd_kcontrol_new alc880_three_stack_mixer[] = {
2665 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2666 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2667 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2668 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
2669 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2670 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2671 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2672 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2673 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2674 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2675 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2676 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2677 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2678 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2679 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
2680 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
2681 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
2683 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2684 .name = "Channel Mode",
2685 .info = alc_ch_mode_info,
2686 .get = alc_ch_mode_get,
2687 .put = alc_ch_mode_put,
2689 { } /* end */
2692 /* capture mixer elements */
2693 static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
2694 struct snd_ctl_elem_info *uinfo)
2696 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2697 struct alc_spec *spec = codec->spec;
2698 int err;
2700 mutex_lock(&codec->control_mutex);
2701 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
2702 HDA_INPUT);
2703 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
2704 mutex_unlock(&codec->control_mutex);
2705 return err;
2708 static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
2709 unsigned int size, unsigned int __user *tlv)
2711 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2712 struct alc_spec *spec = codec->spec;
2713 int err;
2715 mutex_lock(&codec->control_mutex);
2716 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
2717 HDA_INPUT);
2718 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
2719 mutex_unlock(&codec->control_mutex);
2720 return err;
2723 typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
2724 struct snd_ctl_elem_value *ucontrol);
2726 static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
2727 struct snd_ctl_elem_value *ucontrol,
2728 getput_call_t func, bool check_adc_switch)
2730 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2731 struct alc_spec *spec = codec->spec;
2732 int i, err = 0;
2734 mutex_lock(&codec->control_mutex);
2735 if (check_adc_switch && spec->dual_adc_switch) {
2736 for (i = 0; i < spec->num_adc_nids; i++) {
2737 kcontrol->private_value =
2738 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
2739 3, 0, HDA_INPUT);
2740 err = func(kcontrol, ucontrol);
2741 if (err < 0)
2742 goto error;
2744 } else {
2745 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2746 kcontrol->private_value =
2747 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
2748 3, 0, HDA_INPUT);
2749 err = func(kcontrol, ucontrol);
2751 error:
2752 mutex_unlock(&codec->control_mutex);
2753 return err;
2756 static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
2757 struct snd_ctl_elem_value *ucontrol)
2759 return alc_cap_getput_caller(kcontrol, ucontrol,
2760 snd_hda_mixer_amp_volume_get, false);
2763 static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
2764 struct snd_ctl_elem_value *ucontrol)
2766 return alc_cap_getput_caller(kcontrol, ucontrol,
2767 snd_hda_mixer_amp_volume_put, true);
2770 /* capture mixer elements */
2771 #define alc_cap_sw_info snd_ctl_boolean_stereo_info
2773 static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
2774 struct snd_ctl_elem_value *ucontrol)
2776 return alc_cap_getput_caller(kcontrol, ucontrol,
2777 snd_hda_mixer_amp_switch_get, false);
2780 static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
2781 struct snd_ctl_elem_value *ucontrol)
2783 return alc_cap_getput_caller(kcontrol, ucontrol,
2784 snd_hda_mixer_amp_switch_put, true);
2787 #define _DEFINE_CAPMIX(num) \
2789 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2790 .name = "Capture Switch", \
2791 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
2792 .count = num, \
2793 .info = alc_cap_sw_info, \
2794 .get = alc_cap_sw_get, \
2795 .put = alc_cap_sw_put, \
2796 }, \
2798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2799 .name = "Capture Volume", \
2800 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2801 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
2802 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
2803 .count = num, \
2804 .info = alc_cap_vol_info, \
2805 .get = alc_cap_vol_get, \
2806 .put = alc_cap_vol_put, \
2807 .tlv = { .c = alc_cap_vol_tlv }, \
2810 #define _DEFINE_CAPSRC(num) \
2812 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2813 /* .name = "Capture Source", */ \
2814 .name = "Input Source", \
2815 .count = num, \
2816 .info = alc_mux_enum_info, \
2817 .get = alc_mux_enum_get, \
2818 .put = alc_mux_enum_put, \
2821 #define DEFINE_CAPMIX(num) \
2822 static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
2823 _DEFINE_CAPMIX(num), \
2824 _DEFINE_CAPSRC(num), \
2825 { } /* end */ \
2828 #define DEFINE_CAPMIX_NOSRC(num) \
2829 static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
2830 _DEFINE_CAPMIX(num), \
2831 { } /* end */ \
2834 /* up to three ADCs */
2835 DEFINE_CAPMIX(1);
2836 DEFINE_CAPMIX(2);
2837 DEFINE_CAPMIX(3);
2838 DEFINE_CAPMIX_NOSRC(1);
2839 DEFINE_CAPMIX_NOSRC(2);
2840 DEFINE_CAPMIX_NOSRC(3);
2843 * ALC880 5-stack model
2845 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
2846 * Side = 0x02 (0xd)
2847 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
2848 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
2851 /* additional mixers to alc880_three_stack_mixer */
2852 static const struct snd_kcontrol_new alc880_five_stack_mixer[] = {
2853 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2854 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
2855 { } /* end */
2858 /* channel source setting (6/8 channel selection for 5-stack) */
2859 /* 6ch mode */
2860 static const struct hda_verb alc880_fivestack_ch6_init[] = {
2861 /* set line-in to input, mute it */
2862 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2863 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2864 { } /* end */
2867 /* 8ch mode */
2868 static const struct hda_verb alc880_fivestack_ch8_init[] = {
2869 /* set line-in to output, unmute it */
2870 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2871 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2872 { } /* end */
2875 static const struct hda_channel_mode alc880_fivestack_modes[2] = {
2876 { 6, alc880_fivestack_ch6_init },
2877 { 8, alc880_fivestack_ch8_init },
2882 * ALC880 6-stack model
2884 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
2885 * Side = 0x05 (0x0f)
2886 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
2887 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
2890 static const hda_nid_t alc880_6st_dac_nids[4] = {
2891 /* front, rear, clfe, rear_surr */
2892 0x02, 0x03, 0x04, 0x05
2895 static const struct hda_input_mux alc880_6stack_capture_source = {
2896 .num_items = 4,
2897 .items = {
2898 { "Mic", 0x0 },
2899 { "Front Mic", 0x1 },
2900 { "Line", 0x2 },
2901 { "CD", 0x4 },
2905 /* fixed 8-channels */
2906 static const struct hda_channel_mode alc880_sixstack_modes[1] = {
2907 { 8, NULL },
2910 static const struct snd_kcontrol_new alc880_six_stack_mixer[] = {
2911 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2912 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2913 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2914 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2915 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2916 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2917 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2918 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2919 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2920 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
2921 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2922 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2923 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2924 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2925 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2926 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2927 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2928 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
2930 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2931 .name = "Channel Mode",
2932 .info = alc_ch_mode_info,
2933 .get = alc_ch_mode_get,
2934 .put = alc_ch_mode_put,
2936 { } /* end */
2941 * ALC880 W810 model
2943 * W810 has rear IO for:
2944 * Front (DAC 02)
2945 * Surround (DAC 03)
2946 * Center/LFE (DAC 04)
2947 * Digital out (06)
2949 * The system also has a pair of internal speakers, and a headphone jack.
2950 * These are both connected to Line2 on the codec, hence to DAC 02.
2952 * There is a variable resistor to control the speaker or headphone
2953 * volume. This is a hardware-only device without a software API.
2955 * Plugging headphones in will disable the internal speakers. This is
2956 * implemented in hardware, not via the driver using jack sense. In
2957 * a similar fashion, plugging into the rear socket marked "front" will
2958 * disable both the speakers and headphones.
2960 * For input, there's a microphone jack, and an "audio in" jack.
2961 * These may not do anything useful with this driver yet, because I
2962 * haven't setup any initialization verbs for these yet...
2965 static const hda_nid_t alc880_w810_dac_nids[3] = {
2966 /* front, rear/surround, clfe */
2967 0x02, 0x03, 0x04
2970 /* fixed 6 channels */
2971 static const struct hda_channel_mode alc880_w810_modes[1] = {
2972 { 6, NULL }
2975 /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
2976 static const struct snd_kcontrol_new alc880_w810_base_mixer[] = {
2977 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2978 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2979 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2980 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2981 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2982 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2983 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2984 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2985 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
2986 { } /* end */
2991 * Z710V model
2993 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
2994 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
2995 * Line = 0x1a
2998 static const hda_nid_t alc880_z71v_dac_nids[1] = {
2999 0x02
3001 #define ALC880_Z71V_HP_DAC 0x03
3003 /* fixed 2 channels */
3004 static const struct hda_channel_mode alc880_2_jack_modes[1] = {
3005 { 2, NULL }
3008 static const struct snd_kcontrol_new alc880_z71v_mixer[] = {
3009 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3010 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3011 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3012 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
3013 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3014 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3015 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3016 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3017 { } /* end */
3022 * ALC880 F1734 model
3024 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
3025 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
3028 static const hda_nid_t alc880_f1734_dac_nids[1] = {
3029 0x03
3031 #define ALC880_F1734_HP_DAC 0x02
3033 static const struct snd_kcontrol_new alc880_f1734_mixer[] = {
3034 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3035 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
3036 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3037 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
3038 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3039 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3040 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3041 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3042 { } /* end */
3045 static const struct hda_input_mux alc880_f1734_capture_source = {
3046 .num_items = 2,
3047 .items = {
3048 { "Mic", 0x1 },
3049 { "CD", 0x4 },
3055 * ALC880 ASUS model
3057 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
3058 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
3059 * Mic = 0x18, Line = 0x1a
3062 #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
3063 #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
3065 static const struct snd_kcontrol_new alc880_asus_mixer[] = {
3066 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3067 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3068 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3069 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
3070 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3071 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3072 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3073 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3074 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3075 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3076 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3077 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3078 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3079 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3081 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3082 .name = "Channel Mode",
3083 .info = alc_ch_mode_info,
3084 .get = alc_ch_mode_get,
3085 .put = alc_ch_mode_put,
3087 { } /* end */
3091 * ALC880 ASUS W1V model
3093 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
3094 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
3095 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
3098 /* additional mixers to alc880_asus_mixer */
3099 static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
3100 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
3101 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
3102 { } /* end */
3105 /* TCL S700 */
3106 static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
3107 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3108 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
3109 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
3110 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
3111 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
3112 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
3113 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
3114 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3115 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3116 { } /* end */
3119 /* Uniwill */
3120 static const struct snd_kcontrol_new alc880_uniwill_mixer[] = {
3121 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3122 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
3123 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3124 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
3125 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3126 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3127 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3128 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3129 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3130 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3131 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3132 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3133 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3134 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3135 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3136 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3138 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3139 .name = "Channel Mode",
3140 .info = alc_ch_mode_info,
3141 .get = alc_ch_mode_get,
3142 .put = alc_ch_mode_put,
3144 { } /* end */
3147 static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
3148 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3149 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
3150 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3151 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
3152 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3153 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3154 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3155 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3156 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3157 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3158 { } /* end */
3161 static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
3162 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3163 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
3164 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3165 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
3166 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3167 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3168 { } /* end */
3172 * virtual master controls
3176 * slave controls for virtual master
3178 static const char * const alc_slave_vols[] = {
3179 "Front Playback Volume",
3180 "Surround Playback Volume",
3181 "Center Playback Volume",
3182 "LFE Playback Volume",
3183 "Side Playback Volume",
3184 "Headphone Playback Volume",
3185 "Speaker Playback Volume",
3186 "Mono Playback Volume",
3187 "Line-Out Playback Volume",
3188 NULL,
3191 static const char * const alc_slave_sws[] = {
3192 "Front Playback Switch",
3193 "Surround Playback Switch",
3194 "Center Playback Switch",
3195 "LFE Playback Switch",
3196 "Side Playback Switch",
3197 "Headphone Playback Switch",
3198 "Speaker Playback Switch",
3199 "Mono Playback Switch",
3200 "IEC958 Playback Switch",
3201 "Line-Out Playback Switch",
3202 NULL,
3206 * build control elements
3209 #define NID_MAPPING (-1)
3211 #define SUBDEV_SPEAKER_ (0 << 6)
3212 #define SUBDEV_HP_ (1 << 6)
3213 #define SUBDEV_LINE_ (2 << 6)
3214 #define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
3215 #define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
3216 #define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
3218 static void alc_free_kctls(struct hda_codec *codec);
3220 #ifdef CONFIG_SND_HDA_INPUT_BEEP
3221 /* additional beep mixers; the actual parameters are overwritten at build */
3222 static const struct snd_kcontrol_new alc_beep_mixer[] = {
3223 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
3224 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
3225 { } /* end */
3227 #endif
3229 static int alc_build_controls(struct hda_codec *codec)
3231 struct alc_spec *spec = codec->spec;
3232 struct snd_kcontrol *kctl = NULL;
3233 const struct snd_kcontrol_new *knew;
3234 int i, j, err;
3235 unsigned int u;
3236 hda_nid_t nid;
3238 for (i = 0; i < spec->num_mixers; i++) {
3239 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
3240 if (err < 0)
3241 return err;
3243 if (spec->cap_mixer) {
3244 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
3245 if (err < 0)
3246 return err;
3248 if (spec->multiout.dig_out_nid) {
3249 err = snd_hda_create_spdif_out_ctls(codec,
3250 spec->multiout.dig_out_nid);
3251 if (err < 0)
3252 return err;
3253 if (!spec->no_analog) {
3254 err = snd_hda_create_spdif_share_sw(codec,
3255 &spec->multiout);
3256 if (err < 0)
3257 return err;
3258 spec->multiout.share_spdif = 1;
3261 if (spec->dig_in_nid) {
3262 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
3263 if (err < 0)
3264 return err;
3267 #ifdef CONFIG_SND_HDA_INPUT_BEEP
3268 /* create beep controls if needed */
3269 if (spec->beep_amp) {
3270 const struct snd_kcontrol_new *knew;
3271 for (knew = alc_beep_mixer; knew->name; knew++) {
3272 struct snd_kcontrol *kctl;
3273 kctl = snd_ctl_new1(knew, codec);
3274 if (!kctl)
3275 return -ENOMEM;
3276 kctl->private_value = spec->beep_amp;
3277 err = snd_hda_ctl_add(codec, 0, kctl);
3278 if (err < 0)
3279 return err;
3282 #endif
3284 /* if we have no master control, let's create it */
3285 if (!spec->no_analog &&
3286 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
3287 unsigned int vmaster_tlv[4];
3288 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
3289 HDA_OUTPUT, vmaster_tlv);
3290 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
3291 vmaster_tlv, alc_slave_vols);
3292 if (err < 0)
3293 return err;
3295 if (!spec->no_analog &&
3296 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
3297 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
3298 NULL, alc_slave_sws);
3299 if (err < 0)
3300 return err;
3303 /* assign Capture Source enums to NID */
3304 if (spec->capsrc_nids || spec->adc_nids) {
3305 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
3306 if (!kctl)
3307 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
3308 for (i = 0; kctl && i < kctl->count; i++) {
3309 const hda_nid_t *nids = spec->capsrc_nids;
3310 if (!nids)
3311 nids = spec->adc_nids;
3312 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
3313 if (err < 0)
3314 return err;
3317 if (spec->cap_mixer) {
3318 const char *kname = kctl ? kctl->id.name : NULL;
3319 for (knew = spec->cap_mixer; knew->name; knew++) {
3320 if (kname && strcmp(knew->name, kname) == 0)
3321 continue;
3322 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
3323 for (i = 0; kctl && i < kctl->count; i++) {
3324 err = snd_hda_add_nid(codec, kctl, i,
3325 spec->adc_nids[i]);
3326 if (err < 0)
3327 return err;
3332 /* other nid->control mapping */
3333 for (i = 0; i < spec->num_mixers; i++) {
3334 for (knew = spec->mixers[i]; knew->name; knew++) {
3335 if (knew->iface != NID_MAPPING)
3336 continue;
3337 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
3338 if (kctl == NULL)
3339 continue;
3340 u = knew->subdevice;
3341 for (j = 0; j < 4; j++, u >>= 8) {
3342 nid = u & 0x3f;
3343 if (nid == 0)
3344 continue;
3345 switch (u & 0xc0) {
3346 case SUBDEV_SPEAKER_:
3347 nid = spec->autocfg.speaker_pins[nid];
3348 break;
3349 case SUBDEV_LINE_:
3350 nid = spec->autocfg.line_out_pins[nid];
3351 break;
3352 case SUBDEV_HP_:
3353 nid = spec->autocfg.hp_pins[nid];
3354 break;
3355 default:
3356 continue;
3358 err = snd_hda_add_nid(codec, kctl, 0, nid);
3359 if (err < 0)
3360 return err;
3362 u = knew->private_value;
3363 for (j = 0; j < 4; j++, u >>= 8) {
3364 nid = u & 0xff;
3365 if (nid == 0)
3366 continue;
3367 err = snd_hda_add_nid(codec, kctl, 0, nid);
3368 if (err < 0)
3369 return err;
3374 alc_free_kctls(codec); /* no longer needed */
3376 return 0;
3381 * initialize the codec volumes, etc
3385 * generic initialization of ADC, input mixers and output mixers
3387 static const struct hda_verb alc880_volume_init_verbs[] = {
3389 * Unmute ADC0-2 and set the default input to mic-in
3391 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3392 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3393 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3394 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3395 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3396 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3398 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3399 * mixer widget
3400 * Note: PASD motherboards uses the Line In 2 as the input for front
3401 * panel mic (mic 2)
3403 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3404 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3405 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3406 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3407 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3408 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3409 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3410 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
3413 * Set up output mixers (0x0c - 0x0f)
3415 /* set vol=0 to output mixers */
3416 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3417 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3418 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3419 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3420 /* set up input amps for analog loopback */
3421 /* Amp Indices: DAC = 0, mixer = 1 */
3422 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3423 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3424 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3425 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3426 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3427 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3428 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3429 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3435 * 3-stack pin configuration:
3436 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
3438 static const struct hda_verb alc880_pin_3stack_init_verbs[] = {
3440 * preset connection lists of input pins
3441 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
3443 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
3444 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3445 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
3448 * Set pin mode and muting
3450 /* set front pin widgets 0x14 for output */
3451 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3452 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3453 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3454 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3455 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3456 /* Mic2 (as headphone out) for HP output */
3457 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3458 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3459 /* Line In pin widget for input */
3460 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3461 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3462 /* Line2 (as front mic) pin widget for input and vref at 80% */
3463 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3464 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3465 /* CD pin widget for input */
3466 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3472 * 5-stack pin configuration:
3473 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
3474 * line-in/side = 0x1a, f-mic = 0x1b
3476 static const struct hda_verb alc880_pin_5stack_init_verbs[] = {
3478 * preset connection lists of input pins
3479 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
3481 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3482 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
3485 * Set pin mode and muting
3487 /* set pin widgets 0x14-0x17 for output */
3488 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3489 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3490 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3491 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3492 /* unmute pins for output (no gain on this amp) */
3493 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3494 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3495 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3496 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3498 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3499 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3500 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3501 /* Mic2 (as headphone out) for HP output */
3502 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3503 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3504 /* Line In pin widget for input */
3505 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3506 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3507 /* Line2 (as front mic) pin widget for input and vref at 80% */
3508 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3509 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3510 /* CD pin widget for input */
3511 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3517 * W810 pin configuration:
3518 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
3520 static const struct hda_verb alc880_pin_w810_init_verbs[] = {
3521 /* hphone/speaker input selector: front DAC */
3522 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
3524 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3525 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3526 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3527 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3528 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3529 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3531 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3532 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3538 * Z71V pin configuration:
3539 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
3541 static const struct hda_verb alc880_pin_z71v_init_verbs[] = {
3542 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3543 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3544 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3545 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3547 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3548 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3549 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3550 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3556 * 6-stack pin configuration:
3557 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
3558 * f-mic = 0x19, line = 0x1a, HP = 0x1b
3560 static const struct hda_verb alc880_pin_6stack_init_verbs[] = {
3561 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3563 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3564 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3565 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3566 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3567 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3568 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3569 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3570 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3572 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3573 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3574 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3575 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3576 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3577 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3578 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3579 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3580 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3586 * Uniwill pin configuration:
3587 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
3588 * line = 0x1a
3590 static const struct hda_verb alc880_uniwill_init_verbs[] = {
3591 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3593 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3594 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3595 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3596 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3597 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3598 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3599 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3600 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3601 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3602 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3603 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3604 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3605 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3606 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3608 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3609 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3610 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3611 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3612 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3613 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3614 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
3615 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
3616 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3618 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3619 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
3625 * Uniwill P53
3626 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
3628 static const struct hda_verb alc880_uniwill_p53_init_verbs[] = {
3629 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3631 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3632 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3633 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3634 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3635 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3636 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3637 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3638 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3639 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3640 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3641 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3642 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3644 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3645 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3646 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3647 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3648 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3649 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3651 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3652 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
3657 static const struct hda_verb alc880_beep_init_verbs[] = {
3658 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
3662 /* auto-toggle front mic */
3663 static void alc88x_simple_mic_automute(struct hda_codec *codec)
3665 unsigned int present;
3666 unsigned char bits;
3668 present = snd_hda_jack_detect(codec, 0x18);
3669 bits = present ? HDA_AMP_MUTE : 0;
3670 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
3673 static void alc880_uniwill_setup(struct hda_codec *codec)
3675 struct alc_spec *spec = codec->spec;
3677 spec->autocfg.hp_pins[0] = 0x14;
3678 spec->autocfg.speaker_pins[0] = 0x15;
3679 spec->autocfg.speaker_pins[0] = 0x16;
3680 spec->automute = 1;
3681 spec->automute_mode = ALC_AUTOMUTE_AMP;
3684 static void alc880_uniwill_init_hook(struct hda_codec *codec)
3686 alc_hp_automute(codec);
3687 alc88x_simple_mic_automute(codec);
3690 static void alc880_uniwill_unsol_event(struct hda_codec *codec,
3691 unsigned int res)
3693 /* Looks like the unsol event is incompatible with the standard
3694 * definition. 4bit tag is placed at 28 bit!
3696 switch (res >> 28) {
3697 case ALC880_MIC_EVENT:
3698 alc88x_simple_mic_automute(codec);
3699 break;
3700 default:
3701 alc_sku_unsol_event(codec, res);
3702 break;
3706 static void alc880_uniwill_p53_setup(struct hda_codec *codec)
3708 struct alc_spec *spec = codec->spec;
3710 spec->autocfg.hp_pins[0] = 0x14;
3711 spec->autocfg.speaker_pins[0] = 0x15;
3712 spec->automute = 1;
3713 spec->automute_mode = ALC_AUTOMUTE_AMP;
3716 static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
3718 unsigned int present;
3720 present = snd_hda_codec_read(codec, 0x21, 0,
3721 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
3722 present &= HDA_AMP_VOLMASK;
3723 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
3724 HDA_AMP_VOLMASK, present);
3725 snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
3726 HDA_AMP_VOLMASK, present);
3729 static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
3730 unsigned int res)
3732 /* Looks like the unsol event is incompatible with the standard
3733 * definition. 4bit tag is placed at 28 bit!
3735 if ((res >> 28) == ALC880_DCVOL_EVENT)
3736 alc880_uniwill_p53_dcvol_automute(codec);
3737 else
3738 alc_sku_unsol_event(codec, res);
3742 * F1734 pin configuration:
3743 * HP = 0x14, speaker-out = 0x15, mic = 0x18
3745 static const struct hda_verb alc880_pin_f1734_init_verbs[] = {
3746 {0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
3747 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
3748 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
3749 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
3750 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
3752 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3753 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3754 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3755 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3757 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3758 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3759 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
3760 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3761 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3762 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3763 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3764 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3765 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3767 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
3768 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
3774 * ASUS pin configuration:
3775 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
3777 static const struct hda_verb alc880_pin_asus_init_verbs[] = {
3778 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
3779 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
3780 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
3781 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
3783 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3784 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3785 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3786 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3787 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3788 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3789 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3790 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3792 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3793 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3794 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3795 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3796 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3797 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3798 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3799 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3800 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3805 /* Enable GPIO mask and set output */
3806 #define alc880_gpio1_init_verbs alc_gpio1_init_verbs
3807 #define alc880_gpio2_init_verbs alc_gpio2_init_verbs
3808 #define alc880_gpio3_init_verbs alc_gpio3_init_verbs
3810 /* Clevo m520g init */
3811 static const struct hda_verb alc880_pin_clevo_init_verbs[] = {
3812 /* headphone output */
3813 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
3814 /* line-out */
3815 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3816 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3817 /* Line-in */
3818 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3819 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3820 /* CD */
3821 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3822 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3823 /* Mic1 (rear panel) */
3824 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3825 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3826 /* Mic2 (front panel) */
3827 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3828 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3829 /* headphone */
3830 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3831 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3832 /* change to EAPD mode */
3833 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3834 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3839 static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
3840 /* change to EAPD mode */
3841 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3842 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3844 /* Headphone output */
3845 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3846 /* Front output*/
3847 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3848 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
3850 /* Line In pin widget for input */
3851 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3852 /* CD pin widget for input */
3853 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3854 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3855 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3857 /* change to EAPD mode */
3858 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3859 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
3865 * LG m1 express dual
3867 * Pin assignment:
3868 * Rear Line-In/Out (blue): 0x14
3869 * Build-in Mic-In: 0x15
3870 * Speaker-out: 0x17
3871 * HP-Out (green): 0x1b
3872 * Mic-In/Out (red): 0x19
3873 * SPDIF-Out: 0x1e
3876 /* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
3877 static const hda_nid_t alc880_lg_dac_nids[3] = {
3878 0x05, 0x02, 0x03
3881 /* seems analog CD is not working */
3882 static const struct hda_input_mux alc880_lg_capture_source = {
3883 .num_items = 3,
3884 .items = {
3885 { "Mic", 0x1 },
3886 { "Line", 0x5 },
3887 { "Internal Mic", 0x6 },
3891 /* 2,4,6 channel modes */
3892 static const struct hda_verb alc880_lg_ch2_init[] = {
3893 /* set line-in and mic-in to input */
3894 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
3895 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
3899 static const struct hda_verb alc880_lg_ch4_init[] = {
3900 /* set line-in to out and mic-in to input */
3901 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3902 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
3906 static const struct hda_verb alc880_lg_ch6_init[] = {
3907 /* set line-in and mic-in to output */
3908 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3909 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3913 static const struct hda_channel_mode alc880_lg_ch_modes[3] = {
3914 { 2, alc880_lg_ch2_init },
3915 { 4, alc880_lg_ch4_init },
3916 { 6, alc880_lg_ch6_init },
3919 static const struct snd_kcontrol_new alc880_lg_mixer[] = {
3920 HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3921 HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
3922 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3923 HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
3924 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
3925 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
3926 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
3927 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
3928 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3929 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3930 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
3931 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
3932 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
3933 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
3935 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3936 .name = "Channel Mode",
3937 .info = alc_ch_mode_info,
3938 .get = alc_ch_mode_get,
3939 .put = alc_ch_mode_put,
3941 { } /* end */
3944 static const struct hda_verb alc880_lg_init_verbs[] = {
3945 /* set capture source to mic-in */
3946 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3947 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3948 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3949 /* mute all amp mixer inputs */
3950 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
3951 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3952 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
3953 /* line-in to input */
3954 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3955 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3956 /* built-in mic */
3957 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3958 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3959 /* speaker-out */
3960 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3961 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3962 /* mic-in to input */
3963 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
3964 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3965 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3966 /* HP-out */
3967 {0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
3968 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3969 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3970 /* jack sense */
3971 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3975 /* toggle speaker-output according to the hp-jack state */
3976 static void alc880_lg_setup(struct hda_codec *codec)
3978 struct alc_spec *spec = codec->spec;
3980 spec->autocfg.hp_pins[0] = 0x1b;
3981 spec->autocfg.speaker_pins[0] = 0x17;
3982 spec->automute = 1;
3983 spec->automute_mode = ALC_AUTOMUTE_AMP;
3987 * LG LW20
3989 * Pin assignment:
3990 * Speaker-out: 0x14
3991 * Mic-In: 0x18
3992 * Built-in Mic-In: 0x19
3993 * Line-In: 0x1b
3994 * HP-Out: 0x1a
3995 * SPDIF-Out: 0x1e
3998 static const struct hda_input_mux alc880_lg_lw_capture_source = {
3999 .num_items = 3,
4000 .items = {
4001 { "Mic", 0x0 },
4002 { "Internal Mic", 0x1 },
4003 { "Line In", 0x2 },
4007 #define alc880_lg_lw_modes alc880_threestack_modes
4009 static const struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
4010 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4011 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4012 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
4013 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
4014 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
4015 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
4016 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
4017 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
4018 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4019 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4020 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
4021 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4022 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
4023 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
4025 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4026 .name = "Channel Mode",
4027 .info = alc_ch_mode_info,
4028 .get = alc_ch_mode_get,
4029 .put = alc_ch_mode_put,
4031 { } /* end */
4034 static const struct hda_verb alc880_lg_lw_init_verbs[] = {
4035 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
4036 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
4037 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
4039 /* set capture source to mic-in */
4040 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4041 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4042 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4043 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4044 /* speaker-out */
4045 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4046 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4047 /* HP-out */
4048 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4049 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4050 /* mic-in to input */
4051 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4052 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4053 /* built-in mic */
4054 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4055 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4056 /* jack sense */
4057 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
4061 /* toggle speaker-output according to the hp-jack state */
4062 static void alc880_lg_lw_setup(struct hda_codec *codec)
4064 struct alc_spec *spec = codec->spec;
4066 spec->autocfg.hp_pins[0] = 0x1b;
4067 spec->autocfg.speaker_pins[0] = 0x14;
4068 spec->automute = 1;
4069 spec->automute_mode = ALC_AUTOMUTE_AMP;
4072 static const struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
4073 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4074 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
4075 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
4076 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4077 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
4078 HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
4079 { } /* end */
4082 static const struct hda_input_mux alc880_medion_rim_capture_source = {
4083 .num_items = 2,
4084 .items = {
4085 { "Mic", 0x0 },
4086 { "Internal Mic", 0x1 },
4090 static const struct hda_verb alc880_medion_rim_init_verbs[] = {
4091 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
4093 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4094 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4096 /* Mic1 (rear panel) pin widget for input and vref at 80% */
4097 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4098 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4099 /* Mic2 (as headphone out) for HP output */
4100 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4101 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4102 /* Internal Speaker */
4103 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4104 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4106 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
4107 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
4109 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
4113 /* toggle speaker-output according to the hp-jack state */
4114 static void alc880_medion_rim_automute(struct hda_codec *codec)
4116 struct alc_spec *spec = codec->spec;
4117 alc_hp_automute(codec);
4118 /* toggle EAPD */
4119 if (spec->jack_present)
4120 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
4121 else
4122 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
4125 static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
4126 unsigned int res)
4128 /* Looks like the unsol event is incompatible with the standard
4129 * definition. 4bit tag is placed at 28 bit!
4131 if ((res >> 28) == ALC880_HP_EVENT)
4132 alc880_medion_rim_automute(codec);
4135 static void alc880_medion_rim_setup(struct hda_codec *codec)
4137 struct alc_spec *spec = codec->spec;
4139 spec->autocfg.hp_pins[0] = 0x14;
4140 spec->autocfg.speaker_pins[0] = 0x1b;
4141 spec->automute = 1;
4142 spec->automute_mode = ALC_AUTOMUTE_AMP;
4145 #ifdef CONFIG_SND_HDA_POWER_SAVE
4146 static const struct hda_amp_list alc880_loopbacks[] = {
4147 { 0x0b, HDA_INPUT, 0 },
4148 { 0x0b, HDA_INPUT, 1 },
4149 { 0x0b, HDA_INPUT, 2 },
4150 { 0x0b, HDA_INPUT, 3 },
4151 { 0x0b, HDA_INPUT, 4 },
4152 { } /* end */
4155 static const struct hda_amp_list alc880_lg_loopbacks[] = {
4156 { 0x0b, HDA_INPUT, 1 },
4157 { 0x0b, HDA_INPUT, 6 },
4158 { 0x0b, HDA_INPUT, 7 },
4159 { } /* end */
4161 #endif
4164 * Common callbacks
4167 static void alc_init_special_input_src(struct hda_codec *codec);
4169 static int alc_init(struct hda_codec *codec)
4171 struct alc_spec *spec = codec->spec;
4172 unsigned int i;
4174 alc_fix_pll(codec);
4175 alc_auto_init_amp(codec, spec->init_amp);
4177 for (i = 0; i < spec->num_init_verbs; i++)
4178 snd_hda_sequence_write(codec, spec->init_verbs[i]);
4179 alc_init_special_input_src(codec);
4181 if (spec->init_hook)
4182 spec->init_hook(codec);
4184 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
4186 hda_call_check_power_status(codec, 0x01);
4187 return 0;
4190 static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
4192 struct alc_spec *spec = codec->spec;
4194 if (spec->unsol_event)
4195 spec->unsol_event(codec, res);
4198 #ifdef CONFIG_SND_HDA_POWER_SAVE
4199 static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
4201 struct alc_spec *spec = codec->spec;
4202 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
4204 #endif
4207 * Analog playback callbacks
4209 static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
4210 struct hda_codec *codec,
4211 struct snd_pcm_substream *substream)
4213 struct alc_spec *spec = codec->spec;
4214 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
4215 hinfo);
4218 static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4219 struct hda_codec *codec,
4220 unsigned int stream_tag,
4221 unsigned int format,
4222 struct snd_pcm_substream *substream)
4224 struct alc_spec *spec = codec->spec;
4225 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
4226 stream_tag, format, substream);
4229 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4230 struct hda_codec *codec,
4231 struct snd_pcm_substream *substream)
4233 struct alc_spec *spec = codec->spec;
4234 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
4238 * Digital out
4240 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
4241 struct hda_codec *codec,
4242 struct snd_pcm_substream *substream)
4244 struct alc_spec *spec = codec->spec;
4245 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
4248 static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4249 struct hda_codec *codec,
4250 unsigned int stream_tag,
4251 unsigned int format,
4252 struct snd_pcm_substream *substream)
4254 struct alc_spec *spec = codec->spec;
4255 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
4256 stream_tag, format, substream);
4259 static int alc880_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4260 struct hda_codec *codec,
4261 struct snd_pcm_substream *substream)
4263 struct alc_spec *spec = codec->spec;
4264 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
4267 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
4268 struct hda_codec *codec,
4269 struct snd_pcm_substream *substream)
4271 struct alc_spec *spec = codec->spec;
4272 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
4276 * Analog capture
4278 static int alc880_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4279 struct hda_codec *codec,
4280 unsigned int stream_tag,
4281 unsigned int format,
4282 struct snd_pcm_substream *substream)
4284 struct alc_spec *spec = codec->spec;
4286 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
4287 stream_tag, 0, format);
4288 return 0;
4291 static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4292 struct hda_codec *codec,
4293 struct snd_pcm_substream *substream)
4295 struct alc_spec *spec = codec->spec;
4297 snd_hda_codec_cleanup_stream(codec,
4298 spec->adc_nids[substream->number + 1]);
4299 return 0;
4302 /* analog capture with dynamic dual-adc changes */
4303 static int dualmic_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4304 struct hda_codec *codec,
4305 unsigned int stream_tag,
4306 unsigned int format,
4307 struct snd_pcm_substream *substream)
4309 struct alc_spec *spec = codec->spec;
4310 spec->cur_adc = spec->adc_nids[spec->cur_adc_idx];
4311 spec->cur_adc_stream_tag = stream_tag;
4312 spec->cur_adc_format = format;
4313 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
4314 return 0;
4317 static int dualmic_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4318 struct hda_codec *codec,
4319 struct snd_pcm_substream *substream)
4321 struct alc_spec *spec = codec->spec;
4322 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
4323 spec->cur_adc = 0;
4324 return 0;
4327 static const struct hda_pcm_stream dualmic_pcm_analog_capture = {
4328 .substreams = 1,
4329 .channels_min = 2,
4330 .channels_max = 2,
4331 .nid = 0, /* fill later */
4332 .ops = {
4333 .prepare = dualmic_capture_pcm_prepare,
4334 .cleanup = dualmic_capture_pcm_cleanup
4340 static const struct hda_pcm_stream alc880_pcm_analog_playback = {
4341 .substreams = 1,
4342 .channels_min = 2,
4343 .channels_max = 8,
4344 /* NID is set in alc_build_pcms */
4345 .ops = {
4346 .open = alc880_playback_pcm_open,
4347 .prepare = alc880_playback_pcm_prepare,
4348 .cleanup = alc880_playback_pcm_cleanup
4352 static const struct hda_pcm_stream alc880_pcm_analog_capture = {
4353 .substreams = 1,
4354 .channels_min = 2,
4355 .channels_max = 2,
4356 /* NID is set in alc_build_pcms */
4359 static const struct hda_pcm_stream alc880_pcm_analog_alt_playback = {
4360 .substreams = 1,
4361 .channels_min = 2,
4362 .channels_max = 2,
4363 /* NID is set in alc_build_pcms */
4366 static const struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
4367 .substreams = 2, /* can be overridden */
4368 .channels_min = 2,
4369 .channels_max = 2,
4370 /* NID is set in alc_build_pcms */
4371 .ops = {
4372 .prepare = alc880_alt_capture_pcm_prepare,
4373 .cleanup = alc880_alt_capture_pcm_cleanup
4377 static const struct hda_pcm_stream alc880_pcm_digital_playback = {
4378 .substreams = 1,
4379 .channels_min = 2,
4380 .channels_max = 2,
4381 /* NID is set in alc_build_pcms */
4382 .ops = {
4383 .open = alc880_dig_playback_pcm_open,
4384 .close = alc880_dig_playback_pcm_close,
4385 .prepare = alc880_dig_playback_pcm_prepare,
4386 .cleanup = alc880_dig_playback_pcm_cleanup
4390 static const struct hda_pcm_stream alc880_pcm_digital_capture = {
4391 .substreams = 1,
4392 .channels_min = 2,
4393 .channels_max = 2,
4394 /* NID is set in alc_build_pcms */
4397 /* Used by alc_build_pcms to flag that a PCM has no playback stream */
4398 static const struct hda_pcm_stream alc_pcm_null_stream = {
4399 .substreams = 0,
4400 .channels_min = 0,
4401 .channels_max = 0,
4404 static int alc_build_pcms(struct hda_codec *codec)
4406 struct alc_spec *spec = codec->spec;
4407 struct hda_pcm *info = spec->pcm_rec;
4408 int i;
4410 codec->num_pcms = 1;
4411 codec->pcm_info = info;
4413 if (spec->no_analog)
4414 goto skip_analog;
4416 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
4417 "%s Analog", codec->chip_name);
4418 info->name = spec->stream_name_analog;
4420 if (spec->stream_analog_playback) {
4421 if (snd_BUG_ON(!spec->multiout.dac_nids))
4422 return -EINVAL;
4423 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
4424 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
4426 if (spec->stream_analog_capture) {
4427 if (snd_BUG_ON(!spec->adc_nids))
4428 return -EINVAL;
4429 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
4430 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
4433 if (spec->channel_mode) {
4434 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
4435 for (i = 0; i < spec->num_channel_mode; i++) {
4436 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
4437 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
4442 skip_analog:
4443 /* SPDIF for stream index #1 */
4444 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
4445 snprintf(spec->stream_name_digital,
4446 sizeof(spec->stream_name_digital),
4447 "%s Digital", codec->chip_name);
4448 codec->num_pcms = 2;
4449 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
4450 info = spec->pcm_rec + 1;
4451 info->name = spec->stream_name_digital;
4452 if (spec->dig_out_type)
4453 info->pcm_type = spec->dig_out_type;
4454 else
4455 info->pcm_type = HDA_PCM_TYPE_SPDIF;
4456 if (spec->multiout.dig_out_nid &&
4457 spec->stream_digital_playback) {
4458 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
4459 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
4461 if (spec->dig_in_nid &&
4462 spec->stream_digital_capture) {
4463 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
4464 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
4466 /* FIXME: do we need this for all Realtek codec models? */
4467 codec->spdif_status_reset = 1;
4470 if (spec->no_analog)
4471 return 0;
4473 /* If the use of more than one ADC is requested for the current
4474 * model, configure a second analog capture-only PCM.
4476 /* Additional Analaog capture for index #2 */
4477 if ((spec->alt_dac_nid && spec->stream_analog_alt_playback) ||
4478 (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture)) {
4479 codec->num_pcms = 3;
4480 info = spec->pcm_rec + 2;
4481 info->name = spec->stream_name_analog;
4482 if (spec->alt_dac_nid) {
4483 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
4484 *spec->stream_analog_alt_playback;
4485 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
4486 spec->alt_dac_nid;
4487 } else {
4488 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
4489 alc_pcm_null_stream;
4490 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
4492 if (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture) {
4493 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
4494 *spec->stream_analog_alt_capture;
4495 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
4496 spec->adc_nids[1];
4497 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
4498 spec->num_adc_nids - 1;
4499 } else {
4500 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
4501 alc_pcm_null_stream;
4502 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
4506 return 0;
4509 static inline void alc_shutup(struct hda_codec *codec)
4511 struct alc_spec *spec = codec->spec;
4513 if (spec && spec->shutup)
4514 spec->shutup(codec);
4515 snd_hda_shutup_pins(codec);
4518 static void alc_free_kctls(struct hda_codec *codec)
4520 struct alc_spec *spec = codec->spec;
4522 if (spec->kctls.list) {
4523 struct snd_kcontrol_new *kctl = spec->kctls.list;
4524 int i;
4525 for (i = 0; i < spec->kctls.used; i++)
4526 kfree(kctl[i].name);
4528 snd_array_free(&spec->kctls);
4531 static void alc_free(struct hda_codec *codec)
4533 struct alc_spec *spec = codec->spec;
4535 if (!spec)
4536 return;
4538 alc_shutup(codec);
4539 snd_hda_input_jack_free(codec);
4540 alc_free_kctls(codec);
4541 kfree(spec);
4542 snd_hda_detach_beep_device(codec);
4545 #ifdef CONFIG_SND_HDA_POWER_SAVE
4546 static void alc_power_eapd(struct hda_codec *codec)
4548 alc_auto_setup_eapd(codec, false);
4551 static int alc_suspend(struct hda_codec *codec, pm_message_t state)
4553 struct alc_spec *spec = codec->spec;
4554 alc_shutup(codec);
4555 if (spec && spec->power_hook)
4556 spec->power_hook(codec);
4557 return 0;
4559 #endif
4561 #ifdef SND_HDA_NEEDS_RESUME
4562 static int alc_resume(struct hda_codec *codec)
4564 msleep(150); /* to avoid pop noise */
4565 codec->patch_ops.init(codec);
4566 snd_hda_codec_resume_amp(codec);
4567 snd_hda_codec_resume_cache(codec);
4568 hda_call_check_power_status(codec, 0x01);
4569 return 0;
4571 #endif
4575 static const struct hda_codec_ops alc_patch_ops = {
4576 .build_controls = alc_build_controls,
4577 .build_pcms = alc_build_pcms,
4578 .init = alc_init,
4579 .free = alc_free,
4580 .unsol_event = alc_unsol_event,
4581 #ifdef SND_HDA_NEEDS_RESUME
4582 .resume = alc_resume,
4583 #endif
4584 #ifdef CONFIG_SND_HDA_POWER_SAVE
4585 .suspend = alc_suspend,
4586 .check_power_status = alc_check_power_status,
4587 #endif
4588 .reboot_notify = alc_shutup,
4591 /* replace the codec chip_name with the given string */
4592 static int alc_codec_rename(struct hda_codec *codec, const char *name)
4594 kfree(codec->chip_name);
4595 codec->chip_name = kstrdup(name, GFP_KERNEL);
4596 if (!codec->chip_name) {
4597 alc_free(codec);
4598 return -ENOMEM;
4600 return 0;
4604 * Test configuration for debugging
4606 * Almost all inputs/outputs are enabled. I/O pins can be configured via
4607 * enum controls.
4609 #ifdef CONFIG_SND_DEBUG
4610 static const hda_nid_t alc880_test_dac_nids[4] = {
4611 0x02, 0x03, 0x04, 0x05
4614 static const struct hda_input_mux alc880_test_capture_source = {
4615 .num_items = 7,
4616 .items = {
4617 { "In-1", 0x0 },
4618 { "In-2", 0x1 },
4619 { "In-3", 0x2 },
4620 { "In-4", 0x3 },
4621 { "CD", 0x4 },
4622 { "Front", 0x5 },
4623 { "Surround", 0x6 },
4627 static const struct hda_channel_mode alc880_test_modes[4] = {
4628 { 2, NULL },
4629 { 4, NULL },
4630 { 6, NULL },
4631 { 8, NULL },
4634 static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
4635 struct snd_ctl_elem_info *uinfo)
4637 static const char * const texts[] = {
4638 "N/A", "Line Out", "HP Out",
4639 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
4641 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4642 uinfo->count = 1;
4643 uinfo->value.enumerated.items = 8;
4644 if (uinfo->value.enumerated.item >= 8)
4645 uinfo->value.enumerated.item = 7;
4646 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
4647 return 0;
4650 static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
4651 struct snd_ctl_elem_value *ucontrol)
4653 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4654 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4655 unsigned int pin_ctl, item = 0;
4657 pin_ctl = snd_hda_codec_read(codec, nid, 0,
4658 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4659 if (pin_ctl & AC_PINCTL_OUT_EN) {
4660 if (pin_ctl & AC_PINCTL_HP_EN)
4661 item = 2;
4662 else
4663 item = 1;
4664 } else if (pin_ctl & AC_PINCTL_IN_EN) {
4665 switch (pin_ctl & AC_PINCTL_VREFEN) {
4666 case AC_PINCTL_VREF_HIZ: item = 3; break;
4667 case AC_PINCTL_VREF_50: item = 4; break;
4668 case AC_PINCTL_VREF_GRD: item = 5; break;
4669 case AC_PINCTL_VREF_80: item = 6; break;
4670 case AC_PINCTL_VREF_100: item = 7; break;
4673 ucontrol->value.enumerated.item[0] = item;
4674 return 0;
4677 static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
4678 struct snd_ctl_elem_value *ucontrol)
4680 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4681 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4682 static const unsigned int ctls[] = {
4683 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
4684 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
4685 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
4686 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
4687 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
4688 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
4690 unsigned int old_ctl, new_ctl;
4692 old_ctl = snd_hda_codec_read(codec, nid, 0,
4693 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4694 new_ctl = ctls[ucontrol->value.enumerated.item[0]];
4695 if (old_ctl != new_ctl) {
4696 int val;
4697 snd_hda_codec_write_cache(codec, nid, 0,
4698 AC_VERB_SET_PIN_WIDGET_CONTROL,
4699 new_ctl);
4700 val = ucontrol->value.enumerated.item[0] >= 3 ?
4701 HDA_AMP_MUTE : 0;
4702 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
4703 HDA_AMP_MUTE, val);
4704 return 1;
4706 return 0;
4709 static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
4710 struct snd_ctl_elem_info *uinfo)
4712 static const char * const texts[] = {
4713 "Front", "Surround", "CLFE", "Side"
4715 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4716 uinfo->count = 1;
4717 uinfo->value.enumerated.items = 4;
4718 if (uinfo->value.enumerated.item >= 4)
4719 uinfo->value.enumerated.item = 3;
4720 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
4721 return 0;
4724 static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
4725 struct snd_ctl_elem_value *ucontrol)
4727 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4728 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4729 unsigned int sel;
4731 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
4732 ucontrol->value.enumerated.item[0] = sel & 3;
4733 return 0;
4736 static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
4737 struct snd_ctl_elem_value *ucontrol)
4739 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4740 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4741 unsigned int sel;
4743 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
4744 if (ucontrol->value.enumerated.item[0] != sel) {
4745 sel = ucontrol->value.enumerated.item[0] & 3;
4746 snd_hda_codec_write_cache(codec, nid, 0,
4747 AC_VERB_SET_CONNECT_SEL, sel);
4748 return 1;
4750 return 0;
4753 #define PIN_CTL_TEST(xname,nid) { \
4754 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4755 .name = xname, \
4756 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
4757 .info = alc_test_pin_ctl_info, \
4758 .get = alc_test_pin_ctl_get, \
4759 .put = alc_test_pin_ctl_put, \
4760 .private_value = nid \
4763 #define PIN_SRC_TEST(xname,nid) { \
4764 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4765 .name = xname, \
4766 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
4767 .info = alc_test_pin_src_info, \
4768 .get = alc_test_pin_src_get, \
4769 .put = alc_test_pin_src_put, \
4770 .private_value = nid \
4773 static const struct snd_kcontrol_new alc880_test_mixer[] = {
4774 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4775 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
4776 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
4777 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
4778 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4779 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
4780 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
4781 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
4782 PIN_CTL_TEST("Front Pin Mode", 0x14),
4783 PIN_CTL_TEST("Surround Pin Mode", 0x15),
4784 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
4785 PIN_CTL_TEST("Side Pin Mode", 0x17),
4786 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
4787 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
4788 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
4789 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
4790 PIN_SRC_TEST("In-1 Pin Source", 0x18),
4791 PIN_SRC_TEST("In-2 Pin Source", 0x19),
4792 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
4793 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
4794 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
4795 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
4796 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
4797 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
4798 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
4799 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
4800 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
4801 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
4802 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
4803 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
4805 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4806 .name = "Channel Mode",
4807 .info = alc_ch_mode_info,
4808 .get = alc_ch_mode_get,
4809 .put = alc_ch_mode_put,
4811 { } /* end */
4814 static const struct hda_verb alc880_test_init_verbs[] = {
4815 /* Unmute inputs of 0x0c - 0x0f */
4816 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4817 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4818 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4819 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4820 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4821 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4822 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4823 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4824 /* Vol output for 0x0c-0x0f */
4825 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4826 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4827 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4828 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4829 /* Set output pins 0x14-0x17 */
4830 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4831 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4832 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4833 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4834 /* Unmute output pins 0x14-0x17 */
4835 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4836 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4837 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4838 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4839 /* Set input pins 0x18-0x1c */
4840 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4841 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4842 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4843 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4844 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4845 /* Mute input pins 0x18-0x1b */
4846 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4847 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4848 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4849 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4850 /* ADC set up */
4851 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4852 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4853 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4854 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4855 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4856 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4857 /* Analog input/passthru */
4858 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4859 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4860 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4861 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4862 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4865 #endif
4870 static const char * const alc880_models[ALC880_MODEL_LAST] = {
4871 [ALC880_3ST] = "3stack",
4872 [ALC880_TCL_S700] = "tcl",
4873 [ALC880_3ST_DIG] = "3stack-digout",
4874 [ALC880_CLEVO] = "clevo",
4875 [ALC880_5ST] = "5stack",
4876 [ALC880_5ST_DIG] = "5stack-digout",
4877 [ALC880_W810] = "w810",
4878 [ALC880_Z71V] = "z71v",
4879 [ALC880_6ST] = "6stack",
4880 [ALC880_6ST_DIG] = "6stack-digout",
4881 [ALC880_ASUS] = "asus",
4882 [ALC880_ASUS_W1V] = "asus-w1v",
4883 [ALC880_ASUS_DIG] = "asus-dig",
4884 [ALC880_ASUS_DIG2] = "asus-dig2",
4885 [ALC880_UNIWILL_DIG] = "uniwill",
4886 [ALC880_UNIWILL_P53] = "uniwill-p53",
4887 [ALC880_FUJITSU] = "fujitsu",
4888 [ALC880_F1734] = "F1734",
4889 [ALC880_LG] = "lg",
4890 [ALC880_LG_LW] = "lg-lw",
4891 [ALC880_MEDION_RIM] = "medion",
4892 #ifdef CONFIG_SND_DEBUG
4893 [ALC880_TEST] = "test",
4894 #endif
4895 [ALC880_AUTO] = "auto",
4898 static const struct snd_pci_quirk alc880_cfg_tbl[] = {
4899 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
4900 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
4901 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
4902 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
4903 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
4904 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
4905 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
4906 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
4907 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
4908 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
4909 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
4910 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
4911 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
4912 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
4913 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
4914 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
4915 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
4916 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
4917 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
4918 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
4919 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
4920 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
4921 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
4922 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
4923 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
4924 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
4925 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
4926 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
4927 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
4928 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
4929 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
4930 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
4931 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
4932 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
4933 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
4934 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
4935 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
4936 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
4937 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
4938 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734),
4939 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
4940 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
4941 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
4942 SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
4943 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
4944 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
4945 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
4946 SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
4947 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734),
4948 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
4949 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
4950 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
4951 SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
4952 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
4953 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
4954 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
4955 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
4956 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
4957 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
4958 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
4959 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
4960 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
4961 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
4962 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
4963 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
4964 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
4965 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
4966 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
4967 /* default Intel */
4968 SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
4969 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
4970 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
4975 * ALC880 codec presets
4977 static const struct alc_config_preset alc880_presets[] = {
4978 [ALC880_3ST] = {
4979 .mixers = { alc880_three_stack_mixer },
4980 .init_verbs = { alc880_volume_init_verbs,
4981 alc880_pin_3stack_init_verbs },
4982 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4983 .dac_nids = alc880_dac_nids,
4984 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4985 .channel_mode = alc880_threestack_modes,
4986 .need_dac_fix = 1,
4987 .input_mux = &alc880_capture_source,
4989 [ALC880_3ST_DIG] = {
4990 .mixers = { alc880_three_stack_mixer },
4991 .init_verbs = { alc880_volume_init_verbs,
4992 alc880_pin_3stack_init_verbs },
4993 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4994 .dac_nids = alc880_dac_nids,
4995 .dig_out_nid = ALC880_DIGOUT_NID,
4996 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4997 .channel_mode = alc880_threestack_modes,
4998 .need_dac_fix = 1,
4999 .input_mux = &alc880_capture_source,
5001 [ALC880_TCL_S700] = {
5002 .mixers = { alc880_tcl_s700_mixer },
5003 .init_verbs = { alc880_volume_init_verbs,
5004 alc880_pin_tcl_S700_init_verbs,
5005 alc880_gpio2_init_verbs },
5006 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5007 .dac_nids = alc880_dac_nids,
5008 .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
5009 .num_adc_nids = 1, /* single ADC */
5010 .hp_nid = 0x03,
5011 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
5012 .channel_mode = alc880_2_jack_modes,
5013 .input_mux = &alc880_capture_source,
5015 [ALC880_5ST] = {
5016 .mixers = { alc880_three_stack_mixer,
5017 alc880_five_stack_mixer},
5018 .init_verbs = { alc880_volume_init_verbs,
5019 alc880_pin_5stack_init_verbs },
5020 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5021 .dac_nids = alc880_dac_nids,
5022 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
5023 .channel_mode = alc880_fivestack_modes,
5024 .input_mux = &alc880_capture_source,
5026 [ALC880_5ST_DIG] = {
5027 .mixers = { alc880_three_stack_mixer,
5028 alc880_five_stack_mixer },
5029 .init_verbs = { alc880_volume_init_verbs,
5030 alc880_pin_5stack_init_verbs },
5031 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5032 .dac_nids = alc880_dac_nids,
5033 .dig_out_nid = ALC880_DIGOUT_NID,
5034 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
5035 .channel_mode = alc880_fivestack_modes,
5036 .input_mux = &alc880_capture_source,
5038 [ALC880_6ST] = {
5039 .mixers = { alc880_six_stack_mixer },
5040 .init_verbs = { alc880_volume_init_verbs,
5041 alc880_pin_6stack_init_verbs },
5042 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
5043 .dac_nids = alc880_6st_dac_nids,
5044 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
5045 .channel_mode = alc880_sixstack_modes,
5046 .input_mux = &alc880_6stack_capture_source,
5048 [ALC880_6ST_DIG] = {
5049 .mixers = { alc880_six_stack_mixer },
5050 .init_verbs = { alc880_volume_init_verbs,
5051 alc880_pin_6stack_init_verbs },
5052 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
5053 .dac_nids = alc880_6st_dac_nids,
5054 .dig_out_nid = ALC880_DIGOUT_NID,
5055 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
5056 .channel_mode = alc880_sixstack_modes,
5057 .input_mux = &alc880_6stack_capture_source,
5059 [ALC880_W810] = {
5060 .mixers = { alc880_w810_base_mixer },
5061 .init_verbs = { alc880_volume_init_verbs,
5062 alc880_pin_w810_init_verbs,
5063 alc880_gpio2_init_verbs },
5064 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
5065 .dac_nids = alc880_w810_dac_nids,
5066 .dig_out_nid = ALC880_DIGOUT_NID,
5067 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
5068 .channel_mode = alc880_w810_modes,
5069 .input_mux = &alc880_capture_source,
5071 [ALC880_Z71V] = {
5072 .mixers = { alc880_z71v_mixer },
5073 .init_verbs = { alc880_volume_init_verbs,
5074 alc880_pin_z71v_init_verbs },
5075 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
5076 .dac_nids = alc880_z71v_dac_nids,
5077 .dig_out_nid = ALC880_DIGOUT_NID,
5078 .hp_nid = 0x03,
5079 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
5080 .channel_mode = alc880_2_jack_modes,
5081 .input_mux = &alc880_capture_source,
5083 [ALC880_F1734] = {
5084 .mixers = { alc880_f1734_mixer },
5085 .init_verbs = { alc880_volume_init_verbs,
5086 alc880_pin_f1734_init_verbs },
5087 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
5088 .dac_nids = alc880_f1734_dac_nids,
5089 .hp_nid = 0x02,
5090 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
5091 .channel_mode = alc880_2_jack_modes,
5092 .input_mux = &alc880_f1734_capture_source,
5093 .unsol_event = alc880_uniwill_p53_unsol_event,
5094 .setup = alc880_uniwill_p53_setup,
5095 .init_hook = alc_hp_automute,
5097 [ALC880_ASUS] = {
5098 .mixers = { alc880_asus_mixer },
5099 .init_verbs = { alc880_volume_init_verbs,
5100 alc880_pin_asus_init_verbs,
5101 alc880_gpio1_init_verbs },
5102 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5103 .dac_nids = alc880_asus_dac_nids,
5104 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
5105 .channel_mode = alc880_asus_modes,
5106 .need_dac_fix = 1,
5107 .input_mux = &alc880_capture_source,
5109 [ALC880_ASUS_DIG] = {
5110 .mixers = { alc880_asus_mixer },
5111 .init_verbs = { alc880_volume_init_verbs,
5112 alc880_pin_asus_init_verbs,
5113 alc880_gpio1_init_verbs },
5114 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5115 .dac_nids = alc880_asus_dac_nids,
5116 .dig_out_nid = ALC880_DIGOUT_NID,
5117 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
5118 .channel_mode = alc880_asus_modes,
5119 .need_dac_fix = 1,
5120 .input_mux = &alc880_capture_source,
5122 [ALC880_ASUS_DIG2] = {
5123 .mixers = { alc880_asus_mixer },
5124 .init_verbs = { alc880_volume_init_verbs,
5125 alc880_pin_asus_init_verbs,
5126 alc880_gpio2_init_verbs }, /* use GPIO2 */
5127 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5128 .dac_nids = alc880_asus_dac_nids,
5129 .dig_out_nid = ALC880_DIGOUT_NID,
5130 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
5131 .channel_mode = alc880_asus_modes,
5132 .need_dac_fix = 1,
5133 .input_mux = &alc880_capture_source,
5135 [ALC880_ASUS_W1V] = {
5136 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
5137 .init_verbs = { alc880_volume_init_verbs,
5138 alc880_pin_asus_init_verbs,
5139 alc880_gpio1_init_verbs },
5140 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5141 .dac_nids = alc880_asus_dac_nids,
5142 .dig_out_nid = ALC880_DIGOUT_NID,
5143 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
5144 .channel_mode = alc880_asus_modes,
5145 .need_dac_fix = 1,
5146 .input_mux = &alc880_capture_source,
5148 [ALC880_UNIWILL_DIG] = {
5149 .mixers = { alc880_asus_mixer },
5150 .init_verbs = { alc880_volume_init_verbs,
5151 alc880_pin_asus_init_verbs },
5152 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5153 .dac_nids = alc880_asus_dac_nids,
5154 .dig_out_nid = ALC880_DIGOUT_NID,
5155 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
5156 .channel_mode = alc880_asus_modes,
5157 .need_dac_fix = 1,
5158 .input_mux = &alc880_capture_source,
5160 [ALC880_UNIWILL] = {
5161 .mixers = { alc880_uniwill_mixer },
5162 .init_verbs = { alc880_volume_init_verbs,
5163 alc880_uniwill_init_verbs },
5164 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5165 .dac_nids = alc880_asus_dac_nids,
5166 .dig_out_nid = ALC880_DIGOUT_NID,
5167 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
5168 .channel_mode = alc880_threestack_modes,
5169 .need_dac_fix = 1,
5170 .input_mux = &alc880_capture_source,
5171 .unsol_event = alc880_uniwill_unsol_event,
5172 .setup = alc880_uniwill_setup,
5173 .init_hook = alc880_uniwill_init_hook,
5175 [ALC880_UNIWILL_P53] = {
5176 .mixers = { alc880_uniwill_p53_mixer },
5177 .init_verbs = { alc880_volume_init_verbs,
5178 alc880_uniwill_p53_init_verbs },
5179 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
5180 .dac_nids = alc880_asus_dac_nids,
5181 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
5182 .channel_mode = alc880_threestack_modes,
5183 .input_mux = &alc880_capture_source,
5184 .unsol_event = alc880_uniwill_p53_unsol_event,
5185 .setup = alc880_uniwill_p53_setup,
5186 .init_hook = alc_hp_automute,
5188 [ALC880_FUJITSU] = {
5189 .mixers = { alc880_fujitsu_mixer },
5190 .init_verbs = { alc880_volume_init_verbs,
5191 alc880_uniwill_p53_init_verbs,
5192 alc880_beep_init_verbs },
5193 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5194 .dac_nids = alc880_dac_nids,
5195 .dig_out_nid = ALC880_DIGOUT_NID,
5196 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
5197 .channel_mode = alc880_2_jack_modes,
5198 .input_mux = &alc880_capture_source,
5199 .unsol_event = alc880_uniwill_p53_unsol_event,
5200 .setup = alc880_uniwill_p53_setup,
5201 .init_hook = alc_hp_automute,
5203 [ALC880_CLEVO] = {
5204 .mixers = { alc880_three_stack_mixer },
5205 .init_verbs = { alc880_volume_init_verbs,
5206 alc880_pin_clevo_init_verbs },
5207 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5208 .dac_nids = alc880_dac_nids,
5209 .hp_nid = 0x03,
5210 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
5211 .channel_mode = alc880_threestack_modes,
5212 .need_dac_fix = 1,
5213 .input_mux = &alc880_capture_source,
5215 [ALC880_LG] = {
5216 .mixers = { alc880_lg_mixer },
5217 .init_verbs = { alc880_volume_init_verbs,
5218 alc880_lg_init_verbs },
5219 .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
5220 .dac_nids = alc880_lg_dac_nids,
5221 .dig_out_nid = ALC880_DIGOUT_NID,
5222 .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
5223 .channel_mode = alc880_lg_ch_modes,
5224 .need_dac_fix = 1,
5225 .input_mux = &alc880_lg_capture_source,
5226 .unsol_event = alc_sku_unsol_event,
5227 .setup = alc880_lg_setup,
5228 .init_hook = alc_hp_automute,
5229 #ifdef CONFIG_SND_HDA_POWER_SAVE
5230 .loopbacks = alc880_lg_loopbacks,
5231 #endif
5233 [ALC880_LG_LW] = {
5234 .mixers = { alc880_lg_lw_mixer },
5235 .init_verbs = { alc880_volume_init_verbs,
5236 alc880_lg_lw_init_verbs },
5237 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5238 .dac_nids = alc880_dac_nids,
5239 .dig_out_nid = ALC880_DIGOUT_NID,
5240 .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
5241 .channel_mode = alc880_lg_lw_modes,
5242 .input_mux = &alc880_lg_lw_capture_source,
5243 .unsol_event = alc_sku_unsol_event,
5244 .setup = alc880_lg_lw_setup,
5245 .init_hook = alc_hp_automute,
5247 [ALC880_MEDION_RIM] = {
5248 .mixers = { alc880_medion_rim_mixer },
5249 .init_verbs = { alc880_volume_init_verbs,
5250 alc880_medion_rim_init_verbs,
5251 alc_gpio2_init_verbs },
5252 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
5253 .dac_nids = alc880_dac_nids,
5254 .dig_out_nid = ALC880_DIGOUT_NID,
5255 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
5256 .channel_mode = alc880_2_jack_modes,
5257 .input_mux = &alc880_medion_rim_capture_source,
5258 .unsol_event = alc880_medion_rim_unsol_event,
5259 .setup = alc880_medion_rim_setup,
5260 .init_hook = alc880_medion_rim_automute,
5262 #ifdef CONFIG_SND_DEBUG
5263 [ALC880_TEST] = {
5264 .mixers = { alc880_test_mixer },
5265 .init_verbs = { alc880_test_init_verbs },
5266 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
5267 .dac_nids = alc880_test_dac_nids,
5268 .dig_out_nid = ALC880_DIGOUT_NID,
5269 .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
5270 .channel_mode = alc880_test_modes,
5271 .input_mux = &alc880_test_capture_source,
5273 #endif
5277 * Automatic parse of I/O pins from the BIOS configuration
5280 enum {
5281 ALC_CTL_WIDGET_VOL,
5282 ALC_CTL_WIDGET_MUTE,
5283 ALC_CTL_BIND_MUTE,
5285 static const struct snd_kcontrol_new alc880_control_templates[] = {
5286 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
5287 HDA_CODEC_MUTE(NULL, 0, 0, 0),
5288 HDA_BIND_MUTE(NULL, 0, 0, 0),
5291 static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
5293 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
5294 return snd_array_new(&spec->kctls);
5297 /* add dynamic controls */
5298 static int add_control(struct alc_spec *spec, int type, const char *name,
5299 int cidx, unsigned long val)
5301 struct snd_kcontrol_new *knew;
5303 knew = alc_kcontrol_new(spec);
5304 if (!knew)
5305 return -ENOMEM;
5306 *knew = alc880_control_templates[type];
5307 knew->name = kstrdup(name, GFP_KERNEL);
5308 if (!knew->name)
5309 return -ENOMEM;
5310 knew->index = cidx;
5311 if (get_amp_nid_(val))
5312 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
5313 knew->private_value = val;
5314 return 0;
5317 static int add_control_with_pfx(struct alc_spec *spec, int type,
5318 const char *pfx, const char *dir,
5319 const char *sfx, int cidx, unsigned long val)
5321 char name[32];
5322 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
5323 return add_control(spec, type, name, cidx, val);
5326 #define add_pb_vol_ctrl(spec, type, pfx, val) \
5327 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
5328 #define add_pb_sw_ctrl(spec, type, pfx, val) \
5329 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
5330 #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
5331 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
5332 #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
5333 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
5335 #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
5336 #define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
5337 #define alc880_is_multi_pin(nid) ((nid) >= 0x18)
5338 #define alc880_multi_pin_idx(nid) ((nid) - 0x18)
5339 #define alc880_idx_to_dac(nid) ((nid) + 0x02)
5340 #define alc880_dac_to_idx(nid) ((nid) - 0x02)
5341 #define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
5342 #define alc880_idx_to_selector(nid) ((nid) + 0x10)
5343 #define ALC880_PIN_CD_NID 0x1c
5345 /* fill in the dac_nids table from the parsed pin configuration */
5346 static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
5347 const struct auto_pin_cfg *cfg)
5349 hda_nid_t nid;
5350 int assigned[4];
5351 int i, j;
5353 memset(assigned, 0, sizeof(assigned));
5354 spec->multiout.dac_nids = spec->private_dac_nids;
5356 /* check the pins hardwired to audio widget */
5357 for (i = 0; i < cfg->line_outs; i++) {
5358 nid = cfg->line_out_pins[i];
5359 if (alc880_is_fixed_pin(nid)) {
5360 int idx = alc880_fixed_pin_idx(nid);
5361 spec->private_dac_nids[i] = alc880_idx_to_dac(idx);
5362 assigned[idx] = 1;
5365 /* left pins can be connect to any audio widget */
5366 for (i = 0; i < cfg->line_outs; i++) {
5367 nid = cfg->line_out_pins[i];
5368 if (alc880_is_fixed_pin(nid))
5369 continue;
5370 /* search for an empty channel */
5371 for (j = 0; j < cfg->line_outs; j++) {
5372 if (!assigned[j]) {
5373 spec->private_dac_nids[i] =
5374 alc880_idx_to_dac(j);
5375 assigned[j] = 1;
5376 break;
5380 spec->multiout.num_dacs = cfg->line_outs;
5381 return 0;
5384 static const char *alc_get_line_out_pfx(struct alc_spec *spec,
5385 bool can_be_master)
5387 struct auto_pin_cfg *cfg = &spec->autocfg;
5389 if (cfg->line_outs == 1 && !spec->multi_ios &&
5390 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
5391 return "Master";
5393 switch (cfg->line_out_type) {
5394 case AUTO_PIN_SPEAKER_OUT:
5395 if (cfg->line_outs == 1)
5396 return "Speaker";
5397 break;
5398 case AUTO_PIN_HP_OUT:
5399 return "Headphone";
5400 default:
5401 if (cfg->line_outs == 1 && !spec->multi_ios)
5402 return "PCM";
5403 break;
5405 return NULL;
5408 /* add playback controls from the parsed DAC table */
5409 static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
5410 const struct auto_pin_cfg *cfg)
5412 static const char * const chname[4] = {
5413 "Front", "Surround", NULL /*CLFE*/, "Side"
5415 const char *pfx = alc_get_line_out_pfx(spec, false);
5416 hda_nid_t nid;
5417 int i, err, noutputs;
5419 noutputs = cfg->line_outs;
5420 if (spec->multi_ios > 0)
5421 noutputs += spec->multi_ios;
5423 for (i = 0; i < noutputs; i++) {
5424 if (!spec->multiout.dac_nids[i])
5425 continue;
5426 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
5427 if (!pfx && i == 2) {
5428 /* Center/LFE */
5429 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
5430 "Center",
5431 HDA_COMPOSE_AMP_VAL(nid, 1, 0,
5432 HDA_OUTPUT));
5433 if (err < 0)
5434 return err;
5435 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
5436 "LFE",
5437 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
5438 HDA_OUTPUT));
5439 if (err < 0)
5440 return err;
5441 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
5442 "Center",
5443 HDA_COMPOSE_AMP_VAL(nid, 1, 2,
5444 HDA_INPUT));
5445 if (err < 0)
5446 return err;
5447 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
5448 "LFE",
5449 HDA_COMPOSE_AMP_VAL(nid, 2, 2,
5450 HDA_INPUT));
5451 if (err < 0)
5452 return err;
5453 } else {
5454 const char *name = pfx;
5455 int index = i;
5456 if (!name) {
5457 name = chname[i];
5458 index = 0;
5460 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
5461 name, index,
5462 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
5463 HDA_OUTPUT));
5464 if (err < 0)
5465 return err;
5466 err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
5467 name, index,
5468 HDA_COMPOSE_AMP_VAL(nid, 3, 2,
5469 HDA_INPUT));
5470 if (err < 0)
5471 return err;
5474 return 0;
5477 /* add playback controls for speaker and HP outputs */
5478 static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
5479 const char *pfx)
5481 hda_nid_t nid;
5482 int err;
5484 if (!pin)
5485 return 0;
5487 if (alc880_is_fixed_pin(pin)) {
5488 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
5489 /* specify the DAC as the extra output */
5490 if (!spec->multiout.hp_nid)
5491 spec->multiout.hp_nid = nid;
5492 else
5493 spec->multiout.extra_out_nid[0] = nid;
5494 /* control HP volume/switch on the output mixer amp */
5495 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
5496 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
5497 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
5498 if (err < 0)
5499 return err;
5500 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
5501 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
5502 if (err < 0)
5503 return err;
5504 } else if (alc880_is_multi_pin(pin)) {
5505 /* set manual connection */
5506 /* we have only a switch on HP-out PIN */
5507 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
5508 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
5509 if (err < 0)
5510 return err;
5512 return 0;
5515 /* create input playback/capture controls for the given pin */
5516 static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
5517 const char *ctlname, int ctlidx,
5518 int idx, hda_nid_t mix_nid)
5520 int err;
5522 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
5523 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
5524 if (err < 0)
5525 return err;
5526 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
5527 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
5528 if (err < 0)
5529 return err;
5530 return 0;
5533 static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
5535 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
5536 return (pincap & AC_PINCAP_IN) != 0;
5539 /* create playback/capture controls for input pins */
5540 static int alc_auto_create_input_ctls(struct hda_codec *codec,
5541 const struct auto_pin_cfg *cfg,
5542 hda_nid_t mixer,
5543 hda_nid_t cap1, hda_nid_t cap2)
5545 struct alc_spec *spec = codec->spec;
5546 struct hda_input_mux *imux = &spec->private_imux[0];
5547 int i, err, idx, type_idx = 0;
5548 const char *prev_label = NULL;
5550 for (i = 0; i < cfg->num_inputs; i++) {
5551 hda_nid_t pin;
5552 const char *label;
5554 pin = cfg->inputs[i].pin;
5555 if (!alc_is_input_pin(codec, pin))
5556 continue;
5558 label = hda_get_autocfg_input_label(codec, cfg, i);
5559 if (prev_label && !strcmp(label, prev_label))
5560 type_idx++;
5561 else
5562 type_idx = 0;
5563 prev_label = label;
5565 if (mixer) {
5566 idx = get_connection_index(codec, mixer, pin);
5567 if (idx >= 0) {
5568 err = new_analog_input(spec, pin,
5569 label, type_idx,
5570 idx, mixer);
5571 if (err < 0)
5572 return err;
5576 if (!cap1)
5577 continue;
5578 idx = get_connection_index(codec, cap1, pin);
5579 if (idx < 0 && cap2)
5580 idx = get_connection_index(codec, cap2, pin);
5581 if (idx >= 0)
5582 snd_hda_add_imux_item(imux, label, idx, NULL);
5584 return 0;
5587 static int alc880_auto_create_input_ctls(struct hda_codec *codec,
5588 const struct auto_pin_cfg *cfg)
5590 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x08, 0x09);
5593 static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
5594 unsigned int pin_type)
5596 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5597 pin_type);
5598 /* unmute pin */
5599 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
5600 AMP_OUT_UNMUTE);
5603 static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
5604 hda_nid_t nid, int pin_type,
5605 int dac_idx)
5607 alc_set_pin_output(codec, nid, pin_type);
5608 /* need the manual connection? */
5609 if (alc880_is_multi_pin(nid)) {
5610 struct alc_spec *spec = codec->spec;
5611 int idx = alc880_multi_pin_idx(nid);
5612 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
5613 AC_VERB_SET_CONNECT_SEL,
5614 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
5618 static int get_pin_type(int line_out_type)
5620 if (line_out_type == AUTO_PIN_HP_OUT)
5621 return PIN_HP;
5622 else
5623 return PIN_OUT;
5626 static void alc880_auto_init_multi_out(struct hda_codec *codec)
5628 struct alc_spec *spec = codec->spec;
5629 int i;
5631 for (i = 0; i < spec->autocfg.line_outs; i++) {
5632 hda_nid_t nid = spec->autocfg.line_out_pins[i];
5633 int pin_type = get_pin_type(spec->autocfg.line_out_type);
5634 alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);
5638 static void alc880_auto_init_extra_out(struct hda_codec *codec)
5640 struct alc_spec *spec = codec->spec;
5641 hda_nid_t pin;
5643 pin = spec->autocfg.speaker_pins[0];
5644 if (pin) /* connect to front */
5645 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
5646 pin = spec->autocfg.hp_pins[0];
5647 if (pin) /* connect to front */
5648 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
5651 static void alc880_auto_init_analog_input(struct hda_codec *codec)
5653 struct alc_spec *spec = codec->spec;
5654 struct auto_pin_cfg *cfg = &spec->autocfg;
5655 int i;
5657 for (i = 0; i < cfg->num_inputs; i++) {
5658 hda_nid_t nid = cfg->inputs[i].pin;
5659 if (alc_is_input_pin(codec, nid)) {
5660 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
5661 if (nid != ALC880_PIN_CD_NID &&
5662 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
5663 snd_hda_codec_write(codec, nid, 0,
5664 AC_VERB_SET_AMP_GAIN_MUTE,
5665 AMP_OUT_MUTE);
5670 static void alc880_auto_init_input_src(struct hda_codec *codec)
5672 struct alc_spec *spec = codec->spec;
5673 int c;
5675 for (c = 0; c < spec->num_adc_nids; c++) {
5676 unsigned int mux_idx;
5677 const struct hda_input_mux *imux;
5678 mux_idx = c >= spec->num_mux_defs ? 0 : c;
5679 imux = &spec->input_mux[mux_idx];
5680 if (!imux->num_items && mux_idx > 0)
5681 imux = &spec->input_mux[0];
5682 if (imux)
5683 snd_hda_codec_write(codec, spec->adc_nids[c], 0,
5684 AC_VERB_SET_CONNECT_SEL,
5685 imux->items[0].index);
5689 static int alc_auto_add_multi_channel_mode(struct hda_codec *codec);
5691 /* parse the BIOS configuration and set up the alc_spec */
5692 /* return 1 if successful, 0 if the proper config is not found,
5693 * or a negative error code
5695 static int alc880_parse_auto_config(struct hda_codec *codec)
5697 struct alc_spec *spec = codec->spec;
5698 int err;
5699 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
5701 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
5702 alc880_ignore);
5703 if (err < 0)
5704 return err;
5705 if (!spec->autocfg.line_outs)
5706 return 0; /* can't find valid BIOS pin config */
5708 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
5709 if (err < 0)
5710 return err;
5711 err = alc_auto_add_multi_channel_mode(codec);
5712 if (err < 0)
5713 return err;
5714 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
5715 if (err < 0)
5716 return err;
5717 err = alc880_auto_create_extra_out(spec,
5718 spec->autocfg.speaker_pins[0],
5719 "Speaker");
5720 if (err < 0)
5721 return err;
5722 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
5723 "Headphone");
5724 if (err < 0)
5725 return err;
5726 err = alc880_auto_create_input_ctls(codec, &spec->autocfg);
5727 if (err < 0)
5728 return err;
5730 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
5732 alc_auto_parse_digital(codec);
5734 if (spec->kctls.list)
5735 add_mixer(spec, spec->kctls.list);
5737 add_verb(spec, alc880_volume_init_verbs);
5739 spec->num_mux_defs = 1;
5740 spec->input_mux = &spec->private_imux[0];
5742 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
5744 return 1;
5747 /* additional initialization for auto-configuration model */
5748 static void alc880_auto_init(struct hda_codec *codec)
5750 struct alc_spec *spec = codec->spec;
5751 alc880_auto_init_multi_out(codec);
5752 alc880_auto_init_extra_out(codec);
5753 alc880_auto_init_analog_input(codec);
5754 alc880_auto_init_input_src(codec);
5755 alc_auto_init_digital(codec);
5756 if (spec->unsol_event)
5757 alc_inithook(codec);
5760 /* check the ADC/MUX contains all input pins; some ADC/MUX contains only
5761 * one of two digital mic pins, e.g. on ALC272
5763 static void fixup_automic_adc(struct hda_codec *codec)
5765 struct alc_spec *spec = codec->spec;
5766 int i;
5768 for (i = 0; i < spec->num_adc_nids; i++) {
5769 hda_nid_t cap = spec->capsrc_nids ?
5770 spec->capsrc_nids[i] : spec->adc_nids[i];
5771 int iidx, eidx;
5773 iidx = get_connection_index(codec, cap, spec->int_mic.pin);
5774 if (iidx < 0)
5775 continue;
5776 eidx = get_connection_index(codec, cap, spec->ext_mic.pin);
5777 if (eidx < 0)
5778 continue;
5779 spec->int_mic.mux_idx = iidx;
5780 spec->ext_mic.mux_idx = eidx;
5781 if (spec->capsrc_nids)
5782 spec->capsrc_nids += i;
5783 spec->adc_nids += i;
5784 spec->num_adc_nids = 1;
5785 /* optional dock-mic */
5786 eidx = get_connection_index(codec, cap, spec->dock_mic.pin);
5787 if (eidx < 0)
5788 spec->dock_mic.pin = 0;
5789 else
5790 spec->dock_mic.mux_idx = eidx;
5791 return;
5793 snd_printd(KERN_INFO "hda_codec: %s: "
5794 "No ADC/MUX containing both 0x%x and 0x%x pins\n",
5795 codec->chip_name, spec->int_mic.pin, spec->ext_mic.pin);
5796 spec->auto_mic = 0; /* disable auto-mic to be sure */
5799 /* select or unmute the given capsrc route */
5800 static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
5801 int idx)
5803 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
5804 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
5805 HDA_AMP_MUTE, 0);
5806 } else {
5807 snd_hda_codec_write_cache(codec, cap, 0,
5808 AC_VERB_SET_CONNECT_SEL, idx);
5812 /* set the default connection to that pin */
5813 static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
5815 struct alc_spec *spec = codec->spec;
5816 int i;
5818 if (!pin)
5819 return 0;
5820 for (i = 0; i < spec->num_adc_nids; i++) {
5821 hda_nid_t cap = spec->capsrc_nids ?
5822 spec->capsrc_nids[i] : spec->adc_nids[i];
5823 int idx;
5825 idx = get_connection_index(codec, cap, pin);
5826 if (idx < 0)
5827 continue;
5828 select_or_unmute_capsrc(codec, cap, idx);
5829 return i; /* return the found index */
5831 return -1; /* not found */
5834 /* choose the ADC/MUX containing the input pin and initialize the setup */
5835 static void fixup_single_adc(struct hda_codec *codec)
5837 struct alc_spec *spec = codec->spec;
5838 struct auto_pin_cfg *cfg = &spec->autocfg;
5839 int i;
5841 /* search for the input pin; there must be only one */
5842 if (cfg->num_inputs != 1)
5843 return;
5844 i = init_capsrc_for_pin(codec, cfg->inputs[0].pin);
5845 if (i >= 0) {
5846 /* use only this ADC */
5847 if (spec->capsrc_nids)
5848 spec->capsrc_nids += i;
5849 spec->adc_nids += i;
5850 spec->num_adc_nids = 1;
5851 spec->single_input_src = 1;
5855 /* initialize dual adcs */
5856 static void fixup_dual_adc_switch(struct hda_codec *codec)
5858 struct alc_spec *spec = codec->spec;
5859 init_capsrc_for_pin(codec, spec->ext_mic.pin);
5860 init_capsrc_for_pin(codec, spec->dock_mic.pin);
5861 init_capsrc_for_pin(codec, spec->int_mic.pin);
5864 /* initialize some special cases for input sources */
5865 static void alc_init_special_input_src(struct hda_codec *codec)
5867 struct alc_spec *spec = codec->spec;
5868 if (spec->dual_adc_switch)
5869 fixup_dual_adc_switch(codec);
5870 else if (spec->single_input_src)
5871 init_capsrc_for_pin(codec, spec->autocfg.inputs[0].pin);
5874 static void set_capture_mixer(struct hda_codec *codec)
5876 struct alc_spec *spec = codec->spec;
5877 static const struct snd_kcontrol_new *caps[2][3] = {
5878 { alc_capture_mixer_nosrc1,
5879 alc_capture_mixer_nosrc2,
5880 alc_capture_mixer_nosrc3 },
5881 { alc_capture_mixer1,
5882 alc_capture_mixer2,
5883 alc_capture_mixer3 },
5885 if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
5886 int mux = 0;
5887 int num_adcs = spec->num_adc_nids;
5888 if (spec->dual_adc_switch)
5889 num_adcs = 1;
5890 else if (spec->auto_mic)
5891 fixup_automic_adc(codec);
5892 else if (spec->input_mux) {
5893 if (spec->input_mux->num_items > 1)
5894 mux = 1;
5895 else if (spec->input_mux->num_items == 1)
5896 fixup_single_adc(codec);
5898 spec->cap_mixer = caps[mux][num_adcs - 1];
5902 /* fill adc_nids (and capsrc_nids) containing all active input pins */
5903 static void fillup_priv_adc_nids(struct hda_codec *codec, const hda_nid_t *nids,
5904 int num_nids)
5906 struct alc_spec *spec = codec->spec;
5907 struct auto_pin_cfg *cfg = &spec->autocfg;
5908 int n;
5909 hda_nid_t fallback_adc = 0, fallback_cap = 0;
5911 for (n = 0; n < num_nids; n++) {
5912 hda_nid_t adc, cap;
5913 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
5914 int nconns, i, j;
5916 adc = nids[n];
5917 if (get_wcaps_type(get_wcaps(codec, adc)) != AC_WID_AUD_IN)
5918 continue;
5919 cap = adc;
5920 nconns = snd_hda_get_connections(codec, cap, conn,
5921 ARRAY_SIZE(conn));
5922 if (nconns == 1) {
5923 cap = conn[0];
5924 nconns = snd_hda_get_connections(codec, cap, conn,
5925 ARRAY_SIZE(conn));
5927 if (nconns <= 0)
5928 continue;
5929 if (!fallback_adc) {
5930 fallback_adc = adc;
5931 fallback_cap = cap;
5933 for (i = 0; i < cfg->num_inputs; i++) {
5934 hda_nid_t nid = cfg->inputs[i].pin;
5935 for (j = 0; j < nconns; j++) {
5936 if (conn[j] == nid)
5937 break;
5939 if (j >= nconns)
5940 break;
5942 if (i >= cfg->num_inputs) {
5943 int num_adcs = spec->num_adc_nids;
5944 spec->private_adc_nids[num_adcs] = adc;
5945 spec->private_capsrc_nids[num_adcs] = cap;
5946 spec->num_adc_nids++;
5947 spec->adc_nids = spec->private_adc_nids;
5948 if (adc != cap)
5949 spec->capsrc_nids = spec->private_capsrc_nids;
5952 if (!spec->num_adc_nids) {
5953 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
5954 " using fallback 0x%x\n",
5955 codec->chip_name, fallback_adc);
5956 spec->private_adc_nids[0] = fallback_adc;
5957 spec->adc_nids = spec->private_adc_nids;
5958 if (fallback_adc != fallback_cap) {
5959 spec->private_capsrc_nids[0] = fallback_cap;
5960 spec->capsrc_nids = spec->private_adc_nids;
5965 #ifdef CONFIG_SND_HDA_INPUT_BEEP
5966 #define set_beep_amp(spec, nid, idx, dir) \
5967 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
5969 static const struct snd_pci_quirk beep_white_list[] = {
5970 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
5971 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
5972 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
5973 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
5974 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
5978 static inline int has_cdefine_beep(struct hda_codec *codec)
5980 struct alc_spec *spec = codec->spec;
5981 const struct snd_pci_quirk *q;
5982 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
5983 if (q)
5984 return q->value;
5985 return spec->cdefine.enable_pcbeep;
5987 #else
5988 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
5989 #define has_cdefine_beep(codec) 0
5990 #endif
5993 * OK, here we have finally the patch for ALC880
5996 static int patch_alc880(struct hda_codec *codec)
5998 struct alc_spec *spec;
5999 int board_config;
6000 int err;
6002 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6003 if (spec == NULL)
6004 return -ENOMEM;
6006 codec->spec = spec;
6008 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
6009 alc880_models,
6010 alc880_cfg_tbl);
6011 if (board_config < 0) {
6012 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
6013 codec->chip_name);
6014 board_config = ALC880_AUTO;
6017 if (board_config == ALC880_AUTO) {
6018 /* automatic parse from the BIOS config */
6019 err = alc880_parse_auto_config(codec);
6020 if (err < 0) {
6021 alc_free(codec);
6022 return err;
6023 } else if (!err) {
6024 printk(KERN_INFO
6025 "hda_codec: Cannot set up configuration "
6026 "from BIOS. Using 3-stack mode...\n");
6027 board_config = ALC880_3ST;
6031 err = snd_hda_attach_beep_device(codec, 0x1);
6032 if (err < 0) {
6033 alc_free(codec);
6034 return err;
6037 if (board_config != ALC880_AUTO)
6038 setup_preset(codec, &alc880_presets[board_config]);
6040 spec->stream_analog_playback = &alc880_pcm_analog_playback;
6041 spec->stream_analog_capture = &alc880_pcm_analog_capture;
6042 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
6044 spec->stream_digital_playback = &alc880_pcm_digital_playback;
6045 spec->stream_digital_capture = &alc880_pcm_digital_capture;
6047 if (!spec->adc_nids && spec->input_mux) {
6048 /* check whether NID 0x07 is valid */
6049 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
6050 /* get type */
6051 wcap = get_wcaps_type(wcap);
6052 if (wcap != AC_WID_AUD_IN) {
6053 spec->adc_nids = alc880_adc_nids_alt;
6054 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
6055 } else {
6056 spec->adc_nids = alc880_adc_nids;
6057 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
6060 set_capture_mixer(codec);
6061 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
6063 spec->vmaster_nid = 0x0c;
6065 codec->patch_ops = alc_patch_ops;
6066 if (board_config == ALC880_AUTO)
6067 spec->init_hook = alc880_auto_init;
6068 #ifdef CONFIG_SND_HDA_POWER_SAVE
6069 if (!spec->loopback.amplist)
6070 spec->loopback.amplist = alc880_loopbacks;
6071 #endif
6073 return 0;
6078 * ALC260 support
6081 static const hda_nid_t alc260_dac_nids[1] = {
6082 /* front */
6083 0x02,
6086 static const hda_nid_t alc260_adc_nids[1] = {
6087 /* ADC0 */
6088 0x04,
6091 static const hda_nid_t alc260_adc_nids_alt[1] = {
6092 /* ADC1 */
6093 0x05,
6096 /* NIDs used when simultaneous access to both ADCs makes sense. Note that
6097 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
6099 static const hda_nid_t alc260_dual_adc_nids[2] = {
6100 /* ADC0, ADC1 */
6101 0x04, 0x05
6104 #define ALC260_DIGOUT_NID 0x03
6105 #define ALC260_DIGIN_NID 0x06
6107 static const struct hda_input_mux alc260_capture_source = {
6108 .num_items = 4,
6109 .items = {
6110 { "Mic", 0x0 },
6111 { "Front Mic", 0x1 },
6112 { "Line", 0x2 },
6113 { "CD", 0x4 },
6117 /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
6118 * headphone jack and the internal CD lines since these are the only pins at
6119 * which audio can appear. For flexibility, also allow the option of
6120 * recording the mixer output on the second ADC (ADC0 doesn't have a
6121 * connection to the mixer output).
6123 static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
6125 .num_items = 3,
6126 .items = {
6127 { "Mic/Line", 0x0 },
6128 { "CD", 0x4 },
6129 { "Headphone", 0x2 },
6133 .num_items = 4,
6134 .items = {
6135 { "Mic/Line", 0x0 },
6136 { "CD", 0x4 },
6137 { "Headphone", 0x2 },
6138 { "Mixer", 0x5 },
6144 /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
6145 * the Fujitsu S702x, but jacks are marked differently.
6147 static const struct hda_input_mux alc260_acer_capture_sources[2] = {
6149 .num_items = 4,
6150 .items = {
6151 { "Mic", 0x0 },
6152 { "Line", 0x2 },
6153 { "CD", 0x4 },
6154 { "Headphone", 0x5 },
6158 .num_items = 5,
6159 .items = {
6160 { "Mic", 0x0 },
6161 { "Line", 0x2 },
6162 { "CD", 0x4 },
6163 { "Headphone", 0x6 },
6164 { "Mixer", 0x5 },
6169 /* Maxdata Favorit 100XS */
6170 static const struct hda_input_mux alc260_favorit100_capture_sources[2] = {
6172 .num_items = 2,
6173 .items = {
6174 { "Line/Mic", 0x0 },
6175 { "CD", 0x4 },
6179 .num_items = 3,
6180 .items = {
6181 { "Line/Mic", 0x0 },
6182 { "CD", 0x4 },
6183 { "Mixer", 0x5 },
6189 * This is just place-holder, so there's something for alc_build_pcms to look
6190 * at when it calculates the maximum number of channels. ALC260 has no mixer
6191 * element which allows changing the channel mode, so the verb list is
6192 * never used.
6194 static const struct hda_channel_mode alc260_modes[1] = {
6195 { 2, NULL },
6199 /* Mixer combinations
6201 * basic: base_output + input + pc_beep + capture
6202 * HP: base_output + input + capture_alt
6203 * HP_3013: hp_3013 + input + capture
6204 * fujitsu: fujitsu + capture
6205 * acer: acer + capture
6208 static const struct snd_kcontrol_new alc260_base_output_mixer[] = {
6209 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6210 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
6211 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6212 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
6213 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
6214 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
6215 { } /* end */
6218 static const struct snd_kcontrol_new alc260_input_mixer[] = {
6219 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6220 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
6221 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
6222 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
6223 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
6224 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
6225 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
6226 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
6227 { } /* end */
6230 /* update HP, line and mono out pins according to the master switch */
6231 static void alc260_hp_master_update(struct hda_codec *codec)
6233 update_speakers(codec);
6236 static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
6237 struct snd_ctl_elem_value *ucontrol)
6239 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
6240 struct alc_spec *spec = codec->spec;
6241 *ucontrol->value.integer.value = !spec->master_mute;
6242 return 0;
6245 static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
6246 struct snd_ctl_elem_value *ucontrol)
6248 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
6249 struct alc_spec *spec = codec->spec;
6250 int val = !*ucontrol->value.integer.value;
6252 if (val == spec->master_mute)
6253 return 0;
6254 spec->master_mute = val;
6255 alc260_hp_master_update(codec);
6256 return 1;
6259 static const struct snd_kcontrol_new alc260_hp_output_mixer[] = {
6261 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6262 .name = "Master Playback Switch",
6263 .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
6264 .info = snd_ctl_boolean_mono_info,
6265 .get = alc260_hp_master_sw_get,
6266 .put = alc260_hp_master_sw_put,
6268 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6269 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
6270 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6271 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
6272 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
6273 HDA_OUTPUT),
6274 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT),
6275 { } /* end */
6278 static const struct hda_verb alc260_hp_unsol_verbs[] = {
6279 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6283 static void alc260_hp_setup(struct hda_codec *codec)
6285 struct alc_spec *spec = codec->spec;
6287 spec->autocfg.hp_pins[0] = 0x0f;
6288 spec->autocfg.speaker_pins[0] = 0x10;
6289 spec->autocfg.speaker_pins[1] = 0x11;
6290 spec->automute = 1;
6291 spec->automute_mode = ALC_AUTOMUTE_PIN;
6294 static const struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
6296 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6297 .name = "Master Playback Switch",
6298 .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
6299 .info = snd_ctl_boolean_mono_info,
6300 .get = alc260_hp_master_sw_get,
6301 .put = alc260_hp_master_sw_put,
6303 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6304 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
6305 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
6306 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
6307 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6308 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6309 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
6310 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
6311 { } /* end */
6314 static void alc260_hp_3013_setup(struct hda_codec *codec)
6316 struct alc_spec *spec = codec->spec;
6318 spec->autocfg.hp_pins[0] = 0x15;
6319 spec->autocfg.speaker_pins[0] = 0x10;
6320 spec->autocfg.speaker_pins[1] = 0x11;
6321 spec->automute = 1;
6322 spec->automute_mode = ALC_AUTOMUTE_PIN;
6325 static const struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
6326 .ops = &snd_hda_bind_vol,
6327 .values = {
6328 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_OUTPUT),
6329 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
6330 HDA_COMPOSE_AMP_VAL(0x0a, 3, 0, HDA_OUTPUT),
6335 static const struct hda_bind_ctls alc260_dc7600_bind_switch = {
6336 .ops = &snd_hda_bind_sw,
6337 .values = {
6338 HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
6339 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
6344 static const struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
6345 HDA_BIND_VOL("Master Playback Volume", &alc260_dc7600_bind_master_vol),
6346 HDA_BIND_SW("LineOut Playback Switch", &alc260_dc7600_bind_switch),
6347 HDA_CODEC_MUTE("Speaker Playback Switch", 0x0f, 0x0, HDA_OUTPUT),
6348 HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
6349 { } /* end */
6352 static const struct hda_verb alc260_hp_3013_unsol_verbs[] = {
6353 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6357 static void alc260_hp_3012_setup(struct hda_codec *codec)
6359 struct alc_spec *spec = codec->spec;
6361 spec->autocfg.hp_pins[0] = 0x10;
6362 spec->autocfg.speaker_pins[0] = 0x0f;
6363 spec->autocfg.speaker_pins[1] = 0x11;
6364 spec->autocfg.speaker_pins[2] = 0x15;
6365 spec->automute = 1;
6366 spec->automute_mode = ALC_AUTOMUTE_PIN;
6369 /* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
6370 * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
6372 static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
6373 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6374 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
6375 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
6376 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6377 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
6378 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
6379 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
6380 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
6381 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6382 HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
6383 { } /* end */
6386 /* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current
6387 * versions of the ALC260 don't act on requests to enable mic bias from NID
6388 * 0x0f (used to drive the headphone jack in these laptops). The ALC260
6389 * datasheet doesn't mention this restriction. At this stage it's not clear
6390 * whether this behaviour is intentional or is a hardware bug in chip
6391 * revisions available in early 2006. Therefore for now allow the
6392 * "Headphone Jack Mode" control to span all choices, but if it turns out
6393 * that the lack of mic bias for this NID is intentional we could change the
6394 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
6396 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
6397 * don't appear to make the mic bias available from the "line" jack, even
6398 * though the NID used for this jack (0x14) can supply it. The theory is
6399 * that perhaps Acer have included blocking capacitors between the ALC260
6400 * and the output jack. If this turns out to be the case for all such
6401 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
6402 * to ALC_PIN_DIR_INOUT_NOMICBIAS.
6404 * The C20x Tablet series have a mono internal speaker which is controlled
6405 * via the chip's Mono sum widget and pin complex, so include the necessary
6406 * controls for such models. On models without a "mono speaker" the control
6407 * won't do anything.
6409 static const struct snd_kcontrol_new alc260_acer_mixer[] = {
6410 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6411 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
6412 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
6413 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
6414 HDA_OUTPUT),
6415 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
6416 HDA_INPUT),
6417 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6418 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
6419 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
6420 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
6421 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
6422 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
6423 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
6424 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
6425 { } /* end */
6428 /* Maxdata Favorit 100XS: one output and one input (0x12) jack
6430 static const struct snd_kcontrol_new alc260_favorit100_mixer[] = {
6431 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6432 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
6433 ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
6434 HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
6435 HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
6436 ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
6437 { } /* end */
6440 /* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
6441 * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17.
6443 static const struct snd_kcontrol_new alc260_will_mixer[] = {
6444 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6445 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
6446 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
6447 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
6448 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
6449 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
6450 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
6451 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
6452 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6453 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
6454 { } /* end */
6457 /* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
6458 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
6460 static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
6461 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6462 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
6463 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
6464 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
6465 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
6466 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
6467 HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
6468 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
6469 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
6470 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
6471 { } /* end */
6475 * initialization verbs
6477 static const struct hda_verb alc260_init_verbs[] = {
6478 /* Line In pin widget for input */
6479 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6480 /* CD pin widget for input */
6481 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6482 /* Mic1 (rear panel) pin widget for input and vref at 80% */
6483 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
6484 /* Mic2 (front panel) pin widget for input and vref at 80% */
6485 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
6486 /* LINE-2 is used for line-out in rear */
6487 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6488 /* select line-out */
6489 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
6490 /* LINE-OUT pin */
6491 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6492 /* enable HP */
6493 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6494 /* enable Mono */
6495 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6496 /* mute capture amp left and right */
6497 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6498 /* set connection select to line in (default select for this ADC) */
6499 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
6500 /* mute capture amp left and right */
6501 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6502 /* set connection select to line in (default select for this ADC) */
6503 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
6504 /* set vol=0 Line-Out mixer amp left and right */
6505 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6506 /* unmute pin widget amp left and right (no gain on this amp) */
6507 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6508 /* set vol=0 HP mixer amp left and right */
6509 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6510 /* unmute pin widget amp left and right (no gain on this amp) */
6511 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6512 /* set vol=0 Mono mixer amp left and right */
6513 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6514 /* unmute pin widget amp left and right (no gain on this amp) */
6515 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6516 /* unmute LINE-2 out pin */
6517 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6518 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
6519 * Line In 2 = 0x03
6521 /* mute analog inputs */
6522 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6523 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6524 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6525 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6526 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
6527 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
6528 /* mute Front out path */
6529 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6530 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6531 /* mute Headphone out path */
6532 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6533 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6534 /* mute Mono out path */
6535 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6536 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6540 #if 0 /* should be identical with alc260_init_verbs? */
6541 static const struct hda_verb alc260_hp_init_verbs[] = {
6542 /* Headphone and output */
6543 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6544 /* mono output */
6545 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6546 /* Mic1 (rear panel) pin widget for input and vref at 80% */
6547 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6548 /* Mic2 (front panel) pin widget for input and vref at 80% */
6549 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6550 /* Line In pin widget for input */
6551 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6552 /* Line-2 pin widget for output */
6553 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6554 /* CD pin widget for input */
6555 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6556 /* unmute amp left and right */
6557 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
6558 /* set connection select to line in (default select for this ADC) */
6559 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
6560 /* unmute Line-Out mixer amp left and right (volume = 0) */
6561 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
6562 /* mute pin widget amp left and right (no gain on this amp) */
6563 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6564 /* unmute HP mixer amp left and right (volume = 0) */
6565 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
6566 /* mute pin widget amp left and right (no gain on this amp) */
6567 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6568 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
6569 * Line In 2 = 0x03
6571 /* mute analog inputs */
6572 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6573 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6574 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6575 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6576 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
6577 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
6578 /* Unmute Front out path */
6579 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6580 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6581 /* Unmute Headphone out path */
6582 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6583 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6584 /* Unmute Mono out path */
6585 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6586 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6589 #endif
6591 static const struct hda_verb alc260_hp_3013_init_verbs[] = {
6592 /* Line out and output */
6593 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6594 /* mono output */
6595 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6596 /* Mic1 (rear panel) pin widget for input and vref at 80% */
6597 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6598 /* Mic2 (front panel) pin widget for input and vref at 80% */
6599 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6600 /* Line In pin widget for input */
6601 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6602 /* Headphone pin widget for output */
6603 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6604 /* CD pin widget for input */
6605 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6606 /* unmute amp left and right */
6607 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
6608 /* set connection select to line in (default select for this ADC) */
6609 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
6610 /* unmute Line-Out mixer amp left and right (volume = 0) */
6611 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
6612 /* mute pin widget amp left and right (no gain on this amp) */
6613 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6614 /* unmute HP mixer amp left and right (volume = 0) */
6615 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
6616 /* mute pin widget amp left and right (no gain on this amp) */
6617 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6618 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
6619 * Line In 2 = 0x03
6621 /* mute analog inputs */
6622 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6623 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6624 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6625 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6626 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
6627 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
6628 /* Unmute Front out path */
6629 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6630 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6631 /* Unmute Headphone out path */
6632 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6633 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6634 /* Unmute Mono out path */
6635 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6636 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6640 /* Initialisation sequence for ALC260 as configured in Fujitsu S702x
6641 * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
6642 * audio = 0x16, internal speaker = 0x10.
6644 static const struct hda_verb alc260_fujitsu_init_verbs[] = {
6645 /* Disable all GPIOs */
6646 {0x01, AC_VERB_SET_GPIO_MASK, 0},
6647 /* Internal speaker is connected to headphone pin */
6648 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6649 /* Headphone/Line-out jack connects to Line1 pin; make it an output */
6650 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6651 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
6652 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6653 /* Ensure all other unused pins are disabled and muted. */
6654 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6655 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6656 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6657 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6658 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6659 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6660 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6661 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6663 /* Disable digital (SPDIF) pins */
6664 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6665 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6667 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
6668 * when acting as an output.
6670 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6672 /* Start with output sum widgets muted and their output gains at min */
6673 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6674 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6675 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6676 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6677 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6678 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6679 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6680 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6681 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6683 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
6684 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6685 /* Unmute Line1 pin widget output buffer since it starts as an output.
6686 * If the pin mode is changed by the user the pin mode control will
6687 * take care of enabling the pin's input/output buffers as needed.
6688 * Therefore there's no need to enable the input buffer at this
6689 * stage.
6691 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6692 /* Unmute input buffer of pin widget used for Line-in (no equiv
6693 * mixer ctrl)
6695 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6697 /* Mute capture amp left and right */
6698 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6699 /* Set ADC connection select to match default mixer setting - line
6700 * in (on mic1 pin)
6702 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6704 /* Do the same for the second ADC: mute capture input amp and
6705 * set ADC connection to line in (on mic1 pin)
6707 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6708 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6710 /* Mute all inputs to mixer widget (even unconnected ones) */
6711 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6712 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6713 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6714 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6715 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6716 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6717 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6718 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6723 /* Initialisation sequence for ALC260 as configured in Acer TravelMate and
6724 * similar laptops (adapted from Fujitsu init verbs).
6726 static const struct hda_verb alc260_acer_init_verbs[] = {
6727 /* On TravelMate laptops, GPIO 0 enables the internal speaker and
6728 * the headphone jack. Turn this on and rely on the standard mute
6729 * methods whenever the user wants to turn these outputs off.
6731 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
6732 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6733 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
6734 /* Internal speaker/Headphone jack is connected to Line-out pin */
6735 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6736 /* Internal microphone/Mic jack is connected to Mic1 pin */
6737 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
6738 /* Line In jack is connected to Line1 pin */
6739 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6740 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
6741 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6742 /* Ensure all other unused pins are disabled and muted. */
6743 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6744 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6745 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6746 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6747 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6748 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6749 /* Disable digital (SPDIF) pins */
6750 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6751 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6753 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
6754 * bus when acting as outputs.
6756 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
6757 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6759 /* Start with output sum widgets muted and their output gains at min */
6760 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6761 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6762 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6763 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6764 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6765 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6766 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6767 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6768 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6770 /* Unmute Line-out pin widget amp left and right
6771 * (no equiv mixer ctrl)
6773 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6774 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */
6775 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6776 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
6777 * inputs. If the pin mode is changed by the user the pin mode control
6778 * will take care of enabling the pin's input/output buffers as needed.
6779 * Therefore there's no need to enable the input buffer at this
6780 * stage.
6782 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6783 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6785 /* Mute capture amp left and right */
6786 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6787 /* Set ADC connection select to match default mixer setting - mic
6788 * (on mic1 pin)
6790 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6792 /* Do similar with the second ADC: mute capture input amp and
6793 * set ADC connection to mic to match ALSA's default state.
6795 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6796 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6798 /* Mute all inputs to mixer widget (even unconnected ones) */
6799 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6800 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6801 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6802 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6803 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6804 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6805 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6806 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6811 /* Initialisation sequence for Maxdata Favorit 100XS
6812 * (adapted from Acer init verbs).
6814 static const struct hda_verb alc260_favorit100_init_verbs[] = {
6815 /* GPIO 0 enables the output jack.
6816 * Turn this on and rely on the standard mute
6817 * methods whenever the user wants to turn these outputs off.
6819 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
6820 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6821 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
6822 /* Line/Mic input jack is connected to Mic1 pin */
6823 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
6824 /* Ensure all other unused pins are disabled and muted. */
6825 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6826 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6827 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6828 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6829 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6830 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6831 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6832 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6833 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6834 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6835 /* Disable digital (SPDIF) pins */
6836 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6837 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6839 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
6840 * bus when acting as outputs.
6842 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
6843 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6845 /* Start with output sum widgets muted and their output gains at min */
6846 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6847 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6848 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6849 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6850 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6851 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6852 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6853 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6854 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6856 /* Unmute Line-out pin widget amp left and right
6857 * (no equiv mixer ctrl)
6859 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6860 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
6861 * inputs. If the pin mode is changed by the user the pin mode control
6862 * will take care of enabling the pin's input/output buffers as needed.
6863 * Therefore there's no need to enable the input buffer at this
6864 * stage.
6866 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6868 /* Mute capture amp left and right */
6869 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6870 /* Set ADC connection select to match default mixer setting - mic
6871 * (on mic1 pin)
6873 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6875 /* Do similar with the second ADC: mute capture input amp and
6876 * set ADC connection to mic to match ALSA's default state.
6878 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6879 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6881 /* Mute all inputs to mixer widget (even unconnected ones) */
6882 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6883 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6884 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6885 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6886 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6887 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6888 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6889 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6894 static const struct hda_verb alc260_will_verbs[] = {
6895 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6896 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
6897 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
6898 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
6899 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
6900 {0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
6904 static const struct hda_verb alc260_replacer_672v_verbs[] = {
6905 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
6906 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
6907 {0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
6909 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
6910 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6911 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
6913 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6917 /* toggle speaker-output according to the hp-jack state */
6918 static void alc260_replacer_672v_automute(struct hda_codec *codec)
6920 unsigned int present;
6922 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
6923 present = snd_hda_jack_detect(codec, 0x0f);
6924 if (present) {
6925 snd_hda_codec_write_cache(codec, 0x01, 0,
6926 AC_VERB_SET_GPIO_DATA, 1);
6927 snd_hda_codec_write_cache(codec, 0x0f, 0,
6928 AC_VERB_SET_PIN_WIDGET_CONTROL,
6929 PIN_HP);
6930 } else {
6931 snd_hda_codec_write_cache(codec, 0x01, 0,
6932 AC_VERB_SET_GPIO_DATA, 0);
6933 snd_hda_codec_write_cache(codec, 0x0f, 0,
6934 AC_VERB_SET_PIN_WIDGET_CONTROL,
6935 PIN_OUT);
6939 static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
6940 unsigned int res)
6942 if ((res >> 26) == ALC880_HP_EVENT)
6943 alc260_replacer_672v_automute(codec);
6946 static const struct hda_verb alc260_hp_dc7600_verbs[] = {
6947 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
6948 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
6949 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6950 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6951 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6952 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6953 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
6954 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6955 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6956 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6960 /* Test configuration for debugging, modelled after the ALC880 test
6961 * configuration.
6963 #ifdef CONFIG_SND_DEBUG
6964 static const hda_nid_t alc260_test_dac_nids[1] = {
6965 0x02,
6967 static const hda_nid_t alc260_test_adc_nids[2] = {
6968 0x04, 0x05,
6970 /* For testing the ALC260, each input MUX needs its own definition since
6971 * the signal assignments are different. This assumes that the first ADC
6972 * is NID 0x04.
6974 static const struct hda_input_mux alc260_test_capture_sources[2] = {
6976 .num_items = 7,
6977 .items = {
6978 { "MIC1 pin", 0x0 },
6979 { "MIC2 pin", 0x1 },
6980 { "LINE1 pin", 0x2 },
6981 { "LINE2 pin", 0x3 },
6982 { "CD pin", 0x4 },
6983 { "LINE-OUT pin", 0x5 },
6984 { "HP-OUT pin", 0x6 },
6988 .num_items = 8,
6989 .items = {
6990 { "MIC1 pin", 0x0 },
6991 { "MIC2 pin", 0x1 },
6992 { "LINE1 pin", 0x2 },
6993 { "LINE2 pin", 0x3 },
6994 { "CD pin", 0x4 },
6995 { "Mixer", 0x5 },
6996 { "LINE-OUT pin", 0x6 },
6997 { "HP-OUT pin", 0x7 },
7001 static const struct snd_kcontrol_new alc260_test_mixer[] = {
7002 /* Output driver widgets */
7003 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
7004 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
7005 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
7006 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
7007 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
7008 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
7010 /* Modes for retasking pin widgets
7011 * Note: the ALC260 doesn't seem to act on requests to enable mic
7012 * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't
7013 * mention this restriction. At this stage it's not clear whether
7014 * this behaviour is intentional or is a hardware bug in chip
7015 * revisions available at least up until early 2006. Therefore for
7016 * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
7017 * choices, but if it turns out that the lack of mic bias for these
7018 * NIDs is intentional we could change their modes from
7019 * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
7021 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
7022 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
7023 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
7024 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
7025 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
7026 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
7028 /* Loopback mixer controls */
7029 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
7030 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
7031 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
7032 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
7033 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
7034 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
7035 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
7036 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
7037 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
7038 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
7039 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
7040 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
7041 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
7042 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
7044 /* Controls for GPIO pins, assuming they are configured as outputs */
7045 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
7046 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
7047 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
7048 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
7050 /* Switches to allow the digital IO pins to be enabled. The datasheet
7051 * is ambigious as to which NID is which; testing on laptops which
7052 * make this output available should provide clarification.
7054 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
7055 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
7057 /* A switch allowing EAPD to be enabled. Some laptops seem to use
7058 * this output to turn on an external amplifier.
7060 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
7061 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
7063 { } /* end */
7065 static const struct hda_verb alc260_test_init_verbs[] = {
7066 /* Enable all GPIOs as outputs with an initial value of 0 */
7067 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
7068 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
7069 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
7071 /* Enable retasking pins as output, initially without power amp */
7072 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7073 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7074 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7075 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7076 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7077 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7079 /* Disable digital (SPDIF) pins initially, but users can enable
7080 * them via a mixer switch. In the case of SPDIF-out, this initverb
7081 * payload also sets the generation to 0, output to be in "consumer"
7082 * PCM format, copyright asserted, no pre-emphasis and no validity
7083 * control.
7085 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
7086 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
7088 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
7089 * OUT1 sum bus when acting as an output.
7091 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
7092 {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
7093 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
7094 {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
7096 /* Start with output sum widgets muted and their output gains at min */
7097 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7098 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7099 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7100 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7101 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7102 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7103 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7104 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7105 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7107 /* Unmute retasking pin widget output buffers since the default
7108 * state appears to be output. As the pin mode is changed by the
7109 * user the pin mode control will take care of enabling the pin's
7110 * input/output buffers as needed.
7112 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7113 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7114 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7115 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7116 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7117 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7118 /* Also unmute the mono-out pin widget */
7119 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7121 /* Mute capture amp left and right */
7122 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7123 /* Set ADC connection select to match default mixer setting (mic1
7124 * pin)
7126 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
7128 /* Do the same for the second ADC: mute capture input amp and
7129 * set ADC connection to mic1 pin
7131 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7132 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
7134 /* Mute all inputs to mixer widget (even unconnected ones) */
7135 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
7136 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
7137 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
7138 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
7139 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
7140 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
7141 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
7142 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
7146 #endif
7148 #define alc260_pcm_analog_playback alc880_pcm_analog_alt_playback
7149 #define alc260_pcm_analog_capture alc880_pcm_analog_capture
7151 #define alc260_pcm_digital_playback alc880_pcm_digital_playback
7152 #define alc260_pcm_digital_capture alc880_pcm_digital_capture
7155 * for BIOS auto-configuration
7158 static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
7159 const char *pfx, int *vol_bits)
7161 hda_nid_t nid_vol;
7162 unsigned long vol_val, sw_val;
7163 int err;
7165 if (nid >= 0x0f && nid < 0x11) {
7166 nid_vol = nid - 0x7;
7167 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
7168 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
7169 } else if (nid == 0x11) {
7170 nid_vol = nid - 0x7;
7171 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
7172 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
7173 } else if (nid >= 0x12 && nid <= 0x15) {
7174 nid_vol = 0x08;
7175 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
7176 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
7177 } else
7178 return 0; /* N/A */
7180 if (!(*vol_bits & (1 << nid_vol))) {
7181 /* first control for the volume widget */
7182 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
7183 if (err < 0)
7184 return err;
7185 *vol_bits |= (1 << nid_vol);
7187 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
7188 if (err < 0)
7189 return err;
7190 return 1;
7193 /* add playback controls from the parsed DAC table */
7194 static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
7195 const struct auto_pin_cfg *cfg)
7197 hda_nid_t nid;
7198 int err;
7199 int vols = 0;
7201 spec->multiout.num_dacs = 1;
7202 spec->multiout.dac_nids = spec->private_dac_nids;
7203 spec->private_dac_nids[0] = 0x02;
7205 nid = cfg->line_out_pins[0];
7206 if (nid) {
7207 const char *pfx;
7208 if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
7209 pfx = "Master";
7210 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
7211 pfx = "Speaker";
7212 else
7213 pfx = "Front";
7214 err = alc260_add_playback_controls(spec, nid, pfx, &vols);
7215 if (err < 0)
7216 return err;
7219 nid = cfg->speaker_pins[0];
7220 if (nid) {
7221 err = alc260_add_playback_controls(spec, nid, "Speaker", &vols);
7222 if (err < 0)
7223 return err;
7226 nid = cfg->hp_pins[0];
7227 if (nid) {
7228 err = alc260_add_playback_controls(spec, nid, "Headphone",
7229 &vols);
7230 if (err < 0)
7231 return err;
7233 return 0;
7236 /* create playback/capture controls for input pins */
7237 static int alc260_auto_create_input_ctls(struct hda_codec *codec,
7238 const struct auto_pin_cfg *cfg)
7240 return alc_auto_create_input_ctls(codec, cfg, 0x07, 0x04, 0x05);
7243 static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
7244 hda_nid_t nid, int pin_type,
7245 int sel_idx)
7247 alc_set_pin_output(codec, nid, pin_type);
7248 /* need the manual connection? */
7249 if (nid >= 0x12) {
7250 int idx = nid - 0x12;
7251 snd_hda_codec_write(codec, idx + 0x0b, 0,
7252 AC_VERB_SET_CONNECT_SEL, sel_idx);
7256 static void alc260_auto_init_multi_out(struct hda_codec *codec)
7258 struct alc_spec *spec = codec->spec;
7259 hda_nid_t nid;
7261 nid = spec->autocfg.line_out_pins[0];
7262 if (nid) {
7263 int pin_type = get_pin_type(spec->autocfg.line_out_type);
7264 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
7267 nid = spec->autocfg.speaker_pins[0];
7268 if (nid)
7269 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
7271 nid = spec->autocfg.hp_pins[0];
7272 if (nid)
7273 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
7276 #define ALC260_PIN_CD_NID 0x16
7277 static void alc260_auto_init_analog_input(struct hda_codec *codec)
7279 struct alc_spec *spec = codec->spec;
7280 struct auto_pin_cfg *cfg = &spec->autocfg;
7281 int i;
7283 for (i = 0; i < cfg->num_inputs; i++) {
7284 hda_nid_t nid = cfg->inputs[i].pin;
7285 if (nid >= 0x12) {
7286 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
7287 if (nid != ALC260_PIN_CD_NID &&
7288 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
7289 snd_hda_codec_write(codec, nid, 0,
7290 AC_VERB_SET_AMP_GAIN_MUTE,
7291 AMP_OUT_MUTE);
7296 #define alc260_auto_init_input_src alc880_auto_init_input_src
7299 * generic initialization of ADC, input mixers and output mixers
7301 static const struct hda_verb alc260_volume_init_verbs[] = {
7303 * Unmute ADC0-1 and set the default input to mic-in
7305 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
7306 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7307 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
7308 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7310 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
7311 * mixer widget
7312 * Note: PASD motherboards uses the Line In 2 as the input for
7313 * front panel mic (mic 2)
7315 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
7316 /* mute analog inputs */
7317 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7318 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7319 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7320 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7321 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7324 * Set up output mixers (0x08 - 0x0a)
7326 /* set vol=0 to output mixers */
7327 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7328 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7329 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7330 /* set up input amps for analog loopback */
7331 /* Amp Indices: DAC = 0, mixer = 1 */
7332 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7333 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7334 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7335 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7336 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7337 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7342 static int alc260_parse_auto_config(struct hda_codec *codec)
7344 struct alc_spec *spec = codec->spec;
7345 int err;
7346 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
7348 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
7349 alc260_ignore);
7350 if (err < 0)
7351 return err;
7352 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
7353 if (err < 0)
7354 return err;
7355 if (!spec->kctls.list)
7356 return 0; /* can't find valid BIOS pin config */
7357 err = alc260_auto_create_input_ctls(codec, &spec->autocfg);
7358 if (err < 0)
7359 return err;
7361 spec->multiout.max_channels = 2;
7363 if (spec->autocfg.dig_outs)
7364 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
7365 if (spec->kctls.list)
7366 add_mixer(spec, spec->kctls.list);
7368 add_verb(spec, alc260_volume_init_verbs);
7370 spec->num_mux_defs = 1;
7371 spec->input_mux = &spec->private_imux[0];
7373 alc_ssid_check(codec, 0x10, 0x15, 0x0f, 0);
7375 return 1;
7378 /* additional initialization for auto-configuration model */
7379 static void alc260_auto_init(struct hda_codec *codec)
7381 struct alc_spec *spec = codec->spec;
7382 alc260_auto_init_multi_out(codec);
7383 alc260_auto_init_analog_input(codec);
7384 alc260_auto_init_input_src(codec);
7385 alc_auto_init_digital(codec);
7386 if (spec->unsol_event)
7387 alc_inithook(codec);
7390 #ifdef CONFIG_SND_HDA_POWER_SAVE
7391 static const struct hda_amp_list alc260_loopbacks[] = {
7392 { 0x07, HDA_INPUT, 0 },
7393 { 0x07, HDA_INPUT, 1 },
7394 { 0x07, HDA_INPUT, 2 },
7395 { 0x07, HDA_INPUT, 3 },
7396 { 0x07, HDA_INPUT, 4 },
7397 { } /* end */
7399 #endif
7402 * Pin config fixes
7404 enum {
7405 PINFIX_HP_DC5750,
7408 static const struct alc_fixup alc260_fixups[] = {
7409 [PINFIX_HP_DC5750] = {
7410 .type = ALC_FIXUP_PINS,
7411 .v.pins = (const struct alc_pincfg[]) {
7412 { 0x11, 0x90130110 }, /* speaker */
7418 static const struct snd_pci_quirk alc260_fixup_tbl[] = {
7419 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
7424 * ALC260 configurations
7426 static const char * const alc260_models[ALC260_MODEL_LAST] = {
7427 [ALC260_BASIC] = "basic",
7428 [ALC260_HP] = "hp",
7429 [ALC260_HP_3013] = "hp-3013",
7430 [ALC260_HP_DC7600] = "hp-dc7600",
7431 [ALC260_FUJITSU_S702X] = "fujitsu",
7432 [ALC260_ACER] = "acer",
7433 [ALC260_WILL] = "will",
7434 [ALC260_REPLACER_672V] = "replacer",
7435 [ALC260_FAVORIT100] = "favorit100",
7436 #ifdef CONFIG_SND_DEBUG
7437 [ALC260_TEST] = "test",
7438 #endif
7439 [ALC260_AUTO] = "auto",
7442 static const struct snd_pci_quirk alc260_cfg_tbl[] = {
7443 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
7444 SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
7445 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
7446 SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
7447 SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
7448 SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_AUTO), /* no quirk */
7449 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
7450 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
7451 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_DC7600),
7452 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
7453 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
7454 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
7455 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
7456 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
7457 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
7458 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
7459 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
7460 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
7461 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
7462 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
7466 static const struct alc_config_preset alc260_presets[] = {
7467 [ALC260_BASIC] = {
7468 .mixers = { alc260_base_output_mixer,
7469 alc260_input_mixer },
7470 .init_verbs = { alc260_init_verbs },
7471 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7472 .dac_nids = alc260_dac_nids,
7473 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
7474 .adc_nids = alc260_dual_adc_nids,
7475 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7476 .channel_mode = alc260_modes,
7477 .input_mux = &alc260_capture_source,
7479 [ALC260_HP] = {
7480 .mixers = { alc260_hp_output_mixer,
7481 alc260_input_mixer },
7482 .init_verbs = { alc260_init_verbs,
7483 alc260_hp_unsol_verbs },
7484 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7485 .dac_nids = alc260_dac_nids,
7486 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
7487 .adc_nids = alc260_adc_nids_alt,
7488 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7489 .channel_mode = alc260_modes,
7490 .input_mux = &alc260_capture_source,
7491 .unsol_event = alc_sku_unsol_event,
7492 .setup = alc260_hp_setup,
7493 .init_hook = alc_inithook,
7495 [ALC260_HP_DC7600] = {
7496 .mixers = { alc260_hp_dc7600_mixer,
7497 alc260_input_mixer },
7498 .init_verbs = { alc260_init_verbs,
7499 alc260_hp_dc7600_verbs },
7500 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7501 .dac_nids = alc260_dac_nids,
7502 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
7503 .adc_nids = alc260_adc_nids_alt,
7504 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7505 .channel_mode = alc260_modes,
7506 .input_mux = &alc260_capture_source,
7507 .unsol_event = alc_sku_unsol_event,
7508 .setup = alc260_hp_3012_setup,
7509 .init_hook = alc_inithook,
7511 [ALC260_HP_3013] = {
7512 .mixers = { alc260_hp_3013_mixer,
7513 alc260_input_mixer },
7514 .init_verbs = { alc260_hp_3013_init_verbs,
7515 alc260_hp_3013_unsol_verbs },
7516 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7517 .dac_nids = alc260_dac_nids,
7518 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
7519 .adc_nids = alc260_adc_nids_alt,
7520 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7521 .channel_mode = alc260_modes,
7522 .input_mux = &alc260_capture_source,
7523 .unsol_event = alc_sku_unsol_event,
7524 .setup = alc260_hp_3013_setup,
7525 .init_hook = alc_inithook,
7527 [ALC260_FUJITSU_S702X] = {
7528 .mixers = { alc260_fujitsu_mixer },
7529 .init_verbs = { alc260_fujitsu_init_verbs },
7530 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7531 .dac_nids = alc260_dac_nids,
7532 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
7533 .adc_nids = alc260_dual_adc_nids,
7534 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7535 .channel_mode = alc260_modes,
7536 .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
7537 .input_mux = alc260_fujitsu_capture_sources,
7539 [ALC260_ACER] = {
7540 .mixers = { alc260_acer_mixer },
7541 .init_verbs = { alc260_acer_init_verbs },
7542 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7543 .dac_nids = alc260_dac_nids,
7544 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
7545 .adc_nids = alc260_dual_adc_nids,
7546 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7547 .channel_mode = alc260_modes,
7548 .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
7549 .input_mux = alc260_acer_capture_sources,
7551 [ALC260_FAVORIT100] = {
7552 .mixers = { alc260_favorit100_mixer },
7553 .init_verbs = { alc260_favorit100_init_verbs },
7554 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7555 .dac_nids = alc260_dac_nids,
7556 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
7557 .adc_nids = alc260_dual_adc_nids,
7558 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7559 .channel_mode = alc260_modes,
7560 .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
7561 .input_mux = alc260_favorit100_capture_sources,
7563 [ALC260_WILL] = {
7564 .mixers = { alc260_will_mixer },
7565 .init_verbs = { alc260_init_verbs, alc260_will_verbs },
7566 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7567 .dac_nids = alc260_dac_nids,
7568 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
7569 .adc_nids = alc260_adc_nids,
7570 .dig_out_nid = ALC260_DIGOUT_NID,
7571 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7572 .channel_mode = alc260_modes,
7573 .input_mux = &alc260_capture_source,
7575 [ALC260_REPLACER_672V] = {
7576 .mixers = { alc260_replacer_672v_mixer },
7577 .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
7578 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
7579 .dac_nids = alc260_dac_nids,
7580 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
7581 .adc_nids = alc260_adc_nids,
7582 .dig_out_nid = ALC260_DIGOUT_NID,
7583 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7584 .channel_mode = alc260_modes,
7585 .input_mux = &alc260_capture_source,
7586 .unsol_event = alc260_replacer_672v_unsol_event,
7587 .init_hook = alc260_replacer_672v_automute,
7589 #ifdef CONFIG_SND_DEBUG
7590 [ALC260_TEST] = {
7591 .mixers = { alc260_test_mixer },
7592 .init_verbs = { alc260_test_init_verbs },
7593 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
7594 .dac_nids = alc260_test_dac_nids,
7595 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
7596 .adc_nids = alc260_test_adc_nids,
7597 .num_channel_mode = ARRAY_SIZE(alc260_modes),
7598 .channel_mode = alc260_modes,
7599 .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
7600 .input_mux = alc260_test_capture_sources,
7602 #endif
7605 static int patch_alc260(struct hda_codec *codec)
7607 struct alc_spec *spec;
7608 int err, board_config;
7610 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
7611 if (spec == NULL)
7612 return -ENOMEM;
7614 codec->spec = spec;
7616 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
7617 alc260_models,
7618 alc260_cfg_tbl);
7619 if (board_config < 0) {
7620 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
7621 codec->chip_name);
7622 board_config = ALC260_AUTO;
7625 if (board_config == ALC260_AUTO) {
7626 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
7627 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
7630 if (board_config == ALC260_AUTO) {
7631 /* automatic parse from the BIOS config */
7632 err = alc260_parse_auto_config(codec);
7633 if (err < 0) {
7634 alc_free(codec);
7635 return err;
7636 } else if (!err) {
7637 printk(KERN_INFO
7638 "hda_codec: Cannot set up configuration "
7639 "from BIOS. Using base mode...\n");
7640 board_config = ALC260_BASIC;
7644 err = snd_hda_attach_beep_device(codec, 0x1);
7645 if (err < 0) {
7646 alc_free(codec);
7647 return err;
7650 if (board_config != ALC260_AUTO)
7651 setup_preset(codec, &alc260_presets[board_config]);
7653 spec->stream_analog_playback = &alc260_pcm_analog_playback;
7654 spec->stream_analog_capture = &alc260_pcm_analog_capture;
7655 spec->stream_analog_alt_capture = &alc260_pcm_analog_capture;
7657 spec->stream_digital_playback = &alc260_pcm_digital_playback;
7658 spec->stream_digital_capture = &alc260_pcm_digital_capture;
7660 if (!spec->adc_nids && spec->input_mux) {
7661 /* check whether NID 0x04 is valid */
7662 unsigned int wcap = get_wcaps(codec, 0x04);
7663 wcap = get_wcaps_type(wcap);
7664 /* get type */
7665 if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
7666 spec->adc_nids = alc260_adc_nids_alt;
7667 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
7668 } else {
7669 spec->adc_nids = alc260_adc_nids;
7670 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
7673 set_capture_mixer(codec);
7674 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
7676 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
7678 spec->vmaster_nid = 0x08;
7680 codec->patch_ops = alc_patch_ops;
7681 if (board_config == ALC260_AUTO)
7682 spec->init_hook = alc260_auto_init;
7683 spec->shutup = alc_eapd_shutup;
7684 #ifdef CONFIG_SND_HDA_POWER_SAVE
7685 if (!spec->loopback.amplist)
7686 spec->loopback.amplist = alc260_loopbacks;
7687 #endif
7689 return 0;
7694 * ALC882/883/885/888/889 support
7696 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
7697 * configuration. Each pin widget can choose any input DACs and a mixer.
7698 * Each ADC is connected from a mixer of all inputs. This makes possible
7699 * 6-channel independent captures.
7701 * In addition, an independent DAC for the multi-playback (not used in this
7702 * driver yet).
7704 #define ALC882_DIGOUT_NID 0x06
7705 #define ALC882_DIGIN_NID 0x0a
7706 #define ALC883_DIGOUT_NID ALC882_DIGOUT_NID
7707 #define ALC883_DIGIN_NID ALC882_DIGIN_NID
7708 #define ALC1200_DIGOUT_NID 0x10
7711 static const struct hda_channel_mode alc882_ch_modes[1] = {
7712 { 8, NULL }
7715 /* DACs */
7716 static const hda_nid_t alc882_dac_nids[4] = {
7717 /* front, rear, clfe, rear_surr */
7718 0x02, 0x03, 0x04, 0x05
7720 #define alc883_dac_nids alc882_dac_nids
7722 /* ADCs */
7723 #define alc882_adc_nids alc880_adc_nids
7724 #define alc882_adc_nids_alt alc880_adc_nids_alt
7725 #define alc883_adc_nids alc882_adc_nids_alt
7726 static const hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
7727 static const hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
7728 #define alc889_adc_nids alc880_adc_nids
7730 static const hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
7731 static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
7732 #define alc883_capsrc_nids alc882_capsrc_nids_alt
7733 static const hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
7734 #define alc889_capsrc_nids alc882_capsrc_nids
7736 /* input MUX */
7737 /* FIXME: should be a matrix-type input source selection */
7739 static const struct hda_input_mux alc882_capture_source = {
7740 .num_items = 4,
7741 .items = {
7742 { "Mic", 0x0 },
7743 { "Front Mic", 0x1 },
7744 { "Line", 0x2 },
7745 { "CD", 0x4 },
7749 #define alc883_capture_source alc882_capture_source
7751 static const struct hda_input_mux alc889_capture_source = {
7752 .num_items = 3,
7753 .items = {
7754 { "Front Mic", 0x0 },
7755 { "Mic", 0x3 },
7756 { "Line", 0x2 },
7760 static const struct hda_input_mux mb5_capture_source = {
7761 .num_items = 3,
7762 .items = {
7763 { "Mic", 0x1 },
7764 { "Line", 0x7 },
7765 { "CD", 0x4 },
7769 static const struct hda_input_mux macmini3_capture_source = {
7770 .num_items = 2,
7771 .items = {
7772 { "Line", 0x2 },
7773 { "CD", 0x4 },
7777 static const struct hda_input_mux alc883_3stack_6ch_intel = {
7778 .num_items = 4,
7779 .items = {
7780 { "Mic", 0x1 },
7781 { "Front Mic", 0x0 },
7782 { "Line", 0x2 },
7783 { "CD", 0x4 },
7787 static const struct hda_input_mux alc883_lenovo_101e_capture_source = {
7788 .num_items = 2,
7789 .items = {
7790 { "Mic", 0x1 },
7791 { "Line", 0x2 },
7795 static const struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
7796 .num_items = 4,
7797 .items = {
7798 { "Mic", 0x0 },
7799 { "Internal Mic", 0x1 },
7800 { "Line", 0x2 },
7801 { "CD", 0x4 },
7805 static const struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
7806 .num_items = 2,
7807 .items = {
7808 { "Mic", 0x0 },
7809 { "Internal Mic", 0x1 },
7813 static const struct hda_input_mux alc883_lenovo_sky_capture_source = {
7814 .num_items = 3,
7815 .items = {
7816 { "Mic", 0x0 },
7817 { "Front Mic", 0x1 },
7818 { "Line", 0x4 },
7822 static const struct hda_input_mux alc883_asus_eee1601_capture_source = {
7823 .num_items = 2,
7824 .items = {
7825 { "Mic", 0x0 },
7826 { "Line", 0x2 },
7830 static const struct hda_input_mux alc889A_mb31_capture_source = {
7831 .num_items = 2,
7832 .items = {
7833 { "Mic", 0x0 },
7834 /* Front Mic (0x01) unused */
7835 { "Line", 0x2 },
7836 /* Line 2 (0x03) unused */
7837 /* CD (0x04) unused? */
7841 static const struct hda_input_mux alc889A_imac91_capture_source = {
7842 .num_items = 2,
7843 .items = {
7844 { "Mic", 0x01 },
7845 { "Line", 0x2 }, /* Not sure! */
7850 * 2ch mode
7852 static const struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
7853 { 2, NULL }
7857 * 2ch mode
7859 static const struct hda_verb alc882_3ST_ch2_init[] = {
7860 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7861 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7862 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7863 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7864 { } /* end */
7868 * 4ch mode
7870 static const struct hda_verb alc882_3ST_ch4_init[] = {
7871 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7872 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7873 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7874 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7875 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7876 { } /* end */
7880 * 6ch mode
7882 static const struct hda_verb alc882_3ST_ch6_init[] = {
7883 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7884 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7885 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7886 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7887 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7888 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7889 { } /* end */
7892 static const struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
7893 { 2, alc882_3ST_ch2_init },
7894 { 4, alc882_3ST_ch4_init },
7895 { 6, alc882_3ST_ch6_init },
7898 #define alc883_3ST_6ch_modes alc882_3ST_6ch_modes
7901 * 2ch mode
7903 static const struct hda_verb alc883_3ST_ch2_clevo_init[] = {
7904 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
7905 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7906 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7907 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7908 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7909 { } /* end */
7913 * 4ch mode
7915 static const struct hda_verb alc883_3ST_ch4_clevo_init[] = {
7916 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7917 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7918 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7919 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7920 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7921 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7922 { } /* end */
7926 * 6ch mode
7928 static const struct hda_verb alc883_3ST_ch6_clevo_init[] = {
7929 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7930 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7931 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7932 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7933 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7934 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7935 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7936 { } /* end */
7939 static const struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
7940 { 2, alc883_3ST_ch2_clevo_init },
7941 { 4, alc883_3ST_ch4_clevo_init },
7942 { 6, alc883_3ST_ch6_clevo_init },
7947 * 6ch mode
7949 static const struct hda_verb alc882_sixstack_ch6_init[] = {
7950 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7951 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7952 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7953 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7954 { } /* end */
7958 * 8ch mode
7960 static const struct hda_verb alc882_sixstack_ch8_init[] = {
7961 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7962 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7963 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7964 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7965 { } /* end */
7968 static const struct hda_channel_mode alc882_sixstack_modes[2] = {
7969 { 6, alc882_sixstack_ch6_init },
7970 { 8, alc882_sixstack_ch8_init },
7974 /* Macbook Air 2,1 */
7976 static const struct hda_channel_mode alc885_mba21_ch_modes[1] = {
7977 { 2, NULL },
7981 * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
7985 * 2ch mode
7987 static const struct hda_verb alc885_mbp_ch2_init[] = {
7988 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7989 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7990 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7991 { } /* end */
7995 * 4ch mode
7997 static const struct hda_verb alc885_mbp_ch4_init[] = {
7998 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7999 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8000 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8001 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8002 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8003 { } /* end */
8006 static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
8007 { 2, alc885_mbp_ch2_init },
8008 { 4, alc885_mbp_ch4_init },
8012 * 2ch
8013 * Speakers/Woofer/HP = Front
8014 * LineIn = Input
8016 static const struct hda_verb alc885_mb5_ch2_init[] = {
8017 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8018 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8019 { } /* end */
8023 * 6ch mode
8024 * Speakers/HP = Front
8025 * Woofer = LFE
8026 * LineIn = Surround
8028 static const struct hda_verb alc885_mb5_ch6_init[] = {
8029 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8030 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8031 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
8032 { } /* end */
8035 static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
8036 { 2, alc885_mb5_ch2_init },
8037 { 6, alc885_mb5_ch6_init },
8040 #define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes
8043 * 2ch mode
8045 static const struct hda_verb alc883_4ST_ch2_init[] = {
8046 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8047 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8048 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8049 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8050 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
8051 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8052 { } /* end */
8056 * 4ch mode
8058 static const struct hda_verb alc883_4ST_ch4_init[] = {
8059 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8060 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8061 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8062 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8063 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8064 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8065 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8066 { } /* end */
8070 * 6ch mode
8072 static const struct hda_verb alc883_4ST_ch6_init[] = {
8073 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8074 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8075 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8076 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8077 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
8078 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8079 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8080 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8081 { } /* end */
8085 * 8ch mode
8087 static const struct hda_verb alc883_4ST_ch8_init[] = {
8088 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8089 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8090 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
8091 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8092 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8093 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
8094 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8095 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8096 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8097 { } /* end */
8100 static const struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
8101 { 2, alc883_4ST_ch2_init },
8102 { 4, alc883_4ST_ch4_init },
8103 { 6, alc883_4ST_ch6_init },
8104 { 8, alc883_4ST_ch8_init },
8109 * 2ch mode
8111 static const struct hda_verb alc883_3ST_ch2_intel_init[] = {
8112 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8113 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8114 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
8115 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8116 { } /* end */
8120 * 4ch mode
8122 static const struct hda_verb alc883_3ST_ch4_intel_init[] = {
8123 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8124 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8125 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8126 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8127 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8128 { } /* end */
8132 * 6ch mode
8134 static const struct hda_verb alc883_3ST_ch6_intel_init[] = {
8135 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8136 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8137 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
8138 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8139 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8140 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
8141 { } /* end */
8144 static const struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
8145 { 2, alc883_3ST_ch2_intel_init },
8146 { 4, alc883_3ST_ch4_intel_init },
8147 { 6, alc883_3ST_ch6_intel_init },
8151 * 2ch mode
8153 static const struct hda_verb alc889_ch2_intel_init[] = {
8154 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
8155 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
8156 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
8157 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00 },
8158 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
8159 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8160 { } /* end */
8164 * 6ch mode
8166 static const struct hda_verb alc889_ch6_intel_init[] = {
8167 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
8168 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
8169 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
8170 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
8171 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
8172 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8173 { } /* end */
8177 * 8ch mode
8179 static const struct hda_verb alc889_ch8_intel_init[] = {
8180 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
8181 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
8182 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
8183 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
8184 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x03 },
8185 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8186 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8187 { } /* end */
8190 static const struct hda_channel_mode alc889_8ch_intel_modes[3] = {
8191 { 2, alc889_ch2_intel_init },
8192 { 6, alc889_ch6_intel_init },
8193 { 8, alc889_ch8_intel_init },
8197 * 6ch mode
8199 static const struct hda_verb alc883_sixstack_ch6_init[] = {
8200 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8201 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8202 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8203 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8204 { } /* end */
8208 * 8ch mode
8210 static const struct hda_verb alc883_sixstack_ch8_init[] = {
8211 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8212 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8213 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8214 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8215 { } /* end */
8218 static const struct hda_channel_mode alc883_sixstack_modes[2] = {
8219 { 6, alc883_sixstack_ch6_init },
8220 { 8, alc883_sixstack_ch8_init },
8224 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
8225 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
8227 static const struct snd_kcontrol_new alc882_base_mixer[] = {
8228 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8229 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8230 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8231 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8232 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8233 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8234 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8235 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8236 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8237 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
8238 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8239 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8240 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8241 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8242 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8243 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8244 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
8245 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8246 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8247 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
8248 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8249 { } /* end */
8252 /* Macbook Air 2,1 same control for HP and internal Speaker */
8254 static const struct snd_kcontrol_new alc885_mba21_mixer[] = {
8255 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8256 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
8261 static const struct snd_kcontrol_new alc885_mbp3_mixer[] = {
8262 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8263 HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
8264 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
8265 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
8266 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
8267 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8268 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8269 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
8270 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
8271 HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
8272 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
8273 { } /* end */
8276 static const struct snd_kcontrol_new alc885_mb5_mixer[] = {
8277 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8278 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
8279 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
8280 HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
8281 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
8282 HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
8283 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
8284 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
8285 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
8286 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
8287 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
8288 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
8289 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
8290 HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT),
8291 { } /* end */
8294 static const struct snd_kcontrol_new alc885_macmini3_mixer[] = {
8295 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8296 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
8297 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
8298 HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
8299 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
8300 HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
8301 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
8302 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
8303 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
8304 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
8305 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
8306 { } /* end */
8309 static const struct snd_kcontrol_new alc885_imac91_mixer[] = {
8310 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8311 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
8312 { } /* end */
8316 static const struct snd_kcontrol_new alc882_w2jc_mixer[] = {
8317 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8318 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8319 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8320 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8321 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8322 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8323 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8324 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
8325 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8326 { } /* end */
8329 static const struct snd_kcontrol_new alc882_targa_mixer[] = {
8330 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8331 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8332 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8333 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8334 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8335 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8336 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8337 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8338 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8339 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
8340 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8341 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8342 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
8343 { } /* end */
8346 /* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
8347 * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
8349 static const struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
8350 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8351 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8352 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8353 HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),
8354 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8355 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8356 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8357 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8358 HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),
8359 HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
8360 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8361 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8362 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
8363 { } /* end */
8366 static const struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
8367 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8368 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8369 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8370 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8371 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8372 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8373 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8374 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8375 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
8376 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8377 { } /* end */
8380 static const struct snd_kcontrol_new alc882_chmode_mixer[] = {
8382 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8383 .name = "Channel Mode",
8384 .info = alc_ch_mode_info,
8385 .get = alc_ch_mode_get,
8386 .put = alc_ch_mode_put,
8388 { } /* end */
8391 static const struct hda_verb alc882_base_init_verbs[] = {
8392 /* Front mixer: unmute input/output amp left and right (volume = 0) */
8393 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8394 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8395 /* Rear mixer */
8396 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8397 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8398 /* CLFE mixer */
8399 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8400 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8401 /* Side mixer */
8402 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8403 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8405 /* Front Pin: output 0 (0x0c) */
8406 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8407 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8408 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8409 /* Rear Pin: output 1 (0x0d) */
8410 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8411 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8412 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
8413 /* CLFE Pin: output 2 (0x0e) */
8414 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8415 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8416 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
8417 /* Side Pin: output 3 (0x0f) */
8418 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8419 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8420 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
8421 /* Mic (rear) pin: input vref at 80% */
8422 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8423 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8424 /* Front Mic pin: input vref at 80% */
8425 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8426 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8427 /* Line In pin: input */
8428 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8429 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8430 /* Line-2 In: Headphone output (output 0 - 0x0c) */
8431 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8432 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8433 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
8434 /* CD pin widget for input */
8435 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8437 /* FIXME: use matrix-type input source selection */
8438 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
8439 /* Input mixer2 */
8440 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8441 /* Input mixer3 */
8442 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8443 /* ADC2: mute amp left and right */
8444 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8445 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8446 /* ADC3: mute amp left and right */
8447 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8448 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8453 static const struct hda_verb alc882_adc1_init_verbs[] = {
8454 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
8455 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8456 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8457 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8458 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8459 /* ADC1: mute amp left and right */
8460 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8461 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8465 static const struct hda_verb alc882_eapd_verbs[] = {
8466 /* change to EAPD mode */
8467 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
8468 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
8472 static const struct hda_verb alc889_eapd_verbs[] = {
8473 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
8474 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
8478 static const struct hda_verb alc_hp15_unsol_verbs[] = {
8479 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
8480 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8484 static const struct hda_verb alc885_init_verbs[] = {
8485 /* Front mixer: unmute input/output amp left and right (volume = 0) */
8486 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8487 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8488 /* Rear mixer */
8489 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8490 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8491 /* CLFE mixer */
8492 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8493 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8494 /* Side mixer */
8495 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8496 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8498 /* Front HP Pin: output 0 (0x0c) */
8499 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8500 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8501 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8502 /* Front Pin: output 0 (0x0c) */
8503 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8504 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8505 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8506 /* Rear Pin: output 1 (0x0d) */
8507 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8508 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8509 {0x19, AC_VERB_SET_CONNECT_SEL, 0x01},
8510 /* CLFE Pin: output 2 (0x0e) */
8511 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8512 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8513 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
8514 /* Side Pin: output 3 (0x0f) */
8515 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8516 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8517 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
8518 /* Mic (rear) pin: input vref at 80% */
8519 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8520 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8521 /* Front Mic pin: input vref at 80% */
8522 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8523 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8524 /* Line In pin: input */
8525 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8526 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8528 /* Mixer elements: 0x18, , 0x1a, 0x1b */
8529 /* Input mixer1 */
8530 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8531 /* Input mixer2 */
8532 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8533 /* Input mixer3 */
8534 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8535 /* ADC2: mute amp left and right */
8536 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8537 /* ADC3: mute amp left and right */
8538 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8543 static const struct hda_verb alc885_init_input_verbs[] = {
8544 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8545 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8546 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8551 /* Unmute Selector 24h and set the default input to front mic */
8552 static const struct hda_verb alc889_init_input_verbs[] = {
8553 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
8554 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8559 #define alc883_init_verbs alc882_base_init_verbs
8561 /* Mac Pro test */
8562 static const struct snd_kcontrol_new alc882_macpro_mixer[] = {
8563 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8564 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8565 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
8566 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
8567 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
8568 /* FIXME: this looks suspicious...
8569 HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x02, HDA_INPUT),
8570 HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x02, HDA_INPUT),
8572 { } /* end */
8575 static const struct hda_verb alc882_macpro_init_verbs[] = {
8576 /* Front mixer: unmute input/output amp left and right (volume = 0) */
8577 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8578 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8579 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8580 /* Front Pin: output 0 (0x0c) */
8581 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8582 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8583 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8584 /* Front Mic pin: input vref at 80% */
8585 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8586 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8587 /* Speaker: output */
8588 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8589 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8590 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
8591 /* Headphone output (output 0 - 0x0c) */
8592 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8593 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8594 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8596 /* FIXME: use matrix-type input source selection */
8597 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
8598 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
8599 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8600 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8601 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8602 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8603 /* Input mixer2 */
8604 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8605 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8606 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8607 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8608 /* Input mixer3 */
8609 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8610 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8611 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8612 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8613 /* ADC1: mute amp left and right */
8614 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8615 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8616 /* ADC2: mute amp left and right */
8617 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8618 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8619 /* ADC3: mute amp left and right */
8620 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8621 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8626 /* Macbook 5,1 */
8627 static const struct hda_verb alc885_mb5_init_verbs[] = {
8628 /* DACs */
8629 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8630 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8631 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8632 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8633 /* Front mixer */
8634 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8635 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8636 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8637 /* Surround mixer */
8638 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8639 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8640 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8641 /* LFE mixer */
8642 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8643 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8644 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8645 /* HP mixer */
8646 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8647 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8648 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8649 /* Front Pin (0x0c) */
8650 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8651 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8652 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8653 /* LFE Pin (0x0e) */
8654 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8655 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8656 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
8657 /* HP Pin (0x0f) */
8658 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8659 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8660 {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
8661 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8662 /* Front Mic pin: input vref at 80% */
8663 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8664 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8665 /* Line In pin */
8666 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8667 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8669 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
8670 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
8671 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
8675 /* Macmini 3,1 */
8676 static const struct hda_verb alc885_macmini3_init_verbs[] = {
8677 /* DACs */
8678 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8679 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8680 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8681 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8682 /* Front mixer */
8683 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8684 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8685 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8686 /* Surround mixer */
8687 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8688 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8689 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8690 /* LFE mixer */
8691 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8692 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8693 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8694 /* HP mixer */
8695 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8696 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8697 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8698 /* Front Pin (0x0c) */
8699 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8700 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8701 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8702 /* LFE Pin (0x0e) */
8703 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8704 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8705 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
8706 /* HP Pin (0x0f) */
8707 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8708 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8709 {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
8710 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8711 /* Line In pin */
8712 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8713 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8715 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8716 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8717 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8718 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8723 static const struct hda_verb alc885_mba21_init_verbs[] = {
8724 /*Internal and HP Speaker Mixer*/
8725 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8726 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8727 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8728 /*Internal Speaker Pin (0x0c)*/
8729 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
8730 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8731 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8732 /* HP Pin: output 0 (0x0e) */
8733 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
8734 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8735 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8736 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
8737 /* Line in (is hp when jack connected)*/
8738 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
8739 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8745 /* Macbook Pro rev3 */
8746 static const struct hda_verb alc885_mbp3_init_verbs[] = {
8747 /* Front mixer: unmute input/output amp left and right (volume = 0) */
8748 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8749 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8750 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8751 /* Rear mixer */
8752 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8753 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8754 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8755 /* HP mixer */
8756 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8757 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8758 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8759 /* Front Pin: output 0 (0x0c) */
8760 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8761 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8762 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8763 /* HP Pin: output 0 (0x0e) */
8764 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
8765 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8766 {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
8767 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8768 /* Mic (rear) pin: input vref at 80% */
8769 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8770 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8771 /* Front Mic pin: input vref at 80% */
8772 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8773 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8774 /* Line In pin: use output 1 when in LineOut mode */
8775 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8776 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8777 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
8779 /* FIXME: use matrix-type input source selection */
8780 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
8781 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
8782 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8783 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8784 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8785 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8786 /* Input mixer2 */
8787 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8788 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8789 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8790 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8791 /* Input mixer3 */
8792 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8793 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8794 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8795 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8796 /* ADC1: mute amp left and right */
8797 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8798 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8799 /* ADC2: mute amp left and right */
8800 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8801 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8802 /* ADC3: mute amp left and right */
8803 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8804 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8809 /* iMac 9,1 */
8810 static const struct hda_verb alc885_imac91_init_verbs[] = {
8811 /* Internal Speaker Pin (0x0c) */
8812 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
8813 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8814 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8815 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
8816 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8817 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
8818 /* HP Pin: Rear */
8819 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8820 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8821 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8822 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
8823 /* Line in Rear */
8824 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
8825 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8826 /* Front Mic pin: input vref at 80% */
8827 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8828 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8829 /* Rear mixer */
8830 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8831 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8832 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8833 /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
8834 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8835 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8836 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8837 /* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
8838 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8839 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8840 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8841 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8842 /* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
8843 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8844 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8845 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8846 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8847 /* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
8848 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8849 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8850 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8851 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8852 /* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
8853 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8854 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8855 /* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
8856 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8857 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8858 /* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
8859 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8860 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8864 /* iMac 24 mixer. */
8865 static const struct snd_kcontrol_new alc885_imac24_mixer[] = {
8866 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8867 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
8868 { } /* end */
8871 /* iMac 24 init verbs. */
8872 static const struct hda_verb alc885_imac24_init_verbs[] = {
8873 /* Internal speakers: output 0 (0x0c) */
8874 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8875 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8876 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8877 /* Internal speakers: output 0 (0x0c) */
8878 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8879 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8880 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
8881 /* Headphone: output 0 (0x0c) */
8882 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8883 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8884 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8885 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8886 /* Front Mic: input vref at 80% */
8887 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8888 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8892 /* Toggle speaker-output according to the hp-jack state */
8893 static void alc885_imac24_setup(struct hda_codec *codec)
8895 struct alc_spec *spec = codec->spec;
8897 spec->autocfg.hp_pins[0] = 0x14;
8898 spec->autocfg.speaker_pins[0] = 0x18;
8899 spec->autocfg.speaker_pins[1] = 0x1a;
8900 spec->automute = 1;
8901 spec->automute_mode = ALC_AUTOMUTE_AMP;
8904 #define alc885_mb5_setup alc885_imac24_setup
8905 #define alc885_macmini3_setup alc885_imac24_setup
8907 /* Macbook Air 2,1 */
8908 static void alc885_mba21_setup(struct hda_codec *codec)
8910 struct alc_spec *spec = codec->spec;
8912 spec->autocfg.hp_pins[0] = 0x14;
8913 spec->autocfg.speaker_pins[0] = 0x18;
8914 spec->automute = 1;
8915 spec->automute_mode = ALC_AUTOMUTE_AMP;
8920 static void alc885_mbp3_setup(struct hda_codec *codec)
8922 struct alc_spec *spec = codec->spec;
8924 spec->autocfg.hp_pins[0] = 0x15;
8925 spec->autocfg.speaker_pins[0] = 0x14;
8926 spec->automute = 1;
8927 spec->automute_mode = ALC_AUTOMUTE_AMP;
8930 static void alc885_imac91_setup(struct hda_codec *codec)
8932 struct alc_spec *spec = codec->spec;
8934 spec->autocfg.hp_pins[0] = 0x14;
8935 spec->autocfg.speaker_pins[0] = 0x18;
8936 spec->autocfg.speaker_pins[1] = 0x1a;
8937 spec->automute = 1;
8938 spec->automute_mode = ALC_AUTOMUTE_AMP;
8941 static const struct hda_verb alc882_targa_verbs[] = {
8942 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8943 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8945 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8946 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8948 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
8949 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
8950 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8952 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8953 { } /* end */
8956 /* toggle speaker-output according to the hp-jack state */
8957 static void alc882_targa_automute(struct hda_codec *codec)
8959 struct alc_spec *spec = codec->spec;
8960 alc_hp_automute(codec);
8961 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
8962 spec->jack_present ? 1 : 3);
8965 static void alc882_targa_setup(struct hda_codec *codec)
8967 struct alc_spec *spec = codec->spec;
8969 spec->autocfg.hp_pins[0] = 0x14;
8970 spec->autocfg.speaker_pins[0] = 0x1b;
8971 spec->automute = 1;
8972 spec->automute_mode = ALC_AUTOMUTE_AMP;
8975 static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
8977 if ((res >> 26) == ALC880_HP_EVENT)
8978 alc882_targa_automute(codec);
8981 static const struct hda_verb alc882_asus_a7j_verbs[] = {
8982 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8983 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8985 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8986 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8987 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8989 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8990 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8991 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8993 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
8994 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
8995 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8996 { } /* end */
8999 static const struct hda_verb alc882_asus_a7m_verbs[] = {
9000 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9001 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9003 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9004 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9005 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9007 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
9008 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
9009 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
9011 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
9012 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
9013 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
9014 { } /* end */
9017 static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
9019 unsigned int gpiostate, gpiomask, gpiodir;
9021 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
9022 AC_VERB_GET_GPIO_DATA, 0);
9024 if (!muted)
9025 gpiostate |= (1 << pin);
9026 else
9027 gpiostate &= ~(1 << pin);
9029 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
9030 AC_VERB_GET_GPIO_MASK, 0);
9031 gpiomask |= (1 << pin);
9033 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
9034 AC_VERB_GET_GPIO_DIRECTION, 0);
9035 gpiodir |= (1 << pin);
9038 snd_hda_codec_write(codec, codec->afg, 0,
9039 AC_VERB_SET_GPIO_MASK, gpiomask);
9040 snd_hda_codec_write(codec, codec->afg, 0,
9041 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
9043 msleep(1);
9045 snd_hda_codec_write(codec, codec->afg, 0,
9046 AC_VERB_SET_GPIO_DATA, gpiostate);
9049 /* set up GPIO at initialization */
9050 static void alc885_macpro_init_hook(struct hda_codec *codec)
9052 alc882_gpio_mute(codec, 0, 0);
9053 alc882_gpio_mute(codec, 1, 0);
9056 /* set up GPIO and update auto-muting at initialization */
9057 static void alc885_imac24_init_hook(struct hda_codec *codec)
9059 alc885_macpro_init_hook(codec);
9060 alc_hp_automute(codec);
9064 * generic initialization of ADC, input mixers and output mixers
9066 static const struct hda_verb alc883_auto_init_verbs[] = {
9068 * Unmute ADC0-2 and set the default input to mic-in
9070 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
9071 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9072 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
9073 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9076 * Set up output mixers (0x0c - 0x0f)
9078 /* set vol=0 to output mixers */
9079 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9080 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9081 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9082 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9083 /* set up input amps for analog loopback */
9084 /* Amp Indices: DAC = 0, mixer = 1 */
9085 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9086 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9087 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9088 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9089 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9090 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9091 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9092 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9093 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9094 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9096 /* FIXME: use matrix-type input source selection */
9097 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
9098 /* Input mixer2 */
9099 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9100 /* Input mixer3 */
9101 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9105 /* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
9106 static const struct hda_verb alc889A_mb31_ch2_init[] = {
9107 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
9108 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
9109 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
9110 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
9111 { } /* end */
9114 /* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
9115 static const struct hda_verb alc889A_mb31_ch4_init[] = {
9116 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
9117 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
9118 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
9119 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
9120 { } /* end */
9123 /* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
9124 static const struct hda_verb alc889A_mb31_ch5_init[] = {
9125 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */
9126 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
9127 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
9128 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
9129 { } /* end */
9132 /* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
9133 static const struct hda_verb alc889A_mb31_ch6_init[] = {
9134 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */
9135 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */
9136 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
9137 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
9138 { } /* end */
9141 static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
9142 { 2, alc889A_mb31_ch2_init },
9143 { 4, alc889A_mb31_ch4_init },
9144 { 5, alc889A_mb31_ch5_init },
9145 { 6, alc889A_mb31_ch6_init },
9148 static const struct hda_verb alc883_medion_eapd_verbs[] = {
9149 /* eanable EAPD on medion laptop */
9150 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
9151 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
9155 #define alc883_base_mixer alc882_base_mixer
9157 static const struct snd_kcontrol_new alc883_mitac_mixer[] = {
9158 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9159 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9160 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
9161 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9162 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9163 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9164 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9165 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9166 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9167 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9168 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9169 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
9170 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9171 { } /* end */
9174 static const struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
9175 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9176 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
9177 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9178 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
9179 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9180 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9181 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9182 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9183 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
9184 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9185 { } /* end */
9188 static const struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
9189 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9190 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
9191 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9192 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
9193 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9194 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9195 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9196 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9197 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
9198 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9199 { } /* end */
9202 static const struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
9203 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9204 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9205 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9206 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9207 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9208 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9209 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9210 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9211 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9212 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9213 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9214 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
9215 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9216 { } /* end */
9219 static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
9220 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9221 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9222 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9223 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9224 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
9225 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9226 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9227 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9228 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9229 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9230 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9231 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9232 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9233 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9234 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9235 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9236 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9237 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
9238 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9239 { } /* end */
9242 static const struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
9243 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9244 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9245 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9246 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9247 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
9248 HDA_OUTPUT),
9249 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9250 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9251 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9252 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9253 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9254 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9255 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9256 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9257 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9258 HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
9259 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9260 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9261 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT),
9262 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9263 { } /* end */
9266 static const struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
9267 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9268 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9269 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9270 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9271 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
9272 HDA_OUTPUT),
9273 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9274 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9275 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9276 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
9277 HDA_BIND_MUTE("Speaker Playback Switch", 0x0f, 2, HDA_INPUT),
9278 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9279 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9280 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9281 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
9282 HDA_CODEC_VOLUME("Mic Boost Volume", 0x1b, 0, HDA_INPUT),
9283 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
9284 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9285 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT),
9286 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9287 { } /* end */
9290 static const struct snd_kcontrol_new alc883_fivestack_mixer[] = {
9291 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9292 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9293 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9294 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9295 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
9296 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9297 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9298 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9299 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9300 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9301 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9302 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9303 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9304 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9305 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9306 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9307 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9308 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
9309 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9310 { } /* end */
9313 static const struct snd_kcontrol_new alc883_targa_mixer[] = {
9314 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9315 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9316 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9317 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9318 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9319 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9320 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
9321 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
9322 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9323 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9324 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9325 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9326 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9327 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9328 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9329 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9330 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9331 { } /* end */
9334 static const struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
9335 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9336 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9337 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9338 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9339 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9340 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9341 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9342 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9343 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9344 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9345 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
9346 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9347 { } /* end */
9350 static const struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
9351 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
9352 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
9353 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9354 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
9355 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9356 { } /* end */
9359 static const struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
9360 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9361 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9362 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9363 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
9364 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9365 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9366 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9367 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9368 { } /* end */
9371 static const struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
9372 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9373 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
9374 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9375 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9376 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9377 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9378 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9379 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9380 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9381 { } /* end */
9384 static const struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
9385 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9386 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9387 HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9388 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
9389 HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT),
9390 HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT),
9391 { } /* end */
9394 static const struct hda_verb alc883_medion_wim2160_verbs[] = {
9395 /* Unmute front mixer */
9396 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9397 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9399 /* Set speaker pin to front mixer */
9400 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9402 /* Init headphone pin */
9403 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9404 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9405 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
9406 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9408 { } /* end */
9411 /* toggle speaker-output according to the hp-jack state */
9412 static void alc883_medion_wim2160_setup(struct hda_codec *codec)
9414 struct alc_spec *spec = codec->spec;
9416 spec->autocfg.hp_pins[0] = 0x1a;
9417 spec->autocfg.speaker_pins[0] = 0x15;
9418 spec->automute = 1;
9419 spec->automute_mode = ALC_AUTOMUTE_AMP;
9422 static const struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
9423 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9424 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9425 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9426 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9427 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9428 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9429 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9430 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9431 { } /* end */
9434 static const struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
9435 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9436 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
9437 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9438 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9439 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9440 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9441 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9442 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9443 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9444 { } /* end */
9447 static const struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
9448 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9449 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9450 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
9451 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
9452 HDA_CODEC_VOLUME_MONO("Center Playback Volume",
9453 0x0d, 1, 0x0, HDA_OUTPUT),
9454 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
9455 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
9456 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
9457 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
9458 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
9459 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9460 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9461 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9462 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9463 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9464 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9465 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9466 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9467 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
9468 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9469 { } /* end */
9472 static const struct snd_kcontrol_new alc889A_mb31_mixer[] = {
9473 /* Output mixers */
9474 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
9475 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
9476 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
9477 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
9478 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00,
9479 HDA_OUTPUT),
9480 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT),
9481 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT),
9482 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT),
9483 /* Output switches */
9484 HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT),
9485 HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT),
9486 HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT),
9487 /* Boost mixers */
9488 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
9489 HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
9490 /* Input mixers */
9491 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
9492 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
9493 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9494 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9495 { } /* end */
9498 static const struct snd_kcontrol_new alc883_vaiott_mixer[] = {
9499 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9500 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9501 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9502 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9503 HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
9504 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9505 { } /* end */
9508 static const struct hda_bind_ctls alc883_bind_cap_vol = {
9509 .ops = &snd_hda_bind_vol,
9510 .values = {
9511 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
9512 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
9517 static const struct hda_bind_ctls alc883_bind_cap_switch = {
9518 .ops = &snd_hda_bind_sw,
9519 .values = {
9520 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
9521 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
9526 static const struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
9527 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9528 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9529 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9530 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9531 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9532 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9533 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
9534 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9535 { } /* end */
9538 static const struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
9539 HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
9540 HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
9542 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9543 /* .name = "Capture Source", */
9544 .name = "Input Source",
9545 .count = 1,
9546 .info = alc_mux_enum_info,
9547 .get = alc_mux_enum_get,
9548 .put = alc_mux_enum_put,
9550 { } /* end */
9553 static const struct snd_kcontrol_new alc883_chmode_mixer[] = {
9555 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9556 .name = "Channel Mode",
9557 .info = alc_ch_mode_info,
9558 .get = alc_ch_mode_get,
9559 .put = alc_ch_mode_put,
9561 { } /* end */
9564 /* toggle speaker-output according to the hp-jack state */
9565 static void alc883_mitac_setup(struct hda_codec *codec)
9567 struct alc_spec *spec = codec->spec;
9569 spec->autocfg.hp_pins[0] = 0x15;
9570 spec->autocfg.speaker_pins[0] = 0x14;
9571 spec->autocfg.speaker_pins[1] = 0x17;
9572 spec->automute = 1;
9573 spec->automute_mode = ALC_AUTOMUTE_AMP;
9576 static const struct hda_verb alc883_mitac_verbs[] = {
9577 /* HP */
9578 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9579 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9580 /* Subwoofer */
9581 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
9582 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9584 /* enable unsolicited event */
9585 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9586 /* {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, */
9588 { } /* end */
9591 static const struct hda_verb alc883_clevo_m540r_verbs[] = {
9592 /* HP */
9593 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9594 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9595 /* Int speaker */
9596 /*{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},*/
9598 /* enable unsolicited event */
9600 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9601 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
9604 { } /* end */
9607 static const struct hda_verb alc883_clevo_m720_verbs[] = {
9608 /* HP */
9609 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9610 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9611 /* Int speaker */
9612 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
9613 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9615 /* enable unsolicited event */
9616 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9617 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
9619 { } /* end */
9622 static const struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
9623 /* HP */
9624 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9625 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9626 /* Subwoofer */
9627 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
9628 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9630 /* enable unsolicited event */
9631 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9633 { } /* end */
9636 static const struct hda_verb alc883_targa_verbs[] = {
9637 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9638 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9640 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9641 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9643 /* Connect Line-Out side jack (SPDIF) to Side */
9644 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9645 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9646 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
9647 /* Connect Mic jack to CLFE */
9648 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9649 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9650 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
9651 /* Connect Line-in jack to Surround */
9652 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9653 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9654 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
9655 /* Connect HP out jack to Front */
9656 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9657 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9658 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9660 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9662 { } /* end */
9665 static const struct hda_verb alc883_lenovo_101e_verbs[] = {
9666 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9667 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},
9668 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},
9669 { } /* end */
9672 static const struct hda_verb alc883_lenovo_nb0763_verbs[] = {
9673 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9674 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9675 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9676 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9677 { } /* end */
9680 static const struct hda_verb alc888_lenovo_ms7195_verbs[] = {
9681 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9682 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9683 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9684 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN},
9685 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9686 { } /* end */
9689 static const struct hda_verb alc883_haier_w66_verbs[] = {
9690 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9691 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9693 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9695 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9696 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9697 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9698 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9699 { } /* end */
9702 static const struct hda_verb alc888_lenovo_sky_verbs[] = {
9703 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9704 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9705 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9706 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9707 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9708 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9709 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
9710 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9711 { } /* end */
9714 static const struct hda_verb alc888_6st_dell_verbs[] = {
9715 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9719 static const struct hda_verb alc883_vaiott_verbs[] = {
9720 /* HP */
9721 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9722 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9724 /* enable unsolicited event */
9725 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9727 { } /* end */
9730 static void alc888_3st_hp_setup(struct hda_codec *codec)
9732 struct alc_spec *spec = codec->spec;
9734 spec->autocfg.hp_pins[0] = 0x1b;
9735 spec->autocfg.speaker_pins[0] = 0x14;
9736 spec->autocfg.speaker_pins[1] = 0x16;
9737 spec->autocfg.speaker_pins[2] = 0x18;
9738 spec->automute = 1;
9739 spec->automute_mode = ALC_AUTOMUTE_AMP;
9742 static const struct hda_verb alc888_3st_hp_verbs[] = {
9743 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
9744 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */
9745 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */
9746 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9747 { } /* end */
9751 * 2ch mode
9753 static const struct hda_verb alc888_3st_hp_2ch_init[] = {
9754 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
9755 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9756 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
9757 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9758 { } /* end */
9762 * 4ch mode
9764 static const struct hda_verb alc888_3st_hp_4ch_init[] = {
9765 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
9766 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9767 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9768 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9769 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
9770 { } /* end */
9774 * 6ch mode
9776 static const struct hda_verb alc888_3st_hp_6ch_init[] = {
9777 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9778 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9779 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
9780 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9781 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9782 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
9783 { } /* end */
9786 static const struct hda_channel_mode alc888_3st_hp_modes[3] = {
9787 { 2, alc888_3st_hp_2ch_init },
9788 { 4, alc888_3st_hp_4ch_init },
9789 { 6, alc888_3st_hp_6ch_init },
9792 static void alc888_lenovo_ms7195_setup(struct hda_codec *codec)
9794 struct alc_spec *spec = codec->spec;
9796 spec->autocfg.hp_pins[0] = 0x1b;
9797 spec->autocfg.line_out_pins[0] = 0x14;
9798 spec->autocfg.speaker_pins[0] = 0x15;
9799 spec->automute = 1;
9800 spec->automute_mode = ALC_AUTOMUTE_AMP;
9803 /* toggle speaker-output according to the hp-jack state */
9804 static void alc883_lenovo_nb0763_setup(struct hda_codec *codec)
9806 struct alc_spec *spec = codec->spec;
9808 spec->autocfg.hp_pins[0] = 0x14;
9809 spec->autocfg.speaker_pins[0] = 0x15;
9810 spec->automute = 1;
9811 spec->automute_mode = ALC_AUTOMUTE_AMP;
9814 /* toggle speaker-output according to the hp-jack state */
9815 #define alc883_targa_init_hook alc882_targa_init_hook
9816 #define alc883_targa_unsol_event alc882_targa_unsol_event
9818 static void alc883_clevo_m720_setup(struct hda_codec *codec)
9820 struct alc_spec *spec = codec->spec;
9822 spec->autocfg.hp_pins[0] = 0x15;
9823 spec->autocfg.speaker_pins[0] = 0x14;
9824 spec->automute = 1;
9825 spec->automute_mode = ALC_AUTOMUTE_AMP;
9828 static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
9830 alc_hp_automute(codec);
9831 alc88x_simple_mic_automute(codec);
9834 static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
9835 unsigned int res)
9837 switch (res >> 26) {
9838 case ALC880_MIC_EVENT:
9839 alc88x_simple_mic_automute(codec);
9840 break;
9841 default:
9842 alc_sku_unsol_event(codec, res);
9843 break;
9847 /* toggle speaker-output according to the hp-jack state */
9848 static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
9850 struct alc_spec *spec = codec->spec;
9852 spec->autocfg.hp_pins[0] = 0x14;
9853 spec->autocfg.speaker_pins[0] = 0x15;
9854 spec->automute = 1;
9855 spec->automute_mode = ALC_AUTOMUTE_AMP;
9858 static void alc883_haier_w66_setup(struct hda_codec *codec)
9860 struct alc_spec *spec = codec->spec;
9862 spec->autocfg.hp_pins[0] = 0x1b;
9863 spec->autocfg.speaker_pins[0] = 0x14;
9864 spec->automute = 1;
9865 spec->automute_mode = ALC_AUTOMUTE_AMP;
9868 static void alc883_lenovo_101e_setup(struct hda_codec *codec)
9870 struct alc_spec *spec = codec->spec;
9872 spec->autocfg.hp_pins[0] = 0x1b;
9873 spec->autocfg.line_out_pins[0] = 0x14;
9874 spec->autocfg.speaker_pins[0] = 0x15;
9875 spec->automute = 1;
9876 spec->detect_line = 1;
9877 spec->automute_lines = 1;
9878 spec->automute_mode = ALC_AUTOMUTE_AMP;
9881 /* toggle speaker-output according to the hp-jack state */
9882 static void alc883_acer_aspire_setup(struct hda_codec *codec)
9884 struct alc_spec *spec = codec->spec;
9886 spec->autocfg.hp_pins[0] = 0x14;
9887 spec->autocfg.speaker_pins[0] = 0x15;
9888 spec->autocfg.speaker_pins[1] = 0x16;
9889 spec->automute = 1;
9890 spec->automute_mode = ALC_AUTOMUTE_AMP;
9893 static const struct hda_verb alc883_acer_eapd_verbs[] = {
9894 /* HP Pin: output 0 (0x0c) */
9895 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9896 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9897 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9898 /* Front Pin: output 0 (0x0c) */
9899 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9900 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9901 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9902 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
9903 /* eanable EAPD on medion laptop */
9904 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
9905 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
9906 /* enable unsolicited event */
9907 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9911 static void alc888_6st_dell_setup(struct hda_codec *codec)
9913 struct alc_spec *spec = codec->spec;
9915 spec->autocfg.hp_pins[0] = 0x1b;
9916 spec->autocfg.speaker_pins[0] = 0x14;
9917 spec->autocfg.speaker_pins[1] = 0x15;
9918 spec->autocfg.speaker_pins[2] = 0x16;
9919 spec->autocfg.speaker_pins[3] = 0x17;
9920 spec->automute = 1;
9921 spec->automute_mode = ALC_AUTOMUTE_AMP;
9924 static void alc888_lenovo_sky_setup(struct hda_codec *codec)
9926 struct alc_spec *spec = codec->spec;
9928 spec->autocfg.hp_pins[0] = 0x1b;
9929 spec->autocfg.speaker_pins[0] = 0x14;
9930 spec->autocfg.speaker_pins[1] = 0x15;
9931 spec->autocfg.speaker_pins[2] = 0x16;
9932 spec->autocfg.speaker_pins[3] = 0x17;
9933 spec->autocfg.speaker_pins[4] = 0x1a;
9934 spec->automute = 1;
9935 spec->automute_mode = ALC_AUTOMUTE_AMP;
9938 static void alc883_vaiott_setup(struct hda_codec *codec)
9940 struct alc_spec *spec = codec->spec;
9942 spec->autocfg.hp_pins[0] = 0x15;
9943 spec->autocfg.speaker_pins[0] = 0x14;
9944 spec->autocfg.speaker_pins[1] = 0x17;
9945 spec->automute = 1;
9946 spec->automute_mode = ALC_AUTOMUTE_AMP;
9949 static const struct hda_verb alc888_asus_m90v_verbs[] = {
9950 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9951 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9952 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9953 /* enable unsolicited event */
9954 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9955 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
9956 { } /* end */
9959 static void alc883_mode2_setup(struct hda_codec *codec)
9961 struct alc_spec *spec = codec->spec;
9963 spec->autocfg.hp_pins[0] = 0x1b;
9964 spec->autocfg.speaker_pins[0] = 0x14;
9965 spec->autocfg.speaker_pins[1] = 0x15;
9966 spec->autocfg.speaker_pins[2] = 0x16;
9967 spec->ext_mic.pin = 0x18;
9968 spec->int_mic.pin = 0x19;
9969 spec->ext_mic.mux_idx = 0;
9970 spec->int_mic.mux_idx = 1;
9971 spec->auto_mic = 1;
9972 spec->automute = 1;
9973 spec->automute_mode = ALC_AUTOMUTE_AMP;
9976 static const struct hda_verb alc888_asus_eee1601_verbs[] = {
9977 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9978 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9979 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9980 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9981 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9982 {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
9983 {0x20, AC_VERB_SET_PROC_COEF, 0x0838},
9984 /* enable unsolicited event */
9985 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9986 { } /* end */
9989 static void alc883_eee1601_inithook(struct hda_codec *codec)
9991 struct alc_spec *spec = codec->spec;
9993 spec->autocfg.hp_pins[0] = 0x14;
9994 spec->autocfg.speaker_pins[0] = 0x1b;
9995 alc_hp_automute(codec);
9998 static const struct hda_verb alc889A_mb31_verbs[] = {
9999 /* Init rear pin (used as headphone output) */
10000 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */
10001 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */
10002 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
10003 /* Init line pin (used as output in 4ch and 6ch mode) */
10004 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Connect to CLFE */
10005 /* Init line 2 pin (used as headphone out by default) */
10006 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Use as input */
10007 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */
10008 { } /* end */
10011 /* Mute speakers according to the headphone jack state */
10012 static void alc889A_mb31_automute(struct hda_codec *codec)
10014 unsigned int present;
10016 /* Mute only in 2ch or 4ch mode */
10017 if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
10018 == 0x00) {
10019 present = snd_hda_jack_detect(codec, 0x15);
10020 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
10021 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
10022 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
10023 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
10027 static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
10029 if ((res >> 26) == ALC880_HP_EVENT)
10030 alc889A_mb31_automute(codec);
10034 #ifdef CONFIG_SND_HDA_POWER_SAVE
10035 #define alc882_loopbacks alc880_loopbacks
10036 #endif
10038 /* pcm configuration: identical with ALC880 */
10039 #define alc882_pcm_analog_playback alc880_pcm_analog_playback
10040 #define alc882_pcm_analog_capture alc880_pcm_analog_capture
10041 #define alc882_pcm_digital_playback alc880_pcm_digital_playback
10042 #define alc882_pcm_digital_capture alc880_pcm_digital_capture
10044 static const hda_nid_t alc883_slave_dig_outs[] = {
10045 ALC1200_DIGOUT_NID, 0,
10048 static const hda_nid_t alc1200_slave_dig_outs[] = {
10049 ALC883_DIGOUT_NID, 0,
10053 * configuration and preset
10055 static const char * const alc882_models[ALC882_MODEL_LAST] = {
10056 [ALC882_3ST_DIG] = "3stack-dig",
10057 [ALC882_6ST_DIG] = "6stack-dig",
10058 [ALC882_ARIMA] = "arima",
10059 [ALC882_W2JC] = "w2jc",
10060 [ALC882_TARGA] = "targa",
10061 [ALC882_ASUS_A7J] = "asus-a7j",
10062 [ALC882_ASUS_A7M] = "asus-a7m",
10063 [ALC885_MACPRO] = "macpro",
10064 [ALC885_MB5] = "mb5",
10065 [ALC885_MACMINI3] = "macmini3",
10066 [ALC885_MBA21] = "mba21",
10067 [ALC885_MBP3] = "mbp3",
10068 [ALC885_IMAC24] = "imac24",
10069 [ALC885_IMAC91] = "imac91",
10070 [ALC883_3ST_2ch_DIG] = "3stack-2ch-dig",
10071 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig",
10072 [ALC883_3ST_6ch] = "3stack-6ch",
10073 [ALC883_6ST_DIG] = "alc883-6stack-dig",
10074 [ALC883_TARGA_DIG] = "targa-dig",
10075 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
10076 [ALC883_TARGA_8ch_DIG] = "targa-8ch-dig",
10077 [ALC883_ACER] = "acer",
10078 [ALC883_ACER_ASPIRE] = "acer-aspire",
10079 [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g",
10080 [ALC888_ACER_ASPIRE_6530G] = "acer-aspire-6530g",
10081 [ALC888_ACER_ASPIRE_8930G] = "acer-aspire-8930g",
10082 [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g",
10083 [ALC883_MEDION] = "medion",
10084 [ALC883_MEDION_WIM2160] = "medion-wim2160",
10085 [ALC883_LAPTOP_EAPD] = "laptop-eapd",
10086 [ALC883_LENOVO_101E_2ch] = "lenovo-101e",
10087 [ALC883_LENOVO_NB0763] = "lenovo-nb0763",
10088 [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
10089 [ALC888_LENOVO_SKY] = "lenovo-sky",
10090 [ALC883_HAIER_W66] = "haier-w66",
10091 [ALC888_3ST_HP] = "3stack-hp",
10092 [ALC888_6ST_DELL] = "6stack-dell",
10093 [ALC883_MITAC] = "mitac",
10094 [ALC883_CLEVO_M540R] = "clevo-m540r",
10095 [ALC883_CLEVO_M720] = "clevo-m720",
10096 [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
10097 [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
10098 [ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel",
10099 [ALC889A_INTEL] = "intel-alc889a",
10100 [ALC889_INTEL] = "intel-x58",
10101 [ALC1200_ASUS_P5Q] = "asus-p5q",
10102 [ALC889A_MB31] = "mb31",
10103 [ALC883_SONY_VAIO_TT] = "sony-vaio-tt",
10104 [ALC882_AUTO] = "auto",
10107 static const struct snd_pci_quirk alc882_cfg_tbl[] = {
10108 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
10110 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
10111 SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
10112 SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE),
10113 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
10114 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
10115 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
10116 SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
10117 ALC888_ACER_ASPIRE_4930G),
10118 SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
10119 ALC888_ACER_ASPIRE_4930G),
10120 SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
10121 ALC888_ACER_ASPIRE_8930G),
10122 SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
10123 ALC888_ACER_ASPIRE_8930G),
10124 SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO),
10125 SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO),
10126 SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
10127 ALC888_ACER_ASPIRE_6530G),
10128 SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
10129 ALC888_ACER_ASPIRE_6530G),
10130 SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
10131 ALC888_ACER_ASPIRE_7730G),
10132 /* default Acer -- disabled as it causes more problems.
10133 * model=auto should work fine now
10135 /* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */
10137 SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
10139 SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavilion", ALC883_6ST_DIG),
10140 SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
10141 SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
10142 SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
10143 SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
10144 SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
10146 SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
10147 SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
10148 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
10149 SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
10150 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
10151 SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
10152 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
10153 SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
10154 SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
10155 SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
10156 SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
10158 SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT),
10159 SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
10160 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
10161 SND_PCI_QUIRK(0x1071, 0x8227, "Mitac 82801H", ALC883_MITAC),
10162 SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
10163 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
10164 SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
10165 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
10166 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
10168 SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
10169 SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
10170 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
10171 SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */
10172 SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
10173 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
10174 SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
10175 SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
10176 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
10177 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
10178 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
10179 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
10180 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
10181 SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
10182 SND_PCI_QUIRK(0x1462, 0x42cd, "MSI", ALC883_TARGA_DIG),
10183 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
10184 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
10185 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
10186 SND_PCI_QUIRK(0x1462, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG),
10187 SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG),
10188 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
10189 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
10190 SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
10191 SND_PCI_QUIRK(0x1462, 0x7260, "MSI 7260", ALC883_TARGA_DIG),
10192 SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
10193 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
10194 SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
10195 SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
10196 SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG),
10197 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
10198 SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
10200 SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
10201 SND_PCI_QUIRK(0x1558, 0x0571, "Clevo laptop M570U", ALC883_3ST_6ch_DIG),
10202 SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
10203 SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
10204 SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R),
10205 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
10206 SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
10207 /* SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), */
10208 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
10209 SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
10210 ALC883_FUJITSU_PI2515),
10211 SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx",
10212 ALC888_FUJITSU_XA3530),
10213 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
10214 SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
10215 SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
10216 SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
10217 SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY),
10218 SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
10219 SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
10220 SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
10222 SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
10223 SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
10224 SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC),
10225 SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
10226 SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
10227 SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
10228 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG),
10233 /* codec SSID table for Intel Mac */
10234 static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
10235 SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
10236 SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
10237 SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
10238 SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_MACPRO),
10239 SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
10240 SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
10241 SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
10242 SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
10243 SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_ASUS_A7M),
10244 SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3),
10245 SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21),
10246 SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
10247 SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
10248 SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
10249 SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
10250 SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
10251 SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5),
10252 /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
10253 * so apparently no perfect solution yet
10255 SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
10256 SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
10257 SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
10258 {} /* terminator */
10261 static const struct alc_config_preset alc882_presets[] = {
10262 [ALC882_3ST_DIG] = {
10263 .mixers = { alc882_base_mixer },
10264 .init_verbs = { alc882_base_init_verbs,
10265 alc882_adc1_init_verbs },
10266 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10267 .dac_nids = alc882_dac_nids,
10268 .dig_out_nid = ALC882_DIGOUT_NID,
10269 .dig_in_nid = ALC882_DIGIN_NID,
10270 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
10271 .channel_mode = alc882_ch_modes,
10272 .need_dac_fix = 1,
10273 .input_mux = &alc882_capture_source,
10275 [ALC882_6ST_DIG] = {
10276 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
10277 .init_verbs = { alc882_base_init_verbs,
10278 alc882_adc1_init_verbs },
10279 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10280 .dac_nids = alc882_dac_nids,
10281 .dig_out_nid = ALC882_DIGOUT_NID,
10282 .dig_in_nid = ALC882_DIGIN_NID,
10283 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
10284 .channel_mode = alc882_sixstack_modes,
10285 .input_mux = &alc882_capture_source,
10287 [ALC882_ARIMA] = {
10288 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
10289 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
10290 alc882_eapd_verbs },
10291 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10292 .dac_nids = alc882_dac_nids,
10293 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
10294 .channel_mode = alc882_sixstack_modes,
10295 .input_mux = &alc882_capture_source,
10297 [ALC882_W2JC] = {
10298 .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
10299 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
10300 alc882_eapd_verbs, alc880_gpio1_init_verbs },
10301 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10302 .dac_nids = alc882_dac_nids,
10303 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
10304 .channel_mode = alc880_threestack_modes,
10305 .need_dac_fix = 1,
10306 .input_mux = &alc882_capture_source,
10307 .dig_out_nid = ALC882_DIGOUT_NID,
10309 [ALC885_MBA21] = {
10310 .mixers = { alc885_mba21_mixer },
10311 .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
10312 .num_dacs = 2,
10313 .dac_nids = alc882_dac_nids,
10314 .channel_mode = alc885_mba21_ch_modes,
10315 .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
10316 .input_mux = &alc882_capture_source,
10317 .unsol_event = alc_sku_unsol_event,
10318 .setup = alc885_mba21_setup,
10319 .init_hook = alc_hp_automute,
10321 [ALC885_MBP3] = {
10322 .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
10323 .init_verbs = { alc885_mbp3_init_verbs,
10324 alc880_gpio1_init_verbs },
10325 .num_dacs = 2,
10326 .dac_nids = alc882_dac_nids,
10327 .hp_nid = 0x04,
10328 .channel_mode = alc885_mbp_4ch_modes,
10329 .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
10330 .input_mux = &alc882_capture_source,
10331 .dig_out_nid = ALC882_DIGOUT_NID,
10332 .dig_in_nid = ALC882_DIGIN_NID,
10333 .unsol_event = alc_sku_unsol_event,
10334 .setup = alc885_mbp3_setup,
10335 .init_hook = alc_hp_automute,
10337 [ALC885_MB5] = {
10338 .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
10339 .init_verbs = { alc885_mb5_init_verbs,
10340 alc880_gpio1_init_verbs },
10341 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10342 .dac_nids = alc882_dac_nids,
10343 .channel_mode = alc885_mb5_6ch_modes,
10344 .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
10345 .input_mux = &mb5_capture_source,
10346 .dig_out_nid = ALC882_DIGOUT_NID,
10347 .dig_in_nid = ALC882_DIGIN_NID,
10348 .unsol_event = alc_sku_unsol_event,
10349 .setup = alc885_mb5_setup,
10350 .init_hook = alc_hp_automute,
10352 [ALC885_MACMINI3] = {
10353 .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
10354 .init_verbs = { alc885_macmini3_init_verbs,
10355 alc880_gpio1_init_verbs },
10356 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10357 .dac_nids = alc882_dac_nids,
10358 .channel_mode = alc885_macmini3_6ch_modes,
10359 .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
10360 .input_mux = &macmini3_capture_source,
10361 .dig_out_nid = ALC882_DIGOUT_NID,
10362 .dig_in_nid = ALC882_DIGIN_NID,
10363 .unsol_event = alc_sku_unsol_event,
10364 .setup = alc885_macmini3_setup,
10365 .init_hook = alc_hp_automute,
10367 [ALC885_MACPRO] = {
10368 .mixers = { alc882_macpro_mixer },
10369 .init_verbs = { alc882_macpro_init_verbs },
10370 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10371 .dac_nids = alc882_dac_nids,
10372 .dig_out_nid = ALC882_DIGOUT_NID,
10373 .dig_in_nid = ALC882_DIGIN_NID,
10374 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
10375 .channel_mode = alc882_ch_modes,
10376 .input_mux = &alc882_capture_source,
10377 .init_hook = alc885_macpro_init_hook,
10379 [ALC885_IMAC24] = {
10380 .mixers = { alc885_imac24_mixer },
10381 .init_verbs = { alc885_imac24_init_verbs },
10382 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10383 .dac_nids = alc882_dac_nids,
10384 .dig_out_nid = ALC882_DIGOUT_NID,
10385 .dig_in_nid = ALC882_DIGIN_NID,
10386 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
10387 .channel_mode = alc882_ch_modes,
10388 .input_mux = &alc882_capture_source,
10389 .unsol_event = alc_sku_unsol_event,
10390 .setup = alc885_imac24_setup,
10391 .init_hook = alc885_imac24_init_hook,
10393 [ALC885_IMAC91] = {
10394 .mixers = {alc885_imac91_mixer},
10395 .init_verbs = { alc885_imac91_init_verbs,
10396 alc880_gpio1_init_verbs },
10397 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10398 .dac_nids = alc882_dac_nids,
10399 .channel_mode = alc885_mba21_ch_modes,
10400 .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
10401 .input_mux = &alc889A_imac91_capture_source,
10402 .dig_out_nid = ALC882_DIGOUT_NID,
10403 .dig_in_nid = ALC882_DIGIN_NID,
10404 .unsol_event = alc_sku_unsol_event,
10405 .setup = alc885_imac91_setup,
10406 .init_hook = alc_hp_automute,
10408 [ALC882_TARGA] = {
10409 .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
10410 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
10411 alc880_gpio3_init_verbs, alc882_targa_verbs},
10412 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10413 .dac_nids = alc882_dac_nids,
10414 .dig_out_nid = ALC882_DIGOUT_NID,
10415 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
10416 .adc_nids = alc882_adc_nids,
10417 .capsrc_nids = alc882_capsrc_nids,
10418 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
10419 .channel_mode = alc882_3ST_6ch_modes,
10420 .need_dac_fix = 1,
10421 .input_mux = &alc882_capture_source,
10422 .unsol_event = alc_sku_unsol_event,
10423 .setup = alc882_targa_setup,
10424 .init_hook = alc882_targa_automute,
10426 [ALC882_ASUS_A7J] = {
10427 .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
10428 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
10429 alc882_asus_a7j_verbs},
10430 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10431 .dac_nids = alc882_dac_nids,
10432 .dig_out_nid = ALC882_DIGOUT_NID,
10433 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
10434 .adc_nids = alc882_adc_nids,
10435 .capsrc_nids = alc882_capsrc_nids,
10436 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
10437 .channel_mode = alc882_3ST_6ch_modes,
10438 .need_dac_fix = 1,
10439 .input_mux = &alc882_capture_source,
10441 [ALC882_ASUS_A7M] = {
10442 .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
10443 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
10444 alc882_eapd_verbs, alc880_gpio1_init_verbs,
10445 alc882_asus_a7m_verbs },
10446 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
10447 .dac_nids = alc882_dac_nids,
10448 .dig_out_nid = ALC882_DIGOUT_NID,
10449 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
10450 .channel_mode = alc880_threestack_modes,
10451 .need_dac_fix = 1,
10452 .input_mux = &alc882_capture_source,
10454 [ALC883_3ST_2ch_DIG] = {
10455 .mixers = { alc883_3ST_2ch_mixer },
10456 .init_verbs = { alc883_init_verbs },
10457 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10458 .dac_nids = alc883_dac_nids,
10459 .dig_out_nid = ALC883_DIGOUT_NID,
10460 .dig_in_nid = ALC883_DIGIN_NID,
10461 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10462 .channel_mode = alc883_3ST_2ch_modes,
10463 .input_mux = &alc883_capture_source,
10465 [ALC883_3ST_6ch_DIG] = {
10466 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10467 .init_verbs = { alc883_init_verbs },
10468 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10469 .dac_nids = alc883_dac_nids,
10470 .dig_out_nid = ALC883_DIGOUT_NID,
10471 .dig_in_nid = ALC883_DIGIN_NID,
10472 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10473 .channel_mode = alc883_3ST_6ch_modes,
10474 .need_dac_fix = 1,
10475 .input_mux = &alc883_capture_source,
10477 [ALC883_3ST_6ch] = {
10478 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10479 .init_verbs = { alc883_init_verbs },
10480 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10481 .dac_nids = alc883_dac_nids,
10482 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10483 .channel_mode = alc883_3ST_6ch_modes,
10484 .need_dac_fix = 1,
10485 .input_mux = &alc883_capture_source,
10487 [ALC883_3ST_6ch_INTEL] = {
10488 .mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
10489 .init_verbs = { alc883_init_verbs },
10490 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10491 .dac_nids = alc883_dac_nids,
10492 .dig_out_nid = ALC883_DIGOUT_NID,
10493 .dig_in_nid = ALC883_DIGIN_NID,
10494 .slave_dig_outs = alc883_slave_dig_outs,
10495 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
10496 .channel_mode = alc883_3ST_6ch_intel_modes,
10497 .need_dac_fix = 1,
10498 .input_mux = &alc883_3stack_6ch_intel,
10500 [ALC889A_INTEL] = {
10501 .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
10502 .init_verbs = { alc885_init_verbs, alc885_init_input_verbs,
10503 alc_hp15_unsol_verbs },
10504 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10505 .dac_nids = alc883_dac_nids,
10506 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
10507 .adc_nids = alc889_adc_nids,
10508 .dig_out_nid = ALC883_DIGOUT_NID,
10509 .dig_in_nid = ALC883_DIGIN_NID,
10510 .slave_dig_outs = alc883_slave_dig_outs,
10511 .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
10512 .channel_mode = alc889_8ch_intel_modes,
10513 .capsrc_nids = alc889_capsrc_nids,
10514 .input_mux = &alc889_capture_source,
10515 .setup = alc889_automute_setup,
10516 .init_hook = alc_hp_automute,
10517 .unsol_event = alc_sku_unsol_event,
10518 .need_dac_fix = 1,
10520 [ALC889_INTEL] = {
10521 .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
10522 .init_verbs = { alc885_init_verbs, alc889_init_input_verbs,
10523 alc889_eapd_verbs, alc_hp15_unsol_verbs},
10524 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10525 .dac_nids = alc883_dac_nids,
10526 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
10527 .adc_nids = alc889_adc_nids,
10528 .dig_out_nid = ALC883_DIGOUT_NID,
10529 .dig_in_nid = ALC883_DIGIN_NID,
10530 .slave_dig_outs = alc883_slave_dig_outs,
10531 .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
10532 .channel_mode = alc889_8ch_intel_modes,
10533 .capsrc_nids = alc889_capsrc_nids,
10534 .input_mux = &alc889_capture_source,
10535 .setup = alc889_automute_setup,
10536 .init_hook = alc889_intel_init_hook,
10537 .unsol_event = alc_sku_unsol_event,
10538 .need_dac_fix = 1,
10540 [ALC883_6ST_DIG] = {
10541 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
10542 .init_verbs = { alc883_init_verbs },
10543 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10544 .dac_nids = alc883_dac_nids,
10545 .dig_out_nid = ALC883_DIGOUT_NID,
10546 .dig_in_nid = ALC883_DIGIN_NID,
10547 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10548 .channel_mode = alc883_sixstack_modes,
10549 .input_mux = &alc883_capture_source,
10551 [ALC883_TARGA_DIG] = {
10552 .mixers = { alc883_targa_mixer, alc883_chmode_mixer },
10553 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
10554 alc883_targa_verbs},
10555 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10556 .dac_nids = alc883_dac_nids,
10557 .dig_out_nid = ALC883_DIGOUT_NID,
10558 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10559 .channel_mode = alc883_3ST_6ch_modes,
10560 .need_dac_fix = 1,
10561 .input_mux = &alc883_capture_source,
10562 .unsol_event = alc883_targa_unsol_event,
10563 .setup = alc882_targa_setup,
10564 .init_hook = alc882_targa_automute,
10566 [ALC883_TARGA_2ch_DIG] = {
10567 .mixers = { alc883_targa_2ch_mixer},
10568 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
10569 alc883_targa_verbs},
10570 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10571 .dac_nids = alc883_dac_nids,
10572 .adc_nids = alc883_adc_nids_alt,
10573 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
10574 .capsrc_nids = alc883_capsrc_nids,
10575 .dig_out_nid = ALC883_DIGOUT_NID,
10576 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10577 .channel_mode = alc883_3ST_2ch_modes,
10578 .input_mux = &alc883_capture_source,
10579 .unsol_event = alc883_targa_unsol_event,
10580 .setup = alc882_targa_setup,
10581 .init_hook = alc882_targa_automute,
10583 [ALC883_TARGA_8ch_DIG] = {
10584 .mixers = { alc883_targa_mixer, alc883_targa_8ch_mixer,
10585 alc883_chmode_mixer },
10586 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
10587 alc883_targa_verbs },
10588 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10589 .dac_nids = alc883_dac_nids,
10590 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10591 .adc_nids = alc883_adc_nids_rev,
10592 .capsrc_nids = alc883_capsrc_nids_rev,
10593 .dig_out_nid = ALC883_DIGOUT_NID,
10594 .dig_in_nid = ALC883_DIGIN_NID,
10595 .num_channel_mode = ARRAY_SIZE(alc883_4ST_8ch_modes),
10596 .channel_mode = alc883_4ST_8ch_modes,
10597 .need_dac_fix = 1,
10598 .input_mux = &alc883_capture_source,
10599 .unsol_event = alc883_targa_unsol_event,
10600 .setup = alc882_targa_setup,
10601 .init_hook = alc882_targa_automute,
10603 [ALC883_ACER] = {
10604 .mixers = { alc883_base_mixer },
10605 /* On TravelMate laptops, GPIO 0 enables the internal speaker
10606 * and the headphone jack. Turn this on and rely on the
10607 * standard mute methods whenever the user wants to turn
10608 * these outputs off.
10610 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
10611 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10612 .dac_nids = alc883_dac_nids,
10613 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10614 .channel_mode = alc883_3ST_2ch_modes,
10615 .input_mux = &alc883_capture_source,
10617 [ALC883_ACER_ASPIRE] = {
10618 .mixers = { alc883_acer_aspire_mixer },
10619 .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
10620 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10621 .dac_nids = alc883_dac_nids,
10622 .dig_out_nid = ALC883_DIGOUT_NID,
10623 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10624 .channel_mode = alc883_3ST_2ch_modes,
10625 .input_mux = &alc883_capture_source,
10626 .unsol_event = alc_sku_unsol_event,
10627 .setup = alc883_acer_aspire_setup,
10628 .init_hook = alc_hp_automute,
10630 [ALC888_ACER_ASPIRE_4930G] = {
10631 .mixers = { alc888_acer_aspire_4930g_mixer,
10632 alc883_chmode_mixer },
10633 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10634 alc888_acer_aspire_4930g_verbs },
10635 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10636 .dac_nids = alc883_dac_nids,
10637 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10638 .adc_nids = alc883_adc_nids_rev,
10639 .capsrc_nids = alc883_capsrc_nids_rev,
10640 .dig_out_nid = ALC883_DIGOUT_NID,
10641 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10642 .channel_mode = alc883_3ST_6ch_modes,
10643 .need_dac_fix = 1,
10644 .const_channel_count = 6,
10645 .num_mux_defs =
10646 ARRAY_SIZE(alc888_2_capture_sources),
10647 .input_mux = alc888_2_capture_sources,
10648 .unsol_event = alc_sku_unsol_event,
10649 .setup = alc888_acer_aspire_4930g_setup,
10650 .init_hook = alc_hp_automute,
10652 [ALC888_ACER_ASPIRE_6530G] = {
10653 .mixers = { alc888_acer_aspire_6530_mixer },
10654 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10655 alc888_acer_aspire_6530g_verbs },
10656 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10657 .dac_nids = alc883_dac_nids,
10658 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10659 .adc_nids = alc883_adc_nids_rev,
10660 .capsrc_nids = alc883_capsrc_nids_rev,
10661 .dig_out_nid = ALC883_DIGOUT_NID,
10662 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10663 .channel_mode = alc883_3ST_2ch_modes,
10664 .num_mux_defs =
10665 ARRAY_SIZE(alc888_2_capture_sources),
10666 .input_mux = alc888_acer_aspire_6530_sources,
10667 .unsol_event = alc_sku_unsol_event,
10668 .setup = alc888_acer_aspire_6530g_setup,
10669 .init_hook = alc_hp_automute,
10671 [ALC888_ACER_ASPIRE_8930G] = {
10672 .mixers = { alc889_acer_aspire_8930g_mixer,
10673 alc883_chmode_mixer },
10674 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10675 alc889_acer_aspire_8930g_verbs,
10676 alc889_eapd_verbs},
10677 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10678 .dac_nids = alc883_dac_nids,
10679 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
10680 .adc_nids = alc889_adc_nids,
10681 .capsrc_nids = alc889_capsrc_nids,
10682 .dig_out_nid = ALC883_DIGOUT_NID,
10683 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10684 .channel_mode = alc883_3ST_6ch_modes,
10685 .need_dac_fix = 1,
10686 .const_channel_count = 6,
10687 .num_mux_defs =
10688 ARRAY_SIZE(alc889_capture_sources),
10689 .input_mux = alc889_capture_sources,
10690 .unsol_event = alc_sku_unsol_event,
10691 .setup = alc889_acer_aspire_8930g_setup,
10692 .init_hook = alc_hp_automute,
10693 #ifdef CONFIG_SND_HDA_POWER_SAVE
10694 .power_hook = alc_power_eapd,
10695 #endif
10697 [ALC888_ACER_ASPIRE_7730G] = {
10698 .mixers = { alc883_3ST_6ch_mixer,
10699 alc883_chmode_mixer },
10700 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10701 alc888_acer_aspire_7730G_verbs },
10702 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10703 .dac_nids = alc883_dac_nids,
10704 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10705 .adc_nids = alc883_adc_nids_rev,
10706 .capsrc_nids = alc883_capsrc_nids_rev,
10707 .dig_out_nid = ALC883_DIGOUT_NID,
10708 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10709 .channel_mode = alc883_3ST_6ch_modes,
10710 .need_dac_fix = 1,
10711 .const_channel_count = 6,
10712 .input_mux = &alc883_capture_source,
10713 .unsol_event = alc_sku_unsol_event,
10714 .setup = alc888_acer_aspire_7730g_setup,
10715 .init_hook = alc_hp_automute,
10717 [ALC883_MEDION] = {
10718 .mixers = { alc883_fivestack_mixer,
10719 alc883_chmode_mixer },
10720 .init_verbs = { alc883_init_verbs,
10721 alc883_medion_eapd_verbs },
10722 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10723 .dac_nids = alc883_dac_nids,
10724 .adc_nids = alc883_adc_nids_alt,
10725 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
10726 .capsrc_nids = alc883_capsrc_nids,
10727 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10728 .channel_mode = alc883_sixstack_modes,
10729 .input_mux = &alc883_capture_source,
10731 [ALC883_MEDION_WIM2160] = {
10732 .mixers = { alc883_medion_wim2160_mixer },
10733 .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs },
10734 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10735 .dac_nids = alc883_dac_nids,
10736 .dig_out_nid = ALC883_DIGOUT_NID,
10737 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
10738 .adc_nids = alc883_adc_nids,
10739 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10740 .channel_mode = alc883_3ST_2ch_modes,
10741 .input_mux = &alc883_capture_source,
10742 .unsol_event = alc_sku_unsol_event,
10743 .setup = alc883_medion_wim2160_setup,
10744 .init_hook = alc_hp_automute,
10746 [ALC883_LAPTOP_EAPD] = {
10747 .mixers = { alc883_base_mixer },
10748 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
10749 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10750 .dac_nids = alc883_dac_nids,
10751 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10752 .channel_mode = alc883_3ST_2ch_modes,
10753 .input_mux = &alc883_capture_source,
10755 [ALC883_CLEVO_M540R] = {
10756 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10757 .init_verbs = { alc883_init_verbs, alc883_clevo_m540r_verbs },
10758 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10759 .dac_nids = alc883_dac_nids,
10760 .dig_out_nid = ALC883_DIGOUT_NID,
10761 .dig_in_nid = ALC883_DIGIN_NID,
10762 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_clevo_modes),
10763 .channel_mode = alc883_3ST_6ch_clevo_modes,
10764 .need_dac_fix = 1,
10765 .input_mux = &alc883_capture_source,
10766 /* This machine has the hardware HP auto-muting, thus
10767 * we need no software mute via unsol event
10770 [ALC883_CLEVO_M720] = {
10771 .mixers = { alc883_clevo_m720_mixer },
10772 .init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
10773 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10774 .dac_nids = alc883_dac_nids,
10775 .dig_out_nid = ALC883_DIGOUT_NID,
10776 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10777 .channel_mode = alc883_3ST_2ch_modes,
10778 .input_mux = &alc883_capture_source,
10779 .unsol_event = alc883_clevo_m720_unsol_event,
10780 .setup = alc883_clevo_m720_setup,
10781 .init_hook = alc883_clevo_m720_init_hook,
10783 [ALC883_LENOVO_101E_2ch] = {
10784 .mixers = { alc883_lenovo_101e_2ch_mixer},
10785 .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
10786 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10787 .dac_nids = alc883_dac_nids,
10788 .adc_nids = alc883_adc_nids_alt,
10789 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
10790 .capsrc_nids = alc883_capsrc_nids,
10791 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10792 .channel_mode = alc883_3ST_2ch_modes,
10793 .input_mux = &alc883_lenovo_101e_capture_source,
10794 .setup = alc883_lenovo_101e_setup,
10795 .unsol_event = alc_sku_unsol_event,
10796 .init_hook = alc_inithook,
10798 [ALC883_LENOVO_NB0763] = {
10799 .mixers = { alc883_lenovo_nb0763_mixer },
10800 .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
10801 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10802 .dac_nids = alc883_dac_nids,
10803 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10804 .channel_mode = alc883_3ST_2ch_modes,
10805 .need_dac_fix = 1,
10806 .input_mux = &alc883_lenovo_nb0763_capture_source,
10807 .unsol_event = alc_sku_unsol_event,
10808 .setup = alc883_lenovo_nb0763_setup,
10809 .init_hook = alc_hp_automute,
10811 [ALC888_LENOVO_MS7195_DIG] = {
10812 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10813 .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
10814 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10815 .dac_nids = alc883_dac_nids,
10816 .dig_out_nid = ALC883_DIGOUT_NID,
10817 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10818 .channel_mode = alc883_3ST_6ch_modes,
10819 .need_dac_fix = 1,
10820 .input_mux = &alc883_capture_source,
10821 .unsol_event = alc_sku_unsol_event,
10822 .setup = alc888_lenovo_ms7195_setup,
10823 .init_hook = alc_inithook,
10825 [ALC883_HAIER_W66] = {
10826 .mixers = { alc883_targa_2ch_mixer},
10827 .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},
10828 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10829 .dac_nids = alc883_dac_nids,
10830 .dig_out_nid = ALC883_DIGOUT_NID,
10831 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10832 .channel_mode = alc883_3ST_2ch_modes,
10833 .input_mux = &alc883_capture_source,
10834 .unsol_event = alc_sku_unsol_event,
10835 .setup = alc883_haier_w66_setup,
10836 .init_hook = alc_hp_automute,
10838 [ALC888_3ST_HP] = {
10839 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10840 .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
10841 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10842 .dac_nids = alc883_dac_nids,
10843 .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
10844 .channel_mode = alc888_3st_hp_modes,
10845 .need_dac_fix = 1,
10846 .input_mux = &alc883_capture_source,
10847 .unsol_event = alc_sku_unsol_event,
10848 .setup = alc888_3st_hp_setup,
10849 .init_hook = alc_hp_automute,
10851 [ALC888_6ST_DELL] = {
10852 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
10853 .init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
10854 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10855 .dac_nids = alc883_dac_nids,
10856 .dig_out_nid = ALC883_DIGOUT_NID,
10857 .dig_in_nid = ALC883_DIGIN_NID,
10858 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10859 .channel_mode = alc883_sixstack_modes,
10860 .input_mux = &alc883_capture_source,
10861 .unsol_event = alc_sku_unsol_event,
10862 .setup = alc888_6st_dell_setup,
10863 .init_hook = alc_hp_automute,
10865 [ALC883_MITAC] = {
10866 .mixers = { alc883_mitac_mixer },
10867 .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
10868 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10869 .dac_nids = alc883_dac_nids,
10870 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10871 .channel_mode = alc883_3ST_2ch_modes,
10872 .input_mux = &alc883_capture_source,
10873 .unsol_event = alc_sku_unsol_event,
10874 .setup = alc883_mitac_setup,
10875 .init_hook = alc_hp_automute,
10877 [ALC883_FUJITSU_PI2515] = {
10878 .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
10879 .init_verbs = { alc883_init_verbs,
10880 alc883_2ch_fujitsu_pi2515_verbs},
10881 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10882 .dac_nids = alc883_dac_nids,
10883 .dig_out_nid = ALC883_DIGOUT_NID,
10884 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10885 .channel_mode = alc883_3ST_2ch_modes,
10886 .input_mux = &alc883_fujitsu_pi2515_capture_source,
10887 .unsol_event = alc_sku_unsol_event,
10888 .setup = alc883_2ch_fujitsu_pi2515_setup,
10889 .init_hook = alc_hp_automute,
10891 [ALC888_FUJITSU_XA3530] = {
10892 .mixers = { alc888_base_mixer, alc883_chmode_mixer },
10893 .init_verbs = { alc883_init_verbs,
10894 alc888_fujitsu_xa3530_verbs },
10895 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10896 .dac_nids = alc883_dac_nids,
10897 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10898 .adc_nids = alc883_adc_nids_rev,
10899 .capsrc_nids = alc883_capsrc_nids_rev,
10900 .dig_out_nid = ALC883_DIGOUT_NID,
10901 .num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes),
10902 .channel_mode = alc888_4ST_8ch_intel_modes,
10903 .num_mux_defs =
10904 ARRAY_SIZE(alc888_2_capture_sources),
10905 .input_mux = alc888_2_capture_sources,
10906 .unsol_event = alc_sku_unsol_event,
10907 .setup = alc888_fujitsu_xa3530_setup,
10908 .init_hook = alc_hp_automute,
10910 [ALC888_LENOVO_SKY] = {
10911 .mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
10912 .init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs},
10913 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10914 .dac_nids = alc883_dac_nids,
10915 .dig_out_nid = ALC883_DIGOUT_NID,
10916 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10917 .channel_mode = alc883_sixstack_modes,
10918 .need_dac_fix = 1,
10919 .input_mux = &alc883_lenovo_sky_capture_source,
10920 .unsol_event = alc_sku_unsol_event,
10921 .setup = alc888_lenovo_sky_setup,
10922 .init_hook = alc_hp_automute,
10924 [ALC888_ASUS_M90V] = {
10925 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10926 .init_verbs = { alc883_init_verbs, alc888_asus_m90v_verbs },
10927 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10928 .dac_nids = alc883_dac_nids,
10929 .dig_out_nid = ALC883_DIGOUT_NID,
10930 .dig_in_nid = ALC883_DIGIN_NID,
10931 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10932 .channel_mode = alc883_3ST_6ch_modes,
10933 .need_dac_fix = 1,
10934 .input_mux = &alc883_fujitsu_pi2515_capture_source,
10935 .unsol_event = alc_sku_unsol_event,
10936 .setup = alc883_mode2_setup,
10937 .init_hook = alc_inithook,
10939 [ALC888_ASUS_EEE1601] = {
10940 .mixers = { alc883_asus_eee1601_mixer },
10941 .cap_mixer = alc883_asus_eee1601_cap_mixer,
10942 .init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
10943 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10944 .dac_nids = alc883_dac_nids,
10945 .dig_out_nid = ALC883_DIGOUT_NID,
10946 .dig_in_nid = ALC883_DIGIN_NID,
10947 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10948 .channel_mode = alc883_3ST_2ch_modes,
10949 .need_dac_fix = 1,
10950 .input_mux = &alc883_asus_eee1601_capture_source,
10951 .unsol_event = alc_sku_unsol_event,
10952 .init_hook = alc883_eee1601_inithook,
10954 [ALC1200_ASUS_P5Q] = {
10955 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
10956 .init_verbs = { alc883_init_verbs },
10957 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10958 .dac_nids = alc883_dac_nids,
10959 .dig_out_nid = ALC1200_DIGOUT_NID,
10960 .dig_in_nid = ALC883_DIGIN_NID,
10961 .slave_dig_outs = alc1200_slave_dig_outs,
10962 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10963 .channel_mode = alc883_sixstack_modes,
10964 .input_mux = &alc883_capture_source,
10966 [ALC889A_MB31] = {
10967 .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer},
10968 .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs,
10969 alc880_gpio1_init_verbs },
10970 .adc_nids = alc883_adc_nids,
10971 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
10972 .capsrc_nids = alc883_capsrc_nids,
10973 .dac_nids = alc883_dac_nids,
10974 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10975 .channel_mode = alc889A_mb31_6ch_modes,
10976 .num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes),
10977 .input_mux = &alc889A_mb31_capture_source,
10978 .dig_out_nid = ALC883_DIGOUT_NID,
10979 .unsol_event = alc889A_mb31_unsol_event,
10980 .init_hook = alc889A_mb31_automute,
10982 [ALC883_SONY_VAIO_TT] = {
10983 .mixers = { alc883_vaiott_mixer },
10984 .init_verbs = { alc883_init_verbs, alc883_vaiott_verbs },
10985 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10986 .dac_nids = alc883_dac_nids,
10987 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10988 .channel_mode = alc883_3ST_2ch_modes,
10989 .input_mux = &alc883_capture_source,
10990 .unsol_event = alc_sku_unsol_event,
10991 .setup = alc883_vaiott_setup,
10992 .init_hook = alc_hp_automute,
10998 * Pin config fixes
11000 enum {
11001 PINFIX_ABIT_AW9D_MAX,
11002 PINFIX_LENOVO_Y530,
11003 PINFIX_PB_M5210,
11004 PINFIX_ACER_ASPIRE_7736,
11007 static const struct alc_fixup alc882_fixups[] = {
11008 [PINFIX_ABIT_AW9D_MAX] = {
11009 .type = ALC_FIXUP_PINS,
11010 .v.pins = (const struct alc_pincfg[]) {
11011 { 0x15, 0x01080104 }, /* side */
11012 { 0x16, 0x01011012 }, /* rear */
11013 { 0x17, 0x01016011 }, /* clfe */
11017 [PINFIX_LENOVO_Y530] = {
11018 .type = ALC_FIXUP_PINS,
11019 .v.pins = (const struct alc_pincfg[]) {
11020 { 0x15, 0x99130112 }, /* rear int speakers */
11021 { 0x16, 0x99130111 }, /* subwoofer */
11025 [PINFIX_PB_M5210] = {
11026 .type = ALC_FIXUP_VERBS,
11027 .v.verbs = (const struct hda_verb[]) {
11028 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
11032 [PINFIX_ACER_ASPIRE_7736] = {
11033 .type = ALC_FIXUP_SKU,
11034 .v.sku = ALC_FIXUP_SKU_IGNORE,
11038 static const struct snd_pci_quirk alc882_fixup_tbl[] = {
11039 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
11040 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
11041 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
11042 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
11047 * BIOS auto configuration
11049 static int alc882_auto_create_input_ctls(struct hda_codec *codec,
11050 const struct auto_pin_cfg *cfg)
11052 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x23, 0x22);
11055 static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
11056 hda_nid_t nid, int pin_type,
11057 hda_nid_t dac)
11059 int idx;
11061 /* set as output */
11062 alc_set_pin_output(codec, nid, pin_type);
11064 if (dac == 0x25)
11065 idx = 4;
11066 else if (dac >= 0x02 && dac <= 0x05)
11067 idx = dac - 2;
11068 else
11069 return;
11070 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
11073 static void alc882_auto_init_multi_out(struct hda_codec *codec)
11075 struct alc_spec *spec = codec->spec;
11076 int i;
11078 for (i = 0; i <= HDA_SIDE; i++) {
11079 hda_nid_t nid = spec->autocfg.line_out_pins[i];
11080 int pin_type = get_pin_type(spec->autocfg.line_out_type);
11081 if (nid)
11082 alc882_auto_set_output_and_unmute(codec, nid, pin_type,
11083 spec->multiout.dac_nids[i]);
11087 static void alc882_auto_init_hp_out(struct hda_codec *codec)
11089 struct alc_spec *spec = codec->spec;
11090 hda_nid_t pin, dac;
11091 int i;
11093 if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT) {
11094 for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
11095 pin = spec->autocfg.hp_pins[i];
11096 if (!pin)
11097 break;
11098 dac = spec->multiout.hp_nid;
11099 if (!dac)
11100 dac = spec->multiout.dac_nids[0]; /* to front */
11101 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
11105 if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT) {
11106 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
11107 pin = spec->autocfg.speaker_pins[i];
11108 if (!pin)
11109 break;
11110 dac = spec->multiout.extra_out_nid[0];
11111 if (!dac)
11112 dac = spec->multiout.dac_nids[0]; /* to front */
11113 alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
11118 static void alc882_auto_init_analog_input(struct hda_codec *codec)
11120 struct alc_spec *spec = codec->spec;
11121 struct auto_pin_cfg *cfg = &spec->autocfg;
11122 int i;
11124 for (i = 0; i < cfg->num_inputs; i++) {
11125 hda_nid_t nid = cfg->inputs[i].pin;
11126 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
11127 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
11128 snd_hda_codec_write(codec, nid, 0,
11129 AC_VERB_SET_AMP_GAIN_MUTE,
11130 AMP_OUT_MUTE);
11134 static void alc882_auto_init_input_src(struct hda_codec *codec)
11136 struct alc_spec *spec = codec->spec;
11137 int c;
11139 for (c = 0; c < spec->num_adc_nids; c++) {
11140 hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
11141 hda_nid_t nid = spec->capsrc_nids[c];
11142 unsigned int mux_idx;
11143 const struct hda_input_mux *imux;
11144 int conns, mute, idx, item;
11146 /* mute ADC */
11147 snd_hda_codec_write(codec, spec->adc_nids[c], 0,
11148 AC_VERB_SET_AMP_GAIN_MUTE,
11149 AMP_IN_MUTE(0));
11151 conns = snd_hda_get_connections(codec, nid, conn_list,
11152 ARRAY_SIZE(conn_list));
11153 if (conns < 0)
11154 continue;
11155 mux_idx = c >= spec->num_mux_defs ? 0 : c;
11156 imux = &spec->input_mux[mux_idx];
11157 if (!imux->num_items && mux_idx > 0)
11158 imux = &spec->input_mux[0];
11159 for (idx = 0; idx < conns; idx++) {
11160 /* if the current connection is the selected one,
11161 * unmute it as default - otherwise mute it
11163 mute = AMP_IN_MUTE(idx);
11164 for (item = 0; item < imux->num_items; item++) {
11165 if (imux->items[item].index == idx) {
11166 if (spec->cur_mux[c] == item)
11167 mute = AMP_IN_UNMUTE(idx);
11168 break;
11171 /* check if we have a selector or mixer
11172 * we could check for the widget type instead, but
11173 * just check for Amp-In presence (in case of mixer
11174 * without amp-in there is something wrong, this
11175 * function shouldn't be used or capsrc nid is wrong)
11177 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
11178 snd_hda_codec_write(codec, nid, 0,
11179 AC_VERB_SET_AMP_GAIN_MUTE,
11180 mute);
11181 else if (mute != AMP_IN_MUTE(idx))
11182 snd_hda_codec_write(codec, nid, 0,
11183 AC_VERB_SET_CONNECT_SEL,
11184 idx);
11189 /* add mic boosts if needed */
11190 static int alc_auto_add_mic_boost(struct hda_codec *codec)
11192 struct alc_spec *spec = codec->spec;
11193 struct auto_pin_cfg *cfg = &spec->autocfg;
11194 int i, err;
11195 int type_idx = 0;
11196 hda_nid_t nid;
11197 const char *prev_label = NULL;
11199 for (i = 0; i < cfg->num_inputs; i++) {
11200 if (cfg->inputs[i].type > AUTO_PIN_MIC)
11201 break;
11202 nid = cfg->inputs[i].pin;
11203 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
11204 const char *label;
11205 char boost_label[32];
11207 label = hda_get_autocfg_input_label(codec, cfg, i);
11208 if (prev_label && !strcmp(label, prev_label))
11209 type_idx++;
11210 else
11211 type_idx = 0;
11212 prev_label = label;
11214 snprintf(boost_label, sizeof(boost_label),
11215 "%s Boost Volume", label);
11216 err = add_control(spec, ALC_CTL_WIDGET_VOL,
11217 boost_label, type_idx,
11218 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
11219 if (err < 0)
11220 return err;
11223 return 0;
11226 /* almost identical with ALC880 parser... */
11227 static int alc882_parse_auto_config(struct hda_codec *codec)
11229 struct alc_spec *spec = codec->spec;
11230 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
11231 int err;
11233 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
11234 alc882_ignore);
11235 if (err < 0)
11236 return err;
11237 if (!spec->autocfg.line_outs)
11238 return 0; /* can't find valid BIOS pin config */
11240 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
11241 if (err < 0)
11242 return err;
11243 err = alc_auto_add_multi_channel_mode(codec);
11244 if (err < 0)
11245 return err;
11246 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
11247 if (err < 0)
11248 return err;
11249 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
11250 "Headphone");
11251 if (err < 0)
11252 return err;
11253 err = alc880_auto_create_extra_out(spec,
11254 spec->autocfg.speaker_pins[0],
11255 "Speaker");
11256 if (err < 0)
11257 return err;
11258 err = alc882_auto_create_input_ctls(codec, &spec->autocfg);
11259 if (err < 0)
11260 return err;
11262 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
11264 alc_auto_parse_digital(codec);
11266 if (spec->kctls.list)
11267 add_mixer(spec, spec->kctls.list);
11269 add_verb(spec, alc883_auto_init_verbs);
11270 /* if ADC 0x07 is available, initialize it, too */
11271 if (get_wcaps_type(get_wcaps(codec, 0x07)) == AC_WID_AUD_IN)
11272 add_verb(spec, alc882_adc1_init_verbs);
11274 spec->num_mux_defs = 1;
11275 spec->input_mux = &spec->private_imux[0];
11277 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
11279 err = alc_auto_add_mic_boost(codec);
11280 if (err < 0)
11281 return err;
11283 return 1; /* config found */
11286 /* additional initialization for auto-configuration model */
11287 static void alc882_auto_init(struct hda_codec *codec)
11289 struct alc_spec *spec = codec->spec;
11290 alc882_auto_init_multi_out(codec);
11291 alc882_auto_init_hp_out(codec);
11292 alc882_auto_init_analog_input(codec);
11293 alc882_auto_init_input_src(codec);
11294 alc_auto_init_digital(codec);
11295 if (spec->unsol_event)
11296 alc_inithook(codec);
11299 static int patch_alc882(struct hda_codec *codec)
11301 struct alc_spec *spec;
11302 int err, board_config;
11304 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
11305 if (spec == NULL)
11306 return -ENOMEM;
11308 codec->spec = spec;
11310 switch (codec->vendor_id) {
11311 case 0x10ec0882:
11312 case 0x10ec0885:
11313 break;
11314 default:
11315 /* ALC883 and variants */
11316 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
11317 break;
11320 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
11321 alc882_models,
11322 alc882_cfg_tbl);
11324 if (board_config < 0 || board_config >= ALC882_MODEL_LAST)
11325 board_config = snd_hda_check_board_codec_sid_config(codec,
11326 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
11328 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
11329 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
11330 codec->chip_name);
11331 board_config = ALC882_AUTO;
11334 if (board_config == ALC882_AUTO) {
11335 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
11336 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
11339 alc_auto_parse_customize_define(codec);
11341 if (board_config == ALC882_AUTO) {
11342 /* automatic parse from the BIOS config */
11343 err = alc882_parse_auto_config(codec);
11344 if (err < 0) {
11345 alc_free(codec);
11346 return err;
11347 } else if (!err) {
11348 printk(KERN_INFO
11349 "hda_codec: Cannot set up configuration "
11350 "from BIOS. Using base mode...\n");
11351 board_config = ALC882_3ST_DIG;
11355 if (has_cdefine_beep(codec)) {
11356 err = snd_hda_attach_beep_device(codec, 0x1);
11357 if (err < 0) {
11358 alc_free(codec);
11359 return err;
11363 if (board_config != ALC882_AUTO)
11364 setup_preset(codec, &alc882_presets[board_config]);
11366 spec->stream_analog_playback = &alc882_pcm_analog_playback;
11367 spec->stream_analog_capture = &alc882_pcm_analog_capture;
11368 /* FIXME: setup DAC5 */
11369 /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
11370 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
11372 spec->stream_digital_playback = &alc882_pcm_digital_playback;
11373 spec->stream_digital_capture = &alc882_pcm_digital_capture;
11375 if (!spec->adc_nids && spec->input_mux) {
11376 int i, j;
11377 spec->num_adc_nids = 0;
11378 for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) {
11379 const struct hda_input_mux *imux = spec->input_mux;
11380 hda_nid_t cap;
11381 hda_nid_t items[16];
11382 hda_nid_t nid = alc882_adc_nids[i];
11383 unsigned int wcap = get_wcaps(codec, nid);
11384 /* get type */
11385 wcap = get_wcaps_type(wcap);
11386 if (wcap != AC_WID_AUD_IN)
11387 continue;
11388 spec->private_adc_nids[spec->num_adc_nids] = nid;
11389 err = snd_hda_get_connections(codec, nid, &cap, 1);
11390 if (err < 0)
11391 continue;
11392 err = snd_hda_get_connections(codec, cap, items,
11393 ARRAY_SIZE(items));
11394 if (err < 0)
11395 continue;
11396 for (j = 0; j < imux->num_items; j++)
11397 if (imux->items[j].index >= err)
11398 break;
11399 if (j < imux->num_items)
11400 continue;
11401 spec->private_capsrc_nids[spec->num_adc_nids] = cap;
11402 spec->num_adc_nids++;
11404 spec->adc_nids = spec->private_adc_nids;
11405 spec->capsrc_nids = spec->private_capsrc_nids;
11408 set_capture_mixer(codec);
11410 if (has_cdefine_beep(codec))
11411 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
11413 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
11415 spec->vmaster_nid = 0x0c;
11417 codec->patch_ops = alc_patch_ops;
11418 if (board_config == ALC882_AUTO)
11419 spec->init_hook = alc882_auto_init;
11421 alc_init_jacks(codec);
11422 #ifdef CONFIG_SND_HDA_POWER_SAVE
11423 if (!spec->loopback.amplist)
11424 spec->loopback.amplist = alc882_loopbacks;
11425 #endif
11427 return 0;
11432 * ALC262 support
11435 #define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
11436 #define ALC262_DIGIN_NID ALC880_DIGIN_NID
11438 #define alc262_dac_nids alc260_dac_nids
11439 #define alc262_adc_nids alc882_adc_nids
11440 #define alc262_adc_nids_alt alc882_adc_nids_alt
11441 #define alc262_capsrc_nids alc882_capsrc_nids
11442 #define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
11444 #define alc262_modes alc260_modes
11445 #define alc262_capture_source alc882_capture_source
11447 static const hda_nid_t alc262_dmic_adc_nids[1] = {
11448 /* ADC0 */
11449 0x09
11452 static const hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
11454 static const struct snd_kcontrol_new alc262_base_mixer[] = {
11455 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11456 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
11457 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11458 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11459 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11460 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11461 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11462 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11463 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11464 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11465 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11466 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
11467 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
11468 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11469 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
11470 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
11471 { } /* end */
11474 /* update HP, line and mono-out pins according to the master switch */
11475 #define alc262_hp_master_update alc260_hp_master_update
11477 static void alc262_hp_bpc_setup(struct hda_codec *codec)
11479 struct alc_spec *spec = codec->spec;
11481 spec->autocfg.hp_pins[0] = 0x1b;
11482 spec->autocfg.speaker_pins[0] = 0x16;
11483 spec->automute = 1;
11484 spec->automute_mode = ALC_AUTOMUTE_PIN;
11487 static void alc262_hp_wildwest_setup(struct hda_codec *codec)
11489 struct alc_spec *spec = codec->spec;
11491 spec->autocfg.hp_pins[0] = 0x15;
11492 spec->autocfg.speaker_pins[0] = 0x16;
11493 spec->automute = 1;
11494 spec->automute_mode = ALC_AUTOMUTE_PIN;
11497 #define alc262_hp_master_sw_get alc260_hp_master_sw_get
11498 #define alc262_hp_master_sw_put alc260_hp_master_sw_put
11500 #define ALC262_HP_MASTER_SWITCH \
11502 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
11503 .name = "Master Playback Switch", \
11504 .info = snd_ctl_boolean_mono_info, \
11505 .get = alc262_hp_master_sw_get, \
11506 .put = alc262_hp_master_sw_put, \
11507 }, \
11509 .iface = NID_MAPPING, \
11510 .name = "Master Playback Switch", \
11511 .private_value = 0x15 | (0x16 << 8) | (0x1b << 16), \
11515 static const struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
11516 ALC262_HP_MASTER_SWITCH,
11517 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11518 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11519 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
11520 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
11521 HDA_OUTPUT),
11522 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
11523 HDA_OUTPUT),
11524 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11525 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11526 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11527 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11528 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11529 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
11530 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11531 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11532 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11533 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11534 HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
11535 HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
11536 { } /* end */
11539 static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
11540 ALC262_HP_MASTER_SWITCH,
11541 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11542 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
11543 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11544 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11545 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
11546 HDA_OUTPUT),
11547 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
11548 HDA_OUTPUT),
11549 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
11550 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
11551 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x1a, 0, HDA_INPUT),
11552 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
11553 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
11554 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11555 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11556 { } /* end */
11559 static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
11560 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11561 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11562 HDA_CODEC_VOLUME("Rear Mic Boost Volume", 0x18, 0, HDA_INPUT),
11563 { } /* end */
11566 /* mute/unmute internal speaker according to the hp jack and mute state */
11567 static void alc262_hp_t5735_setup(struct hda_codec *codec)
11569 struct alc_spec *spec = codec->spec;
11571 spec->autocfg.hp_pins[0] = 0x15;
11572 spec->autocfg.speaker_pins[0] = 0x14;
11573 spec->automute = 1;
11574 spec->automute_mode = ALC_AUTOMUTE_PIN;
11577 static const struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
11578 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11579 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
11580 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11581 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11582 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11583 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11584 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11585 { } /* end */
11588 static const struct hda_verb alc262_hp_t5735_verbs[] = {
11589 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11590 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11592 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
11596 static const struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
11597 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11598 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
11599 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
11600 HDA_CODEC_MUTE("Speaker Playback Switch", 0x16, 0x0, HDA_OUTPUT),
11601 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
11602 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
11603 { } /* end */
11606 static const struct hda_verb alc262_hp_rp5700_verbs[] = {
11607 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11608 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11609 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11610 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11611 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11612 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11613 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
11614 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
11615 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
11616 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
11620 static const struct hda_input_mux alc262_hp_rp5700_capture_source = {
11621 .num_items = 1,
11622 .items = {
11623 { "Line", 0x1 },
11627 /* bind hp and internal speaker mute (with plug check) as master switch */
11628 #define alc262_hippo_master_update alc262_hp_master_update
11629 #define alc262_hippo_master_sw_get alc262_hp_master_sw_get
11630 #define alc262_hippo_master_sw_put alc262_hp_master_sw_put
11632 #define ALC262_HIPPO_MASTER_SWITCH \
11634 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
11635 .name = "Master Playback Switch", \
11636 .info = snd_ctl_boolean_mono_info, \
11637 .get = alc262_hippo_master_sw_get, \
11638 .put = alc262_hippo_master_sw_put, \
11639 }, \
11641 .iface = NID_MAPPING, \
11642 .name = "Master Playback Switch", \
11643 .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
11644 (SUBDEV_SPEAKER(0) << 16), \
11647 static const struct snd_kcontrol_new alc262_hippo_mixer[] = {
11648 ALC262_HIPPO_MASTER_SWITCH,
11649 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11650 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11651 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11652 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11653 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11654 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11655 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11656 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11657 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11658 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11659 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
11660 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11661 { } /* end */
11664 static const struct snd_kcontrol_new alc262_hippo1_mixer[] = {
11665 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11666 ALC262_HIPPO_MASTER_SWITCH,
11667 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11668 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11669 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11670 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11671 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11672 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11673 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11674 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11675 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11676 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
11677 { } /* end */
11680 /* mute/unmute internal speaker according to the hp jack and mute state */
11681 static void alc262_hippo_setup(struct hda_codec *codec)
11683 struct alc_spec *spec = codec->spec;
11685 spec->autocfg.hp_pins[0] = 0x15;
11686 spec->autocfg.speaker_pins[0] = 0x14;
11687 spec->automute = 1;
11688 spec->automute_mode = ALC_AUTOMUTE_AMP;
11691 static void alc262_hippo1_setup(struct hda_codec *codec)
11693 struct alc_spec *spec = codec->spec;
11695 spec->autocfg.hp_pins[0] = 0x1b;
11696 spec->autocfg.speaker_pins[0] = 0x14;
11697 spec->automute = 1;
11698 spec->automute_mode = ALC_AUTOMUTE_AMP;
11702 static const struct snd_kcontrol_new alc262_sony_mixer[] = {
11703 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11704 ALC262_HIPPO_MASTER_SWITCH,
11705 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11706 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11707 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11708 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11709 { } /* end */
11712 static const struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
11713 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11714 ALC262_HIPPO_MASTER_SWITCH,
11715 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11716 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11717 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11718 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11719 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11720 { } /* end */
11723 static const struct snd_kcontrol_new alc262_tyan_mixer[] = {
11724 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11725 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
11726 HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT),
11727 HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT),
11728 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11729 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11730 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11731 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11732 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11733 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11734 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11735 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
11736 { } /* end */
11739 static const struct hda_verb alc262_tyan_verbs[] = {
11740 /* Headphone automute */
11741 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11742 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11743 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11745 /* P11 AUX_IN, white 4-pin connector */
11746 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11747 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1},
11748 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93},
11749 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19},
11754 /* unsolicited event for HP jack sensing */
11755 static void alc262_tyan_setup(struct hda_codec *codec)
11757 struct alc_spec *spec = codec->spec;
11759 spec->autocfg.hp_pins[0] = 0x1b;
11760 spec->autocfg.speaker_pins[0] = 0x15;
11761 spec->automute = 1;
11762 spec->automute_mode = ALC_AUTOMUTE_AMP;
11766 #define alc262_capture_mixer alc882_capture_mixer
11767 #define alc262_capture_alt_mixer alc882_capture_alt_mixer
11770 * generic initialization of ADC, input mixers and output mixers
11772 static const struct hda_verb alc262_init_verbs[] = {
11774 * Unmute ADC0-2 and set the default input to mic-in
11776 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11777 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11778 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11779 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11780 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11781 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11783 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
11784 * mixer widget
11785 * Note: PASD motherboards uses the Line In 2 as the input for
11786 * front panel mic (mic 2)
11788 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
11789 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11790 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11791 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11792 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11793 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11796 * Set up output mixers (0x0c - 0x0e)
11798 /* set vol=0 to output mixers */
11799 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11800 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11801 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11802 /* set up input amps for analog loopback */
11803 /* Amp Indices: DAC = 0, mixer = 1 */
11804 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11805 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11806 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11807 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11808 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11809 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11811 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
11812 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11813 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
11814 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11815 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11816 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11818 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11819 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11820 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11821 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11822 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11824 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
11825 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
11827 /* FIXME: use matrix-type input source selection */
11828 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
11829 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
11830 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11831 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11832 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11833 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11834 /* Input mixer2 */
11835 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11836 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11837 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11838 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11839 /* Input mixer3 */
11840 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11841 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11842 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11843 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11848 static const struct hda_verb alc262_eapd_verbs[] = {
11849 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
11850 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
11854 static const struct hda_verb alc262_hippo1_unsol_verbs[] = {
11855 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11856 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11857 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11859 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11860 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11864 static const struct hda_verb alc262_sony_unsol_verbs[] = {
11865 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11866 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11867 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic
11869 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11870 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11874 static const struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
11875 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11876 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
11877 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11878 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11879 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11880 { } /* end */
11883 static const struct hda_verb alc262_toshiba_s06_verbs[] = {
11884 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11885 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11886 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11887 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11888 {0x22, AC_VERB_SET_CONNECT_SEL, 0x09},
11889 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11890 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
11891 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11895 static void alc262_toshiba_s06_setup(struct hda_codec *codec)
11897 struct alc_spec *spec = codec->spec;
11899 spec->autocfg.hp_pins[0] = 0x15;
11900 spec->autocfg.speaker_pins[0] = 0x14;
11901 spec->ext_mic.pin = 0x18;
11902 spec->ext_mic.mux_idx = 0;
11903 spec->int_mic.pin = 0x12;
11904 spec->int_mic.mux_idx = 9;
11905 spec->auto_mic = 1;
11906 spec->automute = 1;
11907 spec->automute_mode = ALC_AUTOMUTE_PIN;
11911 * nec model
11912 * 0x15 = headphone
11913 * 0x16 = internal speaker
11914 * 0x18 = external mic
11917 static const struct snd_kcontrol_new alc262_nec_mixer[] = {
11918 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
11919 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
11921 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11922 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11923 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
11925 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11926 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11927 { } /* end */
11930 static const struct hda_verb alc262_nec_verbs[] = {
11931 /* Unmute Speaker */
11932 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11934 /* Headphone */
11935 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11936 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11938 /* External mic to headphone */
11939 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11940 /* External mic to speaker */
11941 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11946 * fujitsu model
11947 * 0x14 = headphone/spdif-out, 0x15 = internal speaker,
11948 * 0x1b = port replicator headphone out
11951 #define ALC_HP_EVENT ALC880_HP_EVENT
11953 static const struct hda_verb alc262_fujitsu_unsol_verbs[] = {
11954 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11955 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
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_unsol_verbs[] = {
11962 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11963 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11967 static const struct hda_verb alc262_lenovo_3000_init_verbs[] = {
11968 /* Front Mic pin: input vref at 50% */
11969 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
11970 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11974 static const struct hda_input_mux alc262_fujitsu_capture_source = {
11975 .num_items = 3,
11976 .items = {
11977 { "Mic", 0x0 },
11978 { "Internal Mic", 0x1 },
11979 { "CD", 0x4 },
11983 static const struct hda_input_mux alc262_HP_capture_source = {
11984 .num_items = 5,
11985 .items = {
11986 { "Mic", 0x0 },
11987 { "Front Mic", 0x1 },
11988 { "Line", 0x2 },
11989 { "CD", 0x4 },
11990 { "AUX IN", 0x6 },
11994 static const struct hda_input_mux alc262_HP_D7000_capture_source = {
11995 .num_items = 4,
11996 .items = {
11997 { "Mic", 0x0 },
11998 { "Front Mic", 0x2 },
11999 { "Line", 0x1 },
12000 { "CD", 0x4 },
12004 static void alc262_fujitsu_setup(struct hda_codec *codec)
12006 struct alc_spec *spec = codec->spec;
12008 spec->autocfg.hp_pins[0] = 0x14;
12009 spec->autocfg.hp_pins[1] = 0x1b;
12010 spec->autocfg.speaker_pins[0] = 0x15;
12011 spec->automute = 1;
12012 spec->automute_mode = ALC_AUTOMUTE_AMP;
12015 /* bind volumes of both NID 0x0c and 0x0d */
12016 static const struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
12017 .ops = &snd_hda_bind_vol,
12018 .values = {
12019 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
12020 HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
12025 static const struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
12026 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
12028 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12029 .name = "Master Playback Switch",
12030 .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
12031 .info = snd_ctl_boolean_mono_info,
12032 .get = alc262_hp_master_sw_get,
12033 .put = alc262_hp_master_sw_put,
12036 .iface = NID_MAPPING,
12037 .name = "Master Playback Switch",
12038 .private_value = 0x1b,
12040 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
12041 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
12042 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
12043 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
12044 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
12045 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
12046 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
12047 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
12048 { } /* end */
12051 static void alc262_lenovo_3000_setup(struct hda_codec *codec)
12053 struct alc_spec *spec = codec->spec;
12055 spec->autocfg.hp_pins[0] = 0x1b;
12056 spec->autocfg.speaker_pins[0] = 0x14;
12057 spec->autocfg.speaker_pins[1] = 0x16;
12058 spec->automute = 1;
12059 spec->automute_mode = ALC_AUTOMUTE_AMP;
12062 static const struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
12063 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
12065 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12066 .name = "Master Playback Switch",
12067 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
12068 .info = snd_ctl_boolean_mono_info,
12069 .get = alc262_hp_master_sw_get,
12070 .put = alc262_hp_master_sw_put,
12072 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
12073 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
12074 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
12075 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
12076 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
12077 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
12078 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
12079 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
12080 { } /* end */
12083 static const struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
12084 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
12085 ALC262_HIPPO_MASTER_SWITCH,
12086 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
12087 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
12088 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
12089 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
12090 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
12091 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
12092 { } /* end */
12095 /* additional init verbs for Benq laptops */
12096 static const struct hda_verb alc262_EAPD_verbs[] = {
12097 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
12098 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
12102 static const struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
12103 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
12104 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12106 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
12107 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
12111 /* Samsung Q1 Ultra Vista model setup */
12112 static const struct snd_kcontrol_new alc262_ultra_mixer[] = {
12113 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
12114 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
12115 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
12116 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
12117 HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
12118 HDA_CODEC_VOLUME("Headphone Mic Boost Volume", 0x15, 0, HDA_INPUT),
12119 { } /* end */
12122 static const struct hda_verb alc262_ultra_verbs[] = {
12123 /* output mixer */
12124 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12125 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12126 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12127 /* speaker */
12128 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
12129 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12130 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12131 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
12132 /* HP */
12133 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12134 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12135 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12136 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
12137 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
12138 /* internal mic */
12139 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
12140 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12141 /* ADC, choose mic */
12142 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12143 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12144 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12145 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
12146 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
12147 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
12148 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
12149 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
12150 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
12151 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
12155 /* mute/unmute internal speaker according to the hp jack and mute state */
12156 static void alc262_ultra_automute(struct hda_codec *codec)
12158 struct alc_spec *spec = codec->spec;
12159 unsigned int mute;
12161 mute = 0;
12162 /* auto-mute only when HP is used as HP */
12163 if (!spec->cur_mux[0]) {
12164 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
12165 if (spec->jack_present)
12166 mute = HDA_AMP_MUTE;
12168 /* mute/unmute internal speaker */
12169 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
12170 HDA_AMP_MUTE, mute);
12171 /* mute/unmute HP */
12172 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
12173 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
12176 /* unsolicited event for HP jack sensing */
12177 static void alc262_ultra_unsol_event(struct hda_codec *codec,
12178 unsigned int res)
12180 if ((res >> 26) != ALC880_HP_EVENT)
12181 return;
12182 alc262_ultra_automute(codec);
12185 static const struct hda_input_mux alc262_ultra_capture_source = {
12186 .num_items = 2,
12187 .items = {
12188 { "Mic", 0x1 },
12189 { "Headphone", 0x7 },
12193 static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
12194 struct snd_ctl_elem_value *ucontrol)
12196 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
12197 struct alc_spec *spec = codec->spec;
12198 int ret;
12200 ret = alc_mux_enum_put(kcontrol, ucontrol);
12201 if (!ret)
12202 return 0;
12203 /* reprogram the HP pin as mic or HP according to the input source */
12204 snd_hda_codec_write_cache(codec, 0x15, 0,
12205 AC_VERB_SET_PIN_WIDGET_CONTROL,
12206 spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
12207 alc262_ultra_automute(codec); /* mute/unmute HP */
12208 return ret;
12211 static const struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
12212 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
12213 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
12215 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12216 .name = "Capture Source",
12217 .info = alc_mux_enum_info,
12218 .get = alc_mux_enum_get,
12219 .put = alc262_ultra_mux_enum_put,
12222 .iface = NID_MAPPING,
12223 .name = "Capture Source",
12224 .private_value = 0x15,
12226 { } /* end */
12229 /* We use two mixers depending on the output pin; 0x16 is a mono output
12230 * and thus it's bound with a different mixer.
12231 * This function returns which mixer amp should be used.
12233 static int alc262_check_volbit(hda_nid_t nid)
12235 if (!nid)
12236 return 0;
12237 else if (nid == 0x16)
12238 return 2;
12239 else
12240 return 1;
12243 static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
12244 const char *pfx, int *vbits, int idx)
12246 unsigned long val;
12247 int vbit;
12249 vbit = alc262_check_volbit(nid);
12250 if (!vbit)
12251 return 0;
12252 if (*vbits & vbit) /* a volume control for this mixer already there */
12253 return 0;
12254 *vbits |= vbit;
12255 if (vbit == 2)
12256 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
12257 else
12258 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
12259 return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, val);
12262 static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
12263 const char *pfx, int idx)
12265 unsigned long val;
12267 if (!nid)
12268 return 0;
12269 if (nid == 0x16)
12270 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
12271 else
12272 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
12273 return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, val);
12276 /* add playback controls from the parsed DAC table */
12277 static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
12278 const struct auto_pin_cfg *cfg)
12280 const char *pfx;
12281 int vbits;
12282 int i, err;
12284 spec->multiout.num_dacs = 1; /* only use one dac */
12285 spec->multiout.dac_nids = spec->private_dac_nids;
12286 spec->private_dac_nids[0] = 2;
12288 pfx = alc_get_line_out_pfx(spec, true);
12289 if (!pfx)
12290 pfx = "Front";
12291 for (i = 0; i < 2; i++) {
12292 err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i);
12293 if (err < 0)
12294 return err;
12295 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
12296 err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[i],
12297 "Speaker", i);
12298 if (err < 0)
12299 return err;
12301 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
12302 err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[i],
12303 "Headphone", i);
12304 if (err < 0)
12305 return err;
12309 vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
12310 alc262_check_volbit(cfg->speaker_pins[0]) |
12311 alc262_check_volbit(cfg->hp_pins[0]);
12312 if (vbits == 1 || vbits == 2)
12313 pfx = "Master"; /* only one mixer is used */
12314 vbits = 0;
12315 for (i = 0; i < 2; i++) {
12316 err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx,
12317 &vbits, i);
12318 if (err < 0)
12319 return err;
12320 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
12321 err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[i],
12322 "Speaker", &vbits, i);
12323 if (err < 0)
12324 return err;
12326 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
12327 err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[i],
12328 "Headphone", &vbits, i);
12329 if (err < 0)
12330 return err;
12333 return 0;
12336 #define alc262_auto_create_input_ctls \
12337 alc882_auto_create_input_ctls
12340 * generic initialization of ADC, input mixers and output mixers
12342 static const struct hda_verb alc262_volume_init_verbs[] = {
12344 * Unmute ADC0-2 and set the default input to mic-in
12346 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
12347 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12348 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
12349 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12350 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
12351 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12353 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
12354 * mixer widget
12355 * Note: PASD motherboards uses the Line In 2 as the input for
12356 * front panel mic (mic 2)
12358 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
12359 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12360 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12361 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
12362 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
12363 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
12366 * Set up output mixers (0x0c - 0x0f)
12368 /* set vol=0 to output mixers */
12369 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12370 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12371 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12373 /* set up input amps for analog loopback */
12374 /* Amp Indices: DAC = 0, mixer = 1 */
12375 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12376 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12377 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12378 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12379 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12380 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12382 /* FIXME: use matrix-type input source selection */
12383 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
12384 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
12385 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12386 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12387 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12388 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12389 /* Input mixer2 */
12390 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12391 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12392 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12393 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12394 /* Input mixer3 */
12395 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12396 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12397 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12398 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12403 static const struct hda_verb alc262_HP_BPC_init_verbs[] = {
12405 * Unmute ADC0-2 and set the default input to mic-in
12407 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
12408 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12409 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
12410 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12411 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
12412 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12414 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
12415 * mixer widget
12416 * Note: PASD motherboards uses the Line In 2 as the input for
12417 * front panel mic (mic 2)
12419 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
12420 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12421 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12422 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
12423 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
12424 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
12425 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
12426 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
12429 * Set up output mixers (0x0c - 0x0e)
12431 /* set vol=0 to output mixers */
12432 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12433 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12434 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12436 /* set up input amps for analog loopback */
12437 /* Amp Indices: DAC = 0, mixer = 1 */
12438 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12439 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12440 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12441 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12442 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12443 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12445 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12446 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12447 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12449 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12450 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12452 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
12453 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
12455 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12456 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12457 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12458 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12459 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12461 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12462 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12463 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12464 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12465 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12466 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12469 /* FIXME: use matrix-type input source selection */
12470 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 0b, 12 */
12471 /* Input mixer1: only unmute Mic */
12472 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12473 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
12474 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12475 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12476 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12477 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
12478 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
12479 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
12480 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
12481 /* Input mixer2 */
12482 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12483 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
12484 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12485 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12486 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12487 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
12488 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
12489 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
12490 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
12491 /* Input mixer3 */
12492 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12493 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
12494 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12495 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12496 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12497 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
12498 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
12499 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
12500 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
12502 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12507 static const struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
12509 * Unmute ADC0-2 and set the default input to mic-in
12511 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
12512 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12513 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
12514 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12515 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
12516 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12518 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
12519 * mixer widget
12520 * Note: PASD motherboards uses the Line In 2 as the input for front
12521 * panel mic (mic 2)
12523 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
12524 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12525 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12526 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
12527 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
12528 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
12529 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
12530 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
12531 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
12533 * Set up output mixers (0x0c - 0x0e)
12535 /* set vol=0 to output mixers */
12536 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12537 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12538 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12540 /* set up input amps for analog loopback */
12541 /* Amp Indices: DAC = 0, mixer = 1 */
12542 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12543 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12544 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12545 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12546 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12547 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12550 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */
12551 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */
12552 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */
12553 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */
12554 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
12555 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */
12556 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */
12558 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12559 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12561 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
12562 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
12564 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
12565 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12566 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12567 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
12568 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12569 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12571 /* FIXME: use matrix-type input source selection */
12572 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
12573 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
12574 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
12575 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
12576 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
12577 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
12578 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
12579 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
12580 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
12581 /* Input mixer2 */
12582 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12583 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
12584 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
12585 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
12586 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
12587 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
12588 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
12589 /* Input mixer3 */
12590 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12591 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
12592 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
12593 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
12594 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
12595 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
12596 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
12598 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12603 static const struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
12605 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Front Speaker */
12606 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12607 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
12609 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* MIC jack */
12610 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
12611 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
12612 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
12614 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP jack */
12615 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
12616 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
12621 * Pin config fixes
12623 enum {
12624 PINFIX_FSC_H270,
12625 PINFIX_HP_Z200,
12628 static const struct alc_fixup alc262_fixups[] = {
12629 [PINFIX_FSC_H270] = {
12630 .type = ALC_FIXUP_PINS,
12631 .v.pins = (const struct alc_pincfg[]) {
12632 { 0x14, 0x99130110 }, /* speaker */
12633 { 0x15, 0x0221142f }, /* front HP */
12634 { 0x1b, 0x0121141f }, /* rear HP */
12638 [PINFIX_HP_Z200] = {
12639 .type = ALC_FIXUP_PINS,
12640 .v.pins = (const struct alc_pincfg[]) {
12641 { 0x16, 0x99130120 }, /* internal speaker */
12647 static const struct snd_pci_quirk alc262_fixup_tbl[] = {
12648 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
12649 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
12654 #ifdef CONFIG_SND_HDA_POWER_SAVE
12655 #define alc262_loopbacks alc880_loopbacks
12656 #endif
12658 /* pcm configuration: identical with ALC880 */
12659 #define alc262_pcm_analog_playback alc880_pcm_analog_playback
12660 #define alc262_pcm_analog_capture alc880_pcm_analog_capture
12661 #define alc262_pcm_digital_playback alc880_pcm_digital_playback
12662 #define alc262_pcm_digital_capture alc880_pcm_digital_capture
12665 * BIOS auto configuration
12667 static int alc262_parse_auto_config(struct hda_codec *codec)
12669 struct alc_spec *spec = codec->spec;
12670 int err;
12671 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
12673 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
12674 alc262_ignore);
12675 if (err < 0)
12676 return err;
12677 if (!spec->autocfg.line_outs) {
12678 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
12679 spec->multiout.max_channels = 2;
12680 spec->no_analog = 1;
12681 goto dig_only;
12683 return 0; /* can't find valid BIOS pin config */
12685 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
12686 if (err < 0)
12687 return err;
12688 err = alc262_auto_create_input_ctls(codec, &spec->autocfg);
12689 if (err < 0)
12690 return err;
12692 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
12694 dig_only:
12695 alc_auto_parse_digital(codec);
12697 if (spec->kctls.list)
12698 add_mixer(spec, spec->kctls.list);
12700 add_verb(spec, alc262_volume_init_verbs);
12701 spec->num_mux_defs = 1;
12702 spec->input_mux = &spec->private_imux[0];
12704 err = alc_auto_add_mic_boost(codec);
12705 if (err < 0)
12706 return err;
12708 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
12710 return 1;
12713 #define alc262_auto_init_multi_out alc882_auto_init_multi_out
12714 #define alc262_auto_init_hp_out alc882_auto_init_hp_out
12715 #define alc262_auto_init_analog_input alc882_auto_init_analog_input
12716 #define alc262_auto_init_input_src alc882_auto_init_input_src
12719 /* init callback for auto-configuration model -- overriding the default init */
12720 static void alc262_auto_init(struct hda_codec *codec)
12722 struct alc_spec *spec = codec->spec;
12723 alc262_auto_init_multi_out(codec);
12724 alc262_auto_init_hp_out(codec);
12725 alc262_auto_init_analog_input(codec);
12726 alc262_auto_init_input_src(codec);
12727 alc_auto_init_digital(codec);
12728 if (spec->unsol_event)
12729 alc_inithook(codec);
12733 * configuration and preset
12735 static const char * const alc262_models[ALC262_MODEL_LAST] = {
12736 [ALC262_BASIC] = "basic",
12737 [ALC262_HIPPO] = "hippo",
12738 [ALC262_HIPPO_1] = "hippo_1",
12739 [ALC262_FUJITSU] = "fujitsu",
12740 [ALC262_HP_BPC] = "hp-bpc",
12741 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
12742 [ALC262_HP_TC_T5735] = "hp-tc-t5735",
12743 [ALC262_HP_RP5700] = "hp-rp5700",
12744 [ALC262_BENQ_ED8] = "benq",
12745 [ALC262_BENQ_T31] = "benq-t31",
12746 [ALC262_SONY_ASSAMD] = "sony-assamd",
12747 [ALC262_TOSHIBA_S06] = "toshiba-s06",
12748 [ALC262_TOSHIBA_RX1] = "toshiba-rx1",
12749 [ALC262_ULTRA] = "ultra",
12750 [ALC262_LENOVO_3000] = "lenovo-3000",
12751 [ALC262_NEC] = "nec",
12752 [ALC262_TYAN] = "tyan",
12753 [ALC262_AUTO] = "auto",
12756 static const struct snd_pci_quirk alc262_cfg_tbl[] = {
12757 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
12758 SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
12759 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
12760 ALC262_HP_BPC),
12761 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series",
12762 ALC262_HP_BPC),
12763 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1500, "HP z series",
12764 ALC262_HP_BPC),
12765 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200",
12766 ALC262_AUTO),
12767 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
12768 ALC262_HP_BPC),
12769 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
12770 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
12771 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
12772 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
12773 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
12774 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
12775 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
12776 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
12777 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
12778 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
12779 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
12780 SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735",
12781 ALC262_HP_TC_T5735),
12782 SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700),
12783 SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
12784 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
12785 SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
12786 SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */
12787 SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06),
12788 SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO),
12789 SND_PCI_QUIRK(0x104d, 0x9047, "Sony VAIO Type G", ALC262_AUTO),
12790 #if 0 /* disable the quirk since model=auto works better in recent versions */
12791 SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
12792 ALC262_SONY_ASSAMD),
12793 #endif
12794 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
12795 ALC262_TOSHIBA_RX1),
12796 SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
12797 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
12798 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
12799 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN),
12800 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
12801 ALC262_ULTRA),
12802 SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
12803 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
12804 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
12805 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
12806 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
12810 static const struct alc_config_preset alc262_presets[] = {
12811 [ALC262_BASIC] = {
12812 .mixers = { alc262_base_mixer },
12813 .init_verbs = { alc262_init_verbs },
12814 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12815 .dac_nids = alc262_dac_nids,
12816 .hp_nid = 0x03,
12817 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12818 .channel_mode = alc262_modes,
12819 .input_mux = &alc262_capture_source,
12821 [ALC262_HIPPO] = {
12822 .mixers = { alc262_hippo_mixer },
12823 .init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
12824 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12825 .dac_nids = alc262_dac_nids,
12826 .hp_nid = 0x03,
12827 .dig_out_nid = ALC262_DIGOUT_NID,
12828 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12829 .channel_mode = alc262_modes,
12830 .input_mux = &alc262_capture_source,
12831 .unsol_event = alc_sku_unsol_event,
12832 .setup = alc262_hippo_setup,
12833 .init_hook = alc_inithook,
12835 [ALC262_HIPPO_1] = {
12836 .mixers = { alc262_hippo1_mixer },
12837 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
12838 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12839 .dac_nids = alc262_dac_nids,
12840 .hp_nid = 0x02,
12841 .dig_out_nid = ALC262_DIGOUT_NID,
12842 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12843 .channel_mode = alc262_modes,
12844 .input_mux = &alc262_capture_source,
12845 .unsol_event = alc_sku_unsol_event,
12846 .setup = alc262_hippo1_setup,
12847 .init_hook = alc_inithook,
12849 [ALC262_FUJITSU] = {
12850 .mixers = { alc262_fujitsu_mixer },
12851 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
12852 alc262_fujitsu_unsol_verbs },
12853 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12854 .dac_nids = alc262_dac_nids,
12855 .hp_nid = 0x03,
12856 .dig_out_nid = ALC262_DIGOUT_NID,
12857 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12858 .channel_mode = alc262_modes,
12859 .input_mux = &alc262_fujitsu_capture_source,
12860 .unsol_event = alc_sku_unsol_event,
12861 .setup = alc262_fujitsu_setup,
12862 .init_hook = alc_inithook,
12864 [ALC262_HP_BPC] = {
12865 .mixers = { alc262_HP_BPC_mixer },
12866 .init_verbs = { alc262_HP_BPC_init_verbs },
12867 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12868 .dac_nids = alc262_dac_nids,
12869 .hp_nid = 0x03,
12870 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12871 .channel_mode = alc262_modes,
12872 .input_mux = &alc262_HP_capture_source,
12873 .unsol_event = alc_sku_unsol_event,
12874 .setup = alc262_hp_bpc_setup,
12875 .init_hook = alc_inithook,
12877 [ALC262_HP_BPC_D7000_WF] = {
12878 .mixers = { alc262_HP_BPC_WildWest_mixer },
12879 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
12880 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12881 .dac_nids = alc262_dac_nids,
12882 .hp_nid = 0x03,
12883 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12884 .channel_mode = alc262_modes,
12885 .input_mux = &alc262_HP_D7000_capture_source,
12886 .unsol_event = alc_sku_unsol_event,
12887 .setup = alc262_hp_wildwest_setup,
12888 .init_hook = alc_inithook,
12890 [ALC262_HP_BPC_D7000_WL] = {
12891 .mixers = { alc262_HP_BPC_WildWest_mixer,
12892 alc262_HP_BPC_WildWest_option_mixer },
12893 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
12894 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12895 .dac_nids = alc262_dac_nids,
12896 .hp_nid = 0x03,
12897 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12898 .channel_mode = alc262_modes,
12899 .input_mux = &alc262_HP_D7000_capture_source,
12900 .unsol_event = alc_sku_unsol_event,
12901 .setup = alc262_hp_wildwest_setup,
12902 .init_hook = alc_inithook,
12904 [ALC262_HP_TC_T5735] = {
12905 .mixers = { alc262_hp_t5735_mixer },
12906 .init_verbs = { alc262_init_verbs, alc262_hp_t5735_verbs },
12907 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12908 .dac_nids = alc262_dac_nids,
12909 .hp_nid = 0x03,
12910 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12911 .channel_mode = alc262_modes,
12912 .input_mux = &alc262_capture_source,
12913 .unsol_event = alc_sku_unsol_event,
12914 .setup = alc262_hp_t5735_setup,
12915 .init_hook = alc_inithook,
12917 [ALC262_HP_RP5700] = {
12918 .mixers = { alc262_hp_rp5700_mixer },
12919 .init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs },
12920 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12921 .dac_nids = alc262_dac_nids,
12922 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12923 .channel_mode = alc262_modes,
12924 .input_mux = &alc262_hp_rp5700_capture_source,
12926 [ALC262_BENQ_ED8] = {
12927 .mixers = { alc262_base_mixer },
12928 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
12929 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12930 .dac_nids = alc262_dac_nids,
12931 .hp_nid = 0x03,
12932 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12933 .channel_mode = alc262_modes,
12934 .input_mux = &alc262_capture_source,
12936 [ALC262_SONY_ASSAMD] = {
12937 .mixers = { alc262_sony_mixer },
12938 .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
12939 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12940 .dac_nids = alc262_dac_nids,
12941 .hp_nid = 0x02,
12942 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12943 .channel_mode = alc262_modes,
12944 .input_mux = &alc262_capture_source,
12945 .unsol_event = alc_sku_unsol_event,
12946 .setup = alc262_hippo_setup,
12947 .init_hook = alc_inithook,
12949 [ALC262_BENQ_T31] = {
12950 .mixers = { alc262_benq_t31_mixer },
12951 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
12952 alc_hp15_unsol_verbs },
12953 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12954 .dac_nids = alc262_dac_nids,
12955 .hp_nid = 0x03,
12956 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12957 .channel_mode = alc262_modes,
12958 .input_mux = &alc262_capture_source,
12959 .unsol_event = alc_sku_unsol_event,
12960 .setup = alc262_hippo_setup,
12961 .init_hook = alc_inithook,
12963 [ALC262_ULTRA] = {
12964 .mixers = { alc262_ultra_mixer },
12965 .cap_mixer = alc262_ultra_capture_mixer,
12966 .init_verbs = { alc262_ultra_verbs },
12967 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12968 .dac_nids = alc262_dac_nids,
12969 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12970 .channel_mode = alc262_modes,
12971 .input_mux = &alc262_ultra_capture_source,
12972 .adc_nids = alc262_adc_nids, /* ADC0 */
12973 .capsrc_nids = alc262_capsrc_nids,
12974 .num_adc_nids = 1, /* single ADC */
12975 .unsol_event = alc262_ultra_unsol_event,
12976 .init_hook = alc262_ultra_automute,
12978 [ALC262_LENOVO_3000] = {
12979 .mixers = { alc262_lenovo_3000_mixer },
12980 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
12981 alc262_lenovo_3000_unsol_verbs,
12982 alc262_lenovo_3000_init_verbs },
12983 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12984 .dac_nids = alc262_dac_nids,
12985 .hp_nid = 0x03,
12986 .dig_out_nid = ALC262_DIGOUT_NID,
12987 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12988 .channel_mode = alc262_modes,
12989 .input_mux = &alc262_fujitsu_capture_source,
12990 .unsol_event = alc_sku_unsol_event,
12991 .setup = alc262_lenovo_3000_setup,
12992 .init_hook = alc_inithook,
12994 [ALC262_NEC] = {
12995 .mixers = { alc262_nec_mixer },
12996 .init_verbs = { alc262_nec_verbs },
12997 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12998 .dac_nids = alc262_dac_nids,
12999 .hp_nid = 0x03,
13000 .num_channel_mode = ARRAY_SIZE(alc262_modes),
13001 .channel_mode = alc262_modes,
13002 .input_mux = &alc262_capture_source,
13004 [ALC262_TOSHIBA_S06] = {
13005 .mixers = { alc262_toshiba_s06_mixer },
13006 .init_verbs = { alc262_init_verbs, alc262_toshiba_s06_verbs,
13007 alc262_eapd_verbs },
13008 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
13009 .capsrc_nids = alc262_dmic_capsrc_nids,
13010 .dac_nids = alc262_dac_nids,
13011 .adc_nids = alc262_dmic_adc_nids, /* ADC0 */
13012 .num_adc_nids = 1, /* single ADC */
13013 .dig_out_nid = ALC262_DIGOUT_NID,
13014 .num_channel_mode = ARRAY_SIZE(alc262_modes),
13015 .channel_mode = alc262_modes,
13016 .unsol_event = alc_sku_unsol_event,
13017 .setup = alc262_toshiba_s06_setup,
13018 .init_hook = alc_inithook,
13020 [ALC262_TOSHIBA_RX1] = {
13021 .mixers = { alc262_toshiba_rx1_mixer },
13022 .init_verbs = { alc262_init_verbs, alc262_toshiba_rx1_unsol_verbs },
13023 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
13024 .dac_nids = alc262_dac_nids,
13025 .hp_nid = 0x03,
13026 .num_channel_mode = ARRAY_SIZE(alc262_modes),
13027 .channel_mode = alc262_modes,
13028 .input_mux = &alc262_capture_source,
13029 .unsol_event = alc_sku_unsol_event,
13030 .setup = alc262_hippo_setup,
13031 .init_hook = alc_inithook,
13033 [ALC262_TYAN] = {
13034 .mixers = { alc262_tyan_mixer },
13035 .init_verbs = { alc262_init_verbs, alc262_tyan_verbs},
13036 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
13037 .dac_nids = alc262_dac_nids,
13038 .hp_nid = 0x02,
13039 .dig_out_nid = ALC262_DIGOUT_NID,
13040 .num_channel_mode = ARRAY_SIZE(alc262_modes),
13041 .channel_mode = alc262_modes,
13042 .input_mux = &alc262_capture_source,
13043 .unsol_event = alc_sku_unsol_event,
13044 .setup = alc262_tyan_setup,
13045 .init_hook = alc_hp_automute,
13049 static int patch_alc262(struct hda_codec *codec)
13051 struct alc_spec *spec;
13052 int board_config;
13053 int err;
13055 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
13056 if (spec == NULL)
13057 return -ENOMEM;
13059 codec->spec = spec;
13060 #if 0
13061 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
13062 * under-run
13065 int tmp;
13066 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
13067 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
13068 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
13069 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
13071 #endif
13072 alc_auto_parse_customize_define(codec);
13074 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
13076 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
13077 alc262_models,
13078 alc262_cfg_tbl);
13080 if (board_config < 0) {
13081 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
13082 codec->chip_name);
13083 board_config = ALC262_AUTO;
13086 if (board_config == ALC262_AUTO) {
13087 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
13088 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
13091 if (board_config == ALC262_AUTO) {
13092 /* automatic parse from the BIOS config */
13093 err = alc262_parse_auto_config(codec);
13094 if (err < 0) {
13095 alc_free(codec);
13096 return err;
13097 } else if (!err) {
13098 printk(KERN_INFO
13099 "hda_codec: Cannot set up configuration "
13100 "from BIOS. Using base mode...\n");
13101 board_config = ALC262_BASIC;
13105 if (!spec->no_analog && has_cdefine_beep(codec)) {
13106 err = snd_hda_attach_beep_device(codec, 0x1);
13107 if (err < 0) {
13108 alc_free(codec);
13109 return err;
13113 if (board_config != ALC262_AUTO)
13114 setup_preset(codec, &alc262_presets[board_config]);
13116 spec->stream_analog_playback = &alc262_pcm_analog_playback;
13117 spec->stream_analog_capture = &alc262_pcm_analog_capture;
13119 spec->stream_digital_playback = &alc262_pcm_digital_playback;
13120 spec->stream_digital_capture = &alc262_pcm_digital_capture;
13122 if (!spec->adc_nids && spec->input_mux) {
13123 int i;
13124 /* check whether the digital-mic has to be supported */
13125 for (i = 0; i < spec->input_mux->num_items; i++) {
13126 if (spec->input_mux->items[i].index >= 9)
13127 break;
13129 if (i < spec->input_mux->num_items) {
13130 /* use only ADC0 */
13131 spec->adc_nids = alc262_dmic_adc_nids;
13132 spec->num_adc_nids = 1;
13133 spec->capsrc_nids = alc262_dmic_capsrc_nids;
13134 } else {
13135 /* all analog inputs */
13136 /* check whether NID 0x07 is valid */
13137 unsigned int wcap = get_wcaps(codec, 0x07);
13139 /* get type */
13140 wcap = get_wcaps_type(wcap);
13141 if (wcap != AC_WID_AUD_IN) {
13142 spec->adc_nids = alc262_adc_nids_alt;
13143 spec->num_adc_nids =
13144 ARRAY_SIZE(alc262_adc_nids_alt);
13145 spec->capsrc_nids = alc262_capsrc_nids_alt;
13146 } else {
13147 spec->adc_nids = alc262_adc_nids;
13148 spec->num_adc_nids =
13149 ARRAY_SIZE(alc262_adc_nids);
13150 spec->capsrc_nids = alc262_capsrc_nids;
13154 if (!spec->cap_mixer && !spec->no_analog)
13155 set_capture_mixer(codec);
13156 if (!spec->no_analog && has_cdefine_beep(codec))
13157 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
13159 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
13161 spec->vmaster_nid = 0x0c;
13163 codec->patch_ops = alc_patch_ops;
13164 if (board_config == ALC262_AUTO)
13165 spec->init_hook = alc262_auto_init;
13166 spec->shutup = alc_eapd_shutup;
13168 alc_init_jacks(codec);
13169 #ifdef CONFIG_SND_HDA_POWER_SAVE
13170 if (!spec->loopback.amplist)
13171 spec->loopback.amplist = alc262_loopbacks;
13172 #endif
13174 return 0;
13178 * ALC268 channel source setting (2 channel)
13180 #define ALC268_DIGOUT_NID ALC880_DIGOUT_NID
13181 #define alc268_modes alc260_modes
13183 static const hda_nid_t alc268_dac_nids[2] = {
13184 /* front, hp */
13185 0x02, 0x03
13188 static const hda_nid_t alc268_adc_nids[2] = {
13189 /* ADC0-1 */
13190 0x08, 0x07
13193 static const hda_nid_t alc268_adc_nids_alt[1] = {
13194 /* ADC0 */
13195 0x08
13198 static const hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
13200 static const struct snd_kcontrol_new alc268_base_mixer[] = {
13201 /* output mixer control */
13202 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
13203 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13204 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
13205 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
13206 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13207 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
13208 HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
13212 static const struct snd_kcontrol_new alc268_toshiba_mixer[] = {
13213 /* output mixer control */
13214 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
13215 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
13216 ALC262_HIPPO_MASTER_SWITCH,
13217 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13218 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
13219 HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
13223 /* bind Beep switches of both NID 0x0f and 0x10 */
13224 static const struct hda_bind_ctls alc268_bind_beep_sw = {
13225 .ops = &snd_hda_bind_sw,
13226 .values = {
13227 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
13228 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
13233 static const struct snd_kcontrol_new alc268_beep_mixer[] = {
13234 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
13235 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
13239 static const struct hda_verb alc268_eapd_verbs[] = {
13240 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
13241 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
13245 /* Toshiba specific */
13246 static const struct hda_verb alc268_toshiba_verbs[] = {
13247 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13248 { } /* end */
13251 /* Acer specific */
13252 /* bind volumes of both NID 0x02 and 0x03 */
13253 static const struct hda_bind_ctls alc268_acer_bind_master_vol = {
13254 .ops = &snd_hda_bind_vol,
13255 .values = {
13256 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
13257 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
13262 static void alc268_acer_setup(struct hda_codec *codec)
13264 struct alc_spec *spec = codec->spec;
13266 spec->autocfg.hp_pins[0] = 0x14;
13267 spec->autocfg.speaker_pins[0] = 0x15;
13268 spec->automute = 1;
13269 spec->automute_mode = ALC_AUTOMUTE_AMP;
13272 #define alc268_acer_master_sw_get alc262_hp_master_sw_get
13273 #define alc268_acer_master_sw_put alc262_hp_master_sw_put
13275 static const struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
13276 /* output mixer control */
13277 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13279 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13280 .name = "Master Playback Switch",
13281 .subdevice = HDA_SUBDEV_NID_FLAG | 0x15,
13282 .info = snd_ctl_boolean_mono_info,
13283 .get = alc268_acer_master_sw_get,
13284 .put = alc268_acer_master_sw_put,
13286 HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
13290 static const struct snd_kcontrol_new alc268_acer_mixer[] = {
13291 /* output mixer control */
13292 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13294 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13295 .name = "Master Playback Switch",
13296 .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
13297 .info = snd_ctl_boolean_mono_info,
13298 .get = alc268_acer_master_sw_get,
13299 .put = alc268_acer_master_sw_put,
13301 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13302 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
13303 HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
13307 static const struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
13308 /* output mixer control */
13309 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13311 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13312 .name = "Master Playback Switch",
13313 .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
13314 .info = snd_ctl_boolean_mono_info,
13315 .get = alc268_acer_master_sw_get,
13316 .put = alc268_acer_master_sw_put,
13318 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13319 HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
13323 static const struct hda_verb alc268_acer_aspire_one_verbs[] = {
13324 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13325 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13326 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13327 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13328 {0x23, AC_VERB_SET_CONNECT_SEL, 0x06},
13329 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, 0xa017},
13333 static const struct hda_verb alc268_acer_verbs[] = {
13334 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
13335 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13336 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13337 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13338 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13339 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13340 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13344 /* unsolicited event for HP jack sensing */
13345 #define alc268_toshiba_setup alc262_hippo_setup
13347 static void alc268_acer_lc_setup(struct hda_codec *codec)
13349 struct alc_spec *spec = codec->spec;
13350 spec->autocfg.hp_pins[0] = 0x15;
13351 spec->autocfg.speaker_pins[0] = 0x14;
13352 spec->automute = 1;
13353 spec->automute_mode = ALC_AUTOMUTE_AMP;
13354 spec->ext_mic.pin = 0x18;
13355 spec->ext_mic.mux_idx = 0;
13356 spec->int_mic.pin = 0x12;
13357 spec->int_mic.mux_idx = 6;
13358 spec->auto_mic = 1;
13361 static const struct snd_kcontrol_new alc268_dell_mixer[] = {
13362 /* output mixer control */
13363 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13364 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13365 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13366 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
13367 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13368 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
13372 static const struct hda_verb alc268_dell_verbs[] = {
13373 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13374 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13375 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13376 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
13380 /* mute/unmute internal speaker according to the hp jack and mute state */
13381 static void alc268_dell_setup(struct hda_codec *codec)
13383 struct alc_spec *spec = codec->spec;
13385 spec->autocfg.hp_pins[0] = 0x15;
13386 spec->autocfg.speaker_pins[0] = 0x14;
13387 spec->ext_mic.pin = 0x18;
13388 spec->ext_mic.mux_idx = 0;
13389 spec->int_mic.pin = 0x19;
13390 spec->int_mic.mux_idx = 1;
13391 spec->auto_mic = 1;
13392 spec->automute = 1;
13393 spec->automute_mode = ALC_AUTOMUTE_PIN;
13396 static const struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
13397 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
13398 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13399 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
13400 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
13401 HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13402 HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
13403 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
13404 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
13408 static const struct hda_verb alc267_quanta_il1_verbs[] = {
13409 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13410 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
13414 static void alc267_quanta_il1_setup(struct hda_codec *codec)
13416 struct alc_spec *spec = codec->spec;
13417 spec->autocfg.hp_pins[0] = 0x15;
13418 spec->autocfg.speaker_pins[0] = 0x14;
13419 spec->ext_mic.pin = 0x18;
13420 spec->ext_mic.mux_idx = 0;
13421 spec->int_mic.pin = 0x19;
13422 spec->int_mic.mux_idx = 1;
13423 spec->auto_mic = 1;
13424 spec->automute = 1;
13425 spec->automute_mode = ALC_AUTOMUTE_PIN;
13429 * generic initialization of ADC, input mixers and output mixers
13431 static const struct hda_verb alc268_base_init_verbs[] = {
13432 /* Unmute DAC0-1 and set vol = 0 */
13433 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13434 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13437 * Set up output mixers (0x0c - 0x0e)
13439 /* set vol=0 to output mixers */
13440 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13441 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
13443 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13444 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13446 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
13447 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
13448 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
13449 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13450 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13451 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13452 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13453 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13455 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13456 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13457 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13458 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13459 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13461 /* set PCBEEP vol = 0, mute connections */
13462 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13463 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13464 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13466 /* Unmute Selector 23h,24h and set the default input to mic-in */
13468 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
13469 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13470 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
13471 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13477 * generic initialization of ADC, input mixers and output mixers
13479 static const struct hda_verb alc268_volume_init_verbs[] = {
13480 /* set output DAC */
13481 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13482 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13484 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13485 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13486 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13487 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13488 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13490 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13491 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13492 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13494 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13495 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13497 /* set PCBEEP vol = 0, mute connections */
13498 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13499 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13500 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13505 static const struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
13506 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13507 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
13508 { } /* end */
13511 static const struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
13512 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13513 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
13514 _DEFINE_CAPSRC(1),
13515 { } /* end */
13518 static const struct snd_kcontrol_new alc268_capture_mixer[] = {
13519 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13520 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
13521 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
13522 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
13523 _DEFINE_CAPSRC(2),
13524 { } /* end */
13527 static const struct hda_input_mux alc268_capture_source = {
13528 .num_items = 4,
13529 .items = {
13530 { "Mic", 0x0 },
13531 { "Front Mic", 0x1 },
13532 { "Line", 0x2 },
13533 { "CD", 0x3 },
13537 static const struct hda_input_mux alc268_acer_capture_source = {
13538 .num_items = 3,
13539 .items = {
13540 { "Mic", 0x0 },
13541 { "Internal Mic", 0x1 },
13542 { "Line", 0x2 },
13546 static const struct hda_input_mux alc268_acer_dmic_capture_source = {
13547 .num_items = 3,
13548 .items = {
13549 { "Mic", 0x0 },
13550 { "Internal Mic", 0x6 },
13551 { "Line", 0x2 },
13555 #ifdef CONFIG_SND_DEBUG
13556 static const struct snd_kcontrol_new alc268_test_mixer[] = {
13557 /* Volume widgets */
13558 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13559 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13560 HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),
13561 HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),
13562 HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),
13563 HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),
13564 HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),
13565 HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),
13566 HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),
13567 HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),
13568 HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),
13569 HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),
13570 HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),
13571 /* The below appears problematic on some hardwares */
13572 /*HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),*/
13573 HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13574 HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),
13575 HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),
13576 HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),
13578 /* Modes for retasking pin widgets */
13579 ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),
13580 ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),
13581 ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),
13582 ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),
13584 /* Controls for GPIO pins, assuming they are configured as outputs */
13585 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
13586 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
13587 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
13588 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
13590 /* Switches to allow the digital SPDIF output pin to be enabled.
13591 * The ALC268 does not have an SPDIF input.
13593 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),
13595 /* A switch allowing EAPD to be enabled. Some laptops seem to use
13596 * this output to turn on an external amplifier.
13598 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
13599 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
13601 { } /* end */
13603 #endif
13605 /* create input playback/capture controls for the given pin */
13606 static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
13607 const char *ctlname, int idx)
13609 hda_nid_t dac;
13610 int err;
13612 switch (nid) {
13613 case 0x14:
13614 case 0x16:
13615 dac = 0x02;
13616 break;
13617 case 0x15:
13618 case 0x1a: /* ALC259/269 only */
13619 case 0x1b: /* ALC259/269 only */
13620 case 0x21: /* ALC269vb has this pin, too */
13621 dac = 0x03;
13622 break;
13623 default:
13624 snd_printd(KERN_WARNING "hda_codec: "
13625 "ignoring pin 0x%x as unknown\n", nid);
13626 return 0;
13628 if (spec->multiout.dac_nids[0] != dac &&
13629 spec->multiout.dac_nids[1] != dac) {
13630 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
13631 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
13632 HDA_OUTPUT));
13633 if (err < 0)
13634 return err;
13635 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
13638 if (nid != 0x16)
13639 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
13640 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
13641 else /* mono */
13642 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
13643 HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT));
13644 if (err < 0)
13645 return err;
13646 return 0;
13649 /* add playback controls from the parsed DAC table */
13650 static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
13651 const struct auto_pin_cfg *cfg)
13653 hda_nid_t nid;
13654 int err;
13656 spec->multiout.dac_nids = spec->private_dac_nids;
13658 nid = cfg->line_out_pins[0];
13659 if (nid) {
13660 const char *name;
13661 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
13662 name = "Speaker";
13663 else
13664 name = "Front";
13665 err = alc268_new_analog_output(spec, nid, name, 0);
13666 if (err < 0)
13667 return err;
13670 nid = cfg->speaker_pins[0];
13671 if (nid == 0x1d) {
13672 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, "Speaker",
13673 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
13674 if (err < 0)
13675 return err;
13676 } else if (nid) {
13677 err = alc268_new_analog_output(spec, nid, "Speaker", 0);
13678 if (err < 0)
13679 return err;
13681 nid = cfg->hp_pins[0];
13682 if (nid) {
13683 err = alc268_new_analog_output(spec, nid, "Headphone", 0);
13684 if (err < 0)
13685 return err;
13688 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
13689 if (nid == 0x16) {
13690 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, "Mono",
13691 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT));
13692 if (err < 0)
13693 return err;
13695 return 0;
13698 /* create playback/capture controls for input pins */
13699 static int alc268_auto_create_input_ctls(struct hda_codec *codec,
13700 const struct auto_pin_cfg *cfg)
13702 return alc_auto_create_input_ctls(codec, cfg, 0, 0x23, 0x24);
13705 static void alc268_auto_set_output_and_unmute(struct hda_codec *codec,
13706 hda_nid_t nid, int pin_type)
13708 int idx;
13710 alc_set_pin_output(codec, nid, pin_type);
13711 if (nid == 0x14 || nid == 0x16)
13712 idx = 0;
13713 else
13714 idx = 1;
13715 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
13718 static void alc268_auto_init_multi_out(struct hda_codec *codec)
13720 struct alc_spec *spec = codec->spec;
13721 int i;
13723 for (i = 0; i < spec->autocfg.line_outs; i++) {
13724 hda_nid_t nid = spec->autocfg.line_out_pins[i];
13725 int pin_type = get_pin_type(spec->autocfg.line_out_type);
13726 alc268_auto_set_output_and_unmute(codec, nid, pin_type);
13730 static void alc268_auto_init_hp_out(struct hda_codec *codec)
13732 struct alc_spec *spec = codec->spec;
13733 hda_nid_t pin;
13734 int i;
13736 for (i = 0; i < spec->autocfg.hp_outs; i++) {
13737 pin = spec->autocfg.hp_pins[i];
13738 alc268_auto_set_output_and_unmute(codec, pin, PIN_HP);
13740 for (i = 0; i < spec->autocfg.speaker_outs; i++) {
13741 pin = spec->autocfg.speaker_pins[i];
13742 alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT);
13744 if (spec->autocfg.mono_out_pin)
13745 snd_hda_codec_write(codec, spec->autocfg.mono_out_pin, 0,
13746 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
13749 static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
13751 struct alc_spec *spec = codec->spec;
13752 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
13753 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
13754 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
13755 unsigned int dac_vol1, dac_vol2;
13757 if (line_nid == 0x1d || speaker_nid == 0x1d) {
13758 snd_hda_codec_write(codec, speaker_nid, 0,
13759 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
13760 /* mute mixer inputs from 0x1d */
13761 snd_hda_codec_write(codec, 0x0f, 0,
13762 AC_VERB_SET_AMP_GAIN_MUTE,
13763 AMP_IN_UNMUTE(1));
13764 snd_hda_codec_write(codec, 0x10, 0,
13765 AC_VERB_SET_AMP_GAIN_MUTE,
13766 AMP_IN_UNMUTE(1));
13767 } else {
13768 /* unmute mixer inputs from 0x1d */
13769 snd_hda_codec_write(codec, 0x0f, 0,
13770 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
13771 snd_hda_codec_write(codec, 0x10, 0,
13772 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
13775 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */
13776 if (line_nid == 0x14)
13777 dac_vol2 = AMP_OUT_ZERO;
13778 else if (line_nid == 0x15)
13779 dac_vol1 = AMP_OUT_ZERO;
13780 if (hp_nid == 0x14)
13781 dac_vol2 = AMP_OUT_ZERO;
13782 else if (hp_nid == 0x15)
13783 dac_vol1 = AMP_OUT_ZERO;
13784 if (line_nid != 0x16 || hp_nid != 0x16 ||
13785 spec->autocfg.line_out_pins[1] != 0x16 ||
13786 spec->autocfg.line_out_pins[2] != 0x16)
13787 dac_vol1 = dac_vol2 = AMP_OUT_ZERO;
13789 snd_hda_codec_write(codec, 0x02, 0,
13790 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);
13791 snd_hda_codec_write(codec, 0x03, 0,
13792 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);
13795 /* pcm configuration: identical with ALC880 */
13796 #define alc268_pcm_analog_playback alc880_pcm_analog_playback
13797 #define alc268_pcm_analog_capture alc880_pcm_analog_capture
13798 #define alc268_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
13799 #define alc268_pcm_digital_playback alc880_pcm_digital_playback
13802 * BIOS auto configuration
13804 static int alc268_parse_auto_config(struct hda_codec *codec)
13806 struct alc_spec *spec = codec->spec;
13807 int err;
13808 static const hda_nid_t alc268_ignore[] = { 0 };
13810 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
13811 alc268_ignore);
13812 if (err < 0)
13813 return err;
13814 if (!spec->autocfg.line_outs) {
13815 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
13816 spec->multiout.max_channels = 2;
13817 spec->no_analog = 1;
13818 goto dig_only;
13820 return 0; /* can't find valid BIOS pin config */
13822 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
13823 if (err < 0)
13824 return err;
13825 err = alc268_auto_create_input_ctls(codec, &spec->autocfg);
13826 if (err < 0)
13827 return err;
13829 spec->multiout.max_channels = 2;
13831 dig_only:
13832 /* digital only support output */
13833 alc_auto_parse_digital(codec);
13834 if (spec->kctls.list)
13835 add_mixer(spec, spec->kctls.list);
13837 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d)
13838 add_mixer(spec, alc268_beep_mixer);
13840 add_verb(spec, alc268_volume_init_verbs);
13841 spec->num_mux_defs = 2;
13842 spec->input_mux = &spec->private_imux[0];
13844 err = alc_auto_add_mic_boost(codec);
13845 if (err < 0)
13846 return err;
13848 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
13850 return 1;
13853 #define alc268_auto_init_analog_input alc882_auto_init_analog_input
13854 #define alc268_auto_init_input_src alc882_auto_init_input_src
13856 /* init callback for auto-configuration model -- overriding the default init */
13857 static void alc268_auto_init(struct hda_codec *codec)
13859 struct alc_spec *spec = codec->spec;
13860 alc268_auto_init_multi_out(codec);
13861 alc268_auto_init_hp_out(codec);
13862 alc268_auto_init_mono_speaker_out(codec);
13863 alc268_auto_init_analog_input(codec);
13864 alc268_auto_init_input_src(codec);
13865 alc_auto_init_digital(codec);
13866 if (spec->unsol_event)
13867 alc_inithook(codec);
13871 * configuration and preset
13873 static const char * const alc268_models[ALC268_MODEL_LAST] = {
13874 [ALC267_QUANTA_IL1] = "quanta-il1",
13875 [ALC268_3ST] = "3stack",
13876 [ALC268_TOSHIBA] = "toshiba",
13877 [ALC268_ACER] = "acer",
13878 [ALC268_ACER_DMIC] = "acer-dmic",
13879 [ALC268_ACER_ASPIRE_ONE] = "acer-aspire",
13880 [ALC268_DELL] = "dell",
13881 [ALC268_ZEPTO] = "zepto",
13882 #ifdef CONFIG_SND_DEBUG
13883 [ALC268_TEST] = "test",
13884 #endif
13885 [ALC268_AUTO] = "auto",
13888 static const struct snd_pci_quirk alc268_cfg_tbl[] = {
13889 SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
13890 SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
13891 SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
13892 SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
13893 SND_PCI_QUIRK(0x1025, 0x0136, "Acer Aspire 5315", ALC268_ACER),
13894 SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
13895 ALC268_ACER_ASPIRE_ONE),
13896 SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
13897 SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO),
13898 SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
13899 "Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
13900 /* almost compatible with toshiba but with optional digital outs;
13901 * auto-probing seems working fine
13903 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP TX25xx series",
13904 ALC268_AUTO),
13905 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
13906 SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
13907 SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
13908 SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
13912 /* Toshiba laptops have no unique PCI SSID but only codec SSID */
13913 static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
13914 SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
13915 SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
13916 SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
13917 ALC268_TOSHIBA),
13921 static const struct alc_config_preset alc268_presets[] = {
13922 [ALC267_QUANTA_IL1] = {
13923 .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
13924 alc268_capture_nosrc_mixer },
13925 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13926 alc267_quanta_il1_verbs },
13927 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13928 .dac_nids = alc268_dac_nids,
13929 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13930 .adc_nids = alc268_adc_nids_alt,
13931 .hp_nid = 0x03,
13932 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13933 .channel_mode = alc268_modes,
13934 .unsol_event = alc_sku_unsol_event,
13935 .setup = alc267_quanta_il1_setup,
13936 .init_hook = alc_inithook,
13938 [ALC268_3ST] = {
13939 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
13940 alc268_beep_mixer },
13941 .init_verbs = { alc268_base_init_verbs },
13942 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13943 .dac_nids = alc268_dac_nids,
13944 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13945 .adc_nids = alc268_adc_nids_alt,
13946 .capsrc_nids = alc268_capsrc_nids,
13947 .hp_nid = 0x03,
13948 .dig_out_nid = ALC268_DIGOUT_NID,
13949 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13950 .channel_mode = alc268_modes,
13951 .input_mux = &alc268_capture_source,
13953 [ALC268_TOSHIBA] = {
13954 .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
13955 alc268_beep_mixer },
13956 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13957 alc268_toshiba_verbs },
13958 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13959 .dac_nids = alc268_dac_nids,
13960 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13961 .adc_nids = alc268_adc_nids_alt,
13962 .capsrc_nids = alc268_capsrc_nids,
13963 .hp_nid = 0x03,
13964 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13965 .channel_mode = alc268_modes,
13966 .input_mux = &alc268_capture_source,
13967 .unsol_event = alc_sku_unsol_event,
13968 .setup = alc268_toshiba_setup,
13969 .init_hook = alc_inithook,
13971 [ALC268_ACER] = {
13972 .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
13973 alc268_beep_mixer },
13974 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13975 alc268_acer_verbs },
13976 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13977 .dac_nids = alc268_dac_nids,
13978 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13979 .adc_nids = alc268_adc_nids_alt,
13980 .capsrc_nids = alc268_capsrc_nids,
13981 .hp_nid = 0x02,
13982 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13983 .channel_mode = alc268_modes,
13984 .input_mux = &alc268_acer_capture_source,
13985 .unsol_event = alc_sku_unsol_event,
13986 .setup = alc268_acer_setup,
13987 .init_hook = alc_inithook,
13989 [ALC268_ACER_DMIC] = {
13990 .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
13991 alc268_beep_mixer },
13992 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13993 alc268_acer_verbs },
13994 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13995 .dac_nids = alc268_dac_nids,
13996 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13997 .adc_nids = alc268_adc_nids_alt,
13998 .capsrc_nids = alc268_capsrc_nids,
13999 .hp_nid = 0x02,
14000 .num_channel_mode = ARRAY_SIZE(alc268_modes),
14001 .channel_mode = alc268_modes,
14002 .input_mux = &alc268_acer_dmic_capture_source,
14003 .unsol_event = alc_sku_unsol_event,
14004 .setup = alc268_acer_setup,
14005 .init_hook = alc_inithook,
14007 [ALC268_ACER_ASPIRE_ONE] = {
14008 .mixers = { alc268_acer_aspire_one_mixer,
14009 alc268_beep_mixer,
14010 alc268_capture_nosrc_mixer },
14011 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
14012 alc268_acer_aspire_one_verbs },
14013 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
14014 .dac_nids = alc268_dac_nids,
14015 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
14016 .adc_nids = alc268_adc_nids_alt,
14017 .capsrc_nids = alc268_capsrc_nids,
14018 .hp_nid = 0x03,
14019 .num_channel_mode = ARRAY_SIZE(alc268_modes),
14020 .channel_mode = alc268_modes,
14021 .unsol_event = alc_sku_unsol_event,
14022 .setup = alc268_acer_lc_setup,
14023 .init_hook = alc_inithook,
14025 [ALC268_DELL] = {
14026 .mixers = { alc268_dell_mixer, alc268_beep_mixer,
14027 alc268_capture_nosrc_mixer },
14028 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
14029 alc268_dell_verbs },
14030 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
14031 .dac_nids = alc268_dac_nids,
14032 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
14033 .adc_nids = alc268_adc_nids_alt,
14034 .capsrc_nids = alc268_capsrc_nids,
14035 .hp_nid = 0x02,
14036 .num_channel_mode = ARRAY_SIZE(alc268_modes),
14037 .channel_mode = alc268_modes,
14038 .unsol_event = alc_sku_unsol_event,
14039 .setup = alc268_dell_setup,
14040 .init_hook = alc_inithook,
14042 [ALC268_ZEPTO] = {
14043 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
14044 alc268_beep_mixer },
14045 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
14046 alc268_toshiba_verbs },
14047 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
14048 .dac_nids = alc268_dac_nids,
14049 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
14050 .adc_nids = alc268_adc_nids_alt,
14051 .capsrc_nids = alc268_capsrc_nids,
14052 .hp_nid = 0x03,
14053 .dig_out_nid = ALC268_DIGOUT_NID,
14054 .num_channel_mode = ARRAY_SIZE(alc268_modes),
14055 .channel_mode = alc268_modes,
14056 .input_mux = &alc268_capture_source,
14057 .unsol_event = alc_sku_unsol_event,
14058 .setup = alc268_toshiba_setup,
14059 .init_hook = alc_inithook,
14061 #ifdef CONFIG_SND_DEBUG
14062 [ALC268_TEST] = {
14063 .mixers = { alc268_test_mixer, alc268_capture_mixer },
14064 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
14065 alc268_volume_init_verbs },
14066 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
14067 .dac_nids = alc268_dac_nids,
14068 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
14069 .adc_nids = alc268_adc_nids_alt,
14070 .capsrc_nids = alc268_capsrc_nids,
14071 .hp_nid = 0x03,
14072 .dig_out_nid = ALC268_DIGOUT_NID,
14073 .num_channel_mode = ARRAY_SIZE(alc268_modes),
14074 .channel_mode = alc268_modes,
14075 .input_mux = &alc268_capture_source,
14077 #endif
14080 static int patch_alc268(struct hda_codec *codec)
14082 struct alc_spec *spec;
14083 int board_config;
14084 int i, has_beep, err;
14086 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
14087 if (spec == NULL)
14088 return -ENOMEM;
14090 codec->spec = spec;
14092 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,
14093 alc268_models,
14094 alc268_cfg_tbl);
14096 if (board_config < 0 || board_config >= ALC268_MODEL_LAST)
14097 board_config = snd_hda_check_board_codec_sid_config(codec,
14098 ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
14100 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
14101 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
14102 codec->chip_name);
14103 board_config = ALC268_AUTO;
14106 if (board_config == ALC268_AUTO) {
14107 /* automatic parse from the BIOS config */
14108 err = alc268_parse_auto_config(codec);
14109 if (err < 0) {
14110 alc_free(codec);
14111 return err;
14112 } else if (!err) {
14113 printk(KERN_INFO
14114 "hda_codec: Cannot set up configuration "
14115 "from BIOS. Using base mode...\n");
14116 board_config = ALC268_3ST;
14120 if (board_config != ALC268_AUTO)
14121 setup_preset(codec, &alc268_presets[board_config]);
14123 spec->stream_analog_playback = &alc268_pcm_analog_playback;
14124 spec->stream_analog_capture = &alc268_pcm_analog_capture;
14125 spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;
14127 spec->stream_digital_playback = &alc268_pcm_digital_playback;
14129 has_beep = 0;
14130 for (i = 0; i < spec->num_mixers; i++) {
14131 if (spec->mixers[i] == alc268_beep_mixer) {
14132 has_beep = 1;
14133 break;
14137 if (has_beep) {
14138 err = snd_hda_attach_beep_device(codec, 0x1);
14139 if (err < 0) {
14140 alc_free(codec);
14141 return err;
14143 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
14144 /* override the amp caps for beep generator */
14145 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
14146 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
14147 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
14148 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
14149 (0 << AC_AMPCAP_MUTE_SHIFT));
14152 if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
14153 /* check whether NID 0x07 is valid */
14154 unsigned int wcap = get_wcaps(codec, 0x07);
14156 spec->capsrc_nids = alc268_capsrc_nids;
14157 /* get type */
14158 wcap = get_wcaps_type(wcap);
14159 if (spec->auto_mic ||
14160 wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
14161 spec->adc_nids = alc268_adc_nids_alt;
14162 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
14163 if (spec->auto_mic)
14164 fixup_automic_adc(codec);
14165 if (spec->auto_mic || spec->input_mux->num_items == 1)
14166 add_mixer(spec, alc268_capture_nosrc_mixer);
14167 else
14168 add_mixer(spec, alc268_capture_alt_mixer);
14169 } else {
14170 spec->adc_nids = alc268_adc_nids;
14171 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
14172 add_mixer(spec, alc268_capture_mixer);
14176 spec->vmaster_nid = 0x02;
14178 codec->patch_ops = alc_patch_ops;
14179 if (board_config == ALC268_AUTO)
14180 spec->init_hook = alc268_auto_init;
14181 spec->shutup = alc_eapd_shutup;
14183 alc_init_jacks(codec);
14185 return 0;
14189 * ALC269 channel source setting (2 channel)
14191 #define ALC269_DIGOUT_NID ALC880_DIGOUT_NID
14193 #define alc269_dac_nids alc260_dac_nids
14195 static const hda_nid_t alc269_adc_nids[1] = {
14196 /* ADC1 */
14197 0x08,
14200 static const hda_nid_t alc269_capsrc_nids[1] = {
14201 0x23,
14204 static const hda_nid_t alc269vb_adc_nids[1] = {
14205 /* ADC1 */
14206 0x09,
14209 static const hda_nid_t alc269vb_capsrc_nids[1] = {
14210 0x22,
14213 static const hda_nid_t alc269_adc_candidates[] = {
14214 0x08, 0x09, 0x07, 0x11,
14217 #define alc269_modes alc260_modes
14218 #define alc269_capture_source alc880_lg_lw_capture_source
14220 static const struct snd_kcontrol_new alc269_base_mixer[] = {
14221 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14222 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
14223 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
14224 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
14225 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
14226 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14227 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14228 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
14229 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
14230 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
14231 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
14232 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
14233 { } /* end */
14236 static const struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
14237 /* output mixer control */
14238 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
14240 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14241 .name = "Master Playback Switch",
14242 .subdevice = HDA_SUBDEV_AMP_FLAG,
14243 .info = snd_hda_mixer_amp_switch_info,
14244 .get = snd_hda_mixer_amp_switch_get,
14245 .put = alc268_acer_master_sw_put,
14246 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
14248 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
14249 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14250 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14251 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
14252 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
14253 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
14257 static const struct snd_kcontrol_new alc269_lifebook_mixer[] = {
14258 /* output mixer control */
14259 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
14261 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14262 .name = "Master Playback Switch",
14263 .subdevice = HDA_SUBDEV_AMP_FLAG,
14264 .info = snd_hda_mixer_amp_switch_info,
14265 .get = snd_hda_mixer_amp_switch_get,
14266 .put = alc268_acer_master_sw_put,
14267 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
14269 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
14270 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14271 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14272 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
14273 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
14274 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
14275 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
14276 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
14277 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x1b, 0, HDA_INPUT),
14281 static const struct snd_kcontrol_new alc269_laptop_mixer[] = {
14282 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
14283 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14284 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
14285 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
14286 { } /* end */
14289 static const struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
14290 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
14291 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14292 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
14293 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
14294 { } /* end */
14297 static const struct snd_kcontrol_new alc269_asus_mixer[] = {
14298 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14299 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x0, HDA_INPUT),
14300 { } /* end */
14303 /* capture mixer elements */
14304 static const struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
14305 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
14306 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
14307 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14308 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
14309 { } /* end */
14312 static const struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
14313 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
14314 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
14315 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14316 { } /* end */
14319 static const struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
14320 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
14321 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
14322 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14323 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
14324 { } /* end */
14327 static const struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
14328 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
14329 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
14330 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
14331 { } /* end */
14334 /* FSC amilo */
14335 #define alc269_fujitsu_mixer alc269_laptop_mixer
14337 static const struct hda_verb alc269_quanta_fl1_verbs[] = {
14338 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
14339 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14340 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14341 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
14342 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14343 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14347 static const struct hda_verb alc269_lifebook_verbs[] = {
14348 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
14349 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
14350 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14351 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14352 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
14353 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14354 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14355 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
14356 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14357 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14361 /* toggle speaker-output according to the hp-jack state */
14362 static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
14364 alc_hp_automute(codec);
14366 snd_hda_codec_write(codec, 0x20, 0,
14367 AC_VERB_SET_COEF_INDEX, 0x0c);
14368 snd_hda_codec_write(codec, 0x20, 0,
14369 AC_VERB_SET_PROC_COEF, 0x680);
14371 snd_hda_codec_write(codec, 0x20, 0,
14372 AC_VERB_SET_COEF_INDEX, 0x0c);
14373 snd_hda_codec_write(codec, 0x20, 0,
14374 AC_VERB_SET_PROC_COEF, 0x480);
14377 #define alc269_lifebook_speaker_automute \
14378 alc269_quanta_fl1_speaker_automute
14380 static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
14382 unsigned int present_laptop;
14383 unsigned int present_dock;
14385 present_laptop = snd_hda_jack_detect(codec, 0x18);
14386 present_dock = snd_hda_jack_detect(codec, 0x1b);
14388 /* Laptop mic port overrides dock mic port, design decision */
14389 if (present_dock)
14390 snd_hda_codec_write(codec, 0x23, 0,
14391 AC_VERB_SET_CONNECT_SEL, 0x3);
14392 if (present_laptop)
14393 snd_hda_codec_write(codec, 0x23, 0,
14394 AC_VERB_SET_CONNECT_SEL, 0x0);
14395 if (!present_dock && !present_laptop)
14396 snd_hda_codec_write(codec, 0x23, 0,
14397 AC_VERB_SET_CONNECT_SEL, 0x1);
14400 static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
14401 unsigned int res)
14403 switch (res >> 26) {
14404 case ALC880_HP_EVENT:
14405 alc269_quanta_fl1_speaker_automute(codec);
14406 break;
14407 case ALC880_MIC_EVENT:
14408 alc_mic_automute(codec);
14409 break;
14413 static void alc269_lifebook_unsol_event(struct hda_codec *codec,
14414 unsigned int res)
14416 if ((res >> 26) == ALC880_HP_EVENT)
14417 alc269_lifebook_speaker_automute(codec);
14418 if ((res >> 26) == ALC880_MIC_EVENT)
14419 alc269_lifebook_mic_autoswitch(codec);
14422 static void alc269_quanta_fl1_setup(struct hda_codec *codec)
14424 struct alc_spec *spec = codec->spec;
14425 spec->autocfg.hp_pins[0] = 0x15;
14426 spec->autocfg.speaker_pins[0] = 0x14;
14427 spec->automute_mixer_nid[0] = 0x0c;
14428 spec->automute = 1;
14429 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14430 spec->ext_mic.pin = 0x18;
14431 spec->ext_mic.mux_idx = 0;
14432 spec->int_mic.pin = 0x19;
14433 spec->int_mic.mux_idx = 1;
14434 spec->auto_mic = 1;
14437 static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
14439 alc269_quanta_fl1_speaker_automute(codec);
14440 alc_mic_automute(codec);
14443 static void alc269_lifebook_setup(struct hda_codec *codec)
14445 struct alc_spec *spec = codec->spec;
14446 spec->autocfg.hp_pins[0] = 0x15;
14447 spec->autocfg.hp_pins[1] = 0x1a;
14448 spec->autocfg.speaker_pins[0] = 0x14;
14449 spec->automute_mixer_nid[0] = 0x0c;
14450 spec->automute = 1;
14451 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14454 static void alc269_lifebook_init_hook(struct hda_codec *codec)
14456 alc269_lifebook_speaker_automute(codec);
14457 alc269_lifebook_mic_autoswitch(codec);
14460 static const struct hda_verb alc269_laptop_dmic_init_verbs[] = {
14461 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
14462 {0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
14463 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14464 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
14465 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14466 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14467 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14471 static const struct hda_verb alc269_laptop_amic_init_verbs[] = {
14472 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
14473 {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
14474 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14475 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))},
14476 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14477 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14481 static const struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
14482 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
14483 {0x22, AC_VERB_SET_CONNECT_SEL, 0x06},
14484 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14485 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
14486 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14487 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14488 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14492 static const struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
14493 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
14494 {0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
14495 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14496 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
14497 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14498 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14499 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14503 static const struct hda_verb alc271_acer_dmic_verbs[] = {
14504 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
14505 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
14506 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14507 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14508 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14509 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14510 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00},
14511 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14512 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14513 {0x22, AC_VERB_SET_CONNECT_SEL, 6},
14517 static void alc269_laptop_amic_setup(struct hda_codec *codec)
14519 struct alc_spec *spec = codec->spec;
14520 spec->autocfg.hp_pins[0] = 0x15;
14521 spec->autocfg.speaker_pins[0] = 0x14;
14522 spec->automute_mixer_nid[0] = 0x0c;
14523 spec->automute = 1;
14524 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14525 spec->ext_mic.pin = 0x18;
14526 spec->ext_mic.mux_idx = 0;
14527 spec->int_mic.pin = 0x19;
14528 spec->int_mic.mux_idx = 1;
14529 spec->auto_mic = 1;
14532 static void alc269_laptop_dmic_setup(struct hda_codec *codec)
14534 struct alc_spec *spec = codec->spec;
14535 spec->autocfg.hp_pins[0] = 0x15;
14536 spec->autocfg.speaker_pins[0] = 0x14;
14537 spec->automute_mixer_nid[0] = 0x0c;
14538 spec->automute = 1;
14539 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14540 spec->ext_mic.pin = 0x18;
14541 spec->ext_mic.mux_idx = 0;
14542 spec->int_mic.pin = 0x12;
14543 spec->int_mic.mux_idx = 5;
14544 spec->auto_mic = 1;
14547 static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
14549 struct alc_spec *spec = codec->spec;
14550 spec->autocfg.hp_pins[0] = 0x21;
14551 spec->autocfg.speaker_pins[0] = 0x14;
14552 spec->automute_mixer_nid[0] = 0x0c;
14553 spec->automute = 1;
14554 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14555 spec->ext_mic.pin = 0x18;
14556 spec->ext_mic.mux_idx = 0;
14557 spec->int_mic.pin = 0x19;
14558 spec->int_mic.mux_idx = 1;
14559 spec->auto_mic = 1;
14562 static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
14564 struct alc_spec *spec = codec->spec;
14565 spec->autocfg.hp_pins[0] = 0x21;
14566 spec->autocfg.speaker_pins[0] = 0x14;
14567 spec->automute_mixer_nid[0] = 0x0c;
14568 spec->automute = 1;
14569 spec->automute_mode = ALC_AUTOMUTE_MIXER;
14570 spec->ext_mic.pin = 0x18;
14571 spec->ext_mic.mux_idx = 0;
14572 spec->int_mic.pin = 0x12;
14573 spec->int_mic.mux_idx = 6;
14574 spec->auto_mic = 1;
14578 * generic initialization of ADC, input mixers and output mixers
14580 static const struct hda_verb alc269_init_verbs[] = {
14582 * Unmute ADC0 and set the default input to mic-in
14584 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14587 * Set up output mixers (0x02 - 0x03)
14589 /* set vol=0 to output mixers */
14590 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14591 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14593 /* set up input amps for analog loopback */
14594 /* Amp Indices: DAC = 0, mixer = 1 */
14595 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14596 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14597 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14598 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14599 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14600 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14602 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14603 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14604 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14605 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14606 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14607 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14608 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14610 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14611 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14613 /* FIXME: use Mux-type input source selection */
14614 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
14615 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
14616 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
14618 /* set EAPD */
14619 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
14623 static const struct hda_verb alc269vb_init_verbs[] = {
14625 * Unmute ADC0 and set the default input to mic-in
14627 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14630 * Set up output mixers (0x02 - 0x03)
14632 /* set vol=0 to output mixers */
14633 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14634 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14636 /* set up input amps for analog loopback */
14637 /* Amp Indices: DAC = 0, mixer = 1 */
14638 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14639 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14640 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14641 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14642 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14643 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14645 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14646 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14647 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14648 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14649 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14650 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14651 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14653 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14654 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14656 /* FIXME: use Mux-type input source selection */
14657 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
14658 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
14659 {0x22, AC_VERB_SET_CONNECT_SEL, 0x00},
14661 /* set EAPD */
14662 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
14666 #define alc269_auto_create_multi_out_ctls \
14667 alc268_auto_create_multi_out_ctls
14668 #define alc269_auto_create_input_ctls \
14669 alc268_auto_create_input_ctls
14671 #ifdef CONFIG_SND_HDA_POWER_SAVE
14672 #define alc269_loopbacks alc880_loopbacks
14673 #endif
14675 /* pcm configuration: identical with ALC880 */
14676 #define alc269_pcm_analog_playback alc880_pcm_analog_playback
14677 #define alc269_pcm_analog_capture alc880_pcm_analog_capture
14678 #define alc269_pcm_digital_playback alc880_pcm_digital_playback
14679 #define alc269_pcm_digital_capture alc880_pcm_digital_capture
14681 static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
14682 .substreams = 1,
14683 .channels_min = 2,
14684 .channels_max = 8,
14685 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
14686 /* NID is set in alc_build_pcms */
14687 .ops = {
14688 .open = alc880_playback_pcm_open,
14689 .prepare = alc880_playback_pcm_prepare,
14690 .cleanup = alc880_playback_pcm_cleanup
14694 static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
14695 .substreams = 1,
14696 .channels_min = 2,
14697 .channels_max = 2,
14698 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
14699 /* NID is set in alc_build_pcms */
14702 #ifdef CONFIG_SND_HDA_POWER_SAVE
14703 static int alc269_mic2_for_mute_led(struct hda_codec *codec)
14705 switch (codec->subsystem_id) {
14706 case 0x103c1586:
14707 return 1;
14709 return 0;
14712 static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
14714 /* update mute-LED according to the speaker mute state */
14715 if (nid == 0x01 || nid == 0x14) {
14716 int pinval;
14717 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
14718 HDA_AMP_MUTE)
14719 pinval = 0x24;
14720 else
14721 pinval = 0x20;
14722 /* mic2 vref pin is used for mute LED control */
14723 snd_hda_codec_update_cache(codec, 0x19, 0,
14724 AC_VERB_SET_PIN_WIDGET_CONTROL,
14725 pinval);
14727 return alc_check_power_status(codec, nid);
14729 #endif /* CONFIG_SND_HDA_POWER_SAVE */
14731 static int alc275_setup_dual_adc(struct hda_codec *codec)
14733 struct alc_spec *spec = codec->spec;
14735 if (codec->vendor_id != 0x10ec0275 || !spec->auto_mic)
14736 return 0;
14737 if ((spec->ext_mic.pin >= 0x18 && spec->int_mic.pin <= 0x13) ||
14738 (spec->ext_mic.pin <= 0x12 && spec->int_mic.pin >= 0x18)) {
14739 if (spec->ext_mic.pin <= 0x12) {
14740 spec->private_adc_nids[0] = 0x08;
14741 spec->private_adc_nids[1] = 0x11;
14742 spec->private_capsrc_nids[0] = 0x23;
14743 spec->private_capsrc_nids[1] = 0x22;
14744 } else {
14745 spec->private_adc_nids[0] = 0x11;
14746 spec->private_adc_nids[1] = 0x08;
14747 spec->private_capsrc_nids[0] = 0x22;
14748 spec->private_capsrc_nids[1] = 0x23;
14750 spec->adc_nids = spec->private_adc_nids;
14751 spec->capsrc_nids = spec->private_capsrc_nids;
14752 spec->num_adc_nids = 2;
14753 spec->dual_adc_switch = 1;
14754 snd_printdd("realtek: enabling dual ADC switchg (%02x:%02x)\n",
14755 spec->adc_nids[0], spec->adc_nids[1]);
14756 return 1;
14758 return 0;
14761 /* different alc269-variants */
14762 enum {
14763 ALC269_TYPE_NORMAL,
14764 ALC269_TYPE_ALC258,
14765 ALC269_TYPE_ALC259,
14766 ALC269_TYPE_ALC269VB,
14767 ALC269_TYPE_ALC270,
14768 ALC269_TYPE_ALC271X,
14772 * BIOS auto configuration
14774 static int alc269_parse_auto_config(struct hda_codec *codec)
14776 struct alc_spec *spec = codec->spec;
14777 int err;
14778 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
14780 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
14781 alc269_ignore);
14782 if (err < 0)
14783 return err;
14785 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
14786 if (err < 0)
14787 return err;
14788 if (spec->codec_variant == ALC269_TYPE_NORMAL)
14789 err = alc269_auto_create_input_ctls(codec, &spec->autocfg);
14790 else
14791 err = alc_auto_create_input_ctls(codec, &spec->autocfg, 0,
14792 0x22, 0);
14793 if (err < 0)
14794 return err;
14796 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
14798 alc_auto_parse_digital(codec);
14800 if (spec->kctls.list)
14801 add_mixer(spec, spec->kctls.list);
14803 if (spec->codec_variant != ALC269_TYPE_NORMAL) {
14804 add_verb(spec, alc269vb_init_verbs);
14805 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
14806 } else {
14807 add_verb(spec, alc269_init_verbs);
14808 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
14811 spec->num_mux_defs = 1;
14812 spec->input_mux = &spec->private_imux[0];
14814 if (!alc275_setup_dual_adc(codec))
14815 fillup_priv_adc_nids(codec, alc269_adc_candidates,
14816 sizeof(alc269_adc_candidates));
14818 err = alc_auto_add_mic_boost(codec);
14819 if (err < 0)
14820 return err;
14822 if (!spec->cap_mixer && !spec->no_analog)
14823 set_capture_mixer(codec);
14825 return 1;
14828 #define alc269_auto_init_multi_out alc268_auto_init_multi_out
14829 #define alc269_auto_init_hp_out alc268_auto_init_hp_out
14830 #define alc269_auto_init_analog_input alc882_auto_init_analog_input
14831 #define alc269_auto_init_input_src alc882_auto_init_input_src
14834 /* init callback for auto-configuration model -- overriding the default init */
14835 static void alc269_auto_init(struct hda_codec *codec)
14837 struct alc_spec *spec = codec->spec;
14838 alc269_auto_init_multi_out(codec);
14839 alc269_auto_init_hp_out(codec);
14840 alc269_auto_init_analog_input(codec);
14841 if (!spec->dual_adc_switch)
14842 alc269_auto_init_input_src(codec);
14843 alc_auto_init_digital(codec);
14844 if (spec->unsol_event)
14845 alc_inithook(codec);
14848 static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
14850 int val = alc_read_coef_idx(codec, 0x04);
14851 if (power_up)
14852 val |= 1 << 11;
14853 else
14854 val &= ~(1 << 11);
14855 alc_write_coef_idx(codec, 0x04, val);
14858 static void alc269_shutup(struct hda_codec *codec)
14860 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
14861 alc269_toggle_power_output(codec, 0);
14862 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
14863 alc269_toggle_power_output(codec, 0);
14864 msleep(150);
14868 #ifdef SND_HDA_NEEDS_RESUME
14869 static int alc269_resume(struct hda_codec *codec)
14871 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
14872 alc269_toggle_power_output(codec, 0);
14873 msleep(150);
14876 codec->patch_ops.init(codec);
14878 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
14879 alc269_toggle_power_output(codec, 1);
14880 msleep(200);
14883 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
14884 alc269_toggle_power_output(codec, 1);
14886 snd_hda_codec_resume_amp(codec);
14887 snd_hda_codec_resume_cache(codec);
14888 hda_call_check_power_status(codec, 0x01);
14889 return 0;
14891 #endif /* SND_HDA_NEEDS_RESUME */
14893 static void alc269_fixup_hweq(struct hda_codec *codec,
14894 const struct alc_fixup *fix, int action)
14896 int coef;
14898 if (action != ALC_FIXUP_ACT_INIT)
14899 return;
14900 coef = alc_read_coef_idx(codec, 0x1e);
14901 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
14904 static void alc271_fixup_dmic(struct hda_codec *codec,
14905 const struct alc_fixup *fix, int action)
14907 static const struct hda_verb verbs[] = {
14908 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
14909 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
14912 unsigned int cfg;
14914 if (strcmp(codec->chip_name, "ALC271X"))
14915 return;
14916 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
14917 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
14918 snd_hda_sequence_write(codec, verbs);
14921 enum {
14922 ALC269_FIXUP_SONY_VAIO,
14923 ALC275_FIXUP_SONY_VAIO_GPIO2,
14924 ALC269_FIXUP_DELL_M101Z,
14925 ALC269_FIXUP_SKU_IGNORE,
14926 ALC269_FIXUP_ASUS_G73JW,
14927 ALC269_FIXUP_LENOVO_EAPD,
14928 ALC275_FIXUP_SONY_HWEQ,
14929 ALC271_FIXUP_DMIC,
14932 static const struct alc_fixup alc269_fixups[] = {
14933 [ALC269_FIXUP_SONY_VAIO] = {
14934 .type = ALC_FIXUP_VERBS,
14935 .v.verbs = (const struct hda_verb[]) {
14936 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
14940 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
14941 .type = ALC_FIXUP_VERBS,
14942 .v.verbs = (const struct hda_verb[]) {
14943 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
14944 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
14945 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
14948 .chained = true,
14949 .chain_id = ALC269_FIXUP_SONY_VAIO
14951 [ALC269_FIXUP_DELL_M101Z] = {
14952 .type = ALC_FIXUP_VERBS,
14953 .v.verbs = (const struct hda_verb[]) {
14954 /* Enables internal speaker */
14955 {0x20, AC_VERB_SET_COEF_INDEX, 13},
14956 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
14960 [ALC269_FIXUP_SKU_IGNORE] = {
14961 .type = ALC_FIXUP_SKU,
14962 .v.sku = ALC_FIXUP_SKU_IGNORE,
14964 [ALC269_FIXUP_ASUS_G73JW] = {
14965 .type = ALC_FIXUP_PINS,
14966 .v.pins = (const struct alc_pincfg[]) {
14967 { 0x17, 0x99130111 }, /* subwoofer */
14971 [ALC269_FIXUP_LENOVO_EAPD] = {
14972 .type = ALC_FIXUP_VERBS,
14973 .v.verbs = (const struct hda_verb[]) {
14974 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
14978 [ALC275_FIXUP_SONY_HWEQ] = {
14979 .type = ALC_FIXUP_FUNC,
14980 .v.func = alc269_fixup_hweq,
14981 .chained = true,
14982 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
14984 [ALC271_FIXUP_DMIC] = {
14985 .type = ALC_FIXUP_FUNC,
14986 .v.func = alc271_fixup_dmic,
14990 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
14991 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
14992 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
14993 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
14994 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
14995 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
14996 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
14997 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
14998 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
14999 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
15000 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
15001 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
15002 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
15003 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
15009 * configuration and preset
15011 static const char * const alc269_models[ALC269_MODEL_LAST] = {
15012 [ALC269_BASIC] = "basic",
15013 [ALC269_QUANTA_FL1] = "quanta",
15014 [ALC269_AMIC] = "laptop-amic",
15015 [ALC269_DMIC] = "laptop-dmic",
15016 [ALC269_FUJITSU] = "fujitsu",
15017 [ALC269_LIFEBOOK] = "lifebook",
15018 [ALC269_AUTO] = "auto",
15021 static const struct snd_pci_quirk alc269_cfg_tbl[] = {
15022 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
15023 SND_PCI_QUIRK(0x1025, 0x047c, "ACER ZGA", ALC271_ACER),
15024 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
15025 ALC269_AMIC),
15026 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC),
15027 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC),
15028 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC),
15029 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC),
15030 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC),
15031 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC),
15032 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC),
15033 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC),
15034 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC),
15035 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269VB_AMIC),
15036 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC),
15037 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC),
15038 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC),
15039 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC),
15040 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC),
15041 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC),
15042 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC),
15043 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC),
15044 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC),
15045 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC),
15046 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC),
15047 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC),
15048 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC),
15049 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC),
15050 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC),
15051 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC),
15052 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC),
15053 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC),
15054 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
15055 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
15056 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
15057 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
15058 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
15059 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
15060 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
15061 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
15062 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
15063 ALC269_DMIC),
15064 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
15065 ALC269_DMIC),
15066 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
15067 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
15068 SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO),
15069 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
15070 SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
15071 SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
15072 SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_AMIC),
15073 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_AMIC),
15074 SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_DMIC),
15075 SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_DMIC),
15079 static const struct alc_config_preset alc269_presets[] = {
15080 [ALC269_BASIC] = {
15081 .mixers = { alc269_base_mixer },
15082 .init_verbs = { alc269_init_verbs },
15083 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15084 .dac_nids = alc269_dac_nids,
15085 .hp_nid = 0x03,
15086 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15087 .channel_mode = alc269_modes,
15088 .input_mux = &alc269_capture_source,
15090 [ALC269_QUANTA_FL1] = {
15091 .mixers = { alc269_quanta_fl1_mixer },
15092 .init_verbs = { alc269_init_verbs, alc269_quanta_fl1_verbs },
15093 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15094 .dac_nids = alc269_dac_nids,
15095 .hp_nid = 0x03,
15096 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15097 .channel_mode = alc269_modes,
15098 .input_mux = &alc269_capture_source,
15099 .unsol_event = alc269_quanta_fl1_unsol_event,
15100 .setup = alc269_quanta_fl1_setup,
15101 .init_hook = alc269_quanta_fl1_init_hook,
15103 [ALC269_AMIC] = {
15104 .mixers = { alc269_laptop_mixer },
15105 .cap_mixer = alc269_laptop_analog_capture_mixer,
15106 .init_verbs = { alc269_init_verbs,
15107 alc269_laptop_amic_init_verbs },
15108 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15109 .dac_nids = alc269_dac_nids,
15110 .hp_nid = 0x03,
15111 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15112 .channel_mode = alc269_modes,
15113 .unsol_event = alc_sku_unsol_event,
15114 .setup = alc269_laptop_amic_setup,
15115 .init_hook = alc_inithook,
15117 [ALC269_DMIC] = {
15118 .mixers = { alc269_laptop_mixer },
15119 .cap_mixer = alc269_laptop_digital_capture_mixer,
15120 .init_verbs = { alc269_init_verbs,
15121 alc269_laptop_dmic_init_verbs },
15122 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15123 .dac_nids = alc269_dac_nids,
15124 .hp_nid = 0x03,
15125 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15126 .channel_mode = alc269_modes,
15127 .unsol_event = alc_sku_unsol_event,
15128 .setup = alc269_laptop_dmic_setup,
15129 .init_hook = alc_inithook,
15131 [ALC269VB_AMIC] = {
15132 .mixers = { alc269vb_laptop_mixer },
15133 .cap_mixer = alc269vb_laptop_analog_capture_mixer,
15134 .init_verbs = { alc269vb_init_verbs,
15135 alc269vb_laptop_amic_init_verbs },
15136 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15137 .dac_nids = alc269_dac_nids,
15138 .hp_nid = 0x03,
15139 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15140 .channel_mode = alc269_modes,
15141 .unsol_event = alc_sku_unsol_event,
15142 .setup = alc269vb_laptop_amic_setup,
15143 .init_hook = alc_inithook,
15145 [ALC269VB_DMIC] = {
15146 .mixers = { alc269vb_laptop_mixer },
15147 .cap_mixer = alc269vb_laptop_digital_capture_mixer,
15148 .init_verbs = { alc269vb_init_verbs,
15149 alc269vb_laptop_dmic_init_verbs },
15150 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15151 .dac_nids = alc269_dac_nids,
15152 .hp_nid = 0x03,
15153 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15154 .channel_mode = alc269_modes,
15155 .unsol_event = alc_sku_unsol_event,
15156 .setup = alc269vb_laptop_dmic_setup,
15157 .init_hook = alc_inithook,
15159 [ALC269_FUJITSU] = {
15160 .mixers = { alc269_fujitsu_mixer },
15161 .cap_mixer = alc269_laptop_digital_capture_mixer,
15162 .init_verbs = { alc269_init_verbs,
15163 alc269_laptop_dmic_init_verbs },
15164 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15165 .dac_nids = alc269_dac_nids,
15166 .hp_nid = 0x03,
15167 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15168 .channel_mode = alc269_modes,
15169 .unsol_event = alc_sku_unsol_event,
15170 .setup = alc269_laptop_dmic_setup,
15171 .init_hook = alc_inithook,
15173 [ALC269_LIFEBOOK] = {
15174 .mixers = { alc269_lifebook_mixer },
15175 .init_verbs = { alc269_init_verbs, alc269_lifebook_verbs },
15176 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15177 .dac_nids = alc269_dac_nids,
15178 .hp_nid = 0x03,
15179 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15180 .channel_mode = alc269_modes,
15181 .input_mux = &alc269_capture_source,
15182 .unsol_event = alc269_lifebook_unsol_event,
15183 .setup = alc269_lifebook_setup,
15184 .init_hook = alc269_lifebook_init_hook,
15186 [ALC271_ACER] = {
15187 .mixers = { alc269_asus_mixer },
15188 .cap_mixer = alc269vb_laptop_digital_capture_mixer,
15189 .init_verbs = { alc269_init_verbs, alc271_acer_dmic_verbs },
15190 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
15191 .dac_nids = alc269_dac_nids,
15192 .adc_nids = alc262_dmic_adc_nids,
15193 .num_adc_nids = ARRAY_SIZE(alc262_dmic_adc_nids),
15194 .capsrc_nids = alc262_dmic_capsrc_nids,
15195 .num_channel_mode = ARRAY_SIZE(alc269_modes),
15196 .channel_mode = alc269_modes,
15197 .input_mux = &alc269_capture_source,
15198 .dig_out_nid = ALC880_DIGOUT_NID,
15199 .unsol_event = alc_sku_unsol_event,
15200 .setup = alc269vb_laptop_dmic_setup,
15201 .init_hook = alc_inithook,
15205 static int alc269_fill_coef(struct hda_codec *codec)
15207 int val;
15209 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
15210 alc_write_coef_idx(codec, 0xf, 0x960b);
15211 alc_write_coef_idx(codec, 0xe, 0x8817);
15214 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
15215 alc_write_coef_idx(codec, 0xf, 0x960b);
15216 alc_write_coef_idx(codec, 0xe, 0x8814);
15219 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
15220 val = alc_read_coef_idx(codec, 0x04);
15221 /* Power up output pin */
15222 alc_write_coef_idx(codec, 0x04, val | (1<<11));
15225 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
15226 val = alc_read_coef_idx(codec, 0xd);
15227 if ((val & 0x0c00) >> 10 != 0x1) {
15228 /* Capless ramp up clock control */
15229 alc_write_coef_idx(codec, 0xd, val | (1<<10));
15231 val = alc_read_coef_idx(codec, 0x17);
15232 if ((val & 0x01c0) >> 6 != 0x4) {
15233 /* Class D power on reset */
15234 alc_write_coef_idx(codec, 0x17, val | (1<<7));
15238 val = alc_read_coef_idx(codec, 0xd); /* Class D */
15239 alc_write_coef_idx(codec, 0xd, val | (1<<14));
15241 val = alc_read_coef_idx(codec, 0x4); /* HP */
15242 alc_write_coef_idx(codec, 0x4, val | (1<<11));
15244 return 0;
15247 static int patch_alc269(struct hda_codec *codec)
15249 struct alc_spec *spec;
15250 int board_config, coef;
15251 int err;
15253 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
15254 if (spec == NULL)
15255 return -ENOMEM;
15257 codec->spec = spec;
15259 alc_auto_parse_customize_define(codec);
15261 if (codec->vendor_id == 0x10ec0269) {
15262 coef = alc_read_coef_idx(codec, 0);
15263 if ((coef & 0x00f0) == 0x0010) {
15264 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
15265 spec->cdefine.platform_type == 1) {
15266 alc_codec_rename(codec, "ALC271X");
15267 spec->codec_variant = ALC269_TYPE_ALC271X;
15268 } else if ((coef & 0xf000) == 0x1000) {
15269 spec->codec_variant = ALC269_TYPE_ALC270;
15270 } else if ((coef & 0xf000) == 0x2000) {
15271 alc_codec_rename(codec, "ALC259");
15272 spec->codec_variant = ALC269_TYPE_ALC259;
15273 } else if ((coef & 0xf000) == 0x3000) {
15274 alc_codec_rename(codec, "ALC258");
15275 spec->codec_variant = ALC269_TYPE_ALC258;
15276 } else {
15277 alc_codec_rename(codec, "ALC269VB");
15278 spec->codec_variant = ALC269_TYPE_ALC269VB;
15280 } else
15281 alc_fix_pll_init(codec, 0x20, 0x04, 15);
15282 alc269_fill_coef(codec);
15285 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
15286 alc269_models,
15287 alc269_cfg_tbl);
15289 if (board_config < 0) {
15290 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
15291 codec->chip_name);
15292 board_config = ALC269_AUTO;
15295 if (board_config == ALC269_AUTO) {
15296 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
15297 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
15300 if (board_config == ALC269_AUTO) {
15301 /* automatic parse from the BIOS config */
15302 err = alc269_parse_auto_config(codec);
15303 if (err < 0) {
15304 alc_free(codec);
15305 return err;
15306 } else if (!err) {
15307 printk(KERN_INFO
15308 "hda_codec: Cannot set up configuration "
15309 "from BIOS. Using base mode...\n");
15310 board_config = ALC269_BASIC;
15314 if (has_cdefine_beep(codec)) {
15315 err = snd_hda_attach_beep_device(codec, 0x1);
15316 if (err < 0) {
15317 alc_free(codec);
15318 return err;
15322 if (board_config != ALC269_AUTO)
15323 setup_preset(codec, &alc269_presets[board_config]);
15325 if (board_config == ALC269_QUANTA_FL1) {
15326 /* Due to a hardware problem on Lenovo Ideadpad, we need to
15327 * fix the sample rate of analog I/O to 44.1kHz
15329 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
15330 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
15331 } else if (spec->dual_adc_switch) {
15332 spec->stream_analog_playback = &alc269_pcm_analog_playback;
15333 /* switch ADC dynamically */
15334 spec->stream_analog_capture = &dualmic_pcm_analog_capture;
15335 } else {
15336 spec->stream_analog_playback = &alc269_pcm_analog_playback;
15337 spec->stream_analog_capture = &alc269_pcm_analog_capture;
15339 spec->stream_digital_playback = &alc269_pcm_digital_playback;
15340 spec->stream_digital_capture = &alc269_pcm_digital_capture;
15342 if (!spec->adc_nids) { /* wasn't filled automatically? use default */
15343 if (spec->codec_variant == ALC269_TYPE_NORMAL) {
15344 spec->adc_nids = alc269_adc_nids;
15345 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
15346 spec->capsrc_nids = alc269_capsrc_nids;
15347 } else {
15348 spec->adc_nids = alc269vb_adc_nids;
15349 spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
15350 spec->capsrc_nids = alc269vb_capsrc_nids;
15354 if (!spec->cap_mixer)
15355 set_capture_mixer(codec);
15356 if (has_cdefine_beep(codec))
15357 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
15359 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
15361 spec->vmaster_nid = 0x02;
15363 codec->patch_ops = alc_patch_ops;
15364 #ifdef SND_HDA_NEEDS_RESUME
15365 codec->patch_ops.resume = alc269_resume;
15366 #endif
15367 if (board_config == ALC269_AUTO)
15368 spec->init_hook = alc269_auto_init;
15369 spec->shutup = alc269_shutup;
15371 alc_init_jacks(codec);
15372 #ifdef CONFIG_SND_HDA_POWER_SAVE
15373 if (!spec->loopback.amplist)
15374 spec->loopback.amplist = alc269_loopbacks;
15375 if (alc269_mic2_for_mute_led(codec))
15376 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
15377 #endif
15379 return 0;
15383 * ALC861 channel source setting (2/6 channel selection for 3-stack)
15387 * set the path ways for 2 channel output
15388 * need to set the codec line out and mic 1 pin widgets to inputs
15390 static const struct hda_verb alc861_threestack_ch2_init[] = {
15391 /* set pin widget 1Ah (line in) for input */
15392 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15393 /* set pin widget 18h (mic1/2) for input, for mic also enable
15394 * the vref
15396 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15398 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
15399 #if 0
15400 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
15401 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
15402 #endif
15403 { } /* end */
15406 * 6ch mode
15407 * need to set the codec line out and mic 1 pin widgets to outputs
15409 static const struct hda_verb alc861_threestack_ch6_init[] = {
15410 /* set pin widget 1Ah (line in) for output (Back Surround)*/
15411 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15412 /* set pin widget 18h (mic1) for output (CLFE)*/
15413 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15415 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
15416 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
15418 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
15419 #if 0
15420 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
15421 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
15422 #endif
15423 { } /* end */
15426 static const struct hda_channel_mode alc861_threestack_modes[2] = {
15427 { 2, alc861_threestack_ch2_init },
15428 { 6, alc861_threestack_ch6_init },
15430 /* Set mic1 as input and unmute the mixer */
15431 static const struct hda_verb alc861_uniwill_m31_ch2_init[] = {
15432 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15433 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
15434 { } /* end */
15436 /* Set mic1 as output and mute mixer */
15437 static const struct hda_verb alc861_uniwill_m31_ch4_init[] = {
15438 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15439 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
15440 { } /* end */
15443 static const struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
15444 { 2, alc861_uniwill_m31_ch2_init },
15445 { 4, alc861_uniwill_m31_ch4_init },
15448 /* Set mic1 and line-in as input and unmute the mixer */
15449 static const struct hda_verb alc861_asus_ch2_init[] = {
15450 /* set pin widget 1Ah (line in) for input */
15451 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15452 /* set pin widget 18h (mic1/2) for input, for mic also enable
15453 * the vref
15455 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15457 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
15458 #if 0
15459 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
15460 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
15461 #endif
15462 { } /* end */
15464 /* Set mic1 nad line-in as output and mute mixer */
15465 static const struct hda_verb alc861_asus_ch6_init[] = {
15466 /* set pin widget 1Ah (line in) for output (Back Surround)*/
15467 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15468 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
15469 /* set pin widget 18h (mic1) for output (CLFE)*/
15470 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15471 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
15472 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
15473 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
15475 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
15476 #if 0
15477 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
15478 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
15479 #endif
15480 { } /* end */
15483 static const struct hda_channel_mode alc861_asus_modes[2] = {
15484 { 2, alc861_asus_ch2_init },
15485 { 6, alc861_asus_ch6_init },
15488 /* patch-ALC861 */
15490 static const struct snd_kcontrol_new alc861_base_mixer[] = {
15491 /* output mixer control */
15492 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
15493 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
15494 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
15495 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
15496 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
15498 /*Input mixer control */
15499 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
15500 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
15501 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15502 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
15503 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
15504 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
15505 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
15506 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
15507 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
15508 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
15510 { } /* end */
15513 static const struct snd_kcontrol_new alc861_3ST_mixer[] = {
15514 /* output mixer control */
15515 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
15516 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
15517 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
15518 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
15519 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
15521 /* Input mixer control */
15522 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
15523 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
15524 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15525 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
15526 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
15527 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
15528 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
15529 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
15530 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
15531 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
15534 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15535 .name = "Channel Mode",
15536 .info = alc_ch_mode_info,
15537 .get = alc_ch_mode_get,
15538 .put = alc_ch_mode_put,
15539 .private_value = ARRAY_SIZE(alc861_threestack_modes),
15541 { } /* end */
15544 static const struct snd_kcontrol_new alc861_toshiba_mixer[] = {
15545 /* output mixer control */
15546 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
15547 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
15548 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
15550 { } /* end */
15553 static const struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
15554 /* output mixer control */
15555 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
15556 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
15557 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
15558 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
15559 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
15561 /* Input mixer control */
15562 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
15563 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
15564 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15565 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
15566 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
15567 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
15568 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
15569 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
15570 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
15571 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
15574 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15575 .name = "Channel Mode",
15576 .info = alc_ch_mode_info,
15577 .get = alc_ch_mode_get,
15578 .put = alc_ch_mode_put,
15579 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
15581 { } /* end */
15584 static const struct snd_kcontrol_new alc861_asus_mixer[] = {
15585 /* output mixer control */
15586 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
15587 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
15588 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
15589 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
15590 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
15592 /* Input mixer control */
15593 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
15594 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
15595 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15596 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
15597 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
15598 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
15599 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
15600 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
15601 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
15602 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
15605 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15606 .name = "Channel Mode",
15607 .info = alc_ch_mode_info,
15608 .get = alc_ch_mode_get,
15609 .put = alc_ch_mode_put,
15610 .private_value = ARRAY_SIZE(alc861_asus_modes),
15615 /* additional mixer */
15616 static const struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
15617 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15618 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
15623 * generic initialization of ADC, input mixers and output mixers
15625 static const struct hda_verb alc861_base_init_verbs[] = {
15627 * Unmute ADC0 and set the default input to mic-in
15629 /* port-A for surround (rear panel) */
15630 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15631 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
15632 /* port-B for mic-in (rear panel) with vref */
15633 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15634 /* port-C for line-in (rear panel) */
15635 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15636 /* port-D for Front */
15637 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15638 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15639 /* port-E for HP out (front panel) */
15640 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
15641 /* route front PCM to HP */
15642 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15643 /* port-F for mic-in (front panel) with vref */
15644 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15645 /* port-G for CLFE (rear panel) */
15646 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15647 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15648 /* port-H for side (rear panel) */
15649 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15650 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
15651 /* CD-in */
15652 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15653 /* route front mic to ADC1*/
15654 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15655 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15657 /* Unmute DAC0~3 & spdif out*/
15658 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15659 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15660 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15661 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15662 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15664 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15665 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15666 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15667 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15668 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15670 /* Unmute Stereo Mixer 15 */
15671 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15672 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15673 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15674 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
15676 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15677 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15678 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15679 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15680 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15681 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15682 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15683 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15684 /* hp used DAC 3 (Front) */
15685 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
15686 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15691 static const struct hda_verb alc861_threestack_init_verbs[] = {
15693 * Unmute ADC0 and set the default input to mic-in
15695 /* port-A for surround (rear panel) */
15696 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15697 /* port-B for mic-in (rear panel) with vref */
15698 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15699 /* port-C for line-in (rear panel) */
15700 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15701 /* port-D for Front */
15702 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15703 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15704 /* port-E for HP out (front panel) */
15705 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
15706 /* route front PCM to HP */
15707 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15708 /* port-F for mic-in (front panel) with vref */
15709 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15710 /* port-G for CLFE (rear panel) */
15711 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15712 /* port-H for side (rear panel) */
15713 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15714 /* CD-in */
15715 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15716 /* route front mic to ADC1*/
15717 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15718 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15719 /* Unmute DAC0~3 & spdif out*/
15720 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15721 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15722 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15723 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15724 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15726 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15727 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15728 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15729 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15730 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15732 /* Unmute Stereo Mixer 15 */
15733 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15734 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15735 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15736 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
15738 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15739 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15740 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15741 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15742 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15743 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15744 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15745 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15746 /* hp used DAC 3 (Front) */
15747 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
15748 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15752 static const struct hda_verb alc861_uniwill_m31_init_verbs[] = {
15754 * Unmute ADC0 and set the default input to mic-in
15756 /* port-A for surround (rear panel) */
15757 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15758 /* port-B for mic-in (rear panel) with vref */
15759 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15760 /* port-C for line-in (rear panel) */
15761 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15762 /* port-D for Front */
15763 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15764 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15765 /* port-E for HP out (front panel) */
15766 /* this has to be set to VREF80 */
15767 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15768 /* route front PCM to HP */
15769 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15770 /* port-F for mic-in (front panel) with vref */
15771 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15772 /* port-G for CLFE (rear panel) */
15773 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15774 /* port-H for side (rear panel) */
15775 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15776 /* CD-in */
15777 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15778 /* route front mic to ADC1*/
15779 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15780 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15781 /* Unmute DAC0~3 & spdif out*/
15782 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15783 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15784 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15785 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15786 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15788 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15789 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15790 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15791 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15792 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15794 /* Unmute Stereo Mixer 15 */
15795 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15796 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15797 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15798 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
15800 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15801 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15802 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15803 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15804 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15805 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15806 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15807 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15808 /* hp used DAC 3 (Front) */
15809 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
15810 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15814 static const struct hda_verb alc861_asus_init_verbs[] = {
15816 * Unmute ADC0 and set the default input to mic-in
15818 /* port-A for surround (rear panel)
15819 * according to codec#0 this is the HP jack
15821 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
15822 /* route front PCM to HP */
15823 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
15824 /* port-B for mic-in (rear panel) with vref */
15825 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15826 /* port-C for line-in (rear panel) */
15827 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15828 /* port-D for Front */
15829 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15830 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15831 /* port-E for HP out (front panel) */
15832 /* this has to be set to VREF80 */
15833 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15834 /* route front PCM to HP */
15835 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15836 /* port-F for mic-in (front panel) with vref */
15837 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15838 /* port-G for CLFE (rear panel) */
15839 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15840 /* port-H for side (rear panel) */
15841 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15842 /* CD-in */
15843 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15844 /* route front mic to ADC1*/
15845 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15846 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15847 /* Unmute DAC0~3 & spdif out*/
15848 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15849 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15850 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15851 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15852 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15853 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15854 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15855 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15856 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15857 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15859 /* Unmute Stereo Mixer 15 */
15860 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15861 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15862 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15863 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
15865 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15866 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15867 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15868 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15869 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15870 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15871 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15872 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15873 /* hp used DAC 3 (Front) */
15874 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
15875 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15879 /* additional init verbs for ASUS laptops */
15880 static const struct hda_verb alc861_asus_laptop_init_verbs[] = {
15881 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
15882 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
15887 * generic initialization of ADC, input mixers and output mixers
15889 static const struct hda_verb alc861_auto_init_verbs[] = {
15891 * Unmute ADC0 and set the default input to mic-in
15893 /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
15894 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15896 /* Unmute DAC0~3 & spdif out*/
15897 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15898 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15899 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15900 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15901 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15903 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15904 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15905 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15906 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15907 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15909 /* Unmute Stereo Mixer 15 */
15910 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15911 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15912 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15913 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
15915 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15916 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15917 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15918 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15919 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15920 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15921 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15922 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15924 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15925 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15926 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
15927 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
15928 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15929 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15930 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
15931 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
15933 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */
15938 static const struct hda_verb alc861_toshiba_init_verbs[] = {
15939 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
15944 /* toggle speaker-output according to the hp-jack state */
15945 static void alc861_toshiba_automute(struct hda_codec *codec)
15947 unsigned int present = snd_hda_jack_detect(codec, 0x0f);
15949 snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
15950 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
15951 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
15952 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
15955 static void alc861_toshiba_unsol_event(struct hda_codec *codec,
15956 unsigned int res)
15958 if ((res >> 26) == ALC880_HP_EVENT)
15959 alc861_toshiba_automute(codec);
15962 /* pcm configuration: identical with ALC880 */
15963 #define alc861_pcm_analog_playback alc880_pcm_analog_playback
15964 #define alc861_pcm_analog_capture alc880_pcm_analog_capture
15965 #define alc861_pcm_digital_playback alc880_pcm_digital_playback
15966 #define alc861_pcm_digital_capture alc880_pcm_digital_capture
15969 #define ALC861_DIGOUT_NID 0x07
15971 static const struct hda_channel_mode alc861_8ch_modes[1] = {
15972 { 8, NULL }
15975 static const hda_nid_t alc861_dac_nids[4] = {
15976 /* front, surround, clfe, side */
15977 0x03, 0x06, 0x05, 0x04
15980 static const hda_nid_t alc660_dac_nids[3] = {
15981 /* front, clfe, surround */
15982 0x03, 0x05, 0x06
15985 static const hda_nid_t alc861_adc_nids[1] = {
15986 /* ADC0-2 */
15987 0x08,
15990 static const struct hda_input_mux alc861_capture_source = {
15991 .num_items = 5,
15992 .items = {
15993 { "Mic", 0x0 },
15994 { "Front Mic", 0x3 },
15995 { "Line", 0x1 },
15996 { "CD", 0x4 },
15997 { "Mixer", 0x5 },
16001 static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
16003 struct alc_spec *spec = codec->spec;
16004 hda_nid_t mix, srcs[5];
16005 int i, j, num;
16007 if (snd_hda_get_connections(codec, pin, &mix, 1) != 1)
16008 return 0;
16009 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
16010 if (num < 0)
16011 return 0;
16012 for (i = 0; i < num; i++) {
16013 unsigned int type;
16014 type = get_wcaps_type(get_wcaps(codec, srcs[i]));
16015 if (type != AC_WID_AUD_OUT)
16016 continue;
16017 for (j = 0; j < spec->multiout.num_dacs; j++)
16018 if (spec->multiout.dac_nids[j] == srcs[i])
16019 break;
16020 if (j >= spec->multiout.num_dacs)
16021 return srcs[i];
16023 return 0;
16026 /* fill in the dac_nids table from the parsed pin configuration */
16027 static int alc861_auto_fill_dac_nids(struct hda_codec *codec,
16028 const struct auto_pin_cfg *cfg)
16030 struct alc_spec *spec = codec->spec;
16031 int i;
16032 hda_nid_t nid, dac;
16034 spec->multiout.dac_nids = spec->private_dac_nids;
16035 for (i = 0; i < cfg->line_outs; i++) {
16036 nid = cfg->line_out_pins[i];
16037 dac = alc861_look_for_dac(codec, nid);
16038 if (!dac)
16039 continue;
16040 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
16042 return 0;
16045 static int __alc861_create_out_sw(struct hda_codec *codec, const char *pfx,
16046 hda_nid_t nid, int idx, unsigned int chs)
16048 return __add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx, idx,
16049 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
16052 #define alc861_create_out_sw(codec, pfx, nid, chs) \
16053 __alc861_create_out_sw(codec, pfx, nid, 0, chs)
16055 /* add playback controls from the parsed DAC table */
16056 static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
16057 const struct auto_pin_cfg *cfg)
16059 struct alc_spec *spec = codec->spec;
16060 static const char * const chname[4] = {
16061 "Front", "Surround", NULL /*CLFE*/, "Side"
16063 const char *pfx = alc_get_line_out_pfx(spec, true);
16064 hda_nid_t nid;
16065 int i, err, noutputs;
16067 noutputs = cfg->line_outs;
16068 if (spec->multi_ios > 0)
16069 noutputs += spec->multi_ios;
16071 for (i = 0; i < noutputs; i++) {
16072 nid = spec->multiout.dac_nids[i];
16073 if (!nid)
16074 continue;
16075 if (!pfx && i == 2) {
16076 /* Center/LFE */
16077 err = alc861_create_out_sw(codec, "Center", nid, 1);
16078 if (err < 0)
16079 return err;
16080 err = alc861_create_out_sw(codec, "LFE", nid, 2);
16081 if (err < 0)
16082 return err;
16083 } else {
16084 const char *name = pfx;
16085 int index = i;
16086 if (!name) {
16087 name = chname[i];
16088 index = 0;
16090 err = __alc861_create_out_sw(codec, name, nid, index, 3);
16091 if (err < 0)
16092 return err;
16095 return 0;
16098 static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
16100 struct alc_spec *spec = codec->spec;
16101 int err;
16102 hda_nid_t nid;
16104 if (!pin)
16105 return 0;
16107 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
16108 nid = alc861_look_for_dac(codec, pin);
16109 if (nid) {
16110 err = alc861_create_out_sw(codec, "Headphone", nid, 3);
16111 if (err < 0)
16112 return err;
16113 spec->multiout.hp_nid = nid;
16116 return 0;
16119 /* create playback/capture controls for input pins */
16120 static int alc861_auto_create_input_ctls(struct hda_codec *codec,
16121 const struct auto_pin_cfg *cfg)
16123 return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x08, 0);
16126 static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
16127 hda_nid_t nid,
16128 int pin_type, hda_nid_t dac)
16130 hda_nid_t mix, srcs[5];
16131 int i, num;
16133 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
16134 pin_type);
16135 snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
16136 AMP_OUT_UNMUTE);
16137 if (snd_hda_get_connections(codec, nid, &mix, 1) != 1)
16138 return;
16139 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
16140 if (num < 0)
16141 return;
16142 for (i = 0; i < num; i++) {
16143 unsigned int mute;
16144 if (srcs[i] == dac || srcs[i] == 0x15)
16145 mute = AMP_IN_UNMUTE(i);
16146 else
16147 mute = AMP_IN_MUTE(i);
16148 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
16149 mute);
16153 static void alc861_auto_init_multi_out(struct hda_codec *codec)
16155 struct alc_spec *spec = codec->spec;
16156 int i;
16158 for (i = 0; i < spec->autocfg.line_outs; i++) {
16159 hda_nid_t nid = spec->autocfg.line_out_pins[i];
16160 int pin_type = get_pin_type(spec->autocfg.line_out_type);
16161 if (nid)
16162 alc861_auto_set_output_and_unmute(codec, nid, pin_type,
16163 spec->multiout.dac_nids[i]);
16167 static void alc861_auto_init_hp_out(struct hda_codec *codec)
16169 struct alc_spec *spec = codec->spec;
16171 if (spec->autocfg.hp_outs)
16172 alc861_auto_set_output_and_unmute(codec,
16173 spec->autocfg.hp_pins[0],
16174 PIN_HP,
16175 spec->multiout.hp_nid);
16176 if (spec->autocfg.speaker_outs)
16177 alc861_auto_set_output_and_unmute(codec,
16178 spec->autocfg.speaker_pins[0],
16179 PIN_OUT,
16180 spec->multiout.dac_nids[0]);
16183 static void alc861_auto_init_analog_input(struct hda_codec *codec)
16185 struct alc_spec *spec = codec->spec;
16186 struct auto_pin_cfg *cfg = &spec->autocfg;
16187 int i;
16189 for (i = 0; i < cfg->num_inputs; i++) {
16190 hda_nid_t nid = cfg->inputs[i].pin;
16191 if (nid >= 0x0c && nid <= 0x11)
16192 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
16196 /* parse the BIOS configuration and set up the alc_spec */
16197 /* return 1 if successful, 0 if the proper config is not found,
16198 * or a negative error code
16200 static int alc861_parse_auto_config(struct hda_codec *codec)
16202 struct alc_spec *spec = codec->spec;
16203 int err;
16204 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
16206 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
16207 alc861_ignore);
16208 if (err < 0)
16209 return err;
16210 if (!spec->autocfg.line_outs)
16211 return 0; /* can't find valid BIOS pin config */
16213 err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
16214 if (err < 0)
16215 return err;
16216 err = alc_auto_add_multi_channel_mode(codec);
16217 if (err < 0)
16218 return err;
16219 err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
16220 if (err < 0)
16221 return err;
16222 err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]);
16223 if (err < 0)
16224 return err;
16225 err = alc861_auto_create_input_ctls(codec, &spec->autocfg);
16226 if (err < 0)
16227 return err;
16229 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
16231 alc_auto_parse_digital(codec);
16233 if (spec->kctls.list)
16234 add_mixer(spec, spec->kctls.list);
16236 add_verb(spec, alc861_auto_init_verbs);
16238 spec->num_mux_defs = 1;
16239 spec->input_mux = &spec->private_imux[0];
16241 spec->adc_nids = alc861_adc_nids;
16242 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
16243 set_capture_mixer(codec);
16245 alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0);
16247 return 1;
16250 /* additional initialization for auto-configuration model */
16251 static void alc861_auto_init(struct hda_codec *codec)
16253 struct alc_spec *spec = codec->spec;
16254 alc861_auto_init_multi_out(codec);
16255 alc861_auto_init_hp_out(codec);
16256 alc861_auto_init_analog_input(codec);
16257 alc_auto_init_digital(codec);
16258 if (spec->unsol_event)
16259 alc_inithook(codec);
16262 #ifdef CONFIG_SND_HDA_POWER_SAVE
16263 static const struct hda_amp_list alc861_loopbacks[] = {
16264 { 0x15, HDA_INPUT, 0 },
16265 { 0x15, HDA_INPUT, 1 },
16266 { 0x15, HDA_INPUT, 2 },
16267 { 0x15, HDA_INPUT, 3 },
16268 { } /* end */
16270 #endif
16274 * configuration and preset
16276 static const char * const alc861_models[ALC861_MODEL_LAST] = {
16277 [ALC861_3ST] = "3stack",
16278 [ALC660_3ST] = "3stack-660",
16279 [ALC861_3ST_DIG] = "3stack-dig",
16280 [ALC861_6ST_DIG] = "6stack-dig",
16281 [ALC861_UNIWILL_M31] = "uniwill-m31",
16282 [ALC861_TOSHIBA] = "toshiba",
16283 [ALC861_ASUS] = "asus",
16284 [ALC861_ASUS_LAPTOP] = "asus-laptop",
16285 [ALC861_AUTO] = "auto",
16288 static const struct snd_pci_quirk alc861_cfg_tbl[] = {
16289 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
16290 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
16291 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
16292 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
16293 SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
16294 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
16295 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
16296 /* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
16297 * Any other models that need this preset?
16299 /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
16300 SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
16301 SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
16302 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
16303 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
16304 SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
16305 /* FIXME: the below seems conflict */
16306 /* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */
16307 SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
16308 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
16312 static const struct alc_config_preset alc861_presets[] = {
16313 [ALC861_3ST] = {
16314 .mixers = { alc861_3ST_mixer },
16315 .init_verbs = { alc861_threestack_init_verbs },
16316 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16317 .dac_nids = alc861_dac_nids,
16318 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
16319 .channel_mode = alc861_threestack_modes,
16320 .need_dac_fix = 1,
16321 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16322 .adc_nids = alc861_adc_nids,
16323 .input_mux = &alc861_capture_source,
16325 [ALC861_3ST_DIG] = {
16326 .mixers = { alc861_base_mixer },
16327 .init_verbs = { alc861_threestack_init_verbs },
16328 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16329 .dac_nids = alc861_dac_nids,
16330 .dig_out_nid = ALC861_DIGOUT_NID,
16331 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
16332 .channel_mode = alc861_threestack_modes,
16333 .need_dac_fix = 1,
16334 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16335 .adc_nids = alc861_adc_nids,
16336 .input_mux = &alc861_capture_source,
16338 [ALC861_6ST_DIG] = {
16339 .mixers = { alc861_base_mixer },
16340 .init_verbs = { alc861_base_init_verbs },
16341 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16342 .dac_nids = alc861_dac_nids,
16343 .dig_out_nid = ALC861_DIGOUT_NID,
16344 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
16345 .channel_mode = alc861_8ch_modes,
16346 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16347 .adc_nids = alc861_adc_nids,
16348 .input_mux = &alc861_capture_source,
16350 [ALC660_3ST] = {
16351 .mixers = { alc861_3ST_mixer },
16352 .init_verbs = { alc861_threestack_init_verbs },
16353 .num_dacs = ARRAY_SIZE(alc660_dac_nids),
16354 .dac_nids = alc660_dac_nids,
16355 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
16356 .channel_mode = alc861_threestack_modes,
16357 .need_dac_fix = 1,
16358 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16359 .adc_nids = alc861_adc_nids,
16360 .input_mux = &alc861_capture_source,
16362 [ALC861_UNIWILL_M31] = {
16363 .mixers = { alc861_uniwill_m31_mixer },
16364 .init_verbs = { alc861_uniwill_m31_init_verbs },
16365 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16366 .dac_nids = alc861_dac_nids,
16367 .dig_out_nid = ALC861_DIGOUT_NID,
16368 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
16369 .channel_mode = alc861_uniwill_m31_modes,
16370 .need_dac_fix = 1,
16371 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16372 .adc_nids = alc861_adc_nids,
16373 .input_mux = &alc861_capture_source,
16375 [ALC861_TOSHIBA] = {
16376 .mixers = { alc861_toshiba_mixer },
16377 .init_verbs = { alc861_base_init_verbs,
16378 alc861_toshiba_init_verbs },
16379 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16380 .dac_nids = alc861_dac_nids,
16381 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
16382 .channel_mode = alc883_3ST_2ch_modes,
16383 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16384 .adc_nids = alc861_adc_nids,
16385 .input_mux = &alc861_capture_source,
16386 .unsol_event = alc861_toshiba_unsol_event,
16387 .init_hook = alc861_toshiba_automute,
16389 [ALC861_ASUS] = {
16390 .mixers = { alc861_asus_mixer },
16391 .init_verbs = { alc861_asus_init_verbs },
16392 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16393 .dac_nids = alc861_dac_nids,
16394 .dig_out_nid = ALC861_DIGOUT_NID,
16395 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
16396 .channel_mode = alc861_asus_modes,
16397 .need_dac_fix = 1,
16398 .hp_nid = 0x06,
16399 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16400 .adc_nids = alc861_adc_nids,
16401 .input_mux = &alc861_capture_source,
16403 [ALC861_ASUS_LAPTOP] = {
16404 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
16405 .init_verbs = { alc861_asus_init_verbs,
16406 alc861_asus_laptop_init_verbs },
16407 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
16408 .dac_nids = alc861_dac_nids,
16409 .dig_out_nid = ALC861_DIGOUT_NID,
16410 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
16411 .channel_mode = alc883_3ST_2ch_modes,
16412 .need_dac_fix = 1,
16413 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
16414 .adc_nids = alc861_adc_nids,
16415 .input_mux = &alc861_capture_source,
16419 /* Pin config fixes */
16420 enum {
16421 PINFIX_FSC_AMILO_PI1505,
16422 PINFIX_ASUS_A6RP,
16425 static const struct alc_fixup alc861_fixups[] = {
16426 [PINFIX_FSC_AMILO_PI1505] = {
16427 .type = ALC_FIXUP_PINS,
16428 .v.pins = (const struct alc_pincfg[]) {
16429 { 0x0b, 0x0221101f }, /* HP */
16430 { 0x0f, 0x90170310 }, /* speaker */
16434 [PINFIX_ASUS_A6RP] = {
16435 .type = ALC_FIXUP_VERBS,
16436 .v.verbs = (const struct hda_verb[]) {
16437 /* node 0x0f VREF seems controlling the master output */
16438 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
16444 static const struct snd_pci_quirk alc861_fixup_tbl[] = {
16445 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", PINFIX_ASUS_A6RP),
16446 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
16450 static int patch_alc861(struct hda_codec *codec)
16452 struct alc_spec *spec;
16453 int board_config;
16454 int err;
16456 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
16457 if (spec == NULL)
16458 return -ENOMEM;
16460 codec->spec = spec;
16462 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
16463 alc861_models,
16464 alc861_cfg_tbl);
16466 if (board_config < 0) {
16467 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
16468 codec->chip_name);
16469 board_config = ALC861_AUTO;
16472 if (board_config == ALC861_AUTO) {
16473 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
16474 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
16477 if (board_config == ALC861_AUTO) {
16478 /* automatic parse from the BIOS config */
16479 err = alc861_parse_auto_config(codec);
16480 if (err < 0) {
16481 alc_free(codec);
16482 return err;
16483 } else if (!err) {
16484 printk(KERN_INFO
16485 "hda_codec: Cannot set up configuration "
16486 "from BIOS. Using base mode...\n");
16487 board_config = ALC861_3ST_DIG;
16491 err = snd_hda_attach_beep_device(codec, 0x23);
16492 if (err < 0) {
16493 alc_free(codec);
16494 return err;
16497 if (board_config != ALC861_AUTO)
16498 setup_preset(codec, &alc861_presets[board_config]);
16500 spec->stream_analog_playback = &alc861_pcm_analog_playback;
16501 spec->stream_analog_capture = &alc861_pcm_analog_capture;
16503 spec->stream_digital_playback = &alc861_pcm_digital_playback;
16504 spec->stream_digital_capture = &alc861_pcm_digital_capture;
16506 if (!spec->cap_mixer)
16507 set_capture_mixer(codec);
16508 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
16510 spec->vmaster_nid = 0x03;
16512 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
16514 codec->patch_ops = alc_patch_ops;
16515 if (board_config == ALC861_AUTO) {
16516 spec->init_hook = alc861_auto_init;
16517 #ifdef CONFIG_SND_HDA_POWER_SAVE
16518 spec->power_hook = alc_power_eapd;
16519 #endif
16521 #ifdef CONFIG_SND_HDA_POWER_SAVE
16522 if (!spec->loopback.amplist)
16523 spec->loopback.amplist = alc861_loopbacks;
16524 #endif
16526 return 0;
16530 * ALC861-VD support
16532 * Based on ALC882
16534 * In addition, an independent DAC
16536 #define ALC861VD_DIGOUT_NID 0x06
16538 static const hda_nid_t alc861vd_dac_nids[4] = {
16539 /* front, surr, clfe, side surr */
16540 0x02, 0x03, 0x04, 0x05
16543 /* dac_nids for ALC660vd are in a different order - according to
16544 * Realtek's driver.
16545 * This should probably result in a different mixer for 6stack models
16546 * of ALC660vd codecs, but for now there is only 3stack mixer
16547 * - and it is the same as in 861vd.
16548 * adc_nids in ALC660vd are (is) the same as in 861vd
16550 static const hda_nid_t alc660vd_dac_nids[3] = {
16551 /* front, rear, clfe, rear_surr */
16552 0x02, 0x04, 0x03
16555 static const hda_nid_t alc861vd_adc_nids[1] = {
16556 /* ADC0 */
16557 0x09,
16560 static const hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
16562 /* input MUX */
16563 /* FIXME: should be a matrix-type input source selection */
16564 static const struct hda_input_mux alc861vd_capture_source = {
16565 .num_items = 4,
16566 .items = {
16567 { "Mic", 0x0 },
16568 { "Front Mic", 0x1 },
16569 { "Line", 0x2 },
16570 { "CD", 0x4 },
16574 static const struct hda_input_mux alc861vd_dallas_capture_source = {
16575 .num_items = 2,
16576 .items = {
16577 { "Mic", 0x0 },
16578 { "Internal Mic", 0x1 },
16582 static const struct hda_input_mux alc861vd_hp_capture_source = {
16583 .num_items = 2,
16584 .items = {
16585 { "Front Mic", 0x0 },
16586 { "ATAPI Mic", 0x1 },
16591 * 2ch mode
16593 static const struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
16594 { 2, NULL }
16598 * 6ch mode
16600 static const struct hda_verb alc861vd_6stack_ch6_init[] = {
16601 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
16602 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16603 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16604 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16605 { } /* end */
16609 * 8ch mode
16611 static const struct hda_verb alc861vd_6stack_ch8_init[] = {
16612 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16613 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16614 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16615 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16616 { } /* end */
16619 static const struct hda_channel_mode alc861vd_6stack_modes[2] = {
16620 { 6, alc861vd_6stack_ch6_init },
16621 { 8, alc861vd_6stack_ch8_init },
16624 static const struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
16626 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16627 .name = "Channel Mode",
16628 .info = alc_ch_mode_info,
16629 .get = alc_ch_mode_get,
16630 .put = alc_ch_mode_put,
16632 { } /* end */
16635 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
16636 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
16638 static const struct snd_kcontrol_new alc861vd_6st_mixer[] = {
16639 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16640 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
16642 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16643 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
16645 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
16646 HDA_OUTPUT),
16647 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
16648 HDA_OUTPUT),
16649 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
16650 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
16652 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
16653 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
16655 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16657 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
16658 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16659 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16661 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
16662 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16663 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16665 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16666 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16668 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16669 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16671 { } /* end */
16674 static const struct snd_kcontrol_new alc861vd_3st_mixer[] = {
16675 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16676 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
16678 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16680 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
16681 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16682 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16684 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
16685 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16686 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16688 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16689 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16691 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16692 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16694 { } /* end */
16697 static const struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
16698 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16699 /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
16700 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
16702 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16704 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
16705 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16706 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16708 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
16709 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16710 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16712 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16713 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16715 { } /* end */
16718 /* Pin assignment: Speaker=0x14, HP = 0x15,
16719 * Mic=0x18, Internal Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
16721 static const struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
16722 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16723 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
16724 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16725 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
16726 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
16727 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16728 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16729 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
16730 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16731 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16732 { } /* end */
16735 /* Pin assignment: Speaker=0x14, Line-out = 0x15,
16736 * Front Mic=0x18, ATAPI Mic = 0x19,
16738 static const struct snd_kcontrol_new alc861vd_hp_mixer[] = {
16739 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16740 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
16741 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16742 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
16743 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16744 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16745 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16746 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16748 { } /* end */
16752 * generic initialization of ADC, input mixers and output mixers
16754 static const struct hda_verb alc861vd_volume_init_verbs[] = {
16756 * Unmute ADC0 and set the default input to mic-in
16758 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
16759 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16761 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
16762 * the analog-loopback mixer widget
16764 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
16765 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16766 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16767 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
16768 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
16769 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
16771 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
16772 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16773 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16774 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
16775 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
16778 * Set up output mixers (0x02 - 0x05)
16780 /* set vol=0 to output mixers */
16781 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16782 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16783 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16784 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16786 /* set up input amps for analog loopback */
16787 /* Amp Indices: DAC = 0, mixer = 1 */
16788 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16789 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16790 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16791 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16792 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16793 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16794 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16795 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16801 * 3-stack pin configuration:
16802 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
16804 static const struct hda_verb alc861vd_3stack_init_verbs[] = {
16806 * Set pin mode and muting
16808 /* set front pin widgets 0x14 for output */
16809 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16810 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16811 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
16813 /* Mic (rear) pin: input vref at 80% */
16814 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16815 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16816 /* Front Mic pin: input vref at 80% */
16817 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16818 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16819 /* Line In pin: input */
16820 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16821 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16822 /* Line-2 In: Headphone output (output 0 - 0x0c) */
16823 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16824 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16825 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
16826 /* CD pin widget for input */
16827 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16833 * 6-stack pin configuration:
16835 static const struct hda_verb alc861vd_6stack_init_verbs[] = {
16837 * Set pin mode and muting
16839 /* set front pin widgets 0x14 for output */
16840 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16841 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16842 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
16844 /* Rear Pin: output 1 (0x0d) */
16845 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16846 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16847 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
16848 /* CLFE Pin: output 2 (0x0e) */
16849 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16850 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16851 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
16852 /* Side Pin: output 3 (0x0f) */
16853 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16854 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16855 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
16857 /* Mic (rear) pin: input vref at 80% */
16858 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16859 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16860 /* Front Mic pin: input vref at 80% */
16861 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16862 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16863 /* Line In pin: input */
16864 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16865 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16866 /* Line-2 In: Headphone output (output 0 - 0x0c) */
16867 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16868 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16869 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
16870 /* CD pin widget for input */
16871 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16876 static const struct hda_verb alc861vd_eapd_verbs[] = {
16877 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
16881 static const struct hda_verb alc660vd_eapd_verbs[] = {
16882 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
16883 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
16887 static const struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
16888 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16889 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16890 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
16891 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16892 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16896 static void alc861vd_lenovo_setup(struct hda_codec *codec)
16898 struct alc_spec *spec = codec->spec;
16899 spec->autocfg.hp_pins[0] = 0x1b;
16900 spec->autocfg.speaker_pins[0] = 0x14;
16901 spec->automute = 1;
16902 spec->automute_mode = ALC_AUTOMUTE_AMP;
16905 static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
16907 alc_hp_automute(codec);
16908 alc88x_simple_mic_automute(codec);
16911 static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
16912 unsigned int res)
16914 switch (res >> 26) {
16915 case ALC880_MIC_EVENT:
16916 alc88x_simple_mic_automute(codec);
16917 break;
16918 default:
16919 alc_sku_unsol_event(codec, res);
16920 break;
16924 static const struct hda_verb alc861vd_dallas_verbs[] = {
16925 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16926 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16927 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16928 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16930 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16931 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16932 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16933 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16934 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16935 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16936 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16937 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16939 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16940 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16941 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16942 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16943 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16944 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16945 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16946 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16948 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
16949 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16950 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
16951 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16952 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16953 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16954 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16955 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16957 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16958 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
16959 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
16960 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
16962 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16963 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
16964 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16966 { } /* end */
16969 /* toggle speaker-output according to the hp-jack state */
16970 static void alc861vd_dallas_setup(struct hda_codec *codec)
16972 struct alc_spec *spec = codec->spec;
16974 spec->autocfg.hp_pins[0] = 0x15;
16975 spec->autocfg.speaker_pins[0] = 0x14;
16976 spec->automute = 1;
16977 spec->automute_mode = ALC_AUTOMUTE_AMP;
16980 #ifdef CONFIG_SND_HDA_POWER_SAVE
16981 #define alc861vd_loopbacks alc880_loopbacks
16982 #endif
16984 /* pcm configuration: identical with ALC880 */
16985 #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback
16986 #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture
16987 #define alc861vd_pcm_digital_playback alc880_pcm_digital_playback
16988 #define alc861vd_pcm_digital_capture alc880_pcm_digital_capture
16991 * configuration and preset
16993 static const char * const alc861vd_models[ALC861VD_MODEL_LAST] = {
16994 [ALC660VD_3ST] = "3stack-660",
16995 [ALC660VD_3ST_DIG] = "3stack-660-digout",
16996 [ALC660VD_ASUS_V1S] = "asus-v1s",
16997 [ALC861VD_3ST] = "3stack",
16998 [ALC861VD_3ST_DIG] = "3stack-digout",
16999 [ALC861VD_6ST_DIG] = "6stack-digout",
17000 [ALC861VD_LENOVO] = "lenovo",
17001 [ALC861VD_DALLAS] = "dallas",
17002 [ALC861VD_HP] = "hp",
17003 [ALC861VD_AUTO] = "auto",
17006 static const struct snd_pci_quirk alc861vd_cfg_tbl[] = {
17007 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
17008 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
17009 SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
17010 /*SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),*/ /* auto */
17011 SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S),
17012 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
17013 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
17014 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
17015 /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
17016 SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
17017 SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
17018 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
17019 SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
17020 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO),
17021 SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
17025 static const struct alc_config_preset alc861vd_presets[] = {
17026 [ALC660VD_3ST] = {
17027 .mixers = { alc861vd_3st_mixer },
17028 .init_verbs = { alc861vd_volume_init_verbs,
17029 alc861vd_3stack_init_verbs },
17030 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
17031 .dac_nids = alc660vd_dac_nids,
17032 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17033 .channel_mode = alc861vd_3stack_2ch_modes,
17034 .input_mux = &alc861vd_capture_source,
17036 [ALC660VD_3ST_DIG] = {
17037 .mixers = { alc861vd_3st_mixer },
17038 .init_verbs = { alc861vd_volume_init_verbs,
17039 alc861vd_3stack_init_verbs },
17040 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
17041 .dac_nids = alc660vd_dac_nids,
17042 .dig_out_nid = ALC861VD_DIGOUT_NID,
17043 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17044 .channel_mode = alc861vd_3stack_2ch_modes,
17045 .input_mux = &alc861vd_capture_source,
17047 [ALC861VD_3ST] = {
17048 .mixers = { alc861vd_3st_mixer },
17049 .init_verbs = { alc861vd_volume_init_verbs,
17050 alc861vd_3stack_init_verbs },
17051 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
17052 .dac_nids = alc861vd_dac_nids,
17053 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17054 .channel_mode = alc861vd_3stack_2ch_modes,
17055 .input_mux = &alc861vd_capture_source,
17057 [ALC861VD_3ST_DIG] = {
17058 .mixers = { alc861vd_3st_mixer },
17059 .init_verbs = { alc861vd_volume_init_verbs,
17060 alc861vd_3stack_init_verbs },
17061 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
17062 .dac_nids = alc861vd_dac_nids,
17063 .dig_out_nid = ALC861VD_DIGOUT_NID,
17064 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17065 .channel_mode = alc861vd_3stack_2ch_modes,
17066 .input_mux = &alc861vd_capture_source,
17068 [ALC861VD_6ST_DIG] = {
17069 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
17070 .init_verbs = { alc861vd_volume_init_verbs,
17071 alc861vd_6stack_init_verbs },
17072 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
17073 .dac_nids = alc861vd_dac_nids,
17074 .dig_out_nid = ALC861VD_DIGOUT_NID,
17075 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
17076 .channel_mode = alc861vd_6stack_modes,
17077 .input_mux = &alc861vd_capture_source,
17079 [ALC861VD_LENOVO] = {
17080 .mixers = { alc861vd_lenovo_mixer },
17081 .init_verbs = { alc861vd_volume_init_verbs,
17082 alc861vd_3stack_init_verbs,
17083 alc861vd_eapd_verbs,
17084 alc861vd_lenovo_unsol_verbs },
17085 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
17086 .dac_nids = alc660vd_dac_nids,
17087 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17088 .channel_mode = alc861vd_3stack_2ch_modes,
17089 .input_mux = &alc861vd_capture_source,
17090 .unsol_event = alc861vd_lenovo_unsol_event,
17091 .setup = alc861vd_lenovo_setup,
17092 .init_hook = alc861vd_lenovo_init_hook,
17094 [ALC861VD_DALLAS] = {
17095 .mixers = { alc861vd_dallas_mixer },
17096 .init_verbs = { alc861vd_dallas_verbs },
17097 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
17098 .dac_nids = alc861vd_dac_nids,
17099 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17100 .channel_mode = alc861vd_3stack_2ch_modes,
17101 .input_mux = &alc861vd_dallas_capture_source,
17102 .unsol_event = alc_sku_unsol_event,
17103 .setup = alc861vd_dallas_setup,
17104 .init_hook = alc_hp_automute,
17106 [ALC861VD_HP] = {
17107 .mixers = { alc861vd_hp_mixer },
17108 .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
17109 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
17110 .dac_nids = alc861vd_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_hp_capture_source,
17115 .unsol_event = alc_sku_unsol_event,
17116 .setup = alc861vd_dallas_setup,
17117 .init_hook = alc_hp_automute,
17119 [ALC660VD_ASUS_V1S] = {
17120 .mixers = { alc861vd_lenovo_mixer },
17121 .init_verbs = { alc861vd_volume_init_verbs,
17122 alc861vd_3stack_init_verbs,
17123 alc861vd_eapd_verbs,
17124 alc861vd_lenovo_unsol_verbs },
17125 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
17126 .dac_nids = alc660vd_dac_nids,
17127 .dig_out_nid = ALC861VD_DIGOUT_NID,
17128 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
17129 .channel_mode = alc861vd_3stack_2ch_modes,
17130 .input_mux = &alc861vd_capture_source,
17131 .unsol_event = alc861vd_lenovo_unsol_event,
17132 .setup = alc861vd_lenovo_setup,
17133 .init_hook = alc861vd_lenovo_init_hook,
17138 * BIOS auto configuration
17140 static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
17141 const struct auto_pin_cfg *cfg)
17143 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x22, 0);
17147 static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
17148 hda_nid_t nid, int pin_type, int dac_idx)
17150 alc_set_pin_output(codec, nid, pin_type);
17153 static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
17155 struct alc_spec *spec = codec->spec;
17156 int i;
17158 for (i = 0; i <= HDA_SIDE; i++) {
17159 hda_nid_t nid = spec->autocfg.line_out_pins[i];
17160 int pin_type = get_pin_type(spec->autocfg.line_out_type);
17161 if (nid)
17162 alc861vd_auto_set_output_and_unmute(codec, nid,
17163 pin_type, i);
17168 static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
17170 struct alc_spec *spec = codec->spec;
17171 hda_nid_t pin;
17173 pin = spec->autocfg.hp_pins[0];
17174 if (pin) /* connect to front and use dac 0 */
17175 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
17176 pin = spec->autocfg.speaker_pins[0];
17177 if (pin)
17178 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
17181 #define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID
17183 static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
17185 struct alc_spec *spec = codec->spec;
17186 struct auto_pin_cfg *cfg = &spec->autocfg;
17187 int i;
17189 for (i = 0; i < cfg->num_inputs; i++) {
17190 hda_nid_t nid = cfg->inputs[i].pin;
17191 if (alc_is_input_pin(codec, nid)) {
17192 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
17193 if (nid != ALC861VD_PIN_CD_NID &&
17194 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
17195 snd_hda_codec_write(codec, nid, 0,
17196 AC_VERB_SET_AMP_GAIN_MUTE,
17197 AMP_OUT_MUTE);
17202 #define alc861vd_auto_init_input_src alc882_auto_init_input_src
17204 #define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02)
17205 #define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)
17207 /* add playback controls from the parsed DAC table */
17208 /* Based on ALC880 version. But ALC861VD has separate,
17209 * different NIDs for mute/unmute switch and volume control */
17210 static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
17211 const struct auto_pin_cfg *cfg)
17213 static const char * const chname[4] = {
17214 "Front", "Surround", "CLFE", "Side"
17216 const char *pfx = alc_get_line_out_pfx(spec, true);
17217 hda_nid_t nid_v, nid_s;
17218 int i, err, noutputs;
17220 noutputs = cfg->line_outs;
17221 if (spec->multi_ios > 0)
17222 noutputs += spec->multi_ios;
17224 for (i = 0; i < noutputs; i++) {
17225 if (!spec->multiout.dac_nids[i])
17226 continue;
17227 nid_v = alc861vd_idx_to_mixer_vol(
17228 alc880_dac_to_idx(
17229 spec->multiout.dac_nids[i]));
17230 nid_s = alc861vd_idx_to_mixer_switch(
17231 alc880_dac_to_idx(
17232 spec->multiout.dac_nids[i]));
17234 if (!pfx && i == 2) {
17235 /* Center/LFE */
17236 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
17237 "Center",
17238 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
17239 HDA_OUTPUT));
17240 if (err < 0)
17241 return err;
17242 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
17243 "LFE",
17244 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
17245 HDA_OUTPUT));
17246 if (err < 0)
17247 return err;
17248 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
17249 "Center",
17250 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
17251 HDA_INPUT));
17252 if (err < 0)
17253 return err;
17254 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
17255 "LFE",
17256 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
17257 HDA_INPUT));
17258 if (err < 0)
17259 return err;
17260 } else {
17261 const char *name = pfx;
17262 int index = i;
17263 if (!name) {
17264 name = chname[i];
17265 index = 0;
17267 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
17268 name, index,
17269 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
17270 HDA_OUTPUT));
17271 if (err < 0)
17272 return err;
17273 err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
17274 name, index,
17275 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
17276 HDA_INPUT));
17277 if (err < 0)
17278 return err;
17281 return 0;
17284 /* add playback controls for speaker and HP outputs */
17285 /* Based on ALC880 version. But ALC861VD has separate,
17286 * different NIDs for mute/unmute switch and volume control */
17287 static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
17288 hda_nid_t pin, const char *pfx)
17290 hda_nid_t nid_v, nid_s;
17291 int err;
17293 if (!pin)
17294 return 0;
17296 if (alc880_is_fixed_pin(pin)) {
17297 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
17298 /* specify the DAC as the extra output */
17299 if (!spec->multiout.hp_nid)
17300 spec->multiout.hp_nid = nid_v;
17301 else
17302 spec->multiout.extra_out_nid[0] = nid_v;
17303 /* control HP volume/switch on the output mixer amp */
17304 nid_v = alc861vd_idx_to_mixer_vol(
17305 alc880_fixed_pin_idx(pin));
17306 nid_s = alc861vd_idx_to_mixer_switch(
17307 alc880_fixed_pin_idx(pin));
17309 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
17310 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
17311 if (err < 0)
17312 return err;
17313 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
17314 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
17315 if (err < 0)
17316 return err;
17317 } else if (alc880_is_multi_pin(pin)) {
17318 /* set manual connection */
17319 /* we have only a switch on HP-out PIN */
17320 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
17321 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
17322 if (err < 0)
17323 return err;
17325 return 0;
17328 /* parse the BIOS configuration and set up the alc_spec
17329 * return 1 if successful, 0 if the proper config is not found,
17330 * or a negative error code
17331 * Based on ALC880 version - had to change it to override
17332 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
17333 static int alc861vd_parse_auto_config(struct hda_codec *codec)
17335 struct alc_spec *spec = codec->spec;
17336 int err;
17337 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
17339 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
17340 alc861vd_ignore);
17341 if (err < 0)
17342 return err;
17343 if (!spec->autocfg.line_outs)
17344 return 0; /* can't find valid BIOS pin config */
17346 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
17347 if (err < 0)
17348 return err;
17349 err = alc_auto_add_multi_channel_mode(codec);
17350 if (err < 0)
17351 return err;
17352 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
17353 if (err < 0)
17354 return err;
17355 err = alc861vd_auto_create_extra_out(spec,
17356 spec->autocfg.speaker_pins[0],
17357 "Speaker");
17358 if (err < 0)
17359 return err;
17360 err = alc861vd_auto_create_extra_out(spec,
17361 spec->autocfg.hp_pins[0],
17362 "Headphone");
17363 if (err < 0)
17364 return err;
17365 err = alc861vd_auto_create_input_ctls(codec, &spec->autocfg);
17366 if (err < 0)
17367 return err;
17369 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
17371 alc_auto_parse_digital(codec);
17373 if (spec->kctls.list)
17374 add_mixer(spec, spec->kctls.list);
17376 add_verb(spec, alc861vd_volume_init_verbs);
17378 spec->num_mux_defs = 1;
17379 spec->input_mux = &spec->private_imux[0];
17381 err = alc_auto_add_mic_boost(codec);
17382 if (err < 0)
17383 return err;
17385 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
17387 return 1;
17390 /* additional initialization for auto-configuration model */
17391 static void alc861vd_auto_init(struct hda_codec *codec)
17393 struct alc_spec *spec = codec->spec;
17394 alc861vd_auto_init_multi_out(codec);
17395 alc861vd_auto_init_hp_out(codec);
17396 alc861vd_auto_init_analog_input(codec);
17397 alc861vd_auto_init_input_src(codec);
17398 alc_auto_init_digital(codec);
17399 if (spec->unsol_event)
17400 alc_inithook(codec);
17403 enum {
17404 ALC660VD_FIX_ASUS_GPIO1
17407 /* reset GPIO1 */
17408 static const struct alc_fixup alc861vd_fixups[] = {
17409 [ALC660VD_FIX_ASUS_GPIO1] = {
17410 .type = ALC_FIXUP_VERBS,
17411 .v.verbs = (const struct hda_verb[]) {
17412 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
17413 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
17414 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
17420 static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
17421 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
17425 static int patch_alc861vd(struct hda_codec *codec)
17427 struct alc_spec *spec;
17428 int err, board_config;
17430 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
17431 if (spec == NULL)
17432 return -ENOMEM;
17434 codec->spec = spec;
17436 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
17437 alc861vd_models,
17438 alc861vd_cfg_tbl);
17440 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
17441 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
17442 codec->chip_name);
17443 board_config = ALC861VD_AUTO;
17446 if (board_config == ALC861VD_AUTO) {
17447 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
17448 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
17451 if (board_config == ALC861VD_AUTO) {
17452 /* automatic parse from the BIOS config */
17453 err = alc861vd_parse_auto_config(codec);
17454 if (err < 0) {
17455 alc_free(codec);
17456 return err;
17457 } else if (!err) {
17458 printk(KERN_INFO
17459 "hda_codec: Cannot set up configuration "
17460 "from BIOS. Using base mode...\n");
17461 board_config = ALC861VD_3ST;
17465 err = snd_hda_attach_beep_device(codec, 0x23);
17466 if (err < 0) {
17467 alc_free(codec);
17468 return err;
17471 if (board_config != ALC861VD_AUTO)
17472 setup_preset(codec, &alc861vd_presets[board_config]);
17474 if (codec->vendor_id == 0x10ec0660) {
17475 /* always turn on EAPD */
17476 add_verb(spec, alc660vd_eapd_verbs);
17479 spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
17480 spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
17482 spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
17483 spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
17485 if (!spec->adc_nids) {
17486 spec->adc_nids = alc861vd_adc_nids;
17487 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
17489 if (!spec->capsrc_nids)
17490 spec->capsrc_nids = alc861vd_capsrc_nids;
17492 set_capture_mixer(codec);
17493 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
17495 spec->vmaster_nid = 0x02;
17497 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
17499 codec->patch_ops = alc_patch_ops;
17501 if (board_config == ALC861VD_AUTO)
17502 spec->init_hook = alc861vd_auto_init;
17503 spec->shutup = alc_eapd_shutup;
17504 #ifdef CONFIG_SND_HDA_POWER_SAVE
17505 if (!spec->loopback.amplist)
17506 spec->loopback.amplist = alc861vd_loopbacks;
17507 #endif
17509 return 0;
17513 * ALC662 support
17515 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
17516 * configuration. Each pin widget can choose any input DACs and a mixer.
17517 * Each ADC is connected from a mixer of all inputs. This makes possible
17518 * 6-channel independent captures.
17520 * In addition, an independent DAC for the multi-playback (not used in this
17521 * driver yet).
17523 #define ALC662_DIGOUT_NID 0x06
17524 #define ALC662_DIGIN_NID 0x0a
17526 static const hda_nid_t alc662_dac_nids[3] = {
17527 /* front, rear, clfe */
17528 0x02, 0x03, 0x04
17531 static const hda_nid_t alc272_dac_nids[2] = {
17532 0x02, 0x03
17535 static const hda_nid_t alc662_adc_nids[2] = {
17536 /* ADC1-2 */
17537 0x09, 0x08
17540 static const hda_nid_t alc272_adc_nids[1] = {
17541 /* ADC1-2 */
17542 0x08,
17545 static const hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
17546 static const hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
17549 /* input MUX */
17550 /* FIXME: should be a matrix-type input source selection */
17551 static const struct hda_input_mux alc662_capture_source = {
17552 .num_items = 4,
17553 .items = {
17554 { "Mic", 0x0 },
17555 { "Front Mic", 0x1 },
17556 { "Line", 0x2 },
17557 { "CD", 0x4 },
17561 static const struct hda_input_mux alc662_lenovo_101e_capture_source = {
17562 .num_items = 2,
17563 .items = {
17564 { "Mic", 0x1 },
17565 { "Line", 0x2 },
17569 static const struct hda_input_mux alc663_capture_source = {
17570 .num_items = 3,
17571 .items = {
17572 { "Mic", 0x0 },
17573 { "Front Mic", 0x1 },
17574 { "Line", 0x2 },
17578 #if 0 /* set to 1 for testing other input sources below */
17579 static const struct hda_input_mux alc272_nc10_capture_source = {
17580 .num_items = 16,
17581 .items = {
17582 { "Autoselect Mic", 0x0 },
17583 { "Internal Mic", 0x1 },
17584 { "In-0x02", 0x2 },
17585 { "In-0x03", 0x3 },
17586 { "In-0x04", 0x4 },
17587 { "In-0x05", 0x5 },
17588 { "In-0x06", 0x6 },
17589 { "In-0x07", 0x7 },
17590 { "In-0x08", 0x8 },
17591 { "In-0x09", 0x9 },
17592 { "In-0x0a", 0x0a },
17593 { "In-0x0b", 0x0b },
17594 { "In-0x0c", 0x0c },
17595 { "In-0x0d", 0x0d },
17596 { "In-0x0e", 0x0e },
17597 { "In-0x0f", 0x0f },
17600 #endif
17603 * 2ch mode
17605 static const struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
17606 { 2, NULL }
17610 * 2ch mode
17612 static const struct hda_verb alc662_3ST_ch2_init[] = {
17613 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
17614 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
17615 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
17616 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
17617 { } /* end */
17621 * 6ch mode
17623 static const struct hda_verb alc662_3ST_ch6_init[] = {
17624 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17625 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
17626 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
17627 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17628 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
17629 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
17630 { } /* end */
17633 static const struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
17634 { 2, alc662_3ST_ch2_init },
17635 { 6, alc662_3ST_ch6_init },
17639 * 2ch mode
17641 static const struct hda_verb alc662_sixstack_ch6_init[] = {
17642 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
17643 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
17644 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17645 { } /* end */
17649 * 6ch mode
17651 static const struct hda_verb alc662_sixstack_ch8_init[] = {
17652 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17653 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17654 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17655 { } /* end */
17658 static const struct hda_channel_mode alc662_5stack_modes[2] = {
17659 { 2, alc662_sixstack_ch6_init },
17660 { 6, alc662_sixstack_ch8_init },
17663 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
17664 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
17667 static const struct snd_kcontrol_new alc662_base_mixer[] = {
17668 /* output mixer control */
17669 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
17670 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
17671 HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
17672 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
17673 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
17674 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
17675 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
17676 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
17677 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17679 /*Input mixer control */
17680 HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
17681 HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
17682 HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
17683 HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
17684 HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
17685 HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
17686 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
17687 HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
17688 { } /* end */
17691 static const struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
17692 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17693 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
17694 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17695 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
17696 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
17697 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17698 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17699 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17700 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17701 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17702 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17703 { } /* end */
17706 static const struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
17707 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17708 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
17709 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17710 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
17711 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
17712 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
17713 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
17714 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
17715 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17716 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
17717 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
17718 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17719 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17720 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17721 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17722 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17723 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17724 { } /* end */
17727 static const struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
17728 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17729 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
17730 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17731 HDA_BIND_MUTE("Speaker Playback Switch", 0x03, 2, HDA_INPUT),
17732 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17733 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17734 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17735 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17736 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17737 { } /* end */
17740 static const struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
17741 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17742 ALC262_HIPPO_MASTER_SWITCH,
17744 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
17745 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17746 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17748 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
17749 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17750 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17751 { } /* end */
17754 static const struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
17755 ALC262_HIPPO_MASTER_SWITCH,
17756 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17757 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17758 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
17759 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
17760 HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),
17761 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17762 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17763 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17764 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17765 { } /* end */
17768 static const struct hda_bind_ctls alc663_asus_bind_master_vol = {
17769 .ops = &snd_hda_bind_vol,
17770 .values = {
17771 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
17772 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
17777 static const struct hda_bind_ctls alc663_asus_one_bind_switch = {
17778 .ops = &snd_hda_bind_sw,
17779 .values = {
17780 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17781 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
17786 static const struct snd_kcontrol_new alc663_m51va_mixer[] = {
17787 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17788 HDA_BIND_SW("Master Playback Switch", &alc663_asus_one_bind_switch),
17789 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17790 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17791 { } /* end */
17794 static const struct hda_bind_ctls alc663_asus_tree_bind_switch = {
17795 .ops = &snd_hda_bind_sw,
17796 .values = {
17797 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17798 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
17799 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
17804 static const struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
17805 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17806 HDA_BIND_SW("Master Playback Switch", &alc663_asus_tree_bind_switch),
17807 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17808 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17809 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17810 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17812 { } /* end */
17815 static const struct hda_bind_ctls alc663_asus_four_bind_switch = {
17816 .ops = &snd_hda_bind_sw,
17817 .values = {
17818 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17819 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
17820 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
17825 static const struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
17826 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17827 HDA_BIND_SW("Master Playback Switch", &alc663_asus_four_bind_switch),
17828 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17829 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17830 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17831 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17832 { } /* end */
17835 static const struct snd_kcontrol_new alc662_1bjd_mixer[] = {
17836 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17837 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
17838 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17839 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17840 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17841 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17842 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17843 { } /* end */
17846 static const struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
17847 .ops = &snd_hda_bind_vol,
17848 .values = {
17849 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
17850 HDA_COMPOSE_AMP_VAL(0x04, 3, 0, HDA_OUTPUT),
17855 static const struct hda_bind_ctls alc663_asus_two_bind_switch = {
17856 .ops = &snd_hda_bind_sw,
17857 .values = {
17858 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17859 HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT),
17864 static const struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
17865 HDA_BIND_VOL("Master Playback Volume",
17866 &alc663_asus_two_bind_master_vol),
17867 HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
17868 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17869 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17870 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17871 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17872 { } /* end */
17875 static const struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
17876 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17877 HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
17878 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17879 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
17880 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17881 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17882 { } /* end */
17885 static const struct snd_kcontrol_new alc663_g71v_mixer[] = {
17886 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17887 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
17888 HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17889 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
17890 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17892 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17893 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17894 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17895 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17896 { } /* end */
17899 static const struct snd_kcontrol_new alc663_g50v_mixer[] = {
17900 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17901 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
17902 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17904 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17905 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17906 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17907 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17908 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17909 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17910 { } /* end */
17913 static const struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
17914 .ops = &snd_hda_bind_sw,
17915 .values = {
17916 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17917 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
17918 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
17919 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
17920 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
17925 static const struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
17926 .ops = &snd_hda_bind_sw,
17927 .values = {
17928 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17929 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
17934 static const struct snd_kcontrol_new alc663_mode7_mixer[] = {
17935 HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
17936 HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
17937 HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
17938 HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17939 HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17940 HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17941 HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17942 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17943 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17944 { } /* end */
17947 static const struct snd_kcontrol_new alc663_mode8_mixer[] = {
17948 HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
17949 HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
17950 HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
17951 HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT),
17952 HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17953 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17954 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17955 { } /* end */
17959 static const struct snd_kcontrol_new alc662_chmode_mixer[] = {
17961 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
17962 .name = "Channel Mode",
17963 .info = alc_ch_mode_info,
17964 .get = alc_ch_mode_get,
17965 .put = alc_ch_mode_put,
17967 { } /* end */
17970 static const struct hda_verb alc662_init_verbs[] = {
17971 /* ADC: mute amp left and right */
17972 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17973 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
17975 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17976 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17977 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17978 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17979 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17980 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17982 /* Front Pin: output 0 (0x0c) */
17983 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17984 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17986 /* Rear Pin: output 1 (0x0d) */
17987 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17988 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17990 /* CLFE Pin: output 2 (0x0e) */
17991 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17992 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17994 /* Mic (rear) pin: input vref at 80% */
17995 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
17996 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
17997 /* Front Mic pin: input vref at 80% */
17998 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
17999 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
18000 /* Line In pin: input */
18001 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18002 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
18003 /* Line-2 In: Headphone output (output 0 - 0x0c) */
18004 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18005 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18006 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
18007 /* CD pin widget for input */
18008 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18010 /* FIXME: use matrix-type input source selection */
18011 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
18012 /* Input mixer */
18013 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
18014 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
18019 static const struct hda_verb alc662_eapd_init_verbs[] = {
18020 /* always trun on EAPD */
18021 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
18022 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
18026 static const struct hda_verb alc662_sue_init_verbs[] = {
18027 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
18028 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
18032 static const struct hda_verb alc662_eeepc_sue_init_verbs[] = {
18033 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18034 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18038 /* Set Unsolicited Event*/
18039 static const struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
18040 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
18041 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18045 static const struct hda_verb alc663_m51va_init_verbs[] = {
18046 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18047 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18048 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18049 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18050 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18051 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18052 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
18053 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18054 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18058 static const struct hda_verb alc663_21jd_amic_init_verbs[] = {
18059 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18060 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18061 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18062 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18063 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
18064 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18065 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18069 static const struct hda_verb alc662_1bjd_amic_init_verbs[] = {
18070 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18071 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18072 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18073 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
18074 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18075 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
18076 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18077 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18081 static const struct hda_verb alc663_15jd_amic_init_verbs[] = {
18082 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18083 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18084 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18085 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18086 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
18087 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18088 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18092 static const struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
18093 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18094 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18095 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18096 {0x21, AC_VERB_SET_CONNECT_SEL, 0x0}, /* 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, 0x0}, /* 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 {0x21, 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_two_hp_amic_m2_init_verbs[] = {
18109 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18110 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18111 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18112 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18113 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18114 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18115 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18116 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18117 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
18118 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18119 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18120 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18124 static const struct hda_verb alc663_g71v_init_verbs[] = {
18125 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18126 /* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
18127 /* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
18129 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18130 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18131 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
18133 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
18134 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_MIC_EVENT},
18135 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
18139 static const struct hda_verb alc663_g50v_init_verbs[] = {
18140 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18141 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18142 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
18144 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18145 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18149 static const struct hda_verb alc662_ecs_init_verbs[] = {
18150 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
18151 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18152 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18153 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18157 static const struct hda_verb alc272_dell_zm1_init_verbs[] = {
18158 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18159 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18160 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18161 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18162 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18163 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18164 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18165 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18166 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
18167 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18168 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18172 static const struct hda_verb alc272_dell_init_verbs[] = {
18173 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18174 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18175 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18176 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18177 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18178 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18179 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18180 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18181 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
18182 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18183 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18187 static const struct hda_verb alc663_mode7_init_verbs[] = {
18188 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18189 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18190 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
18191 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18192 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18193 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18194 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
18195 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18196 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18197 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18198 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18199 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
18200 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18201 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18202 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18206 static const struct hda_verb alc663_mode8_init_verbs[] = {
18207 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18208 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18209 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18210 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
18211 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18212 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
18213 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18214 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
18215 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
18216 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
18217 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
18218 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
18219 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
18220 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18221 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
18222 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
18226 static const struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
18227 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
18228 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
18229 { } /* end */
18232 static const struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
18233 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
18234 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
18235 { } /* end */
18238 static void alc662_lenovo_101e_setup(struct hda_codec *codec)
18240 struct alc_spec *spec = codec->spec;
18242 spec->autocfg.hp_pins[0] = 0x1b;
18243 spec->autocfg.line_out_pins[0] = 0x14;
18244 spec->autocfg.speaker_pins[0] = 0x15;
18245 spec->automute = 1;
18246 spec->detect_line = 1;
18247 spec->automute_lines = 1;
18248 spec->automute_mode = ALC_AUTOMUTE_AMP;
18251 static void alc662_eeepc_setup(struct hda_codec *codec)
18253 struct alc_spec *spec = codec->spec;
18255 alc262_hippo1_setup(codec);
18256 spec->ext_mic.pin = 0x18;
18257 spec->ext_mic.mux_idx = 0;
18258 spec->int_mic.pin = 0x19;
18259 spec->int_mic.mux_idx = 1;
18260 spec->auto_mic = 1;
18263 static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
18265 struct alc_spec *spec = codec->spec;
18267 spec->autocfg.hp_pins[0] = 0x14;
18268 spec->autocfg.speaker_pins[0] = 0x1b;
18269 spec->automute = 1;
18270 spec->automute_mode = ALC_AUTOMUTE_AMP;
18273 static void alc663_m51va_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 = 0x12;
18284 spec->int_mic.mux_idx = 9;
18285 spec->auto_mic = 1;
18288 /* ***************** Mode1 ******************************/
18289 static void alc663_mode1_setup(struct hda_codec *codec)
18291 struct alc_spec *spec = codec->spec;
18292 spec->autocfg.hp_pins[0] = 0x21;
18293 spec->autocfg.speaker_pins[0] = 0x14;
18294 spec->automute_mixer_nid[0] = 0x0c;
18295 spec->automute = 1;
18296 spec->automute_mode = ALC_AUTOMUTE_MIXER;
18297 spec->ext_mic.pin = 0x18;
18298 spec->ext_mic.mux_idx = 0;
18299 spec->int_mic.pin = 0x19;
18300 spec->int_mic.mux_idx = 1;
18301 spec->auto_mic = 1;
18304 /* ***************** Mode2 ******************************/
18305 static void alc662_mode2_setup(struct hda_codec *codec)
18307 struct alc_spec *spec = codec->spec;
18308 spec->autocfg.hp_pins[0] = 0x1b;
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 /* ***************** Mode3 ******************************/
18320 static void alc663_mode3_setup(struct hda_codec *codec)
18322 struct alc_spec *spec = codec->spec;
18323 spec->autocfg.hp_pins[0] = 0x21;
18324 spec->autocfg.hp_pins[0] = 0x15;
18325 spec->autocfg.speaker_pins[0] = 0x14;
18326 spec->automute = 1;
18327 spec->automute_mode = ALC_AUTOMUTE_PIN;
18328 spec->ext_mic.pin = 0x18;
18329 spec->ext_mic.mux_idx = 0;
18330 spec->int_mic.pin = 0x19;
18331 spec->int_mic.mux_idx = 1;
18332 spec->auto_mic = 1;
18335 /* ***************** Mode4 ******************************/
18336 static void alc663_mode4_setup(struct hda_codec *codec)
18338 struct alc_spec *spec = codec->spec;
18339 spec->autocfg.hp_pins[0] = 0x21;
18340 spec->autocfg.speaker_pins[0] = 0x14;
18341 spec->autocfg.speaker_pins[1] = 0x16;
18342 spec->automute_mixer_nid[0] = 0x0c;
18343 spec->automute_mixer_nid[1] = 0x0e;
18344 spec->automute = 1;
18345 spec->automute_mode = ALC_AUTOMUTE_MIXER;
18346 spec->ext_mic.pin = 0x18;
18347 spec->ext_mic.mux_idx = 0;
18348 spec->int_mic.pin = 0x19;
18349 spec->int_mic.mux_idx = 1;
18350 spec->auto_mic = 1;
18353 /* ***************** Mode5 ******************************/
18354 static void alc663_mode5_setup(struct hda_codec *codec)
18356 struct alc_spec *spec = codec->spec;
18357 spec->autocfg.hp_pins[0] = 0x15;
18358 spec->autocfg.speaker_pins[0] = 0x14;
18359 spec->autocfg.speaker_pins[1] = 0x16;
18360 spec->automute_mixer_nid[0] = 0x0c;
18361 spec->automute_mixer_nid[1] = 0x0e;
18362 spec->automute = 1;
18363 spec->automute_mode = ALC_AUTOMUTE_MIXER;
18364 spec->ext_mic.pin = 0x18;
18365 spec->ext_mic.mux_idx = 0;
18366 spec->int_mic.pin = 0x19;
18367 spec->int_mic.mux_idx = 1;
18368 spec->auto_mic = 1;
18371 /* ***************** Mode6 ******************************/
18372 static void alc663_mode6_setup(struct hda_codec *codec)
18374 struct alc_spec *spec = codec->spec;
18375 spec->autocfg.hp_pins[0] = 0x1b;
18376 spec->autocfg.hp_pins[0] = 0x15;
18377 spec->autocfg.speaker_pins[0] = 0x14;
18378 spec->automute_mixer_nid[0] = 0x0c;
18379 spec->automute = 1;
18380 spec->automute_mode = ALC_AUTOMUTE_MIXER;
18381 spec->ext_mic.pin = 0x18;
18382 spec->ext_mic.mux_idx = 0;
18383 spec->int_mic.pin = 0x19;
18384 spec->int_mic.mux_idx = 1;
18385 spec->auto_mic = 1;
18388 /* ***************** Mode7 ******************************/
18389 static void alc663_mode7_setup(struct hda_codec *codec)
18391 struct alc_spec *spec = codec->spec;
18392 spec->autocfg.hp_pins[0] = 0x1b;
18393 spec->autocfg.hp_pins[0] = 0x21;
18394 spec->autocfg.speaker_pins[0] = 0x14;
18395 spec->autocfg.speaker_pins[0] = 0x17;
18396 spec->automute = 1;
18397 spec->automute_mode = ALC_AUTOMUTE_PIN;
18398 spec->ext_mic.pin = 0x18;
18399 spec->ext_mic.mux_idx = 0;
18400 spec->int_mic.pin = 0x19;
18401 spec->int_mic.mux_idx = 1;
18402 spec->auto_mic = 1;
18405 /* ***************** Mode8 ******************************/
18406 static void alc663_mode8_setup(struct hda_codec *codec)
18408 struct alc_spec *spec = codec->spec;
18409 spec->autocfg.hp_pins[0] = 0x21;
18410 spec->autocfg.hp_pins[1] = 0x15;
18411 spec->autocfg.speaker_pins[0] = 0x14;
18412 spec->autocfg.speaker_pins[0] = 0x17;
18413 spec->automute = 1;
18414 spec->automute_mode = ALC_AUTOMUTE_PIN;
18415 spec->ext_mic.pin = 0x18;
18416 spec->ext_mic.mux_idx = 0;
18417 spec->int_mic.pin = 0x12;
18418 spec->int_mic.mux_idx = 9;
18419 spec->auto_mic = 1;
18422 static void alc663_g71v_setup(struct hda_codec *codec)
18424 struct alc_spec *spec = codec->spec;
18425 spec->autocfg.hp_pins[0] = 0x21;
18426 spec->autocfg.line_out_pins[0] = 0x15;
18427 spec->autocfg.speaker_pins[0] = 0x14;
18428 spec->automute = 1;
18429 spec->automute_mode = ALC_AUTOMUTE_AMP;
18430 spec->detect_line = 1;
18431 spec->automute_lines = 1;
18432 spec->ext_mic.pin = 0x18;
18433 spec->ext_mic.mux_idx = 0;
18434 spec->int_mic.pin = 0x12;
18435 spec->int_mic.mux_idx = 9;
18436 spec->auto_mic = 1;
18439 #define alc663_g50v_setup alc663_m51va_setup
18441 static const struct snd_kcontrol_new alc662_ecs_mixer[] = {
18442 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
18443 ALC262_HIPPO_MASTER_SWITCH,
18445 HDA_CODEC_VOLUME("Mic/LineIn Boost Volume", 0x18, 0, HDA_INPUT),
18446 HDA_CODEC_VOLUME("Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT),
18447 HDA_CODEC_MUTE("Mic/LineIn Playback Switch", 0x0b, 0x0, HDA_INPUT),
18449 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 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 { } /* end */
18455 static const struct snd_kcontrol_new alc272_nc10_mixer[] = {
18456 /* Master Playback automatically created from Speaker and Headphone */
18457 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
18458 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
18459 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
18460 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
18462 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
18463 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
18464 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
18466 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
18467 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
18468 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
18469 { } /* end */
18472 #ifdef CONFIG_SND_HDA_POWER_SAVE
18473 #define alc662_loopbacks alc880_loopbacks
18474 #endif
18477 /* pcm configuration: identical with ALC880 */
18478 #define alc662_pcm_analog_playback alc880_pcm_analog_playback
18479 #define alc662_pcm_analog_capture alc880_pcm_analog_capture
18480 #define alc662_pcm_digital_playback alc880_pcm_digital_playback
18481 #define alc662_pcm_digital_capture alc880_pcm_digital_capture
18484 * configuration and preset
18486 static const char * const alc662_models[ALC662_MODEL_LAST] = {
18487 [ALC662_3ST_2ch_DIG] = "3stack-dig",
18488 [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig",
18489 [ALC662_3ST_6ch] = "3stack-6ch",
18490 [ALC662_5ST_DIG] = "5stack-dig",
18491 [ALC662_LENOVO_101E] = "lenovo-101e",
18492 [ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
18493 [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
18494 [ALC662_ECS] = "ecs",
18495 [ALC663_ASUS_M51VA] = "m51va",
18496 [ALC663_ASUS_G71V] = "g71v",
18497 [ALC663_ASUS_H13] = "h13",
18498 [ALC663_ASUS_G50V] = "g50v",
18499 [ALC663_ASUS_MODE1] = "asus-mode1",
18500 [ALC662_ASUS_MODE2] = "asus-mode2",
18501 [ALC663_ASUS_MODE3] = "asus-mode3",
18502 [ALC663_ASUS_MODE4] = "asus-mode4",
18503 [ALC663_ASUS_MODE5] = "asus-mode5",
18504 [ALC663_ASUS_MODE6] = "asus-mode6",
18505 [ALC663_ASUS_MODE7] = "asus-mode7",
18506 [ALC663_ASUS_MODE8] = "asus-mode8",
18507 [ALC272_DELL] = "dell",
18508 [ALC272_DELL_ZM1] = "dell-zm1",
18509 [ALC272_SAMSUNG_NC10] = "samsung-nc10",
18510 [ALC662_AUTO] = "auto",
18513 static const struct snd_pci_quirk alc662_cfg_tbl[] = {
18514 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
18515 SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL),
18516 SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
18517 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
18518 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
18519 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1),
18520 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
18521 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
18522 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
18523 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
18524 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1),
18525 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1),
18526 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
18527 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7),
18528 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7),
18529 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8),
18530 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3),
18531 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1),
18532 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
18533 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2),
18534 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1),
18535 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
18536 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
18537 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
18538 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
18539 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1),
18540 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
18541 SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
18542 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
18543 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
18544 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
18545 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
18546 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
18547 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC663_ASUS_MODE1),
18548 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
18549 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
18550 SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
18551 /*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/
18552 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
18553 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
18554 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1),
18555 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1),
18556 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1),
18557 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1),
18558 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
18559 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
18560 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
18561 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC663_ASUS_MODE1),
18562 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
18563 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
18564 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC663_ASUS_MODE1),
18565 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
18566 SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
18567 /*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/
18568 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
18569 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
18570 SND_PCI_QUIRK(0x1043, 0x19d3, "ASUS NB", ALC663_ASUS_M51VA),
18571 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
18572 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
18573 SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
18574 SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
18575 SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
18576 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
18577 SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
18578 ALC662_3ST_6ch_DIG),
18579 SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
18580 SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
18581 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
18582 ALC662_3ST_6ch_DIG),
18583 SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
18584 SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
18585 SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
18586 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
18587 SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
18588 ALC662_3ST_6ch_DIG),
18589 SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
18590 ALC663_ASUS_H13),
18591 SND_PCI_QUIRK(0x1991, 0x5628, "Ordissimo EVE", ALC662_LENOVO_101E),
18595 static const struct alc_config_preset alc662_presets[] = {
18596 [ALC662_3ST_2ch_DIG] = {
18597 .mixers = { alc662_3ST_2ch_mixer },
18598 .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
18599 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18600 .dac_nids = alc662_dac_nids,
18601 .dig_out_nid = ALC662_DIGOUT_NID,
18602 .dig_in_nid = ALC662_DIGIN_NID,
18603 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18604 .channel_mode = alc662_3ST_2ch_modes,
18605 .input_mux = &alc662_capture_source,
18607 [ALC662_3ST_6ch_DIG] = {
18608 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
18609 .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
18610 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18611 .dac_nids = alc662_dac_nids,
18612 .dig_out_nid = ALC662_DIGOUT_NID,
18613 .dig_in_nid = ALC662_DIGIN_NID,
18614 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18615 .channel_mode = alc662_3ST_6ch_modes,
18616 .need_dac_fix = 1,
18617 .input_mux = &alc662_capture_source,
18619 [ALC662_3ST_6ch] = {
18620 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
18621 .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
18622 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18623 .dac_nids = alc662_dac_nids,
18624 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18625 .channel_mode = alc662_3ST_6ch_modes,
18626 .need_dac_fix = 1,
18627 .input_mux = &alc662_capture_source,
18629 [ALC662_5ST_DIG] = {
18630 .mixers = { alc662_base_mixer, alc662_chmode_mixer },
18631 .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
18632 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18633 .dac_nids = alc662_dac_nids,
18634 .dig_out_nid = ALC662_DIGOUT_NID,
18635 .dig_in_nid = ALC662_DIGIN_NID,
18636 .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
18637 .channel_mode = alc662_5stack_modes,
18638 .input_mux = &alc662_capture_source,
18640 [ALC662_LENOVO_101E] = {
18641 .mixers = { alc662_lenovo_101e_mixer },
18642 .init_verbs = { alc662_init_verbs,
18643 alc662_eapd_init_verbs,
18644 alc662_sue_init_verbs },
18645 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18646 .dac_nids = alc662_dac_nids,
18647 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18648 .channel_mode = alc662_3ST_2ch_modes,
18649 .input_mux = &alc662_lenovo_101e_capture_source,
18650 .unsol_event = alc_sku_unsol_event,
18651 .setup = alc662_lenovo_101e_setup,
18652 .init_hook = alc_inithook,
18654 [ALC662_ASUS_EEEPC_P701] = {
18655 .mixers = { alc662_eeepc_p701_mixer },
18656 .init_verbs = { alc662_init_verbs,
18657 alc662_eapd_init_verbs,
18658 alc662_eeepc_sue_init_verbs },
18659 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18660 .dac_nids = alc662_dac_nids,
18661 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18662 .channel_mode = alc662_3ST_2ch_modes,
18663 .unsol_event = alc_sku_unsol_event,
18664 .setup = alc662_eeepc_setup,
18665 .init_hook = alc_inithook,
18667 [ALC662_ASUS_EEEPC_EP20] = {
18668 .mixers = { alc662_eeepc_ep20_mixer,
18669 alc662_chmode_mixer },
18670 .init_verbs = { alc662_init_verbs,
18671 alc662_eapd_init_verbs,
18672 alc662_eeepc_ep20_sue_init_verbs },
18673 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18674 .dac_nids = alc662_dac_nids,
18675 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18676 .channel_mode = alc662_3ST_6ch_modes,
18677 .input_mux = &alc662_lenovo_101e_capture_source,
18678 .unsol_event = alc_sku_unsol_event,
18679 .setup = alc662_eeepc_ep20_setup,
18680 .init_hook = alc_inithook,
18682 [ALC662_ECS] = {
18683 .mixers = { alc662_ecs_mixer },
18684 .init_verbs = { alc662_init_verbs,
18685 alc662_eapd_init_verbs,
18686 alc662_ecs_init_verbs },
18687 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18688 .dac_nids = alc662_dac_nids,
18689 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18690 .channel_mode = alc662_3ST_2ch_modes,
18691 .unsol_event = alc_sku_unsol_event,
18692 .setup = alc662_eeepc_setup,
18693 .init_hook = alc_inithook,
18695 [ALC663_ASUS_M51VA] = {
18696 .mixers = { alc663_m51va_mixer },
18697 .init_verbs = { alc662_init_verbs,
18698 alc662_eapd_init_verbs,
18699 alc663_m51va_init_verbs },
18700 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18701 .dac_nids = alc662_dac_nids,
18702 .dig_out_nid = ALC662_DIGOUT_NID,
18703 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18704 .channel_mode = alc662_3ST_2ch_modes,
18705 .unsol_event = alc_sku_unsol_event,
18706 .setup = alc663_m51va_setup,
18707 .init_hook = alc_inithook,
18709 [ALC663_ASUS_G71V] = {
18710 .mixers = { alc663_g71v_mixer },
18711 .init_verbs = { alc662_init_verbs,
18712 alc662_eapd_init_verbs,
18713 alc663_g71v_init_verbs },
18714 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18715 .dac_nids = alc662_dac_nids,
18716 .dig_out_nid = ALC662_DIGOUT_NID,
18717 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18718 .channel_mode = alc662_3ST_2ch_modes,
18719 .unsol_event = alc_sku_unsol_event,
18720 .setup = alc663_g71v_setup,
18721 .init_hook = alc_inithook,
18723 [ALC663_ASUS_H13] = {
18724 .mixers = { alc663_m51va_mixer },
18725 .init_verbs = { alc662_init_verbs,
18726 alc662_eapd_init_verbs,
18727 alc663_m51va_init_verbs },
18728 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18729 .dac_nids = alc662_dac_nids,
18730 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18731 .channel_mode = alc662_3ST_2ch_modes,
18732 .setup = alc663_m51va_setup,
18733 .unsol_event = alc_sku_unsol_event,
18734 .init_hook = alc_inithook,
18736 [ALC663_ASUS_G50V] = {
18737 .mixers = { alc663_g50v_mixer },
18738 .init_verbs = { alc662_init_verbs,
18739 alc662_eapd_init_verbs,
18740 alc663_g50v_init_verbs },
18741 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18742 .dac_nids = alc662_dac_nids,
18743 .dig_out_nid = ALC662_DIGOUT_NID,
18744 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18745 .channel_mode = alc662_3ST_6ch_modes,
18746 .input_mux = &alc663_capture_source,
18747 .unsol_event = alc_sku_unsol_event,
18748 .setup = alc663_g50v_setup,
18749 .init_hook = alc_inithook,
18751 [ALC663_ASUS_MODE1] = {
18752 .mixers = { alc663_m51va_mixer },
18753 .cap_mixer = alc662_auto_capture_mixer,
18754 .init_verbs = { alc662_init_verbs,
18755 alc662_eapd_init_verbs,
18756 alc663_21jd_amic_init_verbs },
18757 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18758 .hp_nid = 0x03,
18759 .dac_nids = alc662_dac_nids,
18760 .dig_out_nid = ALC662_DIGOUT_NID,
18761 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18762 .channel_mode = alc662_3ST_2ch_modes,
18763 .unsol_event = alc_sku_unsol_event,
18764 .setup = alc663_mode1_setup,
18765 .init_hook = alc_inithook,
18767 [ALC662_ASUS_MODE2] = {
18768 .mixers = { alc662_1bjd_mixer },
18769 .cap_mixer = alc662_auto_capture_mixer,
18770 .init_verbs = { alc662_init_verbs,
18771 alc662_eapd_init_verbs,
18772 alc662_1bjd_amic_init_verbs },
18773 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
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 = alc662_mode2_setup,
18780 .init_hook = alc_inithook,
18782 [ALC663_ASUS_MODE3] = {
18783 .mixers = { alc663_two_hp_m1_mixer },
18784 .cap_mixer = alc662_auto_capture_mixer,
18785 .init_verbs = { alc662_init_verbs,
18786 alc662_eapd_init_verbs,
18787 alc663_two_hp_amic_m1_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_mode3_setup,
18796 .init_hook = alc_inithook,
18798 [ALC663_ASUS_MODE4] = {
18799 .mixers = { alc663_asus_21jd_clfe_mixer },
18800 .cap_mixer = alc662_auto_capture_mixer,
18801 .init_verbs = { alc662_init_verbs,
18802 alc662_eapd_init_verbs,
18803 alc663_21jd_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_mode4_setup,
18812 .init_hook = alc_inithook,
18814 [ALC663_ASUS_MODE5] = {
18815 .mixers = { alc663_asus_15jd_clfe_mixer },
18816 .cap_mixer = alc662_auto_capture_mixer,
18817 .init_verbs = { alc662_init_verbs,
18818 alc662_eapd_init_verbs,
18819 alc663_15jd_amic_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_mode5_setup,
18828 .init_hook = alc_inithook,
18830 [ALC663_ASUS_MODE6] = {
18831 .mixers = { alc663_two_hp_m2_mixer },
18832 .cap_mixer = alc662_auto_capture_mixer,
18833 .init_verbs = { alc662_init_verbs,
18834 alc662_eapd_init_verbs,
18835 alc663_two_hp_amic_m2_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_mode6_setup,
18844 .init_hook = alc_inithook,
18846 [ALC663_ASUS_MODE7] = {
18847 .mixers = { alc663_mode7_mixer },
18848 .cap_mixer = alc662_auto_capture_mixer,
18849 .init_verbs = { alc662_init_verbs,
18850 alc662_eapd_init_verbs,
18851 alc663_mode7_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_mode7_setup,
18860 .init_hook = alc_inithook,
18862 [ALC663_ASUS_MODE8] = {
18863 .mixers = { alc663_mode8_mixer },
18864 .cap_mixer = alc662_auto_capture_mixer,
18865 .init_verbs = { alc662_init_verbs,
18866 alc662_eapd_init_verbs,
18867 alc663_mode8_init_verbs },
18868 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18869 .hp_nid = 0x03,
18870 .dac_nids = alc662_dac_nids,
18871 .dig_out_nid = ALC662_DIGOUT_NID,
18872 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18873 .channel_mode = alc662_3ST_2ch_modes,
18874 .unsol_event = alc_sku_unsol_event,
18875 .setup = alc663_mode8_setup,
18876 .init_hook = alc_inithook,
18878 [ALC272_DELL] = {
18879 .mixers = { alc663_m51va_mixer },
18880 .cap_mixer = alc272_auto_capture_mixer,
18881 .init_verbs = { alc662_init_verbs,
18882 alc662_eapd_init_verbs,
18883 alc272_dell_init_verbs },
18884 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18885 .dac_nids = alc272_dac_nids,
18886 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18887 .adc_nids = alc272_adc_nids,
18888 .num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
18889 .capsrc_nids = alc272_capsrc_nids,
18890 .channel_mode = alc662_3ST_2ch_modes,
18891 .unsol_event = alc_sku_unsol_event,
18892 .setup = alc663_m51va_setup,
18893 .init_hook = alc_inithook,
18895 [ALC272_DELL_ZM1] = {
18896 .mixers = { alc663_m51va_mixer },
18897 .cap_mixer = alc662_auto_capture_mixer,
18898 .init_verbs = { alc662_init_verbs,
18899 alc662_eapd_init_verbs,
18900 alc272_dell_zm1_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 .adc_nids = alc662_adc_nids,
18905 .num_adc_nids = 1,
18906 .capsrc_nids = alc662_capsrc_nids,
18907 .channel_mode = alc662_3ST_2ch_modes,
18908 .unsol_event = alc_sku_unsol_event,
18909 .setup = alc663_m51va_setup,
18910 .init_hook = alc_inithook,
18912 [ALC272_SAMSUNG_NC10] = {
18913 .mixers = { alc272_nc10_mixer },
18914 .init_verbs = { alc662_init_verbs,
18915 alc662_eapd_init_verbs,
18916 alc663_21jd_amic_init_verbs },
18917 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18918 .dac_nids = alc272_dac_nids,
18919 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18920 .channel_mode = alc662_3ST_2ch_modes,
18921 /*.input_mux = &alc272_nc10_capture_source,*/
18922 .unsol_event = alc_sku_unsol_event,
18923 .setup = alc663_mode4_setup,
18924 .init_hook = alc_inithook,
18930 * BIOS auto configuration
18933 /* convert from MIX nid to DAC */
18934 static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
18936 hda_nid_t list[5];
18937 int i, num;
18939 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
18940 for (i = 0; i < num; i++) {
18941 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
18942 return list[i];
18944 return 0;
18947 /* go down to the selector widget before the mixer */
18948 static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
18950 hda_nid_t srcs[5];
18951 int num = snd_hda_get_connections(codec, pin, srcs,
18952 ARRAY_SIZE(srcs));
18953 if (num != 1 ||
18954 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
18955 return pin;
18956 return srcs[0];
18959 /* get MIX nid connected to the given pin targeted to DAC */
18960 static hda_nid_t alc_auto_dac_to_mix(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 for (i = 0; i < num; i++) {
18969 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
18970 return mix[i];
18972 return 0;
18975 /* select the connection from pin to DAC if needed */
18976 static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
18977 hda_nid_t dac)
18979 hda_nid_t mix[5];
18980 int i, num;
18982 pin = alc_go_down_to_selector(codec, pin);
18983 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
18984 if (num < 2)
18985 return 0;
18986 for (i = 0; i < num; i++) {
18987 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
18988 snd_hda_codec_update_cache(codec, pin, 0,
18989 AC_VERB_SET_CONNECT_SEL, i);
18990 return 0;
18993 return 0;
18996 /* look for an empty DAC slot */
18997 static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
18999 struct alc_spec *spec = codec->spec;
19000 hda_nid_t srcs[5];
19001 int i, j, num;
19003 pin = alc_go_down_to_selector(codec, pin);
19004 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
19005 for (i = 0; i < num; i++) {
19006 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
19007 if (!nid)
19008 continue;
19009 for (j = 0; j < spec->multiout.num_dacs; j++)
19010 if (spec->multiout.dac_nids[j] == nid)
19011 break;
19012 if (j >= spec->multiout.num_dacs)
19013 return nid;
19015 return 0;
19018 /* fill in the dac_nids table from the parsed pin configuration */
19019 static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
19020 const struct auto_pin_cfg *cfg)
19022 struct alc_spec *spec = codec->spec;
19023 int i;
19024 hda_nid_t dac;
19026 spec->multiout.dac_nids = spec->private_dac_nids;
19027 for (i = 0; i < cfg->line_outs; i++) {
19028 dac = alc_auto_look_for_dac(codec, cfg->line_out_pins[i]);
19029 if (!dac)
19030 continue;
19031 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
19033 return 0;
19036 static inline int __alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
19037 hda_nid_t nid, int idx, unsigned int chs)
19039 return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx,
19040 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
19043 static inline int __alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
19044 hda_nid_t nid, int idx, unsigned int chs)
19046 return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx,
19047 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
19050 #define alc662_add_vol_ctl(spec, pfx, nid, chs) \
19051 __alc662_add_vol_ctl(spec, pfx, nid, 0, chs)
19052 #define alc662_add_sw_ctl(spec, pfx, nid, chs) \
19053 __alc662_add_sw_ctl(spec, pfx, nid, 0, chs)
19054 #define alc662_add_stereo_vol(spec, pfx, nid) \
19055 alc662_add_vol_ctl(spec, pfx, nid, 3)
19056 #define alc662_add_stereo_sw(spec, pfx, nid) \
19057 alc662_add_sw_ctl(spec, pfx, nid, 3)
19059 /* add playback controls from the parsed DAC table */
19060 static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
19061 const struct auto_pin_cfg *cfg)
19063 struct alc_spec *spec = codec->spec;
19064 static const char * const chname[4] = {
19065 "Front", "Surround", NULL /*CLFE*/, "Side"
19067 const char *pfx = alc_get_line_out_pfx(spec, true);
19068 hda_nid_t nid, mix, pin;
19069 int i, err, noutputs;
19071 noutputs = cfg->line_outs;
19072 if (spec->multi_ios > 0)
19073 noutputs += spec->multi_ios;
19075 for (i = 0; i < noutputs; i++) {
19076 nid = spec->multiout.dac_nids[i];
19077 if (!nid)
19078 continue;
19079 if (i >= cfg->line_outs)
19080 pin = spec->multi_io[i - 1].pin;
19081 else
19082 pin = cfg->line_out_pins[i];
19083 mix = alc_auto_dac_to_mix(codec, pin, nid);
19084 if (!mix)
19085 continue;
19086 if (!pfx && i == 2) {
19087 /* Center/LFE */
19088 err = alc662_add_vol_ctl(spec, "Center", nid, 1);
19089 if (err < 0)
19090 return err;
19091 err = alc662_add_vol_ctl(spec, "LFE", nid, 2);
19092 if (err < 0)
19093 return err;
19094 err = alc662_add_sw_ctl(spec, "Center", mix, 1);
19095 if (err < 0)
19096 return err;
19097 err = alc662_add_sw_ctl(spec, "LFE", mix, 2);
19098 if (err < 0)
19099 return err;
19100 } else {
19101 const char *name = pfx;
19102 int index = i;
19103 if (!name) {
19104 name = chname[i];
19105 index = 0;
19107 err = __alc662_add_vol_ctl(spec, name, nid, index, 3);
19108 if (err < 0)
19109 return err;
19110 err = __alc662_add_sw_ctl(spec, name, mix, index, 3);
19111 if (err < 0)
19112 return err;
19115 return 0;
19118 /* add playback controls for speaker and HP outputs */
19119 /* return DAC nid if any new DAC is assigned */
19120 static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
19121 const char *pfx)
19123 struct alc_spec *spec = codec->spec;
19124 hda_nid_t nid, mix;
19125 int err;
19127 if (!pin)
19128 return 0;
19129 nid = alc_auto_look_for_dac(codec, pin);
19130 if (!nid) {
19131 /* the corresponding DAC is already occupied */
19132 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
19133 return 0; /* no way */
19134 /* create a switch only */
19135 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
19136 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
19139 mix = alc_auto_dac_to_mix(codec, pin, nid);
19140 if (!mix)
19141 return 0;
19142 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
19143 if (err < 0)
19144 return err;
19145 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
19146 if (err < 0)
19147 return err;
19148 return nid;
19151 /* create playback/capture controls for input pins */
19152 #define alc662_auto_create_input_ctls \
19153 alc882_auto_create_input_ctls
19155 static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
19156 hda_nid_t nid, int pin_type,
19157 hda_nid_t dac)
19159 int i, num;
19160 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
19162 alc_set_pin_output(codec, nid, pin_type);
19163 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
19164 for (i = 0; i < num; i++) {
19165 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
19166 continue;
19167 /* need the manual connection? */
19168 if (num > 1)
19169 snd_hda_codec_write(codec, nid, 0,
19170 AC_VERB_SET_CONNECT_SEL, i);
19171 /* unmute mixer widget inputs */
19172 snd_hda_codec_write(codec, srcs[i], 0,
19173 AC_VERB_SET_AMP_GAIN_MUTE,
19174 AMP_IN_UNMUTE(0));
19175 snd_hda_codec_write(codec, srcs[i], 0,
19176 AC_VERB_SET_AMP_GAIN_MUTE,
19177 AMP_IN_UNMUTE(1));
19178 return;
19182 static void alc662_auto_init_multi_out(struct hda_codec *codec)
19184 struct alc_spec *spec = codec->spec;
19185 int pin_type = get_pin_type(spec->autocfg.line_out_type);
19186 int i;
19188 for (i = 0; i <= HDA_SIDE; i++) {
19189 hda_nid_t nid = spec->autocfg.line_out_pins[i];
19190 if (nid)
19191 alc662_auto_set_output_and_unmute(codec, nid, pin_type,
19192 spec->multiout.dac_nids[i]);
19196 static void alc662_auto_init_hp_out(struct hda_codec *codec)
19198 struct alc_spec *spec = codec->spec;
19199 hda_nid_t pin;
19201 pin = spec->autocfg.hp_pins[0];
19202 if (pin)
19203 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP,
19204 spec->multiout.hp_nid);
19205 pin = spec->autocfg.speaker_pins[0];
19206 if (pin)
19207 alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT,
19208 spec->multiout.extra_out_nid[0]);
19211 #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
19213 static void alc662_auto_init_analog_input(struct hda_codec *codec)
19215 struct alc_spec *spec = codec->spec;
19216 struct auto_pin_cfg *cfg = &spec->autocfg;
19217 int i;
19219 for (i = 0; i < cfg->num_inputs; i++) {
19220 hda_nid_t nid = cfg->inputs[i].pin;
19221 if (alc_is_input_pin(codec, nid)) {
19222 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
19223 if (nid != ALC662_PIN_CD_NID &&
19224 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
19225 snd_hda_codec_write(codec, nid, 0,
19226 AC_VERB_SET_AMP_GAIN_MUTE,
19227 AMP_OUT_MUTE);
19232 #define alc662_auto_init_input_src alc882_auto_init_input_src
19235 * multi-io helper
19237 static int alc_auto_fill_multi_ios(struct hda_codec *codec,
19238 unsigned int location)
19240 struct alc_spec *spec = codec->spec;
19241 struct auto_pin_cfg *cfg = &spec->autocfg;
19242 int type, i, num_pins = 0;
19244 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
19245 for (i = 0; i < cfg->num_inputs; i++) {
19246 hda_nid_t nid = cfg->inputs[i].pin;
19247 hda_nid_t dac;
19248 unsigned int defcfg, caps;
19249 if (cfg->inputs[i].type != type)
19250 continue;
19251 defcfg = snd_hda_codec_get_pincfg(codec, nid);
19252 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
19253 continue;
19254 if (location && get_defcfg_location(defcfg) != location)
19255 continue;
19256 caps = snd_hda_query_pin_caps(codec, nid);
19257 if (!(caps & AC_PINCAP_OUT))
19258 continue;
19259 dac = alc_auto_look_for_dac(codec, nid);
19260 if (!dac)
19261 continue;
19262 spec->multi_io[num_pins].pin = nid;
19263 spec->multi_io[num_pins].dac = dac;
19264 num_pins++;
19265 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
19268 spec->multiout.num_dacs = 1;
19269 if (num_pins < 2)
19270 return 0;
19271 return num_pins;
19274 static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
19275 struct snd_ctl_elem_info *uinfo)
19277 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
19278 struct alc_spec *spec = codec->spec;
19280 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
19281 uinfo->count = 1;
19282 uinfo->value.enumerated.items = spec->multi_ios + 1;
19283 if (uinfo->value.enumerated.item > spec->multi_ios)
19284 uinfo->value.enumerated.item = spec->multi_ios;
19285 sprintf(uinfo->value.enumerated.name, "%dch",
19286 (uinfo->value.enumerated.item + 1) * 2);
19287 return 0;
19290 static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
19291 struct snd_ctl_elem_value *ucontrol)
19293 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
19294 struct alc_spec *spec = codec->spec;
19295 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
19296 return 0;
19299 static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
19301 struct alc_spec *spec = codec->spec;
19302 hda_nid_t nid = spec->multi_io[idx].pin;
19304 if (!spec->multi_io[idx].ctl_in)
19305 spec->multi_io[idx].ctl_in =
19306 snd_hda_codec_read(codec, nid, 0,
19307 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
19308 if (output) {
19309 snd_hda_codec_update_cache(codec, nid, 0,
19310 AC_VERB_SET_PIN_WIDGET_CONTROL,
19311 PIN_OUT);
19312 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
19313 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
19314 HDA_AMP_MUTE, 0);
19315 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
19316 } else {
19317 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
19318 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
19319 HDA_AMP_MUTE, HDA_AMP_MUTE);
19320 snd_hda_codec_update_cache(codec, nid, 0,
19321 AC_VERB_SET_PIN_WIDGET_CONTROL,
19322 spec->multi_io[idx].ctl_in);
19324 return 0;
19327 static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
19328 struct snd_ctl_elem_value *ucontrol)
19330 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
19331 struct alc_spec *spec = codec->spec;
19332 int i, ch;
19334 ch = ucontrol->value.enumerated.item[0];
19335 if (ch < 0 || ch > spec->multi_ios)
19336 return -EINVAL;
19337 if (ch == (spec->ext_channel_count - 1) / 2)
19338 return 0;
19339 spec->ext_channel_count = (ch + 1) * 2;
19340 for (i = 0; i < spec->multi_ios; i++)
19341 alc_set_multi_io(codec, i, i < ch);
19342 spec->multiout.max_channels = spec->ext_channel_count;
19343 return 1;
19346 static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
19347 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
19348 .name = "Channel Mode",
19349 .info = alc_auto_ch_mode_info,
19350 .get = alc_auto_ch_mode_get,
19351 .put = alc_auto_ch_mode_put,
19354 static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
19356 struct alc_spec *spec = codec->spec;
19357 struct auto_pin_cfg *cfg = &spec->autocfg;
19358 unsigned int location, defcfg;
19359 int num_pins;
19361 if (cfg->line_outs != 1 ||
19362 cfg->line_out_type != AUTO_PIN_LINE_OUT)
19363 return 0;
19365 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
19366 location = get_defcfg_location(defcfg);
19368 num_pins = alc_auto_fill_multi_ios(codec, location);
19369 if (num_pins > 0) {
19370 struct snd_kcontrol_new *knew;
19372 knew = alc_kcontrol_new(spec);
19373 if (!knew)
19374 return -ENOMEM;
19375 *knew = alc_auto_channel_mode_enum;
19376 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
19377 if (!knew->name)
19378 return -ENOMEM;
19380 spec->multi_ios = num_pins;
19381 spec->ext_channel_count = 2;
19382 spec->multiout.num_dacs = num_pins + 1;
19384 return 0;
19387 static int alc662_parse_auto_config(struct hda_codec *codec)
19389 struct alc_spec *spec = codec->spec;
19390 int err;
19391 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
19393 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
19394 alc662_ignore);
19395 if (err < 0)
19396 return err;
19397 if (!spec->autocfg.line_outs)
19398 return 0; /* can't find valid BIOS pin config */
19400 err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
19401 if (err < 0)
19402 return err;
19403 err = alc_auto_add_multi_channel_mode(codec);
19404 if (err < 0)
19405 return err;
19406 err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
19407 if (err < 0)
19408 return err;
19409 err = alc662_auto_create_extra_out(codec,
19410 spec->autocfg.speaker_pins[0],
19411 "Speaker");
19412 if (err < 0)
19413 return err;
19414 if (err)
19415 spec->multiout.extra_out_nid[0] = err;
19416 err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
19417 "Headphone");
19418 if (err < 0)
19419 return err;
19420 if (err)
19421 spec->multiout.hp_nid = err;
19422 err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
19423 if (err < 0)
19424 return err;
19426 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
19428 alc_auto_parse_digital(codec);
19430 if (spec->kctls.list)
19431 add_mixer(spec, spec->kctls.list);
19433 spec->num_mux_defs = 1;
19434 spec->input_mux = &spec->private_imux[0];
19436 err = alc_auto_add_mic_boost(codec);
19437 if (err < 0)
19438 return err;
19440 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
19441 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
19442 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21);
19443 else
19444 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
19446 return 1;
19449 /* additional initialization for auto-configuration model */
19450 static void alc662_auto_init(struct hda_codec *codec)
19452 struct alc_spec *spec = codec->spec;
19453 alc662_auto_init_multi_out(codec);
19454 alc662_auto_init_hp_out(codec);
19455 alc662_auto_init_analog_input(codec);
19456 alc662_auto_init_input_src(codec);
19457 alc_auto_init_digital(codec);
19458 if (spec->unsol_event)
19459 alc_inithook(codec);
19462 static void alc272_fixup_mario(struct hda_codec *codec,
19463 const struct alc_fixup *fix, int action)
19465 if (action != ALC_FIXUP_ACT_PROBE)
19466 return;
19467 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
19468 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
19469 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
19470 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
19471 (0 << AC_AMPCAP_MUTE_SHIFT)))
19472 printk(KERN_WARNING
19473 "hda_codec: failed to override amp caps for NID 0x2\n");
19476 enum {
19477 ALC662_FIXUP_ASPIRE,
19478 ALC662_FIXUP_IDEAPAD,
19479 ALC272_FIXUP_MARIO,
19480 ALC662_FIXUP_CZC_P10T,
19481 ALC662_FIXUP_SKU_IGNORE,
19484 static const struct alc_fixup alc662_fixups[] = {
19485 [ALC662_FIXUP_ASPIRE] = {
19486 .type = ALC_FIXUP_PINS,
19487 .v.pins = (const struct alc_pincfg[]) {
19488 { 0x15, 0x99130112 }, /* subwoofer */
19492 [ALC662_FIXUP_IDEAPAD] = {
19493 .type = ALC_FIXUP_PINS,
19494 .v.pins = (const struct alc_pincfg[]) {
19495 { 0x17, 0x99130112 }, /* subwoofer */
19499 [ALC272_FIXUP_MARIO] = {
19500 .type = ALC_FIXUP_FUNC,
19501 .v.func = alc272_fixup_mario,
19503 [ALC662_FIXUP_CZC_P10T] = {
19504 .type = ALC_FIXUP_VERBS,
19505 .v.verbs = (const struct hda_verb[]) {
19506 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
19510 [ALC662_FIXUP_SKU_IGNORE] = {
19511 .type = ALC_FIXUP_SKU,
19512 .v.sku = ALC_FIXUP_SKU_IGNORE,
19516 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
19517 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
19518 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
19519 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
19520 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
19521 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
19522 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
19523 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
19527 static const struct alc_model_fixup alc662_fixup_models[] = {
19528 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
19533 static int patch_alc662(struct hda_codec *codec)
19535 struct alc_spec *spec;
19536 int err, board_config;
19537 int coef;
19539 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
19540 if (!spec)
19541 return -ENOMEM;
19543 codec->spec = spec;
19545 alc_auto_parse_customize_define(codec);
19547 alc_fix_pll_init(codec, 0x20, 0x04, 15);
19549 coef = alc_read_coef_idx(codec, 0);
19550 if (coef == 0x8020 || coef == 0x8011)
19551 alc_codec_rename(codec, "ALC661");
19552 else if (coef & (1 << 14) &&
19553 codec->bus->pci->subsystem_vendor == 0x1025 &&
19554 spec->cdefine.platform_type == 1)
19555 alc_codec_rename(codec, "ALC272X");
19556 else if (coef == 0x4011)
19557 alc_codec_rename(codec, "ALC656");
19559 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
19560 alc662_models,
19561 alc662_cfg_tbl);
19562 if (board_config < 0) {
19563 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
19564 codec->chip_name);
19565 board_config = ALC662_AUTO;
19568 if (board_config == ALC662_AUTO) {
19569 alc_pick_fixup(codec, alc662_fixup_models,
19570 alc662_fixup_tbl, alc662_fixups);
19571 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
19572 /* automatic parse from the BIOS config */
19573 err = alc662_parse_auto_config(codec);
19574 if (err < 0) {
19575 alc_free(codec);
19576 return err;
19577 } else if (!err) {
19578 printk(KERN_INFO
19579 "hda_codec: Cannot set up configuration "
19580 "from BIOS. Using base mode...\n");
19581 board_config = ALC662_3ST_2ch_DIG;
19585 if (has_cdefine_beep(codec)) {
19586 err = snd_hda_attach_beep_device(codec, 0x1);
19587 if (err < 0) {
19588 alc_free(codec);
19589 return err;
19593 if (board_config != ALC662_AUTO)
19594 setup_preset(codec, &alc662_presets[board_config]);
19596 spec->stream_analog_playback = &alc662_pcm_analog_playback;
19597 spec->stream_analog_capture = &alc662_pcm_analog_capture;
19599 spec->stream_digital_playback = &alc662_pcm_digital_playback;
19600 spec->stream_digital_capture = &alc662_pcm_digital_capture;
19602 if (!spec->adc_nids) {
19603 spec->adc_nids = alc662_adc_nids;
19604 spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
19606 if (!spec->capsrc_nids)
19607 spec->capsrc_nids = alc662_capsrc_nids;
19609 if (!spec->cap_mixer)
19610 set_capture_mixer(codec);
19612 if (has_cdefine_beep(codec)) {
19613 switch (codec->vendor_id) {
19614 case 0x10ec0662:
19615 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
19616 break;
19617 case 0x10ec0272:
19618 case 0x10ec0663:
19619 case 0x10ec0665:
19620 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
19621 break;
19622 case 0x10ec0273:
19623 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
19624 break;
19627 spec->vmaster_nid = 0x02;
19629 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
19631 codec->patch_ops = alc_patch_ops;
19632 if (board_config == ALC662_AUTO)
19633 spec->init_hook = alc662_auto_init;
19634 spec->shutup = alc_eapd_shutup;
19636 alc_init_jacks(codec);
19638 #ifdef CONFIG_SND_HDA_POWER_SAVE
19639 if (!spec->loopback.amplist)
19640 spec->loopback.amplist = alc662_loopbacks;
19641 #endif
19643 return 0;
19646 static int patch_alc888(struct hda_codec *codec)
19648 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
19649 kfree(codec->chip_name);
19650 if (codec->vendor_id == 0x10ec0887)
19651 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
19652 else
19653 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
19654 if (!codec->chip_name) {
19655 alc_free(codec);
19656 return -ENOMEM;
19658 return patch_alc662(codec);
19660 return patch_alc882(codec);
19663 static int patch_alc899(struct hda_codec *codec)
19665 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
19666 kfree(codec->chip_name);
19667 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
19669 return patch_alc882(codec);
19673 * ALC680 support
19675 #define ALC680_DIGIN_NID ALC880_DIGIN_NID
19676 #define ALC680_DIGOUT_NID ALC880_DIGOUT_NID
19677 #define alc680_modes alc260_modes
19679 static const hda_nid_t alc680_dac_nids[3] = {
19680 /* Lout1, Lout2, hp */
19681 0x02, 0x03, 0x04
19684 static const hda_nid_t alc680_adc_nids[3] = {
19685 /* ADC0-2 */
19686 /* DMIC, MIC, Line-in*/
19687 0x07, 0x08, 0x09
19691 * Analog capture ADC cgange
19693 static void alc680_rec_autoswitch(struct hda_codec *codec)
19695 struct alc_spec *spec = codec->spec;
19696 struct auto_pin_cfg *cfg = &spec->autocfg;
19697 int pin_found = 0;
19698 int type_found = AUTO_PIN_LAST;
19699 hda_nid_t nid;
19700 int i;
19702 for (i = 0; i < cfg->num_inputs; i++) {
19703 nid = cfg->inputs[i].pin;
19704 if (!is_jack_detectable(codec, nid))
19705 continue;
19706 if (snd_hda_jack_detect(codec, nid)) {
19707 if (cfg->inputs[i].type < type_found) {
19708 type_found = cfg->inputs[i].type;
19709 pin_found = nid;
19714 nid = 0x07;
19715 if (pin_found)
19716 snd_hda_get_connections(codec, pin_found, &nid, 1);
19718 if (nid != spec->cur_adc)
19719 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
19720 spec->cur_adc = nid;
19721 snd_hda_codec_setup_stream(codec, nid, spec->cur_adc_stream_tag, 0,
19722 spec->cur_adc_format);
19725 static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
19726 struct hda_codec *codec,
19727 unsigned int stream_tag,
19728 unsigned int format,
19729 struct snd_pcm_substream *substream)
19731 struct alc_spec *spec = codec->spec;
19733 spec->cur_adc = 0x07;
19734 spec->cur_adc_stream_tag = stream_tag;
19735 spec->cur_adc_format = format;
19737 alc680_rec_autoswitch(codec);
19738 return 0;
19741 static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
19742 struct hda_codec *codec,
19743 struct snd_pcm_substream *substream)
19745 snd_hda_codec_cleanup_stream(codec, 0x07);
19746 snd_hda_codec_cleanup_stream(codec, 0x08);
19747 snd_hda_codec_cleanup_stream(codec, 0x09);
19748 return 0;
19751 static const struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
19752 .substreams = 1, /* can be overridden */
19753 .channels_min = 2,
19754 .channels_max = 2,
19755 /* NID is set in alc_build_pcms */
19756 .ops = {
19757 .prepare = alc680_capture_pcm_prepare,
19758 .cleanup = alc680_capture_pcm_cleanup
19762 static const struct snd_kcontrol_new alc680_base_mixer[] = {
19763 /* output mixer control */
19764 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
19765 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
19766 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT),
19767 HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT),
19768 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x12, 0, HDA_INPUT),
19769 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
19770 HDA_CODEC_VOLUME("Line In Boost Volume", 0x19, 0, HDA_INPUT),
19774 static const struct hda_bind_ctls alc680_bind_cap_vol = {
19775 .ops = &snd_hda_bind_vol,
19776 .values = {
19777 HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
19778 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
19779 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
19784 static const struct hda_bind_ctls alc680_bind_cap_switch = {
19785 .ops = &snd_hda_bind_sw,
19786 .values = {
19787 HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
19788 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
19789 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
19794 static const struct snd_kcontrol_new alc680_master_capture_mixer[] = {
19795 HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol),
19796 HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch),
19797 { } /* end */
19801 * generic initialization of ADC, input mixers and output mixers
19803 static const struct hda_verb alc680_init_verbs[] = {
19804 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
19805 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
19806 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
19808 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
19809 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
19810 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
19811 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
19812 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
19813 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
19815 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19816 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19817 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19818 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19819 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19821 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
19822 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
19823 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
19828 /* toggle speaker-output according to the hp-jack state */
19829 static void alc680_base_setup(struct hda_codec *codec)
19831 struct alc_spec *spec = codec->spec;
19833 spec->autocfg.hp_pins[0] = 0x16;
19834 spec->autocfg.speaker_pins[0] = 0x14;
19835 spec->autocfg.speaker_pins[1] = 0x15;
19836 spec->autocfg.num_inputs = 2;
19837 spec->autocfg.inputs[0].pin = 0x18;
19838 spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
19839 spec->autocfg.inputs[1].pin = 0x19;
19840 spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
19841 spec->automute = 1;
19842 spec->automute_mode = ALC_AUTOMUTE_AMP;
19845 static void alc680_unsol_event(struct hda_codec *codec,
19846 unsigned int res)
19848 if ((res >> 26) == ALC880_HP_EVENT)
19849 alc_hp_automute(codec);
19850 if ((res >> 26) == ALC880_MIC_EVENT)
19851 alc680_rec_autoswitch(codec);
19854 static void alc680_inithook(struct hda_codec *codec)
19856 alc_hp_automute(codec);
19857 alc680_rec_autoswitch(codec);
19860 /* create input playback/capture controls for the given pin */
19861 static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
19862 const char *ctlname, int idx)
19864 hda_nid_t dac;
19865 int err;
19867 switch (nid) {
19868 case 0x14:
19869 dac = 0x02;
19870 break;
19871 case 0x15:
19872 dac = 0x03;
19873 break;
19874 case 0x16:
19875 dac = 0x04;
19876 break;
19877 default:
19878 return 0;
19880 if (spec->multiout.dac_nids[0] != dac &&
19881 spec->multiout.dac_nids[1] != dac) {
19882 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
19883 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
19884 HDA_OUTPUT));
19885 if (err < 0)
19886 return err;
19888 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
19889 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
19891 if (err < 0)
19892 return err;
19893 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
19896 return 0;
19899 /* add playback controls from the parsed DAC table */
19900 static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec,
19901 const struct auto_pin_cfg *cfg)
19903 hda_nid_t nid;
19904 int err;
19906 spec->multiout.dac_nids = spec->private_dac_nids;
19908 nid = cfg->line_out_pins[0];
19909 if (nid) {
19910 const char *name;
19911 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
19912 name = "Speaker";
19913 else
19914 name = "Front";
19915 err = alc680_new_analog_output(spec, nid, name, 0);
19916 if (err < 0)
19917 return err;
19920 nid = cfg->speaker_pins[0];
19921 if (nid) {
19922 err = alc680_new_analog_output(spec, nid, "Speaker", 0);
19923 if (err < 0)
19924 return err;
19926 nid = cfg->hp_pins[0];
19927 if (nid) {
19928 err = alc680_new_analog_output(spec, nid, "Headphone", 0);
19929 if (err < 0)
19930 return err;
19933 return 0;
19936 static void alc680_auto_set_output_and_unmute(struct hda_codec *codec,
19937 hda_nid_t nid, int pin_type)
19939 alc_set_pin_output(codec, nid, pin_type);
19942 static void alc680_auto_init_multi_out(struct hda_codec *codec)
19944 struct alc_spec *spec = codec->spec;
19945 hda_nid_t nid = spec->autocfg.line_out_pins[0];
19946 if (nid) {
19947 int pin_type = get_pin_type(spec->autocfg.line_out_type);
19948 alc680_auto_set_output_and_unmute(codec, nid, pin_type);
19952 static void alc680_auto_init_hp_out(struct hda_codec *codec)
19954 struct alc_spec *spec = codec->spec;
19955 hda_nid_t pin;
19957 pin = spec->autocfg.hp_pins[0];
19958 if (pin)
19959 alc680_auto_set_output_and_unmute(codec, pin, PIN_HP);
19960 pin = spec->autocfg.speaker_pins[0];
19961 if (pin)
19962 alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT);
19965 /* pcm configuration: identical with ALC880 */
19966 #define alc680_pcm_analog_playback alc880_pcm_analog_playback
19967 #define alc680_pcm_analog_capture alc880_pcm_analog_capture
19968 #define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
19969 #define alc680_pcm_digital_playback alc880_pcm_digital_playback
19970 #define alc680_pcm_digital_capture alc880_pcm_digital_capture
19973 * BIOS auto configuration
19975 static int alc680_parse_auto_config(struct hda_codec *codec)
19977 struct alc_spec *spec = codec->spec;
19978 int err;
19979 static const hda_nid_t alc680_ignore[] = { 0 };
19981 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
19982 alc680_ignore);
19983 if (err < 0)
19984 return err;
19986 if (!spec->autocfg.line_outs) {
19987 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
19988 spec->multiout.max_channels = 2;
19989 spec->no_analog = 1;
19990 goto dig_only;
19992 return 0; /* can't find valid BIOS pin config */
19994 err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg);
19995 if (err < 0)
19996 return err;
19998 spec->multiout.max_channels = 2;
20000 dig_only:
20001 /* digital only support output */
20002 alc_auto_parse_digital(codec);
20003 if (spec->kctls.list)
20004 add_mixer(spec, spec->kctls.list);
20006 add_verb(spec, alc680_init_verbs);
20008 err = alc_auto_add_mic_boost(codec);
20009 if (err < 0)
20010 return err;
20012 return 1;
20015 #define alc680_auto_init_analog_input alc882_auto_init_analog_input
20017 /* init callback for auto-configuration model -- overriding the default init */
20018 static void alc680_auto_init(struct hda_codec *codec)
20020 struct alc_spec *spec = codec->spec;
20021 alc680_auto_init_multi_out(codec);
20022 alc680_auto_init_hp_out(codec);
20023 alc680_auto_init_analog_input(codec);
20024 alc_auto_init_digital(codec);
20025 if (spec->unsol_event)
20026 alc_inithook(codec);
20030 * configuration and preset
20032 static const char * const alc680_models[ALC680_MODEL_LAST] = {
20033 [ALC680_BASE] = "base",
20034 [ALC680_AUTO] = "auto",
20037 static const struct snd_pci_quirk alc680_cfg_tbl[] = {
20038 SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
20042 static const struct alc_config_preset alc680_presets[] = {
20043 [ALC680_BASE] = {
20044 .mixers = { alc680_base_mixer },
20045 .cap_mixer = alc680_master_capture_mixer,
20046 .init_verbs = { alc680_init_verbs },
20047 .num_dacs = ARRAY_SIZE(alc680_dac_nids),
20048 .dac_nids = alc680_dac_nids,
20049 .dig_out_nid = ALC680_DIGOUT_NID,
20050 .num_channel_mode = ARRAY_SIZE(alc680_modes),
20051 .channel_mode = alc680_modes,
20052 .unsol_event = alc680_unsol_event,
20053 .setup = alc680_base_setup,
20054 .init_hook = alc680_inithook,
20059 static int patch_alc680(struct hda_codec *codec)
20061 struct alc_spec *spec;
20062 int board_config;
20063 int err;
20065 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
20066 if (spec == NULL)
20067 return -ENOMEM;
20069 codec->spec = spec;
20071 board_config = snd_hda_check_board_config(codec, ALC680_MODEL_LAST,
20072 alc680_models,
20073 alc680_cfg_tbl);
20075 if (board_config < 0 || board_config >= ALC680_MODEL_LAST) {
20076 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
20077 codec->chip_name);
20078 board_config = ALC680_AUTO;
20081 if (board_config == ALC680_AUTO) {
20082 /* automatic parse from the BIOS config */
20083 err = alc680_parse_auto_config(codec);
20084 if (err < 0) {
20085 alc_free(codec);
20086 return err;
20087 } else if (!err) {
20088 printk(KERN_INFO
20089 "hda_codec: Cannot set up configuration "
20090 "from BIOS. Using base mode...\n");
20091 board_config = ALC680_BASE;
20095 if (board_config != ALC680_AUTO)
20096 setup_preset(codec, &alc680_presets[board_config]);
20098 spec->stream_analog_playback = &alc680_pcm_analog_playback;
20099 spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
20100 spec->stream_digital_playback = &alc680_pcm_digital_playback;
20101 spec->stream_digital_capture = &alc680_pcm_digital_capture;
20103 if (!spec->adc_nids) {
20104 spec->adc_nids = alc680_adc_nids;
20105 spec->num_adc_nids = ARRAY_SIZE(alc680_adc_nids);
20108 if (!spec->cap_mixer)
20109 set_capture_mixer(codec);
20111 spec->vmaster_nid = 0x02;
20113 codec->patch_ops = alc_patch_ops;
20114 if (board_config == ALC680_AUTO)
20115 spec->init_hook = alc680_auto_init;
20117 return 0;
20121 * patch entries
20123 static const struct hda_codec_preset snd_hda_preset_realtek[] = {
20124 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
20125 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
20126 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
20127 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
20128 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
20129 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
20130 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
20131 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
20132 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
20133 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
20134 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
20135 .patch = patch_alc861 },
20136 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
20137 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
20138 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
20139 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
20140 .patch = patch_alc882 },
20141 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
20142 .patch = patch_alc662 },
20143 { .id = 0x10ec0662, .rev = 0x100300, .name = "ALC662 rev3",
20144 .patch = patch_alc662 },
20145 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
20146 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
20147 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
20148 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
20149 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
20150 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
20151 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
20152 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
20153 .patch = patch_alc882 },
20154 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
20155 .patch = patch_alc882 },
20156 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
20157 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
20158 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
20159 .patch = patch_alc882 },
20160 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
20161 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
20162 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
20163 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
20164 {} /* terminator */
20167 MODULE_ALIAS("snd-hda-codec-id:10ec*");
20169 MODULE_LICENSE("GPL");
20170 MODULE_DESCRIPTION("Realtek HD-audio codec");
20172 static struct hda_codec_preset_list realtek_list = {
20173 .preset = snd_hda_preset_realtek,
20174 .owner = THIS_MODULE,
20177 static int __init patch_realtek_init(void)
20179 return snd_hda_add_codec_preset(&realtek_list);
20182 static void __exit patch_realtek_exit(void)
20184 snd_hda_delete_codec_preset(&realtek_list);
20187 module_init(patch_realtek_init)
20188 module_exit(patch_realtek_exit)