ALSA: hda - Add another HP model for AD1884A
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / sound / pci / hda / patch_realtek.c
blob8723d33d5a978aaa5c10e8c7b9d2b7b69c5659c8
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 "hda_codec.h"
32 #include "hda_local.h"
33 #include "hda_patch.h"
35 #define ALC880_FRONT_EVENT 0x01
36 #define ALC880_DCVOL_EVENT 0x02
37 #define ALC880_HP_EVENT 0x04
38 #define ALC880_MIC_EVENT 0x08
40 /* ALC880 board config type */
41 enum {
42 ALC880_3ST,
43 ALC880_3ST_DIG,
44 ALC880_5ST,
45 ALC880_5ST_DIG,
46 ALC880_W810,
47 ALC880_Z71V,
48 ALC880_6ST,
49 ALC880_6ST_DIG,
50 ALC880_F1734,
51 ALC880_ASUS,
52 ALC880_ASUS_DIG,
53 ALC880_ASUS_W1V,
54 ALC880_ASUS_DIG2,
55 ALC880_FUJITSU,
56 ALC880_UNIWILL_DIG,
57 ALC880_UNIWILL,
58 ALC880_UNIWILL_P53,
59 ALC880_CLEVO,
60 ALC880_TCL_S700,
61 ALC880_LG,
62 ALC880_LG_LW,
63 ALC880_MEDION_RIM,
64 #ifdef CONFIG_SND_DEBUG
65 ALC880_TEST,
66 #endif
67 ALC880_AUTO,
68 ALC880_MODEL_LAST /* last tag */
71 /* ALC260 models */
72 enum {
73 ALC260_BASIC,
74 ALC260_HP,
75 ALC260_HP_3013,
76 ALC260_FUJITSU_S702X,
77 ALC260_ACER,
78 ALC260_WILL,
79 ALC260_REPLACER_672V,
80 #ifdef CONFIG_SND_DEBUG
81 ALC260_TEST,
82 #endif
83 ALC260_AUTO,
84 ALC260_MODEL_LAST /* last tag */
87 /* ALC262 models */
88 enum {
89 ALC262_BASIC,
90 ALC262_HIPPO,
91 ALC262_HIPPO_1,
92 ALC262_FUJITSU,
93 ALC262_HP_BPC,
94 ALC262_HP_BPC_D7000_WL,
95 ALC262_HP_BPC_D7000_WF,
96 ALC262_HP_TC_T5735,
97 ALC262_HP_RP5700,
98 ALC262_BENQ_ED8,
99 ALC262_SONY_ASSAMD,
100 ALC262_BENQ_T31,
101 ALC262_ULTRA,
102 ALC262_LENOVO_3000,
103 ALC262_NEC,
104 ALC262_AUTO,
105 ALC262_MODEL_LAST /* last tag */
108 /* ALC268 models */
109 enum {
110 ALC267_QUANTA_IL1,
111 ALC268_3ST,
112 ALC268_TOSHIBA,
113 ALC268_ACER,
114 ALC268_DELL,
115 ALC268_ZEPTO,
116 #ifdef CONFIG_SND_DEBUG
117 ALC268_TEST,
118 #endif
119 ALC268_AUTO,
120 ALC268_MODEL_LAST /* last tag */
123 /* ALC269 models */
124 enum {
125 ALC269_BASIC,
126 ALC269_ASUS_EEEPC_P703,
127 ALC269_ASUS_EEEPC_P901,
128 ALC269_AUTO,
129 ALC269_MODEL_LAST /* last tag */
132 /* ALC861 models */
133 enum {
134 ALC861_3ST,
135 ALC660_3ST,
136 ALC861_3ST_DIG,
137 ALC861_6ST_DIG,
138 ALC861_UNIWILL_M31,
139 ALC861_TOSHIBA,
140 ALC861_ASUS,
141 ALC861_ASUS_LAPTOP,
142 ALC861_AUTO,
143 ALC861_MODEL_LAST,
146 /* ALC861-VD models */
147 enum {
148 ALC660VD_3ST,
149 ALC660VD_3ST_DIG,
150 ALC861VD_3ST,
151 ALC861VD_3ST_DIG,
152 ALC861VD_6ST_DIG,
153 ALC861VD_LENOVO,
154 ALC861VD_DALLAS,
155 ALC861VD_HP,
156 ALC861VD_AUTO,
157 ALC861VD_MODEL_LAST,
160 /* ALC662 models */
161 enum {
162 ALC662_3ST_2ch_DIG,
163 ALC662_3ST_6ch_DIG,
164 ALC662_3ST_6ch,
165 ALC662_5ST_DIG,
166 ALC662_LENOVO_101E,
167 ALC662_ASUS_EEEPC_P701,
168 ALC662_ASUS_EEEPC_EP20,
169 ALC663_ASUS_M51VA,
170 ALC663_ASUS_G71V,
171 ALC663_ASUS_H13,
172 ALC663_ASUS_G50V,
173 ALC662_AUTO,
174 ALC662_MODEL_LAST,
177 /* ALC882 models */
178 enum {
179 ALC882_3ST_DIG,
180 ALC882_6ST_DIG,
181 ALC882_ARIMA,
182 ALC882_W2JC,
183 ALC882_TARGA,
184 ALC882_ASUS_A7J,
185 ALC882_ASUS_A7M,
186 ALC885_MACPRO,
187 ALC885_MBP3,
188 ALC885_IMAC24,
189 ALC882_AUTO,
190 ALC882_MODEL_LAST,
193 /* ALC883 models */
194 enum {
195 ALC883_3ST_2ch_DIG,
196 ALC883_3ST_6ch_DIG,
197 ALC883_3ST_6ch,
198 ALC883_6ST_DIG,
199 ALC883_TARGA_DIG,
200 ALC883_TARGA_2ch_DIG,
201 ALC883_ACER,
202 ALC883_ACER_ASPIRE,
203 ALC883_MEDION,
204 ALC883_MEDION_MD2,
205 ALC883_LAPTOP_EAPD,
206 ALC883_LENOVO_101E_2ch,
207 ALC883_LENOVO_NB0763,
208 ALC888_LENOVO_MS7195_DIG,
209 ALC883_HAIER_W66,
210 ALC888_3ST_HP,
211 ALC888_6ST_DELL,
212 ALC883_MITAC,
213 ALC883_CLEVO_M720,
214 ALC883_FUJITSU_PI2515,
215 ALC883_3ST_6ch_INTEL,
216 ALC883_AUTO,
217 ALC883_MODEL_LAST,
220 /* for GPIO Poll */
221 #define GPIO_MASK 0x03
223 struct alc_spec {
224 /* codec parameterization */
225 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
226 unsigned int num_mixers;
228 const struct hda_verb *init_verbs[5]; /* initialization verbs
229 * don't forget NULL
230 * termination!
232 unsigned int num_init_verbs;
234 char *stream_name_analog; /* analog PCM stream */
235 struct hda_pcm_stream *stream_analog_playback;
236 struct hda_pcm_stream *stream_analog_capture;
237 struct hda_pcm_stream *stream_analog_alt_playback;
238 struct hda_pcm_stream *stream_analog_alt_capture;
240 char *stream_name_digital; /* digital PCM stream */
241 struct hda_pcm_stream *stream_digital_playback;
242 struct hda_pcm_stream *stream_digital_capture;
244 /* playback */
245 struct hda_multi_out multiout; /* playback set-up
246 * max_channels, dacs must be set
247 * dig_out_nid and hp_nid are optional
249 hda_nid_t alt_dac_nid;
251 /* capture */
252 unsigned int num_adc_nids;
253 hda_nid_t *adc_nids;
254 hda_nid_t *capsrc_nids;
255 hda_nid_t dig_in_nid; /* digital-in NID; optional */
257 /* capture source */
258 unsigned int num_mux_defs;
259 const struct hda_input_mux *input_mux;
260 unsigned int cur_mux[3];
262 /* channel model */
263 const struct hda_channel_mode *channel_mode;
264 int num_channel_mode;
265 int need_dac_fix;
267 /* PCM information */
268 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
270 /* dynamic controls, init_verbs and input_mux */
271 struct auto_pin_cfg autocfg;
272 unsigned int num_kctl_alloc, num_kctl_used;
273 struct snd_kcontrol_new *kctl_alloc;
274 struct hda_input_mux private_imux;
275 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
277 /* hooks */
278 void (*init_hook)(struct hda_codec *codec);
279 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
281 /* for pin sensing */
282 unsigned int sense_updated: 1;
283 unsigned int jack_present: 1;
284 unsigned int master_sw: 1;
286 /* for virtual master */
287 hda_nid_t vmaster_nid;
288 #ifdef CONFIG_SND_HDA_POWER_SAVE
289 struct hda_loopback_check loopback;
290 #endif
292 /* for PLL fix */
293 hda_nid_t pll_nid;
294 unsigned int pll_coef_idx, pll_coef_bit;
296 #ifdef SND_HDA_NEEDS_RESUME
297 #define ALC_MAX_PINS 16
298 unsigned int num_pins;
299 hda_nid_t pin_nids[ALC_MAX_PINS];
300 unsigned int pin_cfgs[ALC_MAX_PINS];
301 #endif
305 * configuration template - to be copied to the spec instance
307 struct alc_config_preset {
308 struct snd_kcontrol_new *mixers[5]; /* should be identical size
309 * with spec
311 const struct hda_verb *init_verbs[5];
312 unsigned int num_dacs;
313 hda_nid_t *dac_nids;
314 hda_nid_t dig_out_nid; /* optional */
315 hda_nid_t hp_nid; /* optional */
316 unsigned int num_adc_nids;
317 hda_nid_t *adc_nids;
318 hda_nid_t *capsrc_nids;
319 hda_nid_t dig_in_nid;
320 unsigned int num_channel_mode;
321 const struct hda_channel_mode *channel_mode;
322 int need_dac_fix;
323 unsigned int num_mux_defs;
324 const struct hda_input_mux *input_mux;
325 void (*unsol_event)(struct hda_codec *, unsigned int);
326 void (*init_hook)(struct hda_codec *);
327 #ifdef CONFIG_SND_HDA_POWER_SAVE
328 struct hda_amp_list *loopbacks;
329 #endif
334 * input MUX handling
336 static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
337 struct snd_ctl_elem_info *uinfo)
339 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
340 struct alc_spec *spec = codec->spec;
341 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
342 if (mux_idx >= spec->num_mux_defs)
343 mux_idx = 0;
344 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
347 static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
348 struct snd_ctl_elem_value *ucontrol)
350 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
351 struct alc_spec *spec = codec->spec;
352 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
354 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
355 return 0;
358 static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
359 struct snd_ctl_elem_value *ucontrol)
361 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
362 struct alc_spec *spec = codec->spec;
363 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
364 unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
365 hda_nid_t nid = spec->capsrc_nids ?
366 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
367 return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
368 nid, &spec->cur_mux[adc_idx]);
373 * channel mode setting
375 static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
376 struct snd_ctl_elem_info *uinfo)
378 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
379 struct alc_spec *spec = codec->spec;
380 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
381 spec->num_channel_mode);
384 static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
385 struct snd_ctl_elem_value *ucontrol)
387 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
388 struct alc_spec *spec = codec->spec;
389 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
390 spec->num_channel_mode,
391 spec->multiout.max_channels);
394 static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
395 struct snd_ctl_elem_value *ucontrol)
397 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
398 struct alc_spec *spec = codec->spec;
399 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
400 spec->num_channel_mode,
401 &spec->multiout.max_channels);
402 if (err >= 0 && spec->need_dac_fix)
403 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
404 return err;
408 * Control the mode of pin widget settings via the mixer. "pc" is used
409 * instead of "%" to avoid consequences of accidently treating the % as
410 * being part of a format specifier. Maximum allowed length of a value is
411 * 63 characters plus NULL terminator.
413 * Note: some retasking pin complexes seem to ignore requests for input
414 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
415 * are requested. Therefore order this list so that this behaviour will not
416 * cause problems when mixer clients move through the enum sequentially.
417 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
418 * March 2006.
420 static char *alc_pin_mode_names[] = {
421 "Mic 50pc bias", "Mic 80pc bias",
422 "Line in", "Line out", "Headphone out",
424 static unsigned char alc_pin_mode_values[] = {
425 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
427 /* The control can present all 5 options, or it can limit the options based
428 * in the pin being assumed to be exclusively an input or an output pin. In
429 * addition, "input" pins may or may not process the mic bias option
430 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
431 * accept requests for bias as of chip versions up to March 2006) and/or
432 * wiring in the computer.
434 #define ALC_PIN_DIR_IN 0x00
435 #define ALC_PIN_DIR_OUT 0x01
436 #define ALC_PIN_DIR_INOUT 0x02
437 #define ALC_PIN_DIR_IN_NOMICBIAS 0x03
438 #define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
440 /* Info about the pin modes supported by the different pin direction modes.
441 * For each direction the minimum and maximum values are given.
443 static signed char alc_pin_mode_dir_info[5][2] = {
444 { 0, 2 }, /* ALC_PIN_DIR_IN */
445 { 3, 4 }, /* ALC_PIN_DIR_OUT */
446 { 0, 4 }, /* ALC_PIN_DIR_INOUT */
447 { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */
448 { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */
450 #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
451 #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
452 #define alc_pin_mode_n_items(_dir) \
453 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
455 static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
456 struct snd_ctl_elem_info *uinfo)
458 unsigned int item_num = uinfo->value.enumerated.item;
459 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
461 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
462 uinfo->count = 1;
463 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
465 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
466 item_num = alc_pin_mode_min(dir);
467 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
468 return 0;
471 static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
472 struct snd_ctl_elem_value *ucontrol)
474 unsigned int i;
475 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
476 hda_nid_t nid = kcontrol->private_value & 0xffff;
477 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
478 long *valp = ucontrol->value.integer.value;
479 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
480 AC_VERB_GET_PIN_WIDGET_CONTROL,
481 0x00);
483 /* Find enumerated value for current pinctl setting */
484 i = alc_pin_mode_min(dir);
485 while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir))
486 i++;
487 *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
488 return 0;
491 static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
492 struct snd_ctl_elem_value *ucontrol)
494 signed int change;
495 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
496 hda_nid_t nid = kcontrol->private_value & 0xffff;
497 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
498 long val = *ucontrol->value.integer.value;
499 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
500 AC_VERB_GET_PIN_WIDGET_CONTROL,
501 0x00);
503 if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
504 val = alc_pin_mode_min(dir);
506 change = pinctl != alc_pin_mode_values[val];
507 if (change) {
508 /* Set pin mode to that requested */
509 snd_hda_codec_write_cache(codec, nid, 0,
510 AC_VERB_SET_PIN_WIDGET_CONTROL,
511 alc_pin_mode_values[val]);
513 /* Also enable the retasking pin's input/output as required
514 * for the requested pin mode. Enum values of 2 or less are
515 * input modes.
517 * Dynamically switching the input/output buffers probably
518 * reduces noise slightly (particularly on input) so we'll
519 * do it. However, having both input and output buffers
520 * enabled simultaneously doesn't seem to be problematic if
521 * this turns out to be necessary in the future.
523 if (val <= 2) {
524 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
525 HDA_AMP_MUTE, HDA_AMP_MUTE);
526 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
527 HDA_AMP_MUTE, 0);
528 } else {
529 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
530 HDA_AMP_MUTE, HDA_AMP_MUTE);
531 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
532 HDA_AMP_MUTE, 0);
535 return change;
538 #define ALC_PIN_MODE(xname, nid, dir) \
539 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
540 .info = alc_pin_mode_info, \
541 .get = alc_pin_mode_get, \
542 .put = alc_pin_mode_put, \
543 .private_value = nid | (dir<<16) }
545 /* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged
546 * together using a mask with more than one bit set. This control is
547 * currently used only by the ALC260 test model. At this stage they are not
548 * needed for any "production" models.
550 #ifdef CONFIG_SND_DEBUG
551 #define alc_gpio_data_info snd_ctl_boolean_mono_info
553 static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
554 struct snd_ctl_elem_value *ucontrol)
556 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
557 hda_nid_t nid = kcontrol->private_value & 0xffff;
558 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
559 long *valp = ucontrol->value.integer.value;
560 unsigned int val = snd_hda_codec_read(codec, nid, 0,
561 AC_VERB_GET_GPIO_DATA, 0x00);
563 *valp = (val & mask) != 0;
564 return 0;
566 static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
567 struct snd_ctl_elem_value *ucontrol)
569 signed int change;
570 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
571 hda_nid_t nid = kcontrol->private_value & 0xffff;
572 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
573 long val = *ucontrol->value.integer.value;
574 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
575 AC_VERB_GET_GPIO_DATA,
576 0x00);
578 /* Set/unset the masked GPIO bit(s) as needed */
579 change = (val == 0 ? 0 : mask) != (gpio_data & mask);
580 if (val == 0)
581 gpio_data &= ~mask;
582 else
583 gpio_data |= mask;
584 snd_hda_codec_write_cache(codec, nid, 0,
585 AC_VERB_SET_GPIO_DATA, gpio_data);
587 return change;
589 #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
590 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
591 .info = alc_gpio_data_info, \
592 .get = alc_gpio_data_get, \
593 .put = alc_gpio_data_put, \
594 .private_value = nid | (mask<<16) }
595 #endif /* CONFIG_SND_DEBUG */
597 /* A switch control to allow the enabling of the digital IO pins on the
598 * ALC260. This is incredibly simplistic; the intention of this control is
599 * to provide something in the test model allowing digital outputs to be
600 * identified if present. If models are found which can utilise these
601 * outputs a more complete mixer control can be devised for those models if
602 * necessary.
604 #ifdef CONFIG_SND_DEBUG
605 #define alc_spdif_ctrl_info snd_ctl_boolean_mono_info
607 static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
608 struct snd_ctl_elem_value *ucontrol)
610 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
611 hda_nid_t nid = kcontrol->private_value & 0xffff;
612 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
613 long *valp = ucontrol->value.integer.value;
614 unsigned int val = snd_hda_codec_read(codec, nid, 0,
615 AC_VERB_GET_DIGI_CONVERT_1, 0x00);
617 *valp = (val & mask) != 0;
618 return 0;
620 static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
621 struct snd_ctl_elem_value *ucontrol)
623 signed int change;
624 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
625 hda_nid_t nid = kcontrol->private_value & 0xffff;
626 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
627 long val = *ucontrol->value.integer.value;
628 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
629 AC_VERB_GET_DIGI_CONVERT_1,
630 0x00);
632 /* Set/unset the masked control bit(s) as needed */
633 change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
634 if (val==0)
635 ctrl_data &= ~mask;
636 else
637 ctrl_data |= mask;
638 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
639 ctrl_data);
641 return change;
643 #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
644 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
645 .info = alc_spdif_ctrl_info, \
646 .get = alc_spdif_ctrl_get, \
647 .put = alc_spdif_ctrl_put, \
648 .private_value = nid | (mask<<16) }
649 #endif /* CONFIG_SND_DEBUG */
651 /* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
652 * Again, this is only used in the ALC26x test models to help identify when
653 * the EAPD line must be asserted for features to work.
655 #ifdef CONFIG_SND_DEBUG
656 #define alc_eapd_ctrl_info snd_ctl_boolean_mono_info
658 static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
659 struct snd_ctl_elem_value *ucontrol)
661 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
662 hda_nid_t nid = kcontrol->private_value & 0xffff;
663 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
664 long *valp = ucontrol->value.integer.value;
665 unsigned int val = snd_hda_codec_read(codec, nid, 0,
666 AC_VERB_GET_EAPD_BTLENABLE, 0x00);
668 *valp = (val & mask) != 0;
669 return 0;
672 static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
673 struct snd_ctl_elem_value *ucontrol)
675 int change;
676 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
677 hda_nid_t nid = kcontrol->private_value & 0xffff;
678 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
679 long val = *ucontrol->value.integer.value;
680 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
681 AC_VERB_GET_EAPD_BTLENABLE,
682 0x00);
684 /* Set/unset the masked control bit(s) as needed */
685 change = (!val ? 0 : mask) != (ctrl_data & mask);
686 if (!val)
687 ctrl_data &= ~mask;
688 else
689 ctrl_data |= mask;
690 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
691 ctrl_data);
693 return change;
696 #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
697 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
698 .info = alc_eapd_ctrl_info, \
699 .get = alc_eapd_ctrl_get, \
700 .put = alc_eapd_ctrl_put, \
701 .private_value = nid | (mask<<16) }
702 #endif /* CONFIG_SND_DEBUG */
705 * set up from the preset table
707 static void setup_preset(struct alc_spec *spec,
708 const struct alc_config_preset *preset)
710 int i;
712 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
713 spec->mixers[spec->num_mixers++] = preset->mixers[i];
714 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
715 i++)
716 spec->init_verbs[spec->num_init_verbs++] =
717 preset->init_verbs[i];
719 spec->channel_mode = preset->channel_mode;
720 spec->num_channel_mode = preset->num_channel_mode;
721 spec->need_dac_fix = preset->need_dac_fix;
723 spec->multiout.max_channels = spec->channel_mode[0].channels;
725 spec->multiout.num_dacs = preset->num_dacs;
726 spec->multiout.dac_nids = preset->dac_nids;
727 spec->multiout.dig_out_nid = preset->dig_out_nid;
728 spec->multiout.hp_nid = preset->hp_nid;
730 spec->num_mux_defs = preset->num_mux_defs;
731 if (!spec->num_mux_defs)
732 spec->num_mux_defs = 1;
733 spec->input_mux = preset->input_mux;
735 spec->num_adc_nids = preset->num_adc_nids;
736 spec->adc_nids = preset->adc_nids;
737 spec->capsrc_nids = preset->capsrc_nids;
738 spec->dig_in_nid = preset->dig_in_nid;
740 spec->unsol_event = preset->unsol_event;
741 spec->init_hook = preset->init_hook;
742 #ifdef CONFIG_SND_HDA_POWER_SAVE
743 spec->loopback.amplist = preset->loopbacks;
744 #endif
747 /* Enable GPIO mask and set output */
748 static struct hda_verb alc_gpio1_init_verbs[] = {
749 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
750 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
751 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
755 static struct hda_verb alc_gpio2_init_verbs[] = {
756 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
757 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
758 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
762 static struct hda_verb alc_gpio3_init_verbs[] = {
763 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
764 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
765 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
770 * Fix hardware PLL issue
771 * On some codecs, the analog PLL gating control must be off while
772 * the default value is 1.
774 static void alc_fix_pll(struct hda_codec *codec)
776 struct alc_spec *spec = codec->spec;
777 unsigned int val;
779 if (!spec->pll_nid)
780 return;
781 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
782 spec->pll_coef_idx);
783 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
784 AC_VERB_GET_PROC_COEF, 0);
785 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
786 spec->pll_coef_idx);
787 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
788 val & ~(1 << spec->pll_coef_bit));
791 static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
792 unsigned int coef_idx, unsigned int coef_bit)
794 struct alc_spec *spec = codec->spec;
795 spec->pll_nid = nid;
796 spec->pll_coef_idx = coef_idx;
797 spec->pll_coef_bit = coef_bit;
798 alc_fix_pll(codec);
801 static void alc_sku_automute(struct hda_codec *codec)
803 struct alc_spec *spec = codec->spec;
804 unsigned int present;
805 unsigned int hp_nid = spec->autocfg.hp_pins[0];
806 unsigned int sp_nid = spec->autocfg.speaker_pins[0];
808 /* need to execute and sync at first */
809 snd_hda_codec_read(codec, hp_nid, 0, AC_VERB_SET_PIN_SENSE, 0);
810 present = snd_hda_codec_read(codec, hp_nid, 0,
811 AC_VERB_GET_PIN_SENSE, 0);
812 spec->jack_present = (present & 0x80000000) != 0;
813 snd_hda_codec_write(codec, sp_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
814 spec->jack_present ? 0 : PIN_OUT);
817 /* unsolicited event for HP jack sensing */
818 static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
820 if (codec->vendor_id == 0x10ec0880)
821 res >>= 28;
822 else
823 res >>= 26;
824 if (res != ALC880_HP_EVENT)
825 return;
827 alc_sku_automute(codec);
830 /* additional initialization for ALC888 variants */
831 static void alc888_coef_init(struct hda_codec *codec)
833 unsigned int tmp;
835 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
836 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
837 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
838 if ((tmp & 0xf0) == 2)
839 /* alc888S-VC */
840 snd_hda_codec_read(codec, 0x20, 0,
841 AC_VERB_SET_PROC_COEF, 0x830);
842 else
843 /* alc888-VB */
844 snd_hda_codec_read(codec, 0x20, 0,
845 AC_VERB_SET_PROC_COEF, 0x3030);
848 /* 32-bit subsystem ID for BIOS loading in HD Audio codec.
849 * 31 ~ 16 : Manufacture ID
850 * 15 ~ 8 : SKU ID
851 * 7 ~ 0 : Assembly ID
852 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
854 static void alc_subsystem_id(struct hda_codec *codec,
855 unsigned int porta, unsigned int porte,
856 unsigned int portd)
858 unsigned int ass, tmp, i;
859 unsigned nid;
860 struct alc_spec *spec = codec->spec;
862 ass = codec->subsystem_id & 0xffff;
863 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
864 goto do_sku;
867 * 31~30 : port conetcivity
868 * 29~21 : reserve
869 * 20 : PCBEEP input
870 * 19~16 : Check sum (15:1)
871 * 15~1 : Custom
872 * 0 : override
874 nid = 0x1d;
875 if (codec->vendor_id == 0x10ec0260)
876 nid = 0x17;
877 ass = snd_hda_codec_read(codec, nid, 0,
878 AC_VERB_GET_CONFIG_DEFAULT, 0);
879 if (!(ass & 1) && !(ass & 0x100000))
880 return;
881 if ((ass >> 30) != 1) /* no physical connection */
882 return;
884 /* check sum */
885 tmp = 0;
886 for (i = 1; i < 16; i++) {
887 if ((ass >> i) & 1)
888 tmp++;
890 if (((ass >> 16) & 0xf) != tmp)
891 return;
892 do_sku:
894 * 0 : override
895 * 1 : Swap Jack
896 * 2 : 0 --> Desktop, 1 --> Laptop
897 * 3~5 : External Amplifier control
898 * 7~6 : Reserved
900 tmp = (ass & 0x38) >> 3; /* external Amp control */
901 switch (tmp) {
902 case 1:
903 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
904 break;
905 case 3:
906 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
907 break;
908 case 7:
909 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
910 break;
911 case 5: /* set EAPD output high */
912 switch (codec->vendor_id) {
913 case 0x10ec0260:
914 snd_hda_codec_write(codec, 0x0f, 0,
915 AC_VERB_SET_EAPD_BTLENABLE, 2);
916 snd_hda_codec_write(codec, 0x10, 0,
917 AC_VERB_SET_EAPD_BTLENABLE, 2);
918 break;
919 case 0x10ec0262:
920 case 0x10ec0267:
921 case 0x10ec0268:
922 case 0x10ec0269:
923 case 0x10ec0660:
924 case 0x10ec0662:
925 case 0x10ec0663:
926 case 0x10ec0862:
927 case 0x10ec0889:
928 snd_hda_codec_write(codec, 0x14, 0,
929 AC_VERB_SET_EAPD_BTLENABLE, 2);
930 snd_hda_codec_write(codec, 0x15, 0,
931 AC_VERB_SET_EAPD_BTLENABLE, 2);
932 break;
934 switch (codec->vendor_id) {
935 case 0x10ec0260:
936 snd_hda_codec_write(codec, 0x1a, 0,
937 AC_VERB_SET_COEF_INDEX, 7);
938 tmp = snd_hda_codec_read(codec, 0x1a, 0,
939 AC_VERB_GET_PROC_COEF, 0);
940 snd_hda_codec_write(codec, 0x1a, 0,
941 AC_VERB_SET_COEF_INDEX, 7);
942 snd_hda_codec_write(codec, 0x1a, 0,
943 AC_VERB_SET_PROC_COEF,
944 tmp | 0x2010);
945 break;
946 case 0x10ec0262:
947 case 0x10ec0880:
948 case 0x10ec0882:
949 case 0x10ec0883:
950 case 0x10ec0885:
951 case 0x10ec0889:
952 snd_hda_codec_write(codec, 0x20, 0,
953 AC_VERB_SET_COEF_INDEX, 7);
954 tmp = snd_hda_codec_read(codec, 0x20, 0,
955 AC_VERB_GET_PROC_COEF, 0);
956 snd_hda_codec_write(codec, 0x20, 0,
957 AC_VERB_SET_COEF_INDEX, 7);
958 snd_hda_codec_write(codec, 0x20, 0,
959 AC_VERB_SET_PROC_COEF,
960 tmp | 0x2010);
961 break;
962 case 0x10ec0888:
963 /*alc888_coef_init(codec);*/ /* called in alc_init() */
964 break;
965 case 0x10ec0267:
966 case 0x10ec0268:
967 snd_hda_codec_write(codec, 0x20, 0,
968 AC_VERB_SET_COEF_INDEX, 7);
969 tmp = snd_hda_codec_read(codec, 0x20, 0,
970 AC_VERB_GET_PROC_COEF, 0);
971 snd_hda_codec_write(codec, 0x20, 0,
972 AC_VERB_SET_COEF_INDEX, 7);
973 snd_hda_codec_write(codec, 0x20, 0,
974 AC_VERB_SET_PROC_COEF,
975 tmp | 0x3000);
976 break;
978 default:
979 break;
982 /* is laptop or Desktop and enable the function "Mute internal speaker
983 * when the external headphone out jack is plugged"
985 if (!(ass & 0x8000))
986 return;
988 * 10~8 : Jack location
989 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
990 * 14~13: Resvered
991 * 15 : 1 --> enable the function "Mute internal speaker
992 * when the external headphone out jack is plugged"
994 if (!spec->autocfg.speaker_pins[0]) {
995 if (spec->autocfg.line_out_pins[0])
996 spec->autocfg.speaker_pins[0] =
997 spec->autocfg.line_out_pins[0];
998 else
999 return;
1002 if (!spec->autocfg.hp_pins[0]) {
1003 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1004 if (tmp == 0)
1005 spec->autocfg.hp_pins[0] = porta;
1006 else if (tmp == 1)
1007 spec->autocfg.hp_pins[0] = porte;
1008 else if (tmp == 2)
1009 spec->autocfg.hp_pins[0] = portd;
1010 else
1011 return;
1014 snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
1015 AC_VERB_SET_UNSOLICITED_ENABLE,
1016 AC_USRSP_EN | ALC880_HP_EVENT);
1017 spec->unsol_event = alc_sku_unsol_event;
1021 * Fix-up pin default configurations
1024 struct alc_pincfg {
1025 hda_nid_t nid;
1026 u32 val;
1029 static void alc_fix_pincfg(struct hda_codec *codec,
1030 const struct snd_pci_quirk *quirk,
1031 const struct alc_pincfg **pinfix)
1033 const struct alc_pincfg *cfg;
1035 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1036 if (!quirk)
1037 return;
1039 cfg = pinfix[quirk->value];
1040 for (; cfg->nid; cfg++) {
1041 int i;
1042 u32 val = cfg->val;
1043 for (i = 0; i < 4; i++) {
1044 snd_hda_codec_write(codec, cfg->nid, 0,
1045 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
1046 val & 0xff);
1047 val >>= 8;
1053 * ALC880 3-stack model
1055 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
1056 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
1057 * F-Mic = 0x1b, HP = 0x19
1060 static hda_nid_t alc880_dac_nids[4] = {
1061 /* front, rear, clfe, rear_surr */
1062 0x02, 0x05, 0x04, 0x03
1065 static hda_nid_t alc880_adc_nids[3] = {
1066 /* ADC0-2 */
1067 0x07, 0x08, 0x09,
1070 /* The datasheet says the node 0x07 is connected from inputs,
1071 * but it shows zero connection in the real implementation on some devices.
1072 * Note: this is a 915GAV bug, fixed on 915GLV
1074 static hda_nid_t alc880_adc_nids_alt[2] = {
1075 /* ADC1-2 */
1076 0x08, 0x09,
1079 #define ALC880_DIGOUT_NID 0x06
1080 #define ALC880_DIGIN_NID 0x0a
1082 static struct hda_input_mux alc880_capture_source = {
1083 .num_items = 4,
1084 .items = {
1085 { "Mic", 0x0 },
1086 { "Front Mic", 0x3 },
1087 { "Line", 0x2 },
1088 { "CD", 0x4 },
1092 /* channel source setting (2/6 channel selection for 3-stack) */
1093 /* 2ch mode */
1094 static struct hda_verb alc880_threestack_ch2_init[] = {
1095 /* set line-in to input, mute it */
1096 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1097 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1098 /* set mic-in to input vref 80%, mute it */
1099 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1100 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1101 { } /* end */
1104 /* 6ch mode */
1105 static struct hda_verb alc880_threestack_ch6_init[] = {
1106 /* set line-in to output, unmute it */
1107 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1108 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1109 /* set mic-in to output, unmute it */
1110 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1111 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1112 { } /* end */
1115 static struct hda_channel_mode alc880_threestack_modes[2] = {
1116 { 2, alc880_threestack_ch2_init },
1117 { 6, alc880_threestack_ch6_init },
1120 static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
1121 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1122 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1123 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1124 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
1125 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1126 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1127 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1128 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1129 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1130 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1131 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1132 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1133 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1134 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1135 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
1136 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
1137 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1138 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1139 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
1141 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1142 .name = "Channel Mode",
1143 .info = alc_ch_mode_info,
1144 .get = alc_ch_mode_get,
1145 .put = alc_ch_mode_put,
1147 { } /* end */
1150 /* capture mixer elements */
1151 static struct snd_kcontrol_new alc880_capture_mixer[] = {
1152 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
1153 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
1154 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
1155 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
1156 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
1157 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
1159 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1160 /* The multiple "Capture Source" controls confuse alsamixer
1161 * So call somewhat different..
1163 /* .name = "Capture Source", */
1164 .name = "Input Source",
1165 .count = 3,
1166 .info = alc_mux_enum_info,
1167 .get = alc_mux_enum_get,
1168 .put = alc_mux_enum_put,
1170 { } /* end */
1173 /* capture mixer elements (in case NID 0x07 not available) */
1174 static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {
1175 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
1176 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
1177 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
1178 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
1180 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1181 /* The multiple "Capture Source" controls confuse alsamixer
1182 * So call somewhat different..
1184 /* .name = "Capture Source", */
1185 .name = "Input Source",
1186 .count = 2,
1187 .info = alc_mux_enum_info,
1188 .get = alc_mux_enum_get,
1189 .put = alc_mux_enum_put,
1191 { } /* end */
1197 * ALC880 5-stack model
1199 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
1200 * Side = 0x02 (0xd)
1201 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
1202 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
1205 /* additional mixers to alc880_three_stack_mixer */
1206 static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
1207 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1208 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
1209 { } /* end */
1212 /* channel source setting (6/8 channel selection for 5-stack) */
1213 /* 6ch mode */
1214 static struct hda_verb alc880_fivestack_ch6_init[] = {
1215 /* set line-in to input, mute it */
1216 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1217 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1218 { } /* end */
1221 /* 8ch mode */
1222 static struct hda_verb alc880_fivestack_ch8_init[] = {
1223 /* set line-in to output, unmute it */
1224 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1225 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1226 { } /* end */
1229 static struct hda_channel_mode alc880_fivestack_modes[2] = {
1230 { 6, alc880_fivestack_ch6_init },
1231 { 8, alc880_fivestack_ch8_init },
1236 * ALC880 6-stack model
1238 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
1239 * Side = 0x05 (0x0f)
1240 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
1241 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
1244 static hda_nid_t alc880_6st_dac_nids[4] = {
1245 /* front, rear, clfe, rear_surr */
1246 0x02, 0x03, 0x04, 0x05
1249 static struct hda_input_mux alc880_6stack_capture_source = {
1250 .num_items = 4,
1251 .items = {
1252 { "Mic", 0x0 },
1253 { "Front Mic", 0x1 },
1254 { "Line", 0x2 },
1255 { "CD", 0x4 },
1259 /* fixed 8-channels */
1260 static struct hda_channel_mode alc880_sixstack_modes[1] = {
1261 { 8, NULL },
1264 static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
1265 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1266 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1267 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1268 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1269 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1270 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1271 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1272 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1273 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1274 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
1275 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1276 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1277 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1278 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1279 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1280 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1281 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1282 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1283 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1284 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1286 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1287 .name = "Channel Mode",
1288 .info = alc_ch_mode_info,
1289 .get = alc_ch_mode_get,
1290 .put = alc_ch_mode_put,
1292 { } /* end */
1297 * ALC880 W810 model
1299 * W810 has rear IO for:
1300 * Front (DAC 02)
1301 * Surround (DAC 03)
1302 * Center/LFE (DAC 04)
1303 * Digital out (06)
1305 * The system also has a pair of internal speakers, and a headphone jack.
1306 * These are both connected to Line2 on the codec, hence to DAC 02.
1308 * There is a variable resistor to control the speaker or headphone
1309 * volume. This is a hardware-only device without a software API.
1311 * Plugging headphones in will disable the internal speakers. This is
1312 * implemented in hardware, not via the driver using jack sense. In
1313 * a similar fashion, plugging into the rear socket marked "front" will
1314 * disable both the speakers and headphones.
1316 * For input, there's a microphone jack, and an "audio in" jack.
1317 * These may not do anything useful with this driver yet, because I
1318 * haven't setup any initialization verbs for these yet...
1321 static hda_nid_t alc880_w810_dac_nids[3] = {
1322 /* front, rear/surround, clfe */
1323 0x02, 0x03, 0x04
1326 /* fixed 6 channels */
1327 static struct hda_channel_mode alc880_w810_modes[1] = {
1328 { 6, NULL }
1331 /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
1332 static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
1333 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1334 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1335 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1336 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1337 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1338 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1339 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1340 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1341 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1342 { } /* end */
1347 * Z710V model
1349 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
1350 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
1351 * Line = 0x1a
1354 static hda_nid_t alc880_z71v_dac_nids[1] = {
1355 0x02
1357 #define ALC880_Z71V_HP_DAC 0x03
1359 /* fixed 2 channels */
1360 static struct hda_channel_mode alc880_2_jack_modes[1] = {
1361 { 2, NULL }
1364 static struct snd_kcontrol_new alc880_z71v_mixer[] = {
1365 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1366 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1367 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1368 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
1369 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1370 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1371 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1372 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1373 { } /* end */
1378 * ALC880 F1734 model
1380 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
1381 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
1384 static hda_nid_t alc880_f1734_dac_nids[1] = {
1385 0x03
1387 #define ALC880_F1734_HP_DAC 0x02
1389 static struct snd_kcontrol_new alc880_f1734_mixer[] = {
1390 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1391 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
1392 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1393 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
1394 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1395 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1396 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1397 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1398 { } /* end */
1401 static struct hda_input_mux alc880_f1734_capture_source = {
1402 .num_items = 2,
1403 .items = {
1404 { "Mic", 0x1 },
1405 { "CD", 0x4 },
1411 * ALC880 ASUS model
1413 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
1414 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
1415 * Mic = 0x18, Line = 0x1a
1418 #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
1419 #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
1421 static struct snd_kcontrol_new alc880_asus_mixer[] = {
1422 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1423 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1424 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1425 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1426 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1427 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1428 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1429 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1430 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1431 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1432 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1433 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1434 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1435 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1437 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1438 .name = "Channel Mode",
1439 .info = alc_ch_mode_info,
1440 .get = alc_ch_mode_get,
1441 .put = alc_ch_mode_put,
1443 { } /* end */
1447 * ALC880 ASUS W1V model
1449 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
1450 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
1451 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
1454 /* additional mixers to alc880_asus_mixer */
1455 static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
1456 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
1457 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
1458 { } /* end */
1461 /* additional mixers to alc880_asus_mixer */
1462 static struct snd_kcontrol_new alc880_pcbeep_mixer[] = {
1463 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1464 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1465 { } /* end */
1468 /* TCL S700 */
1469 static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
1470 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1471 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1472 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
1473 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
1474 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
1475 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
1476 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
1477 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
1478 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
1480 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1481 /* The multiple "Capture Source" controls confuse alsamixer
1482 * So call somewhat different..
1484 /* .name = "Capture Source", */
1485 .name = "Input Source",
1486 .count = 1,
1487 .info = alc_mux_enum_info,
1488 .get = alc_mux_enum_get,
1489 .put = alc_mux_enum_put,
1491 { } /* end */
1494 /* Uniwill */
1495 static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
1496 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1497 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
1498 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1499 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
1500 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1501 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1502 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1503 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1504 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1505 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1506 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1507 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1508 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1509 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1510 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1511 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1512 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1513 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1515 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1516 .name = "Channel Mode",
1517 .info = alc_ch_mode_info,
1518 .get = alc_ch_mode_get,
1519 .put = alc_ch_mode_put,
1521 { } /* end */
1524 static struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
1525 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1526 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
1527 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1528 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
1529 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1530 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1531 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1532 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1533 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1534 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1535 { } /* end */
1538 static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
1539 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1540 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
1541 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1542 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
1543 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1544 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1545 { } /* end */
1549 * virtual master controls
1553 * slave controls for virtual master
1555 static const char *alc_slave_vols[] = {
1556 "Front Playback Volume",
1557 "Surround Playback Volume",
1558 "Center Playback Volume",
1559 "LFE Playback Volume",
1560 "Side Playback Volume",
1561 "Headphone Playback Volume",
1562 "Speaker Playback Volume",
1563 "Mono Playback Volume",
1564 "Line-Out Playback Volume",
1565 NULL,
1568 static const char *alc_slave_sws[] = {
1569 "Front Playback Switch",
1570 "Surround Playback Switch",
1571 "Center Playback Switch",
1572 "LFE Playback Switch",
1573 "Side Playback Switch",
1574 "Headphone Playback Switch",
1575 "Speaker Playback Switch",
1576 "Mono Playback Switch",
1577 "IEC958 Playback Switch",
1578 NULL,
1582 * build control elements
1584 static int alc_build_controls(struct hda_codec *codec)
1586 struct alc_spec *spec = codec->spec;
1587 int err;
1588 int i;
1590 for (i = 0; i < spec->num_mixers; i++) {
1591 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1592 if (err < 0)
1593 return err;
1596 if (spec->multiout.dig_out_nid) {
1597 err = snd_hda_create_spdif_out_ctls(codec,
1598 spec->multiout.dig_out_nid);
1599 if (err < 0)
1600 return err;
1601 err = snd_hda_create_spdif_share_sw(codec,
1602 &spec->multiout);
1603 if (err < 0)
1604 return err;
1605 spec->multiout.share_spdif = 1;
1607 if (spec->dig_in_nid) {
1608 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1609 if (err < 0)
1610 return err;
1613 /* if we have no master control, let's create it */
1614 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
1615 unsigned int vmaster_tlv[4];
1616 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
1617 HDA_OUTPUT, vmaster_tlv);
1618 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
1619 vmaster_tlv, alc_slave_vols);
1620 if (err < 0)
1621 return err;
1623 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
1624 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1625 NULL, alc_slave_sws);
1626 if (err < 0)
1627 return err;
1630 return 0;
1635 * initialize the codec volumes, etc
1639 * generic initialization of ADC, input mixers and output mixers
1641 static struct hda_verb alc880_volume_init_verbs[] = {
1643 * Unmute ADC0-2 and set the default input to mic-in
1645 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
1646 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1647 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
1648 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1649 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
1650 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1652 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1653 * mixer widget
1654 * Note: PASD motherboards uses the Line In 2 as the input for front
1655 * panel mic (mic 2)
1657 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
1658 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1659 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1660 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1661 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1662 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1663 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1664 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1667 * Set up output mixers (0x0c - 0x0f)
1669 /* set vol=0 to output mixers */
1670 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1671 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1672 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1673 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1674 /* set up input amps for analog loopback */
1675 /* Amp Indices: DAC = 0, mixer = 1 */
1676 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1677 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1678 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1679 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1680 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1681 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1682 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1683 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1689 * 3-stack pin configuration:
1690 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
1692 static struct hda_verb alc880_pin_3stack_init_verbs[] = {
1694 * preset connection lists of input pins
1695 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
1697 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
1698 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1699 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
1702 * Set pin mode and muting
1704 /* set front pin widgets 0x14 for output */
1705 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1706 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1707 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1708 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1709 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1710 /* Mic2 (as headphone out) for HP output */
1711 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1712 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1713 /* Line In pin widget for input */
1714 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1715 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1716 /* Line2 (as front mic) pin widget for input and vref at 80% */
1717 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1718 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1719 /* CD pin widget for input */
1720 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1726 * 5-stack pin configuration:
1727 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
1728 * line-in/side = 0x1a, f-mic = 0x1b
1730 static struct hda_verb alc880_pin_5stack_init_verbs[] = {
1732 * preset connection lists of input pins
1733 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
1735 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1736 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
1739 * Set pin mode and muting
1741 /* set pin widgets 0x14-0x17 for output */
1742 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1743 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1744 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1745 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1746 /* unmute pins for output (no gain on this amp) */
1747 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1748 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1749 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1750 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1752 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1753 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1754 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1755 /* Mic2 (as headphone out) for HP output */
1756 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1757 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1758 /* Line In pin widget for input */
1759 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1760 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1761 /* Line2 (as front mic) pin widget for input and vref at 80% */
1762 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1763 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1764 /* CD pin widget for input */
1765 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1771 * W810 pin configuration:
1772 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
1774 static struct hda_verb alc880_pin_w810_init_verbs[] = {
1775 /* hphone/speaker input selector: front DAC */
1776 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
1778 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1779 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1780 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1781 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1782 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1783 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1785 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1786 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1792 * Z71V pin configuration:
1793 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
1795 static struct hda_verb alc880_pin_z71v_init_verbs[] = {
1796 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1797 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1798 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1799 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1801 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1802 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1803 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1804 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1810 * 6-stack pin configuration:
1811 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
1812 * f-mic = 0x19, line = 0x1a, HP = 0x1b
1814 static struct hda_verb alc880_pin_6stack_init_verbs[] = {
1815 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1817 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1818 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1819 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1820 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1821 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1822 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1823 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1824 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1826 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1827 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1828 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1829 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1830 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1831 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1832 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1833 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1834 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1840 * Uniwill pin configuration:
1841 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
1842 * line = 0x1a
1844 static struct hda_verb alc880_uniwill_init_verbs[] = {
1845 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1847 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1848 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1849 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1850 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1851 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1852 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1853 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1854 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1855 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1856 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1857 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1858 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1859 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1860 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1862 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1863 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1864 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1865 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1866 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1867 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1868 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
1869 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
1870 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1872 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
1873 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
1879 * Uniwill P53
1880 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
1882 static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
1883 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1885 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1886 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1887 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1888 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1889 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1890 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1891 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1892 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1893 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1894 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1895 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1896 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1898 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1899 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1900 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1901 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1902 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1903 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1905 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
1906 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
1911 static struct hda_verb alc880_beep_init_verbs[] = {
1912 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
1916 /* toggle speaker-output according to the hp-jack state */
1917 static void alc880_uniwill_hp_automute(struct hda_codec *codec)
1919 unsigned int present;
1920 unsigned char bits;
1922 present = snd_hda_codec_read(codec, 0x14, 0,
1923 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1924 bits = present ? HDA_AMP_MUTE : 0;
1925 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
1926 HDA_AMP_MUTE, bits);
1927 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
1928 HDA_AMP_MUTE, bits);
1931 /* auto-toggle front mic */
1932 static void alc880_uniwill_mic_automute(struct hda_codec *codec)
1934 unsigned int present;
1935 unsigned char bits;
1937 present = snd_hda_codec_read(codec, 0x18, 0,
1938 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1939 bits = present ? HDA_AMP_MUTE : 0;
1940 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
1943 static void alc880_uniwill_automute(struct hda_codec *codec)
1945 alc880_uniwill_hp_automute(codec);
1946 alc880_uniwill_mic_automute(codec);
1949 static void alc880_uniwill_unsol_event(struct hda_codec *codec,
1950 unsigned int res)
1952 /* Looks like the unsol event is incompatible with the standard
1953 * definition. 4bit tag is placed at 28 bit!
1955 switch (res >> 28) {
1956 case ALC880_HP_EVENT:
1957 alc880_uniwill_hp_automute(codec);
1958 break;
1959 case ALC880_MIC_EVENT:
1960 alc880_uniwill_mic_automute(codec);
1961 break;
1965 static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
1967 unsigned int present;
1968 unsigned char bits;
1970 present = snd_hda_codec_read(codec, 0x14, 0,
1971 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1972 bits = present ? HDA_AMP_MUTE : 0;
1973 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, HDA_AMP_MUTE, bits);
1976 static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
1978 unsigned int present;
1980 present = snd_hda_codec_read(codec, 0x21, 0,
1981 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
1982 present &= HDA_AMP_VOLMASK;
1983 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
1984 HDA_AMP_VOLMASK, present);
1985 snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
1986 HDA_AMP_VOLMASK, present);
1989 static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
1990 unsigned int res)
1992 /* Looks like the unsol event is incompatible with the standard
1993 * definition. 4bit tag is placed at 28 bit!
1995 if ((res >> 28) == ALC880_HP_EVENT)
1996 alc880_uniwill_p53_hp_automute(codec);
1997 if ((res >> 28) == ALC880_DCVOL_EVENT)
1998 alc880_uniwill_p53_dcvol_automute(codec);
2002 * F1734 pin configuration:
2003 * HP = 0x14, speaker-out = 0x15, mic = 0x18
2005 static struct hda_verb alc880_pin_f1734_init_verbs[] = {
2006 {0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
2007 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
2008 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
2009 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
2010 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
2012 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2013 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2014 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2015 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2017 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2018 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2019 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
2020 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2021 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2022 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2023 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2024 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2025 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2027 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
2028 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
2034 * ASUS pin configuration:
2035 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
2037 static struct hda_verb alc880_pin_asus_init_verbs[] = {
2038 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
2039 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
2040 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
2041 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
2043 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2044 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2045 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2046 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2047 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2048 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2049 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2050 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2052 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2053 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2054 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2055 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2056 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2057 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2058 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2059 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2060 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2065 /* Enable GPIO mask and set output */
2066 #define alc880_gpio1_init_verbs alc_gpio1_init_verbs
2067 #define alc880_gpio2_init_verbs alc_gpio2_init_verbs
2069 /* Clevo m520g init */
2070 static struct hda_verb alc880_pin_clevo_init_verbs[] = {
2071 /* headphone output */
2072 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
2073 /* line-out */
2074 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2075 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2076 /* Line-in */
2077 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2078 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2079 /* CD */
2080 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2081 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2082 /* Mic1 (rear panel) */
2083 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2084 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2085 /* Mic2 (front panel) */
2086 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2087 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2088 /* headphone */
2089 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2090 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2091 /* change to EAPD mode */
2092 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
2093 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
2098 static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
2099 /* change to EAPD mode */
2100 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
2101 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
2103 /* Headphone output */
2104 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2105 /* Front output*/
2106 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2107 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
2109 /* Line In pin widget for input */
2110 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2111 /* CD pin widget for input */
2112 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2113 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2114 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2116 /* change to EAPD mode */
2117 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
2118 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
2124 * LG m1 express dual
2126 * Pin assignment:
2127 * Rear Line-In/Out (blue): 0x14
2128 * Build-in Mic-In: 0x15
2129 * Speaker-out: 0x17
2130 * HP-Out (green): 0x1b
2131 * Mic-In/Out (red): 0x19
2132 * SPDIF-Out: 0x1e
2135 /* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
2136 static hda_nid_t alc880_lg_dac_nids[3] = {
2137 0x05, 0x02, 0x03
2140 /* seems analog CD is not working */
2141 static struct hda_input_mux alc880_lg_capture_source = {
2142 .num_items = 3,
2143 .items = {
2144 { "Mic", 0x1 },
2145 { "Line", 0x5 },
2146 { "Internal Mic", 0x6 },
2150 /* 2,4,6 channel modes */
2151 static struct hda_verb alc880_lg_ch2_init[] = {
2152 /* set line-in and mic-in to input */
2153 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2154 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2158 static struct hda_verb alc880_lg_ch4_init[] = {
2159 /* set line-in to out and mic-in to input */
2160 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
2161 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2165 static struct hda_verb alc880_lg_ch6_init[] = {
2166 /* set line-in and mic-in to output */
2167 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
2168 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
2172 static struct hda_channel_mode alc880_lg_ch_modes[3] = {
2173 { 2, alc880_lg_ch2_init },
2174 { 4, alc880_lg_ch4_init },
2175 { 6, alc880_lg_ch6_init },
2178 static struct snd_kcontrol_new alc880_lg_mixer[] = {
2179 HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2180 HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
2181 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2182 HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
2183 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
2184 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
2185 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
2186 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
2187 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2188 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
2189 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
2190 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
2191 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
2192 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
2194 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2195 .name = "Channel Mode",
2196 .info = alc_ch_mode_info,
2197 .get = alc_ch_mode_get,
2198 .put = alc_ch_mode_put,
2200 { } /* end */
2203 static struct hda_verb alc880_lg_init_verbs[] = {
2204 /* set capture source to mic-in */
2205 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2206 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2207 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2208 /* mute all amp mixer inputs */
2209 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
2210 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2211 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2212 /* line-in to input */
2213 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2214 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2215 /* built-in mic */
2216 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2217 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2218 /* speaker-out */
2219 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2220 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2221 /* mic-in to input */
2222 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
2223 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2224 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2225 /* HP-out */
2226 {0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
2227 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2228 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2229 /* jack sense */
2230 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
2234 /* toggle speaker-output according to the hp-jack state */
2235 static void alc880_lg_automute(struct hda_codec *codec)
2237 unsigned int present;
2238 unsigned char bits;
2240 present = snd_hda_codec_read(codec, 0x1b, 0,
2241 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
2242 bits = present ? HDA_AMP_MUTE : 0;
2243 snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,
2244 HDA_AMP_MUTE, bits);
2247 static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res)
2249 /* Looks like the unsol event is incompatible with the standard
2250 * definition. 4bit tag is placed at 28 bit!
2252 if ((res >> 28) == 0x01)
2253 alc880_lg_automute(codec);
2257 * LG LW20
2259 * Pin assignment:
2260 * Speaker-out: 0x14
2261 * Mic-In: 0x18
2262 * Built-in Mic-In: 0x19
2263 * Line-In: 0x1b
2264 * HP-Out: 0x1a
2265 * SPDIF-Out: 0x1e
2268 static struct hda_input_mux alc880_lg_lw_capture_source = {
2269 .num_items = 3,
2270 .items = {
2271 { "Mic", 0x0 },
2272 { "Internal Mic", 0x1 },
2273 { "Line In", 0x2 },
2277 #define alc880_lg_lw_modes alc880_threestack_modes
2279 static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
2280 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2281 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2282 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2283 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
2284 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2285 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2286 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2287 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2288 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2289 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2290 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2291 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2292 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
2293 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
2295 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2296 .name = "Channel Mode",
2297 .info = alc_ch_mode_info,
2298 .get = alc_ch_mode_get,
2299 .put = alc_ch_mode_put,
2301 { } /* end */
2304 static struct hda_verb alc880_lg_lw_init_verbs[] = {
2305 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2306 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
2307 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
2309 /* set capture source to mic-in */
2310 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2311 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2312 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2313 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2314 /* speaker-out */
2315 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2316 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2317 /* HP-out */
2318 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2319 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2320 /* mic-in to input */
2321 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2322 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2323 /* built-in mic */
2324 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2325 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2326 /* jack sense */
2327 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
2331 /* toggle speaker-output according to the hp-jack state */
2332 static void alc880_lg_lw_automute(struct hda_codec *codec)
2334 unsigned int present;
2335 unsigned char bits;
2337 present = snd_hda_codec_read(codec, 0x1b, 0,
2338 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
2339 bits = present ? HDA_AMP_MUTE : 0;
2340 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
2341 HDA_AMP_MUTE, bits);
2344 static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
2346 /* Looks like the unsol event is incompatible with the standard
2347 * definition. 4bit tag is placed at 28 bit!
2349 if ((res >> 28) == 0x01)
2350 alc880_lg_lw_automute(codec);
2353 static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
2354 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2355 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
2356 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2357 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2358 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2359 HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
2360 { } /* end */
2363 static struct hda_input_mux alc880_medion_rim_capture_source = {
2364 .num_items = 2,
2365 .items = {
2366 { "Mic", 0x0 },
2367 { "Internal Mic", 0x1 },
2371 static struct hda_verb alc880_medion_rim_init_verbs[] = {
2372 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2374 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2375 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2377 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2378 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2379 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2380 /* Mic2 (as headphone out) for HP output */
2381 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2382 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2383 /* Internal Speaker */
2384 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2385 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2387 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
2388 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
2390 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
2394 /* toggle speaker-output according to the hp-jack state */
2395 static void alc880_medion_rim_automute(struct hda_codec *codec)
2397 unsigned int present;
2398 unsigned char bits;
2400 present = snd_hda_codec_read(codec, 0x14, 0,
2401 AC_VERB_GET_PIN_SENSE, 0)
2402 & AC_PINSENSE_PRESENCE;
2403 bits = present ? HDA_AMP_MUTE : 0;
2404 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
2405 HDA_AMP_MUTE, bits);
2406 if (present)
2407 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
2408 else
2409 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
2412 static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
2413 unsigned int res)
2415 /* Looks like the unsol event is incompatible with the standard
2416 * definition. 4bit tag is placed at 28 bit!
2418 if ((res >> 28) == ALC880_HP_EVENT)
2419 alc880_medion_rim_automute(codec);
2422 #ifdef CONFIG_SND_HDA_POWER_SAVE
2423 static struct hda_amp_list alc880_loopbacks[] = {
2424 { 0x0b, HDA_INPUT, 0 },
2425 { 0x0b, HDA_INPUT, 1 },
2426 { 0x0b, HDA_INPUT, 2 },
2427 { 0x0b, HDA_INPUT, 3 },
2428 { 0x0b, HDA_INPUT, 4 },
2429 { } /* end */
2432 static struct hda_amp_list alc880_lg_loopbacks[] = {
2433 { 0x0b, HDA_INPUT, 1 },
2434 { 0x0b, HDA_INPUT, 6 },
2435 { 0x0b, HDA_INPUT, 7 },
2436 { } /* end */
2438 #endif
2441 * Common callbacks
2444 static int alc_init(struct hda_codec *codec)
2446 struct alc_spec *spec = codec->spec;
2447 unsigned int i;
2449 alc_fix_pll(codec);
2450 if (codec->vendor_id == 0x10ec0888)
2451 alc888_coef_init(codec);
2453 for (i = 0; i < spec->num_init_verbs; i++)
2454 snd_hda_sequence_write(codec, spec->init_verbs[i]);
2456 if (spec->init_hook)
2457 spec->init_hook(codec);
2459 return 0;
2462 static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2464 struct alc_spec *spec = codec->spec;
2466 if (spec->unsol_event)
2467 spec->unsol_event(codec, res);
2470 #ifdef CONFIG_SND_HDA_POWER_SAVE
2471 static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2473 struct alc_spec *spec = codec->spec;
2474 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2476 #endif
2479 * Analog playback callbacks
2481 static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
2482 struct hda_codec *codec,
2483 struct snd_pcm_substream *substream)
2485 struct alc_spec *spec = codec->spec;
2486 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2487 hinfo);
2490 static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
2491 struct hda_codec *codec,
2492 unsigned int stream_tag,
2493 unsigned int format,
2494 struct snd_pcm_substream *substream)
2496 struct alc_spec *spec = codec->spec;
2497 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2498 stream_tag, format, substream);
2501 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
2502 struct hda_codec *codec,
2503 struct snd_pcm_substream *substream)
2505 struct alc_spec *spec = codec->spec;
2506 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2510 * Digital out
2512 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
2513 struct hda_codec *codec,
2514 struct snd_pcm_substream *substream)
2516 struct alc_spec *spec = codec->spec;
2517 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2520 static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
2521 struct hda_codec *codec,
2522 unsigned int stream_tag,
2523 unsigned int format,
2524 struct snd_pcm_substream *substream)
2526 struct alc_spec *spec = codec->spec;
2527 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2528 stream_tag, format, substream);
2531 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
2532 struct hda_codec *codec,
2533 struct snd_pcm_substream *substream)
2535 struct alc_spec *spec = codec->spec;
2536 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2540 * Analog capture
2542 static int alc880_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
2543 struct hda_codec *codec,
2544 unsigned int stream_tag,
2545 unsigned int format,
2546 struct snd_pcm_substream *substream)
2548 struct alc_spec *spec = codec->spec;
2550 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
2551 stream_tag, 0, format);
2552 return 0;
2555 static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
2556 struct hda_codec *codec,
2557 struct snd_pcm_substream *substream)
2559 struct alc_spec *spec = codec->spec;
2561 snd_hda_codec_cleanup_stream(codec,
2562 spec->adc_nids[substream->number + 1]);
2563 return 0;
2569 static struct hda_pcm_stream alc880_pcm_analog_playback = {
2570 .substreams = 1,
2571 .channels_min = 2,
2572 .channels_max = 8,
2573 /* NID is set in alc_build_pcms */
2574 .ops = {
2575 .open = alc880_playback_pcm_open,
2576 .prepare = alc880_playback_pcm_prepare,
2577 .cleanup = alc880_playback_pcm_cleanup
2581 static struct hda_pcm_stream alc880_pcm_analog_capture = {
2582 .substreams = 1,
2583 .channels_min = 2,
2584 .channels_max = 2,
2585 /* NID is set in alc_build_pcms */
2588 static struct hda_pcm_stream alc880_pcm_analog_alt_playback = {
2589 .substreams = 1,
2590 .channels_min = 2,
2591 .channels_max = 2,
2592 /* NID is set in alc_build_pcms */
2595 static struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
2596 .substreams = 2, /* can be overridden */
2597 .channels_min = 2,
2598 .channels_max = 2,
2599 /* NID is set in alc_build_pcms */
2600 .ops = {
2601 .prepare = alc880_alt_capture_pcm_prepare,
2602 .cleanup = alc880_alt_capture_pcm_cleanup
2606 static struct hda_pcm_stream alc880_pcm_digital_playback = {
2607 .substreams = 1,
2608 .channels_min = 2,
2609 .channels_max = 2,
2610 /* NID is set in alc_build_pcms */
2611 .ops = {
2612 .open = alc880_dig_playback_pcm_open,
2613 .close = alc880_dig_playback_pcm_close,
2614 .prepare = alc880_dig_playback_pcm_prepare
2618 static struct hda_pcm_stream alc880_pcm_digital_capture = {
2619 .substreams = 1,
2620 .channels_min = 2,
2621 .channels_max = 2,
2622 /* NID is set in alc_build_pcms */
2625 /* Used by alc_build_pcms to flag that a PCM has no playback stream */
2626 static struct hda_pcm_stream alc_pcm_null_stream = {
2627 .substreams = 0,
2628 .channels_min = 0,
2629 .channels_max = 0,
2632 static int alc_build_pcms(struct hda_codec *codec)
2634 struct alc_spec *spec = codec->spec;
2635 struct hda_pcm *info = spec->pcm_rec;
2636 int i;
2638 codec->num_pcms = 1;
2639 codec->pcm_info = info;
2641 info->name = spec->stream_name_analog;
2642 if (spec->stream_analog_playback) {
2643 snd_assert(spec->multiout.dac_nids, return -EINVAL);
2644 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
2645 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2647 if (spec->stream_analog_capture) {
2648 snd_assert(spec->adc_nids, return -EINVAL);
2649 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
2650 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2653 if (spec->channel_mode) {
2654 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2655 for (i = 0; i < spec->num_channel_mode; i++) {
2656 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2657 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2662 /* SPDIF for stream index #1 */
2663 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
2664 codec->num_pcms = 2;
2665 info = spec->pcm_rec + 1;
2666 info->name = spec->stream_name_digital;
2667 info->pcm_type = HDA_PCM_TYPE_SPDIF;
2668 if (spec->multiout.dig_out_nid &&
2669 spec->stream_digital_playback) {
2670 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
2671 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2673 if (spec->dig_in_nid &&
2674 spec->stream_digital_capture) {
2675 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
2676 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2680 /* If the use of more than one ADC is requested for the current
2681 * model, configure a second analog capture-only PCM.
2683 /* Additional Analaog capture for index #2 */
2684 if ((spec->alt_dac_nid && spec->stream_analog_alt_playback) ||
2685 (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture)) {
2686 codec->num_pcms = 3;
2687 info = spec->pcm_rec + 2;
2688 info->name = spec->stream_name_analog;
2689 if (spec->alt_dac_nid) {
2690 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2691 *spec->stream_analog_alt_playback;
2692 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2693 spec->alt_dac_nid;
2694 } else {
2695 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2696 alc_pcm_null_stream;
2697 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2699 if (spec->num_adc_nids > 1) {
2700 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2701 *spec->stream_analog_alt_capture;
2702 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2703 spec->adc_nids[1];
2704 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2705 spec->num_adc_nids - 1;
2706 } else {
2707 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2708 alc_pcm_null_stream;
2709 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
2713 return 0;
2716 static void alc_free(struct hda_codec *codec)
2718 struct alc_spec *spec = codec->spec;
2719 unsigned int i;
2721 if (!spec)
2722 return;
2724 if (spec->kctl_alloc) {
2725 for (i = 0; i < spec->num_kctl_used; i++)
2726 kfree(spec->kctl_alloc[i].name);
2727 kfree(spec->kctl_alloc);
2729 kfree(spec);
2730 codec->spec = NULL; /* to be sure */
2733 #ifdef SND_HDA_NEEDS_RESUME
2734 static void store_pin_configs(struct hda_codec *codec)
2736 struct alc_spec *spec = codec->spec;
2737 hda_nid_t nid, end_nid;
2739 end_nid = codec->start_nid + codec->num_nodes;
2740 for (nid = codec->start_nid; nid < end_nid; nid++) {
2741 unsigned int wid_caps = get_wcaps(codec, nid);
2742 unsigned int wid_type =
2743 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
2744 if (wid_type != AC_WID_PIN)
2745 continue;
2746 if (spec->num_pins >= ARRAY_SIZE(spec->pin_nids))
2747 break;
2748 spec->pin_nids[spec->num_pins] = nid;
2749 spec->pin_cfgs[spec->num_pins] =
2750 snd_hda_codec_read(codec, nid, 0,
2751 AC_VERB_GET_CONFIG_DEFAULT, 0);
2752 spec->num_pins++;
2756 static void resume_pin_configs(struct hda_codec *codec)
2758 struct alc_spec *spec = codec->spec;
2759 int i;
2761 for (i = 0; i < spec->num_pins; i++) {
2762 hda_nid_t pin_nid = spec->pin_nids[i];
2763 unsigned int pin_config = spec->pin_cfgs[i];
2764 snd_hda_codec_write(codec, pin_nid, 0,
2765 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
2766 pin_config & 0x000000ff);
2767 snd_hda_codec_write(codec, pin_nid, 0,
2768 AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
2769 (pin_config & 0x0000ff00) >> 8);
2770 snd_hda_codec_write(codec, pin_nid, 0,
2771 AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
2772 (pin_config & 0x00ff0000) >> 16);
2773 snd_hda_codec_write(codec, pin_nid, 0,
2774 AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
2775 pin_config >> 24);
2779 static int alc_resume(struct hda_codec *codec)
2781 resume_pin_configs(codec);
2782 codec->patch_ops.init(codec);
2783 snd_hda_codec_resume_amp(codec);
2784 snd_hda_codec_resume_cache(codec);
2785 return 0;
2787 #else
2788 #define store_pin_configs(codec)
2789 #endif
2793 static struct hda_codec_ops alc_patch_ops = {
2794 .build_controls = alc_build_controls,
2795 .build_pcms = alc_build_pcms,
2796 .init = alc_init,
2797 .free = alc_free,
2798 .unsol_event = alc_unsol_event,
2799 #ifdef SND_HDA_NEEDS_RESUME
2800 .resume = alc_resume,
2801 #endif
2802 #ifdef CONFIG_SND_HDA_POWER_SAVE
2803 .check_power_status = alc_check_power_status,
2804 #endif
2809 * Test configuration for debugging
2811 * Almost all inputs/outputs are enabled. I/O pins can be configured via
2812 * enum controls.
2814 #ifdef CONFIG_SND_DEBUG
2815 static hda_nid_t alc880_test_dac_nids[4] = {
2816 0x02, 0x03, 0x04, 0x05
2819 static struct hda_input_mux alc880_test_capture_source = {
2820 .num_items = 7,
2821 .items = {
2822 { "In-1", 0x0 },
2823 { "In-2", 0x1 },
2824 { "In-3", 0x2 },
2825 { "In-4", 0x3 },
2826 { "CD", 0x4 },
2827 { "Front", 0x5 },
2828 { "Surround", 0x6 },
2832 static struct hda_channel_mode alc880_test_modes[4] = {
2833 { 2, NULL },
2834 { 4, NULL },
2835 { 6, NULL },
2836 { 8, NULL },
2839 static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
2840 struct snd_ctl_elem_info *uinfo)
2842 static char *texts[] = {
2843 "N/A", "Line Out", "HP Out",
2844 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
2846 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2847 uinfo->count = 1;
2848 uinfo->value.enumerated.items = 8;
2849 if (uinfo->value.enumerated.item >= 8)
2850 uinfo->value.enumerated.item = 7;
2851 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2852 return 0;
2855 static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
2856 struct snd_ctl_elem_value *ucontrol)
2858 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2859 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2860 unsigned int pin_ctl, item = 0;
2862 pin_ctl = snd_hda_codec_read(codec, nid, 0,
2863 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2864 if (pin_ctl & AC_PINCTL_OUT_EN) {
2865 if (pin_ctl & AC_PINCTL_HP_EN)
2866 item = 2;
2867 else
2868 item = 1;
2869 } else if (pin_ctl & AC_PINCTL_IN_EN) {
2870 switch (pin_ctl & AC_PINCTL_VREFEN) {
2871 case AC_PINCTL_VREF_HIZ: item = 3; break;
2872 case AC_PINCTL_VREF_50: item = 4; break;
2873 case AC_PINCTL_VREF_GRD: item = 5; break;
2874 case AC_PINCTL_VREF_80: item = 6; break;
2875 case AC_PINCTL_VREF_100: item = 7; break;
2878 ucontrol->value.enumerated.item[0] = item;
2879 return 0;
2882 static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
2883 struct snd_ctl_elem_value *ucontrol)
2885 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2886 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2887 static unsigned int ctls[] = {
2888 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
2889 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
2890 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
2891 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
2892 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
2893 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
2895 unsigned int old_ctl, new_ctl;
2897 old_ctl = snd_hda_codec_read(codec, nid, 0,
2898 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2899 new_ctl = ctls[ucontrol->value.enumerated.item[0]];
2900 if (old_ctl != new_ctl) {
2901 int val;
2902 snd_hda_codec_write_cache(codec, nid, 0,
2903 AC_VERB_SET_PIN_WIDGET_CONTROL,
2904 new_ctl);
2905 val = ucontrol->value.enumerated.item[0] >= 3 ?
2906 HDA_AMP_MUTE : 0;
2907 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2908 HDA_AMP_MUTE, val);
2909 return 1;
2911 return 0;
2914 static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
2915 struct snd_ctl_elem_info *uinfo)
2917 static char *texts[] = {
2918 "Front", "Surround", "CLFE", "Side"
2920 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2921 uinfo->count = 1;
2922 uinfo->value.enumerated.items = 4;
2923 if (uinfo->value.enumerated.item >= 4)
2924 uinfo->value.enumerated.item = 3;
2925 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2926 return 0;
2929 static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
2930 struct snd_ctl_elem_value *ucontrol)
2932 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2933 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2934 unsigned int sel;
2936 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
2937 ucontrol->value.enumerated.item[0] = sel & 3;
2938 return 0;
2941 static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
2942 struct snd_ctl_elem_value *ucontrol)
2944 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2945 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2946 unsigned int sel;
2948 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
2949 if (ucontrol->value.enumerated.item[0] != sel) {
2950 sel = ucontrol->value.enumerated.item[0] & 3;
2951 snd_hda_codec_write_cache(codec, nid, 0,
2952 AC_VERB_SET_CONNECT_SEL, sel);
2953 return 1;
2955 return 0;
2958 #define PIN_CTL_TEST(xname,nid) { \
2959 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2960 .name = xname, \
2961 .info = alc_test_pin_ctl_info, \
2962 .get = alc_test_pin_ctl_get, \
2963 .put = alc_test_pin_ctl_put, \
2964 .private_value = nid \
2967 #define PIN_SRC_TEST(xname,nid) { \
2968 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2969 .name = xname, \
2970 .info = alc_test_pin_src_info, \
2971 .get = alc_test_pin_src_get, \
2972 .put = alc_test_pin_src_put, \
2973 .private_value = nid \
2976 static struct snd_kcontrol_new alc880_test_mixer[] = {
2977 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2978 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2979 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
2980 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2981 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2982 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2983 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
2984 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
2985 PIN_CTL_TEST("Front Pin Mode", 0x14),
2986 PIN_CTL_TEST("Surround Pin Mode", 0x15),
2987 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
2988 PIN_CTL_TEST("Side Pin Mode", 0x17),
2989 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
2990 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
2991 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
2992 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
2993 PIN_SRC_TEST("In-1 Pin Source", 0x18),
2994 PIN_SRC_TEST("In-2 Pin Source", 0x19),
2995 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
2996 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
2997 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
2998 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
2999 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
3000 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
3001 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
3002 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
3003 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
3004 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
3005 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
3006 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
3008 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3009 .name = "Channel Mode",
3010 .info = alc_ch_mode_info,
3011 .get = alc_ch_mode_get,
3012 .put = alc_ch_mode_put,
3014 { } /* end */
3017 static struct hda_verb alc880_test_init_verbs[] = {
3018 /* Unmute inputs of 0x0c - 0x0f */
3019 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3020 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3021 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3022 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3023 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3024 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3025 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3026 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3027 /* Vol output for 0x0c-0x0f */
3028 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3029 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3030 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3031 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3032 /* Set output pins 0x14-0x17 */
3033 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3034 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3035 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3036 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3037 /* Unmute output pins 0x14-0x17 */
3038 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3039 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3040 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3041 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3042 /* Set input pins 0x18-0x1c */
3043 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3044 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3045 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3046 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3047 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3048 /* Mute input pins 0x18-0x1b */
3049 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3050 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3051 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3052 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3053 /* ADC set up */
3054 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3055 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3056 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3057 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3058 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3059 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3060 /* Analog input/passthru */
3061 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3062 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3063 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3064 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3065 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3068 #endif
3073 static const char *alc880_models[ALC880_MODEL_LAST] = {
3074 [ALC880_3ST] = "3stack",
3075 [ALC880_TCL_S700] = "tcl",
3076 [ALC880_3ST_DIG] = "3stack-digout",
3077 [ALC880_CLEVO] = "clevo",
3078 [ALC880_5ST] = "5stack",
3079 [ALC880_5ST_DIG] = "5stack-digout",
3080 [ALC880_W810] = "w810",
3081 [ALC880_Z71V] = "z71v",
3082 [ALC880_6ST] = "6stack",
3083 [ALC880_6ST_DIG] = "6stack-digout",
3084 [ALC880_ASUS] = "asus",
3085 [ALC880_ASUS_W1V] = "asus-w1v",
3086 [ALC880_ASUS_DIG] = "asus-dig",
3087 [ALC880_ASUS_DIG2] = "asus-dig2",
3088 [ALC880_UNIWILL_DIG] = "uniwill",
3089 [ALC880_UNIWILL_P53] = "uniwill-p53",
3090 [ALC880_FUJITSU] = "fujitsu",
3091 [ALC880_F1734] = "F1734",
3092 [ALC880_LG] = "lg",
3093 [ALC880_LG_LW] = "lg-lw",
3094 [ALC880_MEDION_RIM] = "medion",
3095 #ifdef CONFIG_SND_DEBUG
3096 [ALC880_TEST] = "test",
3097 #endif
3098 [ALC880_AUTO] = "auto",
3101 static struct snd_pci_quirk alc880_cfg_tbl[] = {
3102 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
3103 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
3104 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
3105 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
3106 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
3107 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
3108 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
3109 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
3110 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
3111 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
3112 SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
3113 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
3114 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
3115 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
3116 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
3117 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
3118 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
3119 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
3120 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
3121 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
3122 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
3123 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
3124 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
3125 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
3126 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
3127 SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS), /* default ASUS */
3128 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
3129 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
3130 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
3131 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
3132 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
3133 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
3134 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
3135 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
3136 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
3137 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
3138 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
3139 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
3140 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
3141 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
3142 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),
3143 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
3144 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
3145 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
3146 SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
3147 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
3148 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
3149 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
3150 SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
3151 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),
3152 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
3153 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
3154 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
3155 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
3156 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
3157 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
3158 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
3159 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
3160 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
3161 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
3162 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
3163 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
3164 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
3165 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
3166 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
3167 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
3168 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
3169 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
3170 SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST), /* default Intel */
3171 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
3172 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
3177 * ALC880 codec presets
3179 static struct alc_config_preset alc880_presets[] = {
3180 [ALC880_3ST] = {
3181 .mixers = { alc880_three_stack_mixer },
3182 .init_verbs = { alc880_volume_init_verbs,
3183 alc880_pin_3stack_init_verbs },
3184 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
3185 .dac_nids = alc880_dac_nids,
3186 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
3187 .channel_mode = alc880_threestack_modes,
3188 .need_dac_fix = 1,
3189 .input_mux = &alc880_capture_source,
3191 [ALC880_3ST_DIG] = {
3192 .mixers = { alc880_three_stack_mixer },
3193 .init_verbs = { alc880_volume_init_verbs,
3194 alc880_pin_3stack_init_verbs },
3195 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
3196 .dac_nids = alc880_dac_nids,
3197 .dig_out_nid = ALC880_DIGOUT_NID,
3198 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
3199 .channel_mode = alc880_threestack_modes,
3200 .need_dac_fix = 1,
3201 .input_mux = &alc880_capture_source,
3203 [ALC880_TCL_S700] = {
3204 .mixers = { alc880_tcl_s700_mixer },
3205 .init_verbs = { alc880_volume_init_verbs,
3206 alc880_pin_tcl_S700_init_verbs,
3207 alc880_gpio2_init_verbs },
3208 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
3209 .dac_nids = alc880_dac_nids,
3210 .hp_nid = 0x03,
3211 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
3212 .channel_mode = alc880_2_jack_modes,
3213 .input_mux = &alc880_capture_source,
3215 [ALC880_5ST] = {
3216 .mixers = { alc880_three_stack_mixer,
3217 alc880_five_stack_mixer},
3218 .init_verbs = { alc880_volume_init_verbs,
3219 alc880_pin_5stack_init_verbs },
3220 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
3221 .dac_nids = alc880_dac_nids,
3222 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
3223 .channel_mode = alc880_fivestack_modes,
3224 .input_mux = &alc880_capture_source,
3226 [ALC880_5ST_DIG] = {
3227 .mixers = { alc880_three_stack_mixer,
3228 alc880_five_stack_mixer },
3229 .init_verbs = { alc880_volume_init_verbs,
3230 alc880_pin_5stack_init_verbs },
3231 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
3232 .dac_nids = alc880_dac_nids,
3233 .dig_out_nid = ALC880_DIGOUT_NID,
3234 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
3235 .channel_mode = alc880_fivestack_modes,
3236 .input_mux = &alc880_capture_source,
3238 [ALC880_6ST] = {
3239 .mixers = { alc880_six_stack_mixer },
3240 .init_verbs = { alc880_volume_init_verbs,
3241 alc880_pin_6stack_init_verbs },
3242 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
3243 .dac_nids = alc880_6st_dac_nids,
3244 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
3245 .channel_mode = alc880_sixstack_modes,
3246 .input_mux = &alc880_6stack_capture_source,
3248 [ALC880_6ST_DIG] = {
3249 .mixers = { alc880_six_stack_mixer },
3250 .init_verbs = { alc880_volume_init_verbs,
3251 alc880_pin_6stack_init_verbs },
3252 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
3253 .dac_nids = alc880_6st_dac_nids,
3254 .dig_out_nid = ALC880_DIGOUT_NID,
3255 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
3256 .channel_mode = alc880_sixstack_modes,
3257 .input_mux = &alc880_6stack_capture_source,
3259 [ALC880_W810] = {
3260 .mixers = { alc880_w810_base_mixer },
3261 .init_verbs = { alc880_volume_init_verbs,
3262 alc880_pin_w810_init_verbs,
3263 alc880_gpio2_init_verbs },
3264 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
3265 .dac_nids = alc880_w810_dac_nids,
3266 .dig_out_nid = ALC880_DIGOUT_NID,
3267 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
3268 .channel_mode = alc880_w810_modes,
3269 .input_mux = &alc880_capture_source,
3271 [ALC880_Z71V] = {
3272 .mixers = { alc880_z71v_mixer },
3273 .init_verbs = { alc880_volume_init_verbs,
3274 alc880_pin_z71v_init_verbs },
3275 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
3276 .dac_nids = alc880_z71v_dac_nids,
3277 .dig_out_nid = ALC880_DIGOUT_NID,
3278 .hp_nid = 0x03,
3279 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
3280 .channel_mode = alc880_2_jack_modes,
3281 .input_mux = &alc880_capture_source,
3283 [ALC880_F1734] = {
3284 .mixers = { alc880_f1734_mixer },
3285 .init_verbs = { alc880_volume_init_verbs,
3286 alc880_pin_f1734_init_verbs },
3287 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
3288 .dac_nids = alc880_f1734_dac_nids,
3289 .hp_nid = 0x02,
3290 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
3291 .channel_mode = alc880_2_jack_modes,
3292 .input_mux = &alc880_f1734_capture_source,
3293 .unsol_event = alc880_uniwill_p53_unsol_event,
3294 .init_hook = alc880_uniwill_p53_hp_automute,
3296 [ALC880_ASUS] = {
3297 .mixers = { alc880_asus_mixer },
3298 .init_verbs = { alc880_volume_init_verbs,
3299 alc880_pin_asus_init_verbs,
3300 alc880_gpio1_init_verbs },
3301 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
3302 .dac_nids = alc880_asus_dac_nids,
3303 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
3304 .channel_mode = alc880_asus_modes,
3305 .need_dac_fix = 1,
3306 .input_mux = &alc880_capture_source,
3308 [ALC880_ASUS_DIG] = {
3309 .mixers = { alc880_asus_mixer },
3310 .init_verbs = { alc880_volume_init_verbs,
3311 alc880_pin_asus_init_verbs,
3312 alc880_gpio1_init_verbs },
3313 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
3314 .dac_nids = alc880_asus_dac_nids,
3315 .dig_out_nid = ALC880_DIGOUT_NID,
3316 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
3317 .channel_mode = alc880_asus_modes,
3318 .need_dac_fix = 1,
3319 .input_mux = &alc880_capture_source,
3321 [ALC880_ASUS_DIG2] = {
3322 .mixers = { alc880_asus_mixer },
3323 .init_verbs = { alc880_volume_init_verbs,
3324 alc880_pin_asus_init_verbs,
3325 alc880_gpio2_init_verbs }, /* use GPIO2 */
3326 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
3327 .dac_nids = alc880_asus_dac_nids,
3328 .dig_out_nid = ALC880_DIGOUT_NID,
3329 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
3330 .channel_mode = alc880_asus_modes,
3331 .need_dac_fix = 1,
3332 .input_mux = &alc880_capture_source,
3334 [ALC880_ASUS_W1V] = {
3335 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
3336 .init_verbs = { alc880_volume_init_verbs,
3337 alc880_pin_asus_init_verbs,
3338 alc880_gpio1_init_verbs },
3339 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
3340 .dac_nids = alc880_asus_dac_nids,
3341 .dig_out_nid = ALC880_DIGOUT_NID,
3342 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
3343 .channel_mode = alc880_asus_modes,
3344 .need_dac_fix = 1,
3345 .input_mux = &alc880_capture_source,
3347 [ALC880_UNIWILL_DIG] = {
3348 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
3349 .init_verbs = { alc880_volume_init_verbs,
3350 alc880_pin_asus_init_verbs },
3351 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
3352 .dac_nids = alc880_asus_dac_nids,
3353 .dig_out_nid = ALC880_DIGOUT_NID,
3354 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
3355 .channel_mode = alc880_asus_modes,
3356 .need_dac_fix = 1,
3357 .input_mux = &alc880_capture_source,
3359 [ALC880_UNIWILL] = {
3360 .mixers = { alc880_uniwill_mixer },
3361 .init_verbs = { alc880_volume_init_verbs,
3362 alc880_uniwill_init_verbs },
3363 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
3364 .dac_nids = alc880_asus_dac_nids,
3365 .dig_out_nid = ALC880_DIGOUT_NID,
3366 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
3367 .channel_mode = alc880_threestack_modes,
3368 .need_dac_fix = 1,
3369 .input_mux = &alc880_capture_source,
3370 .unsol_event = alc880_uniwill_unsol_event,
3371 .init_hook = alc880_uniwill_automute,
3373 [ALC880_UNIWILL_P53] = {
3374 .mixers = { alc880_uniwill_p53_mixer },
3375 .init_verbs = { alc880_volume_init_verbs,
3376 alc880_uniwill_p53_init_verbs },
3377 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
3378 .dac_nids = alc880_asus_dac_nids,
3379 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
3380 .channel_mode = alc880_threestack_modes,
3381 .input_mux = &alc880_capture_source,
3382 .unsol_event = alc880_uniwill_p53_unsol_event,
3383 .init_hook = alc880_uniwill_p53_hp_automute,
3385 [ALC880_FUJITSU] = {
3386 .mixers = { alc880_fujitsu_mixer,
3387 alc880_pcbeep_mixer, },
3388 .init_verbs = { alc880_volume_init_verbs,
3389 alc880_uniwill_p53_init_verbs,
3390 alc880_beep_init_verbs },
3391 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
3392 .dac_nids = alc880_dac_nids,
3393 .dig_out_nid = ALC880_DIGOUT_NID,
3394 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
3395 .channel_mode = alc880_2_jack_modes,
3396 .input_mux = &alc880_capture_source,
3397 .unsol_event = alc880_uniwill_p53_unsol_event,
3398 .init_hook = alc880_uniwill_p53_hp_automute,
3400 [ALC880_CLEVO] = {
3401 .mixers = { alc880_three_stack_mixer },
3402 .init_verbs = { alc880_volume_init_verbs,
3403 alc880_pin_clevo_init_verbs },
3404 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
3405 .dac_nids = alc880_dac_nids,
3406 .hp_nid = 0x03,
3407 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
3408 .channel_mode = alc880_threestack_modes,
3409 .need_dac_fix = 1,
3410 .input_mux = &alc880_capture_source,
3412 [ALC880_LG] = {
3413 .mixers = { alc880_lg_mixer },
3414 .init_verbs = { alc880_volume_init_verbs,
3415 alc880_lg_init_verbs },
3416 .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
3417 .dac_nids = alc880_lg_dac_nids,
3418 .dig_out_nid = ALC880_DIGOUT_NID,
3419 .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
3420 .channel_mode = alc880_lg_ch_modes,
3421 .need_dac_fix = 1,
3422 .input_mux = &alc880_lg_capture_source,
3423 .unsol_event = alc880_lg_unsol_event,
3424 .init_hook = alc880_lg_automute,
3425 #ifdef CONFIG_SND_HDA_POWER_SAVE
3426 .loopbacks = alc880_lg_loopbacks,
3427 #endif
3429 [ALC880_LG_LW] = {
3430 .mixers = { alc880_lg_lw_mixer },
3431 .init_verbs = { alc880_volume_init_verbs,
3432 alc880_lg_lw_init_verbs },
3433 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
3434 .dac_nids = alc880_dac_nids,
3435 .dig_out_nid = ALC880_DIGOUT_NID,
3436 .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
3437 .channel_mode = alc880_lg_lw_modes,
3438 .input_mux = &alc880_lg_lw_capture_source,
3439 .unsol_event = alc880_lg_lw_unsol_event,
3440 .init_hook = alc880_lg_lw_automute,
3442 [ALC880_MEDION_RIM] = {
3443 .mixers = { alc880_medion_rim_mixer },
3444 .init_verbs = { alc880_volume_init_verbs,
3445 alc880_medion_rim_init_verbs,
3446 alc_gpio2_init_verbs },
3447 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
3448 .dac_nids = alc880_dac_nids,
3449 .dig_out_nid = ALC880_DIGOUT_NID,
3450 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
3451 .channel_mode = alc880_2_jack_modes,
3452 .input_mux = &alc880_medion_rim_capture_source,
3453 .unsol_event = alc880_medion_rim_unsol_event,
3454 .init_hook = alc880_medion_rim_automute,
3456 #ifdef CONFIG_SND_DEBUG
3457 [ALC880_TEST] = {
3458 .mixers = { alc880_test_mixer },
3459 .init_verbs = { alc880_test_init_verbs },
3460 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
3461 .dac_nids = alc880_test_dac_nids,
3462 .dig_out_nid = ALC880_DIGOUT_NID,
3463 .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
3464 .channel_mode = alc880_test_modes,
3465 .input_mux = &alc880_test_capture_source,
3467 #endif
3471 * Automatic parse of I/O pins from the BIOS configuration
3474 #define NUM_CONTROL_ALLOC 32
3475 #define NUM_VERB_ALLOC 32
3477 enum {
3478 ALC_CTL_WIDGET_VOL,
3479 ALC_CTL_WIDGET_MUTE,
3480 ALC_CTL_BIND_MUTE,
3482 static struct snd_kcontrol_new alc880_control_templates[] = {
3483 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
3484 HDA_CODEC_MUTE(NULL, 0, 0, 0),
3485 HDA_BIND_MUTE(NULL, 0, 0, 0),
3488 /* add dynamic controls */
3489 static int add_control(struct alc_spec *spec, int type, const char *name,
3490 unsigned long val)
3492 struct snd_kcontrol_new *knew;
3494 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
3495 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
3497 /* array + terminator */
3498 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
3499 if (!knew)
3500 return -ENOMEM;
3501 if (spec->kctl_alloc) {
3502 memcpy(knew, spec->kctl_alloc,
3503 sizeof(*knew) * spec->num_kctl_alloc);
3504 kfree(spec->kctl_alloc);
3506 spec->kctl_alloc = knew;
3507 spec->num_kctl_alloc = num;
3510 knew = &spec->kctl_alloc[spec->num_kctl_used];
3511 *knew = alc880_control_templates[type];
3512 knew->name = kstrdup(name, GFP_KERNEL);
3513 if (!knew->name)
3514 return -ENOMEM;
3515 knew->private_value = val;
3516 spec->num_kctl_used++;
3517 return 0;
3520 #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
3521 #define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
3522 #define alc880_is_multi_pin(nid) ((nid) >= 0x18)
3523 #define alc880_multi_pin_idx(nid) ((nid) - 0x18)
3524 #define alc880_is_input_pin(nid) ((nid) >= 0x18)
3525 #define alc880_input_pin_idx(nid) ((nid) - 0x18)
3526 #define alc880_idx_to_dac(nid) ((nid) + 0x02)
3527 #define alc880_dac_to_idx(nid) ((nid) - 0x02)
3528 #define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
3529 #define alc880_idx_to_selector(nid) ((nid) + 0x10)
3530 #define ALC880_PIN_CD_NID 0x1c
3532 /* fill in the dac_nids table from the parsed pin configuration */
3533 static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
3534 const struct auto_pin_cfg *cfg)
3536 hda_nid_t nid;
3537 int assigned[4];
3538 int i, j;
3540 memset(assigned, 0, sizeof(assigned));
3541 spec->multiout.dac_nids = spec->private_dac_nids;
3543 /* check the pins hardwired to audio widget */
3544 for (i = 0; i < cfg->line_outs; i++) {
3545 nid = cfg->line_out_pins[i];
3546 if (alc880_is_fixed_pin(nid)) {
3547 int idx = alc880_fixed_pin_idx(nid);
3548 spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
3549 assigned[idx] = 1;
3552 /* left pins can be connect to any audio widget */
3553 for (i = 0; i < cfg->line_outs; i++) {
3554 nid = cfg->line_out_pins[i];
3555 if (alc880_is_fixed_pin(nid))
3556 continue;
3557 /* search for an empty channel */
3558 for (j = 0; j < cfg->line_outs; j++) {
3559 if (!assigned[j]) {
3560 spec->multiout.dac_nids[i] =
3561 alc880_idx_to_dac(j);
3562 assigned[j] = 1;
3563 break;
3567 spec->multiout.num_dacs = cfg->line_outs;
3568 return 0;
3571 /* add playback controls from the parsed DAC table */
3572 static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
3573 const struct auto_pin_cfg *cfg)
3575 char name[32];
3576 static const char *chname[4] = {
3577 "Front", "Surround", NULL /*CLFE*/, "Side"
3579 hda_nid_t nid;
3580 int i, err;
3582 for (i = 0; i < cfg->line_outs; i++) {
3583 if (!spec->multiout.dac_nids[i])
3584 continue;
3585 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
3586 if (i == 2) {
3587 /* Center/LFE */
3588 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3589 "Center Playback Volume",
3590 HDA_COMPOSE_AMP_VAL(nid, 1, 0,
3591 HDA_OUTPUT));
3592 if (err < 0)
3593 return err;
3594 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3595 "LFE Playback Volume",
3596 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
3597 HDA_OUTPUT));
3598 if (err < 0)
3599 return err;
3600 err = add_control(spec, ALC_CTL_BIND_MUTE,
3601 "Center Playback Switch",
3602 HDA_COMPOSE_AMP_VAL(nid, 1, 2,
3603 HDA_INPUT));
3604 if (err < 0)
3605 return err;
3606 err = add_control(spec, ALC_CTL_BIND_MUTE,
3607 "LFE Playback Switch",
3608 HDA_COMPOSE_AMP_VAL(nid, 2, 2,
3609 HDA_INPUT));
3610 if (err < 0)
3611 return err;
3612 } else {
3613 sprintf(name, "%s Playback Volume", chname[i]);
3614 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
3615 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
3616 HDA_OUTPUT));
3617 if (err < 0)
3618 return err;
3619 sprintf(name, "%s Playback Switch", chname[i]);
3620 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
3621 HDA_COMPOSE_AMP_VAL(nid, 3, 2,
3622 HDA_INPUT));
3623 if (err < 0)
3624 return err;
3627 return 0;
3630 /* add playback controls for speaker and HP outputs */
3631 static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
3632 const char *pfx)
3634 hda_nid_t nid;
3635 int err;
3636 char name[32];
3638 if (!pin)
3639 return 0;
3641 if (alc880_is_fixed_pin(pin)) {
3642 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
3643 /* specify the DAC as the extra output */
3644 if (!spec->multiout.hp_nid)
3645 spec->multiout.hp_nid = nid;
3646 else
3647 spec->multiout.extra_out_nid[0] = nid;
3648 /* control HP volume/switch on the output mixer amp */
3649 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
3650 sprintf(name, "%s Playback Volume", pfx);
3651 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
3652 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
3653 if (err < 0)
3654 return err;
3655 sprintf(name, "%s Playback Switch", pfx);
3656 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
3657 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
3658 if (err < 0)
3659 return err;
3660 } else if (alc880_is_multi_pin(pin)) {
3661 /* set manual connection */
3662 /* we have only a switch on HP-out PIN */
3663 sprintf(name, "%s Playback Switch", pfx);
3664 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
3665 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3666 if (err < 0)
3667 return err;
3669 return 0;
3672 /* create input playback/capture controls for the given pin */
3673 static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
3674 const char *ctlname,
3675 int idx, hda_nid_t mix_nid)
3677 char name[32];
3678 int err;
3680 sprintf(name, "%s Playback Volume", ctlname);
3681 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
3682 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
3683 if (err < 0)
3684 return err;
3685 sprintf(name, "%s Playback Switch", ctlname);
3686 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
3687 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
3688 if (err < 0)
3689 return err;
3690 return 0;
3693 /* create playback/capture controls for input pins */
3694 static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
3695 const struct auto_pin_cfg *cfg)
3697 struct hda_input_mux *imux = &spec->private_imux;
3698 int i, err, idx;
3700 for (i = 0; i < AUTO_PIN_LAST; i++) {
3701 if (alc880_is_input_pin(cfg->input_pins[i])) {
3702 idx = alc880_input_pin_idx(cfg->input_pins[i]);
3703 err = new_analog_input(spec, cfg->input_pins[i],
3704 auto_pin_cfg_labels[i],
3705 idx, 0x0b);
3706 if (err < 0)
3707 return err;
3708 imux->items[imux->num_items].label =
3709 auto_pin_cfg_labels[i];
3710 imux->items[imux->num_items].index =
3711 alc880_input_pin_idx(cfg->input_pins[i]);
3712 imux->num_items++;
3715 return 0;
3718 static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
3719 unsigned int pin_type)
3721 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3722 pin_type);
3723 /* unmute pin */
3724 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3725 AMP_OUT_UNMUTE);
3728 static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
3729 hda_nid_t nid, int pin_type,
3730 int dac_idx)
3732 alc_set_pin_output(codec, nid, pin_type);
3733 /* need the manual connection? */
3734 if (alc880_is_multi_pin(nid)) {
3735 struct alc_spec *spec = codec->spec;
3736 int idx = alc880_multi_pin_idx(nid);
3737 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
3738 AC_VERB_SET_CONNECT_SEL,
3739 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
3743 static int get_pin_type(int line_out_type)
3745 if (line_out_type == AUTO_PIN_HP_OUT)
3746 return PIN_HP;
3747 else
3748 return PIN_OUT;
3751 static void alc880_auto_init_multi_out(struct hda_codec *codec)
3753 struct alc_spec *spec = codec->spec;
3754 int i;
3756 alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
3757 for (i = 0; i < spec->autocfg.line_outs; i++) {
3758 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3759 int pin_type = get_pin_type(spec->autocfg.line_out_type);
3760 alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);
3764 static void alc880_auto_init_extra_out(struct hda_codec *codec)
3766 struct alc_spec *spec = codec->spec;
3767 hda_nid_t pin;
3769 pin = spec->autocfg.speaker_pins[0];
3770 if (pin) /* connect to front */
3771 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
3772 pin = spec->autocfg.hp_pins[0];
3773 if (pin) /* connect to front */
3774 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
3777 static void alc880_auto_init_analog_input(struct hda_codec *codec)
3779 struct alc_spec *spec = codec->spec;
3780 int i;
3782 for (i = 0; i < AUTO_PIN_LAST; i++) {
3783 hda_nid_t nid = spec->autocfg.input_pins[i];
3784 if (alc880_is_input_pin(nid)) {
3785 snd_hda_codec_write(codec, nid, 0,
3786 AC_VERB_SET_PIN_WIDGET_CONTROL,
3787 i <= AUTO_PIN_FRONT_MIC ?
3788 PIN_VREF80 : PIN_IN);
3789 if (nid != ALC880_PIN_CD_NID)
3790 snd_hda_codec_write(codec, nid, 0,
3791 AC_VERB_SET_AMP_GAIN_MUTE,
3792 AMP_OUT_MUTE);
3797 /* parse the BIOS configuration and set up the alc_spec */
3798 /* return 1 if successful, 0 if the proper config is not found,
3799 * or a negative error code
3801 static int alc880_parse_auto_config(struct hda_codec *codec)
3803 struct alc_spec *spec = codec->spec;
3804 int err;
3805 static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3807 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3808 alc880_ignore);
3809 if (err < 0)
3810 return err;
3811 if (!spec->autocfg.line_outs)
3812 return 0; /* can't find valid BIOS pin config */
3814 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
3815 if (err < 0)
3816 return err;
3817 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
3818 if (err < 0)
3819 return err;
3820 err = alc880_auto_create_extra_out(spec,
3821 spec->autocfg.speaker_pins[0],
3822 "Speaker");
3823 if (err < 0)
3824 return err;
3825 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
3826 "Headphone");
3827 if (err < 0)
3828 return err;
3829 err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);
3830 if (err < 0)
3831 return err;
3833 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3835 if (spec->autocfg.dig_out_pin)
3836 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
3837 if (spec->autocfg.dig_in_pin)
3838 spec->dig_in_nid = ALC880_DIGIN_NID;
3840 if (spec->kctl_alloc)
3841 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
3843 spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
3845 spec->num_mux_defs = 1;
3846 spec->input_mux = &spec->private_imux;
3848 store_pin_configs(codec);
3849 return 1;
3852 /* additional initialization for auto-configuration model */
3853 static void alc880_auto_init(struct hda_codec *codec)
3855 struct alc_spec *spec = codec->spec;
3856 alc880_auto_init_multi_out(codec);
3857 alc880_auto_init_extra_out(codec);
3858 alc880_auto_init_analog_input(codec);
3859 if (spec->unsol_event)
3860 alc_sku_automute(codec);
3864 * OK, here we have finally the patch for ALC880
3867 static int patch_alc880(struct hda_codec *codec)
3869 struct alc_spec *spec;
3870 int board_config;
3871 int err;
3873 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3874 if (spec == NULL)
3875 return -ENOMEM;
3877 codec->spec = spec;
3879 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
3880 alc880_models,
3881 alc880_cfg_tbl);
3882 if (board_config < 0) {
3883 printk(KERN_INFO "hda_codec: Unknown model for ALC880, "
3884 "trying auto-probe from BIOS...\n");
3885 board_config = ALC880_AUTO;
3888 if (board_config == ALC880_AUTO) {
3889 /* automatic parse from the BIOS config */
3890 err = alc880_parse_auto_config(codec);
3891 if (err < 0) {
3892 alc_free(codec);
3893 return err;
3894 } else if (!err) {
3895 printk(KERN_INFO
3896 "hda_codec: Cannot set up configuration "
3897 "from BIOS. Using 3-stack mode...\n");
3898 board_config = ALC880_3ST;
3902 if (board_config != ALC880_AUTO)
3903 setup_preset(spec, &alc880_presets[board_config]);
3905 spec->stream_name_analog = "ALC880 Analog";
3906 spec->stream_analog_playback = &alc880_pcm_analog_playback;
3907 spec->stream_analog_capture = &alc880_pcm_analog_capture;
3908 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
3910 spec->stream_name_digital = "ALC880 Digital";
3911 spec->stream_digital_playback = &alc880_pcm_digital_playback;
3912 spec->stream_digital_capture = &alc880_pcm_digital_capture;
3914 if (!spec->adc_nids && spec->input_mux) {
3915 /* check whether NID 0x07 is valid */
3916 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
3917 /* get type */
3918 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
3919 if (wcap != AC_WID_AUD_IN) {
3920 spec->adc_nids = alc880_adc_nids_alt;
3921 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
3922 spec->mixers[spec->num_mixers] =
3923 alc880_capture_alt_mixer;
3924 spec->num_mixers++;
3925 } else {
3926 spec->adc_nids = alc880_adc_nids;
3927 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
3928 spec->mixers[spec->num_mixers] = alc880_capture_mixer;
3929 spec->num_mixers++;
3933 spec->vmaster_nid = 0x0c;
3935 codec->patch_ops = alc_patch_ops;
3936 if (board_config == ALC880_AUTO)
3937 spec->init_hook = alc880_auto_init;
3938 #ifdef CONFIG_SND_HDA_POWER_SAVE
3939 if (!spec->loopback.amplist)
3940 spec->loopback.amplist = alc880_loopbacks;
3941 #endif
3943 return 0;
3948 * ALC260 support
3951 static hda_nid_t alc260_dac_nids[1] = {
3952 /* front */
3953 0x02,
3956 static hda_nid_t alc260_adc_nids[1] = {
3957 /* ADC0 */
3958 0x04,
3961 static hda_nid_t alc260_adc_nids_alt[1] = {
3962 /* ADC1 */
3963 0x05,
3966 static hda_nid_t alc260_hp_adc_nids[2] = {
3967 /* ADC1, 0 */
3968 0x05, 0x04
3971 /* NIDs used when simultaneous access to both ADCs makes sense. Note that
3972 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
3974 static hda_nid_t alc260_dual_adc_nids[2] = {
3975 /* ADC0, ADC1 */
3976 0x04, 0x05
3979 #define ALC260_DIGOUT_NID 0x03
3980 #define ALC260_DIGIN_NID 0x06
3982 static struct hda_input_mux alc260_capture_source = {
3983 .num_items = 4,
3984 .items = {
3985 { "Mic", 0x0 },
3986 { "Front Mic", 0x1 },
3987 { "Line", 0x2 },
3988 { "CD", 0x4 },
3992 /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
3993 * headphone jack and the internal CD lines since these are the only pins at
3994 * which audio can appear. For flexibility, also allow the option of
3995 * recording the mixer output on the second ADC (ADC0 doesn't have a
3996 * connection to the mixer output).
3998 static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
4000 .num_items = 3,
4001 .items = {
4002 { "Mic/Line", 0x0 },
4003 { "CD", 0x4 },
4004 { "Headphone", 0x2 },
4008 .num_items = 4,
4009 .items = {
4010 { "Mic/Line", 0x0 },
4011 { "CD", 0x4 },
4012 { "Headphone", 0x2 },
4013 { "Mixer", 0x5 },
4019 /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
4020 * the Fujitsu S702x, but jacks are marked differently.
4022 static struct hda_input_mux alc260_acer_capture_sources[2] = {
4024 .num_items = 4,
4025 .items = {
4026 { "Mic", 0x0 },
4027 { "Line", 0x2 },
4028 { "CD", 0x4 },
4029 { "Headphone", 0x5 },
4033 .num_items = 5,
4034 .items = {
4035 { "Mic", 0x0 },
4036 { "Line", 0x2 },
4037 { "CD", 0x4 },
4038 { "Headphone", 0x6 },
4039 { "Mixer", 0x5 },
4044 * This is just place-holder, so there's something for alc_build_pcms to look
4045 * at when it calculates the maximum number of channels. ALC260 has no mixer
4046 * element which allows changing the channel mode, so the verb list is
4047 * never used.
4049 static struct hda_channel_mode alc260_modes[1] = {
4050 { 2, NULL },
4054 /* Mixer combinations
4056 * basic: base_output + input + pc_beep + capture
4057 * HP: base_output + input + capture_alt
4058 * HP_3013: hp_3013 + input + capture
4059 * fujitsu: fujitsu + capture
4060 * acer: acer + capture
4063 static struct snd_kcontrol_new alc260_base_output_mixer[] = {
4064 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
4065 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
4066 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
4067 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
4068 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
4069 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
4070 { } /* end */
4073 static struct snd_kcontrol_new alc260_input_mixer[] = {
4074 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
4075 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
4076 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
4077 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
4078 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
4079 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
4080 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
4081 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
4082 { } /* end */
4085 static struct snd_kcontrol_new alc260_pc_beep_mixer[] = {
4086 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
4087 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
4088 { } /* end */
4091 /* update HP, line and mono out pins according to the master switch */
4092 static void alc260_hp_master_update(struct hda_codec *codec,
4093 hda_nid_t hp, hda_nid_t line,
4094 hda_nid_t mono)
4096 struct alc_spec *spec = codec->spec;
4097 unsigned int val = spec->master_sw ? PIN_HP : 0;
4098 /* change HP and line-out pins */
4099 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4100 val);
4101 snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4102 val);
4103 /* mono (speaker) depending on the HP jack sense */
4104 val = (val && !spec->jack_present) ? PIN_OUT : 0;
4105 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4106 val);
4109 static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
4110 struct snd_ctl_elem_value *ucontrol)
4112 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4113 struct alc_spec *spec = codec->spec;
4114 *ucontrol->value.integer.value = spec->master_sw;
4115 return 0;
4118 static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
4119 struct snd_ctl_elem_value *ucontrol)
4121 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4122 struct alc_spec *spec = codec->spec;
4123 int val = !!*ucontrol->value.integer.value;
4124 hda_nid_t hp, line, mono;
4126 if (val == spec->master_sw)
4127 return 0;
4128 spec->master_sw = val;
4129 hp = (kcontrol->private_value >> 16) & 0xff;
4130 line = (kcontrol->private_value >> 8) & 0xff;
4131 mono = kcontrol->private_value & 0xff;
4132 alc260_hp_master_update(codec, hp, line, mono);
4133 return 1;
4136 static struct snd_kcontrol_new alc260_hp_output_mixer[] = {
4138 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4139 .name = "Master Playback Switch",
4140 .info = snd_ctl_boolean_mono_info,
4141 .get = alc260_hp_master_sw_get,
4142 .put = alc260_hp_master_sw_put,
4143 .private_value = (0x0f << 16) | (0x10 << 8) | 0x11
4145 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
4146 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
4147 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
4148 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
4149 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
4150 HDA_OUTPUT),
4151 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT),
4152 { } /* end */
4155 static struct hda_verb alc260_hp_unsol_verbs[] = {
4156 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
4160 static void alc260_hp_automute(struct hda_codec *codec)
4162 struct alc_spec *spec = codec->spec;
4163 unsigned int present;
4165 present = snd_hda_codec_read(codec, 0x10, 0,
4166 AC_VERB_GET_PIN_SENSE, 0);
4167 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
4168 alc260_hp_master_update(codec, 0x0f, 0x10, 0x11);
4171 static void alc260_hp_unsol_event(struct hda_codec *codec, unsigned int res)
4173 if ((res >> 26) == ALC880_HP_EVENT)
4174 alc260_hp_automute(codec);
4177 static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
4179 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4180 .name = "Master Playback Switch",
4181 .info = snd_ctl_boolean_mono_info,
4182 .get = alc260_hp_master_sw_get,
4183 .put = alc260_hp_master_sw_put,
4184 .private_value = (0x10 << 16) | (0x15 << 8) | 0x11
4186 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
4187 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
4188 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
4189 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
4190 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
4191 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4192 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
4193 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
4194 { } /* end */
4197 static struct hda_verb alc260_hp_3013_unsol_verbs[] = {
4198 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
4202 static void alc260_hp_3013_automute(struct hda_codec *codec)
4204 struct alc_spec *spec = codec->spec;
4205 unsigned int present;
4207 present = snd_hda_codec_read(codec, 0x15, 0,
4208 AC_VERB_GET_PIN_SENSE, 0);
4209 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
4210 alc260_hp_master_update(codec, 0x10, 0x15, 0x11);
4213 static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
4214 unsigned int res)
4216 if ((res >> 26) == ALC880_HP_EVENT)
4217 alc260_hp_3013_automute(codec);
4220 /* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
4221 * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
4223 static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
4224 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
4225 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
4226 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
4227 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
4228 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
4229 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
4230 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
4231 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
4232 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
4233 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
4234 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
4235 HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
4236 { } /* end */
4239 /* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current
4240 * versions of the ALC260 don't act on requests to enable mic bias from NID
4241 * 0x0f (used to drive the headphone jack in these laptops). The ALC260
4242 * datasheet doesn't mention this restriction. At this stage it's not clear
4243 * whether this behaviour is intentional or is a hardware bug in chip
4244 * revisions available in early 2006. Therefore for now allow the
4245 * "Headphone Jack Mode" control to span all choices, but if it turns out
4246 * that the lack of mic bias for this NID is intentional we could change the
4247 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
4249 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
4250 * don't appear to make the mic bias available from the "line" jack, even
4251 * though the NID used for this jack (0x14) can supply it. The theory is
4252 * that perhaps Acer have included blocking capacitors between the ALC260
4253 * and the output jack. If this turns out to be the case for all such
4254 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
4255 * to ALC_PIN_DIR_INOUT_NOMICBIAS.
4257 * The C20x Tablet series have a mono internal speaker which is controlled
4258 * via the chip's Mono sum widget and pin complex, so include the necessary
4259 * controls for such models. On models without a "mono speaker" the control
4260 * won't do anything.
4262 static struct snd_kcontrol_new alc260_acer_mixer[] = {
4263 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
4264 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
4265 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
4266 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
4267 HDA_OUTPUT),
4268 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
4269 HDA_INPUT),
4270 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
4271 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
4272 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
4273 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
4274 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
4275 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
4276 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
4277 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
4278 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
4279 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
4280 { } /* end */
4283 /* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
4284 * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17.
4286 static struct snd_kcontrol_new alc260_will_mixer[] = {
4287 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
4288 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
4289 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
4290 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
4291 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
4292 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
4293 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
4294 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
4295 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
4296 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
4297 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
4298 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
4299 { } /* end */
4302 /* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
4303 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
4305 static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
4306 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
4307 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
4308 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
4309 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
4310 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
4311 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
4312 HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
4313 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
4314 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
4315 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
4316 { } /* end */
4319 /* capture mixer elements */
4320 static struct snd_kcontrol_new alc260_capture_mixer[] = {
4321 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
4322 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
4323 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),
4324 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),
4326 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4327 /* The multiple "Capture Source" controls confuse alsamixer
4328 * So call somewhat different..
4330 /* .name = "Capture Source", */
4331 .name = "Input Source",
4332 .count = 2,
4333 .info = alc_mux_enum_info,
4334 .get = alc_mux_enum_get,
4335 .put = alc_mux_enum_put,
4337 { } /* end */
4340 static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {
4341 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
4342 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
4344 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4345 /* The multiple "Capture Source" controls confuse alsamixer
4346 * So call somewhat different..
4348 /* .name = "Capture Source", */
4349 .name = "Input Source",
4350 .count = 1,
4351 .info = alc_mux_enum_info,
4352 .get = alc_mux_enum_get,
4353 .put = alc_mux_enum_put,
4355 { } /* end */
4359 * initialization verbs
4361 static struct hda_verb alc260_init_verbs[] = {
4362 /* Line In pin widget for input */
4363 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4364 /* CD pin widget for input */
4365 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4366 /* Mic1 (rear panel) pin widget for input and vref at 80% */
4367 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4368 /* Mic2 (front panel) pin widget for input and vref at 80% */
4369 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4370 /* LINE-2 is used for line-out in rear */
4371 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4372 /* select line-out */
4373 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
4374 /* LINE-OUT pin */
4375 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4376 /* enable HP */
4377 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4378 /* enable Mono */
4379 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4380 /* mute capture amp left and right */
4381 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4382 /* set connection select to line in (default select for this ADC) */
4383 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
4384 /* mute capture amp left and right */
4385 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4386 /* set connection select to line in (default select for this ADC) */
4387 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
4388 /* set vol=0 Line-Out mixer amp left and right */
4389 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4390 /* unmute pin widget amp left and right (no gain on this amp) */
4391 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4392 /* set vol=0 HP mixer amp left and right */
4393 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4394 /* unmute pin widget amp left and right (no gain on this amp) */
4395 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4396 /* set vol=0 Mono mixer amp left and right */
4397 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4398 /* unmute pin widget amp left and right (no gain on this amp) */
4399 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4400 /* unmute LINE-2 out pin */
4401 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4402 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
4403 * Line In 2 = 0x03
4405 /* mute analog inputs */
4406 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4407 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4408 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4409 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4410 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4411 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
4412 /* mute Front out path */
4413 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4414 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4415 /* mute Headphone out path */
4416 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4417 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4418 /* mute Mono out path */
4419 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4420 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4424 #if 0 /* should be identical with alc260_init_verbs? */
4425 static struct hda_verb alc260_hp_init_verbs[] = {
4426 /* Headphone and output */
4427 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
4428 /* mono output */
4429 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
4430 /* Mic1 (rear panel) pin widget for input and vref at 80% */
4431 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
4432 /* Mic2 (front panel) pin widget for input and vref at 80% */
4433 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
4434 /* Line In pin widget for input */
4435 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
4436 /* Line-2 pin widget for output */
4437 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
4438 /* CD pin widget for input */
4439 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
4440 /* unmute amp left and right */
4441 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
4442 /* set connection select to line in (default select for this ADC) */
4443 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
4444 /* unmute Line-Out mixer amp left and right (volume = 0) */
4445 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
4446 /* mute pin widget amp left and right (no gain on this amp) */
4447 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
4448 /* unmute HP mixer amp left and right (volume = 0) */
4449 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
4450 /* mute pin widget amp left and right (no gain on this amp) */
4451 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
4452 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
4453 * Line In 2 = 0x03
4455 /* mute analog inputs */
4456 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4457 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4458 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4459 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4460 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4461 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
4462 /* Unmute Front out path */
4463 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4464 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
4465 /* Unmute Headphone out path */
4466 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4467 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
4468 /* Unmute Mono out path */
4469 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4470 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
4473 #endif
4475 static struct hda_verb alc260_hp_3013_init_verbs[] = {
4476 /* Line out and output */
4477 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
4478 /* mono output */
4479 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
4480 /* Mic1 (rear panel) pin widget for input and vref at 80% */
4481 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
4482 /* Mic2 (front panel) pin widget for input and vref at 80% */
4483 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
4484 /* Line In pin widget for input */
4485 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
4486 /* Headphone pin widget for output */
4487 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
4488 /* CD pin widget for input */
4489 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
4490 /* unmute amp left and right */
4491 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
4492 /* set connection select to line in (default select for this ADC) */
4493 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
4494 /* unmute Line-Out mixer amp left and right (volume = 0) */
4495 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
4496 /* mute pin widget amp left and right (no gain on this amp) */
4497 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
4498 /* unmute HP mixer amp left and right (volume = 0) */
4499 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
4500 /* mute pin widget amp left and right (no gain on this amp) */
4501 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
4502 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
4503 * Line In 2 = 0x03
4505 /* mute analog inputs */
4506 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4507 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4508 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4509 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4510 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4511 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
4512 /* Unmute Front out path */
4513 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4514 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
4515 /* Unmute Headphone out path */
4516 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4517 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
4518 /* Unmute Mono out path */
4519 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4520 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
4524 /* Initialisation sequence for ALC260 as configured in Fujitsu S702x
4525 * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
4526 * audio = 0x16, internal speaker = 0x10.
4528 static struct hda_verb alc260_fujitsu_init_verbs[] = {
4529 /* Disable all GPIOs */
4530 {0x01, AC_VERB_SET_GPIO_MASK, 0},
4531 /* Internal speaker is connected to headphone pin */
4532 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4533 /* Headphone/Line-out jack connects to Line1 pin; make it an output */
4534 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4535 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
4536 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4537 /* Ensure all other unused pins are disabled and muted. */
4538 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4539 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4540 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4541 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4542 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4543 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4544 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4545 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4547 /* Disable digital (SPDIF) pins */
4548 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
4549 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
4551 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
4552 * when acting as an output.
4554 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
4556 /* Start with output sum widgets muted and their output gains at min */
4557 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4558 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4559 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4560 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4561 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4562 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4563 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4564 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4565 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4567 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
4568 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4569 /* Unmute Line1 pin widget output buffer since it starts as an output.
4570 * If the pin mode is changed by the user the pin mode control will
4571 * take care of enabling the pin's input/output buffers as needed.
4572 * Therefore there's no need to enable the input buffer at this
4573 * stage.
4575 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4576 /* Unmute input buffer of pin widget used for Line-in (no equiv
4577 * mixer ctrl)
4579 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4581 /* Mute capture amp left and right */
4582 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4583 /* Set ADC connection select to match default mixer setting - line
4584 * in (on mic1 pin)
4586 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
4588 /* Do the same for the second ADC: mute capture input amp and
4589 * set ADC connection to line in (on mic1 pin)
4591 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4592 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
4594 /* Mute all inputs to mixer widget (even unconnected ones) */
4595 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
4596 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
4597 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
4598 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
4599 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
4600 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
4601 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
4602 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
4607 /* Initialisation sequence for ALC260 as configured in Acer TravelMate and
4608 * similar laptops (adapted from Fujitsu init verbs).
4610 static struct hda_verb alc260_acer_init_verbs[] = {
4611 /* On TravelMate laptops, GPIO 0 enables the internal speaker and
4612 * the headphone jack. Turn this on and rely on the standard mute
4613 * methods whenever the user wants to turn these outputs off.
4615 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
4616 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
4617 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
4618 /* Internal speaker/Headphone jack is connected to Line-out pin */
4619 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4620 /* Internal microphone/Mic jack is connected to Mic1 pin */
4621 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
4622 /* Line In jack is connected to Line1 pin */
4623 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4624 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
4625 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4626 /* Ensure all other unused pins are disabled and muted. */
4627 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4628 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4629 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4630 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4631 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4632 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4633 /* Disable digital (SPDIF) pins */
4634 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
4635 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
4637 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
4638 * bus when acting as outputs.
4640 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
4641 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
4643 /* Start with output sum widgets muted and their output gains at min */
4644 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4645 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4646 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4647 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4648 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4649 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4650 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4651 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4652 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4654 /* Unmute Line-out pin widget amp left and right
4655 * (no equiv mixer ctrl)
4657 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4658 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */
4659 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4660 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
4661 * inputs. If the pin mode is changed by the user the pin mode control
4662 * will take care of enabling the pin's input/output buffers as needed.
4663 * Therefore there's no need to enable the input buffer at this
4664 * stage.
4666 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4667 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4669 /* Mute capture amp left and right */
4670 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4671 /* Set ADC connection select to match default mixer setting - mic
4672 * (on mic1 pin)
4674 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
4676 /* Do similar with the second ADC: mute capture input amp and
4677 * set ADC connection to mic to match ALSA's default state.
4679 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4680 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
4682 /* Mute all inputs to mixer widget (even unconnected ones) */
4683 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
4684 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
4685 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
4686 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
4687 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
4688 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
4689 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
4690 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
4695 static struct hda_verb alc260_will_verbs[] = {
4696 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4697 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
4698 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
4699 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4700 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
4701 {0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
4705 static struct hda_verb alc260_replacer_672v_verbs[] = {
4706 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4707 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
4708 {0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
4710 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
4711 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
4712 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4714 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
4718 /* toggle speaker-output according to the hp-jack state */
4719 static void alc260_replacer_672v_automute(struct hda_codec *codec)
4721 unsigned int present;
4723 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
4724 present = snd_hda_codec_read(codec, 0x0f, 0,
4725 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
4726 if (present) {
4727 snd_hda_codec_write_cache(codec, 0x01, 0,
4728 AC_VERB_SET_GPIO_DATA, 1);
4729 snd_hda_codec_write_cache(codec, 0x0f, 0,
4730 AC_VERB_SET_PIN_WIDGET_CONTROL,
4731 PIN_HP);
4732 } else {
4733 snd_hda_codec_write_cache(codec, 0x01, 0,
4734 AC_VERB_SET_GPIO_DATA, 0);
4735 snd_hda_codec_write_cache(codec, 0x0f, 0,
4736 AC_VERB_SET_PIN_WIDGET_CONTROL,
4737 PIN_OUT);
4741 static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
4742 unsigned int res)
4744 if ((res >> 26) == ALC880_HP_EVENT)
4745 alc260_replacer_672v_automute(codec);
4748 /* Test configuration for debugging, modelled after the ALC880 test
4749 * configuration.
4751 #ifdef CONFIG_SND_DEBUG
4752 static hda_nid_t alc260_test_dac_nids[1] = {
4753 0x02,
4755 static hda_nid_t alc260_test_adc_nids[2] = {
4756 0x04, 0x05,
4758 /* For testing the ALC260, each input MUX needs its own definition since
4759 * the signal assignments are different. This assumes that the first ADC
4760 * is NID 0x04.
4762 static struct hda_input_mux alc260_test_capture_sources[2] = {
4764 .num_items = 7,
4765 .items = {
4766 { "MIC1 pin", 0x0 },
4767 { "MIC2 pin", 0x1 },
4768 { "LINE1 pin", 0x2 },
4769 { "LINE2 pin", 0x3 },
4770 { "CD pin", 0x4 },
4771 { "LINE-OUT pin", 0x5 },
4772 { "HP-OUT pin", 0x6 },
4776 .num_items = 8,
4777 .items = {
4778 { "MIC1 pin", 0x0 },
4779 { "MIC2 pin", 0x1 },
4780 { "LINE1 pin", 0x2 },
4781 { "LINE2 pin", 0x3 },
4782 { "CD pin", 0x4 },
4783 { "Mixer", 0x5 },
4784 { "LINE-OUT pin", 0x6 },
4785 { "HP-OUT pin", 0x7 },
4789 static struct snd_kcontrol_new alc260_test_mixer[] = {
4790 /* Output driver widgets */
4791 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
4792 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
4793 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
4794 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
4795 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
4796 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
4798 /* Modes for retasking pin widgets
4799 * Note: the ALC260 doesn't seem to act on requests to enable mic
4800 * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't
4801 * mention this restriction. At this stage it's not clear whether
4802 * this behaviour is intentional or is a hardware bug in chip
4803 * revisions available at least up until early 2006. Therefore for
4804 * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
4805 * choices, but if it turns out that the lack of mic bias for these
4806 * NIDs is intentional we could change their modes from
4807 * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
4809 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
4810 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
4811 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
4812 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
4813 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
4814 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
4816 /* Loopback mixer controls */
4817 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
4818 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
4819 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
4820 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
4821 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
4822 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
4823 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
4824 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
4825 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
4826 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
4827 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
4828 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
4829 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
4830 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
4831 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
4832 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
4834 /* Controls for GPIO pins, assuming they are configured as outputs */
4835 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
4836 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
4837 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
4838 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
4840 /* Switches to allow the digital IO pins to be enabled. The datasheet
4841 * is ambigious as to which NID is which; testing on laptops which
4842 * make this output available should provide clarification.
4844 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
4845 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
4847 /* A switch allowing EAPD to be enabled. Some laptops seem to use
4848 * this output to turn on an external amplifier.
4850 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
4851 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
4853 { } /* end */
4855 static struct hda_verb alc260_test_init_verbs[] = {
4856 /* Enable all GPIOs as outputs with an initial value of 0 */
4857 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
4858 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4859 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
4861 /* Enable retasking pins as output, initially without power amp */
4862 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4863 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4864 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4865 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4866 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4867 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4869 /* Disable digital (SPDIF) pins initially, but users can enable
4870 * them via a mixer switch. In the case of SPDIF-out, this initverb
4871 * payload also sets the generation to 0, output to be in "consumer"
4872 * PCM format, copyright asserted, no pre-emphasis and no validity
4873 * control.
4875 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
4876 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
4878 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
4879 * OUT1 sum bus when acting as an output.
4881 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
4882 {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
4883 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
4884 {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
4886 /* Start with output sum widgets muted and their output gains at min */
4887 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4888 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4889 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4890 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4891 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4892 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4893 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4894 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4895 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4897 /* Unmute retasking pin widget output buffers since the default
4898 * state appears to be output. As the pin mode is changed by the
4899 * user the pin mode control will take care of enabling the pin's
4900 * input/output buffers as needed.
4902 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4903 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4904 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4905 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4906 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4907 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4908 /* Also unmute the mono-out pin widget */
4909 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4911 /* Mute capture amp left and right */
4912 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4913 /* Set ADC connection select to match default mixer setting (mic1
4914 * pin)
4916 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
4918 /* Do the same for the second ADC: mute capture input amp and
4919 * set ADC connection to mic1 pin
4921 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4922 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
4924 /* Mute all inputs to mixer widget (even unconnected ones) */
4925 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
4926 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
4927 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
4928 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
4929 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
4930 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
4931 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
4932 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
4936 #endif
4938 #define alc260_pcm_analog_playback alc880_pcm_analog_alt_playback
4939 #define alc260_pcm_analog_capture alc880_pcm_analog_capture
4941 #define alc260_pcm_digital_playback alc880_pcm_digital_playback
4942 #define alc260_pcm_digital_capture alc880_pcm_digital_capture
4945 * for BIOS auto-configuration
4948 static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
4949 const char *pfx)
4951 hda_nid_t nid_vol;
4952 unsigned long vol_val, sw_val;
4953 char name[32];
4954 int err;
4956 if (nid >= 0x0f && nid < 0x11) {
4957 nid_vol = nid - 0x7;
4958 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
4959 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
4960 } else if (nid == 0x11) {
4961 nid_vol = nid - 0x7;
4962 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
4963 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
4964 } else if (nid >= 0x12 && nid <= 0x15) {
4965 nid_vol = 0x08;
4966 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
4967 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
4968 } else
4969 return 0; /* N/A */
4971 snprintf(name, sizeof(name), "%s Playback Volume", pfx);
4972 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val);
4973 if (err < 0)
4974 return err;
4975 snprintf(name, sizeof(name), "%s Playback Switch", pfx);
4976 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val);
4977 if (err < 0)
4978 return err;
4979 return 1;
4982 /* add playback controls from the parsed DAC table */
4983 static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
4984 const struct auto_pin_cfg *cfg)
4986 hda_nid_t nid;
4987 int err;
4989 spec->multiout.num_dacs = 1;
4990 spec->multiout.dac_nids = spec->private_dac_nids;
4991 spec->multiout.dac_nids[0] = 0x02;
4993 nid = cfg->line_out_pins[0];
4994 if (nid) {
4995 err = alc260_add_playback_controls(spec, nid, "Front");
4996 if (err < 0)
4997 return err;
5000 nid = cfg->speaker_pins[0];
5001 if (nid) {
5002 err = alc260_add_playback_controls(spec, nid, "Speaker");
5003 if (err < 0)
5004 return err;
5007 nid = cfg->hp_pins[0];
5008 if (nid) {
5009 err = alc260_add_playback_controls(spec, nid, "Headphone");
5010 if (err < 0)
5011 return err;
5013 return 0;
5016 /* create playback/capture controls for input pins */
5017 static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
5018 const struct auto_pin_cfg *cfg)
5020 struct hda_input_mux *imux = &spec->private_imux;
5021 int i, err, idx;
5023 for (i = 0; i < AUTO_PIN_LAST; i++) {
5024 if (cfg->input_pins[i] >= 0x12) {
5025 idx = cfg->input_pins[i] - 0x12;
5026 err = new_analog_input(spec, cfg->input_pins[i],
5027 auto_pin_cfg_labels[i], idx,
5028 0x07);
5029 if (err < 0)
5030 return err;
5031 imux->items[imux->num_items].label =
5032 auto_pin_cfg_labels[i];
5033 imux->items[imux->num_items].index = idx;
5034 imux->num_items++;
5036 if (cfg->input_pins[i] >= 0x0f && cfg->input_pins[i] <= 0x10){
5037 idx = cfg->input_pins[i] - 0x09;
5038 err = new_analog_input(spec, cfg->input_pins[i],
5039 auto_pin_cfg_labels[i], idx,
5040 0x07);
5041 if (err < 0)
5042 return err;
5043 imux->items[imux->num_items].label =
5044 auto_pin_cfg_labels[i];
5045 imux->items[imux->num_items].index = idx;
5046 imux->num_items++;
5049 return 0;
5052 static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
5053 hda_nid_t nid, int pin_type,
5054 int sel_idx)
5056 alc_set_pin_output(codec, nid, pin_type);
5057 /* need the manual connection? */
5058 if (nid >= 0x12) {
5059 int idx = nid - 0x12;
5060 snd_hda_codec_write(codec, idx + 0x0b, 0,
5061 AC_VERB_SET_CONNECT_SEL, sel_idx);
5065 static void alc260_auto_init_multi_out(struct hda_codec *codec)
5067 struct alc_spec *spec = codec->spec;
5068 hda_nid_t nid;
5070 alc_subsystem_id(codec, 0x10, 0x15, 0x0f);
5071 nid = spec->autocfg.line_out_pins[0];
5072 if (nid) {
5073 int pin_type = get_pin_type(spec->autocfg.line_out_type);
5074 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
5077 nid = spec->autocfg.speaker_pins[0];
5078 if (nid)
5079 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
5081 nid = spec->autocfg.hp_pins[0];
5082 if (nid)
5083 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
5086 #define ALC260_PIN_CD_NID 0x16
5087 static void alc260_auto_init_analog_input(struct hda_codec *codec)
5089 struct alc_spec *spec = codec->spec;
5090 int i;
5092 for (i = 0; i < AUTO_PIN_LAST; i++) {
5093 hda_nid_t nid = spec->autocfg.input_pins[i];
5094 if (nid >= 0x12) {
5095 snd_hda_codec_write(codec, nid, 0,
5096 AC_VERB_SET_PIN_WIDGET_CONTROL,
5097 i <= AUTO_PIN_FRONT_MIC ?
5098 PIN_VREF80 : PIN_IN);
5099 if (nid != ALC260_PIN_CD_NID)
5100 snd_hda_codec_write(codec, nid, 0,
5101 AC_VERB_SET_AMP_GAIN_MUTE,
5102 AMP_OUT_MUTE);
5108 * generic initialization of ADC, input mixers and output mixers
5110 static struct hda_verb alc260_volume_init_verbs[] = {
5112 * Unmute ADC0-1 and set the default input to mic-in
5114 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
5115 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5116 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
5117 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5119 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
5120 * mixer widget
5121 * Note: PASD motherboards uses the Line In 2 as the input for
5122 * front panel mic (mic 2)
5124 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
5125 /* mute analog inputs */
5126 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5127 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5128 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5129 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5130 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5133 * Set up output mixers (0x08 - 0x0a)
5135 /* set vol=0 to output mixers */
5136 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5137 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5138 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5139 /* set up input amps for analog loopback */
5140 /* Amp Indices: DAC = 0, mixer = 1 */
5141 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5142 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5143 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5144 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5145 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5146 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5151 static int alc260_parse_auto_config(struct hda_codec *codec)
5153 struct alc_spec *spec = codec->spec;
5154 unsigned int wcap;
5155 int err;
5156 static hda_nid_t alc260_ignore[] = { 0x17, 0 };
5158 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
5159 alc260_ignore);
5160 if (err < 0)
5161 return err;
5162 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
5163 if (err < 0)
5164 return err;
5165 if (!spec->kctl_alloc)
5166 return 0; /* can't find valid BIOS pin config */
5167 err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg);
5168 if (err < 0)
5169 return err;
5171 spec->multiout.max_channels = 2;
5173 if (spec->autocfg.dig_out_pin)
5174 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
5175 if (spec->kctl_alloc)
5176 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
5178 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
5180 spec->num_mux_defs = 1;
5181 spec->input_mux = &spec->private_imux;
5183 /* check whether NID 0x04 is valid */
5184 wcap = get_wcaps(codec, 0x04);
5185 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
5186 if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
5187 spec->adc_nids = alc260_adc_nids_alt;
5188 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
5189 spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
5190 } else {
5191 spec->adc_nids = alc260_adc_nids;
5192 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
5193 spec->mixers[spec->num_mixers] = alc260_capture_mixer;
5195 spec->num_mixers++;
5197 store_pin_configs(codec);
5198 return 1;
5201 /* additional initialization for auto-configuration model */
5202 static void alc260_auto_init(struct hda_codec *codec)
5204 struct alc_spec *spec = codec->spec;
5205 alc260_auto_init_multi_out(codec);
5206 alc260_auto_init_analog_input(codec);
5207 if (spec->unsol_event)
5208 alc_sku_automute(codec);
5211 #ifdef CONFIG_SND_HDA_POWER_SAVE
5212 static struct hda_amp_list alc260_loopbacks[] = {
5213 { 0x07, HDA_INPUT, 0 },
5214 { 0x07, HDA_INPUT, 1 },
5215 { 0x07, HDA_INPUT, 2 },
5216 { 0x07, HDA_INPUT, 3 },
5217 { 0x07, HDA_INPUT, 4 },
5218 { } /* end */
5220 #endif
5223 * ALC260 configurations
5225 static const char *alc260_models[ALC260_MODEL_LAST] = {
5226 [ALC260_BASIC] = "basic",
5227 [ALC260_HP] = "hp",
5228 [ALC260_HP_3013] = "hp-3013",
5229 [ALC260_FUJITSU_S702X] = "fujitsu",
5230 [ALC260_ACER] = "acer",
5231 [ALC260_WILL] = "will",
5232 [ALC260_REPLACER_672V] = "replacer",
5233 #ifdef CONFIG_SND_DEBUG
5234 [ALC260_TEST] = "test",
5235 #endif
5236 [ALC260_AUTO] = "auto",
5239 static struct snd_pci_quirk alc260_cfg_tbl[] = {
5240 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
5241 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
5242 SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
5243 SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013),
5244 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
5245 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
5246 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013),
5247 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
5248 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
5249 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
5250 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
5251 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
5252 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
5253 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
5254 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
5255 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
5256 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
5257 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
5261 static struct alc_config_preset alc260_presets[] = {
5262 [ALC260_BASIC] = {
5263 .mixers = { alc260_base_output_mixer,
5264 alc260_input_mixer,
5265 alc260_pc_beep_mixer,
5266 alc260_capture_mixer },
5267 .init_verbs = { alc260_init_verbs },
5268 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
5269 .dac_nids = alc260_dac_nids,
5270 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
5271 .adc_nids = alc260_adc_nids,
5272 .num_channel_mode = ARRAY_SIZE(alc260_modes),
5273 .channel_mode = alc260_modes,
5274 .input_mux = &alc260_capture_source,
5276 [ALC260_HP] = {
5277 .mixers = { alc260_hp_output_mixer,
5278 alc260_input_mixer,
5279 alc260_capture_alt_mixer },
5280 .init_verbs = { alc260_init_verbs,
5281 alc260_hp_unsol_verbs },
5282 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
5283 .dac_nids = alc260_dac_nids,
5284 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
5285 .adc_nids = alc260_hp_adc_nids,
5286 .num_channel_mode = ARRAY_SIZE(alc260_modes),
5287 .channel_mode = alc260_modes,
5288 .input_mux = &alc260_capture_source,
5289 .unsol_event = alc260_hp_unsol_event,
5290 .init_hook = alc260_hp_automute,
5292 [ALC260_HP_3013] = {
5293 .mixers = { alc260_hp_3013_mixer,
5294 alc260_input_mixer,
5295 alc260_capture_alt_mixer },
5296 .init_verbs = { alc260_hp_3013_init_verbs,
5297 alc260_hp_3013_unsol_verbs },
5298 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
5299 .dac_nids = alc260_dac_nids,
5300 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
5301 .adc_nids = alc260_hp_adc_nids,
5302 .num_channel_mode = ARRAY_SIZE(alc260_modes),
5303 .channel_mode = alc260_modes,
5304 .input_mux = &alc260_capture_source,
5305 .unsol_event = alc260_hp_3013_unsol_event,
5306 .init_hook = alc260_hp_3013_automute,
5308 [ALC260_FUJITSU_S702X] = {
5309 .mixers = { alc260_fujitsu_mixer,
5310 alc260_capture_mixer },
5311 .init_verbs = { alc260_fujitsu_init_verbs },
5312 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
5313 .dac_nids = alc260_dac_nids,
5314 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
5315 .adc_nids = alc260_dual_adc_nids,
5316 .num_channel_mode = ARRAY_SIZE(alc260_modes),
5317 .channel_mode = alc260_modes,
5318 .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
5319 .input_mux = alc260_fujitsu_capture_sources,
5321 [ALC260_ACER] = {
5322 .mixers = { alc260_acer_mixer,
5323 alc260_capture_mixer },
5324 .init_verbs = { alc260_acer_init_verbs },
5325 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
5326 .dac_nids = alc260_dac_nids,
5327 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
5328 .adc_nids = alc260_dual_adc_nids,
5329 .num_channel_mode = ARRAY_SIZE(alc260_modes),
5330 .channel_mode = alc260_modes,
5331 .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
5332 .input_mux = alc260_acer_capture_sources,
5334 [ALC260_WILL] = {
5335 .mixers = { alc260_will_mixer,
5336 alc260_capture_mixer },
5337 .init_verbs = { alc260_init_verbs, alc260_will_verbs },
5338 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
5339 .dac_nids = alc260_dac_nids,
5340 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
5341 .adc_nids = alc260_adc_nids,
5342 .dig_out_nid = ALC260_DIGOUT_NID,
5343 .num_channel_mode = ARRAY_SIZE(alc260_modes),
5344 .channel_mode = alc260_modes,
5345 .input_mux = &alc260_capture_source,
5347 [ALC260_REPLACER_672V] = {
5348 .mixers = { alc260_replacer_672v_mixer,
5349 alc260_capture_mixer },
5350 .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
5351 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
5352 .dac_nids = alc260_dac_nids,
5353 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
5354 .adc_nids = alc260_adc_nids,
5355 .dig_out_nid = ALC260_DIGOUT_NID,
5356 .num_channel_mode = ARRAY_SIZE(alc260_modes),
5357 .channel_mode = alc260_modes,
5358 .input_mux = &alc260_capture_source,
5359 .unsol_event = alc260_replacer_672v_unsol_event,
5360 .init_hook = alc260_replacer_672v_automute,
5362 #ifdef CONFIG_SND_DEBUG
5363 [ALC260_TEST] = {
5364 .mixers = { alc260_test_mixer,
5365 alc260_capture_mixer },
5366 .init_verbs = { alc260_test_init_verbs },
5367 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
5368 .dac_nids = alc260_test_dac_nids,
5369 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
5370 .adc_nids = alc260_test_adc_nids,
5371 .num_channel_mode = ARRAY_SIZE(alc260_modes),
5372 .channel_mode = alc260_modes,
5373 .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
5374 .input_mux = alc260_test_capture_sources,
5376 #endif
5379 static int patch_alc260(struct hda_codec *codec)
5381 struct alc_spec *spec;
5382 int err, board_config;
5384 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5385 if (spec == NULL)
5386 return -ENOMEM;
5388 codec->spec = spec;
5390 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
5391 alc260_models,
5392 alc260_cfg_tbl);
5393 if (board_config < 0) {
5394 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, "
5395 "trying auto-probe from BIOS...\n");
5396 board_config = ALC260_AUTO;
5399 if (board_config == ALC260_AUTO) {
5400 /* automatic parse from the BIOS config */
5401 err = alc260_parse_auto_config(codec);
5402 if (err < 0) {
5403 alc_free(codec);
5404 return err;
5405 } else if (!err) {
5406 printk(KERN_INFO
5407 "hda_codec: Cannot set up configuration "
5408 "from BIOS. Using base mode...\n");
5409 board_config = ALC260_BASIC;
5413 if (board_config != ALC260_AUTO)
5414 setup_preset(spec, &alc260_presets[board_config]);
5416 spec->stream_name_analog = "ALC260 Analog";
5417 spec->stream_analog_playback = &alc260_pcm_analog_playback;
5418 spec->stream_analog_capture = &alc260_pcm_analog_capture;
5420 spec->stream_name_digital = "ALC260 Digital";
5421 spec->stream_digital_playback = &alc260_pcm_digital_playback;
5422 spec->stream_digital_capture = &alc260_pcm_digital_capture;
5424 spec->vmaster_nid = 0x08;
5426 codec->patch_ops = alc_patch_ops;
5427 if (board_config == ALC260_AUTO)
5428 spec->init_hook = alc260_auto_init;
5429 #ifdef CONFIG_SND_HDA_POWER_SAVE
5430 if (!spec->loopback.amplist)
5431 spec->loopback.amplist = alc260_loopbacks;
5432 #endif
5434 return 0;
5439 * ALC882 support
5441 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
5442 * configuration. Each pin widget can choose any input DACs and a mixer.
5443 * Each ADC is connected from a mixer of all inputs. This makes possible
5444 * 6-channel independent captures.
5446 * In addition, an independent DAC for the multi-playback (not used in this
5447 * driver yet).
5449 #define ALC882_DIGOUT_NID 0x06
5450 #define ALC882_DIGIN_NID 0x0a
5452 static struct hda_channel_mode alc882_ch_modes[1] = {
5453 { 8, NULL }
5456 static hda_nid_t alc882_dac_nids[4] = {
5457 /* front, rear, clfe, rear_surr */
5458 0x02, 0x03, 0x04, 0x05
5461 /* identical with ALC880 */
5462 #define alc882_adc_nids alc880_adc_nids
5463 #define alc882_adc_nids_alt alc880_adc_nids_alt
5465 static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
5466 static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
5468 /* input MUX */
5469 /* FIXME: should be a matrix-type input source selection */
5471 static struct hda_input_mux alc882_capture_source = {
5472 .num_items = 4,
5473 .items = {
5474 { "Mic", 0x0 },
5475 { "Front Mic", 0x1 },
5476 { "Line", 0x2 },
5477 { "CD", 0x4 },
5480 #define alc882_mux_enum_info alc_mux_enum_info
5481 #define alc882_mux_enum_get alc_mux_enum_get
5483 static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
5484 struct snd_ctl_elem_value *ucontrol)
5486 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5487 struct alc_spec *spec = codec->spec;
5488 const struct hda_input_mux *imux = spec->input_mux;
5489 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
5490 hda_nid_t nid = spec->capsrc_nids ?
5491 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
5492 unsigned int *cur_val = &spec->cur_mux[adc_idx];
5493 unsigned int i, idx;
5495 idx = ucontrol->value.enumerated.item[0];
5496 if (idx >= imux->num_items)
5497 idx = imux->num_items - 1;
5498 if (*cur_val == idx)
5499 return 0;
5500 for (i = 0; i < imux->num_items; i++) {
5501 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
5502 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
5503 imux->items[i].index,
5504 HDA_AMP_MUTE, v);
5506 *cur_val = idx;
5507 return 1;
5511 * 2ch mode
5513 static struct hda_verb alc882_3ST_ch2_init[] = {
5514 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
5515 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
5516 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
5517 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
5518 { } /* end */
5522 * 6ch mode
5524 static struct hda_verb alc882_3ST_ch6_init[] = {
5525 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5526 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
5527 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
5528 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5529 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
5530 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
5531 { } /* end */
5534 static struct hda_channel_mode alc882_3ST_6ch_modes[2] = {
5535 { 2, alc882_3ST_ch2_init },
5536 { 6, alc882_3ST_ch6_init },
5540 * 6ch mode
5542 static struct hda_verb alc882_sixstack_ch6_init[] = {
5543 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
5544 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5545 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5546 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5547 { } /* end */
5551 * 8ch mode
5553 static struct hda_verb alc882_sixstack_ch8_init[] = {
5554 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5555 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5556 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5557 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5558 { } /* end */
5561 static struct hda_channel_mode alc882_sixstack_modes[2] = {
5562 { 6, alc882_sixstack_ch6_init },
5563 { 8, alc882_sixstack_ch8_init },
5567 * macbook pro ALC885 can switch LineIn to LineOut without loosing Mic
5571 * 2ch mode
5573 static struct hda_verb alc885_mbp_ch2_init[] = {
5574 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
5575 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5576 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5577 { } /* end */
5581 * 6ch mode
5583 static struct hda_verb alc885_mbp_ch6_init[] = {
5584 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5585 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5586 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
5587 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5588 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5589 { } /* end */
5592 static struct hda_channel_mode alc885_mbp_6ch_modes[2] = {
5593 { 2, alc885_mbp_ch2_init },
5594 { 6, alc885_mbp_ch6_init },
5598 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
5599 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
5601 static struct snd_kcontrol_new alc882_base_mixer[] = {
5602 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5603 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5604 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5605 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
5606 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5607 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5608 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
5609 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
5610 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
5611 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
5612 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5613 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5614 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5615 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5616 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5617 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5618 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5619 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5620 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5621 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
5622 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5623 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5624 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5625 { } /* end */
5628 static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
5629 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
5630 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
5631 HDA_CODEC_MUTE ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT),
5632 HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
5633 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5634 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5635 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
5636 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
5637 HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT),
5638 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
5639 { } /* end */
5641 static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
5642 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5643 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5644 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5645 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5646 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5647 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5648 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5649 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5650 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5651 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5652 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5653 { } /* end */
5656 static struct snd_kcontrol_new alc882_targa_mixer[] = {
5657 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5658 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5659 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5660 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5661 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5662 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5663 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5664 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5665 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5666 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5667 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5668 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5669 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
5670 { } /* end */
5673 /* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
5674 * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
5676 static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
5677 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5678 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5679 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
5680 HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),
5681 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5682 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5683 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5684 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5685 HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),
5686 HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
5687 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5688 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5689 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5690 { } /* end */
5693 static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
5694 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5695 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5696 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
5697 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5698 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5699 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5700 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5701 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5702 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5703 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5704 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5705 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5706 { } /* end */
5709 static struct snd_kcontrol_new alc882_chmode_mixer[] = {
5711 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5712 .name = "Channel Mode",
5713 .info = alc_ch_mode_info,
5714 .get = alc_ch_mode_get,
5715 .put = alc_ch_mode_put,
5717 { } /* end */
5720 static struct hda_verb alc882_init_verbs[] = {
5721 /* Front mixer: unmute input/output amp left and right (volume = 0) */
5722 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5723 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5724 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5725 /* Rear mixer */
5726 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5727 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5728 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5729 /* CLFE mixer */
5730 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5731 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5732 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5733 /* Side mixer */
5734 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5735 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5736 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5738 /* Front Pin: output 0 (0x0c) */
5739 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5740 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5741 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
5742 /* Rear Pin: output 1 (0x0d) */
5743 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5744 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5745 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
5746 /* CLFE Pin: output 2 (0x0e) */
5747 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5748 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5749 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
5750 /* Side Pin: output 3 (0x0f) */
5751 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5752 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5753 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
5754 /* Mic (rear) pin: input vref at 80% */
5755 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5756 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5757 /* Front Mic pin: input vref at 80% */
5758 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5759 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5760 /* Line In pin: input */
5761 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5762 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5763 /* Line-2 In: Headphone output (output 0 - 0x0c) */
5764 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5765 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5766 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
5767 /* CD pin widget for input */
5768 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5770 /* FIXME: use matrix-type input source selection */
5771 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
5772 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
5773 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5774 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5775 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5776 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5777 /* Input mixer2 */
5778 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5779 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5780 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5781 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5782 /* Input mixer3 */
5783 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5784 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5785 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5786 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5787 /* ADC1: mute amp left and right */
5788 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5789 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
5790 /* ADC2: mute amp left and right */
5791 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5792 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
5793 /* ADC3: mute amp left and right */
5794 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5795 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
5800 static struct hda_verb alc882_eapd_verbs[] = {
5801 /* change to EAPD mode */
5802 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
5803 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
5807 /* Mac Pro test */
5808 static struct snd_kcontrol_new alc882_macpro_mixer[] = {
5809 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5810 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5811 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
5812 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
5813 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
5814 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
5815 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
5816 { } /* end */
5819 static struct hda_verb alc882_macpro_init_verbs[] = {
5820 /* Front mixer: unmute input/output amp left and right (volume = 0) */
5821 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5822 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5823 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5824 /* Front Pin: output 0 (0x0c) */
5825 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5826 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5827 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
5828 /* Front Mic pin: input vref at 80% */
5829 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5830 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5831 /* Speaker: output */
5832 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5833 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5834 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
5835 /* Headphone output (output 0 - 0x0c) */
5836 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5837 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5838 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
5840 /* FIXME: use matrix-type input source selection */
5841 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
5842 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
5843 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5844 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5845 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5846 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5847 /* Input mixer2 */
5848 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5849 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5850 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5851 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5852 /* Input mixer3 */
5853 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5854 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5855 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5856 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5857 /* ADC1: mute amp left and right */
5858 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5859 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
5860 /* ADC2: mute amp left and right */
5861 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5862 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
5863 /* ADC3: mute amp left and right */
5864 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5865 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
5870 /* Macbook Pro rev3 */
5871 static struct hda_verb alc885_mbp3_init_verbs[] = {
5872 /* Front mixer: unmute input/output amp left and right (volume = 0) */
5873 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5874 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5875 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5876 /* Rear mixer */
5877 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5878 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5879 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5880 /* Front Pin: output 0 (0x0c) */
5881 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5882 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5883 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
5884 /* HP Pin: output 0 (0x0d) */
5885 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
5886 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5887 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
5888 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
5889 /* Mic (rear) pin: input vref at 80% */
5890 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5891 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5892 /* Front Mic pin: input vref at 80% */
5893 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5894 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5895 /* Line In pin: use output 1 when in LineOut mode */
5896 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5897 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5898 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
5900 /* FIXME: use matrix-type input source selection */
5901 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
5902 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
5903 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5904 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5905 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5906 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5907 /* Input mixer2 */
5908 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5909 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5910 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5911 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5912 /* Input mixer3 */
5913 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5914 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5915 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5916 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5917 /* ADC1: mute amp left and right */
5918 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5919 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
5920 /* ADC2: mute amp left and right */
5921 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5922 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
5923 /* ADC3: mute amp left and right */
5924 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5925 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
5930 /* iMac 24 mixer. */
5931 static struct snd_kcontrol_new alc885_imac24_mixer[] = {
5932 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
5933 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
5934 { } /* end */
5937 /* iMac 24 init verbs. */
5938 static struct hda_verb alc885_imac24_init_verbs[] = {
5939 /* Internal speakers: output 0 (0x0c) */
5940 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5941 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5942 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
5943 /* Internal speakers: output 0 (0x0c) */
5944 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5945 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5946 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
5947 /* Headphone: output 0 (0x0c) */
5948 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5949 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5950 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
5951 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
5952 /* Front Mic: input vref at 80% */
5953 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5954 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5958 /* Toggle speaker-output according to the hp-jack state */
5959 static void alc885_imac24_automute(struct hda_codec *codec)
5961 unsigned int present;
5963 present = snd_hda_codec_read(codec, 0x14, 0,
5964 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
5965 snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
5966 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
5967 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
5968 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
5971 /* Processes unsolicited events. */
5972 static void alc885_imac24_unsol_event(struct hda_codec *codec,
5973 unsigned int res)
5975 /* Headphone insertion or removal. */
5976 if ((res >> 26) == ALC880_HP_EVENT)
5977 alc885_imac24_automute(codec);
5980 static void alc885_mbp3_automute(struct hda_codec *codec)
5982 unsigned int present;
5984 present = snd_hda_codec_read(codec, 0x15, 0,
5985 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
5986 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
5987 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
5988 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
5989 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
5992 static void alc885_mbp3_unsol_event(struct hda_codec *codec,
5993 unsigned int res)
5995 /* Headphone insertion or removal. */
5996 if ((res >> 26) == ALC880_HP_EVENT)
5997 alc885_mbp3_automute(codec);
6001 static struct hda_verb alc882_targa_verbs[] = {
6002 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6003 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6005 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6006 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6008 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
6009 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
6010 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
6012 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
6013 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
6014 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
6015 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
6016 { } /* end */
6019 /* toggle speaker-output according to the hp-jack state */
6020 static void alc882_targa_automute(struct hda_codec *codec)
6022 unsigned int present;
6024 present = snd_hda_codec_read(codec, 0x14, 0,
6025 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
6026 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
6027 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
6028 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
6029 present ? 1 : 3);
6032 static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
6034 /* Looks like the unsol event is incompatible with the standard
6035 * definition. 4bit tag is placed at 26 bit!
6037 if (((res >> 26) == ALC880_HP_EVENT)) {
6038 alc882_targa_automute(codec);
6042 static struct hda_verb alc882_asus_a7j_verbs[] = {
6043 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6044 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6046 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6047 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6048 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6050 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
6051 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
6052 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
6054 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
6055 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
6056 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
6057 { } /* end */
6060 static struct hda_verb alc882_asus_a7m_verbs[] = {
6061 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6062 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6064 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6065 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6066 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6068 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
6069 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
6070 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
6072 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
6073 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
6074 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
6075 { } /* end */
6078 static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
6080 unsigned int gpiostate, gpiomask, gpiodir;
6082 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
6083 AC_VERB_GET_GPIO_DATA, 0);
6085 if (!muted)
6086 gpiostate |= (1 << pin);
6087 else
6088 gpiostate &= ~(1 << pin);
6090 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
6091 AC_VERB_GET_GPIO_MASK, 0);
6092 gpiomask |= (1 << pin);
6094 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
6095 AC_VERB_GET_GPIO_DIRECTION, 0);
6096 gpiodir |= (1 << pin);
6099 snd_hda_codec_write(codec, codec->afg, 0,
6100 AC_VERB_SET_GPIO_MASK, gpiomask);
6101 snd_hda_codec_write(codec, codec->afg, 0,
6102 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
6104 msleep(1);
6106 snd_hda_codec_write(codec, codec->afg, 0,
6107 AC_VERB_SET_GPIO_DATA, gpiostate);
6110 /* set up GPIO at initialization */
6111 static void alc885_macpro_init_hook(struct hda_codec *codec)
6113 alc882_gpio_mute(codec, 0, 0);
6114 alc882_gpio_mute(codec, 1, 0);
6117 /* set up GPIO and update auto-muting at initialization */
6118 static void alc885_imac24_init_hook(struct hda_codec *codec)
6120 alc885_macpro_init_hook(codec);
6121 alc885_imac24_automute(codec);
6125 * generic initialization of ADC, input mixers and output mixers
6127 static struct hda_verb alc882_auto_init_verbs[] = {
6129 * Unmute ADC0-2 and set the default input to mic-in
6131 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
6132 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6133 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
6134 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6135 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
6136 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6138 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
6139 * mixer widget
6140 * Note: PASD motherboards uses the Line In 2 as the input for
6141 * front panel mic (mic 2)
6143 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
6144 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6145 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6146 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6147 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6148 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
6151 * Set up output mixers (0x0c - 0x0f)
6153 /* set vol=0 to output mixers */
6154 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6155 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6156 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6157 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6158 /* set up input amps for analog loopback */
6159 /* Amp Indices: DAC = 0, mixer = 1 */
6160 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6161 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6162 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6163 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6164 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6165 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6166 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6167 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6168 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6169 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6171 /* FIXME: use matrix-type input source selection */
6172 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
6173 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
6174 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6175 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6176 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6177 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6178 /* Input mixer2 */
6179 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6180 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6181 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6182 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6183 /* Input mixer3 */
6184 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6185 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6186 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6187 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6192 /* capture mixer elements */
6193 static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
6194 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
6195 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
6196 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
6197 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
6199 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6200 /* The multiple "Capture Source" controls confuse alsamixer
6201 * So call somewhat different..
6203 /* .name = "Capture Source", */
6204 .name = "Input Source",
6205 .count = 2,
6206 .info = alc882_mux_enum_info,
6207 .get = alc882_mux_enum_get,
6208 .put = alc882_mux_enum_put,
6210 { } /* end */
6213 static struct snd_kcontrol_new alc882_capture_mixer[] = {
6214 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
6215 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
6216 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
6217 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
6218 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
6219 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
6221 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6222 /* The multiple "Capture Source" controls confuse alsamixer
6223 * So call somewhat different..
6225 /* .name = "Capture Source", */
6226 .name = "Input Source",
6227 .count = 3,
6228 .info = alc882_mux_enum_info,
6229 .get = alc882_mux_enum_get,
6230 .put = alc882_mux_enum_put,
6232 { } /* end */
6235 #ifdef CONFIG_SND_HDA_POWER_SAVE
6236 #define alc882_loopbacks alc880_loopbacks
6237 #endif
6239 /* pcm configuration: identiacal with ALC880 */
6240 #define alc882_pcm_analog_playback alc880_pcm_analog_playback
6241 #define alc882_pcm_analog_capture alc880_pcm_analog_capture
6242 #define alc882_pcm_digital_playback alc880_pcm_digital_playback
6243 #define alc882_pcm_digital_capture alc880_pcm_digital_capture
6246 * configuration and preset
6248 static const char *alc882_models[ALC882_MODEL_LAST] = {
6249 [ALC882_3ST_DIG] = "3stack-dig",
6250 [ALC882_6ST_DIG] = "6stack-dig",
6251 [ALC882_ARIMA] = "arima",
6252 [ALC882_W2JC] = "w2jc",
6253 [ALC882_TARGA] = "targa",
6254 [ALC882_ASUS_A7J] = "asus-a7j",
6255 [ALC882_ASUS_A7M] = "asus-a7m",
6256 [ALC885_MACPRO] = "macpro",
6257 [ALC885_MBP3] = "mbp3",
6258 [ALC885_IMAC24] = "imac24",
6259 [ALC882_AUTO] = "auto",
6262 static struct snd_pci_quirk alc882_cfg_tbl[] = {
6263 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
6264 SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
6265 SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
6266 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
6267 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
6268 SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
6269 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
6270 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
6271 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
6272 SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */
6273 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
6274 SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA),
6278 static struct alc_config_preset alc882_presets[] = {
6279 [ALC882_3ST_DIG] = {
6280 .mixers = { alc882_base_mixer },
6281 .init_verbs = { alc882_init_verbs },
6282 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
6283 .dac_nids = alc882_dac_nids,
6284 .dig_out_nid = ALC882_DIGOUT_NID,
6285 .dig_in_nid = ALC882_DIGIN_NID,
6286 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
6287 .channel_mode = alc882_ch_modes,
6288 .need_dac_fix = 1,
6289 .input_mux = &alc882_capture_source,
6291 [ALC882_6ST_DIG] = {
6292 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
6293 .init_verbs = { alc882_init_verbs },
6294 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
6295 .dac_nids = alc882_dac_nids,
6296 .dig_out_nid = ALC882_DIGOUT_NID,
6297 .dig_in_nid = ALC882_DIGIN_NID,
6298 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
6299 .channel_mode = alc882_sixstack_modes,
6300 .input_mux = &alc882_capture_source,
6302 [ALC882_ARIMA] = {
6303 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
6304 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs },
6305 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
6306 .dac_nids = alc882_dac_nids,
6307 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
6308 .channel_mode = alc882_sixstack_modes,
6309 .input_mux = &alc882_capture_source,
6311 [ALC882_W2JC] = {
6312 .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
6313 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs,
6314 alc880_gpio1_init_verbs },
6315 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
6316 .dac_nids = alc882_dac_nids,
6317 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
6318 .channel_mode = alc880_threestack_modes,
6319 .need_dac_fix = 1,
6320 .input_mux = &alc882_capture_source,
6321 .dig_out_nid = ALC882_DIGOUT_NID,
6323 [ALC885_MBP3] = {
6324 .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
6325 .init_verbs = { alc885_mbp3_init_verbs,
6326 alc880_gpio1_init_verbs },
6327 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
6328 .dac_nids = alc882_dac_nids,
6329 .channel_mode = alc885_mbp_6ch_modes,
6330 .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes),
6331 .input_mux = &alc882_capture_source,
6332 .dig_out_nid = ALC882_DIGOUT_NID,
6333 .dig_in_nid = ALC882_DIGIN_NID,
6334 .unsol_event = alc885_mbp3_unsol_event,
6335 .init_hook = alc885_mbp3_automute,
6337 [ALC885_MACPRO] = {
6338 .mixers = { alc882_macpro_mixer },
6339 .init_verbs = { alc882_macpro_init_verbs },
6340 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
6341 .dac_nids = alc882_dac_nids,
6342 .dig_out_nid = ALC882_DIGOUT_NID,
6343 .dig_in_nid = ALC882_DIGIN_NID,
6344 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
6345 .channel_mode = alc882_ch_modes,
6346 .input_mux = &alc882_capture_source,
6347 .init_hook = alc885_macpro_init_hook,
6349 [ALC885_IMAC24] = {
6350 .mixers = { alc885_imac24_mixer },
6351 .init_verbs = { alc885_imac24_init_verbs },
6352 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
6353 .dac_nids = alc882_dac_nids,
6354 .dig_out_nid = ALC882_DIGOUT_NID,
6355 .dig_in_nid = ALC882_DIGIN_NID,
6356 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
6357 .channel_mode = alc882_ch_modes,
6358 .input_mux = &alc882_capture_source,
6359 .unsol_event = alc885_imac24_unsol_event,
6360 .init_hook = alc885_imac24_init_hook,
6362 [ALC882_TARGA] = {
6363 .mixers = { alc882_targa_mixer, alc882_chmode_mixer,
6364 alc882_capture_mixer },
6365 .init_verbs = { alc882_init_verbs, alc882_targa_verbs},
6366 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
6367 .dac_nids = alc882_dac_nids,
6368 .dig_out_nid = ALC882_DIGOUT_NID,
6369 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
6370 .adc_nids = alc882_adc_nids,
6371 .capsrc_nids = alc882_capsrc_nids,
6372 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
6373 .channel_mode = alc882_3ST_6ch_modes,
6374 .need_dac_fix = 1,
6375 .input_mux = &alc882_capture_source,
6376 .unsol_event = alc882_targa_unsol_event,
6377 .init_hook = alc882_targa_automute,
6379 [ALC882_ASUS_A7J] = {
6380 .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer,
6381 alc882_capture_mixer },
6382 .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs},
6383 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
6384 .dac_nids = alc882_dac_nids,
6385 .dig_out_nid = ALC882_DIGOUT_NID,
6386 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
6387 .adc_nids = alc882_adc_nids,
6388 .capsrc_nids = alc882_capsrc_nids,
6389 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
6390 .channel_mode = alc882_3ST_6ch_modes,
6391 .need_dac_fix = 1,
6392 .input_mux = &alc882_capture_source,
6394 [ALC882_ASUS_A7M] = {
6395 .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
6396 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs,
6397 alc880_gpio1_init_verbs,
6398 alc882_asus_a7m_verbs },
6399 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
6400 .dac_nids = alc882_dac_nids,
6401 .dig_out_nid = ALC882_DIGOUT_NID,
6402 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
6403 .channel_mode = alc880_threestack_modes,
6404 .need_dac_fix = 1,
6405 .input_mux = &alc882_capture_source,
6411 * Pin config fixes
6413 enum {
6414 PINFIX_ABIT_AW9D_MAX
6417 static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {
6418 { 0x15, 0x01080104 }, /* side */
6419 { 0x16, 0x01011012 }, /* rear */
6420 { 0x17, 0x01016011 }, /* clfe */
6424 static const struct alc_pincfg *alc882_pin_fixes[] = {
6425 [PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix,
6428 static struct snd_pci_quirk alc882_pinfix_tbl[] = {
6429 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
6434 * BIOS auto configuration
6436 static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
6437 hda_nid_t nid, int pin_type,
6438 int dac_idx)
6440 /* set as output */
6441 struct alc_spec *spec = codec->spec;
6442 int idx;
6444 alc_set_pin_output(codec, nid, pin_type);
6445 if (spec->multiout.dac_nids[dac_idx] == 0x25)
6446 idx = 4;
6447 else
6448 idx = spec->multiout.dac_nids[dac_idx] - 2;
6449 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
6453 static void alc882_auto_init_multi_out(struct hda_codec *codec)
6455 struct alc_spec *spec = codec->spec;
6456 int i;
6458 alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
6459 for (i = 0; i <= HDA_SIDE; i++) {
6460 hda_nid_t nid = spec->autocfg.line_out_pins[i];
6461 int pin_type = get_pin_type(spec->autocfg.line_out_type);
6462 if (nid)
6463 alc882_auto_set_output_and_unmute(codec, nid, pin_type,
6468 static void alc882_auto_init_hp_out(struct hda_codec *codec)
6470 struct alc_spec *spec = codec->spec;
6471 hda_nid_t pin;
6473 pin = spec->autocfg.hp_pins[0];
6474 if (pin) /* connect to front */
6475 /* use dac 0 */
6476 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
6477 pin = spec->autocfg.speaker_pins[0];
6478 if (pin)
6479 alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
6482 #define alc882_is_input_pin(nid) alc880_is_input_pin(nid)
6483 #define ALC882_PIN_CD_NID ALC880_PIN_CD_NID
6485 static void alc882_auto_init_analog_input(struct hda_codec *codec)
6487 struct alc_spec *spec = codec->spec;
6488 int i;
6490 for (i = 0; i < AUTO_PIN_LAST; i++) {
6491 hda_nid_t nid = spec->autocfg.input_pins[i];
6492 unsigned int vref;
6493 if (!nid)
6494 continue;
6495 vref = PIN_IN;
6496 if (1 /*i <= AUTO_PIN_FRONT_MIC*/) {
6497 unsigned int pincap;
6498 pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
6499 if ((pincap >> AC_PINCAP_VREF_SHIFT) &
6500 AC_PINCAP_VREF_80)
6501 vref = PIN_VREF80;
6503 snd_hda_codec_write(codec, nid, 0,
6504 AC_VERB_SET_PIN_WIDGET_CONTROL, vref);
6505 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
6506 snd_hda_codec_write(codec, nid, 0,
6507 AC_VERB_SET_AMP_GAIN_MUTE,
6508 AMP_OUT_MUTE);
6512 static void alc882_auto_init_input_src(struct hda_codec *codec)
6514 struct alc_spec *spec = codec->spec;
6515 const struct hda_input_mux *imux = spec->input_mux;
6516 int c;
6518 for (c = 0; c < spec->num_adc_nids; c++) {
6519 hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
6520 hda_nid_t nid = spec->capsrc_nids[c];
6521 int conns, mute, idx, item;
6523 conns = snd_hda_get_connections(codec, nid, conn_list,
6524 ARRAY_SIZE(conn_list));
6525 if (conns < 0)
6526 continue;
6527 for (idx = 0; idx < conns; idx++) {
6528 /* if the current connection is the selected one,
6529 * unmute it as default - otherwise mute it
6531 mute = AMP_IN_MUTE(idx);
6532 for (item = 0; item < imux->num_items; item++) {
6533 if (imux->items[item].index == idx) {
6534 if (spec->cur_mux[c] == item)
6535 mute = AMP_IN_UNMUTE(idx);
6536 break;
6539 snd_hda_codec_write(codec, nid, 0,
6540 AC_VERB_SET_AMP_GAIN_MUTE, mute);
6545 /* add mic boosts if needed */
6546 static int alc_auto_add_mic_boost(struct hda_codec *codec)
6548 struct alc_spec *spec = codec->spec;
6549 int err;
6550 hda_nid_t nid;
6552 nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
6553 if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
6554 err = add_control(spec, ALC_CTL_WIDGET_VOL,
6555 "Mic Boost",
6556 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
6557 if (err < 0)
6558 return err;
6560 nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
6561 if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
6562 err = add_control(spec, ALC_CTL_WIDGET_VOL,
6563 "Front Mic Boost",
6564 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
6565 if (err < 0)
6566 return err;
6568 return 0;
6571 /* almost identical with ALC880 parser... */
6572 static int alc882_parse_auto_config(struct hda_codec *codec)
6574 struct alc_spec *spec = codec->spec;
6575 int err = alc880_parse_auto_config(codec);
6577 if (err < 0)
6578 return err;
6579 else if (!err)
6580 return 0; /* no config found */
6582 err = alc_auto_add_mic_boost(codec);
6583 if (err < 0)
6584 return err;
6586 /* hack - override the init verbs */
6587 spec->init_verbs[0] = alc882_auto_init_verbs;
6589 return 1; /* config found */
6592 /* additional initialization for auto-configuration model */
6593 static void alc882_auto_init(struct hda_codec *codec)
6595 struct alc_spec *spec = codec->spec;
6596 alc882_auto_init_multi_out(codec);
6597 alc882_auto_init_hp_out(codec);
6598 alc882_auto_init_analog_input(codec);
6599 alc882_auto_init_input_src(codec);
6600 if (spec->unsol_event)
6601 alc_sku_automute(codec);
6604 static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */
6606 static int patch_alc882(struct hda_codec *codec)
6608 struct alc_spec *spec;
6609 int err, board_config;
6611 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6612 if (spec == NULL)
6613 return -ENOMEM;
6615 codec->spec = spec;
6617 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
6618 alc882_models,
6619 alc882_cfg_tbl);
6621 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
6622 /* Pick up systems that don't supply PCI SSID */
6623 switch (codec->subsystem_id) {
6624 case 0x106b0c00: /* Mac Pro */
6625 board_config = ALC885_MACPRO;
6626 break;
6627 case 0x106b1000: /* iMac 24 */
6628 case 0x106b2800: /* AppleTV */
6629 board_config = ALC885_IMAC24;
6630 break;
6631 case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */
6632 case 0x106b2c00: /* Macbook Pro rev3 */
6633 case 0x106b3600: /* Macbook 3.1 */
6634 board_config = ALC885_MBP3;
6635 break;
6636 default:
6637 /* ALC889A is handled better as ALC888-compatible */
6638 if (codec->revision_id == 0x100101 ||
6639 codec->revision_id == 0x100103) {
6640 alc_free(codec);
6641 return patch_alc883(codec);
6643 printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
6644 "trying auto-probe from BIOS...\n");
6645 board_config = ALC882_AUTO;
6649 alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes);
6651 if (board_config == ALC882_AUTO) {
6652 /* automatic parse from the BIOS config */
6653 err = alc882_parse_auto_config(codec);
6654 if (err < 0) {
6655 alc_free(codec);
6656 return err;
6657 } else if (!err) {
6658 printk(KERN_INFO
6659 "hda_codec: Cannot set up configuration "
6660 "from BIOS. Using base mode...\n");
6661 board_config = ALC882_3ST_DIG;
6665 if (board_config != ALC882_AUTO)
6666 setup_preset(spec, &alc882_presets[board_config]);
6668 if (codec->vendor_id == 0x10ec0885) {
6669 spec->stream_name_analog = "ALC885 Analog";
6670 spec->stream_name_digital = "ALC885 Digital";
6671 } else {
6672 spec->stream_name_analog = "ALC882 Analog";
6673 spec->stream_name_digital = "ALC882 Digital";
6676 spec->stream_analog_playback = &alc882_pcm_analog_playback;
6677 spec->stream_analog_capture = &alc882_pcm_analog_capture;
6678 /* FIXME: setup DAC5 */
6679 /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
6680 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
6682 spec->stream_digital_playback = &alc882_pcm_digital_playback;
6683 spec->stream_digital_capture = &alc882_pcm_digital_capture;
6685 if (!spec->adc_nids && spec->input_mux) {
6686 /* check whether NID 0x07 is valid */
6687 unsigned int wcap = get_wcaps(codec, 0x07);
6688 /* get type */
6689 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
6690 if (wcap != AC_WID_AUD_IN) {
6691 spec->adc_nids = alc882_adc_nids_alt;
6692 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
6693 spec->capsrc_nids = alc882_capsrc_nids_alt;
6694 spec->mixers[spec->num_mixers] =
6695 alc882_capture_alt_mixer;
6696 spec->num_mixers++;
6697 } else {
6698 spec->adc_nids = alc882_adc_nids;
6699 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
6700 spec->capsrc_nids = alc882_capsrc_nids;
6701 spec->mixers[spec->num_mixers] = alc882_capture_mixer;
6702 spec->num_mixers++;
6706 spec->vmaster_nid = 0x0c;
6708 codec->patch_ops = alc_patch_ops;
6709 if (board_config == ALC882_AUTO)
6710 spec->init_hook = alc882_auto_init;
6711 #ifdef CONFIG_SND_HDA_POWER_SAVE
6712 if (!spec->loopback.amplist)
6713 spec->loopback.amplist = alc882_loopbacks;
6714 #endif
6716 return 0;
6720 * ALC883 support
6722 * ALC883 is almost identical with ALC880 but has cleaner and more flexible
6723 * configuration. Each pin widget can choose any input DACs and a mixer.
6724 * Each ADC is connected from a mixer of all inputs. This makes possible
6725 * 6-channel independent captures.
6727 * In addition, an independent DAC for the multi-playback (not used in this
6728 * driver yet).
6730 #define ALC883_DIGOUT_NID 0x06
6731 #define ALC883_DIGIN_NID 0x0a
6733 static hda_nid_t alc883_dac_nids[4] = {
6734 /* front, rear, clfe, rear_surr */
6735 0x02, 0x03, 0x04, 0x05
6738 static hda_nid_t alc883_adc_nids[2] = {
6739 /* ADC1-2 */
6740 0x08, 0x09,
6743 static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };
6745 /* input MUX */
6746 /* FIXME: should be a matrix-type input source selection */
6748 static struct hda_input_mux alc883_capture_source = {
6749 .num_items = 4,
6750 .items = {
6751 { "Mic", 0x0 },
6752 { "Front Mic", 0x1 },
6753 { "Line", 0x2 },
6754 { "CD", 0x4 },
6758 static struct hda_input_mux alc883_3stack_6ch_intel = {
6759 .num_items = 4,
6760 .items = {
6761 { "Mic", 0x1 },
6762 { "Front Mic", 0x0 },
6763 { "Line", 0x2 },
6764 { "CD", 0x4 },
6768 static struct hda_input_mux alc883_lenovo_101e_capture_source = {
6769 .num_items = 2,
6770 .items = {
6771 { "Mic", 0x1 },
6772 { "Line", 0x2 },
6776 static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
6777 .num_items = 4,
6778 .items = {
6779 { "Mic", 0x0 },
6780 { "iMic", 0x1 },
6781 { "Line", 0x2 },
6782 { "CD", 0x4 },
6786 static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
6787 .num_items = 2,
6788 .items = {
6789 { "Mic", 0x0 },
6790 { "Int Mic", 0x1 },
6794 #define alc883_mux_enum_info alc_mux_enum_info
6795 #define alc883_mux_enum_get alc_mux_enum_get
6796 /* ALC883 has the ALC882-type input selection */
6797 #define alc883_mux_enum_put alc882_mux_enum_put
6800 * 2ch mode
6802 static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
6803 { 2, NULL }
6807 * 2ch mode
6809 static struct hda_verb alc883_3ST_ch2_init[] = {
6810 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6811 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6812 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
6813 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6814 { } /* end */
6818 * 4ch mode
6820 static struct hda_verb alc883_3ST_ch4_init[] = {
6821 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6822 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6823 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6824 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6825 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6826 { } /* end */
6830 * 6ch mode
6832 static struct hda_verb alc883_3ST_ch6_init[] = {
6833 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6834 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6835 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
6836 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6837 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6838 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6839 { } /* end */
6842 static struct hda_channel_mode alc883_3ST_6ch_modes[3] = {
6843 { 2, alc883_3ST_ch2_init },
6844 { 4, alc883_3ST_ch4_init },
6845 { 6, alc883_3ST_ch6_init },
6849 * 2ch mode
6851 static struct hda_verb alc883_3ST_ch2_intel_init[] = {
6852 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6853 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6854 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
6855 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6856 { } /* end */
6860 * 4ch mode
6862 static struct hda_verb alc883_3ST_ch4_intel_init[] = {
6863 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6864 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6865 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6866 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6867 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6868 { } /* end */
6872 * 6ch mode
6874 static struct hda_verb alc883_3ST_ch6_intel_init[] = {
6875 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6876 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6877 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
6878 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6879 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6880 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6881 { } /* end */
6884 static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
6885 { 2, alc883_3ST_ch2_intel_init },
6886 { 4, alc883_3ST_ch4_intel_init },
6887 { 6, alc883_3ST_ch6_intel_init },
6891 * 6ch mode
6893 static struct hda_verb alc883_sixstack_ch6_init[] = {
6894 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
6895 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6896 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6897 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6898 { } /* end */
6902 * 8ch mode
6904 static struct hda_verb alc883_sixstack_ch8_init[] = {
6905 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6906 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6907 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6908 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6909 { } /* end */
6912 static struct hda_channel_mode alc883_sixstack_modes[2] = {
6913 { 6, alc883_sixstack_ch6_init },
6914 { 8, alc883_sixstack_ch8_init },
6917 static struct hda_verb alc883_medion_eapd_verbs[] = {
6918 /* eanable EAPD on medion laptop */
6919 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
6920 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
6924 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
6925 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
6928 static struct snd_kcontrol_new alc883_base_mixer[] = {
6929 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6930 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
6931 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
6932 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
6933 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
6934 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
6935 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
6936 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
6937 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
6938 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
6939 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
6940 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
6941 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
6942 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
6943 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
6944 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6945 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
6946 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6947 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
6948 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
6949 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
6950 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
6951 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
6952 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
6953 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
6954 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
6955 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
6957 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6958 /* .name = "Capture Source", */
6959 .name = "Input Source",
6960 .count = 2,
6961 .info = alc883_mux_enum_info,
6962 .get = alc883_mux_enum_get,
6963 .put = alc883_mux_enum_put,
6965 { } /* end */
6968 static struct snd_kcontrol_new alc883_mitac_mixer[] = {
6969 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6970 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
6971 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
6972 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
6973 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
6974 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
6975 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6976 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6977 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
6978 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6979 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
6980 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
6981 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
6982 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
6983 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
6984 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
6985 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
6987 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6988 /* .name = "Capture Source", */
6989 .name = "Input Source",
6990 .count = 2,
6991 .info = alc883_mux_enum_info,
6992 .get = alc883_mux_enum_get,
6993 .put = alc883_mux_enum_put,
6995 { } /* end */
6998 static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
6999 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7000 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
7001 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
7002 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
7003 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7004 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7005 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7006 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7007 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
7008 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
7009 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7010 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7011 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7012 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7014 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7015 /* .name = "Capture Source", */
7016 .name = "Input Source",
7017 .count = 2,
7018 .info = alc883_mux_enum_info,
7019 .get = alc883_mux_enum_get,
7020 .put = alc883_mux_enum_put,
7022 { } /* end */
7025 static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
7026 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7027 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
7028 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
7029 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
7030 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7031 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7032 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7033 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7034 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
7035 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
7036 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7037 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7038 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7039 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7041 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7042 /* .name = "Capture Source", */
7043 .name = "Input Source",
7044 .count = 2,
7045 .info = alc883_mux_enum_info,
7046 .get = alc883_mux_enum_get,
7047 .put = alc883_mux_enum_put,
7049 { } /* end */
7052 static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
7053 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7054 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7055 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7056 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7057 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7058 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7059 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7060 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7061 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7062 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7063 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7064 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
7065 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
7066 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
7067 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
7068 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7069 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7070 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7071 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7073 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7074 /* .name = "Capture Source", */
7075 .name = "Input Source",
7076 .count = 2,
7077 .info = alc883_mux_enum_info,
7078 .get = alc883_mux_enum_get,
7079 .put = alc883_mux_enum_put,
7081 { } /* end */
7084 static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
7085 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7086 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7087 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
7088 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
7089 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
7090 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
7091 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
7092 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
7093 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7094 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7095 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7096 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7097 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7098 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7099 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7100 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7101 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7102 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
7103 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
7104 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
7105 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
7106 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7107 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7108 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7109 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7111 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7112 /* .name = "Capture Source", */
7113 .name = "Input Source",
7114 .count = 2,
7115 .info = alc883_mux_enum_info,
7116 .get = alc883_mux_enum_get,
7117 .put = alc883_mux_enum_put,
7119 { } /* end */
7122 static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
7123 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7124 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7125 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
7126 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
7127 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
7128 HDA_OUTPUT),
7129 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
7130 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
7131 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
7132 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
7133 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7134 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7135 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7136 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7137 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7138 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
7139 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
7140 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7141 HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
7142 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7143 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
7144 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
7145 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7146 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7147 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7148 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7150 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7151 /* .name = "Capture Source", */
7152 .name = "Input Source",
7153 .count = 2,
7154 .info = alc883_mux_enum_info,
7155 .get = alc883_mux_enum_get,
7156 .put = alc883_mux_enum_put,
7158 { } /* end */
7161 static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
7162 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7163 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7164 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
7165 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
7166 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
7167 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
7168 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
7169 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
7170 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7171 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7172 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7173 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7174 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7175 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7176 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7177 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7178 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7179 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
7180 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
7181 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
7182 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
7183 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7184 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7187 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7188 /* .name = "Capture Source", */
7189 .name = "Input Source",
7190 .count = 1,
7191 .info = alc883_mux_enum_info,
7192 .get = alc883_mux_enum_get,
7193 .put = alc883_mux_enum_put,
7195 { } /* end */
7198 static struct snd_kcontrol_new alc883_tagra_mixer[] = {
7199 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7200 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
7201 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7202 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
7203 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
7204 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
7205 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
7206 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
7207 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
7208 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7209 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7210 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7211 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7212 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7213 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7214 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7215 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7216 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7217 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7218 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7220 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7221 /* .name = "Capture Source", */
7222 .name = "Input Source",
7223 .count = 2,
7224 .info = alc883_mux_enum_info,
7225 .get = alc883_mux_enum_get,
7226 .put = alc883_mux_enum_put,
7228 { } /* end */
7231 static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
7232 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7233 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
7234 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7235 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7236 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7237 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7238 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7239 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7240 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7241 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
7242 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
7243 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7244 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7245 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7246 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7248 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7249 /* .name = "Capture Source", */
7250 .name = "Input Source",
7251 .count = 2,
7252 .info = alc883_mux_enum_info,
7253 .get = alc883_mux_enum_get,
7254 .put = alc883_mux_enum_put,
7256 { } /* end */
7259 static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
7260 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7261 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7262 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
7263 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
7264 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7265 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7266 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7267 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
7268 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7269 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7271 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7272 /* .name = "Capture Source", */
7273 .name = "Input Source",
7274 .count = 1,
7275 .info = alc883_mux_enum_info,
7276 .get = alc883_mux_enum_get,
7277 .put = alc883_mux_enum_put,
7279 { } /* end */
7282 static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
7283 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7284 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
7285 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
7286 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7287 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7288 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7289 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7290 HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7291 HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT),
7292 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7293 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7294 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7295 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7297 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7298 /* .name = "Capture Source", */
7299 .name = "Input Source",
7300 .count = 2,
7301 .info = alc883_mux_enum_info,
7302 .get = alc883_mux_enum_get,
7303 .put = alc883_mux_enum_put,
7305 { } /* end */
7308 static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
7309 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7310 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
7311 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
7312 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7313 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7314 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7315 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7316 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7317 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7318 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7319 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7320 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7321 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7323 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7324 /* .name = "Capture Source", */
7325 .name = "Input Source",
7326 .count = 2,
7327 .info = alc883_mux_enum_info,
7328 .get = alc883_mux_enum_get,
7329 .put = alc883_mux_enum_put,
7331 { } /* end */
7334 static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
7335 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7336 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7337 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
7338 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7339 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7340 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7341 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7342 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7343 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7344 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7345 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7346 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7348 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7349 /* .name = "Capture Source", */
7350 .name = "Input Source",
7351 .count = 2,
7352 .info = alc883_mux_enum_info,
7353 .get = alc883_mux_enum_get,
7354 .put = alc883_mux_enum_put,
7356 { } /* end */
7359 static struct snd_kcontrol_new alc883_chmode_mixer[] = {
7361 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7362 .name = "Channel Mode",
7363 .info = alc_ch_mode_info,
7364 .get = alc_ch_mode_get,
7365 .put = alc_ch_mode_put,
7367 { } /* end */
7370 static struct hda_verb alc883_init_verbs[] = {
7371 /* ADC1: mute amp left and right */
7372 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7373 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7374 /* ADC2: mute amp left and right */
7375 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7376 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7377 /* Front mixer: unmute input/output amp left and right (volume = 0) */
7378 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7379 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7380 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7381 /* Rear mixer */
7382 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7383 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7384 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7385 /* CLFE mixer */
7386 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7387 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7388 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7389 /* Side mixer */
7390 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7391 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7392 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7394 /* mute analog input loopbacks */
7395 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7396 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7397 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7398 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7399 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7401 /* Front Pin: output 0 (0x0c) */
7402 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7403 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7404 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7405 /* Rear Pin: output 1 (0x0d) */
7406 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7407 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7408 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
7409 /* CLFE Pin: output 2 (0x0e) */
7410 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7411 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7412 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
7413 /* Side Pin: output 3 (0x0f) */
7414 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7415 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7416 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
7417 /* Mic (rear) pin: input vref at 80% */
7418 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7419 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7420 /* Front Mic pin: input vref at 80% */
7421 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7422 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7423 /* Line In pin: input */
7424 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7425 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7426 /* Line-2 In: Headphone output (output 0 - 0x0c) */
7427 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7428 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7429 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
7430 /* CD pin widget for input */
7431 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7433 /* FIXME: use matrix-type input source selection */
7434 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7435 /* Input mixer2 */
7436 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7437 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7438 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7439 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
7440 /* Input mixer3 */
7441 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7442 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7443 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7444 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
7448 /* toggle speaker-output according to the hp-jack state */
7449 static void alc883_mitac_hp_automute(struct hda_codec *codec)
7451 unsigned int present;
7453 present = snd_hda_codec_read(codec, 0x15, 0,
7454 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7455 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
7456 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7457 snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,
7458 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7461 /* auto-toggle front mic */
7463 static void alc883_mitac_mic_automute(struct hda_codec *codec)
7465 unsigned int present;
7466 unsigned char bits;
7468 present = snd_hda_codec_read(codec, 0x18, 0,
7469 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7470 bits = present ? HDA_AMP_MUTE : 0;
7471 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
7475 static void alc883_mitac_automute(struct hda_codec *codec)
7477 alc883_mitac_hp_automute(codec);
7478 /* alc883_mitac_mic_automute(codec); */
7481 static void alc883_mitac_unsol_event(struct hda_codec *codec,
7482 unsigned int res)
7484 switch (res >> 26) {
7485 case ALC880_HP_EVENT:
7486 alc883_mitac_hp_automute(codec);
7487 break;
7488 case ALC880_MIC_EVENT:
7489 /* alc883_mitac_mic_automute(codec); */
7490 break;
7494 static struct hda_verb alc883_mitac_verbs[] = {
7495 /* HP */
7496 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7497 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7498 /* Subwoofer */
7499 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
7500 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7502 /* enable unsolicited event */
7503 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7504 /* {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, */
7506 { } /* end */
7509 static struct hda_verb alc883_clevo_m720_verbs[] = {
7510 /* HP */
7511 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7512 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7513 /* Int speaker */
7514 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
7515 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7517 /* enable unsolicited event */
7518 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7519 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
7521 { } /* end */
7524 static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
7525 /* HP */
7526 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7527 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7528 /* Subwoofer */
7529 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
7530 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7532 /* enable unsolicited event */
7533 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7535 { } /* end */
7538 static struct hda_verb alc883_tagra_verbs[] = {
7539 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7540 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7542 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7543 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7545 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
7546 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
7547 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
7549 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7550 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
7551 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
7552 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
7554 { } /* end */
7557 static struct hda_verb alc883_lenovo_101e_verbs[] = {
7558 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7559 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},
7560 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},
7561 { } /* end */
7564 static struct hda_verb alc883_lenovo_nb0763_verbs[] = {
7565 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7566 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7567 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7568 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7569 { } /* end */
7572 static struct hda_verb alc888_lenovo_ms7195_verbs[] = {
7573 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7574 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7575 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7576 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN},
7577 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7578 { } /* end */
7581 static struct hda_verb alc883_haier_w66_verbs[] = {
7582 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7583 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7585 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7587 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
7588 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7589 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7590 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7591 { } /* end */
7594 static struct hda_verb alc888_3st_hp_verbs[] = {
7595 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
7596 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */
7597 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */
7601 static struct hda_verb alc888_6st_dell_verbs[] = {
7602 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7606 static struct hda_verb alc888_3st_hp_2ch_init[] = {
7607 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7608 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7609 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7610 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7614 static struct hda_verb alc888_3st_hp_6ch_init[] = {
7615 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7616 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7617 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7618 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7622 static struct hda_channel_mode alc888_3st_hp_modes[2] = {
7623 { 2, alc888_3st_hp_2ch_init },
7624 { 6, alc888_3st_hp_6ch_init },
7627 /* toggle front-jack and RCA according to the hp-jack state */
7628 static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
7630 unsigned int present;
7632 present = snd_hda_codec_read(codec, 0x1b, 0,
7633 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7634 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
7635 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7636 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
7637 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7640 /* toggle RCA according to the front-jack state */
7641 static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
7643 unsigned int present;
7645 present = snd_hda_codec_read(codec, 0x14, 0,
7646 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7647 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
7648 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7651 static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,
7652 unsigned int res)
7654 if ((res >> 26) == ALC880_HP_EVENT)
7655 alc888_lenovo_ms7195_front_automute(codec);
7656 if ((res >> 26) == ALC880_FRONT_EVENT)
7657 alc888_lenovo_ms7195_rca_automute(codec);
7660 static struct hda_verb alc883_medion_md2_verbs[] = {
7661 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7662 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7664 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7666 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7667 { } /* end */
7670 /* toggle speaker-output according to the hp-jack state */
7671 static void alc883_medion_md2_automute(struct hda_codec *codec)
7673 unsigned int present;
7675 present = snd_hda_codec_read(codec, 0x14, 0,
7676 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7677 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
7678 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7681 static void alc883_medion_md2_unsol_event(struct hda_codec *codec,
7682 unsigned int res)
7684 if ((res >> 26) == ALC880_HP_EVENT)
7685 alc883_medion_md2_automute(codec);
7688 /* toggle speaker-output according to the hp-jack state */
7689 static void alc883_tagra_automute(struct hda_codec *codec)
7691 unsigned int present;
7692 unsigned char bits;
7694 present = snd_hda_codec_read(codec, 0x14, 0,
7695 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7696 bits = present ? HDA_AMP_MUTE : 0;
7697 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
7698 HDA_AMP_MUTE, bits);
7699 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
7700 present ? 1 : 3);
7703 static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
7705 if ((res >> 26) == ALC880_HP_EVENT)
7706 alc883_tagra_automute(codec);
7709 /* toggle speaker-output according to the hp-jack state */
7710 static void alc883_clevo_m720_hp_automute(struct hda_codec *codec)
7712 unsigned int present;
7713 unsigned char bits;
7715 present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
7716 & AC_PINSENSE_PRESENCE;
7717 bits = present ? HDA_AMP_MUTE : 0;
7718 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
7719 HDA_AMP_MUTE, bits);
7722 static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
7724 unsigned int present;
7726 present = snd_hda_codec_read(codec, 0x18, 0,
7727 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7728 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
7729 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7732 static void alc883_clevo_m720_automute(struct hda_codec *codec)
7734 alc883_clevo_m720_hp_automute(codec);
7735 alc883_clevo_m720_mic_automute(codec);
7738 static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
7739 unsigned int res)
7741 switch (res >> 26) {
7742 case ALC880_HP_EVENT:
7743 alc883_clevo_m720_hp_automute(codec);
7744 break;
7745 case ALC880_MIC_EVENT:
7746 alc883_clevo_m720_mic_automute(codec);
7747 break;
7751 /* toggle speaker-output according to the hp-jack state */
7752 static void alc883_2ch_fujitsu_pi2515_automute(struct hda_codec *codec)
7754 unsigned int present;
7755 unsigned char bits;
7757 present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0)
7758 & AC_PINSENSE_PRESENCE;
7759 bits = present ? HDA_AMP_MUTE : 0;
7760 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
7761 HDA_AMP_MUTE, bits);
7764 static void alc883_2ch_fujitsu_pi2515_unsol_event(struct hda_codec *codec,
7765 unsigned int res)
7767 if ((res >> 26) == ALC880_HP_EVENT)
7768 alc883_2ch_fujitsu_pi2515_automute(codec);
7771 static void alc883_haier_w66_automute(struct hda_codec *codec)
7773 unsigned int present;
7774 unsigned char bits;
7776 present = snd_hda_codec_read(codec, 0x1b, 0,
7777 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7778 bits = present ? 0x80 : 0;
7779 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
7780 0x80, bits);
7783 static void alc883_haier_w66_unsol_event(struct hda_codec *codec,
7784 unsigned int res)
7786 if ((res >> 26) == ALC880_HP_EVENT)
7787 alc883_haier_w66_automute(codec);
7790 static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
7792 unsigned int present;
7793 unsigned char bits;
7795 present = snd_hda_codec_read(codec, 0x14, 0,
7796 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7797 bits = present ? HDA_AMP_MUTE : 0;
7798 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
7799 HDA_AMP_MUTE, bits);
7802 static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
7804 unsigned int present;
7805 unsigned char bits;
7807 present = snd_hda_codec_read(codec, 0x1b, 0,
7808 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7809 bits = present ? HDA_AMP_MUTE : 0;
7810 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
7811 HDA_AMP_MUTE, bits);
7812 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
7813 HDA_AMP_MUTE, bits);
7816 static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
7817 unsigned int res)
7819 if ((res >> 26) == ALC880_HP_EVENT)
7820 alc883_lenovo_101e_all_automute(codec);
7821 if ((res >> 26) == ALC880_FRONT_EVENT)
7822 alc883_lenovo_101e_ispeaker_automute(codec);
7825 /* toggle speaker-output according to the hp-jack state */
7826 static void alc883_acer_aspire_automute(struct hda_codec *codec)
7828 unsigned int present;
7830 present = snd_hda_codec_read(codec, 0x14, 0,
7831 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7832 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
7833 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7834 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
7835 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7838 static void alc883_acer_aspire_unsol_event(struct hda_codec *codec,
7839 unsigned int res)
7841 if ((res >> 26) == ALC880_HP_EVENT)
7842 alc883_acer_aspire_automute(codec);
7845 static struct hda_verb alc883_acer_eapd_verbs[] = {
7846 /* HP Pin: output 0 (0x0c) */
7847 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7848 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7849 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7850 /* Front Pin: output 0 (0x0c) */
7851 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7852 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7853 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7854 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
7855 /* eanable EAPD on medion laptop */
7856 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
7857 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
7858 /* enable unsolicited event */
7859 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7863 static void alc888_6st_dell_front_automute(struct hda_codec *codec)
7865 unsigned int present;
7867 present = snd_hda_codec_read(codec, 0x1b, 0,
7868 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7869 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
7870 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7871 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
7872 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7873 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
7874 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7875 snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,
7876 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
7879 static void alc888_6st_dell_unsol_event(struct hda_codec *codec,
7880 unsigned int res)
7882 switch (res >> 26) {
7883 case ALC880_HP_EVENT:
7884 printk("hp_event\n");
7885 alc888_6st_dell_front_automute(codec);
7886 break;
7891 * generic initialization of ADC, input mixers and output mixers
7893 static struct hda_verb alc883_auto_init_verbs[] = {
7895 * Unmute ADC0-2 and set the default input to mic-in
7897 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7898 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7899 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7900 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7902 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
7903 * mixer widget
7904 * Note: PASD motherboards uses the Line In 2 as the input for
7905 * front panel mic (mic 2)
7907 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
7908 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7909 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7910 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7911 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7912 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7915 * Set up output mixers (0x0c - 0x0f)
7917 /* set vol=0 to output mixers */
7918 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7919 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7920 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7921 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7922 /* set up input amps for analog loopback */
7923 /* Amp Indices: DAC = 0, mixer = 1 */
7924 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7925 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7926 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7927 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7928 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7929 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7930 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7931 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7932 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7933 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7935 /* FIXME: use matrix-type input source selection */
7936 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7937 /* Input mixer1 */
7938 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7939 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7940 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7941 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */
7942 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
7943 /* Input mixer2 */
7944 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7945 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7946 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7947 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */
7948 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
7953 /* capture mixer elements */
7954 static struct snd_kcontrol_new alc883_capture_mixer[] = {
7955 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7956 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7957 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
7958 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
7960 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7961 /* The multiple "Capture Source" controls confuse alsamixer
7962 * So call somewhat different..
7964 /* .name = "Capture Source", */
7965 .name = "Input Source",
7966 .count = 2,
7967 .info = alc882_mux_enum_info,
7968 .get = alc882_mux_enum_get,
7969 .put = alc882_mux_enum_put,
7971 { } /* end */
7974 #ifdef CONFIG_SND_HDA_POWER_SAVE
7975 #define alc883_loopbacks alc880_loopbacks
7976 #endif
7978 /* pcm configuration: identiacal with ALC880 */
7979 #define alc883_pcm_analog_playback alc880_pcm_analog_playback
7980 #define alc883_pcm_analog_capture alc880_pcm_analog_capture
7981 #define alc883_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
7982 #define alc883_pcm_digital_playback alc880_pcm_digital_playback
7983 #define alc883_pcm_digital_capture alc880_pcm_digital_capture
7986 * configuration and preset
7988 static const char *alc883_models[ALC883_MODEL_LAST] = {
7989 [ALC883_3ST_2ch_DIG] = "3stack-dig",
7990 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig",
7991 [ALC883_3ST_6ch] = "3stack-6ch",
7992 [ALC883_6ST_DIG] = "6stack-dig",
7993 [ALC883_TARGA_DIG] = "targa-dig",
7994 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
7995 [ALC883_ACER] = "acer",
7996 [ALC883_ACER_ASPIRE] = "acer-aspire",
7997 [ALC883_MEDION] = "medion",
7998 [ALC883_MEDION_MD2] = "medion-md2",
7999 [ALC883_LAPTOP_EAPD] = "laptop-eapd",
8000 [ALC883_LENOVO_101E_2ch] = "lenovo-101e",
8001 [ALC883_LENOVO_NB0763] = "lenovo-nb0763",
8002 [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
8003 [ALC883_HAIER_W66] = "haier-w66",
8004 [ALC888_3ST_HP] = "3stack-hp",
8005 [ALC888_6ST_DELL] = "6stack-dell",
8006 [ALC883_MITAC] = "mitac",
8007 [ALC883_CLEVO_M720] = "clevo-m720",
8008 [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
8009 [ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel",
8010 [ALC883_AUTO] = "auto",
8013 static struct snd_pci_quirk alc883_cfg_tbl[] = {
8014 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),
8015 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
8016 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
8017 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
8018 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
8019 SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */
8020 SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
8021 SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
8022 SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
8023 SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
8024 SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
8025 SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
8026 SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
8027 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
8028 SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
8029 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
8030 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
8031 SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG),
8032 SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
8033 SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
8034 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
8035 SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG),
8036 SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
8037 SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
8038 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
8039 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
8040 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
8041 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
8042 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
8043 SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
8044 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
8045 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
8046 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
8047 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
8048 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
8049 SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
8050 SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
8051 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
8052 SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
8053 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
8054 SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
8055 SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
8056 SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
8057 SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
8058 SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
8059 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
8060 SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515),
8061 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
8062 SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
8063 SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
8064 SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
8065 SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
8066 SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
8067 SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
8068 SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
8069 SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
8070 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
8074 static struct alc_config_preset alc883_presets[] = {
8075 [ALC883_3ST_2ch_DIG] = {
8076 .mixers = { alc883_3ST_2ch_mixer },
8077 .init_verbs = { alc883_init_verbs },
8078 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8079 .dac_nids = alc883_dac_nids,
8080 .dig_out_nid = ALC883_DIGOUT_NID,
8081 .dig_in_nid = ALC883_DIGIN_NID,
8082 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8083 .channel_mode = alc883_3ST_2ch_modes,
8084 .input_mux = &alc883_capture_source,
8086 [ALC883_3ST_6ch_DIG] = {
8087 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
8088 .init_verbs = { alc883_init_verbs },
8089 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8090 .dac_nids = alc883_dac_nids,
8091 .dig_out_nid = ALC883_DIGOUT_NID,
8092 .dig_in_nid = ALC883_DIGIN_NID,
8093 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
8094 .channel_mode = alc883_3ST_6ch_modes,
8095 .need_dac_fix = 1,
8096 .input_mux = &alc883_capture_source,
8098 [ALC883_3ST_6ch] = {
8099 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
8100 .init_verbs = { alc883_init_verbs },
8101 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8102 .dac_nids = alc883_dac_nids,
8103 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
8104 .channel_mode = alc883_3ST_6ch_modes,
8105 .need_dac_fix = 1,
8106 .input_mux = &alc883_capture_source,
8108 [ALC883_3ST_6ch_INTEL] = {
8109 .mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
8110 .init_verbs = { alc883_init_verbs },
8111 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8112 .dac_nids = alc883_dac_nids,
8113 .dig_out_nid = ALC883_DIGOUT_NID,
8114 .dig_in_nid = ALC883_DIGIN_NID,
8115 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
8116 .channel_mode = alc883_3ST_6ch_intel_modes,
8117 .need_dac_fix = 1,
8118 .input_mux = &alc883_3stack_6ch_intel,
8120 [ALC883_6ST_DIG] = {
8121 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
8122 .init_verbs = { alc883_init_verbs },
8123 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8124 .dac_nids = alc883_dac_nids,
8125 .dig_out_nid = ALC883_DIGOUT_NID,
8126 .dig_in_nid = ALC883_DIGIN_NID,
8127 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
8128 .channel_mode = alc883_sixstack_modes,
8129 .input_mux = &alc883_capture_source,
8131 [ALC883_TARGA_DIG] = {
8132 .mixers = { alc883_tagra_mixer, alc883_chmode_mixer },
8133 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
8134 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8135 .dac_nids = alc883_dac_nids,
8136 .dig_out_nid = ALC883_DIGOUT_NID,
8137 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
8138 .channel_mode = alc883_3ST_6ch_modes,
8139 .need_dac_fix = 1,
8140 .input_mux = &alc883_capture_source,
8141 .unsol_event = alc883_tagra_unsol_event,
8142 .init_hook = alc883_tagra_automute,
8144 [ALC883_TARGA_2ch_DIG] = {
8145 .mixers = { alc883_tagra_2ch_mixer},
8146 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
8147 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8148 .dac_nids = alc883_dac_nids,
8149 .dig_out_nid = ALC883_DIGOUT_NID,
8150 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8151 .channel_mode = alc883_3ST_2ch_modes,
8152 .input_mux = &alc883_capture_source,
8153 .unsol_event = alc883_tagra_unsol_event,
8154 .init_hook = alc883_tagra_automute,
8156 [ALC883_ACER] = {
8157 .mixers = { alc883_base_mixer },
8158 /* On TravelMate laptops, GPIO 0 enables the internal speaker
8159 * and the headphone jack. Turn this on and rely on the
8160 * standard mute methods whenever the user wants to turn
8161 * these outputs off.
8163 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
8164 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8165 .dac_nids = alc883_dac_nids,
8166 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8167 .channel_mode = alc883_3ST_2ch_modes,
8168 .input_mux = &alc883_capture_source,
8170 [ALC883_ACER_ASPIRE] = {
8171 .mixers = { alc883_acer_aspire_mixer },
8172 .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
8173 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8174 .dac_nids = alc883_dac_nids,
8175 .dig_out_nid = ALC883_DIGOUT_NID,
8176 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8177 .channel_mode = alc883_3ST_2ch_modes,
8178 .input_mux = &alc883_capture_source,
8179 .unsol_event = alc883_acer_aspire_unsol_event,
8180 .init_hook = alc883_acer_aspire_automute,
8182 [ALC883_MEDION] = {
8183 .mixers = { alc883_fivestack_mixer,
8184 alc883_chmode_mixer },
8185 .init_verbs = { alc883_init_verbs,
8186 alc883_medion_eapd_verbs },
8187 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8188 .dac_nids = alc883_dac_nids,
8189 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
8190 .channel_mode = alc883_sixstack_modes,
8191 .input_mux = &alc883_capture_source,
8193 [ALC883_MEDION_MD2] = {
8194 .mixers = { alc883_medion_md2_mixer},
8195 .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs},
8196 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8197 .dac_nids = alc883_dac_nids,
8198 .dig_out_nid = ALC883_DIGOUT_NID,
8199 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8200 .channel_mode = alc883_3ST_2ch_modes,
8201 .input_mux = &alc883_capture_source,
8202 .unsol_event = alc883_medion_md2_unsol_event,
8203 .init_hook = alc883_medion_md2_automute,
8205 [ALC883_LAPTOP_EAPD] = {
8206 .mixers = { alc883_base_mixer },
8207 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
8208 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8209 .dac_nids = alc883_dac_nids,
8210 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8211 .channel_mode = alc883_3ST_2ch_modes,
8212 .input_mux = &alc883_capture_source,
8214 [ALC883_CLEVO_M720] = {
8215 .mixers = { alc883_clevo_m720_mixer },
8216 .init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
8217 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8218 .dac_nids = alc883_dac_nids,
8219 .dig_out_nid = ALC883_DIGOUT_NID,
8220 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8221 .channel_mode = alc883_3ST_2ch_modes,
8222 .input_mux = &alc883_capture_source,
8223 .unsol_event = alc883_clevo_m720_unsol_event,
8224 .init_hook = alc883_clevo_m720_automute,
8226 [ALC883_LENOVO_101E_2ch] = {
8227 .mixers = { alc883_lenovo_101e_2ch_mixer},
8228 .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
8229 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8230 .dac_nids = alc883_dac_nids,
8231 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8232 .channel_mode = alc883_3ST_2ch_modes,
8233 .input_mux = &alc883_lenovo_101e_capture_source,
8234 .unsol_event = alc883_lenovo_101e_unsol_event,
8235 .init_hook = alc883_lenovo_101e_all_automute,
8237 [ALC883_LENOVO_NB0763] = {
8238 .mixers = { alc883_lenovo_nb0763_mixer },
8239 .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
8240 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8241 .dac_nids = alc883_dac_nids,
8242 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8243 .channel_mode = alc883_3ST_2ch_modes,
8244 .need_dac_fix = 1,
8245 .input_mux = &alc883_lenovo_nb0763_capture_source,
8246 .unsol_event = alc883_medion_md2_unsol_event,
8247 .init_hook = alc883_medion_md2_automute,
8249 [ALC888_LENOVO_MS7195_DIG] = {
8250 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
8251 .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
8252 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8253 .dac_nids = alc883_dac_nids,
8254 .dig_out_nid = ALC883_DIGOUT_NID,
8255 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
8256 .channel_mode = alc883_3ST_6ch_modes,
8257 .need_dac_fix = 1,
8258 .input_mux = &alc883_capture_source,
8259 .unsol_event = alc883_lenovo_ms7195_unsol_event,
8260 .init_hook = alc888_lenovo_ms7195_front_automute,
8262 [ALC883_HAIER_W66] = {
8263 .mixers = { alc883_tagra_2ch_mixer},
8264 .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},
8265 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8266 .dac_nids = alc883_dac_nids,
8267 .dig_out_nid = ALC883_DIGOUT_NID,
8268 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8269 .channel_mode = alc883_3ST_2ch_modes,
8270 .input_mux = &alc883_capture_source,
8271 .unsol_event = alc883_haier_w66_unsol_event,
8272 .init_hook = alc883_haier_w66_automute,
8274 [ALC888_3ST_HP] = {
8275 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
8276 .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
8277 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8278 .dac_nids = alc883_dac_nids,
8279 .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
8280 .channel_mode = alc888_3st_hp_modes,
8281 .need_dac_fix = 1,
8282 .input_mux = &alc883_capture_source,
8284 [ALC888_6ST_DELL] = {
8285 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
8286 .init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
8287 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8288 .dac_nids = alc883_dac_nids,
8289 .dig_out_nid = ALC883_DIGOUT_NID,
8290 .dig_in_nid = ALC883_DIGIN_NID,
8291 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
8292 .channel_mode = alc883_sixstack_modes,
8293 .input_mux = &alc883_capture_source,
8294 .unsol_event = alc888_6st_dell_unsol_event,
8295 .init_hook = alc888_6st_dell_front_automute,
8297 [ALC883_MITAC] = {
8298 .mixers = { alc883_mitac_mixer },
8299 .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
8300 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8301 .dac_nids = alc883_dac_nids,
8302 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8303 .channel_mode = alc883_3ST_2ch_modes,
8304 .input_mux = &alc883_capture_source,
8305 .unsol_event = alc883_mitac_unsol_event,
8306 .init_hook = alc883_mitac_automute,
8308 [ALC883_FUJITSU_PI2515] = {
8309 .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
8310 .init_verbs = { alc883_init_verbs,
8311 alc883_2ch_fujitsu_pi2515_verbs},
8312 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
8313 .dac_nids = alc883_dac_nids,
8314 .dig_out_nid = ALC883_DIGOUT_NID,
8315 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8316 .channel_mode = alc883_3ST_2ch_modes,
8317 .input_mux = &alc883_fujitsu_pi2515_capture_source,
8318 .unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event,
8319 .init_hook = alc883_2ch_fujitsu_pi2515_automute,
8325 * BIOS auto configuration
8327 static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
8328 hda_nid_t nid, int pin_type,
8329 int dac_idx)
8331 /* set as output */
8332 struct alc_spec *spec = codec->spec;
8333 int idx;
8335 alc_set_pin_output(codec, nid, pin_type);
8336 if (spec->multiout.dac_nids[dac_idx] == 0x25)
8337 idx = 4;
8338 else
8339 idx = spec->multiout.dac_nids[dac_idx] - 2;
8340 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
8344 static void alc883_auto_init_multi_out(struct hda_codec *codec)
8346 struct alc_spec *spec = codec->spec;
8347 int i;
8349 alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
8350 for (i = 0; i <= HDA_SIDE; i++) {
8351 hda_nid_t nid = spec->autocfg.line_out_pins[i];
8352 int pin_type = get_pin_type(spec->autocfg.line_out_type);
8353 if (nid)
8354 alc883_auto_set_output_and_unmute(codec, nid, pin_type,
8359 static void alc883_auto_init_hp_out(struct hda_codec *codec)
8361 struct alc_spec *spec = codec->spec;
8362 hda_nid_t pin;
8364 pin = spec->autocfg.hp_pins[0];
8365 if (pin) /* connect to front */
8366 /* use dac 0 */
8367 alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
8368 pin = spec->autocfg.speaker_pins[0];
8369 if (pin)
8370 alc883_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
8373 #define alc883_is_input_pin(nid) alc880_is_input_pin(nid)
8374 #define ALC883_PIN_CD_NID ALC880_PIN_CD_NID
8376 static void alc883_auto_init_analog_input(struct hda_codec *codec)
8378 struct alc_spec *spec = codec->spec;
8379 int i;
8381 for (i = 0; i < AUTO_PIN_LAST; i++) {
8382 hda_nid_t nid = spec->autocfg.input_pins[i];
8383 if (alc883_is_input_pin(nid)) {
8384 snd_hda_codec_write(codec, nid, 0,
8385 AC_VERB_SET_PIN_WIDGET_CONTROL,
8386 (i <= AUTO_PIN_FRONT_MIC ?
8387 PIN_VREF80 : PIN_IN));
8388 if (nid != ALC883_PIN_CD_NID)
8389 snd_hda_codec_write(codec, nid, 0,
8390 AC_VERB_SET_AMP_GAIN_MUTE,
8391 AMP_OUT_MUTE);
8396 #define alc883_auto_init_input_src alc882_auto_init_input_src
8398 /* almost identical with ALC880 parser... */
8399 static int alc883_parse_auto_config(struct hda_codec *codec)
8401 struct alc_spec *spec = codec->spec;
8402 int err = alc880_parse_auto_config(codec);
8404 if (err < 0)
8405 return err;
8406 else if (!err)
8407 return 0; /* no config found */
8409 err = alc_auto_add_mic_boost(codec);
8410 if (err < 0)
8411 return err;
8413 /* hack - override the init verbs */
8414 spec->init_verbs[0] = alc883_auto_init_verbs;
8415 spec->mixers[spec->num_mixers] = alc883_capture_mixer;
8416 spec->num_mixers++;
8418 return 1; /* config found */
8421 /* additional initialization for auto-configuration model */
8422 static void alc883_auto_init(struct hda_codec *codec)
8424 struct alc_spec *spec = codec->spec;
8425 alc883_auto_init_multi_out(codec);
8426 alc883_auto_init_hp_out(codec);
8427 alc883_auto_init_analog_input(codec);
8428 alc883_auto_init_input_src(codec);
8429 if (spec->unsol_event)
8430 alc_sku_automute(codec);
8433 static int patch_alc883(struct hda_codec *codec)
8435 struct alc_spec *spec;
8436 int err, board_config;
8438 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
8439 if (spec == NULL)
8440 return -ENOMEM;
8442 codec->spec = spec;
8444 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
8446 board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,
8447 alc883_models,
8448 alc883_cfg_tbl);
8449 if (board_config < 0) {
8450 printk(KERN_INFO "hda_codec: Unknown model for ALC883, "
8451 "trying auto-probe from BIOS...\n");
8452 board_config = ALC883_AUTO;
8455 if (board_config == ALC883_AUTO) {
8456 /* automatic parse from the BIOS config */
8457 err = alc883_parse_auto_config(codec);
8458 if (err < 0) {
8459 alc_free(codec);
8460 return err;
8461 } else if (!err) {
8462 printk(KERN_INFO
8463 "hda_codec: Cannot set up configuration "
8464 "from BIOS. Using base mode...\n");
8465 board_config = ALC883_3ST_2ch_DIG;
8469 if (board_config != ALC883_AUTO)
8470 setup_preset(spec, &alc883_presets[board_config]);
8472 switch (codec->vendor_id) {
8473 case 0x10ec0888:
8474 spec->stream_name_analog = "ALC888 Analog";
8475 spec->stream_name_digital = "ALC888 Digital";
8476 break;
8477 case 0x10ec0889:
8478 spec->stream_name_analog = "ALC889 Analog";
8479 spec->stream_name_digital = "ALC889 Digital";
8480 break;
8481 default:
8482 spec->stream_name_analog = "ALC883 Analog";
8483 spec->stream_name_digital = "ALC883 Digital";
8484 break;
8487 spec->stream_analog_playback = &alc883_pcm_analog_playback;
8488 spec->stream_analog_capture = &alc883_pcm_analog_capture;
8489 spec->stream_analog_alt_capture = &alc883_pcm_analog_alt_capture;
8491 spec->stream_digital_playback = &alc883_pcm_digital_playback;
8492 spec->stream_digital_capture = &alc883_pcm_digital_capture;
8494 spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
8495 spec->adc_nids = alc883_adc_nids;
8496 spec->capsrc_nids = alc883_capsrc_nids;
8498 spec->vmaster_nid = 0x0c;
8500 codec->patch_ops = alc_patch_ops;
8501 if (board_config == ALC883_AUTO)
8502 spec->init_hook = alc883_auto_init;
8504 #ifdef CONFIG_SND_HDA_POWER_SAVE
8505 if (!spec->loopback.amplist)
8506 spec->loopback.amplist = alc883_loopbacks;
8507 #endif
8509 return 0;
8513 * ALC262 support
8516 #define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
8517 #define ALC262_DIGIN_NID ALC880_DIGIN_NID
8519 #define alc262_dac_nids alc260_dac_nids
8520 #define alc262_adc_nids alc882_adc_nids
8521 #define alc262_adc_nids_alt alc882_adc_nids_alt
8522 #define alc262_capsrc_nids alc882_capsrc_nids
8523 #define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
8525 #define alc262_modes alc260_modes
8526 #define alc262_capture_source alc882_capture_source
8528 static struct snd_kcontrol_new alc262_base_mixer[] = {
8529 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8530 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8531 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8532 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8533 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8534 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8535 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8536 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8537 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8538 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
8539 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
8540 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8541 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
8542 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), */
8543 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
8544 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8545 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8546 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
8547 { } /* end */
8550 static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
8551 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8552 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8553 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8554 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8555 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8556 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8557 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8558 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8559 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8560 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
8561 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
8562 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8563 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
8564 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), */
8565 /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
8566 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8567 { } /* end */
8570 /* update HP, line and mono-out pins according to the master switch */
8571 static void alc262_hp_master_update(struct hda_codec *codec)
8573 struct alc_spec *spec = codec->spec;
8574 int val = spec->master_sw;
8576 /* HP & line-out */
8577 snd_hda_codec_write_cache(codec, 0x1b, 0,
8578 AC_VERB_SET_PIN_WIDGET_CONTROL,
8579 val ? PIN_HP : 0);
8580 snd_hda_codec_write_cache(codec, 0x15, 0,
8581 AC_VERB_SET_PIN_WIDGET_CONTROL,
8582 val ? PIN_HP : 0);
8583 /* mono (speaker) depending on the HP jack sense */
8584 val = val && !spec->jack_present;
8585 snd_hda_codec_write_cache(codec, 0x16, 0,
8586 AC_VERB_SET_PIN_WIDGET_CONTROL,
8587 val ? PIN_OUT : 0);
8590 static void alc262_hp_bpc_automute(struct hda_codec *codec)
8592 struct alc_spec *spec = codec->spec;
8593 unsigned int presence;
8594 presence = snd_hda_codec_read(codec, 0x1b, 0,
8595 AC_VERB_GET_PIN_SENSE, 0);
8596 spec->jack_present = !!(presence & AC_PINSENSE_PRESENCE);
8597 alc262_hp_master_update(codec);
8600 static void alc262_hp_bpc_unsol_event(struct hda_codec *codec, unsigned int res)
8602 if ((res >> 26) != ALC880_HP_EVENT)
8603 return;
8604 alc262_hp_bpc_automute(codec);
8607 static void alc262_hp_wildwest_automute(struct hda_codec *codec)
8609 struct alc_spec *spec = codec->spec;
8610 unsigned int presence;
8611 presence = snd_hda_codec_read(codec, 0x15, 0,
8612 AC_VERB_GET_PIN_SENSE, 0);
8613 spec->jack_present = !!(presence & AC_PINSENSE_PRESENCE);
8614 alc262_hp_master_update(codec);
8617 static void alc262_hp_wildwest_unsol_event(struct hda_codec *codec,
8618 unsigned int res)
8620 if ((res >> 26) != ALC880_HP_EVENT)
8621 return;
8622 alc262_hp_wildwest_automute(codec);
8625 static int alc262_hp_master_sw_get(struct snd_kcontrol *kcontrol,
8626 struct snd_ctl_elem_value *ucontrol)
8628 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
8629 struct alc_spec *spec = codec->spec;
8630 *ucontrol->value.integer.value = spec->master_sw;
8631 return 0;
8634 static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,
8635 struct snd_ctl_elem_value *ucontrol)
8637 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
8638 struct alc_spec *spec = codec->spec;
8639 int val = !!*ucontrol->value.integer.value;
8641 if (val == spec->master_sw)
8642 return 0;
8643 spec->master_sw = val;
8644 alc262_hp_master_update(codec);
8645 return 1;
8648 static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
8650 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8651 .name = "Master Playback Switch",
8652 .info = snd_ctl_boolean_mono_info,
8653 .get = alc262_hp_master_sw_get,
8654 .put = alc262_hp_master_sw_put,
8656 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8657 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8658 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8659 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
8660 HDA_OUTPUT),
8661 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
8662 HDA_OUTPUT),
8663 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8664 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8665 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8666 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
8667 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
8668 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8669 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8670 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8671 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8672 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8673 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
8674 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
8675 HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
8676 HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
8677 { } /* end */
8680 static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
8682 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8683 .name = "Master Playback Switch",
8684 .info = snd_ctl_boolean_mono_info,
8685 .get = alc262_hp_master_sw_get,
8686 .put = alc262_hp_master_sw_put,
8688 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8689 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8690 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8691 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8692 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
8693 HDA_OUTPUT),
8694 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
8695 HDA_OUTPUT),
8696 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
8697 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
8698 HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT),
8699 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
8700 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
8701 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8702 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8703 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
8704 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
8705 { } /* end */
8708 static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
8709 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8710 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8711 HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT),
8712 { } /* end */
8715 /* mute/unmute internal speaker according to the hp jack and mute state */
8716 static void alc262_hp_t5735_automute(struct hda_codec *codec, int force)
8718 struct alc_spec *spec = codec->spec;
8720 if (force || !spec->sense_updated) {
8721 unsigned int present;
8722 present = snd_hda_codec_read(codec, 0x15, 0,
8723 AC_VERB_GET_PIN_SENSE, 0);
8724 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
8725 spec->sense_updated = 1;
8727 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0, HDA_AMP_MUTE,
8728 spec->jack_present ? HDA_AMP_MUTE : 0);
8731 static void alc262_hp_t5735_unsol_event(struct hda_codec *codec,
8732 unsigned int res)
8734 if ((res >> 26) != ALC880_HP_EVENT)
8735 return;
8736 alc262_hp_t5735_automute(codec, 1);
8739 static void alc262_hp_t5735_init_hook(struct hda_codec *codec)
8741 alc262_hp_t5735_automute(codec, 1);
8744 static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
8745 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8746 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8747 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8748 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8749 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8750 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8751 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8752 { } /* end */
8755 static struct hda_verb alc262_hp_t5735_verbs[] = {
8756 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8757 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8759 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8763 static struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
8764 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8765 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8766 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
8767 HDA_CODEC_MUTE("Speaker Playback Switch", 0x16, 0x0, HDA_OUTPUT),
8768 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
8769 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
8770 { } /* end */
8773 static struct hda_verb alc262_hp_rp5700_verbs[] = {
8774 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8775 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8776 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8777 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8778 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8779 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
8780 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
8781 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
8782 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
8783 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
8787 static struct hda_input_mux alc262_hp_rp5700_capture_source = {
8788 .num_items = 1,
8789 .items = {
8790 { "Line", 0x1 },
8794 /* bind hp and internal speaker mute (with plug check) */
8795 static int alc262_sony_master_sw_put(struct snd_kcontrol *kcontrol,
8796 struct snd_ctl_elem_value *ucontrol)
8798 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
8799 long *valp = ucontrol->value.integer.value;
8800 int change;
8802 /* change hp mute */
8803 change = snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
8804 HDA_AMP_MUTE,
8805 valp[0] ? 0 : HDA_AMP_MUTE);
8806 change |= snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
8807 HDA_AMP_MUTE,
8808 valp[1] ? 0 : HDA_AMP_MUTE);
8809 if (change) {
8810 /* change speaker according to HP jack state */
8811 struct alc_spec *spec = codec->spec;
8812 unsigned int mute;
8813 if (spec->jack_present)
8814 mute = HDA_AMP_MUTE;
8815 else
8816 mute = snd_hda_codec_amp_read(codec, 0x15, 0,
8817 HDA_OUTPUT, 0);
8818 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
8819 HDA_AMP_MUTE, mute);
8821 return change;
8824 static struct snd_kcontrol_new alc262_sony_mixer[] = {
8825 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8827 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8828 .name = "Master Playback Switch",
8829 .info = snd_hda_mixer_amp_switch_info,
8830 .get = snd_hda_mixer_amp_switch_get,
8831 .put = alc262_sony_master_sw_put,
8832 .private_value = HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
8834 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8835 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8836 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
8837 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
8838 { } /* end */
8841 static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
8842 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8843 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8844 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8845 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8846 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8847 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
8848 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
8849 { } /* end */
8852 #define alc262_capture_mixer alc882_capture_mixer
8853 #define alc262_capture_alt_mixer alc882_capture_alt_mixer
8856 * generic initialization of ADC, input mixers and output mixers
8858 static struct hda_verb alc262_init_verbs[] = {
8860 * Unmute ADC0-2 and set the default input to mic-in
8862 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8863 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8864 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8865 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8866 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8867 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8869 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
8870 * mixer widget
8871 * Note: PASD motherboards uses the Line In 2 as the input for
8872 * front panel mic (mic 2)
8874 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
8875 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8876 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8877 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8878 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8879 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8882 * Set up output mixers (0x0c - 0x0e)
8884 /* set vol=0 to output mixers */
8885 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8886 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8887 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8888 /* set up input amps for analog loopback */
8889 /* Amp Indices: DAC = 0, mixer = 1 */
8890 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8891 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8892 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8893 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8894 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8895 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8897 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
8898 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
8899 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
8900 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
8901 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
8902 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
8904 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
8905 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
8906 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
8907 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
8908 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
8910 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8911 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
8913 /* FIXME: use matrix-type input source selection */
8914 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
8915 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
8916 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
8917 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
8918 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
8919 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
8920 /* Input mixer2 */
8921 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
8922 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
8923 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
8924 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
8925 /* Input mixer3 */
8926 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
8927 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
8928 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
8929 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
8934 static struct hda_verb alc262_hippo_unsol_verbs[] = {
8935 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
8936 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8940 static struct hda_verb alc262_hippo1_unsol_verbs[] = {
8941 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
8942 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
8943 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
8945 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
8946 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8950 static struct hda_verb alc262_sony_unsol_verbs[] = {
8951 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
8952 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8953 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic
8955 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
8956 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8960 /* mute/unmute internal speaker according to the hp jack and mute state */
8961 static void alc262_hippo_automute(struct hda_codec *codec)
8963 struct alc_spec *spec = codec->spec;
8964 unsigned int mute;
8965 unsigned int present;
8967 /* need to execute and sync at first */
8968 snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
8969 present = snd_hda_codec_read(codec, 0x15, 0,
8970 AC_VERB_GET_PIN_SENSE, 0);
8971 spec->jack_present = (present & 0x80000000) != 0;
8972 if (spec->jack_present) {
8973 /* mute internal speaker */
8974 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
8975 HDA_AMP_MUTE, HDA_AMP_MUTE);
8976 } else {
8977 /* unmute internal speaker if necessary */
8978 mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
8979 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
8980 HDA_AMP_MUTE, mute);
8984 /* unsolicited event for HP jack sensing */
8985 static void alc262_hippo_unsol_event(struct hda_codec *codec,
8986 unsigned int res)
8988 if ((res >> 26) != ALC880_HP_EVENT)
8989 return;
8990 alc262_hippo_automute(codec);
8993 static void alc262_hippo1_automute(struct hda_codec *codec)
8995 unsigned int mute;
8996 unsigned int present;
8998 snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
8999 present = snd_hda_codec_read(codec, 0x1b, 0,
9000 AC_VERB_GET_PIN_SENSE, 0);
9001 present = (present & 0x80000000) != 0;
9002 if (present) {
9003 /* mute internal speaker */
9004 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9005 HDA_AMP_MUTE, HDA_AMP_MUTE);
9006 } else {
9007 /* unmute internal speaker if necessary */
9008 mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
9009 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9010 HDA_AMP_MUTE, mute);
9014 /* unsolicited event for HP jack sensing */
9015 static void alc262_hippo1_unsol_event(struct hda_codec *codec,
9016 unsigned int res)
9018 if ((res >> 26) != ALC880_HP_EVENT)
9019 return;
9020 alc262_hippo1_automute(codec);
9024 * nec model
9025 * 0x15 = headphone
9026 * 0x16 = internal speaker
9027 * 0x18 = external mic
9030 static struct snd_kcontrol_new alc262_nec_mixer[] = {
9031 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
9032 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
9034 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9035 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9036 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
9038 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
9039 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9040 { } /* end */
9043 static struct hda_verb alc262_nec_verbs[] = {
9044 /* Unmute Speaker */
9045 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9047 /* Headphone */
9048 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
9049 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9051 /* External mic to headphone */
9052 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9053 /* External mic to speaker */
9054 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9059 * fujitsu model
9060 * 0x14 = headphone/spdif-out, 0x15 = internal speaker,
9061 * 0x1b = port replicator headphone out
9064 #define ALC_HP_EVENT 0x37
9066 static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
9067 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
9068 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9069 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
9070 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9074 static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
9075 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
9076 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9080 static struct hda_input_mux alc262_fujitsu_capture_source = {
9081 .num_items = 3,
9082 .items = {
9083 { "Mic", 0x0 },
9084 { "Int Mic", 0x1 },
9085 { "CD", 0x4 },
9089 static struct hda_input_mux alc262_HP_capture_source = {
9090 .num_items = 5,
9091 .items = {
9092 { "Mic", 0x0 },
9093 { "Front Mic", 0x1 },
9094 { "Line", 0x2 },
9095 { "CD", 0x4 },
9096 { "AUX IN", 0x6 },
9100 static struct hda_input_mux alc262_HP_D7000_capture_source = {
9101 .num_items = 4,
9102 .items = {
9103 { "Mic", 0x0 },
9104 { "Front Mic", 0x2 },
9105 { "Line", 0x1 },
9106 { "CD", 0x4 },
9110 /* mute/unmute internal speaker according to the hp jacks and mute state */
9111 static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
9113 struct alc_spec *spec = codec->spec;
9114 unsigned int mute;
9116 if (force || !spec->sense_updated) {
9117 unsigned int present;
9118 /* need to execute and sync at first */
9119 snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
9120 /* check laptop HP jack */
9121 present = snd_hda_codec_read(codec, 0x14, 0,
9122 AC_VERB_GET_PIN_SENSE, 0);
9123 /* need to execute and sync at first */
9124 snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
9125 /* check docking HP jack */
9126 present |= snd_hda_codec_read(codec, 0x1b, 0,
9127 AC_VERB_GET_PIN_SENSE, 0);
9128 if (present & AC_PINSENSE_PRESENCE)
9129 spec->jack_present = 1;
9130 else
9131 spec->jack_present = 0;
9132 spec->sense_updated = 1;
9134 /* unmute internal speaker only if both HPs are unplugged and
9135 * master switch is on
9137 if (spec->jack_present)
9138 mute = HDA_AMP_MUTE;
9139 else
9140 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
9141 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9142 HDA_AMP_MUTE, mute);
9145 /* unsolicited event for HP jack sensing */
9146 static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
9147 unsigned int res)
9149 if ((res >> 26) != ALC_HP_EVENT)
9150 return;
9151 alc262_fujitsu_automute(codec, 1);
9154 static void alc262_fujitsu_init_hook(struct hda_codec *codec)
9156 alc262_fujitsu_automute(codec, 1);
9159 /* bind volumes of both NID 0x0c and 0x0d */
9160 static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
9161 .ops = &snd_hda_bind_vol,
9162 .values = {
9163 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
9164 HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
9169 /* mute/unmute internal speaker according to the hp jack and mute state */
9170 static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
9172 struct alc_spec *spec = codec->spec;
9173 unsigned int mute;
9175 if (force || !spec->sense_updated) {
9176 unsigned int present_int_hp;
9177 /* need to execute and sync at first */
9178 snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
9179 present_int_hp = snd_hda_codec_read(codec, 0x1b, 0,
9180 AC_VERB_GET_PIN_SENSE, 0);
9181 spec->jack_present = (present_int_hp & 0x80000000) != 0;
9182 spec->sense_updated = 1;
9184 if (spec->jack_present) {
9185 /* mute internal speaker */
9186 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9187 HDA_AMP_MUTE, HDA_AMP_MUTE);
9188 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
9189 HDA_AMP_MUTE, HDA_AMP_MUTE);
9190 } else {
9191 /* unmute internal speaker if necessary */
9192 mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
9193 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9194 HDA_AMP_MUTE, mute);
9195 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
9196 HDA_AMP_MUTE, mute);
9200 /* unsolicited event for HP jack sensing */
9201 static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
9202 unsigned int res)
9204 if ((res >> 26) != ALC_HP_EVENT)
9205 return;
9206 alc262_lenovo_3000_automute(codec, 1);
9209 /* bind hp and internal speaker mute (with plug check) */
9210 static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
9211 struct snd_ctl_elem_value *ucontrol)
9213 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9214 long *valp = ucontrol->value.integer.value;
9215 int change;
9217 change = snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9218 HDA_AMP_MUTE,
9219 valp ? 0 : HDA_AMP_MUTE);
9220 change |= snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
9221 HDA_AMP_MUTE,
9222 valp ? 0 : HDA_AMP_MUTE);
9224 if (change)
9225 alc262_fujitsu_automute(codec, 0);
9226 return change;
9229 static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
9230 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
9232 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9233 .name = "Master Playback Switch",
9234 .info = snd_hda_mixer_amp_switch_info,
9235 .get = snd_hda_mixer_amp_switch_get,
9236 .put = alc262_fujitsu_master_sw_put,
9237 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
9239 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9240 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9241 HDA_CODEC_VOLUME("PC Speaker Volume", 0x0b, 0x05, HDA_INPUT),
9242 HDA_CODEC_MUTE("PC Speaker Switch", 0x0b, 0x05, HDA_INPUT),
9243 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
9244 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9245 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9246 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
9247 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9248 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9249 { } /* end */
9252 /* bind hp and internal speaker mute (with plug check) */
9253 static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
9254 struct snd_ctl_elem_value *ucontrol)
9256 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9257 long *valp = ucontrol->value.integer.value;
9258 int change;
9260 change = snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
9261 HDA_AMP_MUTE,
9262 valp ? 0 : HDA_AMP_MUTE);
9264 if (change)
9265 alc262_lenovo_3000_automute(codec, 0);
9266 return change;
9269 static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
9270 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
9272 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9273 .name = "Master Playback Switch",
9274 .info = snd_hda_mixer_amp_switch_info,
9275 .get = snd_hda_mixer_amp_switch_get,
9276 .put = alc262_lenovo_3000_master_sw_put,
9277 .private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
9279 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9280 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9281 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
9282 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9283 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9284 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
9285 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9286 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9287 { } /* end */
9290 /* additional init verbs for Benq laptops */
9291 static struct hda_verb alc262_EAPD_verbs[] = {
9292 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
9293 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
9297 static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
9298 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9299 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
9301 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
9302 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
9306 /* Samsung Q1 Ultra Vista model setup */
9307 static struct snd_kcontrol_new alc262_ultra_mixer[] = {
9308 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
9309 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
9310 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
9311 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
9312 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
9313 HDA_CODEC_VOLUME("Headphone Mic Boost", 0x15, 0, HDA_INPUT),
9314 { } /* end */
9317 static struct hda_verb alc262_ultra_verbs[] = {
9318 /* output mixer */
9319 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9320 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9321 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9322 /* speaker */
9323 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9324 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9325 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9326 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9327 /* HP */
9328 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9329 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9330 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9331 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9332 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
9333 /* internal mic */
9334 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9335 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9336 /* ADC, choose mic */
9337 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9338 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9339 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9340 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
9341 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
9342 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
9343 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
9344 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
9345 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
9346 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
9350 /* mute/unmute internal speaker according to the hp jack and mute state */
9351 static void alc262_ultra_automute(struct hda_codec *codec)
9353 struct alc_spec *spec = codec->spec;
9354 unsigned int mute;
9356 mute = 0;
9357 /* auto-mute only when HP is used as HP */
9358 if (!spec->cur_mux[0]) {
9359 unsigned int present;
9360 /* need to execute and sync at first */
9361 snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
9362 present = snd_hda_codec_read(codec, 0x15, 0,
9363 AC_VERB_GET_PIN_SENSE, 0);
9364 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
9365 if (spec->jack_present)
9366 mute = HDA_AMP_MUTE;
9368 /* mute/unmute internal speaker */
9369 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9370 HDA_AMP_MUTE, mute);
9371 /* mute/unmute HP */
9372 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9373 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
9376 /* unsolicited event for HP jack sensing */
9377 static void alc262_ultra_unsol_event(struct hda_codec *codec,
9378 unsigned int res)
9380 if ((res >> 26) != ALC880_HP_EVENT)
9381 return;
9382 alc262_ultra_automute(codec);
9385 static struct hda_input_mux alc262_ultra_capture_source = {
9386 .num_items = 2,
9387 .items = {
9388 { "Mic", 0x1 },
9389 { "Headphone", 0x7 },
9393 static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
9394 struct snd_ctl_elem_value *ucontrol)
9396 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9397 struct alc_spec *spec = codec->spec;
9398 int ret;
9400 ret = alc882_mux_enum_put(kcontrol, ucontrol);
9401 if (!ret)
9402 return 0;
9403 /* reprogram the HP pin as mic or HP according to the input source */
9404 snd_hda_codec_write_cache(codec, 0x15, 0,
9405 AC_VERB_SET_PIN_WIDGET_CONTROL,
9406 spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
9407 alc262_ultra_automute(codec); /* mute/unmute HP */
9408 return ret;
9411 static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
9412 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
9413 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
9415 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9416 .name = "Capture Source",
9417 .info = alc882_mux_enum_info,
9418 .get = alc882_mux_enum_get,
9419 .put = alc262_ultra_mux_enum_put,
9421 { } /* end */
9424 /* add playback controls from the parsed DAC table */
9425 static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
9426 const struct auto_pin_cfg *cfg)
9428 hda_nid_t nid;
9429 int err;
9431 spec->multiout.num_dacs = 1; /* only use one dac */
9432 spec->multiout.dac_nids = spec->private_dac_nids;
9433 spec->multiout.dac_nids[0] = 2;
9435 nid = cfg->line_out_pins[0];
9436 if (nid) {
9437 err = add_control(spec, ALC_CTL_WIDGET_VOL,
9438 "Front Playback Volume",
9439 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT));
9440 if (err < 0)
9441 return err;
9442 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
9443 "Front Playback Switch",
9444 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
9445 if (err < 0)
9446 return err;
9449 nid = cfg->speaker_pins[0];
9450 if (nid) {
9451 if (nid == 0x16) {
9452 err = add_control(spec, ALC_CTL_WIDGET_VOL,
9453 "Speaker Playback Volume",
9454 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
9455 HDA_OUTPUT));
9456 if (err < 0)
9457 return err;
9458 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
9459 "Speaker Playback Switch",
9460 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
9461 HDA_OUTPUT));
9462 if (err < 0)
9463 return err;
9464 } else {
9465 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
9466 "Speaker Playback Switch",
9467 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
9468 HDA_OUTPUT));
9469 if (err < 0)
9470 return err;
9473 nid = cfg->hp_pins[0];
9474 if (nid) {
9475 /* spec->multiout.hp_nid = 2; */
9476 if (nid == 0x16) {
9477 err = add_control(spec, ALC_CTL_WIDGET_VOL,
9478 "Headphone Playback Volume",
9479 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
9480 HDA_OUTPUT));
9481 if (err < 0)
9482 return err;
9483 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
9484 "Headphone Playback Switch",
9485 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
9486 HDA_OUTPUT));
9487 if (err < 0)
9488 return err;
9489 } else {
9490 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
9491 "Headphone Playback Switch",
9492 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
9493 HDA_OUTPUT));
9494 if (err < 0)
9495 return err;
9498 return 0;
9501 /* identical with ALC880 */
9502 #define alc262_auto_create_analog_input_ctls \
9503 alc880_auto_create_analog_input_ctls
9506 * generic initialization of ADC, input mixers and output mixers
9508 static struct hda_verb alc262_volume_init_verbs[] = {
9510 * Unmute ADC0-2 and set the default input to mic-in
9512 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
9513 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9514 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
9515 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9516 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
9517 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9519 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
9520 * mixer widget
9521 * Note: PASD motherboards uses the Line In 2 as the input for
9522 * front panel mic (mic 2)
9524 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
9525 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9526 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9527 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
9528 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
9529 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
9532 * Set up output mixers (0x0c - 0x0f)
9534 /* set vol=0 to output mixers */
9535 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9536 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9537 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9539 /* set up input amps for analog loopback */
9540 /* Amp Indices: DAC = 0, mixer = 1 */
9541 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9542 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9543 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9544 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9545 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9546 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9548 /* FIXME: use matrix-type input source selection */
9549 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
9550 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
9551 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
9552 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
9553 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
9554 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
9555 /* Input mixer2 */
9556 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
9557 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
9558 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
9559 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
9560 /* Input mixer3 */
9561 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
9562 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
9563 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
9564 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
9569 static struct hda_verb alc262_HP_BPC_init_verbs[] = {
9571 * Unmute ADC0-2 and set the default input to mic-in
9573 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
9574 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9575 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
9576 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9577 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
9578 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9580 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
9581 * mixer widget
9582 * Note: PASD motherboards uses the Line In 2 as the input for
9583 * front panel mic (mic 2)
9585 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
9586 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9587 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9588 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
9589 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
9590 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
9591 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
9592 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
9595 * Set up output mixers (0x0c - 0x0e)
9597 /* set vol=0 to output mixers */
9598 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9599 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9600 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9602 /* set up input amps for analog loopback */
9603 /* Amp Indices: DAC = 0, mixer = 1 */
9604 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9605 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9606 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9607 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9608 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9609 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9611 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9612 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9613 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9615 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9616 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9618 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9619 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9621 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
9622 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
9623 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
9624 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
9625 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
9627 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
9628 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
9629 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
9630 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
9631 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
9632 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
9635 /* FIXME: use matrix-type input source selection */
9636 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
9637 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
9638 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
9639 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
9640 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
9641 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
9642 /* Input mixer2 */
9643 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
9644 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
9645 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
9646 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
9647 /* Input mixer3 */
9648 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
9649 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
9650 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
9651 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
9653 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9658 static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
9660 * Unmute ADC0-2 and set the default input to mic-in
9662 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
9663 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9664 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
9665 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9666 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
9667 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9669 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
9670 * mixer widget
9671 * Note: PASD motherboards uses the Line In 2 as the input for front
9672 * panel mic (mic 2)
9674 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
9675 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9676 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9677 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
9678 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
9679 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
9680 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
9681 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
9682 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
9684 * Set up output mixers (0x0c - 0x0e)
9686 /* set vol=0 to output mixers */
9687 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9688 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9689 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9691 /* set up input amps for analog loopback */
9692 /* Amp Indices: DAC = 0, mixer = 1 */
9693 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9694 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9695 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9696 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9697 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9698 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9701 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */
9702 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */
9703 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */
9704 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */
9705 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
9706 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */
9707 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */
9709 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9710 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9712 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9713 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
9715 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
9716 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
9717 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
9718 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
9719 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
9720 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
9722 /* FIXME: use matrix-type input source selection */
9723 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
9724 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
9725 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
9726 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
9727 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
9728 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
9729 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
9730 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
9731 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
9732 /* Input mixer2 */
9733 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
9734 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
9735 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
9736 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
9737 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
9738 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
9739 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
9740 /* Input mixer3 */
9741 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
9742 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
9743 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
9744 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
9745 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
9746 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
9747 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
9749 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9754 #ifdef CONFIG_SND_HDA_POWER_SAVE
9755 #define alc262_loopbacks alc880_loopbacks
9756 #endif
9758 /* pcm configuration: identiacal with ALC880 */
9759 #define alc262_pcm_analog_playback alc880_pcm_analog_playback
9760 #define alc262_pcm_analog_capture alc880_pcm_analog_capture
9761 #define alc262_pcm_digital_playback alc880_pcm_digital_playback
9762 #define alc262_pcm_digital_capture alc880_pcm_digital_capture
9765 * BIOS auto configuration
9767 static int alc262_parse_auto_config(struct hda_codec *codec)
9769 struct alc_spec *spec = codec->spec;
9770 int err;
9771 static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
9773 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
9774 alc262_ignore);
9775 if (err < 0)
9776 return err;
9777 if (!spec->autocfg.line_outs)
9778 return 0; /* can't find valid BIOS pin config */
9779 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
9780 if (err < 0)
9781 return err;
9782 err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg);
9783 if (err < 0)
9784 return err;
9786 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
9788 if (spec->autocfg.dig_out_pin)
9789 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
9790 if (spec->autocfg.dig_in_pin)
9791 spec->dig_in_nid = ALC262_DIGIN_NID;
9793 if (spec->kctl_alloc)
9794 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
9796 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
9797 spec->num_mux_defs = 1;
9798 spec->input_mux = &spec->private_imux;
9800 err = alc_auto_add_mic_boost(codec);
9801 if (err < 0)
9802 return err;
9804 store_pin_configs(codec);
9805 return 1;
9808 #define alc262_auto_init_multi_out alc882_auto_init_multi_out
9809 #define alc262_auto_init_hp_out alc882_auto_init_hp_out
9810 #define alc262_auto_init_analog_input alc882_auto_init_analog_input
9811 #define alc262_auto_init_input_src alc882_auto_init_input_src
9814 /* init callback for auto-configuration model -- overriding the default init */
9815 static void alc262_auto_init(struct hda_codec *codec)
9817 struct alc_spec *spec = codec->spec;
9818 alc262_auto_init_multi_out(codec);
9819 alc262_auto_init_hp_out(codec);
9820 alc262_auto_init_analog_input(codec);
9821 alc262_auto_init_input_src(codec);
9822 if (spec->unsol_event)
9823 alc_sku_automute(codec);
9827 * configuration and preset
9829 static const char *alc262_models[ALC262_MODEL_LAST] = {
9830 [ALC262_BASIC] = "basic",
9831 [ALC262_HIPPO] = "hippo",
9832 [ALC262_HIPPO_1] = "hippo_1",
9833 [ALC262_FUJITSU] = "fujitsu",
9834 [ALC262_HP_BPC] = "hp-bpc",
9835 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
9836 [ALC262_HP_TC_T5735] = "hp-tc-t5735",
9837 [ALC262_HP_RP5700] = "hp-rp5700",
9838 [ALC262_BENQ_ED8] = "benq",
9839 [ALC262_BENQ_T31] = "benq-t31",
9840 [ALC262_SONY_ASSAMD] = "sony-assamd",
9841 [ALC262_ULTRA] = "ultra",
9842 [ALC262_LENOVO_3000] = "lenovo-3000",
9843 [ALC262_NEC] = "nec",
9844 [ALC262_AUTO] = "auto",
9847 static struct snd_pci_quirk alc262_cfg_tbl[] = {
9848 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
9849 SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
9850 SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC),
9851 SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC),
9852 SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC),
9853 SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC),
9854 SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC),
9855 SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC),
9856 SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC),
9857 SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC),
9858 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
9859 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
9860 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
9861 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
9862 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
9863 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
9864 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
9865 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
9866 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
9867 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
9868 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
9869 SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735",
9870 ALC262_HP_TC_T5735),
9871 SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700),
9872 SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
9873 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
9874 SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
9875 SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
9876 SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
9877 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
9878 ALC262_SONY_ASSAMD),
9879 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
9880 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
9881 SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
9882 SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA),
9883 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
9884 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
9885 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
9886 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
9890 static struct alc_config_preset alc262_presets[] = {
9891 [ALC262_BASIC] = {
9892 .mixers = { alc262_base_mixer },
9893 .init_verbs = { alc262_init_verbs },
9894 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
9895 .dac_nids = alc262_dac_nids,
9896 .hp_nid = 0x03,
9897 .num_channel_mode = ARRAY_SIZE(alc262_modes),
9898 .channel_mode = alc262_modes,
9899 .input_mux = &alc262_capture_source,
9901 [ALC262_HIPPO] = {
9902 .mixers = { alc262_base_mixer },
9903 .init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},
9904 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
9905 .dac_nids = alc262_dac_nids,
9906 .hp_nid = 0x03,
9907 .dig_out_nid = ALC262_DIGOUT_NID,
9908 .num_channel_mode = ARRAY_SIZE(alc262_modes),
9909 .channel_mode = alc262_modes,
9910 .input_mux = &alc262_capture_source,
9911 .unsol_event = alc262_hippo_unsol_event,
9912 .init_hook = alc262_hippo_automute,
9914 [ALC262_HIPPO_1] = {
9915 .mixers = { alc262_hippo1_mixer },
9916 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
9917 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
9918 .dac_nids = alc262_dac_nids,
9919 .hp_nid = 0x02,
9920 .dig_out_nid = ALC262_DIGOUT_NID,
9921 .num_channel_mode = ARRAY_SIZE(alc262_modes),
9922 .channel_mode = alc262_modes,
9923 .input_mux = &alc262_capture_source,
9924 .unsol_event = alc262_hippo1_unsol_event,
9925 .init_hook = alc262_hippo1_automute,
9927 [ALC262_FUJITSU] = {
9928 .mixers = { alc262_fujitsu_mixer },
9929 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
9930 alc262_fujitsu_unsol_verbs },
9931 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
9932 .dac_nids = alc262_dac_nids,
9933 .hp_nid = 0x03,
9934 .dig_out_nid = ALC262_DIGOUT_NID,
9935 .num_channel_mode = ARRAY_SIZE(alc262_modes),
9936 .channel_mode = alc262_modes,
9937 .input_mux = &alc262_fujitsu_capture_source,
9938 .unsol_event = alc262_fujitsu_unsol_event,
9939 .init_hook = alc262_fujitsu_init_hook,
9941 [ALC262_HP_BPC] = {
9942 .mixers = { alc262_HP_BPC_mixer },
9943 .init_verbs = { alc262_HP_BPC_init_verbs },
9944 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
9945 .dac_nids = alc262_dac_nids,
9946 .hp_nid = 0x03,
9947 .num_channel_mode = ARRAY_SIZE(alc262_modes),
9948 .channel_mode = alc262_modes,
9949 .input_mux = &alc262_HP_capture_source,
9950 .unsol_event = alc262_hp_bpc_unsol_event,
9951 .init_hook = alc262_hp_bpc_automute,
9953 [ALC262_HP_BPC_D7000_WF] = {
9954 .mixers = { alc262_HP_BPC_WildWest_mixer },
9955 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
9956 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
9957 .dac_nids = alc262_dac_nids,
9958 .hp_nid = 0x03,
9959 .num_channel_mode = ARRAY_SIZE(alc262_modes),
9960 .channel_mode = alc262_modes,
9961 .input_mux = &alc262_HP_D7000_capture_source,
9962 .unsol_event = alc262_hp_wildwest_unsol_event,
9963 .init_hook = alc262_hp_wildwest_automute,
9965 [ALC262_HP_BPC_D7000_WL] = {
9966 .mixers = { alc262_HP_BPC_WildWest_mixer,
9967 alc262_HP_BPC_WildWest_option_mixer },
9968 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
9969 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
9970 .dac_nids = alc262_dac_nids,
9971 .hp_nid = 0x03,
9972 .num_channel_mode = ARRAY_SIZE(alc262_modes),
9973 .channel_mode = alc262_modes,
9974 .input_mux = &alc262_HP_D7000_capture_source,
9975 .unsol_event = alc262_hp_wildwest_unsol_event,
9976 .init_hook = alc262_hp_wildwest_automute,
9978 [ALC262_HP_TC_T5735] = {
9979 .mixers = { alc262_hp_t5735_mixer },
9980 .init_verbs = { alc262_init_verbs, alc262_hp_t5735_verbs },
9981 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
9982 .dac_nids = alc262_dac_nids,
9983 .hp_nid = 0x03,
9984 .num_channel_mode = ARRAY_SIZE(alc262_modes),
9985 .channel_mode = alc262_modes,
9986 .input_mux = &alc262_capture_source,
9987 .unsol_event = alc262_hp_t5735_unsol_event,
9988 .init_hook = alc262_hp_t5735_init_hook,
9990 [ALC262_HP_RP5700] = {
9991 .mixers = { alc262_hp_rp5700_mixer },
9992 .init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs },
9993 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
9994 .dac_nids = alc262_dac_nids,
9995 .num_channel_mode = ARRAY_SIZE(alc262_modes),
9996 .channel_mode = alc262_modes,
9997 .input_mux = &alc262_hp_rp5700_capture_source,
9999 [ALC262_BENQ_ED8] = {
10000 .mixers = { alc262_base_mixer },
10001 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
10002 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
10003 .dac_nids = alc262_dac_nids,
10004 .hp_nid = 0x03,
10005 .num_channel_mode = ARRAY_SIZE(alc262_modes),
10006 .channel_mode = alc262_modes,
10007 .input_mux = &alc262_capture_source,
10009 [ALC262_SONY_ASSAMD] = {
10010 .mixers = { alc262_sony_mixer },
10011 .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
10012 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
10013 .dac_nids = alc262_dac_nids,
10014 .hp_nid = 0x02,
10015 .num_channel_mode = ARRAY_SIZE(alc262_modes),
10016 .channel_mode = alc262_modes,
10017 .input_mux = &alc262_capture_source,
10018 .unsol_event = alc262_hippo_unsol_event,
10019 .init_hook = alc262_hippo_automute,
10021 [ALC262_BENQ_T31] = {
10022 .mixers = { alc262_benq_t31_mixer },
10023 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs, alc262_hippo_unsol_verbs },
10024 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
10025 .dac_nids = alc262_dac_nids,
10026 .hp_nid = 0x03,
10027 .num_channel_mode = ARRAY_SIZE(alc262_modes),
10028 .channel_mode = alc262_modes,
10029 .input_mux = &alc262_capture_source,
10030 .unsol_event = alc262_hippo_unsol_event,
10031 .init_hook = alc262_hippo_automute,
10033 [ALC262_ULTRA] = {
10034 .mixers = { alc262_ultra_mixer, alc262_ultra_capture_mixer },
10035 .init_verbs = { alc262_ultra_verbs },
10036 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
10037 .dac_nids = alc262_dac_nids,
10038 .num_channel_mode = ARRAY_SIZE(alc262_modes),
10039 .channel_mode = alc262_modes,
10040 .input_mux = &alc262_ultra_capture_source,
10041 .adc_nids = alc262_adc_nids, /* ADC0 */
10042 .capsrc_nids = alc262_capsrc_nids,
10043 .num_adc_nids = 1, /* single ADC */
10044 .unsol_event = alc262_ultra_unsol_event,
10045 .init_hook = alc262_ultra_automute,
10047 [ALC262_LENOVO_3000] = {
10048 .mixers = { alc262_lenovo_3000_mixer },
10049 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
10050 alc262_lenovo_3000_unsol_verbs },
10051 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
10052 .dac_nids = alc262_dac_nids,
10053 .hp_nid = 0x03,
10054 .dig_out_nid = ALC262_DIGOUT_NID,
10055 .num_channel_mode = ARRAY_SIZE(alc262_modes),
10056 .channel_mode = alc262_modes,
10057 .input_mux = &alc262_fujitsu_capture_source,
10058 .unsol_event = alc262_lenovo_3000_unsol_event,
10060 [ALC262_NEC] = {
10061 .mixers = { alc262_nec_mixer },
10062 .init_verbs = { alc262_nec_verbs },
10063 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
10064 .dac_nids = alc262_dac_nids,
10065 .hp_nid = 0x03,
10066 .num_channel_mode = ARRAY_SIZE(alc262_modes),
10067 .channel_mode = alc262_modes,
10068 .input_mux = &alc262_capture_source,
10072 static int patch_alc262(struct hda_codec *codec)
10074 struct alc_spec *spec;
10075 int board_config;
10076 int err;
10078 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
10079 if (spec == NULL)
10080 return -ENOMEM;
10082 codec->spec = spec;
10083 #if 0
10084 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
10085 * under-run
10088 int tmp;
10089 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
10090 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
10091 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
10092 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
10094 #endif
10096 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
10098 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
10099 alc262_models,
10100 alc262_cfg_tbl);
10102 if (board_config < 0) {
10103 printk(KERN_INFO "hda_codec: Unknown model for ALC262, "
10104 "trying auto-probe from BIOS...\n");
10105 board_config = ALC262_AUTO;
10108 if (board_config == ALC262_AUTO) {
10109 /* automatic parse from the BIOS config */
10110 err = alc262_parse_auto_config(codec);
10111 if (err < 0) {
10112 alc_free(codec);
10113 return err;
10114 } else if (!err) {
10115 printk(KERN_INFO
10116 "hda_codec: Cannot set up configuration "
10117 "from BIOS. Using base mode...\n");
10118 board_config = ALC262_BASIC;
10122 if (board_config != ALC262_AUTO)
10123 setup_preset(spec, &alc262_presets[board_config]);
10125 spec->stream_name_analog = "ALC262 Analog";
10126 spec->stream_analog_playback = &alc262_pcm_analog_playback;
10127 spec->stream_analog_capture = &alc262_pcm_analog_capture;
10129 spec->stream_name_digital = "ALC262 Digital";
10130 spec->stream_digital_playback = &alc262_pcm_digital_playback;
10131 spec->stream_digital_capture = &alc262_pcm_digital_capture;
10133 if (!spec->adc_nids && spec->input_mux) {
10134 /* check whether NID 0x07 is valid */
10135 unsigned int wcap = get_wcaps(codec, 0x07);
10137 /* get type */
10138 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
10139 if (wcap != AC_WID_AUD_IN) {
10140 spec->adc_nids = alc262_adc_nids_alt;
10141 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
10142 spec->capsrc_nids = alc262_capsrc_nids_alt;
10143 spec->mixers[spec->num_mixers] =
10144 alc262_capture_alt_mixer;
10145 spec->num_mixers++;
10146 } else {
10147 spec->adc_nids = alc262_adc_nids;
10148 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
10149 spec->capsrc_nids = alc262_capsrc_nids;
10150 spec->mixers[spec->num_mixers] = alc262_capture_mixer;
10151 spec->num_mixers++;
10155 spec->vmaster_nid = 0x0c;
10157 codec->patch_ops = alc_patch_ops;
10158 if (board_config == ALC262_AUTO)
10159 spec->init_hook = alc262_auto_init;
10160 #ifdef CONFIG_SND_HDA_POWER_SAVE
10161 if (!spec->loopback.amplist)
10162 spec->loopback.amplist = alc262_loopbacks;
10163 #endif
10165 return 0;
10169 * ALC268 channel source setting (2 channel)
10171 #define ALC268_DIGOUT_NID ALC880_DIGOUT_NID
10172 #define alc268_modes alc260_modes
10174 static hda_nid_t alc268_dac_nids[2] = {
10175 /* front, hp */
10176 0x02, 0x03
10179 static hda_nid_t alc268_adc_nids[2] = {
10180 /* ADC0-1 */
10181 0x08, 0x07
10184 static hda_nid_t alc268_adc_nids_alt[1] = {
10185 /* ADC0 */
10186 0x08
10189 static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
10191 static struct snd_kcontrol_new alc268_base_mixer[] = {
10192 /* output mixer control */
10193 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
10194 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
10195 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
10196 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10197 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10198 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
10199 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
10203 /* bind Beep switches of both NID 0x0f and 0x10 */
10204 static struct hda_bind_ctls alc268_bind_beep_sw = {
10205 .ops = &snd_hda_bind_sw,
10206 .values = {
10207 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
10208 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
10213 static struct snd_kcontrol_new alc268_beep_mixer[] = {
10214 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
10215 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
10219 static struct hda_verb alc268_eapd_verbs[] = {
10220 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
10221 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
10225 /* Toshiba specific */
10226 #define alc268_toshiba_automute alc262_hippo_automute
10228 static struct hda_verb alc268_toshiba_verbs[] = {
10229 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
10230 { } /* end */
10233 /* Acer specific */
10234 /* bind volumes of both NID 0x02 and 0x03 */
10235 static struct hda_bind_ctls alc268_acer_bind_master_vol = {
10236 .ops = &snd_hda_bind_vol,
10237 .values = {
10238 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
10239 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
10244 /* mute/unmute internal speaker according to the hp jack and mute state */
10245 static void alc268_acer_automute(struct hda_codec *codec, int force)
10247 struct alc_spec *spec = codec->spec;
10248 unsigned int mute;
10250 if (force || !spec->sense_updated) {
10251 unsigned int present;
10252 present = snd_hda_codec_read(codec, 0x14, 0,
10253 AC_VERB_GET_PIN_SENSE, 0);
10254 spec->jack_present = (present & 0x80000000) != 0;
10255 spec->sense_updated = 1;
10257 if (spec->jack_present)
10258 mute = HDA_AMP_MUTE; /* mute internal speaker */
10259 else /* unmute internal speaker if necessary */
10260 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
10261 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
10262 HDA_AMP_MUTE, mute);
10266 /* bind hp and internal speaker mute (with plug check) */
10267 static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
10268 struct snd_ctl_elem_value *ucontrol)
10270 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
10271 long *valp = ucontrol->value.integer.value;
10272 int change;
10274 change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
10275 HDA_AMP_MUTE,
10276 valp[0] ? 0 : HDA_AMP_MUTE);
10277 change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
10278 HDA_AMP_MUTE,
10279 valp[1] ? 0 : HDA_AMP_MUTE);
10280 if (change)
10281 alc268_acer_automute(codec, 0);
10282 return change;
10285 static struct snd_kcontrol_new alc268_acer_mixer[] = {
10286 /* output mixer control */
10287 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
10289 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10290 .name = "Master Playback Switch",
10291 .info = snd_hda_mixer_amp_switch_info,
10292 .get = snd_hda_mixer_amp_switch_get,
10293 .put = alc268_acer_master_sw_put,
10294 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
10296 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10297 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
10298 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
10302 static struct hda_verb alc268_acer_verbs[] = {
10303 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
10304 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
10305 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10306 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10307 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
10308 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
10310 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
10314 /* unsolicited event for HP jack sensing */
10315 static void alc268_toshiba_unsol_event(struct hda_codec *codec,
10316 unsigned int res)
10318 if ((res >> 26) != ALC880_HP_EVENT)
10319 return;
10320 alc268_toshiba_automute(codec);
10323 static void alc268_acer_unsol_event(struct hda_codec *codec,
10324 unsigned int res)
10326 if ((res >> 26) != ALC880_HP_EVENT)
10327 return;
10328 alc268_acer_automute(codec, 1);
10331 static void alc268_acer_init_hook(struct hda_codec *codec)
10333 alc268_acer_automute(codec, 1);
10336 static struct snd_kcontrol_new alc268_dell_mixer[] = {
10337 /* output mixer control */
10338 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
10339 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
10340 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
10341 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10342 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10343 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
10347 static struct hda_verb alc268_dell_verbs[] = {
10348 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10349 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10350 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
10354 /* mute/unmute internal speaker according to the hp jack and mute state */
10355 static void alc268_dell_automute(struct hda_codec *codec)
10357 unsigned int present;
10358 unsigned int mute;
10360 present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0);
10361 if (present & 0x80000000)
10362 mute = HDA_AMP_MUTE;
10363 else
10364 mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
10365 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
10366 HDA_AMP_MUTE, mute);
10369 static void alc268_dell_unsol_event(struct hda_codec *codec,
10370 unsigned int res)
10372 if ((res >> 26) != ALC880_HP_EVENT)
10373 return;
10374 alc268_dell_automute(codec);
10377 #define alc268_dell_init_hook alc268_dell_automute
10379 static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
10380 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
10381 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
10382 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
10383 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10384 HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
10385 HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
10386 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
10387 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
10391 static struct hda_verb alc267_quanta_il1_verbs[] = {
10392 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
10393 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
10397 static void alc267_quanta_il1_hp_automute(struct hda_codec *codec)
10399 unsigned int present;
10401 present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
10402 & AC_PINSENSE_PRESENCE;
10403 snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
10404 present ? 0 : PIN_OUT);
10407 static void alc267_quanta_il1_mic_automute(struct hda_codec *codec)
10409 unsigned int present;
10411 present = snd_hda_codec_read(codec, 0x18, 0,
10412 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
10413 snd_hda_codec_write(codec, 0x23, 0,
10414 AC_VERB_SET_CONNECT_SEL,
10415 present ? 0x00 : 0x01);
10418 static void alc267_quanta_il1_automute(struct hda_codec *codec)
10420 alc267_quanta_il1_hp_automute(codec);
10421 alc267_quanta_il1_mic_automute(codec);
10424 static void alc267_quanta_il1_unsol_event(struct hda_codec *codec,
10425 unsigned int res)
10427 switch (res >> 26) {
10428 case ALC880_HP_EVENT:
10429 alc267_quanta_il1_hp_automute(codec);
10430 break;
10431 case ALC880_MIC_EVENT:
10432 alc267_quanta_il1_mic_automute(codec);
10433 break;
10438 * generic initialization of ADC, input mixers and output mixers
10440 static struct hda_verb alc268_base_init_verbs[] = {
10441 /* Unmute DAC0-1 and set vol = 0 */
10442 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10443 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10444 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10445 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10446 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10447 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10450 * Set up output mixers (0x0c - 0x0e)
10452 /* set vol=0 to output mixers */
10453 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10454 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10455 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10456 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
10458 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10459 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10461 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
10462 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
10463 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
10464 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
10465 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
10466 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
10467 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
10468 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
10470 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10471 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10472 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10473 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10474 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10475 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10476 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10478 /* set PCBEEP vol = 0, mute connections */
10479 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10480 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
10481 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
10483 /* Unmute Selector 23h,24h and set the default input to mic-in */
10485 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
10486 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10487 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
10488 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10494 * generic initialization of ADC, input mixers and output mixers
10496 static struct hda_verb alc268_volume_init_verbs[] = {
10497 /* set output DAC */
10498 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10499 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10500 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10501 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10503 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
10504 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
10505 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
10506 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
10507 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
10509 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10510 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10511 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10512 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10513 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10515 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10516 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10517 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10518 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10520 /* set PCBEEP vol = 0, mute connections */
10521 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10522 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
10523 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
10528 #define alc268_mux_enum_info alc_mux_enum_info
10529 #define alc268_mux_enum_get alc_mux_enum_get
10530 #define alc268_mux_enum_put alc_mux_enum_put
10532 static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
10533 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
10534 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
10536 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10537 /* The multiple "Capture Source" controls confuse alsamixer
10538 * So call somewhat different..
10540 /* .name = "Capture Source", */
10541 .name = "Input Source",
10542 .count = 1,
10543 .info = alc268_mux_enum_info,
10544 .get = alc268_mux_enum_get,
10545 .put = alc268_mux_enum_put,
10547 { } /* end */
10550 static struct snd_kcontrol_new alc268_capture_mixer[] = {
10551 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
10552 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
10553 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
10554 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
10556 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10557 /* The multiple "Capture Source" controls confuse alsamixer
10558 * So call somewhat different..
10560 /* .name = "Capture Source", */
10561 .name = "Input Source",
10562 .count = 2,
10563 .info = alc268_mux_enum_info,
10564 .get = alc268_mux_enum_get,
10565 .put = alc268_mux_enum_put,
10567 { } /* end */
10570 static struct hda_input_mux alc268_capture_source = {
10571 .num_items = 4,
10572 .items = {
10573 { "Mic", 0x0 },
10574 { "Front Mic", 0x1 },
10575 { "Line", 0x2 },
10576 { "CD", 0x3 },
10580 static struct hda_input_mux alc268_acer_capture_source = {
10581 .num_items = 3,
10582 .items = {
10583 { "Mic", 0x0 },
10584 { "Internal Mic", 0x6 },
10585 { "Line", 0x2 },
10589 #ifdef CONFIG_SND_DEBUG
10590 static struct snd_kcontrol_new alc268_test_mixer[] = {
10591 /* Volume widgets */
10592 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
10593 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
10594 HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),
10595 HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),
10596 HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),
10597 HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),
10598 HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),
10599 HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),
10600 HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),
10601 HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),
10602 HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),
10603 HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),
10604 HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),
10605 /* The below appears problematic on some hardwares */
10606 /*HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),*/
10607 HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),
10608 HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),
10609 HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),
10610 HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),
10612 /* Modes for retasking pin widgets */
10613 ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),
10614 ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),
10615 ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),
10616 ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),
10618 /* Controls for GPIO pins, assuming they are configured as outputs */
10619 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
10620 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
10621 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
10622 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
10624 /* Switches to allow the digital SPDIF output pin to be enabled.
10625 * The ALC268 does not have an SPDIF input.
10627 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),
10629 /* A switch allowing EAPD to be enabled. Some laptops seem to use
10630 * this output to turn on an external amplifier.
10632 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
10633 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
10635 { } /* end */
10637 #endif
10639 /* create input playback/capture controls for the given pin */
10640 static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
10641 const char *ctlname, int idx)
10643 char name[32];
10644 int err;
10646 sprintf(name, "%s Playback Volume", ctlname);
10647 if (nid == 0x14) {
10648 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
10649 HDA_COMPOSE_AMP_VAL(0x02, 3, idx,
10650 HDA_OUTPUT));
10651 if (err < 0)
10652 return err;
10653 } else if (nid == 0x15) {
10654 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
10655 HDA_COMPOSE_AMP_VAL(0x03, 3, idx,
10656 HDA_OUTPUT));
10657 if (err < 0)
10658 return err;
10659 } else
10660 return -1;
10661 sprintf(name, "%s Playback Switch", ctlname);
10662 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
10663 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
10664 if (err < 0)
10665 return err;
10666 return 0;
10669 /* add playback controls from the parsed DAC table */
10670 static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
10671 const struct auto_pin_cfg *cfg)
10673 hda_nid_t nid;
10674 int err;
10676 spec->multiout.num_dacs = 2; /* only use one dac */
10677 spec->multiout.dac_nids = spec->private_dac_nids;
10678 spec->multiout.dac_nids[0] = 2;
10679 spec->multiout.dac_nids[1] = 3;
10681 nid = cfg->line_out_pins[0];
10682 if (nid)
10683 alc268_new_analog_output(spec, nid, "Front", 0);
10685 nid = cfg->speaker_pins[0];
10686 if (nid == 0x1d) {
10687 err = add_control(spec, ALC_CTL_WIDGET_VOL,
10688 "Speaker Playback Volume",
10689 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
10690 if (err < 0)
10691 return err;
10693 nid = cfg->hp_pins[0];
10694 if (nid)
10695 alc268_new_analog_output(spec, nid, "Headphone", 0);
10697 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
10698 if (nid == 0x16) {
10699 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
10700 "Mono Playback Switch",
10701 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_INPUT));
10702 if (err < 0)
10703 return err;
10705 return 0;
10708 /* create playback/capture controls for input pins */
10709 static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
10710 const struct auto_pin_cfg *cfg)
10712 struct hda_input_mux *imux = &spec->private_imux;
10713 int i, idx1;
10715 for (i = 0; i < AUTO_PIN_LAST; i++) {
10716 switch(cfg->input_pins[i]) {
10717 case 0x18:
10718 idx1 = 0; /* Mic 1 */
10719 break;
10720 case 0x19:
10721 idx1 = 1; /* Mic 2 */
10722 break;
10723 case 0x1a:
10724 idx1 = 2; /* Line In */
10725 break;
10726 case 0x1c:
10727 idx1 = 3; /* CD */
10728 break;
10729 case 0x12:
10730 case 0x13:
10731 idx1 = 6; /* digital mics */
10732 break;
10733 default:
10734 continue;
10736 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
10737 imux->items[imux->num_items].index = idx1;
10738 imux->num_items++;
10740 return 0;
10743 static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
10745 struct alc_spec *spec = codec->spec;
10746 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
10747 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
10748 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
10749 unsigned int dac_vol1, dac_vol2;
10751 if (speaker_nid) {
10752 snd_hda_codec_write(codec, speaker_nid, 0,
10753 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
10754 snd_hda_codec_write(codec, 0x0f, 0,
10755 AC_VERB_SET_AMP_GAIN_MUTE,
10756 AMP_IN_UNMUTE(1));
10757 snd_hda_codec_write(codec, 0x10, 0,
10758 AC_VERB_SET_AMP_GAIN_MUTE,
10759 AMP_IN_UNMUTE(1));
10760 } else {
10761 snd_hda_codec_write(codec, 0x0f, 0,
10762 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
10763 snd_hda_codec_write(codec, 0x10, 0,
10764 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
10767 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */
10768 if (line_nid == 0x14)
10769 dac_vol2 = AMP_OUT_ZERO;
10770 else if (line_nid == 0x15)
10771 dac_vol1 = AMP_OUT_ZERO;
10772 if (hp_nid == 0x14)
10773 dac_vol2 = AMP_OUT_ZERO;
10774 else if (hp_nid == 0x15)
10775 dac_vol1 = AMP_OUT_ZERO;
10776 if (line_nid != 0x16 || hp_nid != 0x16 ||
10777 spec->autocfg.line_out_pins[1] != 0x16 ||
10778 spec->autocfg.line_out_pins[2] != 0x16)
10779 dac_vol1 = dac_vol2 = AMP_OUT_ZERO;
10781 snd_hda_codec_write(codec, 0x02, 0,
10782 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);
10783 snd_hda_codec_write(codec, 0x03, 0,
10784 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);
10787 /* pcm configuration: identiacal with ALC880 */
10788 #define alc268_pcm_analog_playback alc880_pcm_analog_playback
10789 #define alc268_pcm_analog_capture alc880_pcm_analog_capture
10790 #define alc268_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
10791 #define alc268_pcm_digital_playback alc880_pcm_digital_playback
10794 * BIOS auto configuration
10796 static int alc268_parse_auto_config(struct hda_codec *codec)
10798 struct alc_spec *spec = codec->spec;
10799 int err;
10800 static hda_nid_t alc268_ignore[] = { 0 };
10802 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
10803 alc268_ignore);
10804 if (err < 0)
10805 return err;
10806 if (!spec->autocfg.line_outs)
10807 return 0; /* can't find valid BIOS pin config */
10809 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
10810 if (err < 0)
10811 return err;
10812 err = alc268_auto_create_analog_input_ctls(spec, &spec->autocfg);
10813 if (err < 0)
10814 return err;
10816 spec->multiout.max_channels = 2;
10818 /* digital only support output */
10819 if (spec->autocfg.dig_out_pin)
10820 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
10822 if (spec->kctl_alloc)
10823 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
10825 if (spec->autocfg.speaker_pins[0] != 0x1d)
10826 spec->mixers[spec->num_mixers++] = alc268_beep_mixer;
10828 spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs;
10829 spec->num_mux_defs = 1;
10830 spec->input_mux = &spec->private_imux;
10832 err = alc_auto_add_mic_boost(codec);
10833 if (err < 0)
10834 return err;
10836 store_pin_configs(codec);
10837 return 1;
10840 #define alc268_auto_init_multi_out alc882_auto_init_multi_out
10841 #define alc268_auto_init_hp_out alc882_auto_init_hp_out
10842 #define alc268_auto_init_analog_input alc882_auto_init_analog_input
10844 /* init callback for auto-configuration model -- overriding the default init */
10845 static void alc268_auto_init(struct hda_codec *codec)
10847 struct alc_spec *spec = codec->spec;
10848 alc268_auto_init_multi_out(codec);
10849 alc268_auto_init_hp_out(codec);
10850 alc268_auto_init_mono_speaker_out(codec);
10851 alc268_auto_init_analog_input(codec);
10852 if (spec->unsol_event)
10853 alc_sku_automute(codec);
10857 * configuration and preset
10859 static const char *alc268_models[ALC268_MODEL_LAST] = {
10860 [ALC267_QUANTA_IL1] = "quanta-il1",
10861 [ALC268_3ST] = "3stack",
10862 [ALC268_TOSHIBA] = "toshiba",
10863 [ALC268_ACER] = "acer",
10864 [ALC268_DELL] = "dell",
10865 [ALC268_ZEPTO] = "zepto",
10866 #ifdef CONFIG_SND_DEBUG
10867 [ALC268_TEST] = "test",
10868 #endif
10869 [ALC268_AUTO] = "auto",
10872 static struct snd_pci_quirk alc268_cfg_tbl[] = {
10873 SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
10874 SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
10875 SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
10876 SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
10877 SND_PCI_QUIRK(0x1025, 0x0136, "Acer Aspire 5315", ALC268_ACER),
10878 SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
10879 SND_PCI_QUIRK(0x103c, 0x30cc, "TOSHIBA", ALC268_TOSHIBA),
10880 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
10881 SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),
10882 SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA),
10883 SND_PCI_QUIRK(0x1179, 0xff64, "TOSHIBA L305", ALC268_TOSHIBA),
10884 SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
10885 SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
10886 SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
10887 SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
10891 static struct alc_config_preset alc268_presets[] = {
10892 [ALC267_QUANTA_IL1] = {
10893 .mixers = { alc267_quanta_il1_mixer },
10894 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
10895 alc267_quanta_il1_verbs },
10896 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
10897 .dac_nids = alc268_dac_nids,
10898 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
10899 .adc_nids = alc268_adc_nids_alt,
10900 .hp_nid = 0x03,
10901 .num_channel_mode = ARRAY_SIZE(alc268_modes),
10902 .channel_mode = alc268_modes,
10903 .input_mux = &alc268_capture_source,
10904 .unsol_event = alc267_quanta_il1_unsol_event,
10905 .init_hook = alc267_quanta_il1_automute,
10907 [ALC268_3ST] = {
10908 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
10909 alc268_beep_mixer },
10910 .init_verbs = { alc268_base_init_verbs },
10911 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
10912 .dac_nids = alc268_dac_nids,
10913 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
10914 .adc_nids = alc268_adc_nids_alt,
10915 .capsrc_nids = alc268_capsrc_nids,
10916 .hp_nid = 0x03,
10917 .dig_out_nid = ALC268_DIGOUT_NID,
10918 .num_channel_mode = ARRAY_SIZE(alc268_modes),
10919 .channel_mode = alc268_modes,
10920 .input_mux = &alc268_capture_source,
10922 [ALC268_TOSHIBA] = {
10923 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
10924 alc268_beep_mixer },
10925 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
10926 alc268_toshiba_verbs },
10927 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
10928 .dac_nids = alc268_dac_nids,
10929 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
10930 .adc_nids = alc268_adc_nids_alt,
10931 .capsrc_nids = alc268_capsrc_nids,
10932 .hp_nid = 0x03,
10933 .num_channel_mode = ARRAY_SIZE(alc268_modes),
10934 .channel_mode = alc268_modes,
10935 .input_mux = &alc268_capture_source,
10936 .unsol_event = alc268_toshiba_unsol_event,
10937 .init_hook = alc268_toshiba_automute,
10939 [ALC268_ACER] = {
10940 .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
10941 alc268_beep_mixer },
10942 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
10943 alc268_acer_verbs },
10944 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
10945 .dac_nids = alc268_dac_nids,
10946 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
10947 .adc_nids = alc268_adc_nids_alt,
10948 .capsrc_nids = alc268_capsrc_nids,
10949 .hp_nid = 0x02,
10950 .num_channel_mode = ARRAY_SIZE(alc268_modes),
10951 .channel_mode = alc268_modes,
10952 .input_mux = &alc268_acer_capture_source,
10953 .unsol_event = alc268_acer_unsol_event,
10954 .init_hook = alc268_acer_init_hook,
10956 [ALC268_DELL] = {
10957 .mixers = { alc268_dell_mixer, alc268_beep_mixer },
10958 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
10959 alc268_dell_verbs },
10960 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
10961 .dac_nids = alc268_dac_nids,
10962 .hp_nid = 0x02,
10963 .num_channel_mode = ARRAY_SIZE(alc268_modes),
10964 .channel_mode = alc268_modes,
10965 .unsol_event = alc268_dell_unsol_event,
10966 .init_hook = alc268_dell_init_hook,
10967 .input_mux = &alc268_capture_source,
10969 [ALC268_ZEPTO] = {
10970 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
10971 alc268_beep_mixer },
10972 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
10973 alc268_toshiba_verbs },
10974 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
10975 .dac_nids = alc268_dac_nids,
10976 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
10977 .adc_nids = alc268_adc_nids_alt,
10978 .capsrc_nids = alc268_capsrc_nids,
10979 .hp_nid = 0x03,
10980 .dig_out_nid = ALC268_DIGOUT_NID,
10981 .num_channel_mode = ARRAY_SIZE(alc268_modes),
10982 .channel_mode = alc268_modes,
10983 .input_mux = &alc268_capture_source,
10984 .unsol_event = alc268_toshiba_unsol_event,
10985 .init_hook = alc268_toshiba_automute
10987 #ifdef CONFIG_SND_DEBUG
10988 [ALC268_TEST] = {
10989 .mixers = { alc268_test_mixer, alc268_capture_mixer },
10990 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
10991 alc268_volume_init_verbs },
10992 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
10993 .dac_nids = alc268_dac_nids,
10994 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
10995 .adc_nids = alc268_adc_nids_alt,
10996 .capsrc_nids = alc268_capsrc_nids,
10997 .hp_nid = 0x03,
10998 .dig_out_nid = ALC268_DIGOUT_NID,
10999 .num_channel_mode = ARRAY_SIZE(alc268_modes),
11000 .channel_mode = alc268_modes,
11001 .input_mux = &alc268_capture_source,
11003 #endif
11006 static int patch_alc268(struct hda_codec *codec)
11008 struct alc_spec *spec;
11009 int board_config;
11010 int err;
11012 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
11013 if (spec == NULL)
11014 return -ENOMEM;
11016 codec->spec = spec;
11018 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,
11019 alc268_models,
11020 alc268_cfg_tbl);
11022 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
11023 printk(KERN_INFO "hda_codec: Unknown model for ALC268, "
11024 "trying auto-probe from BIOS...\n");
11025 board_config = ALC268_AUTO;
11028 if (board_config == ALC268_AUTO) {
11029 /* automatic parse from the BIOS config */
11030 err = alc268_parse_auto_config(codec);
11031 if (err < 0) {
11032 alc_free(codec);
11033 return err;
11034 } else if (!err) {
11035 printk(KERN_INFO
11036 "hda_codec: Cannot set up configuration "
11037 "from BIOS. Using base mode...\n");
11038 board_config = ALC268_3ST;
11042 if (board_config != ALC268_AUTO)
11043 setup_preset(spec, &alc268_presets[board_config]);
11045 if (codec->vendor_id == 0x10ec0267) {
11046 spec->stream_name_analog = "ALC267 Analog";
11047 spec->stream_name_digital = "ALC267 Digital";
11048 } else {
11049 spec->stream_name_analog = "ALC268 Analog";
11050 spec->stream_name_digital = "ALC268 Digital";
11053 spec->stream_analog_playback = &alc268_pcm_analog_playback;
11054 spec->stream_analog_capture = &alc268_pcm_analog_capture;
11055 spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;
11057 spec->stream_digital_playback = &alc268_pcm_digital_playback;
11059 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
11060 /* override the amp caps for beep generator */
11061 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
11062 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
11063 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
11064 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
11065 (0 << AC_AMPCAP_MUTE_SHIFT));
11067 if (!spec->adc_nids && spec->input_mux) {
11068 /* check whether NID 0x07 is valid */
11069 unsigned int wcap = get_wcaps(codec, 0x07);
11070 int i;
11072 /* get type */
11073 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
11074 if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
11075 spec->adc_nids = alc268_adc_nids_alt;
11076 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
11077 spec->mixers[spec->num_mixers] =
11078 alc268_capture_alt_mixer;
11079 spec->num_mixers++;
11080 } else {
11081 spec->adc_nids = alc268_adc_nids;
11082 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
11083 spec->mixers[spec->num_mixers] =
11084 alc268_capture_mixer;
11085 spec->num_mixers++;
11087 spec->capsrc_nids = alc268_capsrc_nids;
11088 /* set default input source */
11089 for (i = 0; i < spec->num_adc_nids; i++)
11090 snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
11091 0, AC_VERB_SET_CONNECT_SEL,
11092 spec->input_mux->items[0].index);
11095 spec->vmaster_nid = 0x02;
11097 codec->patch_ops = alc_patch_ops;
11098 if (board_config == ALC268_AUTO)
11099 spec->init_hook = alc268_auto_init;
11101 return 0;
11105 * ALC269 channel source setting (2 channel)
11107 #define ALC269_DIGOUT_NID ALC880_DIGOUT_NID
11109 #define alc269_dac_nids alc260_dac_nids
11111 static hda_nid_t alc269_adc_nids[1] = {
11112 /* ADC1 */
11113 0x08,
11116 static hda_nid_t alc269_capsrc_nids[1] = {
11117 0x23,
11120 /* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24),
11121 * not a mux!
11124 static struct hda_input_mux alc269_eeepc_dmic_capture_source = {
11125 .num_items = 2,
11126 .items = {
11127 { "i-Mic", 0x5 },
11128 { "e-Mic", 0x0 },
11132 static struct hda_input_mux alc269_eeepc_amic_capture_source = {
11133 .num_items = 2,
11134 .items = {
11135 { "i-Mic", 0x1 },
11136 { "e-Mic", 0x0 },
11140 #define alc269_modes alc260_modes
11141 #define alc269_capture_source alc880_lg_lw_capture_source
11143 static struct snd_kcontrol_new alc269_base_mixer[] = {
11144 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
11145 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
11146 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11147 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11148 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11149 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11150 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11151 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11152 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11153 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
11154 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11155 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
11156 { } /* end */
11159 /* bind volumes of both NID 0x0c and 0x0d */
11160 static struct hda_bind_ctls alc269_epc_bind_vol = {
11161 .ops = &snd_hda_bind_vol,
11162 .values = {
11163 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
11164 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
11169 static struct snd_kcontrol_new alc269_eeepc_mixer[] = {
11170 HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
11171 HDA_BIND_VOL("LineOut Playback Volume", &alc269_epc_bind_vol),
11172 HDA_CODEC_MUTE("LineOut Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11173 { } /* end */
11176 /* capture mixer elements */
11177 static struct snd_kcontrol_new alc269_capture_mixer[] = {
11178 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
11179 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
11181 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11182 /* The multiple "Capture Source" controls confuse alsamixer
11183 * So call somewhat different..
11185 /* .name = "Capture Source", */
11186 .name = "Input Source",
11187 .count = 1,
11188 .info = alc_mux_enum_info,
11189 .get = alc_mux_enum_get,
11190 .put = alc_mux_enum_put,
11192 { } /* end */
11195 /* capture mixer elements */
11196 static struct snd_kcontrol_new alc269_epc_capture_mixer[] = {
11197 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
11198 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
11199 { } /* end */
11203 * generic initialization of ADC, input mixers and output mixers
11205 static struct hda_verb alc269_init_verbs[] = {
11207 * Unmute ADC0 and set the default input to mic-in
11209 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11211 /* Mute input amps (PCBeep, Line In, Mic 1 & Mic 2) of the
11212 * analog-loopback mixer widget
11213 * Note: PASD motherboards uses the Line In 2 as the input for
11214 * front panel mic (mic 2)
11216 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
11217 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11218 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11219 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11220 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11221 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11224 * Set up output mixers (0x0c - 0x0e)
11226 /* set vol=0 to output mixers */
11227 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11228 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11230 /* set up input amps for analog loopback */
11231 /* Amp Indices: DAC = 0, mixer = 1 */
11232 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11233 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11234 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11235 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11236 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11237 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11239 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11240 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11241 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11242 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
11243 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
11244 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11245 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11247 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11248 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11249 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11250 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11251 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11252 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11253 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11255 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
11256 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11258 /* FIXME: use matrix-type input source selection */
11259 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
11260 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
11261 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11262 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11263 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11264 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11266 /* set EAPD */
11267 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
11268 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
11272 static struct hda_verb alc269_eeepc_dmic_init_verbs[] = {
11273 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
11274 {0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
11275 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
11276 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
11277 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11278 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
11279 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11283 static struct hda_verb alc269_eeepc_amic_init_verbs[] = {
11284 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
11285 {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
11286 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
11287 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))},
11288 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
11289 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11293 /* toggle speaker-output according to the hp-jack state */
11294 static void alc269_speaker_automute(struct hda_codec *codec)
11296 unsigned int present;
11297 unsigned int bits;
11299 present = snd_hda_codec_read(codec, 0x15, 0,
11300 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
11301 bits = present ? AMP_IN_MUTE(0) : 0;
11302 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
11303 AMP_IN_MUTE(0), bits);
11304 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
11305 AMP_IN_MUTE(0), bits);
11308 static void alc269_eeepc_dmic_automute(struct hda_codec *codec)
11310 unsigned int present;
11312 present = snd_hda_codec_read(codec, 0x18, 0, AC_VERB_GET_PIN_SENSE, 0)
11313 & AC_PINSENSE_PRESENCE;
11314 snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_CONNECT_SEL,
11315 present ? 0 : 5);
11318 static void alc269_eeepc_amic_automute(struct hda_codec *codec)
11320 unsigned int present;
11322 present = snd_hda_codec_read(codec, 0x18, 0, AC_VERB_GET_PIN_SENSE, 0)
11323 & AC_PINSENSE_PRESENCE;
11324 snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_AMP_GAIN_MUTE,
11325 present ? AMP_IN_UNMUTE(0) : AMP_IN_MUTE(0));
11326 snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_AMP_GAIN_MUTE,
11327 present ? AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1));
11330 /* unsolicited event for HP jack sensing */
11331 static void alc269_eeepc_dmic_unsol_event(struct hda_codec *codec,
11332 unsigned int res)
11334 if ((res >> 26) == ALC880_HP_EVENT)
11335 alc269_speaker_automute(codec);
11337 if ((res >> 26) == ALC880_MIC_EVENT)
11338 alc269_eeepc_dmic_automute(codec);
11341 static void alc269_eeepc_dmic_inithook(struct hda_codec *codec)
11343 alc269_speaker_automute(codec);
11344 alc269_eeepc_dmic_automute(codec);
11347 /* unsolicited event for HP jack sensing */
11348 static void alc269_eeepc_amic_unsol_event(struct hda_codec *codec,
11349 unsigned int res)
11351 if ((res >> 26) == ALC880_HP_EVENT)
11352 alc269_speaker_automute(codec);
11354 if ((res >> 26) == ALC880_MIC_EVENT)
11355 alc269_eeepc_amic_automute(codec);
11358 static void alc269_eeepc_amic_inithook(struct hda_codec *codec)
11360 alc269_speaker_automute(codec);
11361 alc269_eeepc_amic_automute(codec);
11364 /* add playback controls from the parsed DAC table */
11365 static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec,
11366 const struct auto_pin_cfg *cfg)
11368 hda_nid_t nid;
11369 int err;
11371 spec->multiout.num_dacs = 1; /* only use one dac */
11372 spec->multiout.dac_nids = spec->private_dac_nids;
11373 spec->multiout.dac_nids[0] = 2;
11375 nid = cfg->line_out_pins[0];
11376 if (nid) {
11377 err = add_control(spec, ALC_CTL_WIDGET_VOL,
11378 "Front Playback Volume",
11379 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT));
11380 if (err < 0)
11381 return err;
11382 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
11383 "Front Playback Switch",
11384 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
11385 if (err < 0)
11386 return err;
11389 nid = cfg->speaker_pins[0];
11390 if (nid) {
11391 if (!cfg->line_out_pins[0]) {
11392 err = add_control(spec, ALC_CTL_WIDGET_VOL,
11393 "Speaker Playback Volume",
11394 HDA_COMPOSE_AMP_VAL(0x02, 3, 0,
11395 HDA_OUTPUT));
11396 if (err < 0)
11397 return err;
11399 if (nid == 0x16) {
11400 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
11401 "Speaker Playback Switch",
11402 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
11403 HDA_OUTPUT));
11404 if (err < 0)
11405 return err;
11406 } else {
11407 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
11408 "Speaker Playback Switch",
11409 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
11410 HDA_OUTPUT));
11411 if (err < 0)
11412 return err;
11415 nid = cfg->hp_pins[0];
11416 if (nid) {
11417 /* spec->multiout.hp_nid = 2; */
11418 if (!cfg->line_out_pins[0] && !cfg->speaker_pins[0]) {
11419 err = add_control(spec, ALC_CTL_WIDGET_VOL,
11420 "Headphone Playback Volume",
11421 HDA_COMPOSE_AMP_VAL(0x02, 3, 0,
11422 HDA_OUTPUT));
11423 if (err < 0)
11424 return err;
11426 if (nid == 0x16) {
11427 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
11428 "Headphone Playback Switch",
11429 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
11430 HDA_OUTPUT));
11431 if (err < 0)
11432 return err;
11433 } else {
11434 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
11435 "Headphone Playback Switch",
11436 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
11437 HDA_OUTPUT));
11438 if (err < 0)
11439 return err;
11442 return 0;
11445 #define alc269_auto_create_analog_input_ctls \
11446 alc880_auto_create_analog_input_ctls
11448 #ifdef CONFIG_SND_HDA_POWER_SAVE
11449 #define alc269_loopbacks alc880_loopbacks
11450 #endif
11452 /* pcm configuration: identiacal with ALC880 */
11453 #define alc269_pcm_analog_playback alc880_pcm_analog_playback
11454 #define alc269_pcm_analog_capture alc880_pcm_analog_capture
11455 #define alc269_pcm_digital_playback alc880_pcm_digital_playback
11456 #define alc269_pcm_digital_capture alc880_pcm_digital_capture
11459 * BIOS auto configuration
11461 static int alc269_parse_auto_config(struct hda_codec *codec)
11463 struct alc_spec *spec = codec->spec;
11464 int err;
11465 static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
11467 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
11468 alc269_ignore);
11469 if (err < 0)
11470 return err;
11472 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
11473 if (err < 0)
11474 return err;
11475 err = alc269_auto_create_analog_input_ctls(spec, &spec->autocfg);
11476 if (err < 0)
11477 return err;
11479 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
11481 if (spec->autocfg.dig_out_pin)
11482 spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
11484 if (spec->kctl_alloc)
11485 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
11487 spec->init_verbs[spec->num_init_verbs++] = alc269_init_verbs;
11488 spec->num_mux_defs = 1;
11489 spec->input_mux = &spec->private_imux;
11490 /* set default input source */
11491 snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0],
11492 0, AC_VERB_SET_CONNECT_SEL,
11493 spec->input_mux->items[0].index);
11495 err = alc_auto_add_mic_boost(codec);
11496 if (err < 0)
11497 return err;
11499 spec->mixers[spec->num_mixers] = alc269_capture_mixer;
11500 spec->num_mixers++;
11502 store_pin_configs(codec);
11503 return 1;
11506 #define alc269_auto_init_multi_out alc882_auto_init_multi_out
11507 #define alc269_auto_init_hp_out alc882_auto_init_hp_out
11508 #define alc269_auto_init_analog_input alc882_auto_init_analog_input
11511 /* init callback for auto-configuration model -- overriding the default init */
11512 static void alc269_auto_init(struct hda_codec *codec)
11514 struct alc_spec *spec = codec->spec;
11515 alc269_auto_init_multi_out(codec);
11516 alc269_auto_init_hp_out(codec);
11517 alc269_auto_init_analog_input(codec);
11518 if (spec->unsol_event)
11519 alc_sku_automute(codec);
11523 * configuration and preset
11525 static const char *alc269_models[ALC269_MODEL_LAST] = {
11526 [ALC269_BASIC] = "basic",
11529 static struct snd_pci_quirk alc269_cfg_tbl[] = {
11530 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
11531 ALC269_ASUS_EEEPC_P703),
11532 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
11533 ALC269_ASUS_EEEPC_P901),
11537 static struct alc_config_preset alc269_presets[] = {
11538 [ALC269_BASIC] = {
11539 .mixers = { alc269_base_mixer, alc269_capture_mixer },
11540 .init_verbs = { alc269_init_verbs },
11541 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
11542 .dac_nids = alc269_dac_nids,
11543 .hp_nid = 0x03,
11544 .num_channel_mode = ARRAY_SIZE(alc269_modes),
11545 .channel_mode = alc269_modes,
11546 .input_mux = &alc269_capture_source,
11548 [ALC269_ASUS_EEEPC_P703] = {
11549 .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer },
11550 .init_verbs = { alc269_init_verbs,
11551 alc269_eeepc_amic_init_verbs },
11552 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
11553 .dac_nids = alc269_dac_nids,
11554 .hp_nid = 0x03,
11555 .num_channel_mode = ARRAY_SIZE(alc269_modes),
11556 .channel_mode = alc269_modes,
11557 .input_mux = &alc269_eeepc_amic_capture_source,
11558 .unsol_event = alc269_eeepc_amic_unsol_event,
11559 .init_hook = alc269_eeepc_amic_inithook,
11561 [ALC269_ASUS_EEEPC_P901] = {
11562 .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer},
11563 .init_verbs = { alc269_init_verbs,
11564 alc269_eeepc_dmic_init_verbs },
11565 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
11566 .dac_nids = alc269_dac_nids,
11567 .hp_nid = 0x03,
11568 .num_channel_mode = ARRAY_SIZE(alc269_modes),
11569 .channel_mode = alc269_modes,
11570 .input_mux = &alc269_eeepc_dmic_capture_source,
11571 .unsol_event = alc269_eeepc_dmic_unsol_event,
11572 .init_hook = alc269_eeepc_dmic_inithook,
11576 static int patch_alc269(struct hda_codec *codec)
11578 struct alc_spec *spec;
11579 int board_config;
11580 int err;
11582 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
11583 if (spec == NULL)
11584 return -ENOMEM;
11586 codec->spec = spec;
11588 alc_fix_pll_init(codec, 0x20, 0x04, 15);
11590 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
11591 alc269_models,
11592 alc269_cfg_tbl);
11594 if (board_config < 0) {
11595 printk(KERN_INFO "hda_codec: Unknown model for ALC269, "
11596 "trying auto-probe from BIOS...\n");
11597 board_config = ALC269_AUTO;
11600 if (board_config == ALC269_AUTO) {
11601 /* automatic parse from the BIOS config */
11602 err = alc269_parse_auto_config(codec);
11603 if (err < 0) {
11604 alc_free(codec);
11605 return err;
11606 } else if (!err) {
11607 printk(KERN_INFO
11608 "hda_codec: Cannot set up configuration "
11609 "from BIOS. Using base mode...\n");
11610 board_config = ALC269_BASIC;
11614 if (board_config != ALC269_AUTO)
11615 setup_preset(spec, &alc269_presets[board_config]);
11617 spec->stream_name_analog = "ALC269 Analog";
11618 spec->stream_analog_playback = &alc269_pcm_analog_playback;
11619 spec->stream_analog_capture = &alc269_pcm_analog_capture;
11621 spec->stream_name_digital = "ALC269 Digital";
11622 spec->stream_digital_playback = &alc269_pcm_digital_playback;
11623 spec->stream_digital_capture = &alc269_pcm_digital_capture;
11625 spec->adc_nids = alc269_adc_nids;
11626 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
11627 spec->capsrc_nids = alc269_capsrc_nids;
11629 codec->patch_ops = alc_patch_ops;
11630 if (board_config == ALC269_AUTO)
11631 spec->init_hook = alc269_auto_init;
11632 #ifdef CONFIG_SND_HDA_POWER_SAVE
11633 if (!spec->loopback.amplist)
11634 spec->loopback.amplist = alc269_loopbacks;
11635 #endif
11637 return 0;
11641 * ALC861 channel source setting (2/6 channel selection for 3-stack)
11645 * set the path ways for 2 channel output
11646 * need to set the codec line out and mic 1 pin widgets to inputs
11648 static struct hda_verb alc861_threestack_ch2_init[] = {
11649 /* set pin widget 1Ah (line in) for input */
11650 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
11651 /* set pin widget 18h (mic1/2) for input, for mic also enable
11652 * the vref
11654 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
11656 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
11657 #if 0
11658 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
11659 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
11660 #endif
11661 { } /* end */
11664 * 6ch mode
11665 * need to set the codec line out and mic 1 pin widgets to outputs
11667 static struct hda_verb alc861_threestack_ch6_init[] = {
11668 /* set pin widget 1Ah (line in) for output (Back Surround)*/
11669 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
11670 /* set pin widget 18h (mic1) for output (CLFE)*/
11671 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
11673 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
11674 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
11676 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
11677 #if 0
11678 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
11679 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
11680 #endif
11681 { } /* end */
11684 static struct hda_channel_mode alc861_threestack_modes[2] = {
11685 { 2, alc861_threestack_ch2_init },
11686 { 6, alc861_threestack_ch6_init },
11688 /* Set mic1 as input and unmute the mixer */
11689 static struct hda_verb alc861_uniwill_m31_ch2_init[] = {
11690 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
11691 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
11692 { } /* end */
11694 /* Set mic1 as output and mute mixer */
11695 static struct hda_verb alc861_uniwill_m31_ch4_init[] = {
11696 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
11697 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
11698 { } /* end */
11701 static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
11702 { 2, alc861_uniwill_m31_ch2_init },
11703 { 4, alc861_uniwill_m31_ch4_init },
11706 /* Set mic1 and line-in as input and unmute the mixer */
11707 static struct hda_verb alc861_asus_ch2_init[] = {
11708 /* set pin widget 1Ah (line in) for input */
11709 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
11710 /* set pin widget 18h (mic1/2) for input, for mic also enable
11711 * the vref
11713 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
11715 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
11716 #if 0
11717 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
11718 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
11719 #endif
11720 { } /* end */
11722 /* Set mic1 nad line-in as output and mute mixer */
11723 static struct hda_verb alc861_asus_ch6_init[] = {
11724 /* set pin widget 1Ah (line in) for output (Back Surround)*/
11725 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
11726 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
11727 /* set pin widget 18h (mic1) for output (CLFE)*/
11728 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
11729 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
11730 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
11731 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
11733 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
11734 #if 0
11735 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
11736 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
11737 #endif
11738 { } /* end */
11741 static struct hda_channel_mode alc861_asus_modes[2] = {
11742 { 2, alc861_asus_ch2_init },
11743 { 6, alc861_asus_ch6_init },
11746 /* patch-ALC861 */
11748 static struct snd_kcontrol_new alc861_base_mixer[] = {
11749 /* output mixer control */
11750 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
11751 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
11752 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
11753 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
11754 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
11756 /*Input mixer control */
11757 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
11758 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
11759 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
11760 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
11761 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
11762 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
11763 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
11764 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
11765 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
11766 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
11768 /* Capture mixer control */
11769 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
11770 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
11772 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11773 .name = "Capture Source",
11774 .count = 1,
11775 .info = alc_mux_enum_info,
11776 .get = alc_mux_enum_get,
11777 .put = alc_mux_enum_put,
11779 { } /* end */
11782 static struct snd_kcontrol_new alc861_3ST_mixer[] = {
11783 /* output mixer control */
11784 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
11785 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
11786 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
11787 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
11788 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
11790 /* Input mixer control */
11791 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
11792 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
11793 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
11794 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
11795 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
11796 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
11797 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
11798 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
11799 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
11800 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
11802 /* Capture mixer control */
11803 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
11804 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
11806 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11807 .name = "Capture Source",
11808 .count = 1,
11809 .info = alc_mux_enum_info,
11810 .get = alc_mux_enum_get,
11811 .put = alc_mux_enum_put,
11814 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11815 .name = "Channel Mode",
11816 .info = alc_ch_mode_info,
11817 .get = alc_ch_mode_get,
11818 .put = alc_ch_mode_put,
11819 .private_value = ARRAY_SIZE(alc861_threestack_modes),
11821 { } /* end */
11824 static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
11825 /* output mixer control */
11826 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
11827 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
11828 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
11830 /*Capture mixer control */
11831 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
11832 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
11834 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11835 .name = "Capture Source",
11836 .count = 1,
11837 .info = alc_mux_enum_info,
11838 .get = alc_mux_enum_get,
11839 .put = alc_mux_enum_put,
11842 { } /* end */
11845 static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
11846 /* output mixer control */
11847 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
11848 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
11849 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
11850 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
11851 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
11853 /* Input mixer control */
11854 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
11855 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
11856 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
11857 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
11858 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
11859 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
11860 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
11861 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
11862 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
11863 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
11865 /* Capture mixer control */
11866 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
11867 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
11869 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11870 .name = "Capture Source",
11871 .count = 1,
11872 .info = alc_mux_enum_info,
11873 .get = alc_mux_enum_get,
11874 .put = alc_mux_enum_put,
11877 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11878 .name = "Channel Mode",
11879 .info = alc_ch_mode_info,
11880 .get = alc_ch_mode_get,
11881 .put = alc_ch_mode_put,
11882 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
11884 { } /* end */
11887 static struct snd_kcontrol_new alc861_asus_mixer[] = {
11888 /* output mixer control */
11889 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
11890 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
11891 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
11892 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
11893 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
11895 /* Input mixer control */
11896 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
11897 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11898 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
11899 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
11900 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
11901 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
11902 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
11903 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
11904 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
11905 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
11907 /* Capture mixer control */
11908 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
11909 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
11911 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11912 .name = "Capture Source",
11913 .count = 1,
11914 .info = alc_mux_enum_info,
11915 .get = alc_mux_enum_get,
11916 .put = alc_mux_enum_put,
11919 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11920 .name = "Channel Mode",
11921 .info = alc_ch_mode_info,
11922 .get = alc_ch_mode_get,
11923 .put = alc_ch_mode_put,
11924 .private_value = ARRAY_SIZE(alc861_asus_modes),
11929 /* additional mixer */
11930 static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
11931 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
11932 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
11933 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT),
11934 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT),
11939 * generic initialization of ADC, input mixers and output mixers
11941 static struct hda_verb alc861_base_init_verbs[] = {
11943 * Unmute ADC0 and set the default input to mic-in
11945 /* port-A for surround (rear panel) */
11946 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
11947 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
11948 /* port-B for mic-in (rear panel) with vref */
11949 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
11950 /* port-C for line-in (rear panel) */
11951 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
11952 /* port-D for Front */
11953 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
11954 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
11955 /* port-E for HP out (front panel) */
11956 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
11957 /* route front PCM to HP */
11958 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
11959 /* port-F for mic-in (front panel) with vref */
11960 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
11961 /* port-G for CLFE (rear panel) */
11962 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
11963 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
11964 /* port-H for side (rear panel) */
11965 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
11966 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
11967 /* CD-in */
11968 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
11969 /* route front mic to ADC1*/
11970 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11971 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11973 /* Unmute DAC0~3 & spdif out*/
11974 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11975 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11976 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11977 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11978 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11980 /* Unmute Mixer 14 (mic) 1c (Line in)*/
11981 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11982 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11983 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11984 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11986 /* Unmute Stereo Mixer 15 */
11987 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11988 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11989 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
11990 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
11992 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11993 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11994 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11995 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11996 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11997 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11998 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11999 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12000 /* hp used DAC 3 (Front) */
12001 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
12002 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
12007 static struct hda_verb alc861_threestack_init_verbs[] = {
12009 * Unmute ADC0 and set the default input to mic-in
12011 /* port-A for surround (rear panel) */
12012 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
12013 /* port-B for mic-in (rear panel) with vref */
12014 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
12015 /* port-C for line-in (rear panel) */
12016 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
12017 /* port-D for Front */
12018 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
12019 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
12020 /* port-E for HP out (front panel) */
12021 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
12022 /* route front PCM to HP */
12023 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
12024 /* port-F for mic-in (front panel) with vref */
12025 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
12026 /* port-G for CLFE (rear panel) */
12027 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
12028 /* port-H for side (rear panel) */
12029 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
12030 /* CD-in */
12031 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
12032 /* route front mic to ADC1*/
12033 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
12034 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12035 /* Unmute DAC0~3 & spdif out*/
12036 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12037 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12038 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12039 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12040 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12042 /* Unmute Mixer 14 (mic) 1c (Line in)*/
12043 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12044 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12045 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12046 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12048 /* Unmute Stereo Mixer 15 */
12049 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12050 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12051 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
12052 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
12054 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12055 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12056 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12057 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12058 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12059 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12060 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12061 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12062 /* hp used DAC 3 (Front) */
12063 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
12064 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
12068 static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
12070 * Unmute ADC0 and set the default input to mic-in
12072 /* port-A for surround (rear panel) */
12073 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
12074 /* port-B for mic-in (rear panel) with vref */
12075 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
12076 /* port-C for line-in (rear panel) */
12077 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
12078 /* port-D for Front */
12079 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
12080 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
12081 /* port-E for HP out (front panel) */
12082 /* this has to be set to VREF80 */
12083 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
12084 /* route front PCM to HP */
12085 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
12086 /* port-F for mic-in (front panel) with vref */
12087 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
12088 /* port-G for CLFE (rear panel) */
12089 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
12090 /* port-H for side (rear panel) */
12091 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
12092 /* CD-in */
12093 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
12094 /* route front mic to ADC1*/
12095 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
12096 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12097 /* Unmute DAC0~3 & spdif out*/
12098 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12099 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12100 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12101 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12102 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12104 /* Unmute Mixer 14 (mic) 1c (Line in)*/
12105 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12106 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12107 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12108 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12110 /* Unmute Stereo Mixer 15 */
12111 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12112 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12113 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
12114 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
12116 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12117 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12118 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12119 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12120 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12121 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12122 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12123 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12124 /* hp used DAC 3 (Front) */
12125 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
12126 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
12130 static struct hda_verb alc861_asus_init_verbs[] = {
12132 * Unmute ADC0 and set the default input to mic-in
12134 /* port-A for surround (rear panel)
12135 * according to codec#0 this is the HP jack
12137 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
12138 /* route front PCM to HP */
12139 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
12140 /* port-B for mic-in (rear panel) with vref */
12141 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
12142 /* port-C for line-in (rear panel) */
12143 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
12144 /* port-D for Front */
12145 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
12146 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
12147 /* port-E for HP out (front panel) */
12148 /* this has to be set to VREF80 */
12149 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
12150 /* route front PCM to HP */
12151 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
12152 /* port-F for mic-in (front panel) with vref */
12153 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
12154 /* port-G for CLFE (rear panel) */
12155 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
12156 /* port-H for side (rear panel) */
12157 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
12158 /* CD-in */
12159 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
12160 /* route front mic to ADC1*/
12161 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
12162 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12163 /* Unmute DAC0~3 & spdif out*/
12164 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12165 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12166 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12167 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12168 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12169 /* Unmute Mixer 14 (mic) 1c (Line in)*/
12170 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12171 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12172 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12173 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12175 /* Unmute Stereo Mixer 15 */
12176 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12177 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12178 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
12179 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
12181 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12182 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12183 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12184 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12185 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12186 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12187 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12188 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12189 /* hp used DAC 3 (Front) */
12190 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
12191 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
12195 /* additional init verbs for ASUS laptops */
12196 static struct hda_verb alc861_asus_laptop_init_verbs[] = {
12197 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
12198 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
12203 * generic initialization of ADC, input mixers and output mixers
12205 static struct hda_verb alc861_auto_init_verbs[] = {
12207 * Unmute ADC0 and set the default input to mic-in
12209 /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
12210 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12212 /* Unmute DAC0~3 & spdif out*/
12213 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12214 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12215 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12216 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12217 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12219 /* Unmute Mixer 14 (mic) 1c (Line in)*/
12220 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12221 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12222 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12223 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12225 /* Unmute Stereo Mixer 15 */
12226 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12227 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12228 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
12229 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
12231 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12232 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12233 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12234 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12235 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12236 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12237 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12238 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12240 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12241 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12242 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
12243 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
12244 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12245 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12246 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
12247 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
12249 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */
12254 static struct hda_verb alc861_toshiba_init_verbs[] = {
12255 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
12260 /* toggle speaker-output according to the hp-jack state */
12261 static void alc861_toshiba_automute(struct hda_codec *codec)
12263 unsigned int present;
12265 present = snd_hda_codec_read(codec, 0x0f, 0,
12266 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
12267 snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
12268 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
12269 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
12270 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
12273 static void alc861_toshiba_unsol_event(struct hda_codec *codec,
12274 unsigned int res)
12276 if ((res >> 26) == ALC880_HP_EVENT)
12277 alc861_toshiba_automute(codec);
12280 /* pcm configuration: identiacal with ALC880 */
12281 #define alc861_pcm_analog_playback alc880_pcm_analog_playback
12282 #define alc861_pcm_analog_capture alc880_pcm_analog_capture
12283 #define alc861_pcm_digital_playback alc880_pcm_digital_playback
12284 #define alc861_pcm_digital_capture alc880_pcm_digital_capture
12287 #define ALC861_DIGOUT_NID 0x07
12289 static struct hda_channel_mode alc861_8ch_modes[1] = {
12290 { 8, NULL }
12293 static hda_nid_t alc861_dac_nids[4] = {
12294 /* front, surround, clfe, side */
12295 0x03, 0x06, 0x05, 0x04
12298 static hda_nid_t alc660_dac_nids[3] = {
12299 /* front, clfe, surround */
12300 0x03, 0x05, 0x06
12303 static hda_nid_t alc861_adc_nids[1] = {
12304 /* ADC0-2 */
12305 0x08,
12308 static struct hda_input_mux alc861_capture_source = {
12309 .num_items = 5,
12310 .items = {
12311 { "Mic", 0x0 },
12312 { "Front Mic", 0x3 },
12313 { "Line", 0x1 },
12314 { "CD", 0x4 },
12315 { "Mixer", 0x5 },
12319 /* fill in the dac_nids table from the parsed pin configuration */
12320 static int alc861_auto_fill_dac_nids(struct alc_spec *spec,
12321 const struct auto_pin_cfg *cfg)
12323 int i;
12324 hda_nid_t nid;
12326 spec->multiout.dac_nids = spec->private_dac_nids;
12327 for (i = 0; i < cfg->line_outs; i++) {
12328 nid = cfg->line_out_pins[i];
12329 if (nid) {
12330 if (i >= ARRAY_SIZE(alc861_dac_nids))
12331 continue;
12332 spec->multiout.dac_nids[i] = alc861_dac_nids[i];
12335 spec->multiout.num_dacs = cfg->line_outs;
12336 return 0;
12339 /* add playback controls from the parsed DAC table */
12340 static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
12341 const struct auto_pin_cfg *cfg)
12343 char name[32];
12344 static const char *chname[4] = {
12345 "Front", "Surround", NULL /*CLFE*/, "Side"
12347 hda_nid_t nid;
12348 int i, idx, err;
12350 for (i = 0; i < cfg->line_outs; i++) {
12351 nid = spec->multiout.dac_nids[i];
12352 if (!nid)
12353 continue;
12354 if (nid == 0x05) {
12355 /* Center/LFE */
12356 err = add_control(spec, ALC_CTL_BIND_MUTE,
12357 "Center Playback Switch",
12358 HDA_COMPOSE_AMP_VAL(nid, 1, 0,
12359 HDA_OUTPUT));
12360 if (err < 0)
12361 return err;
12362 err = add_control(spec, ALC_CTL_BIND_MUTE,
12363 "LFE Playback Switch",
12364 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
12365 HDA_OUTPUT));
12366 if (err < 0)
12367 return err;
12368 } else {
12369 for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1;
12370 idx++)
12371 if (nid == alc861_dac_nids[idx])
12372 break;
12373 sprintf(name, "%s Playback Switch", chname[idx]);
12374 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
12375 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
12376 HDA_OUTPUT));
12377 if (err < 0)
12378 return err;
12381 return 0;
12384 static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
12386 int err;
12387 hda_nid_t nid;
12389 if (!pin)
12390 return 0;
12392 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
12393 nid = 0x03;
12394 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
12395 "Headphone Playback Switch",
12396 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
12397 if (err < 0)
12398 return err;
12399 spec->multiout.hp_nid = nid;
12401 return 0;
12404 /* create playback/capture controls for input pins */
12405 static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
12406 const struct auto_pin_cfg *cfg)
12408 struct hda_input_mux *imux = &spec->private_imux;
12409 int i, err, idx, idx1;
12411 for (i = 0; i < AUTO_PIN_LAST; i++) {
12412 switch (cfg->input_pins[i]) {
12413 case 0x0c:
12414 idx1 = 1;
12415 idx = 2; /* Line In */
12416 break;
12417 case 0x0f:
12418 idx1 = 2;
12419 idx = 2; /* Line In */
12420 break;
12421 case 0x0d:
12422 idx1 = 0;
12423 idx = 1; /* Mic In */
12424 break;
12425 case 0x10:
12426 idx1 = 3;
12427 idx = 1; /* Mic In */
12428 break;
12429 case 0x11:
12430 idx1 = 4;
12431 idx = 0; /* CD */
12432 break;
12433 default:
12434 continue;
12437 err = new_analog_input(spec, cfg->input_pins[i],
12438 auto_pin_cfg_labels[i], idx, 0x15);
12439 if (err < 0)
12440 return err;
12442 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
12443 imux->items[imux->num_items].index = idx1;
12444 imux->num_items++;
12446 return 0;
12449 static struct snd_kcontrol_new alc861_capture_mixer[] = {
12450 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
12451 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
12454 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12455 /* The multiple "Capture Source" controls confuse alsamixer
12456 * So call somewhat different..
12458 /* .name = "Capture Source", */
12459 .name = "Input Source",
12460 .count = 1,
12461 .info = alc_mux_enum_info,
12462 .get = alc_mux_enum_get,
12463 .put = alc_mux_enum_put,
12465 { } /* end */
12468 static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
12469 hda_nid_t nid,
12470 int pin_type, int dac_idx)
12472 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
12473 pin_type);
12474 snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE,
12475 AMP_OUT_UNMUTE);
12478 static void alc861_auto_init_multi_out(struct hda_codec *codec)
12480 struct alc_spec *spec = codec->spec;
12481 int i;
12483 alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b);
12484 for (i = 0; i < spec->autocfg.line_outs; i++) {
12485 hda_nid_t nid = spec->autocfg.line_out_pins[i];
12486 int pin_type = get_pin_type(spec->autocfg.line_out_type);
12487 if (nid)
12488 alc861_auto_set_output_and_unmute(codec, nid, pin_type,
12489 spec->multiout.dac_nids[i]);
12493 static void alc861_auto_init_hp_out(struct hda_codec *codec)
12495 struct alc_spec *spec = codec->spec;
12496 hda_nid_t pin;
12498 pin = spec->autocfg.hp_pins[0];
12499 if (pin) /* connect to front */
12500 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP,
12501 spec->multiout.dac_nids[0]);
12502 pin = spec->autocfg.speaker_pins[0];
12503 if (pin)
12504 alc861_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
12507 static void alc861_auto_init_analog_input(struct hda_codec *codec)
12509 struct alc_spec *spec = codec->spec;
12510 int i;
12512 for (i = 0; i < AUTO_PIN_LAST; i++) {
12513 hda_nid_t nid = spec->autocfg.input_pins[i];
12514 if (nid >= 0x0c && nid <= 0x11) {
12515 snd_hda_codec_write(codec, nid, 0,
12516 AC_VERB_SET_PIN_WIDGET_CONTROL,
12517 i <= AUTO_PIN_FRONT_MIC ?
12518 PIN_VREF80 : PIN_IN);
12523 /* parse the BIOS configuration and set up the alc_spec */
12524 /* return 1 if successful, 0 if the proper config is not found,
12525 * or a negative error code
12527 static int alc861_parse_auto_config(struct hda_codec *codec)
12529 struct alc_spec *spec = codec->spec;
12530 int err;
12531 static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
12533 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
12534 alc861_ignore);
12535 if (err < 0)
12536 return err;
12537 if (!spec->autocfg.line_outs)
12538 return 0; /* can't find valid BIOS pin config */
12540 err = alc861_auto_fill_dac_nids(spec, &spec->autocfg);
12541 if (err < 0)
12542 return err;
12543 err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg);
12544 if (err < 0)
12545 return err;
12546 err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
12547 if (err < 0)
12548 return err;
12549 err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg);
12550 if (err < 0)
12551 return err;
12553 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
12555 if (spec->autocfg.dig_out_pin)
12556 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
12558 if (spec->kctl_alloc)
12559 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
12561 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
12563 spec->num_mux_defs = 1;
12564 spec->input_mux = &spec->private_imux;
12566 spec->adc_nids = alc861_adc_nids;
12567 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
12568 spec->mixers[spec->num_mixers] = alc861_capture_mixer;
12569 spec->num_mixers++;
12571 store_pin_configs(codec);
12572 return 1;
12575 /* additional initialization for auto-configuration model */
12576 static void alc861_auto_init(struct hda_codec *codec)
12578 struct alc_spec *spec = codec->spec;
12579 alc861_auto_init_multi_out(codec);
12580 alc861_auto_init_hp_out(codec);
12581 alc861_auto_init_analog_input(codec);
12582 if (spec->unsol_event)
12583 alc_sku_automute(codec);
12586 #ifdef CONFIG_SND_HDA_POWER_SAVE
12587 static struct hda_amp_list alc861_loopbacks[] = {
12588 { 0x15, HDA_INPUT, 0 },
12589 { 0x15, HDA_INPUT, 1 },
12590 { 0x15, HDA_INPUT, 2 },
12591 { 0x15, HDA_INPUT, 3 },
12592 { } /* end */
12594 #endif
12598 * configuration and preset
12600 static const char *alc861_models[ALC861_MODEL_LAST] = {
12601 [ALC861_3ST] = "3stack",
12602 [ALC660_3ST] = "3stack-660",
12603 [ALC861_3ST_DIG] = "3stack-dig",
12604 [ALC861_6ST_DIG] = "6stack-dig",
12605 [ALC861_UNIWILL_M31] = "uniwill-m31",
12606 [ALC861_TOSHIBA] = "toshiba",
12607 [ALC861_ASUS] = "asus",
12608 [ALC861_ASUS_LAPTOP] = "asus-laptop",
12609 [ALC861_AUTO] = "auto",
12612 static struct snd_pci_quirk alc861_cfg_tbl[] = {
12613 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
12614 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
12615 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
12616 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
12617 SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
12618 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
12619 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
12620 /* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
12621 * Any other models that need this preset?
12623 /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
12624 SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
12625 SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
12626 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
12627 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
12628 SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
12629 /* FIXME: the below seems conflict */
12630 /* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */
12631 SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
12632 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
12636 static struct alc_config_preset alc861_presets[] = {
12637 [ALC861_3ST] = {
12638 .mixers = { alc861_3ST_mixer },
12639 .init_verbs = { alc861_threestack_init_verbs },
12640 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
12641 .dac_nids = alc861_dac_nids,
12642 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
12643 .channel_mode = alc861_threestack_modes,
12644 .need_dac_fix = 1,
12645 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
12646 .adc_nids = alc861_adc_nids,
12647 .input_mux = &alc861_capture_source,
12649 [ALC861_3ST_DIG] = {
12650 .mixers = { alc861_base_mixer },
12651 .init_verbs = { alc861_threestack_init_verbs },
12652 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
12653 .dac_nids = alc861_dac_nids,
12654 .dig_out_nid = ALC861_DIGOUT_NID,
12655 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
12656 .channel_mode = alc861_threestack_modes,
12657 .need_dac_fix = 1,
12658 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
12659 .adc_nids = alc861_adc_nids,
12660 .input_mux = &alc861_capture_source,
12662 [ALC861_6ST_DIG] = {
12663 .mixers = { alc861_base_mixer },
12664 .init_verbs = { alc861_base_init_verbs },
12665 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
12666 .dac_nids = alc861_dac_nids,
12667 .dig_out_nid = ALC861_DIGOUT_NID,
12668 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
12669 .channel_mode = alc861_8ch_modes,
12670 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
12671 .adc_nids = alc861_adc_nids,
12672 .input_mux = &alc861_capture_source,
12674 [ALC660_3ST] = {
12675 .mixers = { alc861_3ST_mixer },
12676 .init_verbs = { alc861_threestack_init_verbs },
12677 .num_dacs = ARRAY_SIZE(alc660_dac_nids),
12678 .dac_nids = alc660_dac_nids,
12679 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
12680 .channel_mode = alc861_threestack_modes,
12681 .need_dac_fix = 1,
12682 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
12683 .adc_nids = alc861_adc_nids,
12684 .input_mux = &alc861_capture_source,
12686 [ALC861_UNIWILL_M31] = {
12687 .mixers = { alc861_uniwill_m31_mixer },
12688 .init_verbs = { alc861_uniwill_m31_init_verbs },
12689 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
12690 .dac_nids = alc861_dac_nids,
12691 .dig_out_nid = ALC861_DIGOUT_NID,
12692 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
12693 .channel_mode = alc861_uniwill_m31_modes,
12694 .need_dac_fix = 1,
12695 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
12696 .adc_nids = alc861_adc_nids,
12697 .input_mux = &alc861_capture_source,
12699 [ALC861_TOSHIBA] = {
12700 .mixers = { alc861_toshiba_mixer },
12701 .init_verbs = { alc861_base_init_verbs,
12702 alc861_toshiba_init_verbs },
12703 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
12704 .dac_nids = alc861_dac_nids,
12705 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
12706 .channel_mode = alc883_3ST_2ch_modes,
12707 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
12708 .adc_nids = alc861_adc_nids,
12709 .input_mux = &alc861_capture_source,
12710 .unsol_event = alc861_toshiba_unsol_event,
12711 .init_hook = alc861_toshiba_automute,
12713 [ALC861_ASUS] = {
12714 .mixers = { alc861_asus_mixer },
12715 .init_verbs = { alc861_asus_init_verbs },
12716 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
12717 .dac_nids = alc861_dac_nids,
12718 .dig_out_nid = ALC861_DIGOUT_NID,
12719 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
12720 .channel_mode = alc861_asus_modes,
12721 .need_dac_fix = 1,
12722 .hp_nid = 0x06,
12723 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
12724 .adc_nids = alc861_adc_nids,
12725 .input_mux = &alc861_capture_source,
12727 [ALC861_ASUS_LAPTOP] = {
12728 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
12729 .init_verbs = { alc861_asus_init_verbs,
12730 alc861_asus_laptop_init_verbs },
12731 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
12732 .dac_nids = alc861_dac_nids,
12733 .dig_out_nid = ALC861_DIGOUT_NID,
12734 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
12735 .channel_mode = alc883_3ST_2ch_modes,
12736 .need_dac_fix = 1,
12737 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
12738 .adc_nids = alc861_adc_nids,
12739 .input_mux = &alc861_capture_source,
12744 static int patch_alc861(struct hda_codec *codec)
12746 struct alc_spec *spec;
12747 int board_config;
12748 int err;
12750 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
12751 if (spec == NULL)
12752 return -ENOMEM;
12754 codec->spec = spec;
12756 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
12757 alc861_models,
12758 alc861_cfg_tbl);
12760 if (board_config < 0) {
12761 printk(KERN_INFO "hda_codec: Unknown model for ALC861, "
12762 "trying auto-probe from BIOS...\n");
12763 board_config = ALC861_AUTO;
12766 if (board_config == ALC861_AUTO) {
12767 /* automatic parse from the BIOS config */
12768 err = alc861_parse_auto_config(codec);
12769 if (err < 0) {
12770 alc_free(codec);
12771 return err;
12772 } else if (!err) {
12773 printk(KERN_INFO
12774 "hda_codec: Cannot set up configuration "
12775 "from BIOS. Using base mode...\n");
12776 board_config = ALC861_3ST_DIG;
12780 if (board_config != ALC861_AUTO)
12781 setup_preset(spec, &alc861_presets[board_config]);
12783 spec->stream_name_analog = "ALC861 Analog";
12784 spec->stream_analog_playback = &alc861_pcm_analog_playback;
12785 spec->stream_analog_capture = &alc861_pcm_analog_capture;
12787 spec->stream_name_digital = "ALC861 Digital";
12788 spec->stream_digital_playback = &alc861_pcm_digital_playback;
12789 spec->stream_digital_capture = &alc861_pcm_digital_capture;
12791 spec->vmaster_nid = 0x03;
12793 codec->patch_ops = alc_patch_ops;
12794 if (board_config == ALC861_AUTO)
12795 spec->init_hook = alc861_auto_init;
12796 #ifdef CONFIG_SND_HDA_POWER_SAVE
12797 if (!spec->loopback.amplist)
12798 spec->loopback.amplist = alc861_loopbacks;
12799 #endif
12801 return 0;
12805 * ALC861-VD support
12807 * Based on ALC882
12809 * In addition, an independent DAC
12811 #define ALC861VD_DIGOUT_NID 0x06
12813 static hda_nid_t alc861vd_dac_nids[4] = {
12814 /* front, surr, clfe, side surr */
12815 0x02, 0x03, 0x04, 0x05
12818 /* dac_nids for ALC660vd are in a different order - according to
12819 * Realtek's driver.
12820 * This should probably tesult in a different mixer for 6stack models
12821 * of ALC660vd codecs, but for now there is only 3stack mixer
12822 * - and it is the same as in 861vd.
12823 * adc_nids in ALC660vd are (is) the same as in 861vd
12825 static hda_nid_t alc660vd_dac_nids[3] = {
12826 /* front, rear, clfe, rear_surr */
12827 0x02, 0x04, 0x03
12830 static hda_nid_t alc861vd_adc_nids[1] = {
12831 /* ADC0 */
12832 0x09,
12835 static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
12837 /* input MUX */
12838 /* FIXME: should be a matrix-type input source selection */
12839 static struct hda_input_mux alc861vd_capture_source = {
12840 .num_items = 4,
12841 .items = {
12842 { "Mic", 0x0 },
12843 { "Front Mic", 0x1 },
12844 { "Line", 0x2 },
12845 { "CD", 0x4 },
12849 static struct hda_input_mux alc861vd_dallas_capture_source = {
12850 .num_items = 2,
12851 .items = {
12852 { "Ext Mic", 0x0 },
12853 { "Int Mic", 0x1 },
12857 static struct hda_input_mux alc861vd_hp_capture_source = {
12858 .num_items = 2,
12859 .items = {
12860 { "Front Mic", 0x0 },
12861 { "ATAPI Mic", 0x1 },
12865 #define alc861vd_mux_enum_info alc_mux_enum_info
12866 #define alc861vd_mux_enum_get alc_mux_enum_get
12867 /* ALC861VD has the ALC882-type input selection (but has only one ADC) */
12868 #define alc861vd_mux_enum_put alc882_mux_enum_put
12871 * 2ch mode
12873 static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
12874 { 2, NULL }
12878 * 6ch mode
12880 static struct hda_verb alc861vd_6stack_ch6_init[] = {
12881 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
12882 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12883 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12884 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12885 { } /* end */
12889 * 8ch mode
12891 static struct hda_verb alc861vd_6stack_ch8_init[] = {
12892 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12893 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12894 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12895 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12896 { } /* end */
12899 static struct hda_channel_mode alc861vd_6stack_modes[2] = {
12900 { 6, alc861vd_6stack_ch6_init },
12901 { 8, alc861vd_6stack_ch8_init },
12904 static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
12906 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12907 .name = "Channel Mode",
12908 .info = alc_ch_mode_info,
12909 .get = alc_ch_mode_get,
12910 .put = alc_ch_mode_put,
12912 { } /* end */
12915 static struct snd_kcontrol_new alc861vd_capture_mixer[] = {
12916 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
12917 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
12920 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12921 /* The multiple "Capture Source" controls confuse alsamixer
12922 * So call somewhat different..
12924 /* .name = "Capture Source", */
12925 .name = "Input Source",
12926 .count = 1,
12927 .info = alc861vd_mux_enum_info,
12928 .get = alc861vd_mux_enum_get,
12929 .put = alc861vd_mux_enum_put,
12931 { } /* end */
12934 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
12935 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
12937 static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
12938 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
12939 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
12941 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
12942 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
12944 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
12945 HDA_OUTPUT),
12946 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
12947 HDA_OUTPUT),
12948 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
12949 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
12951 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
12952 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
12954 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
12956 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12957 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
12958 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
12960 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
12961 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
12962 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
12964 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
12965 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
12967 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
12968 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
12970 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
12971 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
12973 { } /* end */
12976 static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
12977 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
12978 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
12980 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
12982 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12983 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
12984 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
12986 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
12987 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
12988 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
12990 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
12991 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
12993 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
12994 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
12996 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
12997 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
12999 { } /* end */
13002 static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
13003 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13004 /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
13005 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13007 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
13009 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13010 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13011 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13013 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
13014 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
13015 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
13017 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
13018 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
13020 { } /* end */
13023 /* Pin assignment: Speaker=0x14, HP = 0x15,
13024 * Ext Mic=0x18, Int Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
13026 static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
13027 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13028 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
13029 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13030 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
13031 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
13032 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13033 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13034 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
13035 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
13036 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
13037 HDA_CODEC_VOLUME("PC Beep Volume", 0x0b, 0x05, HDA_INPUT),
13038 HDA_CODEC_MUTE("PC Beep Switch", 0x0b, 0x05, HDA_INPUT),
13039 { } /* end */
13042 /* Pin assignment: Speaker=0x14, Line-out = 0x15,
13043 * Front Mic=0x18, ATAPI Mic = 0x19,
13045 static struct snd_kcontrol_new alc861vd_hp_mixer[] = {
13046 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13047 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
13048 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13049 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
13050 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13051 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13052 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
13053 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
13055 { } /* end */
13059 * generic initialization of ADC, input mixers and output mixers
13061 static struct hda_verb alc861vd_volume_init_verbs[] = {
13063 * Unmute ADC0 and set the default input to mic-in
13065 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
13066 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13068 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
13069 * the analog-loopback mixer widget
13071 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
13072 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
13073 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13074 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
13075 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
13076 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
13078 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
13079 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13080 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13081 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
13082 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
13085 * Set up output mixers (0x02 - 0x05)
13087 /* set vol=0 to output mixers */
13088 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13089 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13090 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13091 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13093 /* set up input amps for analog loopback */
13094 /* Amp Indices: DAC = 0, mixer = 1 */
13095 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
13096 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13097 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
13098 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13099 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
13100 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13101 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
13102 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13108 * 3-stack pin configuration:
13109 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
13111 static struct hda_verb alc861vd_3stack_init_verbs[] = {
13113 * Set pin mode and muting
13115 /* set front pin widgets 0x14 for output */
13116 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13117 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13118 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
13120 /* Mic (rear) pin: input vref at 80% */
13121 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13122 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13123 /* Front Mic pin: input vref at 80% */
13124 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13125 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13126 /* Line In pin: input */
13127 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13128 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13129 /* Line-2 In: Headphone output (output 0 - 0x0c) */
13130 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13131 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13132 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
13133 /* CD pin widget for input */
13134 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13140 * 6-stack pin configuration:
13142 static struct hda_verb alc861vd_6stack_init_verbs[] = {
13144 * Set pin mode and muting
13146 /* set front pin widgets 0x14 for output */
13147 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13148 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13149 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
13151 /* Rear Pin: output 1 (0x0d) */
13152 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13153 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13154 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13155 /* CLFE Pin: output 2 (0x0e) */
13156 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13157 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13158 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
13159 /* Side Pin: output 3 (0x0f) */
13160 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13161 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13162 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
13164 /* Mic (rear) pin: input vref at 80% */
13165 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13166 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13167 /* Front Mic pin: input vref at 80% */
13168 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13169 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13170 /* Line In pin: input */
13171 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13172 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13173 /* Line-2 In: Headphone output (output 0 - 0x0c) */
13174 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13175 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13176 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
13177 /* CD pin widget for input */
13178 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13183 static struct hda_verb alc861vd_eapd_verbs[] = {
13184 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
13188 static struct hda_verb alc660vd_eapd_verbs[] = {
13189 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
13190 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
13194 static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
13195 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13196 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13197 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
13198 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
13199 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13203 /* toggle speaker-output according to the hp-jack state */
13204 static void alc861vd_lenovo_hp_automute(struct hda_codec *codec)
13206 unsigned int present;
13207 unsigned char bits;
13209 present = snd_hda_codec_read(codec, 0x1b, 0,
13210 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
13211 bits = present ? HDA_AMP_MUTE : 0;
13212 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
13213 HDA_AMP_MUTE, bits);
13216 static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
13218 unsigned int present;
13219 unsigned char bits;
13221 present = snd_hda_codec_read(codec, 0x18, 0,
13222 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
13223 bits = present ? HDA_AMP_MUTE : 0;
13224 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
13225 HDA_AMP_MUTE, bits);
13228 static void alc861vd_lenovo_automute(struct hda_codec *codec)
13230 alc861vd_lenovo_hp_automute(codec);
13231 alc861vd_lenovo_mic_automute(codec);
13234 static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
13235 unsigned int res)
13237 switch (res >> 26) {
13238 case ALC880_HP_EVENT:
13239 alc861vd_lenovo_hp_automute(codec);
13240 break;
13241 case ALC880_MIC_EVENT:
13242 alc861vd_lenovo_mic_automute(codec);
13243 break;
13247 static struct hda_verb alc861vd_dallas_verbs[] = {
13248 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13249 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13250 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13251 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13253 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13254 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13255 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
13256 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13257 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
13258 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13259 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
13260 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13262 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13263 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13264 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13265 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13266 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13267 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13268 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13269 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13271 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
13272 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13273 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
13274 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13275 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13276 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13277 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13278 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13280 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13281 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
13282 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
13283 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
13285 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
13286 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
13287 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
13289 { } /* end */
13292 /* toggle speaker-output according to the hp-jack state */
13293 static void alc861vd_dallas_automute(struct hda_codec *codec)
13295 unsigned int present;
13297 present = snd_hda_codec_read(codec, 0x15, 0,
13298 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
13299 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
13300 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
13303 static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res)
13305 if ((res >> 26) == ALC880_HP_EVENT)
13306 alc861vd_dallas_automute(codec);
13309 #ifdef CONFIG_SND_HDA_POWER_SAVE
13310 #define alc861vd_loopbacks alc880_loopbacks
13311 #endif
13313 /* pcm configuration: identiacal with ALC880 */
13314 #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback
13315 #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture
13316 #define alc861vd_pcm_digital_playback alc880_pcm_digital_playback
13317 #define alc861vd_pcm_digital_capture alc880_pcm_digital_capture
13320 * configuration and preset
13322 static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
13323 [ALC660VD_3ST] = "3stack-660",
13324 [ALC660VD_3ST_DIG] = "3stack-660-digout",
13325 [ALC861VD_3ST] = "3stack",
13326 [ALC861VD_3ST_DIG] = "3stack-digout",
13327 [ALC861VD_6ST_DIG] = "6stack-digout",
13328 [ALC861VD_LENOVO] = "lenovo",
13329 [ALC861VD_DALLAS] = "dallas",
13330 [ALC861VD_HP] = "hp",
13331 [ALC861VD_AUTO] = "auto",
13334 static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
13335 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
13336 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
13337 SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
13338 SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
13339 SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC861VD_LENOVO),
13340 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
13341 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
13342 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
13343 /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
13344 SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
13345 SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
13346 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
13347 SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
13348 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
13349 SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
13350 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 N200", ALC861VD_LENOVO),
13351 SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
13355 static struct alc_config_preset alc861vd_presets[] = {
13356 [ALC660VD_3ST] = {
13357 .mixers = { alc861vd_3st_mixer },
13358 .init_verbs = { alc861vd_volume_init_verbs,
13359 alc861vd_3stack_init_verbs },
13360 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
13361 .dac_nids = alc660vd_dac_nids,
13362 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
13363 .channel_mode = alc861vd_3stack_2ch_modes,
13364 .input_mux = &alc861vd_capture_source,
13366 [ALC660VD_3ST_DIG] = {
13367 .mixers = { alc861vd_3st_mixer },
13368 .init_verbs = { alc861vd_volume_init_verbs,
13369 alc861vd_3stack_init_verbs },
13370 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
13371 .dac_nids = alc660vd_dac_nids,
13372 .dig_out_nid = ALC861VD_DIGOUT_NID,
13373 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
13374 .channel_mode = alc861vd_3stack_2ch_modes,
13375 .input_mux = &alc861vd_capture_source,
13377 [ALC861VD_3ST] = {
13378 .mixers = { alc861vd_3st_mixer },
13379 .init_verbs = { alc861vd_volume_init_verbs,
13380 alc861vd_3stack_init_verbs },
13381 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
13382 .dac_nids = alc861vd_dac_nids,
13383 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
13384 .channel_mode = alc861vd_3stack_2ch_modes,
13385 .input_mux = &alc861vd_capture_source,
13387 [ALC861VD_3ST_DIG] = {
13388 .mixers = { alc861vd_3st_mixer },
13389 .init_verbs = { alc861vd_volume_init_verbs,
13390 alc861vd_3stack_init_verbs },
13391 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
13392 .dac_nids = alc861vd_dac_nids,
13393 .dig_out_nid = ALC861VD_DIGOUT_NID,
13394 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
13395 .channel_mode = alc861vd_3stack_2ch_modes,
13396 .input_mux = &alc861vd_capture_source,
13398 [ALC861VD_6ST_DIG] = {
13399 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
13400 .init_verbs = { alc861vd_volume_init_verbs,
13401 alc861vd_6stack_init_verbs },
13402 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
13403 .dac_nids = alc861vd_dac_nids,
13404 .dig_out_nid = ALC861VD_DIGOUT_NID,
13405 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
13406 .channel_mode = alc861vd_6stack_modes,
13407 .input_mux = &alc861vd_capture_source,
13409 [ALC861VD_LENOVO] = {
13410 .mixers = { alc861vd_lenovo_mixer },
13411 .init_verbs = { alc861vd_volume_init_verbs,
13412 alc861vd_3stack_init_verbs,
13413 alc861vd_eapd_verbs,
13414 alc861vd_lenovo_unsol_verbs },
13415 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
13416 .dac_nids = alc660vd_dac_nids,
13417 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
13418 .channel_mode = alc861vd_3stack_2ch_modes,
13419 .input_mux = &alc861vd_capture_source,
13420 .unsol_event = alc861vd_lenovo_unsol_event,
13421 .init_hook = alc861vd_lenovo_automute,
13423 [ALC861VD_DALLAS] = {
13424 .mixers = { alc861vd_dallas_mixer },
13425 .init_verbs = { alc861vd_dallas_verbs },
13426 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
13427 .dac_nids = alc861vd_dac_nids,
13428 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
13429 .channel_mode = alc861vd_3stack_2ch_modes,
13430 .input_mux = &alc861vd_dallas_capture_source,
13431 .unsol_event = alc861vd_dallas_unsol_event,
13432 .init_hook = alc861vd_dallas_automute,
13434 [ALC861VD_HP] = {
13435 .mixers = { alc861vd_hp_mixer },
13436 .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
13437 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
13438 .dac_nids = alc861vd_dac_nids,
13439 .dig_out_nid = ALC861VD_DIGOUT_NID,
13440 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
13441 .channel_mode = alc861vd_3stack_2ch_modes,
13442 .input_mux = &alc861vd_hp_capture_source,
13443 .unsol_event = alc861vd_dallas_unsol_event,
13444 .init_hook = alc861vd_dallas_automute,
13449 * BIOS auto configuration
13451 static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
13452 hda_nid_t nid, int pin_type, int dac_idx)
13454 alc_set_pin_output(codec, nid, pin_type);
13457 static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
13459 struct alc_spec *spec = codec->spec;
13460 int i;
13462 alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
13463 for (i = 0; i <= HDA_SIDE; i++) {
13464 hda_nid_t nid = spec->autocfg.line_out_pins[i];
13465 int pin_type = get_pin_type(spec->autocfg.line_out_type);
13466 if (nid)
13467 alc861vd_auto_set_output_and_unmute(codec, nid,
13468 pin_type, i);
13473 static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
13475 struct alc_spec *spec = codec->spec;
13476 hda_nid_t pin;
13478 pin = spec->autocfg.hp_pins[0];
13479 if (pin) /* connect to front and use dac 0 */
13480 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
13481 pin = spec->autocfg.speaker_pins[0];
13482 if (pin)
13483 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
13486 #define alc861vd_is_input_pin(nid) alc880_is_input_pin(nid)
13487 #define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID
13489 static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
13491 struct alc_spec *spec = codec->spec;
13492 int i;
13494 for (i = 0; i < AUTO_PIN_LAST; i++) {
13495 hda_nid_t nid = spec->autocfg.input_pins[i];
13496 if (alc861vd_is_input_pin(nid)) {
13497 snd_hda_codec_write(codec, nid, 0,
13498 AC_VERB_SET_PIN_WIDGET_CONTROL,
13499 i <= AUTO_PIN_FRONT_MIC ?
13500 PIN_VREF80 : PIN_IN);
13501 if (nid != ALC861VD_PIN_CD_NID)
13502 snd_hda_codec_write(codec, nid, 0,
13503 AC_VERB_SET_AMP_GAIN_MUTE,
13504 AMP_OUT_MUTE);
13509 #define alc861vd_auto_init_input_src alc882_auto_init_input_src
13511 #define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02)
13512 #define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)
13514 /* add playback controls from the parsed DAC table */
13515 /* Based on ALC880 version. But ALC861VD has separate,
13516 * different NIDs for mute/unmute switch and volume control */
13517 static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
13518 const struct auto_pin_cfg *cfg)
13520 char name[32];
13521 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
13522 hda_nid_t nid_v, nid_s;
13523 int i, err;
13525 for (i = 0; i < cfg->line_outs; i++) {
13526 if (!spec->multiout.dac_nids[i])
13527 continue;
13528 nid_v = alc861vd_idx_to_mixer_vol(
13529 alc880_dac_to_idx(
13530 spec->multiout.dac_nids[i]));
13531 nid_s = alc861vd_idx_to_mixer_switch(
13532 alc880_dac_to_idx(
13533 spec->multiout.dac_nids[i]));
13535 if (i == 2) {
13536 /* Center/LFE */
13537 err = add_control(spec, ALC_CTL_WIDGET_VOL,
13538 "Center Playback Volume",
13539 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
13540 HDA_OUTPUT));
13541 if (err < 0)
13542 return err;
13543 err = add_control(spec, ALC_CTL_WIDGET_VOL,
13544 "LFE Playback Volume",
13545 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
13546 HDA_OUTPUT));
13547 if (err < 0)
13548 return err;
13549 err = add_control(spec, ALC_CTL_BIND_MUTE,
13550 "Center Playback Switch",
13551 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
13552 HDA_INPUT));
13553 if (err < 0)
13554 return err;
13555 err = add_control(spec, ALC_CTL_BIND_MUTE,
13556 "LFE Playback Switch",
13557 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
13558 HDA_INPUT));
13559 if (err < 0)
13560 return err;
13561 } else {
13562 sprintf(name, "%s Playback Volume", chname[i]);
13563 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
13564 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
13565 HDA_OUTPUT));
13566 if (err < 0)
13567 return err;
13568 sprintf(name, "%s Playback Switch", chname[i]);
13569 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
13570 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
13571 HDA_INPUT));
13572 if (err < 0)
13573 return err;
13576 return 0;
13579 /* add playback controls for speaker and HP outputs */
13580 /* Based on ALC880 version. But ALC861VD has separate,
13581 * different NIDs for mute/unmute switch and volume control */
13582 static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
13583 hda_nid_t pin, const char *pfx)
13585 hda_nid_t nid_v, nid_s;
13586 int err;
13587 char name[32];
13589 if (!pin)
13590 return 0;
13592 if (alc880_is_fixed_pin(pin)) {
13593 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
13594 /* specify the DAC as the extra output */
13595 if (!spec->multiout.hp_nid)
13596 spec->multiout.hp_nid = nid_v;
13597 else
13598 spec->multiout.extra_out_nid[0] = nid_v;
13599 /* control HP volume/switch on the output mixer amp */
13600 nid_v = alc861vd_idx_to_mixer_vol(
13601 alc880_fixed_pin_idx(pin));
13602 nid_s = alc861vd_idx_to_mixer_switch(
13603 alc880_fixed_pin_idx(pin));
13605 sprintf(name, "%s Playback Volume", pfx);
13606 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
13607 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
13608 if (err < 0)
13609 return err;
13610 sprintf(name, "%s Playback Switch", pfx);
13611 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
13612 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
13613 if (err < 0)
13614 return err;
13615 } else if (alc880_is_multi_pin(pin)) {
13616 /* set manual connection */
13617 /* we have only a switch on HP-out PIN */
13618 sprintf(name, "%s Playback Switch", pfx);
13619 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
13620 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
13621 if (err < 0)
13622 return err;
13624 return 0;
13627 /* parse the BIOS configuration and set up the alc_spec
13628 * return 1 if successful, 0 if the proper config is not found,
13629 * or a negative error code
13630 * Based on ALC880 version - had to change it to override
13631 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
13632 static int alc861vd_parse_auto_config(struct hda_codec *codec)
13634 struct alc_spec *spec = codec->spec;
13635 int err;
13636 static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
13638 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
13639 alc861vd_ignore);
13640 if (err < 0)
13641 return err;
13642 if (!spec->autocfg.line_outs)
13643 return 0; /* can't find valid BIOS pin config */
13645 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
13646 if (err < 0)
13647 return err;
13648 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
13649 if (err < 0)
13650 return err;
13651 err = alc861vd_auto_create_extra_out(spec,
13652 spec->autocfg.speaker_pins[0],
13653 "Speaker");
13654 if (err < 0)
13655 return err;
13656 err = alc861vd_auto_create_extra_out(spec,
13657 spec->autocfg.hp_pins[0],
13658 "Headphone");
13659 if (err < 0)
13660 return err;
13661 err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);
13662 if (err < 0)
13663 return err;
13665 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
13667 if (spec->autocfg.dig_out_pin)
13668 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
13670 if (spec->kctl_alloc)
13671 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
13673 spec->init_verbs[spec->num_init_verbs++]
13674 = alc861vd_volume_init_verbs;
13676 spec->num_mux_defs = 1;
13677 spec->input_mux = &spec->private_imux;
13679 err = alc_auto_add_mic_boost(codec);
13680 if (err < 0)
13681 return err;
13683 store_pin_configs(codec);
13684 return 1;
13687 /* additional initialization for auto-configuration model */
13688 static void alc861vd_auto_init(struct hda_codec *codec)
13690 struct alc_spec *spec = codec->spec;
13691 alc861vd_auto_init_multi_out(codec);
13692 alc861vd_auto_init_hp_out(codec);
13693 alc861vd_auto_init_analog_input(codec);
13694 alc861vd_auto_init_input_src(codec);
13695 if (spec->unsol_event)
13696 alc_sku_automute(codec);
13699 static int patch_alc861vd(struct hda_codec *codec)
13701 struct alc_spec *spec;
13702 int err, board_config;
13704 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
13705 if (spec == NULL)
13706 return -ENOMEM;
13708 codec->spec = spec;
13710 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
13711 alc861vd_models,
13712 alc861vd_cfg_tbl);
13714 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
13715 printk(KERN_INFO "hda_codec: Unknown model for ALC660VD/"
13716 "ALC861VD, trying auto-probe from BIOS...\n");
13717 board_config = ALC861VD_AUTO;
13720 if (board_config == ALC861VD_AUTO) {
13721 /* automatic parse from the BIOS config */
13722 err = alc861vd_parse_auto_config(codec);
13723 if (err < 0) {
13724 alc_free(codec);
13725 return err;
13726 } else if (!err) {
13727 printk(KERN_INFO
13728 "hda_codec: Cannot set up configuration "
13729 "from BIOS. Using base mode...\n");
13730 board_config = ALC861VD_3ST;
13734 if (board_config != ALC861VD_AUTO)
13735 setup_preset(spec, &alc861vd_presets[board_config]);
13737 if (codec->vendor_id == 0x10ec0660) {
13738 spec->stream_name_analog = "ALC660-VD Analog";
13739 spec->stream_name_digital = "ALC660-VD Digital";
13740 /* always turn on EAPD */
13741 spec->init_verbs[spec->num_init_verbs++] = alc660vd_eapd_verbs;
13742 } else {
13743 spec->stream_name_analog = "ALC861VD Analog";
13744 spec->stream_name_digital = "ALC861VD Digital";
13747 spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
13748 spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
13750 spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
13751 spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
13753 spec->adc_nids = alc861vd_adc_nids;
13754 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
13755 spec->capsrc_nids = alc861vd_capsrc_nids;
13757 spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
13758 spec->num_mixers++;
13760 spec->vmaster_nid = 0x02;
13762 codec->patch_ops = alc_patch_ops;
13764 if (board_config == ALC861VD_AUTO)
13765 spec->init_hook = alc861vd_auto_init;
13766 #ifdef CONFIG_SND_HDA_POWER_SAVE
13767 if (!spec->loopback.amplist)
13768 spec->loopback.amplist = alc861vd_loopbacks;
13769 #endif
13771 return 0;
13775 * ALC662 support
13777 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
13778 * configuration. Each pin widget can choose any input DACs and a mixer.
13779 * Each ADC is connected from a mixer of all inputs. This makes possible
13780 * 6-channel independent captures.
13782 * In addition, an independent DAC for the multi-playback (not used in this
13783 * driver yet).
13785 #define ALC662_DIGOUT_NID 0x06
13786 #define ALC662_DIGIN_NID 0x0a
13788 static hda_nid_t alc662_dac_nids[4] = {
13789 /* front, rear, clfe, rear_surr */
13790 0x02, 0x03, 0x04
13793 static hda_nid_t alc662_adc_nids[1] = {
13794 /* ADC1-2 */
13795 0x09,
13798 static hda_nid_t alc662_capsrc_nids[1] = { 0x22 };
13800 /* input MUX */
13801 /* FIXME: should be a matrix-type input source selection */
13802 static struct hda_input_mux alc662_capture_source = {
13803 .num_items = 4,
13804 .items = {
13805 { "Mic", 0x0 },
13806 { "Front Mic", 0x1 },
13807 { "Line", 0x2 },
13808 { "CD", 0x4 },
13812 static struct hda_input_mux alc662_lenovo_101e_capture_source = {
13813 .num_items = 2,
13814 .items = {
13815 { "Mic", 0x1 },
13816 { "Line", 0x2 },
13820 static struct hda_input_mux alc662_eeepc_capture_source = {
13821 .num_items = 2,
13822 .items = {
13823 { "i-Mic", 0x1 },
13824 { "e-Mic", 0x0 },
13828 static struct hda_input_mux alc663_capture_source = {
13829 .num_items = 3,
13830 .items = {
13831 { "Mic", 0x0 },
13832 { "Front Mic", 0x1 },
13833 { "Line", 0x2 },
13837 static struct hda_input_mux alc663_m51va_capture_source = {
13838 .num_items = 2,
13839 .items = {
13840 { "Ext-Mic", 0x0 },
13841 { "D-Mic", 0x9 },
13845 #define alc662_mux_enum_info alc_mux_enum_info
13846 #define alc662_mux_enum_get alc_mux_enum_get
13847 #define alc662_mux_enum_put alc882_mux_enum_put
13850 * 2ch mode
13852 static struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
13853 { 2, NULL }
13857 * 2ch mode
13859 static struct hda_verb alc662_3ST_ch2_init[] = {
13860 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
13861 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
13862 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
13863 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
13864 { } /* end */
13868 * 6ch mode
13870 static struct hda_verb alc662_3ST_ch6_init[] = {
13871 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
13872 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
13873 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
13874 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
13875 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
13876 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
13877 { } /* end */
13880 static struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
13881 { 2, alc662_3ST_ch2_init },
13882 { 6, alc662_3ST_ch6_init },
13886 * 2ch mode
13888 static struct hda_verb alc662_sixstack_ch6_init[] = {
13889 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
13890 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
13891 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
13892 { } /* end */
13896 * 6ch mode
13898 static struct hda_verb alc662_sixstack_ch8_init[] = {
13899 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
13900 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
13901 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
13902 { } /* end */
13905 static struct hda_channel_mode alc662_5stack_modes[2] = {
13906 { 2, alc662_sixstack_ch6_init },
13907 { 6, alc662_sixstack_ch8_init },
13910 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
13911 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
13914 static struct snd_kcontrol_new alc662_base_mixer[] = {
13915 /* output mixer control */
13916 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
13917 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
13918 HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
13919 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
13920 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
13921 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
13922 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
13923 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
13924 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
13926 /*Input mixer control */
13927 HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
13928 HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
13929 HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
13930 HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
13931 HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
13932 HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
13933 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
13934 HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
13935 { } /* end */
13938 static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
13939 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13940 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
13941 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
13942 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
13943 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
13944 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
13945 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
13946 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13947 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13948 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
13949 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
13950 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
13951 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
13952 { } /* end */
13955 static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
13956 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13957 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
13958 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13959 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
13960 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
13961 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
13962 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
13963 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
13964 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
13965 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
13966 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
13967 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
13968 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
13969 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13970 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13971 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
13972 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
13973 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
13974 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
13975 { } /* end */
13978 static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
13979 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13980 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
13981 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13982 HDA_BIND_MUTE("Speaker Playback Switch", 0x03, 2, HDA_INPUT),
13983 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
13984 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
13985 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
13986 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
13987 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
13988 { } /* end */
13991 static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
13992 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13994 HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13995 HDA_CODEC_MUTE("Line-Out Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
13997 HDA_CODEC_VOLUME("e-Mic Boost", 0x18, 0, HDA_INPUT),
13998 HDA_CODEC_VOLUME("e-Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13999 HDA_CODEC_MUTE("e-Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14001 HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT),
14002 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
14003 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
14004 { } /* end */
14007 static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
14008 HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14009 HDA_CODEC_MUTE("Line-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT),
14010 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
14011 HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),
14012 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
14013 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
14014 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
14015 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
14016 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
14017 HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),
14018 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
14019 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
14020 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
14021 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14022 { } /* end */
14025 static struct snd_kcontrol_new alc663_m51va_mixer[] = {
14026 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14027 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
14028 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
14029 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
14030 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14031 HDA_CODEC_MUTE("DMic Playback Switch", 0x23, 0x9, HDA_INPUT),
14032 { } /* end */
14035 static struct snd_kcontrol_new alc663_g71v_mixer[] = {
14036 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14037 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
14038 HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
14039 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
14040 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
14042 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
14043 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14044 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
14045 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
14046 { } /* end */
14049 static struct snd_kcontrol_new alc663_g50v_mixer[] = {
14050 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
14051 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
14052 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
14054 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
14055 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
14056 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
14057 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
14058 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
14059 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
14060 { } /* end */
14063 static struct snd_kcontrol_new alc662_chmode_mixer[] = {
14065 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14066 .name = "Channel Mode",
14067 .info = alc_ch_mode_info,
14068 .get = alc_ch_mode_get,
14069 .put = alc_ch_mode_put,
14071 { } /* end */
14074 static struct hda_verb alc662_init_verbs[] = {
14075 /* ADC: mute amp left and right */
14076 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14077 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
14078 /* Front mixer: unmute input/output amp left and right (volume = 0) */
14080 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14081 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
14082 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
14083 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
14084 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
14086 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14087 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14088 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14089 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14090 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14091 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14093 /* Front Pin: output 0 (0x0c) */
14094 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14095 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14097 /* Rear Pin: output 1 (0x0d) */
14098 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14099 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14101 /* CLFE Pin: output 2 (0x0e) */
14102 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14103 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14105 /* Mic (rear) pin: input vref at 80% */
14106 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14107 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14108 /* Front Mic pin: input vref at 80% */
14109 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14110 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14111 /* Line In pin: input */
14112 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14113 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14114 /* Line-2 In: Headphone output (output 0 - 0x0c) */
14115 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14116 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14117 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
14118 /* CD pin widget for input */
14119 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14121 /* FIXME: use matrix-type input source selection */
14122 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
14123 /* Input mixer */
14124 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14125 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14126 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14127 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
14129 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14130 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14131 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14132 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
14134 /* always trun on EAPD */
14135 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
14136 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
14141 static struct hda_verb alc662_sue_init_verbs[] = {
14142 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
14143 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
14147 static struct hda_verb alc662_eeepc_sue_init_verbs[] = {
14148 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14149 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14153 /* Set Unsolicited Event*/
14154 static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
14155 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14156 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14161 * generic initialization of ADC, input mixers and output mixers
14163 static struct hda_verb alc662_auto_init_verbs[] = {
14165 * Unmute ADC and set the default input to mic-in
14167 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
14168 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14170 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
14171 * mixer widget
14172 * Note: PASD motherboards uses the Line In 2 as the input for front
14173 * panel mic (mic 2)
14175 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
14176 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14177 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
14178 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
14179 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
14180 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
14183 * Set up output mixers (0x0c - 0x0f)
14185 /* set vol=0 to output mixers */
14186 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14187 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14188 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14190 /* set up input amps for analog loopback */
14191 /* Amp Indices: DAC = 0, mixer = 1 */
14192 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14193 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14194 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14195 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14196 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14197 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14200 /* FIXME: use matrix-type input source selection */
14201 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
14202 /* Input mixer */
14203 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14204 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14208 /* additional verbs for ALC663 */
14209 static struct hda_verb alc663_auto_init_verbs[] = {
14210 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14211 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14215 static struct hda_verb alc663_m51va_init_verbs[] = {
14216 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14217 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14218 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
14220 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
14222 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14223 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14227 static struct hda_verb alc663_g71v_init_verbs[] = {
14228 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14229 /* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
14230 /* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
14232 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14233 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14234 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
14236 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
14237 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_MIC_EVENT},
14238 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
14242 static struct hda_verb alc663_g50v_init_verbs[] = {
14243 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14244 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14245 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
14247 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14248 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14252 /* capture mixer elements */
14253 static struct snd_kcontrol_new alc662_capture_mixer[] = {
14254 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
14255 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
14257 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14258 /* The multiple "Capture Source" controls confuse alsamixer
14259 * So call somewhat different..
14261 /* .name = "Capture Source", */
14262 .name = "Input Source",
14263 .count = 1,
14264 .info = alc662_mux_enum_info,
14265 .get = alc662_mux_enum_get,
14266 .put = alc662_mux_enum_put,
14268 { } /* end */
14271 static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
14273 unsigned int present;
14274 unsigned char bits;
14276 present = snd_hda_codec_read(codec, 0x14, 0,
14277 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
14278 bits = present ? HDA_AMP_MUTE : 0;
14279 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
14280 HDA_AMP_MUTE, bits);
14283 static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
14285 unsigned int present;
14286 unsigned char bits;
14288 present = snd_hda_codec_read(codec, 0x1b, 0,
14289 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
14290 bits = present ? HDA_AMP_MUTE : 0;
14291 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
14292 HDA_AMP_MUTE, bits);
14293 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
14294 HDA_AMP_MUTE, bits);
14297 static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
14298 unsigned int res)
14300 if ((res >> 26) == ALC880_HP_EVENT)
14301 alc662_lenovo_101e_all_automute(codec);
14302 if ((res >> 26) == ALC880_FRONT_EVENT)
14303 alc662_lenovo_101e_ispeaker_automute(codec);
14306 static void alc662_eeepc_mic_automute(struct hda_codec *codec)
14308 unsigned int present;
14310 present = snd_hda_codec_read(codec, 0x18, 0,
14311 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
14312 snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
14313 0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
14314 snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
14315 0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
14316 snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
14317 0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
14318 snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
14319 0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
14322 /* unsolicited event for HP jack sensing */
14323 static void alc662_eeepc_unsol_event(struct hda_codec *codec,
14324 unsigned int res)
14326 if ((res >> 26) == ALC880_HP_EVENT)
14327 alc262_hippo1_automute( codec );
14329 if ((res >> 26) == ALC880_MIC_EVENT)
14330 alc662_eeepc_mic_automute(codec);
14333 static void alc662_eeepc_inithook(struct hda_codec *codec)
14335 alc262_hippo1_automute( codec );
14336 alc662_eeepc_mic_automute(codec);
14339 static void alc662_eeepc_ep20_automute(struct hda_codec *codec)
14341 unsigned int mute;
14342 unsigned int present;
14344 snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
14345 present = snd_hda_codec_read(codec, 0x14, 0,
14346 AC_VERB_GET_PIN_SENSE, 0);
14347 present = (present & 0x80000000) != 0;
14348 if (present) {
14349 /* mute internal speaker */
14350 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
14351 HDA_AMP_MUTE, HDA_AMP_MUTE);
14352 } else {
14353 /* unmute internal speaker if necessary */
14354 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
14355 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
14356 HDA_AMP_MUTE, mute);
14360 /* unsolicited event for HP jack sensing */
14361 static void alc662_eeepc_ep20_unsol_event(struct hda_codec *codec,
14362 unsigned int res)
14364 if ((res >> 26) == ALC880_HP_EVENT)
14365 alc662_eeepc_ep20_automute(codec);
14368 static void alc662_eeepc_ep20_inithook(struct hda_codec *codec)
14370 alc662_eeepc_ep20_automute(codec);
14373 static void alc663_m51va_speaker_automute(struct hda_codec *codec)
14375 unsigned int present;
14376 unsigned char bits;
14378 present = snd_hda_codec_read(codec, 0x21, 0,
14379 AC_VERB_GET_PIN_SENSE, 0)
14380 & AC_PINSENSE_PRESENCE;
14381 bits = present ? HDA_AMP_MUTE : 0;
14382 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
14383 HDA_AMP_MUTE, bits);
14386 static void alc663_m51va_mic_automute(struct hda_codec *codec)
14388 unsigned int present;
14390 present = snd_hda_codec_read(codec, 0x18, 0,
14391 AC_VERB_GET_PIN_SENSE, 0)
14392 & AC_PINSENSE_PRESENCE;
14393 snd_hda_codec_write_cache(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
14394 0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
14395 snd_hda_codec_write_cache(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
14396 0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
14397 snd_hda_codec_write_cache(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
14398 0x7000 | (0x09 << 8) | (present ? 0x80 : 0));
14399 snd_hda_codec_write_cache(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
14400 0x7000 | (0x09 << 8) | (present ? 0x80 : 0));
14403 static void alc663_m51va_unsol_event(struct hda_codec *codec,
14404 unsigned int res)
14406 switch (res >> 26) {
14407 case ALC880_HP_EVENT:
14408 alc663_m51va_speaker_automute(codec);
14409 break;
14410 case ALC880_MIC_EVENT:
14411 alc663_m51va_mic_automute(codec);
14412 break;
14416 static void alc663_m51va_inithook(struct hda_codec *codec)
14418 alc663_m51va_speaker_automute(codec);
14419 alc663_m51va_mic_automute(codec);
14422 static void alc663_g71v_hp_automute(struct hda_codec *codec)
14424 unsigned int present;
14425 unsigned char bits;
14427 present = snd_hda_codec_read(codec, 0x21, 0,
14428 AC_VERB_GET_PIN_SENSE, 0)
14429 & AC_PINSENSE_PRESENCE;
14430 bits = present ? HDA_AMP_MUTE : 0;
14431 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
14432 HDA_AMP_MUTE, bits);
14433 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
14434 HDA_AMP_MUTE, bits);
14437 static void alc663_g71v_front_automute(struct hda_codec *codec)
14439 unsigned int present;
14440 unsigned char bits;
14442 present = snd_hda_codec_read(codec, 0x15, 0,
14443 AC_VERB_GET_PIN_SENSE, 0)
14444 & AC_PINSENSE_PRESENCE;
14445 bits = present ? HDA_AMP_MUTE : 0;
14446 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
14447 HDA_AMP_MUTE, bits);
14450 static void alc663_g71v_unsol_event(struct hda_codec *codec,
14451 unsigned int res)
14453 switch (res >> 26) {
14454 case ALC880_HP_EVENT:
14455 alc663_g71v_hp_automute(codec);
14456 break;
14457 case ALC880_FRONT_EVENT:
14458 alc663_g71v_front_automute(codec);
14459 break;
14460 case ALC880_MIC_EVENT:
14461 alc662_eeepc_mic_automute(codec);
14462 break;
14466 static void alc663_g71v_inithook(struct hda_codec *codec)
14468 alc663_g71v_front_automute(codec);
14469 alc663_g71v_hp_automute(codec);
14470 alc662_eeepc_mic_automute(codec);
14473 static void alc663_g50v_unsol_event(struct hda_codec *codec,
14474 unsigned int res)
14476 switch (res >> 26) {
14477 case ALC880_HP_EVENT:
14478 alc663_m51va_speaker_automute(codec);
14479 break;
14480 case ALC880_MIC_EVENT:
14481 alc662_eeepc_mic_automute(codec);
14482 break;
14486 static void alc663_g50v_inithook(struct hda_codec *codec)
14488 alc663_m51va_speaker_automute(codec);
14489 alc662_eeepc_mic_automute(codec);
14492 #ifdef CONFIG_SND_HDA_POWER_SAVE
14493 #define alc662_loopbacks alc880_loopbacks
14494 #endif
14497 /* pcm configuration: identiacal with ALC880 */
14498 #define alc662_pcm_analog_playback alc880_pcm_analog_playback
14499 #define alc662_pcm_analog_capture alc880_pcm_analog_capture
14500 #define alc662_pcm_digital_playback alc880_pcm_digital_playback
14501 #define alc662_pcm_digital_capture alc880_pcm_digital_capture
14504 * configuration and preset
14506 static const char *alc662_models[ALC662_MODEL_LAST] = {
14507 [ALC662_3ST_2ch_DIG] = "3stack-dig",
14508 [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig",
14509 [ALC662_3ST_6ch] = "3stack-6ch",
14510 [ALC662_5ST_DIG] = "6stack-dig",
14511 [ALC662_LENOVO_101E] = "lenovo-101e",
14512 [ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
14513 [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
14514 [ALC663_ASUS_M51VA] = "m51va",
14515 [ALC663_ASUS_G71V] = "g71v",
14516 [ALC663_ASUS_H13] = "h13",
14517 [ALC663_ASUS_G50V] = "g50v",
14518 [ALC662_AUTO] = "auto",
14521 static struct snd_pci_quirk alc662_cfg_tbl[] = {
14522 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS G71V", ALC663_ASUS_G71V),
14523 SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
14524 SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS M51VA", ALC663_ASUS_G50V),
14525 SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
14526 SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
14527 SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
14528 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
14529 SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13),
14530 SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13),
14531 SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13),
14535 static struct alc_config_preset alc662_presets[] = {
14536 [ALC662_3ST_2ch_DIG] = {
14537 .mixers = { alc662_3ST_2ch_mixer, alc662_capture_mixer },
14538 .init_verbs = { alc662_init_verbs },
14539 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14540 .dac_nids = alc662_dac_nids,
14541 .dig_out_nid = ALC662_DIGOUT_NID,
14542 .dig_in_nid = ALC662_DIGIN_NID,
14543 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
14544 .channel_mode = alc662_3ST_2ch_modes,
14545 .input_mux = &alc662_capture_source,
14547 [ALC662_3ST_6ch_DIG] = {
14548 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer,
14549 alc662_capture_mixer },
14550 .init_verbs = { alc662_init_verbs },
14551 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14552 .dac_nids = alc662_dac_nids,
14553 .dig_out_nid = ALC662_DIGOUT_NID,
14554 .dig_in_nid = ALC662_DIGIN_NID,
14555 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
14556 .channel_mode = alc662_3ST_6ch_modes,
14557 .need_dac_fix = 1,
14558 .input_mux = &alc662_capture_source,
14560 [ALC662_3ST_6ch] = {
14561 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer,
14562 alc662_capture_mixer },
14563 .init_verbs = { alc662_init_verbs },
14564 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14565 .dac_nids = alc662_dac_nids,
14566 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
14567 .channel_mode = alc662_3ST_6ch_modes,
14568 .need_dac_fix = 1,
14569 .input_mux = &alc662_capture_source,
14571 [ALC662_5ST_DIG] = {
14572 .mixers = { alc662_base_mixer, alc662_chmode_mixer,
14573 alc662_capture_mixer },
14574 .init_verbs = { alc662_init_verbs },
14575 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14576 .dac_nids = alc662_dac_nids,
14577 .dig_out_nid = ALC662_DIGOUT_NID,
14578 .dig_in_nid = ALC662_DIGIN_NID,
14579 .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
14580 .channel_mode = alc662_5stack_modes,
14581 .input_mux = &alc662_capture_source,
14583 [ALC662_LENOVO_101E] = {
14584 .mixers = { alc662_lenovo_101e_mixer, alc662_capture_mixer },
14585 .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
14586 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14587 .dac_nids = alc662_dac_nids,
14588 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
14589 .channel_mode = alc662_3ST_2ch_modes,
14590 .input_mux = &alc662_lenovo_101e_capture_source,
14591 .unsol_event = alc662_lenovo_101e_unsol_event,
14592 .init_hook = alc662_lenovo_101e_all_automute,
14594 [ALC662_ASUS_EEEPC_P701] = {
14595 .mixers = { alc662_eeepc_p701_mixer, alc662_capture_mixer },
14596 .init_verbs = { alc662_init_verbs,
14597 alc662_eeepc_sue_init_verbs },
14598 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14599 .dac_nids = alc662_dac_nids,
14600 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
14601 .channel_mode = alc662_3ST_2ch_modes,
14602 .input_mux = &alc662_eeepc_capture_source,
14603 .unsol_event = alc662_eeepc_unsol_event,
14604 .init_hook = alc662_eeepc_inithook,
14606 [ALC662_ASUS_EEEPC_EP20] = {
14607 .mixers = { alc662_eeepc_ep20_mixer, alc662_capture_mixer,
14608 alc662_chmode_mixer },
14609 .init_verbs = { alc662_init_verbs,
14610 alc662_eeepc_ep20_sue_init_verbs },
14611 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14612 .dac_nids = alc662_dac_nids,
14613 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
14614 .channel_mode = alc662_3ST_6ch_modes,
14615 .input_mux = &alc662_lenovo_101e_capture_source,
14616 .unsol_event = alc662_eeepc_ep20_unsol_event,
14617 .init_hook = alc662_eeepc_ep20_inithook,
14619 [ALC663_ASUS_M51VA] = {
14620 .mixers = { alc663_m51va_mixer, alc662_capture_mixer},
14621 .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
14622 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14623 .dac_nids = alc662_dac_nids,
14624 .dig_out_nid = ALC662_DIGOUT_NID,
14625 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
14626 .channel_mode = alc662_3ST_2ch_modes,
14627 .input_mux = &alc663_m51va_capture_source,
14628 .unsol_event = alc663_m51va_unsol_event,
14629 .init_hook = alc663_m51va_inithook,
14631 [ALC663_ASUS_G71V] = {
14632 .mixers = { alc663_g71v_mixer, alc662_capture_mixer},
14633 .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
14634 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14635 .dac_nids = alc662_dac_nids,
14636 .dig_out_nid = ALC662_DIGOUT_NID,
14637 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
14638 .channel_mode = alc662_3ST_2ch_modes,
14639 .input_mux = &alc662_eeepc_capture_source,
14640 .unsol_event = alc663_g71v_unsol_event,
14641 .init_hook = alc663_g71v_inithook,
14643 [ALC663_ASUS_H13] = {
14644 .mixers = { alc663_m51va_mixer, alc662_capture_mixer},
14645 .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
14646 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14647 .dac_nids = alc662_dac_nids,
14648 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
14649 .channel_mode = alc662_3ST_2ch_modes,
14650 .input_mux = &alc663_m51va_capture_source,
14651 .unsol_event = alc663_m51va_unsol_event,
14652 .init_hook = alc663_m51va_inithook,
14654 [ALC663_ASUS_G50V] = {
14655 .mixers = { alc663_g50v_mixer, alc662_capture_mixer},
14656 .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
14657 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
14658 .dac_nids = alc662_dac_nids,
14659 .dig_out_nid = ALC662_DIGOUT_NID,
14660 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
14661 .channel_mode = alc662_3ST_6ch_modes,
14662 .input_mux = &alc663_capture_source,
14663 .unsol_event = alc663_g50v_unsol_event,
14664 .init_hook = alc663_g50v_inithook,
14670 * BIOS auto configuration
14673 /* add playback controls from the parsed DAC table */
14674 static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
14675 const struct auto_pin_cfg *cfg)
14677 char name[32];
14678 static const char *chname[4] = {
14679 "Front", "Surround", NULL /*CLFE*/, "Side"
14681 hda_nid_t nid;
14682 int i, err;
14684 for (i = 0; i < cfg->line_outs; i++) {
14685 if (!spec->multiout.dac_nids[i])
14686 continue;
14687 nid = alc880_idx_to_dac(i);
14688 if (i == 2) {
14689 /* Center/LFE */
14690 err = add_control(spec, ALC_CTL_WIDGET_VOL,
14691 "Center Playback Volume",
14692 HDA_COMPOSE_AMP_VAL(nid, 1, 0,
14693 HDA_OUTPUT));
14694 if (err < 0)
14695 return err;
14696 err = add_control(spec, ALC_CTL_WIDGET_VOL,
14697 "LFE Playback Volume",
14698 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
14699 HDA_OUTPUT));
14700 if (err < 0)
14701 return err;
14702 err = add_control(spec, ALC_CTL_BIND_MUTE,
14703 "Center Playback Switch",
14704 HDA_COMPOSE_AMP_VAL(nid, 1, 2,
14705 HDA_INPUT));
14706 if (err < 0)
14707 return err;
14708 err = add_control(spec, ALC_CTL_BIND_MUTE,
14709 "LFE Playback Switch",
14710 HDA_COMPOSE_AMP_VAL(nid, 2, 2,
14711 HDA_INPUT));
14712 if (err < 0)
14713 return err;
14714 } else {
14715 sprintf(name, "%s Playback Volume", chname[i]);
14716 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
14717 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
14718 HDA_OUTPUT));
14719 if (err < 0)
14720 return err;
14721 sprintf(name, "%s Playback Switch", chname[i]);
14722 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
14723 HDA_COMPOSE_AMP_VAL(nid, 3, 2,
14724 HDA_INPUT));
14725 if (err < 0)
14726 return err;
14729 return 0;
14732 /* add playback controls for speaker and HP outputs */
14733 static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
14734 const char *pfx)
14736 hda_nid_t nid;
14737 int err;
14738 char name[32];
14740 if (!pin)
14741 return 0;
14743 if (pin == 0x17) {
14744 /* ALC663 has a mono output pin on 0x17 */
14745 sprintf(name, "%s Playback Switch", pfx);
14746 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
14747 HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT));
14748 return err;
14751 if (alc880_is_fixed_pin(pin)) {
14752 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
14753 /* printk("DAC nid=%x\n",nid); */
14754 /* specify the DAC as the extra output */
14755 if (!spec->multiout.hp_nid)
14756 spec->multiout.hp_nid = nid;
14757 else
14758 spec->multiout.extra_out_nid[0] = nid;
14759 /* control HP volume/switch on the output mixer amp */
14760 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
14761 sprintf(name, "%s Playback Volume", pfx);
14762 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
14763 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
14764 if (err < 0)
14765 return err;
14766 sprintf(name, "%s Playback Switch", pfx);
14767 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
14768 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
14769 if (err < 0)
14770 return err;
14771 } else if (alc880_is_multi_pin(pin)) {
14772 /* set manual connection */
14773 /* we have only a switch on HP-out PIN */
14774 sprintf(name, "%s Playback Switch", pfx);
14775 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
14776 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
14777 if (err < 0)
14778 return err;
14780 return 0;
14783 /* create playback/capture controls for input pins */
14784 static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec,
14785 const struct auto_pin_cfg *cfg)
14787 struct hda_input_mux *imux = &spec->private_imux;
14788 int i, err, idx;
14790 for (i = 0; i < AUTO_PIN_LAST; i++) {
14791 if (alc880_is_input_pin(cfg->input_pins[i])) {
14792 idx = alc880_input_pin_idx(cfg->input_pins[i]);
14793 err = new_analog_input(spec, cfg->input_pins[i],
14794 auto_pin_cfg_labels[i],
14795 idx, 0x0b);
14796 if (err < 0)
14797 return err;
14798 imux->items[imux->num_items].label =
14799 auto_pin_cfg_labels[i];
14800 imux->items[imux->num_items].index =
14801 alc880_input_pin_idx(cfg->input_pins[i]);
14802 imux->num_items++;
14805 return 0;
14808 static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
14809 hda_nid_t nid, int pin_type,
14810 int dac_idx)
14812 alc_set_pin_output(codec, nid, pin_type);
14813 /* need the manual connection? */
14814 if (alc880_is_multi_pin(nid)) {
14815 struct alc_spec *spec = codec->spec;
14816 int idx = alc880_multi_pin_idx(nid);
14817 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
14818 AC_VERB_SET_CONNECT_SEL,
14819 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
14823 static void alc662_auto_init_multi_out(struct hda_codec *codec)
14825 struct alc_spec *spec = codec->spec;
14826 int i;
14828 alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
14829 for (i = 0; i <= HDA_SIDE; i++) {
14830 hda_nid_t nid = spec->autocfg.line_out_pins[i];
14831 int pin_type = get_pin_type(spec->autocfg.line_out_type);
14832 if (nid)
14833 alc662_auto_set_output_and_unmute(codec, nid, pin_type,
14838 static void alc662_auto_init_hp_out(struct hda_codec *codec)
14840 struct alc_spec *spec = codec->spec;
14841 hda_nid_t pin;
14843 pin = spec->autocfg.hp_pins[0];
14844 if (pin) /* connect to front */
14845 /* use dac 0 */
14846 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
14847 pin = spec->autocfg.speaker_pins[0];
14848 if (pin)
14849 alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
14852 #define alc662_is_input_pin(nid) alc880_is_input_pin(nid)
14853 #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
14855 static void alc662_auto_init_analog_input(struct hda_codec *codec)
14857 struct alc_spec *spec = codec->spec;
14858 int i;
14860 for (i = 0; i < AUTO_PIN_LAST; i++) {
14861 hda_nid_t nid = spec->autocfg.input_pins[i];
14862 if (alc662_is_input_pin(nid)) {
14863 snd_hda_codec_write(codec, nid, 0,
14864 AC_VERB_SET_PIN_WIDGET_CONTROL,
14865 (i <= AUTO_PIN_FRONT_MIC ?
14866 PIN_VREF80 : PIN_IN));
14867 if (nid != ALC662_PIN_CD_NID)
14868 snd_hda_codec_write(codec, nid, 0,
14869 AC_VERB_SET_AMP_GAIN_MUTE,
14870 AMP_OUT_MUTE);
14875 #define alc662_auto_init_input_src alc882_auto_init_input_src
14877 static int alc662_parse_auto_config(struct hda_codec *codec)
14879 struct alc_spec *spec = codec->spec;
14880 int err;
14881 static hda_nid_t alc662_ignore[] = { 0x1d, 0 };
14883 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
14884 alc662_ignore);
14885 if (err < 0)
14886 return err;
14887 if (!spec->autocfg.line_outs)
14888 return 0; /* can't find valid BIOS pin config */
14890 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
14891 if (err < 0)
14892 return err;
14893 err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg);
14894 if (err < 0)
14895 return err;
14896 err = alc662_auto_create_extra_out(spec,
14897 spec->autocfg.speaker_pins[0],
14898 "Speaker");
14899 if (err < 0)
14900 return err;
14901 err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
14902 "Headphone");
14903 if (err < 0)
14904 return err;
14905 err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg);
14906 if (err < 0)
14907 return err;
14909 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
14911 if (spec->autocfg.dig_out_pin)
14912 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
14914 if (spec->kctl_alloc)
14915 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
14917 spec->num_mux_defs = 1;
14918 spec->input_mux = &spec->private_imux;
14920 spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs;
14921 if (codec->vendor_id == 0x10ec0663)
14922 spec->init_verbs[spec->num_init_verbs++] =
14923 alc663_auto_init_verbs;
14925 err = alc_auto_add_mic_boost(codec);
14926 if (err < 0)
14927 return err;
14929 spec->mixers[spec->num_mixers] = alc662_capture_mixer;
14930 spec->num_mixers++;
14932 store_pin_configs(codec);
14933 return 1;
14936 /* additional initialization for auto-configuration model */
14937 static void alc662_auto_init(struct hda_codec *codec)
14939 struct alc_spec *spec = codec->spec;
14940 alc662_auto_init_multi_out(codec);
14941 alc662_auto_init_hp_out(codec);
14942 alc662_auto_init_analog_input(codec);
14943 alc662_auto_init_input_src(codec);
14944 if (spec->unsol_event)
14945 alc_sku_automute(codec);
14948 static int patch_alc662(struct hda_codec *codec)
14950 struct alc_spec *spec;
14951 int err, board_config;
14953 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
14954 if (!spec)
14955 return -ENOMEM;
14957 codec->spec = spec;
14959 alc_fix_pll_init(codec, 0x20, 0x04, 15);
14961 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
14962 alc662_models,
14963 alc662_cfg_tbl);
14964 if (board_config < 0) {
14965 printk(KERN_INFO "hda_codec: Unknown model for ALC662, "
14966 "trying auto-probe from BIOS...\n");
14967 board_config = ALC662_AUTO;
14970 if (board_config == ALC662_AUTO) {
14971 /* automatic parse from the BIOS config */
14972 err = alc662_parse_auto_config(codec);
14973 if (err < 0) {
14974 alc_free(codec);
14975 return err;
14976 } else if (!err) {
14977 printk(KERN_INFO
14978 "hda_codec: Cannot set up configuration "
14979 "from BIOS. Using base mode...\n");
14980 board_config = ALC662_3ST_2ch_DIG;
14984 if (board_config != ALC662_AUTO)
14985 setup_preset(spec, &alc662_presets[board_config]);
14987 if (codec->vendor_id == 0x10ec0663) {
14988 spec->stream_name_analog = "ALC663 Analog";
14989 spec->stream_name_digital = "ALC663 Digital";
14990 } else if (codec->vendor_id == 0x10ec0272) {
14991 spec->stream_name_analog = "ALC272 Analog";
14992 spec->stream_name_digital = "ALC272 Digital";
14993 } else {
14994 spec->stream_name_analog = "ALC662 Analog";
14995 spec->stream_name_digital = "ALC662 Digital";
14998 spec->stream_analog_playback = &alc662_pcm_analog_playback;
14999 spec->stream_analog_capture = &alc662_pcm_analog_capture;
15001 spec->stream_digital_playback = &alc662_pcm_digital_playback;
15002 spec->stream_digital_capture = &alc662_pcm_digital_capture;
15004 spec->adc_nids = alc662_adc_nids;
15005 spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
15006 spec->capsrc_nids = alc662_capsrc_nids;
15008 spec->vmaster_nid = 0x02;
15010 codec->patch_ops = alc_patch_ops;
15011 if (board_config == ALC662_AUTO)
15012 spec->init_hook = alc662_auto_init;
15013 #ifdef CONFIG_SND_HDA_POWER_SAVE
15014 if (!spec->loopback.amplist)
15015 spec->loopback.amplist = alc662_loopbacks;
15016 #endif
15018 return 0;
15022 * patch entries
15024 struct hda_codec_preset snd_hda_preset_realtek[] = {
15025 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
15026 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
15027 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
15028 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
15029 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
15030 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
15031 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
15032 .patch = patch_alc861 },
15033 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
15034 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
15035 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
15036 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
15037 .patch = patch_alc883 },
15038 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
15039 .patch = patch_alc662 },
15040 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
15041 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
15042 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
15043 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
15044 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
15045 .patch = patch_alc882 }, /* should be patch_alc883() in future */
15046 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
15047 .patch = patch_alc882 }, /* should be patch_alc883() in future */
15048 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
15049 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 },
15050 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
15051 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
15052 {} /* terminator */