patch_realtek.c revision e60623b406ff3f8fea145466557f22daea671ae1
1/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * HD audio interface patch for ALC 260/880/882 codecs
5 *
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>
10 *
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.
15 *
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.
20 *
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
24 */
25
26#include <sound/driver.h>
27#include <linux/init.h>
28#include <linux/delay.h>
29#include <linux/slab.h>
30#include <linux/pci.h>
31#include <sound/core.h>
32#include "hda_codec.h"
33#include "hda_local.h"
34
35#define ALC880_FRONT_EVENT		0x01
36#define ALC880_DCVOL_EVENT		0x02
37#define ALC880_HP_EVENT			0x04
38#define ALC880_MIC_EVENT		0x08
39
40/* ALC880 board config type */
41enum {
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#ifdef CONFIG_SND_DEBUG
64	ALC880_TEST,
65#endif
66	ALC880_AUTO,
67	ALC880_MODEL_LAST /* last tag */
68};
69
70/* ALC260 models */
71enum {
72	ALC260_BASIC,
73	ALC260_HP,
74	ALC260_HP_3013,
75	ALC260_FUJITSU_S702X,
76	ALC260_ACER,
77	ALC260_WILL,
78	ALC260_REPLACER_672V,
79#ifdef CONFIG_SND_DEBUG
80	ALC260_TEST,
81#endif
82	ALC260_AUTO,
83	ALC260_MODEL_LAST /* last tag */
84};
85
86/* ALC262 models */
87enum {
88	ALC262_BASIC,
89	ALC262_HIPPO,
90	ALC262_HIPPO_1,
91	ALC262_FUJITSU,
92	ALC262_HP_BPC,
93	ALC262_HP_BPC_D7000_WL,
94	ALC262_HP_BPC_D7000_WF,
95	ALC262_BENQ_ED8,
96	ALC262_SONY_ASSAMD,
97	ALC262_AUTO,
98	ALC262_MODEL_LAST /* last tag */
99};
100
101/* ALC861 models */
102enum {
103	ALC861_3ST,
104	ALC660_3ST,
105	ALC861_3ST_DIG,
106	ALC861_6ST_DIG,
107	ALC861_UNIWILL_M31,
108	ALC861_TOSHIBA,
109	ALC861_ASUS,
110	ALC861_ASUS_LAPTOP,
111	ALC861_AUTO,
112	ALC861_MODEL_LAST,
113};
114
115/* ALC861-VD models */
116enum {
117	ALC660VD_3ST,
118	ALC861VD_3ST,
119	ALC861VD_3ST_DIG,
120	ALC861VD_6ST_DIG,
121	ALC861VD_LENOVO,
122	ALC861VD_DALLAS,
123	ALC861VD_AUTO,
124	ALC861VD_MODEL_LAST,
125};
126
127/* ALC662 models */
128enum {
129	ALC662_3ST_2ch_DIG,
130	ALC662_3ST_6ch_DIG,
131	ALC662_3ST_6ch,
132	ALC662_5ST_DIG,
133	ALC662_LENOVO_101E,
134	ALC662_AUTO,
135	ALC662_MODEL_LAST,
136};
137
138/* ALC882 models */
139enum {
140	ALC882_3ST_DIG,
141	ALC882_6ST_DIG,
142	ALC882_ARIMA,
143	ALC882_W2JC,
144	ALC882_TARGA,
145	ALC882_ASUS_A7J,
146	ALC885_MACPRO,
147	ALC882_AUTO,
148	ALC882_MODEL_LAST,
149};
150
151/* ALC883 models */
152enum {
153	ALC883_3ST_2ch_DIG,
154	ALC883_3ST_6ch_DIG,
155	ALC883_3ST_6ch,
156	ALC883_6ST_DIG,
157	ALC883_TARGA_DIG,
158	ALC883_TARGA_2ch_DIG,
159	ALC883_ACER,
160	ALC883_MEDION,
161	ALC883_MEDION_MD2,
162	ALC883_LAPTOP_EAPD,
163	ALC883_LENOVO_101E_2ch,
164	ALC883_LENOVO_NB0763,
165	ALC888_LENOVO_MS7195_DIG,
166	ALC883_AUTO,
167	ALC883_MODEL_LAST,
168};
169
170/* for GPIO Poll */
171#define GPIO_MASK	0x03
172
173struct alc_spec {
174	/* codec parameterization */
175	struct snd_kcontrol_new *mixers[5];	/* mixer arrays */
176	unsigned int num_mixers;
177
178	const struct hda_verb *init_verbs[5];	/* initialization verbs
179						 * don't forget NULL
180						 * termination!
181						 */
182	unsigned int num_init_verbs;
183
184	char *stream_name_analog;	/* analog PCM stream */
185	struct hda_pcm_stream *stream_analog_playback;
186	struct hda_pcm_stream *stream_analog_capture;
187
188	char *stream_name_digital;	/* digital PCM stream */
189	struct hda_pcm_stream *stream_digital_playback;
190	struct hda_pcm_stream *stream_digital_capture;
191
192	/* playback */
193	struct hda_multi_out multiout;	/* playback set-up
194					 * max_channels, dacs must be set
195					 * dig_out_nid and hp_nid are optional
196					 */
197
198	/* capture */
199	unsigned int num_adc_nids;
200	hda_nid_t *adc_nids;
201	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
202
203	/* capture source */
204	unsigned int num_mux_defs;
205	const struct hda_input_mux *input_mux;
206	unsigned int cur_mux[3];
207
208	/* channel model */
209	const struct hda_channel_mode *channel_mode;
210	int num_channel_mode;
211	int need_dac_fix;
212
213	/* PCM information */
214	struct hda_pcm pcm_rec[3];	/* used in alc_build_pcms() */
215
216	/* dynamic controls, init_verbs and input_mux */
217	struct auto_pin_cfg autocfg;
218	unsigned int num_kctl_alloc, num_kctl_used;
219	struct snd_kcontrol_new *kctl_alloc;
220	struct hda_input_mux private_imux;
221	hda_nid_t private_dac_nids[5];
222
223	/* hooks */
224	void (*init_hook)(struct hda_codec *codec);
225	void (*unsol_event)(struct hda_codec *codec, unsigned int res);
226
227	/* for pin sensing */
228	unsigned int sense_updated: 1;
229	unsigned int jack_present: 1;
230};
231
232/*
233 * configuration template - to be copied to the spec instance
234 */
235struct alc_config_preset {
236	struct snd_kcontrol_new *mixers[5]; /* should be identical size
237					     * with spec
238					     */
239	const struct hda_verb *init_verbs[5];
240	unsigned int num_dacs;
241	hda_nid_t *dac_nids;
242	hda_nid_t dig_out_nid;		/* optional */
243	hda_nid_t hp_nid;		/* optional */
244	unsigned int num_adc_nids;
245	hda_nid_t *adc_nids;
246	hda_nid_t dig_in_nid;
247	unsigned int num_channel_mode;
248	const struct hda_channel_mode *channel_mode;
249	int need_dac_fix;
250	unsigned int num_mux_defs;
251	const struct hda_input_mux *input_mux;
252	void (*unsol_event)(struct hda_codec *, unsigned int);
253	void (*init_hook)(struct hda_codec *);
254};
255
256
257/*
258 * input MUX handling
259 */
260static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
261			     struct snd_ctl_elem_info *uinfo)
262{
263	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
264	struct alc_spec *spec = codec->spec;
265	unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
266	if (mux_idx >= spec->num_mux_defs)
267		mux_idx = 0;
268	return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
269}
270
271static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
272			    struct snd_ctl_elem_value *ucontrol)
273{
274	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
275	struct alc_spec *spec = codec->spec;
276	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
277
278	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
279	return 0;
280}
281
282static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
283			    struct snd_ctl_elem_value *ucontrol)
284{
285	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
286	struct alc_spec *spec = codec->spec;
287	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
288	unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
289	return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
290				     spec->adc_nids[adc_idx],
291				     &spec->cur_mux[adc_idx]);
292}
293
294
295/*
296 * channel mode setting
297 */
298static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
299			    struct snd_ctl_elem_info *uinfo)
300{
301	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
302	struct alc_spec *spec = codec->spec;
303	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
304				    spec->num_channel_mode);
305}
306
307static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
308			   struct snd_ctl_elem_value *ucontrol)
309{
310	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
311	struct alc_spec *spec = codec->spec;
312	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
313				   spec->num_channel_mode,
314				   spec->multiout.max_channels);
315}
316
317static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
318			   struct snd_ctl_elem_value *ucontrol)
319{
320	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
321	struct alc_spec *spec = codec->spec;
322	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
323				      spec->num_channel_mode,
324				      &spec->multiout.max_channels);
325	if (err >= 0 && spec->need_dac_fix)
326		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
327	return err;
328}
329
330/*
331 * Control the mode of pin widget settings via the mixer.  "pc" is used
332 * instead of "%" to avoid consequences of accidently treating the % as
333 * being part of a format specifier.  Maximum allowed length of a value is
334 * 63 characters plus NULL terminator.
335 *
336 * Note: some retasking pin complexes seem to ignore requests for input
337 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
338 * are requested.  Therefore order this list so that this behaviour will not
339 * cause problems when mixer clients move through the enum sequentially.
340 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
341 * March 2006.
342 */
343static char *alc_pin_mode_names[] = {
344	"Mic 50pc bias", "Mic 80pc bias",
345	"Line in", "Line out", "Headphone out",
346};
347static unsigned char alc_pin_mode_values[] = {
348	PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
349};
350/* The control can present all 5 options, or it can limit the options based
351 * in the pin being assumed to be exclusively an input or an output pin.  In
352 * addition, "input" pins may or may not process the mic bias option
353 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
354 * accept requests for bias as of chip versions up to March 2006) and/or
355 * wiring in the computer.
356 */
357#define ALC_PIN_DIR_IN              0x00
358#define ALC_PIN_DIR_OUT             0x01
359#define ALC_PIN_DIR_INOUT           0x02
360#define ALC_PIN_DIR_IN_NOMICBIAS    0x03
361#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
362
363/* Info about the pin modes supported by the different pin direction modes.
364 * For each direction the minimum and maximum values are given.
365 */
366static signed char alc_pin_mode_dir_info[5][2] = {
367	{ 0, 2 },    /* ALC_PIN_DIR_IN */
368	{ 3, 4 },    /* ALC_PIN_DIR_OUT */
369	{ 0, 4 },    /* ALC_PIN_DIR_INOUT */
370	{ 2, 2 },    /* ALC_PIN_DIR_IN_NOMICBIAS */
371	{ 2, 4 },    /* ALC_PIN_DIR_INOUT_NOMICBIAS */
372};
373#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
374#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
375#define alc_pin_mode_n_items(_dir) \
376	(alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
377
378static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
379			     struct snd_ctl_elem_info *uinfo)
380{
381	unsigned int item_num = uinfo->value.enumerated.item;
382	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
383
384	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
385	uinfo->count = 1;
386	uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
387
388	if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
389		item_num = alc_pin_mode_min(dir);
390	strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
391	return 0;
392}
393
394static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
395			    struct snd_ctl_elem_value *ucontrol)
396{
397	unsigned int i;
398	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
399	hda_nid_t nid = kcontrol->private_value & 0xffff;
400	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
401	long *valp = ucontrol->value.integer.value;
402	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
403						 AC_VERB_GET_PIN_WIDGET_CONTROL,
404						 0x00);
405
406	/* Find enumerated value for current pinctl setting */
407	i = alc_pin_mode_min(dir);
408	while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir))
409		i++;
410	*valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
411	return 0;
412}
413
414static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
415			    struct snd_ctl_elem_value *ucontrol)
416{
417	signed int change;
418	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
419	hda_nid_t nid = kcontrol->private_value & 0xffff;
420	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
421	long val = *ucontrol->value.integer.value;
422	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
423						 AC_VERB_GET_PIN_WIDGET_CONTROL,
424						 0x00);
425
426	if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
427		val = alc_pin_mode_min(dir);
428
429	change = pinctl != alc_pin_mode_values[val];
430	if (change) {
431		/* Set pin mode to that requested */
432		snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
433				    alc_pin_mode_values[val]);
434
435		/* Also enable the retasking pin's input/output as required
436		 * for the requested pin mode.  Enum values of 2 or less are
437		 * input modes.
438		 *
439		 * Dynamically switching the input/output buffers probably
440		 * reduces noise slightly (particularly on input) so we'll
441		 * do it.  However, having both input and output buffers
442		 * enabled simultaneously doesn't seem to be problematic if
443		 * this turns out to be necessary in the future.
444		 */
445		if (val <= 2) {
446			snd_hda_codec_write(codec, nid, 0,
447					    AC_VERB_SET_AMP_GAIN_MUTE,
448					    AMP_OUT_MUTE);
449			snd_hda_codec_write(codec, nid, 0,
450					    AC_VERB_SET_AMP_GAIN_MUTE,
451					    AMP_IN_UNMUTE(0));
452		} else {
453			snd_hda_codec_write(codec, nid, 0,
454					    AC_VERB_SET_AMP_GAIN_MUTE,
455					    AMP_IN_MUTE(0));
456			snd_hda_codec_write(codec, nid, 0,
457					    AC_VERB_SET_AMP_GAIN_MUTE,
458					    AMP_OUT_UNMUTE);
459		}
460	}
461	return change;
462}
463
464#define ALC_PIN_MODE(xname, nid, dir) \
465	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
466	  .info = alc_pin_mode_info, \
467	  .get = alc_pin_mode_get, \
468	  .put = alc_pin_mode_put, \
469	  .private_value = nid | (dir<<16) }
470
471/* A switch control for ALC260 GPIO pins.  Multiple GPIOs can be ganged
472 * together using a mask with more than one bit set.  This control is
473 * currently used only by the ALC260 test model.  At this stage they are not
474 * needed for any "production" models.
475 */
476#ifdef CONFIG_SND_DEBUG
477static int alc_gpio_data_info(struct snd_kcontrol *kcontrol,
478			      struct snd_ctl_elem_info *uinfo)
479{
480	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
481	uinfo->count = 1;
482	uinfo->value.integer.min = 0;
483	uinfo->value.integer.max = 1;
484	return 0;
485}
486
487static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
488			     struct snd_ctl_elem_value *ucontrol)
489{
490	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
491	hda_nid_t nid = kcontrol->private_value & 0xffff;
492	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
493	long *valp = ucontrol->value.integer.value;
494	unsigned int val = snd_hda_codec_read(codec, nid, 0,
495					      AC_VERB_GET_GPIO_DATA, 0x00);
496
497	*valp = (val & mask) != 0;
498	return 0;
499}
500static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
501			     struct snd_ctl_elem_value *ucontrol)
502{
503	signed int change;
504	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
505	hda_nid_t nid = kcontrol->private_value & 0xffff;
506	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
507	long val = *ucontrol->value.integer.value;
508	unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
509						    AC_VERB_GET_GPIO_DATA,
510						    0x00);
511
512	/* Set/unset the masked GPIO bit(s) as needed */
513	change = (val == 0 ? 0 : mask) != (gpio_data & mask);
514	if (val == 0)
515		gpio_data &= ~mask;
516	else
517		gpio_data |= mask;
518	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
519
520	return change;
521}
522#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
523	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
524	  .info = alc_gpio_data_info, \
525	  .get = alc_gpio_data_get, \
526	  .put = alc_gpio_data_put, \
527	  .private_value = nid | (mask<<16) }
528#endif   /* CONFIG_SND_DEBUG */
529
530/* A switch control to allow the enabling of the digital IO pins on the
531 * ALC260.  This is incredibly simplistic; the intention of this control is
532 * to provide something in the test model allowing digital outputs to be
533 * identified if present.  If models are found which can utilise these
534 * outputs a more complete mixer control can be devised for those models if
535 * necessary.
536 */
537#ifdef CONFIG_SND_DEBUG
538static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol,
539			       struct snd_ctl_elem_info *uinfo)
540{
541	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
542	uinfo->count = 1;
543	uinfo->value.integer.min = 0;
544	uinfo->value.integer.max = 1;
545	return 0;
546}
547
548static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
549			      struct snd_ctl_elem_value *ucontrol)
550{
551	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
552	hda_nid_t nid = kcontrol->private_value & 0xffff;
553	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
554	long *valp = ucontrol->value.integer.value;
555	unsigned int val = snd_hda_codec_read(codec, nid, 0,
556					      AC_VERB_GET_DIGI_CONVERT, 0x00);
557
558	*valp = (val & mask) != 0;
559	return 0;
560}
561static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
562			      struct snd_ctl_elem_value *ucontrol)
563{
564	signed int change;
565	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
566	hda_nid_t nid = kcontrol->private_value & 0xffff;
567	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
568	long val = *ucontrol->value.integer.value;
569	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
570						    AC_VERB_GET_DIGI_CONVERT,
571						    0x00);
572
573	/* Set/unset the masked control bit(s) as needed */
574	change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
575	if (val==0)
576		ctrl_data &= ~mask;
577	else
578		ctrl_data |= mask;
579	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
580			    ctrl_data);
581
582	return change;
583}
584#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
585	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
586	  .info = alc_spdif_ctrl_info, \
587	  .get = alc_spdif_ctrl_get, \
588	  .put = alc_spdif_ctrl_put, \
589	  .private_value = nid | (mask<<16) }
590#endif   /* CONFIG_SND_DEBUG */
591
592/*
593 * set up from the preset table
594 */
595static void setup_preset(struct alc_spec *spec,
596			 const struct alc_config_preset *preset)
597{
598	int i;
599
600	for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
601		spec->mixers[spec->num_mixers++] = preset->mixers[i];
602	for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
603	     i++)
604		spec->init_verbs[spec->num_init_verbs++] =
605			preset->init_verbs[i];
606
607	spec->channel_mode = preset->channel_mode;
608	spec->num_channel_mode = preset->num_channel_mode;
609	spec->need_dac_fix = preset->need_dac_fix;
610
611	spec->multiout.max_channels = spec->channel_mode[0].channels;
612
613	spec->multiout.num_dacs = preset->num_dacs;
614	spec->multiout.dac_nids = preset->dac_nids;
615	spec->multiout.dig_out_nid = preset->dig_out_nid;
616	spec->multiout.hp_nid = preset->hp_nid;
617
618	spec->num_mux_defs = preset->num_mux_defs;
619	if (!spec->num_mux_defs)
620		spec->num_mux_defs = 1;
621	spec->input_mux = preset->input_mux;
622
623	spec->num_adc_nids = preset->num_adc_nids;
624	spec->adc_nids = preset->adc_nids;
625	spec->dig_in_nid = preset->dig_in_nid;
626
627	spec->unsol_event = preset->unsol_event;
628	spec->init_hook = preset->init_hook;
629}
630
631/* Enable GPIO mask and set output */
632static struct hda_verb alc_gpio1_init_verbs[] = {
633	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
634	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
635	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
636	{ }
637};
638
639static struct hda_verb alc_gpio2_init_verbs[] = {
640	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
641	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
642	{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
643	{ }
644};
645
646static struct hda_verb alc_gpio3_init_verbs[] = {
647	{0x01, AC_VERB_SET_GPIO_MASK, 0x03},
648	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
649	{0x01, AC_VERB_SET_GPIO_DATA, 0x03},
650	{ }
651};
652
653/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
654 *	31 ~ 16 :	Manufacture ID
655 *	15 ~ 8	:	SKU ID
656 *	7  ~ 0	:	Assembly ID
657 *	port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
658 */
659static void alc_subsystem_id(struct hda_codec *codec,
660			     unsigned int porta, unsigned int porte,
661			     unsigned int portd)
662{
663	unsigned int ass, tmp;
664
665	ass = codec->subsystem_id;
666	if (!(ass & 1))
667		return;
668
669	/* Override */
670	tmp = (ass & 0x38) >> 3;	/* external Amp control */
671	switch (tmp) {
672	case 1:
673		snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
674		break;
675	case 3:
676		snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
677		break;
678	case 7:
679		snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
680		break;
681	case 5:
682		switch (codec->vendor_id) {
683		case 0x10ec0862:
684		case 0x10ec0660:
685		case 0x10ec0662:
686		case 0x10ec0267:
687		case 0x10ec0268:
688			snd_hda_codec_write(codec, 0x14, 0,
689					    AC_VERB_SET_EAPD_BTLENABLE, 2);
690			snd_hda_codec_write(codec, 0x15, 0,
691					    AC_VERB_SET_EAPD_BTLENABLE, 2);
692			return;
693		}
694	case 6:
695		if (ass & 4) {	/* bit 2 : 0 = Desktop, 1 = Laptop */
696			hda_nid_t port = 0;
697			tmp = (ass & 0x1800) >> 11;
698			switch (tmp) {
699			case 0: port = porta; break;
700			case 1: port = porte; break;
701			case 2: port = portd; break;
702			}
703			if (port)
704				snd_hda_codec_write(codec, port, 0,
705						    AC_VERB_SET_EAPD_BTLENABLE,
706						    2);
707		}
708		snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
709		snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF,
710				    (tmp == 5 ? 0x3040 : 0x3050));
711		break;
712	}
713}
714
715/*
716 * ALC880 3-stack model
717 *
718 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
719 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
720 *                 F-Mic = 0x1b, HP = 0x19
721 */
722
723static hda_nid_t alc880_dac_nids[4] = {
724	/* front, rear, clfe, rear_surr */
725	0x02, 0x05, 0x04, 0x03
726};
727
728static hda_nid_t alc880_adc_nids[3] = {
729	/* ADC0-2 */
730	0x07, 0x08, 0x09,
731};
732
733/* The datasheet says the node 0x07 is connected from inputs,
734 * but it shows zero connection in the real implementation on some devices.
735 * Note: this is a 915GAV bug, fixed on 915GLV
736 */
737static hda_nid_t alc880_adc_nids_alt[2] = {
738	/* ADC1-2 */
739	0x08, 0x09,
740};
741
742#define ALC880_DIGOUT_NID	0x06
743#define ALC880_DIGIN_NID	0x0a
744
745static struct hda_input_mux alc880_capture_source = {
746	.num_items = 4,
747	.items = {
748		{ "Mic", 0x0 },
749		{ "Front Mic", 0x3 },
750		{ "Line", 0x2 },
751		{ "CD", 0x4 },
752	},
753};
754
755/* channel source setting (2/6 channel selection for 3-stack) */
756/* 2ch mode */
757static struct hda_verb alc880_threestack_ch2_init[] = {
758	/* set line-in to input, mute it */
759	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
760	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
761	/* set mic-in to input vref 80%, mute it */
762	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
763	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
764	{ } /* end */
765};
766
767/* 6ch mode */
768static struct hda_verb alc880_threestack_ch6_init[] = {
769	/* set line-in to output, unmute it */
770	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
771	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
772	/* set mic-in to output, unmute it */
773	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
774	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
775	{ } /* end */
776};
777
778static struct hda_channel_mode alc880_threestack_modes[2] = {
779	{ 2, alc880_threestack_ch2_init },
780	{ 6, alc880_threestack_ch6_init },
781};
782
783static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
784	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
785	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
786	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
787	HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
788	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
789	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
790	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
791	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
792	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
793	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
794	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
795	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
796	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
797	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
798	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
799	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
800	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
801	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
802	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
803	{
804		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
805		.name = "Channel Mode",
806		.info = alc_ch_mode_info,
807		.get = alc_ch_mode_get,
808		.put = alc_ch_mode_put,
809	},
810	{ } /* end */
811};
812
813/* capture mixer elements */
814static struct snd_kcontrol_new alc880_capture_mixer[] = {
815	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
816	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
817	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
818	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
819	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
820	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
821	{
822		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
823		/* The multiple "Capture Source" controls confuse alsamixer
824		 * So call somewhat different..
825		 * FIXME: the controls appear in the "playback" view!
826		 */
827		/* .name = "Capture Source", */
828		.name = "Input Source",
829		.count = 3,
830		.info = alc_mux_enum_info,
831		.get = alc_mux_enum_get,
832		.put = alc_mux_enum_put,
833	},
834	{ } /* end */
835};
836
837/* capture mixer elements (in case NID 0x07 not available) */
838static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {
839	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
840	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
841	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
842	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
843	{
844		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
845		/* The multiple "Capture Source" controls confuse alsamixer
846		 * So call somewhat different..
847		 * FIXME: the controls appear in the "playback" view!
848		 */
849		/* .name = "Capture Source", */
850		.name = "Input Source",
851		.count = 2,
852		.info = alc_mux_enum_info,
853		.get = alc_mux_enum_get,
854		.put = alc_mux_enum_put,
855	},
856	{ } /* end */
857};
858
859
860
861/*
862 * ALC880 5-stack model
863 *
864 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
865 *      Side = 0x02 (0xd)
866 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
867 *                 Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
868 */
869
870/* additional mixers to alc880_three_stack_mixer */
871static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
872	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
873	HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
874	{ } /* end */
875};
876
877/* channel source setting (6/8 channel selection for 5-stack) */
878/* 6ch mode */
879static struct hda_verb alc880_fivestack_ch6_init[] = {
880	/* set line-in to input, mute it */
881	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
882	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
883	{ } /* end */
884};
885
886/* 8ch mode */
887static struct hda_verb alc880_fivestack_ch8_init[] = {
888	/* set line-in to output, unmute it */
889	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
890	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
891	{ } /* end */
892};
893
894static struct hda_channel_mode alc880_fivestack_modes[2] = {
895	{ 6, alc880_fivestack_ch6_init },
896	{ 8, alc880_fivestack_ch8_init },
897};
898
899
900/*
901 * ALC880 6-stack model
902 *
903 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
904 *      Side = 0x05 (0x0f)
905 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
906 *   Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
907 */
908
909static hda_nid_t alc880_6st_dac_nids[4] = {
910	/* front, rear, clfe, rear_surr */
911	0x02, 0x03, 0x04, 0x05
912};
913
914static struct hda_input_mux alc880_6stack_capture_source = {
915	.num_items = 4,
916	.items = {
917		{ "Mic", 0x0 },
918		{ "Front Mic", 0x1 },
919		{ "Line", 0x2 },
920		{ "CD", 0x4 },
921	},
922};
923
924/* fixed 8-channels */
925static struct hda_channel_mode alc880_sixstack_modes[1] = {
926	{ 8, NULL },
927};
928
929static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
930	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
931	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
932	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
933	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
934	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
935	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
936	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
937	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
938	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
939	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
940	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
941	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
942	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
943	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
944	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
945	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
946	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
947	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
948	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
949	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
950	{
951		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
952		.name = "Channel Mode",
953		.info = alc_ch_mode_info,
954		.get = alc_ch_mode_get,
955		.put = alc_ch_mode_put,
956	},
957	{ } /* end */
958};
959
960
961/*
962 * ALC880 W810 model
963 *
964 * W810 has rear IO for:
965 * Front (DAC 02)
966 * Surround (DAC 03)
967 * Center/LFE (DAC 04)
968 * Digital out (06)
969 *
970 * The system also has a pair of internal speakers, and a headphone jack.
971 * These are both connected to Line2 on the codec, hence to DAC 02.
972 *
973 * There is a variable resistor to control the speaker or headphone
974 * volume. This is a hardware-only device without a software API.
975 *
976 * Plugging headphones in will disable the internal speakers. This is
977 * implemented in hardware, not via the driver using jack sense. In
978 * a similar fashion, plugging into the rear socket marked "front" will
979 * disable both the speakers and headphones.
980 *
981 * For input, there's a microphone jack, and an "audio in" jack.
982 * These may not do anything useful with this driver yet, because I
983 * haven't setup any initialization verbs for these yet...
984 */
985
986static hda_nid_t alc880_w810_dac_nids[3] = {
987	/* front, rear/surround, clfe */
988	0x02, 0x03, 0x04
989};
990
991/* fixed 6 channels */
992static struct hda_channel_mode alc880_w810_modes[1] = {
993	{ 6, NULL }
994};
995
996/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
997static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
998	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
999	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1000	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1001	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1002	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1003	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1004	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1005	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1006	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1007	{ } /* end */
1008};
1009
1010
1011/*
1012 * Z710V model
1013 *
1014 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
1015 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
1016 *                 Line = 0x1a
1017 */
1018
1019static hda_nid_t alc880_z71v_dac_nids[1] = {
1020	0x02
1021};
1022#define ALC880_Z71V_HP_DAC	0x03
1023
1024/* fixed 2 channels */
1025static struct hda_channel_mode alc880_2_jack_modes[1] = {
1026	{ 2, NULL }
1027};
1028
1029static struct snd_kcontrol_new alc880_z71v_mixer[] = {
1030	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1031	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1032	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1033	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
1034	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1035	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1036	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1037	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1038	{ } /* end */
1039};
1040
1041
1042/* FIXME! */
1043/*
1044 * ALC880 F1734 model
1045 *
1046 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
1047 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
1048 */
1049
1050static hda_nid_t alc880_f1734_dac_nids[1] = {
1051	0x03
1052};
1053#define ALC880_F1734_HP_DAC	0x02
1054
1055static struct snd_kcontrol_new alc880_f1734_mixer[] = {
1056	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1057	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
1058	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1059	HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
1060	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1061	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1062	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1063	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1064	{ } /* end */
1065};
1066
1067
1068/* FIXME! */
1069/*
1070 * ALC880 ASUS model
1071 *
1072 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
1073 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
1074 *  Mic = 0x18, Line = 0x1a
1075 */
1076
1077#define alc880_asus_dac_nids	alc880_w810_dac_nids	/* identical with w810 */
1078#define alc880_asus_modes	alc880_threestack_modes	/* 2/6 channel mode */
1079
1080static struct snd_kcontrol_new alc880_asus_mixer[] = {
1081	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1082	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1083	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1084	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1085	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1086	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1087	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1088	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1089	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1090	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1091	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1092	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1093	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1094	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1095	{
1096		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1097		.name = "Channel Mode",
1098		.info = alc_ch_mode_info,
1099		.get = alc_ch_mode_get,
1100		.put = alc_ch_mode_put,
1101	},
1102	{ } /* end */
1103};
1104
1105/* FIXME! */
1106/*
1107 * ALC880 ASUS W1V model
1108 *
1109 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
1110 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
1111 *  Mic = 0x18, Line = 0x1a, Line2 = 0x1b
1112 */
1113
1114/* additional mixers to alc880_asus_mixer */
1115static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
1116	HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
1117	HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
1118	{ } /* end */
1119};
1120
1121/* additional mixers to alc880_asus_mixer */
1122static struct snd_kcontrol_new alc880_pcbeep_mixer[] = {
1123	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1124	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1125	{ } /* end */
1126};
1127
1128/* TCL S700 */
1129static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
1130	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1131	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1132	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
1133	HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
1134	HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
1135	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
1136	HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
1137	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
1138	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
1139	{
1140		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1141		/* The multiple "Capture Source" controls confuse alsamixer
1142		 * So call somewhat different..
1143		 * FIXME: the controls appear in the "playback" view!
1144		 */
1145		/* .name = "Capture Source", */
1146		.name = "Input Source",
1147		.count = 1,
1148		.info = alc_mux_enum_info,
1149		.get = alc_mux_enum_get,
1150		.put = alc_mux_enum_put,
1151	},
1152	{ } /* end */
1153};
1154
1155/* Uniwill */
1156static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
1157	HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1158	HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT),
1159	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1160	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
1161	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1162	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1163	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1164	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1165	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1166	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1167	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1168	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1169	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1170	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1171	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1172	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1173	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1174	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1175	{
1176		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1177		.name = "Channel Mode",
1178		.info = alc_ch_mode_info,
1179		.get = alc_ch_mode_get,
1180		.put = alc_ch_mode_put,
1181	},
1182	{ } /* end */
1183};
1184
1185static struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
1186	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1187	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
1188	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1189	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
1190	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1191	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1192	HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1193	HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1194	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1195	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1196	{ } /* end */
1197};
1198
1199static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
1200	HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1201	HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT),
1202	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1203	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
1204	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1205	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1206	{ } /* end */
1207};
1208
1209/*
1210 * build control elements
1211 */
1212static int alc_build_controls(struct hda_codec *codec)
1213{
1214	struct alc_spec *spec = codec->spec;
1215	int err;
1216	int i;
1217
1218	for (i = 0; i < spec->num_mixers; i++) {
1219		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1220		if (err < 0)
1221			return err;
1222	}
1223
1224	if (spec->multiout.dig_out_nid) {
1225		err = snd_hda_create_spdif_out_ctls(codec,
1226						    spec->multiout.dig_out_nid);
1227		if (err < 0)
1228			return err;
1229	}
1230	if (spec->dig_in_nid) {
1231		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1232		if (err < 0)
1233			return err;
1234	}
1235	return 0;
1236}
1237
1238
1239/*
1240 * initialize the codec volumes, etc
1241 */
1242
1243/*
1244 * generic initialization of ADC, input mixers and output mixers
1245 */
1246static struct hda_verb alc880_volume_init_verbs[] = {
1247	/*
1248	 * Unmute ADC0-2 and set the default input to mic-in
1249	 */
1250	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
1251	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1252	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
1253	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1254	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
1255	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1256
1257	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1258	 * mixer widget
1259	 * Note: PASD motherboards uses the Line In 2 as the input for front
1260	 * panel mic (mic 2)
1261	 */
1262	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
1263	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1264	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1265	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1266	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1267	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1268
1269	/*
1270	 * Set up output mixers (0x0c - 0x0f)
1271	 */
1272	/* set vol=0 to output mixers */
1273	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1274	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1275	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1276	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1277	/* set up input amps for analog loopback */
1278	/* Amp Indices: DAC = 0, mixer = 1 */
1279	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1280	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1281	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1282	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1283	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1284	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1285	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1286	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1287
1288	{ }
1289};
1290
1291/*
1292 * 3-stack pin configuration:
1293 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
1294 */
1295static struct hda_verb alc880_pin_3stack_init_verbs[] = {
1296	/*
1297	 * preset connection lists of input pins
1298	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
1299	 */
1300	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
1301	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1302	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
1303
1304	/*
1305	 * Set pin mode and muting
1306	 */
1307	/* set front pin widgets 0x14 for output */
1308	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1309	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1310	/* Mic1 (rear panel) pin widget for input and vref at 80% */
1311	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1312	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1313	/* Mic2 (as headphone out) for HP output */
1314	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1315	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1316	/* Line In pin widget for input */
1317	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1318	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1319	/* Line2 (as front mic) pin widget for input and vref at 80% */
1320	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1321	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1322	/* CD pin widget for input */
1323	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1324
1325	{ }
1326};
1327
1328/*
1329 * 5-stack pin configuration:
1330 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
1331 * line-in/side = 0x1a, f-mic = 0x1b
1332 */
1333static struct hda_verb alc880_pin_5stack_init_verbs[] = {
1334	/*
1335	 * preset connection lists of input pins
1336	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
1337	 */
1338	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1339	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
1340
1341	/*
1342	 * Set pin mode and muting
1343	 */
1344	/* set pin widgets 0x14-0x17 for output */
1345	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1346	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1347	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1348	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1349	/* unmute pins for output (no gain on this amp) */
1350	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1351	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1352	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1353	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1354
1355	/* Mic1 (rear panel) pin widget for input and vref at 80% */
1356	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1357	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1358	/* Mic2 (as headphone out) for HP output */
1359	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1360	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1361	/* Line In pin widget for input */
1362	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1363	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1364	/* Line2 (as front mic) pin widget for input and vref at 80% */
1365	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1366	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1367	/* CD pin widget for input */
1368	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1369
1370	{ }
1371};
1372
1373/*
1374 * W810 pin configuration:
1375 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
1376 */
1377static struct hda_verb alc880_pin_w810_init_verbs[] = {
1378	/* hphone/speaker input selector: front DAC */
1379	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
1380
1381	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1382	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1383	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1384	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1385	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1386	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1387
1388	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1389	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1390
1391	{ }
1392};
1393
1394/*
1395 * Z71V pin configuration:
1396 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
1397 */
1398static struct hda_verb alc880_pin_z71v_init_verbs[] = {
1399	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1400	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1401	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1402	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1403
1404	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1405	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1406	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1407	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1408
1409	{ }
1410};
1411
1412/*
1413 * 6-stack pin configuration:
1414 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
1415 * f-mic = 0x19, line = 0x1a, HP = 0x1b
1416 */
1417static struct hda_verb alc880_pin_6stack_init_verbs[] = {
1418	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1419
1420	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1421	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1422	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1423	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1424	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1425	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1426	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1427	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1428
1429	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1430	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1431	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1432	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1433	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1434	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1435	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1436	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1437	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1438
1439	{ }
1440};
1441
1442/*
1443 * Uniwill pin configuration:
1444 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
1445 * line = 0x1a
1446 */
1447static struct hda_verb alc880_uniwill_init_verbs[] = {
1448	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1449
1450	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1451	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1452	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1453	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1454	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1455	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1456	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1457	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1458	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1459	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1460	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1461	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1462	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1463	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1464
1465	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1466	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1467	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1468	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1469	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1470	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1471	/* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
1472	/* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
1473	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1474
1475	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
1476	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
1477
1478	{ }
1479};
1480
1481/*
1482* Uniwill P53
1483* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
1484 */
1485static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
1486	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1487
1488	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1489	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1490	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1491	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1492	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1493	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1494	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1495	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1496	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1497	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1498	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1499	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1500
1501	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1502	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1503	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1504	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1505	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1506	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1507
1508	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
1509	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
1510
1511	{ }
1512};
1513
1514static struct hda_verb alc880_beep_init_verbs[] = {
1515	{ 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
1516	{ }
1517};
1518
1519/* toggle speaker-output according to the hp-jack state */
1520static void alc880_uniwill_hp_automute(struct hda_codec *codec)
1521{
1522 	unsigned int present;
1523	unsigned char bits;
1524
1525 	present = snd_hda_codec_read(codec, 0x14, 0,
1526				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1527	bits = present ? 0x80 : 0;
1528	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
1529				 0x80, bits);
1530	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
1531				 0x80, bits);
1532	snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0,
1533				 0x80, bits);
1534	snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0,
1535				 0x80, bits);
1536}
1537
1538/* auto-toggle front mic */
1539static void alc880_uniwill_mic_automute(struct hda_codec *codec)
1540{
1541 	unsigned int present;
1542	unsigned char bits;
1543
1544	present = snd_hda_codec_read(codec, 0x18, 0,
1545				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1546	bits = present ? 0x80 : 0;
1547	snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1,
1548				 0x80, bits);
1549	snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1,
1550				 0x80, bits);
1551}
1552
1553static void alc880_uniwill_automute(struct hda_codec *codec)
1554{
1555	alc880_uniwill_hp_automute(codec);
1556	alc880_uniwill_mic_automute(codec);
1557}
1558
1559static void alc880_uniwill_unsol_event(struct hda_codec *codec,
1560				       unsigned int res)
1561{
1562	/* Looks like the unsol event is incompatible with the standard
1563	 * definition.  4bit tag is placed at 28 bit!
1564	 */
1565	switch (res >> 28) {
1566	case ALC880_HP_EVENT:
1567		alc880_uniwill_hp_automute(codec);
1568		break;
1569	case ALC880_MIC_EVENT:
1570		alc880_uniwill_mic_automute(codec);
1571		break;
1572	}
1573}
1574
1575static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
1576{
1577 	unsigned int present;
1578	unsigned char bits;
1579
1580 	present = snd_hda_codec_read(codec, 0x14, 0,
1581				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1582	bits = present ? 0x80 : 0;
1583	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0,
1584				 0x80, bits);
1585	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0,
1586				 0x80, bits);
1587}
1588
1589static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
1590{
1591	unsigned int present;
1592
1593	present = snd_hda_codec_read(codec, 0x21, 0,
1594				     AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f;
1595
1596	snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
1597				 0x7f, present);
1598	snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
1599				 0x7f,  present);
1600
1601	snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
1602				 0x7f,  present);
1603	snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
1604				 0x7f, present);
1605
1606}
1607static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
1608					   unsigned int res)
1609{
1610	/* Looks like the unsol event is incompatible with the standard
1611	 * definition.  4bit tag is placed at 28 bit!
1612	 */
1613	if ((res >> 28) == ALC880_HP_EVENT)
1614		alc880_uniwill_p53_hp_automute(codec);
1615	if ((res >> 28) == ALC880_DCVOL_EVENT)
1616		alc880_uniwill_p53_dcvol_automute(codec);
1617}
1618
1619/* FIXME! */
1620/*
1621 * F1734 pin configuration:
1622 * HP = 0x14, speaker-out = 0x15, mic = 0x18
1623 */
1624static struct hda_verb alc880_pin_f1734_init_verbs[] = {
1625	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
1626	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
1627	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
1628	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1629
1630	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1631	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1632	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1633	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1634
1635	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1636	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1637	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1638	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1639	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1640	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1641	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1642	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1643	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1644
1645	{ }
1646};
1647
1648/* FIXME! */
1649/*
1650 * ASUS pin configuration:
1651 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
1652 */
1653static struct hda_verb alc880_pin_asus_init_verbs[] = {
1654	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
1655	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
1656	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
1657	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1658
1659	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1660	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1661	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1662	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1663	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1664	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1665	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1666	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1667
1668	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1669	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1670	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1671	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1672	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1673	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1674	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1675	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1676	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1677
1678	{ }
1679};
1680
1681/* Enable GPIO mask and set output */
1682#define alc880_gpio1_init_verbs	alc_gpio1_init_verbs
1683#define alc880_gpio2_init_verbs	alc_gpio2_init_verbs
1684
1685/* Clevo m520g init */
1686static struct hda_verb alc880_pin_clevo_init_verbs[] = {
1687	/* headphone output */
1688	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
1689	/* line-out */
1690	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1691	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1692	/* Line-in */
1693	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1694	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1695	/* CD */
1696	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1697	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1698	/* Mic1 (rear panel) */
1699	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1700	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1701	/* Mic2 (front panel) */
1702	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1703	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1704	/* headphone */
1705	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1706	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1707        /* change to EAPD mode */
1708	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1709	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
1710
1711	{ }
1712};
1713
1714static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
1715	/* change to EAPD mode */
1716	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1717	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
1718
1719	/* Headphone output */
1720	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1721	/* Front output*/
1722	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1723	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1724
1725	/* Line In pin widget for input */
1726	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1727	/* CD pin widget for input */
1728	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1729	/* Mic1 (rear panel) pin widget for input and vref at 80% */
1730	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1731
1732	/* change to EAPD mode */
1733	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1734	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
1735
1736	{ }
1737};
1738
1739/*
1740 * LG m1 express dual
1741 *
1742 * Pin assignment:
1743 *   Rear Line-In/Out (blue): 0x14
1744 *   Build-in Mic-In: 0x15
1745 *   Speaker-out: 0x17
1746 *   HP-Out (green): 0x1b
1747 *   Mic-In/Out (red): 0x19
1748 *   SPDIF-Out: 0x1e
1749 */
1750
1751/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
1752static hda_nid_t alc880_lg_dac_nids[3] = {
1753	0x05, 0x02, 0x03
1754};
1755
1756/* seems analog CD is not working */
1757static struct hda_input_mux alc880_lg_capture_source = {
1758	.num_items = 3,
1759	.items = {
1760		{ "Mic", 0x1 },
1761		{ "Line", 0x5 },
1762		{ "Internal Mic", 0x6 },
1763	},
1764};
1765
1766/* 2,4,6 channel modes */
1767static struct hda_verb alc880_lg_ch2_init[] = {
1768	/* set line-in and mic-in to input */
1769	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1770	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1771	{ }
1772};
1773
1774static struct hda_verb alc880_lg_ch4_init[] = {
1775	/* set line-in to out and mic-in to input */
1776	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
1777	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1778	{ }
1779};
1780
1781static struct hda_verb alc880_lg_ch6_init[] = {
1782	/* set line-in and mic-in to output */
1783	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
1784	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
1785	{ }
1786};
1787
1788static struct hda_channel_mode alc880_lg_ch_modes[3] = {
1789	{ 2, alc880_lg_ch2_init },
1790	{ 4, alc880_lg_ch4_init },
1791	{ 6, alc880_lg_ch6_init },
1792};
1793
1794static struct snd_kcontrol_new alc880_lg_mixer[] = {
1795	/* FIXME: it's not really "master" but front channels */
1796	HDA_CODEC_VOLUME("Master Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1797	HDA_BIND_MUTE("Master Playback Switch", 0x0f, 2, HDA_INPUT),
1798	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1799	HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
1800	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
1801	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
1802	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
1803	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
1804	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1805	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1806	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
1807	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
1808	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
1809	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
1810	{
1811		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1812		.name = "Channel Mode",
1813		.info = alc_ch_mode_info,
1814		.get = alc_ch_mode_get,
1815		.put = alc_ch_mode_put,
1816	},
1817	{ } /* end */
1818};
1819
1820static struct hda_verb alc880_lg_init_verbs[] = {
1821	/* set capture source to mic-in */
1822	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1823	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1824	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1825	/* mute all amp mixer inputs */
1826	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
1827	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
1828	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
1829	/* line-in to input */
1830	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1831	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1832	/* built-in mic */
1833	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1834	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1835	/* speaker-out */
1836	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1837	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1838	/* mic-in to input */
1839	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
1840	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1841	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1842	/* HP-out */
1843	{0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
1844	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1845	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1846	/* jack sense */
1847	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
1848	{ }
1849};
1850
1851/* toggle speaker-output according to the hp-jack state */
1852static void alc880_lg_automute(struct hda_codec *codec)
1853{
1854	unsigned int present;
1855	unsigned char bits;
1856
1857	present = snd_hda_codec_read(codec, 0x1b, 0,
1858				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1859	bits = present ? 0x80 : 0;
1860	snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0,
1861				 0x80, bits);
1862	snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0,
1863				 0x80, bits);
1864}
1865
1866static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res)
1867{
1868	/* Looks like the unsol event is incompatible with the standard
1869	 * definition.  4bit tag is placed at 28 bit!
1870	 */
1871	if ((res >> 28) == 0x01)
1872		alc880_lg_automute(codec);
1873}
1874
1875/*
1876 * LG LW20
1877 *
1878 * Pin assignment:
1879 *   Speaker-out: 0x14
1880 *   Mic-In: 0x18
1881 *   Built-in Mic-In: 0x19 (?)
1882 *   HP-Out: 0x1b
1883 *   SPDIF-Out: 0x1e
1884 */
1885
1886/* seems analog CD is not working */
1887static struct hda_input_mux alc880_lg_lw_capture_source = {
1888	.num_items = 2,
1889	.items = {
1890		{ "Mic", 0x0 },
1891		{ "Internal Mic", 0x1 },
1892	},
1893};
1894
1895static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
1896	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1897	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
1898	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1899	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1900	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
1901	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
1902	{ } /* end */
1903};
1904
1905static struct hda_verb alc880_lg_lw_init_verbs[] = {
1906	/* set capture source to mic-in */
1907	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1908	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1909	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1910	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
1911	/* speaker-out */
1912	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1913	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1914	/* HP-out */
1915	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1916	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1917	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1918	/* mic-in to input */
1919	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1920	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1921	/* built-in mic */
1922	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1923	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1924	/* jack sense */
1925	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
1926	{ }
1927};
1928
1929/* toggle speaker-output according to the hp-jack state */
1930static void alc880_lg_lw_automute(struct hda_codec *codec)
1931{
1932	unsigned int present;
1933	unsigned char bits;
1934
1935	present = snd_hda_codec_read(codec, 0x1b, 0,
1936				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1937	bits = present ? 0x80 : 0;
1938	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
1939				 0x80, bits);
1940	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
1941				 0x80, bits);
1942}
1943
1944static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
1945{
1946	/* Looks like the unsol event is incompatible with the standard
1947	 * definition.  4bit tag is placed at 28 bit!
1948	 */
1949	if ((res >> 28) == 0x01)
1950		alc880_lg_lw_automute(codec);
1951}
1952
1953/*
1954 * Common callbacks
1955 */
1956
1957static int alc_init(struct hda_codec *codec)
1958{
1959	struct alc_spec *spec = codec->spec;
1960	unsigned int i;
1961
1962	for (i = 0; i < spec->num_init_verbs; i++)
1963		snd_hda_sequence_write(codec, spec->init_verbs[i]);
1964
1965	if (spec->init_hook)
1966		spec->init_hook(codec);
1967
1968	return 0;
1969}
1970
1971static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
1972{
1973	struct alc_spec *spec = codec->spec;
1974
1975	if (spec->unsol_event)
1976		spec->unsol_event(codec, res);
1977}
1978
1979#ifdef CONFIG_PM
1980/*
1981 * resume
1982 */
1983static int alc_resume(struct hda_codec *codec)
1984{
1985	struct alc_spec *spec = codec->spec;
1986	int i;
1987
1988	alc_init(codec);
1989	for (i = 0; i < spec->num_mixers; i++)
1990		snd_hda_resume_ctls(codec, spec->mixers[i]);
1991	if (spec->multiout.dig_out_nid)
1992		snd_hda_resume_spdif_out(codec);
1993	if (spec->dig_in_nid)
1994		snd_hda_resume_spdif_in(codec);
1995
1996	return 0;
1997}
1998#endif
1999
2000/*
2001 * Analog playback callbacks
2002 */
2003static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
2004				    struct hda_codec *codec,
2005				    struct snd_pcm_substream *substream)
2006{
2007	struct alc_spec *spec = codec->spec;
2008	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
2009}
2010
2011static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
2012				       struct hda_codec *codec,
2013				       unsigned int stream_tag,
2014				       unsigned int format,
2015				       struct snd_pcm_substream *substream)
2016{
2017	struct alc_spec *spec = codec->spec;
2018	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2019						stream_tag, format, substream);
2020}
2021
2022static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
2023				       struct hda_codec *codec,
2024				       struct snd_pcm_substream *substream)
2025{
2026	struct alc_spec *spec = codec->spec;
2027	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2028}
2029
2030/*
2031 * Digital out
2032 */
2033static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
2034					struct hda_codec *codec,
2035					struct snd_pcm_substream *substream)
2036{
2037	struct alc_spec *spec = codec->spec;
2038	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2039}
2040
2041static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
2042					   struct hda_codec *codec,
2043					   unsigned int stream_tag,
2044					   unsigned int format,
2045					   struct snd_pcm_substream *substream)
2046{
2047	struct alc_spec *spec = codec->spec;
2048	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2049					     stream_tag, format, substream);
2050}
2051
2052static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
2053					 struct hda_codec *codec,
2054					 struct snd_pcm_substream *substream)
2055{
2056	struct alc_spec *spec = codec->spec;
2057	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2058}
2059
2060/*
2061 * Analog capture
2062 */
2063static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
2064				      struct hda_codec *codec,
2065				      unsigned int stream_tag,
2066				      unsigned int format,
2067				      struct snd_pcm_substream *substream)
2068{
2069	struct alc_spec *spec = codec->spec;
2070
2071	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
2072				   stream_tag, 0, format);
2073	return 0;
2074}
2075
2076static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
2077				      struct hda_codec *codec,
2078				      struct snd_pcm_substream *substream)
2079{
2080	struct alc_spec *spec = codec->spec;
2081
2082	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
2083				   0, 0, 0);
2084	return 0;
2085}
2086
2087
2088/*
2089 */
2090static struct hda_pcm_stream alc880_pcm_analog_playback = {
2091	.substreams = 1,
2092	.channels_min = 2,
2093	.channels_max = 8,
2094	/* NID is set in alc_build_pcms */
2095	.ops = {
2096		.open = alc880_playback_pcm_open,
2097		.prepare = alc880_playback_pcm_prepare,
2098		.cleanup = alc880_playback_pcm_cleanup
2099	},
2100};
2101
2102static struct hda_pcm_stream alc880_pcm_analog_capture = {
2103	.substreams = 2,
2104	.channels_min = 2,
2105	.channels_max = 2,
2106	/* NID is set in alc_build_pcms */
2107	.ops = {
2108		.prepare = alc880_capture_pcm_prepare,
2109		.cleanup = alc880_capture_pcm_cleanup
2110	},
2111};
2112
2113static struct hda_pcm_stream alc880_pcm_digital_playback = {
2114	.substreams = 1,
2115	.channels_min = 2,
2116	.channels_max = 2,
2117	/* NID is set in alc_build_pcms */
2118	.ops = {
2119		.open = alc880_dig_playback_pcm_open,
2120		.close = alc880_dig_playback_pcm_close,
2121		.prepare = alc880_dig_playback_pcm_prepare
2122	},
2123};
2124
2125static struct hda_pcm_stream alc880_pcm_digital_capture = {
2126	.substreams = 1,
2127	.channels_min = 2,
2128	.channels_max = 2,
2129	/* NID is set in alc_build_pcms */
2130};
2131
2132/* Used by alc_build_pcms to flag that a PCM has no playback stream */
2133static struct hda_pcm_stream alc_pcm_null_playback = {
2134	.substreams = 0,
2135	.channels_min = 0,
2136	.channels_max = 0,
2137};
2138
2139static int alc_build_pcms(struct hda_codec *codec)
2140{
2141	struct alc_spec *spec = codec->spec;
2142	struct hda_pcm *info = spec->pcm_rec;
2143	int i;
2144
2145	codec->num_pcms = 1;
2146	codec->pcm_info = info;
2147
2148	info->name = spec->stream_name_analog;
2149	if (spec->stream_analog_playback) {
2150		snd_assert(spec->multiout.dac_nids, return -EINVAL);
2151		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
2152		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2153	}
2154	if (spec->stream_analog_capture) {
2155		snd_assert(spec->adc_nids, return -EINVAL);
2156		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
2157		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2158	}
2159
2160	if (spec->channel_mode) {
2161		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2162		for (i = 0; i < spec->num_channel_mode; i++) {
2163			if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2164				info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2165			}
2166		}
2167	}
2168
2169	/* SPDIF for stream index #1 */
2170	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
2171		codec->num_pcms = 2;
2172		info = spec->pcm_rec + 1;
2173		info->name = spec->stream_name_digital;
2174		if (spec->multiout.dig_out_nid &&
2175		    spec->stream_digital_playback) {
2176			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
2177			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2178		}
2179		if (spec->dig_in_nid &&
2180		    spec->stream_digital_capture) {
2181			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
2182			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2183		}
2184	}
2185
2186	/* If the use of more than one ADC is requested for the current
2187	 * model, configure a second analog capture-only PCM.
2188	 */
2189	/* Additional Analaog capture for index #2 */
2190	if (spec->num_adc_nids > 1 && spec->stream_analog_capture &&
2191	    spec->adc_nids) {
2192		codec->num_pcms = 3;
2193		info = spec->pcm_rec + 2;
2194		info->name = spec->stream_name_analog;
2195		/* No playback stream for second PCM */
2196		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback;
2197		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2198		if (spec->stream_analog_capture) {
2199			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
2200			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1];
2201		}
2202	}
2203
2204	return 0;
2205}
2206
2207static void alc_free(struct hda_codec *codec)
2208{
2209	struct alc_spec *spec = codec->spec;
2210	unsigned int i;
2211
2212	if (!spec)
2213		return;
2214
2215	if (spec->kctl_alloc) {
2216		for (i = 0; i < spec->num_kctl_used; i++)
2217			kfree(spec->kctl_alloc[i].name);
2218		kfree(spec->kctl_alloc);
2219	}
2220	kfree(spec);
2221}
2222
2223/*
2224 */
2225static struct hda_codec_ops alc_patch_ops = {
2226	.build_controls = alc_build_controls,
2227	.build_pcms = alc_build_pcms,
2228	.init = alc_init,
2229	.free = alc_free,
2230	.unsol_event = alc_unsol_event,
2231#ifdef CONFIG_PM
2232	.resume = alc_resume,
2233#endif
2234};
2235
2236
2237/*
2238 * Test configuration for debugging
2239 *
2240 * Almost all inputs/outputs are enabled.  I/O pins can be configured via
2241 * enum controls.
2242 */
2243#ifdef CONFIG_SND_DEBUG
2244static hda_nid_t alc880_test_dac_nids[4] = {
2245	0x02, 0x03, 0x04, 0x05
2246};
2247
2248static struct hda_input_mux alc880_test_capture_source = {
2249	.num_items = 7,
2250	.items = {
2251		{ "In-1", 0x0 },
2252		{ "In-2", 0x1 },
2253		{ "In-3", 0x2 },
2254		{ "In-4", 0x3 },
2255		{ "CD", 0x4 },
2256		{ "Front", 0x5 },
2257		{ "Surround", 0x6 },
2258	},
2259};
2260
2261static struct hda_channel_mode alc880_test_modes[4] = {
2262	{ 2, NULL },
2263	{ 4, NULL },
2264	{ 6, NULL },
2265	{ 8, NULL },
2266};
2267
2268static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
2269				 struct snd_ctl_elem_info *uinfo)
2270{
2271	static char *texts[] = {
2272		"N/A", "Line Out", "HP Out",
2273		"In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
2274	};
2275	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2276	uinfo->count = 1;
2277	uinfo->value.enumerated.items = 8;
2278	if (uinfo->value.enumerated.item >= 8)
2279		uinfo->value.enumerated.item = 7;
2280	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2281	return 0;
2282}
2283
2284static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
2285				struct snd_ctl_elem_value *ucontrol)
2286{
2287	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2288	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2289	unsigned int pin_ctl, item = 0;
2290
2291	pin_ctl = snd_hda_codec_read(codec, nid, 0,
2292				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2293	if (pin_ctl & AC_PINCTL_OUT_EN) {
2294		if (pin_ctl & AC_PINCTL_HP_EN)
2295			item = 2;
2296		else
2297			item = 1;
2298	} else if (pin_ctl & AC_PINCTL_IN_EN) {
2299		switch (pin_ctl & AC_PINCTL_VREFEN) {
2300		case AC_PINCTL_VREF_HIZ: item = 3; break;
2301		case AC_PINCTL_VREF_50:  item = 4; break;
2302		case AC_PINCTL_VREF_GRD: item = 5; break;
2303		case AC_PINCTL_VREF_80:  item = 6; break;
2304		case AC_PINCTL_VREF_100: item = 7; break;
2305		}
2306	}
2307	ucontrol->value.enumerated.item[0] = item;
2308	return 0;
2309}
2310
2311static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
2312				struct snd_ctl_elem_value *ucontrol)
2313{
2314	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2315	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2316	static unsigned int ctls[] = {
2317		0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
2318		AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
2319		AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
2320		AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
2321		AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
2322		AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
2323	};
2324	unsigned int old_ctl, new_ctl;
2325
2326	old_ctl = snd_hda_codec_read(codec, nid, 0,
2327				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2328	new_ctl = ctls[ucontrol->value.enumerated.item[0]];
2329	if (old_ctl != new_ctl) {
2330		snd_hda_codec_write(codec, nid, 0,
2331				    AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
2332		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2333				    (ucontrol->value.enumerated.item[0] >= 3 ?
2334				     0xb080 : 0xb000));
2335		return 1;
2336	}
2337	return 0;
2338}
2339
2340static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
2341				 struct snd_ctl_elem_info *uinfo)
2342{
2343	static char *texts[] = {
2344		"Front", "Surround", "CLFE", "Side"
2345	};
2346	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2347	uinfo->count = 1;
2348	uinfo->value.enumerated.items = 4;
2349	if (uinfo->value.enumerated.item >= 4)
2350		uinfo->value.enumerated.item = 3;
2351	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2352	return 0;
2353}
2354
2355static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
2356				struct snd_ctl_elem_value *ucontrol)
2357{
2358	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2359	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2360	unsigned int sel;
2361
2362	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
2363	ucontrol->value.enumerated.item[0] = sel & 3;
2364	return 0;
2365}
2366
2367static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
2368				struct snd_ctl_elem_value *ucontrol)
2369{
2370	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2371	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2372	unsigned int sel;
2373
2374	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
2375	if (ucontrol->value.enumerated.item[0] != sel) {
2376		sel = ucontrol->value.enumerated.item[0] & 3;
2377		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
2378		return 1;
2379	}
2380	return 0;
2381}
2382
2383#define PIN_CTL_TEST(xname,nid) {			\
2384		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
2385			.name = xname,		       \
2386			.info = alc_test_pin_ctl_info, \
2387			.get = alc_test_pin_ctl_get,   \
2388			.put = alc_test_pin_ctl_put,   \
2389			.private_value = nid	       \
2390			}
2391
2392#define PIN_SRC_TEST(xname,nid) {			\
2393		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
2394			.name = xname,		       \
2395			.info = alc_test_pin_src_info, \
2396			.get = alc_test_pin_src_get,   \
2397			.put = alc_test_pin_src_put,   \
2398			.private_value = nid	       \
2399			}
2400
2401static struct snd_kcontrol_new alc880_test_mixer[] = {
2402	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2403	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2404	HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
2405	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2406	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2407	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2408	HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
2409	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
2410	PIN_CTL_TEST("Front Pin Mode", 0x14),
2411	PIN_CTL_TEST("Surround Pin Mode", 0x15),
2412	PIN_CTL_TEST("CLFE Pin Mode", 0x16),
2413	PIN_CTL_TEST("Side Pin Mode", 0x17),
2414	PIN_CTL_TEST("In-1 Pin Mode", 0x18),
2415	PIN_CTL_TEST("In-2 Pin Mode", 0x19),
2416	PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
2417	PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
2418	PIN_SRC_TEST("In-1 Pin Source", 0x18),
2419	PIN_SRC_TEST("In-2 Pin Source", 0x19),
2420	PIN_SRC_TEST("In-3 Pin Source", 0x1a),
2421	PIN_SRC_TEST("In-4 Pin Source", 0x1b),
2422	HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
2423	HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
2424	HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
2425	HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
2426	HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
2427	HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
2428	HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
2429	HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
2430	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
2431	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
2432	{
2433		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2434		.name = "Channel Mode",
2435		.info = alc_ch_mode_info,
2436		.get = alc_ch_mode_get,
2437		.put = alc_ch_mode_put,
2438	},
2439	{ } /* end */
2440};
2441
2442static struct hda_verb alc880_test_init_verbs[] = {
2443	/* Unmute inputs of 0x0c - 0x0f */
2444	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2445	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2446	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2447	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2448	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2449	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2450	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2451	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2452	/* Vol output for 0x0c-0x0f */
2453	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2454	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2455	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2456	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2457	/* Set output pins 0x14-0x17 */
2458	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2459	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2460	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2461	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2462	/* Unmute output pins 0x14-0x17 */
2463	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2464	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2465	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2466	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2467	/* Set input pins 0x18-0x1c */
2468	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2469	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2470	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2471	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2472	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2473	/* Mute input pins 0x18-0x1b */
2474	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2475	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2476	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2477	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2478	/* ADC set up */
2479	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2480	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
2481	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2482	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
2483	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2484	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
2485	/* Analog input/passthru */
2486	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2487	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2488	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2489	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2490	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2491	{ }
2492};
2493#endif
2494
2495/*
2496 */
2497
2498static const char *alc880_models[ALC880_MODEL_LAST] = {
2499	[ALC880_3ST]		= "3stack",
2500	[ALC880_TCL_S700]	= "tcl",
2501	[ALC880_3ST_DIG]	= "3stack-digout",
2502	[ALC880_CLEVO]		= "clevo",
2503	[ALC880_5ST]		= "5stack",
2504	[ALC880_5ST_DIG]	= "5stack-digout",
2505	[ALC880_W810]		= "w810",
2506	[ALC880_Z71V]		= "z71v",
2507	[ALC880_6ST]		= "6stack",
2508	[ALC880_6ST_DIG]	= "6stack-digout",
2509	[ALC880_ASUS]		= "asus",
2510	[ALC880_ASUS_W1V]	= "asus-w1v",
2511	[ALC880_ASUS_DIG]	= "asus-dig",
2512	[ALC880_ASUS_DIG2]	= "asus-dig2",
2513	[ALC880_UNIWILL_DIG]	= "uniwill",
2514	[ALC880_UNIWILL_P53]	= "uniwill-p53",
2515	[ALC880_FUJITSU]	= "fujitsu",
2516	[ALC880_F1734]		= "F1734",
2517	[ALC880_LG]		= "lg",
2518	[ALC880_LG_LW]		= "lg-lw",
2519#ifdef CONFIG_SND_DEBUG
2520	[ALC880_TEST]		= "test",
2521#endif
2522	[ALC880_AUTO]		= "auto",
2523};
2524
2525static struct snd_pci_quirk alc880_cfg_tbl[] = {
2526	/* Broken BIOS configuration */
2527	SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG),
2528	SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
2529
2530	SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
2531	SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
2532	SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
2533	SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
2534	SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
2535	SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
2536	SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
2537	SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
2538	SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
2539
2540	SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
2541	SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
2542
2543	SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
2544	SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
2545	SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
2546	SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
2547	SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
2548	SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
2549	SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
2550	/* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
2551	SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
2552	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
2553	SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS),
2554	SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
2555	SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
2556	SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
2557	SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS),
2558
2559	SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
2560	SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
2561	SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
2562	SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
2563	SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
2564	SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
2565	SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
2566	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
2567	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
2568	SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
2569	SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
2570	SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
2571	SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
2572	SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
2573	SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
2574	SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
2575	SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
2576	SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
2577
2578	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
2579	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
2580	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
2581	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),
2582
2583	SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
2584	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),
2585	SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
2586	SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
2587
2588	SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
2589	SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
2590	SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
2591	SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
2592
2593	SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
2594	SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
2595	SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
2596	SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
2597	SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
2598	SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
2599	SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
2600	SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
2601	SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
2602	SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
2603	SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST),
2604
2605	{}
2606};
2607
2608/*
2609 * ALC880 codec presets
2610 */
2611static struct alc_config_preset alc880_presets[] = {
2612	[ALC880_3ST] = {
2613		.mixers = { alc880_three_stack_mixer },
2614		.init_verbs = { alc880_volume_init_verbs,
2615				alc880_pin_3stack_init_verbs },
2616		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2617		.dac_nids = alc880_dac_nids,
2618		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
2619		.channel_mode = alc880_threestack_modes,
2620		.need_dac_fix = 1,
2621		.input_mux = &alc880_capture_source,
2622	},
2623	[ALC880_3ST_DIG] = {
2624		.mixers = { alc880_three_stack_mixer },
2625		.init_verbs = { alc880_volume_init_verbs,
2626				alc880_pin_3stack_init_verbs },
2627		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2628		.dac_nids = alc880_dac_nids,
2629		.dig_out_nid = ALC880_DIGOUT_NID,
2630		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
2631		.channel_mode = alc880_threestack_modes,
2632		.need_dac_fix = 1,
2633		.input_mux = &alc880_capture_source,
2634	},
2635	[ALC880_TCL_S700] = {
2636		.mixers = { alc880_tcl_s700_mixer },
2637		.init_verbs = { alc880_volume_init_verbs,
2638				alc880_pin_tcl_S700_init_verbs,
2639				alc880_gpio2_init_verbs },
2640		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2641		.dac_nids = alc880_dac_nids,
2642		.hp_nid = 0x03,
2643		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
2644		.channel_mode = alc880_2_jack_modes,
2645		.input_mux = &alc880_capture_source,
2646	},
2647	[ALC880_5ST] = {
2648		.mixers = { alc880_three_stack_mixer,
2649			    alc880_five_stack_mixer},
2650		.init_verbs = { alc880_volume_init_verbs,
2651				alc880_pin_5stack_init_verbs },
2652		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2653		.dac_nids = alc880_dac_nids,
2654		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
2655		.channel_mode = alc880_fivestack_modes,
2656		.input_mux = &alc880_capture_source,
2657	},
2658	[ALC880_5ST_DIG] = {
2659		.mixers = { alc880_three_stack_mixer,
2660			    alc880_five_stack_mixer },
2661		.init_verbs = { alc880_volume_init_verbs,
2662				alc880_pin_5stack_init_verbs },
2663		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2664		.dac_nids = alc880_dac_nids,
2665		.dig_out_nid = ALC880_DIGOUT_NID,
2666		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
2667		.channel_mode = alc880_fivestack_modes,
2668		.input_mux = &alc880_capture_source,
2669	},
2670	[ALC880_6ST] = {
2671		.mixers = { alc880_six_stack_mixer },
2672		.init_verbs = { alc880_volume_init_verbs,
2673				alc880_pin_6stack_init_verbs },
2674		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
2675		.dac_nids = alc880_6st_dac_nids,
2676		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
2677		.channel_mode = alc880_sixstack_modes,
2678		.input_mux = &alc880_6stack_capture_source,
2679	},
2680	[ALC880_6ST_DIG] = {
2681		.mixers = { alc880_six_stack_mixer },
2682		.init_verbs = { alc880_volume_init_verbs,
2683				alc880_pin_6stack_init_verbs },
2684		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
2685		.dac_nids = alc880_6st_dac_nids,
2686		.dig_out_nid = ALC880_DIGOUT_NID,
2687		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
2688		.channel_mode = alc880_sixstack_modes,
2689		.input_mux = &alc880_6stack_capture_source,
2690	},
2691	[ALC880_W810] = {
2692		.mixers = { alc880_w810_base_mixer },
2693		.init_verbs = { alc880_volume_init_verbs,
2694				alc880_pin_w810_init_verbs,
2695				alc880_gpio2_init_verbs },
2696		.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
2697		.dac_nids = alc880_w810_dac_nids,
2698		.dig_out_nid = ALC880_DIGOUT_NID,
2699		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
2700		.channel_mode = alc880_w810_modes,
2701		.input_mux = &alc880_capture_source,
2702	},
2703	[ALC880_Z71V] = {
2704		.mixers = { alc880_z71v_mixer },
2705		.init_verbs = { alc880_volume_init_verbs,
2706				alc880_pin_z71v_init_verbs },
2707		.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
2708		.dac_nids = alc880_z71v_dac_nids,
2709		.dig_out_nid = ALC880_DIGOUT_NID,
2710		.hp_nid = 0x03,
2711		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
2712		.channel_mode = alc880_2_jack_modes,
2713		.input_mux = &alc880_capture_source,
2714	},
2715	[ALC880_F1734] = {
2716		.mixers = { alc880_f1734_mixer },
2717		.init_verbs = { alc880_volume_init_verbs,
2718				alc880_pin_f1734_init_verbs },
2719		.num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
2720		.dac_nids = alc880_f1734_dac_nids,
2721		.hp_nid = 0x02,
2722		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
2723		.channel_mode = alc880_2_jack_modes,
2724		.input_mux = &alc880_capture_source,
2725	},
2726	[ALC880_ASUS] = {
2727		.mixers = { alc880_asus_mixer },
2728		.init_verbs = { alc880_volume_init_verbs,
2729				alc880_pin_asus_init_verbs,
2730				alc880_gpio1_init_verbs },
2731		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2732		.dac_nids = alc880_asus_dac_nids,
2733		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2734		.channel_mode = alc880_asus_modes,
2735		.need_dac_fix = 1,
2736		.input_mux = &alc880_capture_source,
2737	},
2738	[ALC880_ASUS_DIG] = {
2739		.mixers = { alc880_asus_mixer },
2740		.init_verbs = { alc880_volume_init_verbs,
2741				alc880_pin_asus_init_verbs,
2742				alc880_gpio1_init_verbs },
2743		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2744		.dac_nids = alc880_asus_dac_nids,
2745		.dig_out_nid = ALC880_DIGOUT_NID,
2746		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2747		.channel_mode = alc880_asus_modes,
2748		.need_dac_fix = 1,
2749		.input_mux = &alc880_capture_source,
2750	},
2751	[ALC880_ASUS_DIG2] = {
2752		.mixers = { alc880_asus_mixer },
2753		.init_verbs = { alc880_volume_init_verbs,
2754				alc880_pin_asus_init_verbs,
2755				alc880_gpio2_init_verbs }, /* use GPIO2 */
2756		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2757		.dac_nids = alc880_asus_dac_nids,
2758		.dig_out_nid = ALC880_DIGOUT_NID,
2759		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2760		.channel_mode = alc880_asus_modes,
2761		.need_dac_fix = 1,
2762		.input_mux = &alc880_capture_source,
2763	},
2764	[ALC880_ASUS_W1V] = {
2765		.mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
2766		.init_verbs = { alc880_volume_init_verbs,
2767				alc880_pin_asus_init_verbs,
2768				alc880_gpio1_init_verbs },
2769		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2770		.dac_nids = alc880_asus_dac_nids,
2771		.dig_out_nid = ALC880_DIGOUT_NID,
2772		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2773		.channel_mode = alc880_asus_modes,
2774		.need_dac_fix = 1,
2775		.input_mux = &alc880_capture_source,
2776	},
2777	[ALC880_UNIWILL_DIG] = {
2778		.mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
2779		.init_verbs = { alc880_volume_init_verbs,
2780				alc880_pin_asus_init_verbs },
2781		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2782		.dac_nids = alc880_asus_dac_nids,
2783		.dig_out_nid = ALC880_DIGOUT_NID,
2784		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2785		.channel_mode = alc880_asus_modes,
2786		.need_dac_fix = 1,
2787		.input_mux = &alc880_capture_source,
2788	},
2789	[ALC880_UNIWILL] = {
2790		.mixers = { alc880_uniwill_mixer },
2791		.init_verbs = { alc880_volume_init_verbs,
2792				alc880_uniwill_init_verbs },
2793		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2794		.dac_nids = alc880_asus_dac_nids,
2795		.dig_out_nid = ALC880_DIGOUT_NID,
2796		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
2797		.channel_mode = alc880_threestack_modes,
2798		.need_dac_fix = 1,
2799		.input_mux = &alc880_capture_source,
2800		.unsol_event = alc880_uniwill_unsol_event,
2801		.init_hook = alc880_uniwill_automute,
2802	},
2803	[ALC880_UNIWILL_P53] = {
2804		.mixers = { alc880_uniwill_p53_mixer },
2805		.init_verbs = { alc880_volume_init_verbs,
2806				alc880_uniwill_p53_init_verbs },
2807		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2808		.dac_nids = alc880_asus_dac_nids,
2809		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
2810		.channel_mode = alc880_threestack_modes,
2811		.input_mux = &alc880_capture_source,
2812		.unsol_event = alc880_uniwill_p53_unsol_event,
2813		.init_hook = alc880_uniwill_p53_hp_automute,
2814	},
2815	[ALC880_FUJITSU] = {
2816		.mixers = { alc880_fujitsu_mixer,
2817			    alc880_pcbeep_mixer, },
2818		.init_verbs = { alc880_volume_init_verbs,
2819				alc880_uniwill_p53_init_verbs,
2820	       			alc880_beep_init_verbs },
2821		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2822		.dac_nids = alc880_dac_nids,
2823		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
2824		.channel_mode = alc880_2_jack_modes,
2825		.input_mux = &alc880_capture_source,
2826		.unsol_event = alc880_uniwill_p53_unsol_event,
2827		.init_hook = alc880_uniwill_p53_hp_automute,
2828	},
2829	[ALC880_CLEVO] = {
2830		.mixers = { alc880_three_stack_mixer },
2831		.init_verbs = { alc880_volume_init_verbs,
2832				alc880_pin_clevo_init_verbs },
2833		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2834		.dac_nids = alc880_dac_nids,
2835		.hp_nid = 0x03,
2836		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
2837		.channel_mode = alc880_threestack_modes,
2838		.need_dac_fix = 1,
2839		.input_mux = &alc880_capture_source,
2840	},
2841	[ALC880_LG] = {
2842		.mixers = { alc880_lg_mixer },
2843		.init_verbs = { alc880_volume_init_verbs,
2844				alc880_lg_init_verbs },
2845		.num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
2846		.dac_nids = alc880_lg_dac_nids,
2847		.dig_out_nid = ALC880_DIGOUT_NID,
2848		.num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
2849		.channel_mode = alc880_lg_ch_modes,
2850		.need_dac_fix = 1,
2851		.input_mux = &alc880_lg_capture_source,
2852		.unsol_event = alc880_lg_unsol_event,
2853		.init_hook = alc880_lg_automute,
2854	},
2855	[ALC880_LG_LW] = {
2856		.mixers = { alc880_lg_lw_mixer },
2857		.init_verbs = { alc880_volume_init_verbs,
2858				alc880_lg_lw_init_verbs },
2859		.num_dacs = 1,
2860		.dac_nids = alc880_dac_nids,
2861		.dig_out_nid = ALC880_DIGOUT_NID,
2862		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
2863		.channel_mode = alc880_2_jack_modes,
2864		.input_mux = &alc880_lg_lw_capture_source,
2865		.unsol_event = alc880_lg_lw_unsol_event,
2866		.init_hook = alc880_lg_lw_automute,
2867	},
2868#ifdef CONFIG_SND_DEBUG
2869	[ALC880_TEST] = {
2870		.mixers = { alc880_test_mixer },
2871		.init_verbs = { alc880_test_init_verbs },
2872		.num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
2873		.dac_nids = alc880_test_dac_nids,
2874		.dig_out_nid = ALC880_DIGOUT_NID,
2875		.num_channel_mode = ARRAY_SIZE(alc880_test_modes),
2876		.channel_mode = alc880_test_modes,
2877		.input_mux = &alc880_test_capture_source,
2878	},
2879#endif
2880};
2881
2882/*
2883 * Automatic parse of I/O pins from the BIOS configuration
2884 */
2885
2886#define NUM_CONTROL_ALLOC	32
2887#define NUM_VERB_ALLOC		32
2888
2889enum {
2890	ALC_CTL_WIDGET_VOL,
2891	ALC_CTL_WIDGET_MUTE,
2892	ALC_CTL_BIND_MUTE,
2893};
2894static struct snd_kcontrol_new alc880_control_templates[] = {
2895	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2896	HDA_CODEC_MUTE(NULL, 0, 0, 0),
2897	HDA_BIND_MUTE(NULL, 0, 0, 0),
2898};
2899
2900/* add dynamic controls */
2901static int add_control(struct alc_spec *spec, int type, const char *name,
2902		       unsigned long val)
2903{
2904	struct snd_kcontrol_new *knew;
2905
2906	if (spec->num_kctl_used >= spec->num_kctl_alloc) {
2907		int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
2908
2909		/* array + terminator */
2910		knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
2911		if (!knew)
2912			return -ENOMEM;
2913		if (spec->kctl_alloc) {
2914			memcpy(knew, spec->kctl_alloc,
2915			       sizeof(*knew) * spec->num_kctl_alloc);
2916			kfree(spec->kctl_alloc);
2917		}
2918		spec->kctl_alloc = knew;
2919		spec->num_kctl_alloc = num;
2920	}
2921
2922	knew = &spec->kctl_alloc[spec->num_kctl_used];
2923	*knew = alc880_control_templates[type];
2924	knew->name = kstrdup(name, GFP_KERNEL);
2925	if (!knew->name)
2926		return -ENOMEM;
2927	knew->private_value = val;
2928	spec->num_kctl_used++;
2929	return 0;
2930}
2931
2932#define alc880_is_fixed_pin(nid)	((nid) >= 0x14 && (nid) <= 0x17)
2933#define alc880_fixed_pin_idx(nid)	((nid) - 0x14)
2934#define alc880_is_multi_pin(nid)	((nid) >= 0x18)
2935#define alc880_multi_pin_idx(nid)	((nid) - 0x18)
2936#define alc880_is_input_pin(nid)	((nid) >= 0x18)
2937#define alc880_input_pin_idx(nid)	((nid) - 0x18)
2938#define alc880_idx_to_dac(nid)		((nid) + 0x02)
2939#define alc880_dac_to_idx(nid)		((nid) - 0x02)
2940#define alc880_idx_to_mixer(nid)	((nid) + 0x0c)
2941#define alc880_idx_to_selector(nid)	((nid) + 0x10)
2942#define ALC880_PIN_CD_NID		0x1c
2943
2944/* fill in the dac_nids table from the parsed pin configuration */
2945static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
2946				     const struct auto_pin_cfg *cfg)
2947{
2948	hda_nid_t nid;
2949	int assigned[4];
2950	int i, j;
2951
2952	memset(assigned, 0, sizeof(assigned));
2953	spec->multiout.dac_nids = spec->private_dac_nids;
2954
2955	/* check the pins hardwired to audio widget */
2956	for (i = 0; i < cfg->line_outs; i++) {
2957		nid = cfg->line_out_pins[i];
2958		if (alc880_is_fixed_pin(nid)) {
2959			int idx = alc880_fixed_pin_idx(nid);
2960			spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
2961			assigned[idx] = 1;
2962		}
2963	}
2964	/* left pins can be connect to any audio widget */
2965	for (i = 0; i < cfg->line_outs; i++) {
2966		nid = cfg->line_out_pins[i];
2967		if (alc880_is_fixed_pin(nid))
2968			continue;
2969		/* search for an empty channel */
2970		for (j = 0; j < cfg->line_outs; j++) {
2971			if (!assigned[j]) {
2972				spec->multiout.dac_nids[i] =
2973					alc880_idx_to_dac(j);
2974				assigned[j] = 1;
2975				break;
2976			}
2977		}
2978	}
2979	spec->multiout.num_dacs = cfg->line_outs;
2980	return 0;
2981}
2982
2983/* add playback controls from the parsed DAC table */
2984static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
2985					     const struct auto_pin_cfg *cfg)
2986{
2987	char name[32];
2988	static const char *chname[4] = {
2989		"Front", "Surround", NULL /*CLFE*/, "Side"
2990	};
2991	hda_nid_t nid;
2992	int i, err;
2993
2994	for (i = 0; i < cfg->line_outs; i++) {
2995		if (!spec->multiout.dac_nids[i])
2996			continue;
2997		nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
2998		if (i == 2) {
2999			/* Center/LFE */
3000			err = add_control(spec, ALC_CTL_WIDGET_VOL,
3001					  "Center Playback Volume",
3002					  HDA_COMPOSE_AMP_VAL(nid, 1, 0,
3003							      HDA_OUTPUT));
3004			if (err < 0)
3005				return err;
3006			err = add_control(spec, ALC_CTL_WIDGET_VOL,
3007					  "LFE Playback Volume",
3008					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
3009							      HDA_OUTPUT));
3010			if (err < 0)
3011				return err;
3012			err = add_control(spec, ALC_CTL_BIND_MUTE,
3013					  "Center Playback Switch",
3014					  HDA_COMPOSE_AMP_VAL(nid, 1, 2,
3015							      HDA_INPUT));
3016			if (err < 0)
3017				return err;
3018			err = add_control(spec, ALC_CTL_BIND_MUTE,
3019					  "LFE Playback Switch",
3020					  HDA_COMPOSE_AMP_VAL(nid, 2, 2,
3021							      HDA_INPUT));
3022			if (err < 0)
3023				return err;
3024		} else {
3025			sprintf(name, "%s Playback Volume", chname[i]);
3026			err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
3027					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
3028							      HDA_OUTPUT));
3029			if (err < 0)
3030				return err;
3031			sprintf(name, "%s Playback Switch", chname[i]);
3032			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
3033					  HDA_COMPOSE_AMP_VAL(nid, 3, 2,
3034							      HDA_INPUT));
3035			if (err < 0)
3036				return err;
3037		}
3038	}
3039	return 0;
3040}
3041
3042/* add playback controls for speaker and HP outputs */
3043static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
3044					const char *pfx)
3045{
3046	hda_nid_t nid;
3047	int err;
3048	char name[32];
3049
3050	if (!pin)
3051		return 0;
3052
3053	if (alc880_is_fixed_pin(pin)) {
3054		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
3055		/* specify the DAC as the extra output */
3056		if (!spec->multiout.hp_nid)
3057			spec->multiout.hp_nid = nid;
3058		else
3059			spec->multiout.extra_out_nid[0] = nid;
3060		/* control HP volume/switch on the output mixer amp */
3061		nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
3062		sprintf(name, "%s Playback Volume", pfx);
3063		err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
3064				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
3065		if (err < 0)
3066			return err;
3067		sprintf(name, "%s Playback Switch", pfx);
3068		err = add_control(spec, ALC_CTL_BIND_MUTE, name,
3069				  HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
3070		if (err < 0)
3071			return err;
3072	} else if (alc880_is_multi_pin(pin)) {
3073		/* set manual connection */
3074		/* we have only a switch on HP-out PIN */
3075		sprintf(name, "%s Playback Switch", pfx);
3076		err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
3077				  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3078		if (err < 0)
3079			return err;
3080	}
3081	return 0;
3082}
3083
3084/* create input playback/capture controls for the given pin */
3085static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
3086			    const char *ctlname,
3087			    int idx, hda_nid_t mix_nid)
3088{
3089	char name[32];
3090	int err;
3091
3092	sprintf(name, "%s Playback Volume", ctlname);
3093	err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
3094			  HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
3095	if (err < 0)
3096		return err;
3097	sprintf(name, "%s Playback Switch", ctlname);
3098	err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
3099			  HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
3100	if (err < 0)
3101		return err;
3102	return 0;
3103}
3104
3105/* create playback/capture controls for input pins */
3106static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
3107						const struct auto_pin_cfg *cfg)
3108{
3109	struct hda_input_mux *imux = &spec->private_imux;
3110	int i, err, idx;
3111
3112	for (i = 0; i < AUTO_PIN_LAST; i++) {
3113		if (alc880_is_input_pin(cfg->input_pins[i])) {
3114			idx = alc880_input_pin_idx(cfg->input_pins[i]);
3115			err = new_analog_input(spec, cfg->input_pins[i],
3116					       auto_pin_cfg_labels[i],
3117					       idx, 0x0b);
3118			if (err < 0)
3119				return err;
3120			imux->items[imux->num_items].label =
3121				auto_pin_cfg_labels[i];
3122			imux->items[imux->num_items].index =
3123				alc880_input_pin_idx(cfg->input_pins[i]);
3124			imux->num_items++;
3125		}
3126	}
3127	return 0;
3128}
3129
3130static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
3131					      hda_nid_t nid, int pin_type,
3132					      int dac_idx)
3133{
3134	/* set as output */
3135	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3136			    pin_type);
3137	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3138			    AMP_OUT_UNMUTE);
3139	/* need the manual connection? */
3140	if (alc880_is_multi_pin(nid)) {
3141		struct alc_spec *spec = codec->spec;
3142		int idx = alc880_multi_pin_idx(nid);
3143		snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
3144				    AC_VERB_SET_CONNECT_SEL,
3145				    alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
3146	}
3147}
3148
3149static int get_pin_type(int line_out_type)
3150{
3151	if (line_out_type == AUTO_PIN_HP_OUT)
3152		return PIN_HP;
3153	else
3154		return PIN_OUT;
3155}
3156
3157static void alc880_auto_init_multi_out(struct hda_codec *codec)
3158{
3159	struct alc_spec *spec = codec->spec;
3160	int i;
3161
3162	alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
3163	for (i = 0; i < spec->autocfg.line_outs; i++) {
3164		hda_nid_t nid = spec->autocfg.line_out_pins[i];
3165		int pin_type = get_pin_type(spec->autocfg.line_out_type);
3166		alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);
3167	}
3168}
3169
3170static void alc880_auto_init_extra_out(struct hda_codec *codec)
3171{
3172	struct alc_spec *spec = codec->spec;
3173	hda_nid_t pin;
3174
3175	pin = spec->autocfg.speaker_pins[0];
3176	if (pin) /* connect to front */
3177		alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
3178	pin = spec->autocfg.hp_pins[0];
3179	if (pin) /* connect to front */
3180		alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
3181}
3182
3183static void alc880_auto_init_analog_input(struct hda_codec *codec)
3184{
3185	struct alc_spec *spec = codec->spec;
3186	int i;
3187
3188	for (i = 0; i < AUTO_PIN_LAST; i++) {
3189		hda_nid_t nid = spec->autocfg.input_pins[i];
3190		if (alc880_is_input_pin(nid)) {
3191			snd_hda_codec_write(codec, nid, 0,
3192					    AC_VERB_SET_PIN_WIDGET_CONTROL,
3193					    i <= AUTO_PIN_FRONT_MIC ?
3194					    PIN_VREF80 : PIN_IN);
3195			if (nid != ALC880_PIN_CD_NID)
3196				snd_hda_codec_write(codec, nid, 0,
3197						    AC_VERB_SET_AMP_GAIN_MUTE,
3198						    AMP_OUT_MUTE);
3199		}
3200	}
3201}
3202
3203/* parse the BIOS configuration and set up the alc_spec */
3204/* return 1 if successful, 0 if the proper config is not found,
3205 * or a negative error code
3206 */
3207static int alc880_parse_auto_config(struct hda_codec *codec)
3208{
3209	struct alc_spec *spec = codec->spec;
3210	int err;
3211	static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3212
3213	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3214					   alc880_ignore);
3215	if (err < 0)
3216		return err;
3217	if (!spec->autocfg.line_outs)
3218		return 0; /* can't find valid BIOS pin config */
3219
3220	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
3221	if (err < 0)
3222		return err;
3223	err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
3224	if (err < 0)
3225		return err;
3226	err = alc880_auto_create_extra_out(spec,
3227					   spec->autocfg.speaker_pins[0],
3228					   "Speaker");
3229	if (err < 0)
3230		return err;
3231	err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
3232					   "Headphone");
3233	if (err < 0)
3234		return err;
3235	err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);
3236	if (err < 0)
3237		return err;
3238
3239	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3240
3241	if (spec->autocfg.dig_out_pin)
3242		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
3243	if (spec->autocfg.dig_in_pin)
3244		spec->dig_in_nid = ALC880_DIGIN_NID;
3245
3246	if (spec->kctl_alloc)
3247		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
3248
3249	spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
3250
3251	spec->num_mux_defs = 1;
3252	spec->input_mux = &spec->private_imux;
3253
3254	return 1;
3255}
3256
3257/* additional initialization for auto-configuration model */
3258static void alc880_auto_init(struct hda_codec *codec)
3259{
3260	alc880_auto_init_multi_out(codec);
3261	alc880_auto_init_extra_out(codec);
3262	alc880_auto_init_analog_input(codec);
3263}
3264
3265/*
3266 * OK, here we have finally the patch for ALC880
3267 */
3268
3269static int patch_alc880(struct hda_codec *codec)
3270{
3271	struct alc_spec *spec;
3272	int board_config;
3273	int err;
3274
3275	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3276	if (spec == NULL)
3277		return -ENOMEM;
3278
3279	codec->spec = spec;
3280
3281	board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
3282						  alc880_models,
3283						  alc880_cfg_tbl);
3284	if (board_config < 0) {
3285		printk(KERN_INFO "hda_codec: Unknown model for ALC880, "
3286		       "trying auto-probe from BIOS...\n");
3287		board_config = ALC880_AUTO;
3288	}
3289
3290	if (board_config == ALC880_AUTO) {
3291		/* automatic parse from the BIOS config */
3292		err = alc880_parse_auto_config(codec);
3293		if (err < 0) {
3294			alc_free(codec);
3295			return err;
3296		} else if (!err) {
3297			printk(KERN_INFO
3298			       "hda_codec: Cannot set up configuration "
3299			       "from BIOS.  Using 3-stack mode...\n");
3300			board_config = ALC880_3ST;
3301		}
3302	}
3303
3304	if (board_config != ALC880_AUTO)
3305		setup_preset(spec, &alc880_presets[board_config]);
3306
3307	spec->stream_name_analog = "ALC880 Analog";
3308	spec->stream_analog_playback = &alc880_pcm_analog_playback;
3309	spec->stream_analog_capture = &alc880_pcm_analog_capture;
3310
3311	spec->stream_name_digital = "ALC880 Digital";
3312	spec->stream_digital_playback = &alc880_pcm_digital_playback;
3313	spec->stream_digital_capture = &alc880_pcm_digital_capture;
3314
3315	if (!spec->adc_nids && spec->input_mux) {
3316		/* check whether NID 0x07 is valid */
3317		unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
3318		/* get type */
3319		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
3320		if (wcap != AC_WID_AUD_IN) {
3321			spec->adc_nids = alc880_adc_nids_alt;
3322			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
3323			spec->mixers[spec->num_mixers] =
3324				alc880_capture_alt_mixer;
3325			spec->num_mixers++;
3326		} else {
3327			spec->adc_nids = alc880_adc_nids;
3328			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
3329			spec->mixers[spec->num_mixers] = alc880_capture_mixer;
3330			spec->num_mixers++;
3331		}
3332	}
3333
3334	codec->patch_ops = alc_patch_ops;
3335	if (board_config == ALC880_AUTO)
3336		spec->init_hook = alc880_auto_init;
3337
3338	return 0;
3339}
3340
3341
3342/*
3343 * ALC260 support
3344 */
3345
3346static hda_nid_t alc260_dac_nids[1] = {
3347	/* front */
3348	0x02,
3349};
3350
3351static hda_nid_t alc260_adc_nids[1] = {
3352	/* ADC0 */
3353	0x04,
3354};
3355
3356static hda_nid_t alc260_adc_nids_alt[1] = {
3357	/* ADC1 */
3358	0x05,
3359};
3360
3361static hda_nid_t alc260_hp_adc_nids[2] = {
3362	/* ADC1, 0 */
3363	0x05, 0x04
3364};
3365
3366/* NIDs used when simultaneous access to both ADCs makes sense.  Note that
3367 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
3368 */
3369static hda_nid_t alc260_dual_adc_nids[2] = {
3370	/* ADC0, ADC1 */
3371	0x04, 0x05
3372};
3373
3374#define ALC260_DIGOUT_NID	0x03
3375#define ALC260_DIGIN_NID	0x06
3376
3377static struct hda_input_mux alc260_capture_source = {
3378	.num_items = 4,
3379	.items = {
3380		{ "Mic", 0x0 },
3381		{ "Front Mic", 0x1 },
3382		{ "Line", 0x2 },
3383		{ "CD", 0x4 },
3384	},
3385};
3386
3387/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
3388 * headphone jack and the internal CD lines since these are the only pins at
3389 * which audio can appear.  For flexibility, also allow the option of
3390 * recording the mixer output on the second ADC (ADC0 doesn't have a
3391 * connection to the mixer output).
3392 */
3393static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
3394	{
3395		.num_items = 3,
3396		.items = {
3397			{ "Mic/Line", 0x0 },
3398			{ "CD", 0x4 },
3399			{ "Headphone", 0x2 },
3400		},
3401	},
3402	{
3403		.num_items = 4,
3404		.items = {
3405			{ "Mic/Line", 0x0 },
3406			{ "CD", 0x4 },
3407			{ "Headphone", 0x2 },
3408			{ "Mixer", 0x5 },
3409		},
3410	},
3411
3412};
3413
3414/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
3415 * the Fujitsu S702x, but jacks are marked differently.
3416 */
3417static struct hda_input_mux alc260_acer_capture_sources[2] = {
3418	{
3419		.num_items = 4,
3420		.items = {
3421			{ "Mic", 0x0 },
3422			{ "Line", 0x2 },
3423			{ "CD", 0x4 },
3424			{ "Headphone", 0x5 },
3425		},
3426	},
3427	{
3428		.num_items = 5,
3429		.items = {
3430			{ "Mic", 0x0 },
3431			{ "Line", 0x2 },
3432			{ "CD", 0x4 },
3433			{ "Headphone", 0x6 },
3434			{ "Mixer", 0x5 },
3435		},
3436	},
3437};
3438/*
3439 * This is just place-holder, so there's something for alc_build_pcms to look
3440 * at when it calculates the maximum number of channels. ALC260 has no mixer
3441 * element which allows changing the channel mode, so the verb list is
3442 * never used.
3443 */
3444static struct hda_channel_mode alc260_modes[1] = {
3445	{ 2, NULL },
3446};
3447
3448
3449/* Mixer combinations
3450 *
3451 * basic: base_output + input + pc_beep + capture
3452 * HP: base_output + input + capture_alt
3453 * HP_3013: hp_3013 + input + capture
3454 * fujitsu: fujitsu + capture
3455 * acer: acer + capture
3456 */
3457
3458static struct snd_kcontrol_new alc260_base_output_mixer[] = {
3459	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3460	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
3461	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
3462	HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
3463	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
3464	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
3465	{ } /* end */
3466};
3467
3468static struct snd_kcontrol_new alc260_input_mixer[] = {
3469	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
3470	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
3471	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
3472	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
3473	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
3474	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
3475	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
3476	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
3477	{ } /* end */
3478};
3479
3480static struct snd_kcontrol_new alc260_pc_beep_mixer[] = {
3481	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
3482	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
3483	{ } /* end */
3484};
3485
3486static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
3487	HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
3488	HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
3489	HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
3490	HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
3491	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3492	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
3493	HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
3494	HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
3495	{ } /* end */
3496};
3497
3498/* Fujitsu S702x series laptops.  ALC260 pin usage: Mic/Line jack = 0x12,
3499 * HP jack = 0x14, CD audio =  0x16, internal speaker = 0x10.
3500 */
3501static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
3502	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3503	HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
3504	ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
3505	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
3506	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
3507	HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
3508	HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
3509	ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
3510	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
3511	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
3512	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
3513	HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),
3514	{ } /* end */
3515};
3516
3517/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks.  Note that current
3518 * versions of the ALC260 don't act on requests to enable mic bias from NID
3519 * 0x0f (used to drive the headphone jack in these laptops).  The ALC260
3520 * datasheet doesn't mention this restriction.  At this stage it's not clear
3521 * whether this behaviour is intentional or is a hardware bug in chip
3522 * revisions available in early 2006.  Therefore for now allow the
3523 * "Headphone Jack Mode" control to span all choices, but if it turns out
3524 * that the lack of mic bias for this NID is intentional we could change the
3525 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
3526 *
3527 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
3528 * don't appear to make the mic bias available from the "line" jack, even
3529 * though the NID used for this jack (0x14) can supply it.  The theory is
3530 * that perhaps Acer have included blocking capacitors between the ALC260
3531 * and the output jack.  If this turns out to be the case for all such
3532 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
3533 * to ALC_PIN_DIR_INOUT_NOMICBIAS.
3534 *
3535 * The C20x Tablet series have a mono internal speaker which is controlled
3536 * via the chip's Mono sum widget and pin complex, so include the necessary
3537 * controls for such models.  On models without a "mono speaker" the control
3538 * won't do anything.
3539 */
3540static struct snd_kcontrol_new alc260_acer_mixer[] = {
3541	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3542	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
3543	ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
3544	HDA_CODEC_VOLUME_MONO("Mono Speaker Playback Volume", 0x0a, 1, 0x0,
3545			      HDA_OUTPUT),
3546	HDA_BIND_MUTE_MONO("Mono Speaker Playback Switch", 0x0a, 1, 2,
3547			   HDA_INPUT),
3548	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
3549	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
3550	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
3551	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
3552	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
3553	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
3554	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
3555	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
3556	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
3557	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
3558	{ } /* end */
3559};
3560
3561/* Packard bell V7900  ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
3562 * Line In jack = 0x14, CD audio =  0x16, pc beep = 0x17.
3563 */
3564static struct snd_kcontrol_new alc260_will_mixer[] = {
3565	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3566	HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
3567	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
3568	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
3569	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
3570	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
3571	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
3572	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
3573	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
3574	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
3575	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
3576	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
3577	{ } /* end */
3578};
3579
3580/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
3581 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
3582 */
3583static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
3584	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3585	HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
3586	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
3587	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
3588	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
3589	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
3590	HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
3591	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
3592	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
3593	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
3594	{ } /* end */
3595};
3596
3597/* capture mixer elements */
3598static struct snd_kcontrol_new alc260_capture_mixer[] = {
3599	HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
3600	HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
3601	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),
3602	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),
3603	{
3604		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3605		/* The multiple "Capture Source" controls confuse alsamixer
3606		 * So call somewhat different..
3607		 * FIXME: the controls appear in the "playback" view!
3608		 */
3609		/* .name = "Capture Source", */
3610		.name = "Input Source",
3611		.count = 2,
3612		.info = alc_mux_enum_info,
3613		.get = alc_mux_enum_get,
3614		.put = alc_mux_enum_put,
3615	},
3616	{ } /* end */
3617};
3618
3619static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {
3620	HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
3621	HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
3622	{
3623		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3624		/* The multiple "Capture Source" controls confuse alsamixer
3625		 * So call somewhat different..
3626		 * FIXME: the controls appear in the "playback" view!
3627		 */
3628		/* .name = "Capture Source", */
3629		.name = "Input Source",
3630		.count = 1,
3631		.info = alc_mux_enum_info,
3632		.get = alc_mux_enum_get,
3633		.put = alc_mux_enum_put,
3634	},
3635	{ } /* end */
3636};
3637
3638/*
3639 * initialization verbs
3640 */
3641static struct hda_verb alc260_init_verbs[] = {
3642	/* Line In pin widget for input */
3643	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3644	/* CD pin widget for input */
3645	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3646	/* Mic1 (rear panel) pin widget for input and vref at 80% */
3647	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3648	/* Mic2 (front panel) pin widget for input and vref at 80% */
3649	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3650	/* LINE-2 is used for line-out in rear */
3651	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3652	/* select line-out */
3653	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
3654	/* LINE-OUT pin */
3655	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3656	/* enable HP */
3657	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3658	/* enable Mono */
3659	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3660	/* mute capture amp left and right */
3661	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3662	/* set connection select to line in (default select for this ADC) */
3663	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
3664	/* mute capture amp left and right */
3665	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3666	/* set connection select to line in (default select for this ADC) */
3667	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
3668	/* set vol=0 Line-Out mixer amp left and right */
3669	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3670	/* unmute pin widget amp left and right (no gain on this amp) */
3671	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3672	/* set vol=0 HP mixer amp left and right */
3673	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3674	/* unmute pin widget amp left and right (no gain on this amp) */
3675	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3676	/* set vol=0 Mono mixer amp left and right */
3677	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3678	/* unmute pin widget amp left and right (no gain on this amp) */
3679	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3680	/* unmute LINE-2 out pin */
3681	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3682	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
3683	 * Line In 2 = 0x03
3684	 */
3685	/* mute CD */
3686	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3687	/* mute Line In */
3688	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3689	/* mute Mic */
3690	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3691	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
3692	/* mute Front out path */
3693	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3694	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3695	/* mute Headphone out path */
3696	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3697	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3698	/* mute Mono out path */
3699	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3700	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3701	{ }
3702};
3703
3704#if 0 /* should be identical with alc260_init_verbs? */
3705static struct hda_verb alc260_hp_init_verbs[] = {
3706	/* Headphone and output */
3707	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
3708	/* mono output */
3709	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3710	/* Mic1 (rear panel) pin widget for input and vref at 80% */
3711	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3712	/* Mic2 (front panel) pin widget for input and vref at 80% */
3713	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3714	/* Line In pin widget for input */
3715	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3716	/* Line-2 pin widget for output */
3717	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3718	/* CD pin widget for input */
3719	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3720	/* unmute amp left and right */
3721	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
3722	/* set connection select to line in (default select for this ADC) */
3723	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
3724	/* unmute Line-Out mixer amp left and right (volume = 0) */
3725	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
3726	/* mute pin widget amp left and right (no gain on this amp) */
3727	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3728	/* unmute HP mixer amp left and right (volume = 0) */
3729	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
3730	/* mute pin widget amp left and right (no gain on this amp) */
3731	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3732	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
3733	 * Line In 2 = 0x03
3734	 */
3735	/* unmute CD */
3736	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
3737	/* unmute Line In */
3738	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
3739	/* unmute Mic */
3740	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3741	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
3742	/* Unmute Front out path */
3743	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3744	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3745	/* Unmute Headphone out path */
3746	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3747	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3748	/* Unmute Mono out path */
3749	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3750	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3751	{ }
3752};
3753#endif
3754
3755static struct hda_verb alc260_hp_3013_init_verbs[] = {
3756	/* Line out and output */
3757	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3758	/* mono output */
3759	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3760	/* Mic1 (rear panel) pin widget for input and vref at 80% */
3761	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3762	/* Mic2 (front panel) pin widget for input and vref at 80% */
3763	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3764	/* Line In pin widget for input */
3765	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3766	/* Headphone pin widget for output */
3767	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
3768	/* CD pin widget for input */
3769	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3770	/* unmute amp left and right */
3771	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
3772	/* set connection select to line in (default select for this ADC) */
3773	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
3774	/* unmute Line-Out mixer amp left and right (volume = 0) */
3775	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
3776	/* mute pin widget amp left and right (no gain on this amp) */
3777	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3778	/* unmute HP mixer amp left and right (volume = 0) */
3779	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
3780	/* mute pin widget amp left and right (no gain on this amp) */
3781	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3782	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
3783	 * Line In 2 = 0x03
3784	 */
3785	/* unmute CD */
3786	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
3787	/* unmute Line In */
3788	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
3789	/* unmute Mic */
3790	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3791	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
3792	/* Unmute Front out path */
3793	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3794	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3795	/* Unmute Headphone out path */
3796	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3797	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3798	/* Unmute Mono out path */
3799	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3800	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3801	{ }
3802};
3803
3804/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
3805 * laptops.  ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
3806 * audio = 0x16, internal speaker = 0x10.
3807 */
3808static struct hda_verb alc260_fujitsu_init_verbs[] = {
3809	/* Disable all GPIOs */
3810	{0x01, AC_VERB_SET_GPIO_MASK, 0},
3811	/* Internal speaker is connected to headphone pin */
3812	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3813	/* Headphone/Line-out jack connects to Line1 pin; make it an output */
3814	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3815	/* Mic/Line-in jack is connected to mic1 pin, so make it an input */
3816	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3817	/* Ensure all other unused pins are disabled and muted. */
3818	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3819	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3820	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3821	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3822	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3823	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3824	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3825	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3826
3827	/* Disable digital (SPDIF) pins */
3828	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
3829	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
3830
3831	/* Ensure Line1 pin widget takes its input from the OUT1 sum bus
3832	 * when acting as an output.
3833	 */
3834	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
3835
3836	/* Start with output sum widgets muted and their output gains at min */
3837	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3838	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3839	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3840	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3841	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3842	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3843	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3844	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3845	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3846
3847	/* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
3848	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3849	/* Unmute Line1 pin widget output buffer since it starts as an output.
3850	 * If the pin mode is changed by the user the pin mode control will
3851	 * take care of enabling the pin's input/output buffers as needed.
3852	 * Therefore there's no need to enable the input buffer at this
3853	 * stage.
3854	 */
3855	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3856	/* Unmute input buffer of pin widget used for Line-in (no equiv
3857	 * mixer ctrl)
3858	 */
3859	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3860
3861	/* Mute capture amp left and right */
3862	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3863	/* Set ADC connection select to match default mixer setting - line
3864	 * in (on mic1 pin)
3865	 */
3866	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
3867
3868	/* Do the same for the second ADC: mute capture input amp and
3869	 * set ADC connection to line in (on mic1 pin)
3870	 */
3871	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3872	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
3873
3874	/* Mute all inputs to mixer widget (even unconnected ones) */
3875	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
3876	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
3877	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
3878	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
3879	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
3880	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
3881	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
3882	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
3883
3884	{ }
3885};
3886
3887/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
3888 * similar laptops (adapted from Fujitsu init verbs).
3889 */
3890static struct hda_verb alc260_acer_init_verbs[] = {
3891	/* On TravelMate laptops, GPIO 0 enables the internal speaker and
3892	 * the headphone jack.  Turn this on and rely on the standard mute
3893	 * methods whenever the user wants to turn these outputs off.
3894	 */
3895	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
3896	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
3897	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
3898	/* Internal speaker/Headphone jack is connected to Line-out pin */
3899	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3900	/* Internal microphone/Mic jack is connected to Mic1 pin */
3901	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
3902	/* Line In jack is connected to Line1 pin */
3903	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3904	/* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
3905	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3906	/* Ensure all other unused pins are disabled and muted. */
3907	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3908	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3909	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3910	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3911	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3912	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3913	/* Disable digital (SPDIF) pins */
3914	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
3915	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
3916
3917	/* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
3918	 * bus when acting as outputs.
3919	 */
3920	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
3921	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
3922
3923	/* Start with output sum widgets muted and their output gains at min */
3924	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3925	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3926	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3927	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3928	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3929	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3930	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3931	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3932	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3933
3934	/* Unmute Line-out pin widget amp left and right
3935	 * (no equiv mixer ctrl)
3936	 */
3937	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3938	/* Unmute mono pin widget amp output (no equiv mixer ctrl) */
3939	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3940	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
3941	 * inputs. If the pin mode is changed by the user the pin mode control
3942	 * will take care of enabling the pin's input/output buffers as needed.
3943	 * Therefore there's no need to enable the input buffer at this
3944	 * stage.
3945	 */
3946	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3947	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3948
3949	/* Mute capture amp left and right */
3950	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3951	/* Set ADC connection select to match default mixer setting - mic
3952	 * (on mic1 pin)
3953	 */
3954	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
3955
3956	/* Do similar with the second ADC: mute capture input amp and
3957	 * set ADC connection to mic to match ALSA's default state.
3958	 */
3959	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3960	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
3961
3962	/* Mute all inputs to mixer widget (even unconnected ones) */
3963	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
3964	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
3965	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
3966	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
3967	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
3968	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
3969	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
3970	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
3971
3972	{ }
3973};
3974
3975static struct hda_verb alc260_will_verbs[] = {
3976	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3977	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
3978	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
3979	{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3980	{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
3981	{0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
3982	{}
3983};
3984
3985static struct hda_verb alc260_replacer_672v_verbs[] = {
3986	{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3987	{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
3988	{0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
3989
3990	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
3991	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
3992	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
3993
3994	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3995	{}
3996};
3997
3998/* toggle speaker-output according to the hp-jack state */
3999static void alc260_replacer_672v_automute(struct hda_codec *codec)
4000{
4001        unsigned int present;
4002
4003	/* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
4004        present = snd_hda_codec_read(codec, 0x0f, 0,
4005                                     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
4006	if (present) {
4007		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1);
4008		snd_hda_codec_write(codec, 0x0f, 0,
4009				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
4010	} else {
4011		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
4012		snd_hda_codec_write(codec, 0x0f, 0,
4013				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
4014	}
4015}
4016
4017static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
4018                                       unsigned int res)
4019{
4020        if ((res >> 26) == ALC880_HP_EVENT)
4021                alc260_replacer_672v_automute(codec);
4022}
4023
4024/* Test configuration for debugging, modelled after the ALC880 test
4025 * configuration.
4026 */
4027#ifdef CONFIG_SND_DEBUG
4028static hda_nid_t alc260_test_dac_nids[1] = {
4029	0x02,
4030};
4031static hda_nid_t alc260_test_adc_nids[2] = {
4032	0x04, 0x05,
4033};
4034/* For testing the ALC260, each input MUX needs its own definition since
4035 * the signal assignments are different.  This assumes that the first ADC
4036 * is NID 0x04.
4037 */
4038static struct hda_input_mux alc260_test_capture_sources[2] = {
4039	{
4040		.num_items = 7,
4041		.items = {
4042			{ "MIC1 pin", 0x0 },
4043			{ "MIC2 pin", 0x1 },
4044			{ "LINE1 pin", 0x2 },
4045			{ "LINE2 pin", 0x3 },
4046			{ "CD pin", 0x4 },
4047			{ "LINE-OUT pin", 0x5 },
4048			{ "HP-OUT pin", 0x6 },
4049		},
4050        },
4051	{
4052		.num_items = 8,
4053		.items = {
4054			{ "MIC1 pin", 0x0 },
4055			{ "MIC2 pin", 0x1 },
4056			{ "LINE1 pin", 0x2 },
4057			{ "LINE2 pin", 0x3 },
4058			{ "CD pin", 0x4 },
4059			{ "Mixer", 0x5 },
4060			{ "LINE-OUT pin", 0x6 },
4061			{ "HP-OUT pin", 0x7 },
4062		},
4063        },
4064};
4065static struct snd_kcontrol_new alc260_test_mixer[] = {
4066	/* Output driver widgets */
4067	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
4068	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
4069	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
4070	HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
4071	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
4072	HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
4073
4074	/* Modes for retasking pin widgets
4075	 * Note: the ALC260 doesn't seem to act on requests to enable mic
4076         * bias from NIDs 0x0f and 0x10.  The ALC260 datasheet doesn't
4077         * mention this restriction.  At this stage it's not clear whether
4078         * this behaviour is intentional or is a hardware bug in chip
4079         * revisions available at least up until early 2006.  Therefore for
4080         * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
4081         * choices, but if it turns out that the lack of mic bias for these
4082         * NIDs is intentional we could change their modes from
4083         * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
4084	 */
4085	ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
4086	ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
4087	ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
4088	ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
4089	ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
4090	ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
4091
4092	/* Loopback mixer controls */
4093	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
4094	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
4095	HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
4096	HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
4097	HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
4098	HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
4099	HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
4100	HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
4101	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
4102	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
4103	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
4104	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
4105	HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
4106	HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
4107	HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
4108	HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
4109
4110	/* Controls for GPIO pins, assuming they are configured as outputs */
4111	ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
4112	ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
4113	ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
4114	ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
4115
4116	/* Switches to allow the digital IO pins to be enabled.  The datasheet
4117	 * is ambigious as to which NID is which; testing on laptops which
4118	 * make this output available should provide clarification.
4119	 */
4120	ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
4121	ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
4122
4123	{ } /* end */
4124};
4125static struct hda_verb alc260_test_init_verbs[] = {
4126	/* Enable all GPIOs as outputs with an initial value of 0 */
4127	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
4128	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4129	{0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
4130
4131	/* Enable retasking pins as output, initially without power amp */
4132	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4133	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4134	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4135	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4136	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4137	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4138
4139	/* Disable digital (SPDIF) pins initially, but users can enable
4140	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
4141	 * payload also sets the generation to 0, output to be in "consumer"
4142	 * PCM format, copyright asserted, no pre-emphasis and no validity
4143	 * control.
4144	 */
4145	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
4146	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
4147
4148	/* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
4149	 * OUT1 sum bus when acting as an output.
4150	 */
4151	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
4152	{0x0c, AC_VERB_SET_CONNECT_SEL, 0},
4153	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
4154	{0x0e, AC_VERB_SET_CONNECT_SEL, 0},
4155
4156	/* Start with output sum widgets muted and their output gains at min */
4157	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4158	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4159	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4160	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4161	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4162	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4163	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4164	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4165	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4166
4167	/* Unmute retasking pin widget output buffers since the default
4168	 * state appears to be output.  As the pin mode is changed by the
4169	 * user the pin mode control will take care of enabling the pin's
4170	 * input/output buffers as needed.
4171	 */
4172	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4173	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4174	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4175	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4176	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4177	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4178	/* Also unmute the mono-out pin widget */
4179	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4180
4181	/* Mute capture amp left and right */
4182	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4183	/* Set ADC connection select to match default mixer setting (mic1
4184	 * pin)
4185	 */
4186	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
4187
4188	/* Do the same for the second ADC: mute capture input amp and
4189	 * set ADC connection to mic1 pin
4190	 */
4191	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4192	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
4193
4194	/* Mute all inputs to mixer widget (even unconnected ones) */
4195	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
4196	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
4197	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
4198	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
4199	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
4200	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
4201	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
4202	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
4203
4204	{ }
4205};
4206#endif
4207
4208static struct hda_pcm_stream alc260_pcm_analog_playback = {
4209	.substreams = 1,
4210	.channels_min = 2,
4211	.channels_max = 2,
4212};
4213
4214static struct hda_pcm_stream alc260_pcm_analog_capture = {
4215	.substreams = 1,
4216	.channels_min = 2,
4217	.channels_max = 2,
4218};
4219
4220#define alc260_pcm_digital_playback	alc880_pcm_digital_playback
4221#define alc260_pcm_digital_capture	alc880_pcm_digital_capture
4222
4223/*
4224 * for BIOS auto-configuration
4225 */
4226
4227static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
4228					const char *pfx)
4229{
4230	hda_nid_t nid_vol;
4231	unsigned long vol_val, sw_val;
4232	char name[32];
4233	int err;
4234
4235	if (nid >= 0x0f && nid < 0x11) {
4236		nid_vol = nid - 0x7;
4237		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
4238		sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
4239	} else if (nid == 0x11) {
4240		nid_vol = nid - 0x7;
4241		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
4242		sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
4243	} else if (nid >= 0x12 && nid <= 0x15) {
4244		nid_vol = 0x08;
4245		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
4246		sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
4247	} else
4248		return 0; /* N/A */
4249
4250	snprintf(name, sizeof(name), "%s Playback Volume", pfx);
4251	err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val);
4252	if (err < 0)
4253		return err;
4254	snprintf(name, sizeof(name), "%s Playback Switch", pfx);
4255	err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val);
4256	if (err < 0)
4257		return err;
4258	return 1;
4259}
4260
4261/* add playback controls from the parsed DAC table */
4262static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
4263					     const struct auto_pin_cfg *cfg)
4264{
4265	hda_nid_t nid;
4266	int err;
4267
4268	spec->multiout.num_dacs = 1;
4269	spec->multiout.dac_nids = spec->private_dac_nids;
4270	spec->multiout.dac_nids[0] = 0x02;
4271
4272	nid = cfg->line_out_pins[0];
4273	if (nid) {
4274		err = alc260_add_playback_controls(spec, nid, "Front");
4275		if (err < 0)
4276			return err;
4277	}
4278
4279	nid = cfg->speaker_pins[0];
4280	if (nid) {
4281		err = alc260_add_playback_controls(spec, nid, "Speaker");
4282		if (err < 0)
4283			return err;
4284	}
4285
4286	nid = cfg->hp_pins[0];
4287	if (nid) {
4288		err = alc260_add_playback_controls(spec, nid, "Headphone");
4289		if (err < 0)
4290			return err;
4291	}
4292	return 0;
4293}
4294
4295/* create playback/capture controls for input pins */
4296static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
4297						const struct auto_pin_cfg *cfg)
4298{
4299	struct hda_input_mux *imux = &spec->private_imux;
4300	int i, err, idx;
4301
4302	for (i = 0; i < AUTO_PIN_LAST; i++) {
4303		if (cfg->input_pins[i] >= 0x12) {
4304			idx = cfg->input_pins[i] - 0x12;
4305			err = new_analog_input(spec, cfg->input_pins[i],
4306					       auto_pin_cfg_labels[i], idx,
4307					       0x07);
4308			if (err < 0)
4309				return err;
4310			imux->items[imux->num_items].label =
4311				auto_pin_cfg_labels[i];
4312			imux->items[imux->num_items].index = idx;
4313			imux->num_items++;
4314		}
4315		if (cfg->input_pins[i] >= 0x0f && cfg->input_pins[i] <= 0x10){
4316			idx = cfg->input_pins[i] - 0x09;
4317			err = new_analog_input(spec, cfg->input_pins[i],
4318					       auto_pin_cfg_labels[i], idx,
4319					       0x07);
4320			if (err < 0)
4321				return err;
4322			imux->items[imux->num_items].label =
4323				auto_pin_cfg_labels[i];
4324			imux->items[imux->num_items].index = idx;
4325			imux->num_items++;
4326		}
4327	}
4328	return 0;
4329}
4330
4331static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
4332					      hda_nid_t nid, int pin_type,
4333					      int sel_idx)
4334{
4335	/* set as output */
4336	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4337			    pin_type);
4338	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
4339			    AMP_OUT_UNMUTE);
4340	/* need the manual connection? */
4341	if (nid >= 0x12) {
4342		int idx = nid - 0x12;
4343		snd_hda_codec_write(codec, idx + 0x0b, 0,
4344				    AC_VERB_SET_CONNECT_SEL, sel_idx);
4345	}
4346}
4347
4348static void alc260_auto_init_multi_out(struct hda_codec *codec)
4349{
4350	struct alc_spec *spec = codec->spec;
4351	hda_nid_t nid;
4352
4353	alc_subsystem_id(codec, 0x10, 0x15, 0x0f);
4354	nid = spec->autocfg.line_out_pins[0];
4355	if (nid) {
4356		int pin_type = get_pin_type(spec->autocfg.line_out_type);
4357		alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
4358	}
4359
4360	nid = spec->autocfg.speaker_pins[0];
4361	if (nid)
4362		alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
4363
4364	nid = spec->autocfg.hp_pins[0];
4365	if (nid)
4366		alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
4367}
4368
4369#define ALC260_PIN_CD_NID		0x16
4370static void alc260_auto_init_analog_input(struct hda_codec *codec)
4371{
4372	struct alc_spec *spec = codec->spec;
4373	int i;
4374
4375	for (i = 0; i < AUTO_PIN_LAST; i++) {
4376		hda_nid_t nid = spec->autocfg.input_pins[i];
4377		if (nid >= 0x12) {
4378			snd_hda_codec_write(codec, nid, 0,
4379					    AC_VERB_SET_PIN_WIDGET_CONTROL,
4380					    i <= AUTO_PIN_FRONT_MIC ?
4381					    PIN_VREF80 : PIN_IN);
4382			if (nid != ALC260_PIN_CD_NID)
4383				snd_hda_codec_write(codec, nid, 0,
4384						    AC_VERB_SET_AMP_GAIN_MUTE,
4385						    AMP_OUT_MUTE);
4386		}
4387	}
4388}
4389
4390/*
4391 * generic initialization of ADC, input mixers and output mixers
4392 */
4393static struct hda_verb alc260_volume_init_verbs[] = {
4394	/*
4395	 * Unmute ADC0-1 and set the default input to mic-in
4396	 */
4397	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
4398	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4399	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
4400	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4401
4402	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4403	 * mixer widget
4404	 * Note: PASD motherboards uses the Line In 2 as the input for
4405	 * front panel mic (mic 2)
4406	 */
4407	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
4408	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4409	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4410	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4411	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4412	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
4413
4414	/*
4415	 * Set up output mixers (0x08 - 0x0a)
4416	 */
4417	/* set vol=0 to output mixers */
4418	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4419	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4420	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4421	/* set up input amps for analog loopback */
4422	/* Amp Indices: DAC = 0, mixer = 1 */
4423	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4424	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4425	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4426	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4427	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4428	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4429
4430	{ }
4431};
4432
4433static int alc260_parse_auto_config(struct hda_codec *codec)
4434{
4435	struct alc_spec *spec = codec->spec;
4436	unsigned int wcap;
4437	int err;
4438	static hda_nid_t alc260_ignore[] = { 0x17, 0 };
4439
4440	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4441					   alc260_ignore);
4442	if (err < 0)
4443		return err;
4444	err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
4445	if (err < 0)
4446		return err;
4447	if (!spec->kctl_alloc)
4448		return 0; /* can't find valid BIOS pin config */
4449	err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg);
4450	if (err < 0)
4451		return err;
4452
4453	spec->multiout.max_channels = 2;
4454
4455	if (spec->autocfg.dig_out_pin)
4456		spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
4457	if (spec->kctl_alloc)
4458		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4459
4460	spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
4461
4462	spec->num_mux_defs = 1;
4463	spec->input_mux = &spec->private_imux;
4464
4465	/* check whether NID 0x04 is valid */
4466	wcap = get_wcaps(codec, 0x04);
4467	wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
4468	if (wcap != AC_WID_AUD_IN) {
4469		spec->adc_nids = alc260_adc_nids_alt;
4470		spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
4471		spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
4472	} else {
4473		spec->adc_nids = alc260_adc_nids;
4474		spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
4475		spec->mixers[spec->num_mixers] = alc260_capture_mixer;
4476	}
4477	spec->num_mixers++;
4478
4479	return 1;
4480}
4481
4482/* additional initialization for auto-configuration model */
4483static void alc260_auto_init(struct hda_codec *codec)
4484{
4485	alc260_auto_init_multi_out(codec);
4486	alc260_auto_init_analog_input(codec);
4487}
4488
4489/*
4490 * ALC260 configurations
4491 */
4492static const char *alc260_models[ALC260_MODEL_LAST] = {
4493	[ALC260_BASIC]		= "basic",
4494	[ALC260_HP]		= "hp",
4495	[ALC260_HP_3013]	= "hp-3013",
4496	[ALC260_FUJITSU_S702X]	= "fujitsu",
4497	[ALC260_ACER]		= "acer",
4498	[ALC260_WILL]		= "will",
4499	[ALC260_REPLACER_672V]	= "replacer",
4500#ifdef CONFIG_SND_DEBUG
4501	[ALC260_TEST]		= "test",
4502#endif
4503	[ALC260_AUTO]		= "auto",
4504};
4505
4506static struct snd_pci_quirk alc260_cfg_tbl[] = {
4507	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
4508	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
4509	SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
4510	SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013),
4511	SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
4512	SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP),
4513	SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013),
4514	SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
4515	SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
4516	SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
4517	SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
4518	SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
4519	SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
4520	SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
4521	SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
4522	SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
4523	SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
4524	SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
4525	{}
4526};
4527
4528static struct alc_config_preset alc260_presets[] = {
4529	[ALC260_BASIC] = {
4530		.mixers = { alc260_base_output_mixer,
4531			    alc260_input_mixer,
4532			    alc260_pc_beep_mixer,
4533			    alc260_capture_mixer },
4534		.init_verbs = { alc260_init_verbs },
4535		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4536		.dac_nids = alc260_dac_nids,
4537		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
4538		.adc_nids = alc260_adc_nids,
4539		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4540		.channel_mode = alc260_modes,
4541		.input_mux = &alc260_capture_source,
4542	},
4543	[ALC260_HP] = {
4544		.mixers = { alc260_base_output_mixer,
4545			    alc260_input_mixer,
4546			    alc260_capture_alt_mixer },
4547		.init_verbs = { alc260_init_verbs },
4548		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4549		.dac_nids = alc260_dac_nids,
4550		.num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
4551		.adc_nids = alc260_hp_adc_nids,
4552		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4553		.channel_mode = alc260_modes,
4554		.input_mux = &alc260_capture_source,
4555	},
4556	[ALC260_HP_3013] = {
4557		.mixers = { alc260_hp_3013_mixer,
4558			    alc260_input_mixer,
4559			    alc260_capture_alt_mixer },
4560		.init_verbs = { alc260_hp_3013_init_verbs },
4561		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4562		.dac_nids = alc260_dac_nids,
4563		.num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
4564		.adc_nids = alc260_hp_adc_nids,
4565		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4566		.channel_mode = alc260_modes,
4567		.input_mux = &alc260_capture_source,
4568	},
4569	[ALC260_FUJITSU_S702X] = {
4570		.mixers = { alc260_fujitsu_mixer,
4571			    alc260_capture_mixer },
4572		.init_verbs = { alc260_fujitsu_init_verbs },
4573		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4574		.dac_nids = alc260_dac_nids,
4575		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
4576		.adc_nids = alc260_dual_adc_nids,
4577		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4578		.channel_mode = alc260_modes,
4579		.num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
4580		.input_mux = alc260_fujitsu_capture_sources,
4581	},
4582	[ALC260_ACER] = {
4583		.mixers = { alc260_acer_mixer,
4584			    alc260_capture_mixer },
4585		.init_verbs = { alc260_acer_init_verbs },
4586		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4587		.dac_nids = alc260_dac_nids,
4588		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
4589		.adc_nids = alc260_dual_adc_nids,
4590		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4591		.channel_mode = alc260_modes,
4592		.num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
4593		.input_mux = alc260_acer_capture_sources,
4594	},
4595	[ALC260_WILL] = {
4596		.mixers = { alc260_will_mixer,
4597			    alc260_capture_mixer },
4598		.init_verbs = { alc260_init_verbs, alc260_will_verbs },
4599		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4600		.dac_nids = alc260_dac_nids,
4601		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
4602		.adc_nids = alc260_adc_nids,
4603		.dig_out_nid = ALC260_DIGOUT_NID,
4604		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4605		.channel_mode = alc260_modes,
4606		.input_mux = &alc260_capture_source,
4607	},
4608	[ALC260_REPLACER_672V] = {
4609		.mixers = { alc260_replacer_672v_mixer,
4610			    alc260_capture_mixer },
4611		.init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
4612		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4613		.dac_nids = alc260_dac_nids,
4614		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
4615		.adc_nids = alc260_adc_nids,
4616		.dig_out_nid = ALC260_DIGOUT_NID,
4617		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4618		.channel_mode = alc260_modes,
4619		.input_mux = &alc260_capture_source,
4620		.unsol_event = alc260_replacer_672v_unsol_event,
4621		.init_hook = alc260_replacer_672v_automute,
4622	},
4623#ifdef CONFIG_SND_DEBUG
4624	[ALC260_TEST] = {
4625		.mixers = { alc260_test_mixer,
4626			    alc260_capture_mixer },
4627		.init_verbs = { alc260_test_init_verbs },
4628		.num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
4629		.dac_nids = alc260_test_dac_nids,
4630		.num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
4631		.adc_nids = alc260_test_adc_nids,
4632		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4633		.channel_mode = alc260_modes,
4634		.num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
4635		.input_mux = alc260_test_capture_sources,
4636	},
4637#endif
4638};
4639
4640static int patch_alc260(struct hda_codec *codec)
4641{
4642	struct alc_spec *spec;
4643	int err, board_config;
4644
4645	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4646	if (spec == NULL)
4647		return -ENOMEM;
4648
4649	codec->spec = spec;
4650
4651	board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
4652						  alc260_models,
4653						  alc260_cfg_tbl);
4654	if (board_config < 0) {
4655		snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, "
4656			   "trying auto-probe from BIOS...\n");
4657		board_config = ALC260_AUTO;
4658	}
4659
4660	if (board_config == ALC260_AUTO) {
4661		/* automatic parse from the BIOS config */
4662		err = alc260_parse_auto_config(codec);
4663		if (err < 0) {
4664			alc_free(codec);
4665			return err;
4666		} else if (!err) {
4667			printk(KERN_INFO
4668			       "hda_codec: Cannot set up configuration "
4669			       "from BIOS.  Using base mode...\n");
4670			board_config = ALC260_BASIC;
4671		}
4672	}
4673
4674	if (board_config != ALC260_AUTO)
4675		setup_preset(spec, &alc260_presets[board_config]);
4676
4677	spec->stream_name_analog = "ALC260 Analog";
4678	spec->stream_analog_playback = &alc260_pcm_analog_playback;
4679	spec->stream_analog_capture = &alc260_pcm_analog_capture;
4680
4681	spec->stream_name_digital = "ALC260 Digital";
4682	spec->stream_digital_playback = &alc260_pcm_digital_playback;
4683	spec->stream_digital_capture = &alc260_pcm_digital_capture;
4684
4685	codec->patch_ops = alc_patch_ops;
4686	if (board_config == ALC260_AUTO)
4687		spec->init_hook = alc260_auto_init;
4688
4689	return 0;
4690}
4691
4692
4693/*
4694 * ALC882 support
4695 *
4696 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
4697 * configuration.  Each pin widget can choose any input DACs and a mixer.
4698 * Each ADC is connected from a mixer of all inputs.  This makes possible
4699 * 6-channel independent captures.
4700 *
4701 * In addition, an independent DAC for the multi-playback (not used in this
4702 * driver yet).
4703 */
4704#define ALC882_DIGOUT_NID	0x06
4705#define ALC882_DIGIN_NID	0x0a
4706
4707static struct hda_channel_mode alc882_ch_modes[1] = {
4708	{ 8, NULL }
4709};
4710
4711static hda_nid_t alc882_dac_nids[4] = {
4712	/* front, rear, clfe, rear_surr */
4713	0x02, 0x03, 0x04, 0x05
4714};
4715
4716/* identical with ALC880 */
4717#define alc882_adc_nids		alc880_adc_nids
4718#define alc882_adc_nids_alt	alc880_adc_nids_alt
4719
4720/* input MUX */
4721/* FIXME: should be a matrix-type input source selection */
4722
4723static struct hda_input_mux alc882_capture_source = {
4724	.num_items = 4,
4725	.items = {
4726		{ "Mic", 0x0 },
4727		{ "Front Mic", 0x1 },
4728		{ "Line", 0x2 },
4729		{ "CD", 0x4 },
4730	},
4731};
4732#define alc882_mux_enum_info alc_mux_enum_info
4733#define alc882_mux_enum_get alc_mux_enum_get
4734
4735static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
4736			       struct snd_ctl_elem_value *ucontrol)
4737{
4738	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4739	struct alc_spec *spec = codec->spec;
4740	const struct hda_input_mux *imux = spec->input_mux;
4741	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
4742	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
4743	hda_nid_t nid = capture_mixers[adc_idx];
4744	unsigned int *cur_val = &spec->cur_mux[adc_idx];
4745	unsigned int i, idx;
4746
4747	idx = ucontrol->value.enumerated.item[0];
4748	if (idx >= imux->num_items)
4749		idx = imux->num_items - 1;
4750	if (*cur_val == idx && !codec->in_resume)
4751		return 0;
4752	for (i = 0; i < imux->num_items; i++) {
4753		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
4754		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
4755				    v | (imux->items[i].index << 8));
4756	}
4757	*cur_val = idx;
4758	return 1;
4759}
4760
4761/*
4762 * 2ch mode
4763 */
4764static struct hda_verb alc882_3ST_ch2_init[] = {
4765	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
4766	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
4767	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
4768	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
4769	{ } /* end */
4770};
4771
4772/*
4773 * 6ch mode
4774 */
4775static struct hda_verb alc882_3ST_ch6_init[] = {
4776	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4777	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
4778	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
4779	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4780	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
4781	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
4782	{ } /* end */
4783};
4784
4785static struct hda_channel_mode alc882_3ST_6ch_modes[2] = {
4786	{ 2, alc882_3ST_ch2_init },
4787	{ 6, alc882_3ST_ch6_init },
4788};
4789
4790/*
4791 * 6ch mode
4792 */
4793static struct hda_verb alc882_sixstack_ch6_init[] = {
4794	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4795	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4796	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4797	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4798	{ } /* end */
4799};
4800
4801/*
4802 * 8ch mode
4803 */
4804static struct hda_verb alc882_sixstack_ch8_init[] = {
4805	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4806	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4807	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4808	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4809	{ } /* end */
4810};
4811
4812static struct hda_channel_mode alc882_sixstack_modes[2] = {
4813	{ 6, alc882_sixstack_ch6_init },
4814	{ 8, alc882_sixstack_ch8_init },
4815};
4816
4817/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
4818 *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
4819 */
4820static struct snd_kcontrol_new alc882_base_mixer[] = {
4821	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4822	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4823	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
4824	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
4825	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
4826	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
4827	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
4828	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
4829	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
4830	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
4831	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
4832	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
4833	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
4834	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4835	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4836	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
4837	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
4838	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4839	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
4840	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
4841	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
4842	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
4843	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
4844	{ } /* end */
4845};
4846
4847static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
4848	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4849	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4850	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
4851	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
4852	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4853	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4854	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
4855	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
4856	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4857	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
4858	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
4859	{ } /* end */
4860};
4861
4862static struct snd_kcontrol_new alc882_targa_mixer[] = {
4863	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4864	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4865	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
4866	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
4867	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
4868	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4869	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4870	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
4871	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4872	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
4873	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
4874	{ } /* end */
4875};
4876
4877/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
4878 *                 Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
4879 */
4880static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
4881	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4882	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
4883	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4884	HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4885	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
4886	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
4887	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4888	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4889	HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),
4890	HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
4891	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
4892	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4893	{ } /* end */
4894};
4895
4896static struct snd_kcontrol_new alc882_chmode_mixer[] = {
4897	{
4898		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4899		.name = "Channel Mode",
4900		.info = alc_ch_mode_info,
4901		.get = alc_ch_mode_get,
4902		.put = alc_ch_mode_put,
4903	},
4904	{ } /* end */
4905};
4906
4907static struct hda_verb alc882_init_verbs[] = {
4908	/* Front mixer: unmute input/output amp left and right (volume = 0) */
4909	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4910	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4911	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4912	/* Rear mixer */
4913	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4914	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4915	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4916	/* CLFE mixer */
4917	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4918	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4919	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4920	/* Side mixer */
4921	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4922	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4923	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4924
4925	/* Front Pin: output 0 (0x0c) */
4926	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4927	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4928	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
4929	/* Rear Pin: output 1 (0x0d) */
4930	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4931	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4932	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
4933	/* CLFE Pin: output 2 (0x0e) */
4934	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4935	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4936	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
4937	/* Side Pin: output 3 (0x0f) */
4938	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4939	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4940	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
4941	/* Mic (rear) pin: input vref at 80% */
4942	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4943	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4944	/* Front Mic pin: input vref at 80% */
4945	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4946	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4947	/* Line In pin: input */
4948	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4949	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4950	/* Line-2 In: Headphone output (output 0 - 0x0c) */
4951	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4952	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4953	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
4954	/* CD pin widget for input */
4955	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4956
4957	/* FIXME: use matrix-type input source selection */
4958	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4959	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4960	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4961	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4962	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4963	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4964	/* Input mixer2 */
4965	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4966	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4967	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4968	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4969	/* Input mixer3 */
4970	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4971	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4972	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4973	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4974	/* ADC1: mute amp left and right */
4975	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4976	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4977	/* ADC2: mute amp left and right */
4978	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4979	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4980	/* ADC3: mute amp left and right */
4981	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4982	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4983
4984	{ }
4985};
4986
4987static struct hda_verb alc882_eapd_verbs[] = {
4988	/* change to EAPD mode */
4989	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
4990	{0x20, AC_VERB_SET_PROC_COEF, 0x3060},
4991	{ }
4992};
4993
4994/* Mac Pro test */
4995static struct snd_kcontrol_new alc882_macpro_mixer[] = {
4996	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4997	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4998	HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
4999	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
5000	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
5001	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
5002	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
5003	{ } /* end */
5004};
5005
5006static struct hda_verb alc882_macpro_init_verbs[] = {
5007	/* Front mixer: unmute input/output amp left and right (volume = 0) */
5008	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5009	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5010	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5011	/* Front Pin: output 0 (0x0c) */
5012	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5013	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5014	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
5015	/* Front Mic pin: input vref at 80% */
5016	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5017	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5018	/* Speaker:  output */
5019	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5020	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5021	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
5022	/* Headphone output (output 0 - 0x0c) */
5023	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5024	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5025	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
5026
5027	/* FIXME: use matrix-type input source selection */
5028	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
5029	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
5030	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5031	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5032	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5033	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5034	/* Input mixer2 */
5035	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5036	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5037	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5038	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5039	/* Input mixer3 */
5040	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5041	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5042	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5043	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5044	/* ADC1: mute amp left and right */
5045	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5046	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
5047	/* ADC2: mute amp left and right */
5048	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5049	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
5050	/* ADC3: mute amp left and right */
5051	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5052	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
5053
5054	{ }
5055};
5056
5057static struct hda_verb alc882_targa_verbs[] = {
5058	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5059	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5060
5061	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5062	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5063
5064	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
5065	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
5066	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
5067
5068	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
5069	{0x01, AC_VERB_SET_GPIO_MASK, 0x03},
5070	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
5071	{0x01, AC_VERB_SET_GPIO_DATA, 0x03},
5072	{ } /* end */
5073};
5074
5075/* toggle speaker-output according to the hp-jack state */
5076static void alc882_targa_automute(struct hda_codec *codec)
5077{
5078 	unsigned int present;
5079
5080 	present = snd_hda_codec_read(codec, 0x14, 0,
5081				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
5082	snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
5083				 0x80, present ? 0x80 : 0);
5084	snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
5085				 0x80, present ? 0x80 : 0);
5086	snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3);
5087}
5088
5089static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
5090{
5091	/* Looks like the unsol event is incompatible with the standard
5092	 * definition.  4bit tag is placed at 26 bit!
5093	 */
5094	if (((res >> 26) == ALC880_HP_EVENT)) {
5095		alc882_targa_automute(codec);
5096	}
5097}
5098
5099static struct hda_verb alc882_asus_a7j_verbs[] = {
5100	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5101	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5102
5103	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5104	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5105	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5106
5107	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
5108	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
5109	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
5110
5111	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
5112	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
5113	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
5114	{ } /* end */
5115};
5116
5117static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
5118{
5119	unsigned int gpiostate, gpiomask, gpiodir;
5120
5121	gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
5122				       AC_VERB_GET_GPIO_DATA, 0);
5123
5124	if (!muted)
5125		gpiostate |= (1 << pin);
5126	else
5127		gpiostate &= ~(1 << pin);
5128
5129	gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
5130				      AC_VERB_GET_GPIO_MASK, 0);
5131	gpiomask |= (1 << pin);
5132
5133	gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
5134				     AC_VERB_GET_GPIO_DIRECTION, 0);
5135	gpiodir |= (1 << pin);
5136
5137
5138	snd_hda_codec_write(codec, codec->afg, 0,
5139			    AC_VERB_SET_GPIO_MASK, gpiomask);
5140	snd_hda_codec_write(codec, codec->afg, 0,
5141			    AC_VERB_SET_GPIO_DIRECTION, gpiodir);
5142
5143	msleep(1);
5144
5145	snd_hda_codec_write(codec, codec->afg, 0,
5146			    AC_VERB_SET_GPIO_DATA, gpiostate);
5147}
5148
5149/*
5150 * generic initialization of ADC, input mixers and output mixers
5151 */
5152static struct hda_verb alc882_auto_init_verbs[] = {
5153	/*
5154	 * Unmute ADC0-2 and set the default input to mic-in
5155	 */
5156	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
5157	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5158	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
5159	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5160	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
5161	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5162
5163	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
5164	 * mixer widget
5165	 * Note: PASD motherboards uses the Line In 2 as the input for
5166	 * front panel mic (mic 2)
5167	 */
5168	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
5169	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5170	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5171	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
5172	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
5173	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
5174
5175	/*
5176	 * Set up output mixers (0x0c - 0x0f)
5177	 */
5178	/* set vol=0 to output mixers */
5179	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5180	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5181	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5182	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5183	/* set up input amps for analog loopback */
5184	/* Amp Indices: DAC = 0, mixer = 1 */
5185	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5186	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5187	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5188	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5189	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5190	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5191	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5192	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5193	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5194	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5195
5196	/* FIXME: use matrix-type input source selection */
5197	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
5198	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
5199	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5200	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
5201	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
5202	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
5203	/* Input mixer2 */
5204	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5205	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
5206	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
5207	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
5208	/* Input mixer3 */
5209	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5210	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
5211	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
5212	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
5213
5214	{ }
5215};
5216
5217/* capture mixer elements */
5218static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
5219	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5220	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5221	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5222	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5223	{
5224		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5225		/* The multiple "Capture Source" controls confuse alsamixer
5226		 * So call somewhat different..
5227		 * FIXME: the controls appear in the "playback" view!
5228		 */
5229		/* .name = "Capture Source", */
5230		.name = "Input Source",
5231		.count = 2,
5232		.info = alc882_mux_enum_info,
5233		.get = alc882_mux_enum_get,
5234		.put = alc882_mux_enum_put,
5235	},
5236	{ } /* end */
5237};
5238
5239static struct snd_kcontrol_new alc882_capture_mixer[] = {
5240	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
5241	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
5242	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
5243	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
5244	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
5245	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
5246	{
5247		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5248		/* The multiple "Capture Source" controls confuse alsamixer
5249		 * So call somewhat different..
5250		 * FIXME: the controls appear in the "playback" view!
5251		 */
5252		/* .name = "Capture Source", */
5253		.name = "Input Source",
5254		.count = 3,
5255		.info = alc882_mux_enum_info,
5256		.get = alc882_mux_enum_get,
5257		.put = alc882_mux_enum_put,
5258	},
5259	{ } /* end */
5260};
5261
5262/* pcm configuration: identiacal with ALC880 */
5263#define alc882_pcm_analog_playback	alc880_pcm_analog_playback
5264#define alc882_pcm_analog_capture	alc880_pcm_analog_capture
5265#define alc882_pcm_digital_playback	alc880_pcm_digital_playback
5266#define alc882_pcm_digital_capture	alc880_pcm_digital_capture
5267
5268/*
5269 * configuration and preset
5270 */
5271static const char *alc882_models[ALC882_MODEL_LAST] = {
5272	[ALC882_3ST_DIG]	= "3stack-dig",
5273	[ALC882_6ST_DIG]	= "6stack-dig",
5274	[ALC882_ARIMA]		= "arima",
5275	[ALC882_W2JC]		= "w2jc",
5276	[ALC885_MACPRO]		= "macpro",
5277	[ALC882_AUTO]		= "auto",
5278};
5279
5280static struct snd_pci_quirk alc882_cfg_tbl[] = {
5281	SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
5282	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
5283	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
5284	SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
5285	SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA),
5286	SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
5287	SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
5288	SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
5289	{}
5290};
5291
5292static struct alc_config_preset alc882_presets[] = {
5293	[ALC882_3ST_DIG] = {
5294		.mixers = { alc882_base_mixer },
5295		.init_verbs = { alc882_init_verbs },
5296		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
5297		.dac_nids = alc882_dac_nids,
5298		.dig_out_nid = ALC882_DIGOUT_NID,
5299		.dig_in_nid = ALC882_DIGIN_NID,
5300		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
5301		.channel_mode = alc882_ch_modes,
5302		.need_dac_fix = 1,
5303		.input_mux = &alc882_capture_source,
5304	},
5305	[ALC882_6ST_DIG] = {
5306		.mixers = { alc882_base_mixer, alc882_chmode_mixer },
5307		.init_verbs = { alc882_init_verbs },
5308		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
5309		.dac_nids = alc882_dac_nids,
5310		.dig_out_nid = ALC882_DIGOUT_NID,
5311		.dig_in_nid = ALC882_DIGIN_NID,
5312		.num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
5313		.channel_mode = alc882_sixstack_modes,
5314		.input_mux = &alc882_capture_source,
5315	},
5316	[ALC882_ARIMA] = {
5317		.mixers = { alc882_base_mixer, alc882_chmode_mixer },
5318		.init_verbs = { alc882_init_verbs, alc882_eapd_verbs },
5319		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
5320		.dac_nids = alc882_dac_nids,
5321		.num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
5322		.channel_mode = alc882_sixstack_modes,
5323		.input_mux = &alc882_capture_source,
5324	},
5325	[ALC882_W2JC] = {
5326		.mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
5327		.init_verbs = { alc882_init_verbs, alc882_eapd_verbs,
5328				alc880_gpio1_init_verbs },
5329		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
5330		.dac_nids = alc882_dac_nids,
5331		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
5332		.channel_mode = alc880_threestack_modes,
5333		.need_dac_fix = 1,
5334		.input_mux = &alc882_capture_source,
5335		.dig_out_nid = ALC882_DIGOUT_NID,
5336	},
5337	[ALC885_MACPRO] = {
5338		.mixers = { alc882_macpro_mixer },
5339		.init_verbs = { alc882_macpro_init_verbs },
5340		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
5341		.dac_nids = alc882_dac_nids,
5342		.dig_out_nid = ALC882_DIGOUT_NID,
5343		.dig_in_nid = ALC882_DIGIN_NID,
5344		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
5345		.channel_mode = alc882_ch_modes,
5346		.input_mux = &alc882_capture_source,
5347	},
5348	[ALC882_TARGA] = {
5349		.mixers = { alc882_targa_mixer, alc882_chmode_mixer,
5350			    alc882_capture_mixer },
5351		.init_verbs = { alc882_init_verbs, alc882_targa_verbs},
5352		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
5353		.dac_nids = alc882_dac_nids,
5354		.dig_out_nid = ALC882_DIGOUT_NID,
5355		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
5356		.adc_nids = alc882_adc_nids,
5357		.num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
5358		.channel_mode = alc882_3ST_6ch_modes,
5359		.need_dac_fix = 1,
5360		.input_mux = &alc882_capture_source,
5361		.unsol_event = alc882_targa_unsol_event,
5362		.init_hook = alc882_targa_automute,
5363	},
5364	[ALC882_ASUS_A7J] = {
5365		.mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer,
5366			    alc882_capture_mixer },
5367		.init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs},
5368		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
5369		.dac_nids = alc882_dac_nids,
5370		.dig_out_nid = ALC882_DIGOUT_NID,
5371		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
5372		.adc_nids = alc882_adc_nids,
5373		.num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
5374		.channel_mode = alc882_3ST_6ch_modes,
5375		.need_dac_fix = 1,
5376		.input_mux = &alc882_capture_source,
5377	},
5378};
5379
5380
5381/*
5382 * BIOS auto configuration
5383 */
5384static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
5385					      hda_nid_t nid, int pin_type,
5386					      int dac_idx)
5387{
5388	/* set as output */
5389	struct alc_spec *spec = codec->spec;
5390	int idx;
5391
5392	if (spec->multiout.dac_nids[dac_idx] == 0x25)
5393		idx = 4;
5394	else
5395		idx = spec->multiout.dac_nids[dac_idx] - 2;
5396
5397	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5398			    pin_type);
5399	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
5400			    AMP_OUT_UNMUTE);
5401	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
5402
5403}
5404
5405static void alc882_auto_init_multi_out(struct hda_codec *codec)
5406{
5407	struct alc_spec *spec = codec->spec;
5408	int i;
5409
5410	alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
5411	for (i = 0; i <= HDA_SIDE; i++) {
5412		hda_nid_t nid = spec->autocfg.line_out_pins[i];
5413		int pin_type = get_pin_type(spec->autocfg.line_out_type);
5414		if (nid)
5415			alc882_auto_set_output_and_unmute(codec, nid, pin_type,
5416							  i);
5417	}
5418}
5419
5420static void alc882_auto_init_hp_out(struct hda_codec *codec)
5421{
5422	struct alc_spec *spec = codec->spec;
5423	hda_nid_t pin;
5424
5425	pin = spec->autocfg.hp_pins[0];
5426	if (pin) /* connect to front */
5427		/* use dac 0 */
5428		alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
5429}
5430
5431#define alc882_is_input_pin(nid)	alc880_is_input_pin(nid)
5432#define ALC882_PIN_CD_NID		ALC880_PIN_CD_NID
5433
5434static void alc882_auto_init_analog_input(struct hda_codec *codec)
5435{
5436	struct alc_spec *spec = codec->spec;
5437	int i;
5438
5439	for (i = 0; i < AUTO_PIN_LAST; i++) {
5440		hda_nid_t nid = spec->autocfg.input_pins[i];
5441		if (alc882_is_input_pin(nid)) {
5442			snd_hda_codec_write(codec, nid, 0,
5443					    AC_VERB_SET_PIN_WIDGET_CONTROL,
5444					    i <= AUTO_PIN_FRONT_MIC ?
5445					    PIN_VREF80 : PIN_IN);
5446			if (nid != ALC882_PIN_CD_NID)
5447				snd_hda_codec_write(codec, nid, 0,
5448						    AC_VERB_SET_AMP_GAIN_MUTE,
5449						    AMP_OUT_MUTE);
5450		}
5451	}
5452}
5453
5454/* almost identical with ALC880 parser... */
5455static int alc882_parse_auto_config(struct hda_codec *codec)
5456{
5457	struct alc_spec *spec = codec->spec;
5458	int err = alc880_parse_auto_config(codec);
5459
5460	if (err < 0)
5461		return err;
5462	else if (err > 0)
5463		/* hack - override the init verbs */
5464		spec->init_verbs[0] = alc882_auto_init_verbs;
5465	return err;
5466}
5467
5468/* additional initialization for auto-configuration model */
5469static void alc882_auto_init(struct hda_codec *codec)
5470{
5471	alc882_auto_init_multi_out(codec);
5472	alc882_auto_init_hp_out(codec);
5473	alc882_auto_init_analog_input(codec);
5474}
5475
5476static int patch_alc882(struct hda_codec *codec)
5477{
5478	struct alc_spec *spec;
5479	int err, board_config;
5480
5481	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5482	if (spec == NULL)
5483		return -ENOMEM;
5484
5485	codec->spec = spec;
5486
5487	board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
5488						  alc882_models,
5489						  alc882_cfg_tbl);
5490
5491	if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
5492		/* Pick up systems that don't supply PCI SSID */
5493		switch (codec->subsystem_id) {
5494		case 0x106b0c00: /* Mac Pro */
5495			board_config = ALC885_MACPRO;
5496			break;
5497		default:
5498			printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
5499		       			 "trying auto-probe from BIOS...\n");
5500			board_config = ALC882_AUTO;
5501		}
5502	}
5503
5504	if (board_config == ALC882_AUTO) {
5505		/* automatic parse from the BIOS config */
5506		err = alc882_parse_auto_config(codec);
5507		if (err < 0) {
5508			alc_free(codec);
5509			return err;
5510		} else if (!err) {
5511			printk(KERN_INFO
5512			       "hda_codec: Cannot set up configuration "
5513			       "from BIOS.  Using base mode...\n");
5514			board_config = ALC882_3ST_DIG;
5515		}
5516	}
5517
5518	if (board_config != ALC882_AUTO)
5519		setup_preset(spec, &alc882_presets[board_config]);
5520
5521	if (board_config == ALC885_MACPRO) {
5522		alc882_gpio_mute(codec, 0, 0);
5523		alc882_gpio_mute(codec, 1, 0);
5524	}
5525
5526	spec->stream_name_analog = "ALC882 Analog";
5527	spec->stream_analog_playback = &alc882_pcm_analog_playback;
5528	spec->stream_analog_capture = &alc882_pcm_analog_capture;
5529
5530	spec->stream_name_digital = "ALC882 Digital";
5531	spec->stream_digital_playback = &alc882_pcm_digital_playback;
5532	spec->stream_digital_capture = &alc882_pcm_digital_capture;
5533
5534	if (!spec->adc_nids && spec->input_mux) {
5535		/* check whether NID 0x07 is valid */
5536		unsigned int wcap = get_wcaps(codec, 0x07);
5537		/* get type */
5538		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
5539		if (wcap != AC_WID_AUD_IN) {
5540			spec->adc_nids = alc882_adc_nids_alt;
5541			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
5542			spec->mixers[spec->num_mixers] =
5543				alc882_capture_alt_mixer;
5544			spec->num_mixers++;
5545		} else {
5546			spec->adc_nids = alc882_adc_nids;
5547			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
5548			spec->mixers[spec->num_mixers] = alc882_capture_mixer;
5549			spec->num_mixers++;
5550		}
5551	}
5552
5553	codec->patch_ops = alc_patch_ops;
5554	if (board_config == ALC882_AUTO)
5555		spec->init_hook = alc882_auto_init;
5556
5557	return 0;
5558}
5559
5560/*
5561 * ALC883 support
5562 *
5563 * ALC883 is almost identical with ALC880 but has cleaner and more flexible
5564 * configuration.  Each pin widget can choose any input DACs and a mixer.
5565 * Each ADC is connected from a mixer of all inputs.  This makes possible
5566 * 6-channel independent captures.
5567 *
5568 * In addition, an independent DAC for the multi-playback (not used in this
5569 * driver yet).
5570 */
5571#define ALC883_DIGOUT_NID	0x06
5572#define ALC883_DIGIN_NID	0x0a
5573
5574static hda_nid_t alc883_dac_nids[4] = {
5575	/* front, rear, clfe, rear_surr */
5576	0x02, 0x04, 0x03, 0x05
5577};
5578
5579static hda_nid_t alc883_adc_nids[2] = {
5580	/* ADC1-2 */
5581	0x08, 0x09,
5582};
5583
5584/* input MUX */
5585/* FIXME: should be a matrix-type input source selection */
5586
5587static struct hda_input_mux alc883_capture_source = {
5588	.num_items = 4,
5589	.items = {
5590		{ "Mic", 0x0 },
5591		{ "Front Mic", 0x1 },
5592		{ "Line", 0x2 },
5593		{ "CD", 0x4 },
5594	},
5595};
5596
5597static struct hda_input_mux alc883_lenovo_101e_capture_source = {
5598	.num_items = 2,
5599	.items = {
5600		{ "Mic", 0x1 },
5601		{ "Line", 0x2 },
5602	},
5603};
5604
5605static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
5606	.num_items = 4,
5607	.items = {
5608		{ "Mic", 0x0 },
5609		{ "iMic", 0x1 },
5610		{ "Line", 0x2 },
5611		{ "CD", 0x4 },
5612	},
5613};
5614
5615#define alc883_mux_enum_info alc_mux_enum_info
5616#define alc883_mux_enum_get alc_mux_enum_get
5617
5618static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol,
5619			       struct snd_ctl_elem_value *ucontrol)
5620{
5621	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5622	struct alc_spec *spec = codec->spec;
5623	const struct hda_input_mux *imux = spec->input_mux;
5624	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
5625	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
5626	hda_nid_t nid = capture_mixers[adc_idx];
5627	unsigned int *cur_val = &spec->cur_mux[adc_idx];
5628	unsigned int i, idx;
5629
5630	idx = ucontrol->value.enumerated.item[0];
5631	if (idx >= imux->num_items)
5632		idx = imux->num_items - 1;
5633	if (*cur_val == idx && !codec->in_resume)
5634		return 0;
5635	for (i = 0; i < imux->num_items; i++) {
5636		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
5637		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
5638				    v | (imux->items[i].index << 8));
5639	}
5640	*cur_val = idx;
5641	return 1;
5642}
5643
5644/*
5645 * 2ch mode
5646 */
5647static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
5648	{ 2, NULL }
5649};
5650
5651/*
5652 * 2ch mode
5653 */
5654static struct hda_verb alc883_3ST_ch2_init[] = {
5655	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
5656	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
5657	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
5658	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
5659	{ } /* end */
5660};
5661
5662/*
5663 * 6ch mode
5664 */
5665static struct hda_verb alc883_3ST_ch6_init[] = {
5666	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5667	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
5668	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
5669	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5670	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
5671	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
5672	{ } /* end */
5673};
5674
5675static struct hda_channel_mode alc883_3ST_6ch_modes[2] = {
5676	{ 2, alc883_3ST_ch2_init },
5677	{ 6, alc883_3ST_ch6_init },
5678};
5679
5680/*
5681 * 6ch mode
5682 */
5683static struct hda_verb alc883_sixstack_ch6_init[] = {
5684	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
5685	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5686	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5687	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5688	{ } /* end */
5689};
5690
5691/*
5692 * 8ch mode
5693 */
5694static struct hda_verb alc883_sixstack_ch8_init[] = {
5695	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5696	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5697	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5698	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5699	{ } /* end */
5700};
5701
5702static struct hda_channel_mode alc883_sixstack_modes[2] = {
5703	{ 6, alc883_sixstack_ch6_init },
5704	{ 8, alc883_sixstack_ch8_init },
5705};
5706
5707static struct hda_verb alc883_medion_eapd_verbs[] = {
5708        /* eanable EAPD on medion laptop */
5709	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
5710	{0x20, AC_VERB_SET_PROC_COEF, 0x3070},
5711	{ }
5712};
5713
5714/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
5715 *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
5716 */
5717
5718static struct snd_kcontrol_new alc883_base_mixer[] = {
5719	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5720	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5721	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5722	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
5723	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5724	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5725	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
5726	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
5727	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
5728	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
5729	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5730	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5731	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5732	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5733	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5734	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5735	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5736	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5737	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5738	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
5739	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5740	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5741	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5742	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5743	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5744	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5745	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5746	{
5747		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5748		/* .name = "Capture Source", */
5749		.name = "Input Source",
5750		.count = 2,
5751		.info = alc883_mux_enum_info,
5752		.get = alc883_mux_enum_get,
5753		.put = alc883_mux_enum_put,
5754	},
5755	{ } /* end */
5756};
5757
5758static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
5759	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5760	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5761	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5762	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5763	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5764	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5765	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5766	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5767	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5768	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5769	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5770	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
5771	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5772	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5773	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5774	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5775	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5776	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5777	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5778	{
5779		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5780		/* .name = "Capture Source", */
5781		.name = "Input Source",
5782		.count = 2,
5783		.info = alc883_mux_enum_info,
5784		.get = alc883_mux_enum_get,
5785		.put = alc883_mux_enum_put,
5786	},
5787	{ } /* end */
5788};
5789
5790static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
5791	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5792	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5793	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5794	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
5795	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5796	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5797	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
5798	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
5799	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5800	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5801	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5802	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5803	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5804	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5805	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5806	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5807	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5808	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
5809	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5810	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5811	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5812	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5813	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5814	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5815	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5816	{
5817		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5818		/* .name = "Capture Source", */
5819		.name = "Input Source",
5820		.count = 2,
5821		.info = alc883_mux_enum_info,
5822		.get = alc883_mux_enum_get,
5823		.put = alc883_mux_enum_put,
5824	},
5825	{ } /* end */
5826};
5827
5828static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
5829	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5830	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5831	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5832	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
5833	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5834	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5835	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
5836	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
5837	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5838	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5839	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5840	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5841	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5842	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5843	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5844	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5845	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5846	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
5847	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5848	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5849	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5850	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5851	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5852
5853	{
5854		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5855		/* .name = "Capture Source", */
5856		.name = "Input Source",
5857		.count = 1,
5858		.info = alc883_mux_enum_info,
5859		.get = alc883_mux_enum_get,
5860		.put = alc883_mux_enum_put,
5861	},
5862	{ } /* end */
5863};
5864
5865static struct snd_kcontrol_new alc883_tagra_mixer[] = {
5866	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5867	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5868	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5869	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5870	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
5871	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5872	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5873	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
5874	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
5875	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5876	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5877	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5878	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5879	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5880	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5881	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5882	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5883	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5884	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5885	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5886	{
5887		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5888		/* .name = "Capture Source", */
5889		.name = "Input Source",
5890		.count = 2,
5891		.info = alc883_mux_enum_info,
5892		.get = alc883_mux_enum_get,
5893		.put = alc883_mux_enum_put,
5894	},
5895	{ } /* end */
5896};
5897
5898static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
5899	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5900	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5901	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5902	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5903	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5904	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5905	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5906	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5907	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5908	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5909	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5910	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5911	{
5912		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5913		/* .name = "Capture Source", */
5914		.name = "Input Source",
5915		.count = 2,
5916		.info = alc883_mux_enum_info,
5917		.get = alc883_mux_enum_get,
5918		.put = alc883_mux_enum_put,
5919	},
5920	{ } /* end */
5921};
5922
5923static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
5924	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5925	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5926	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5927	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
5928	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5929	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5930	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5931	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5932	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5933	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5934	{
5935		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5936		/* .name = "Capture Source", */
5937		.name = "Input Source",
5938		.count = 1,
5939		.info = alc883_mux_enum_info,
5940		.get = alc883_mux_enum_get,
5941		.put = alc883_mux_enum_put,
5942	},
5943	{ } /* end */
5944};
5945
5946static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
5947	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5948	HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
5949	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5950	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5951	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5952	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5953	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5954	HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5955	HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5956	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5957	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5958	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5959	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5960	{
5961		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5962		/* .name = "Capture Source", */
5963		.name = "Input Source",
5964		.count = 2,
5965		.info = alc883_mux_enum_info,
5966		.get = alc883_mux_enum_get,
5967		.put = alc883_mux_enum_put,
5968	},
5969	{ } /* end */
5970};
5971
5972static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
5973	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5974	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5975	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
5976	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5977	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5978	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5979	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5980	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5981	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5982	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5983	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5984	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5985	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5986	{
5987		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5988		/* .name = "Capture Source", */
5989		.name = "Input Source",
5990		.count = 2,
5991		.info = alc883_mux_enum_info,
5992		.get = alc883_mux_enum_get,
5993		.put = alc883_mux_enum_put,
5994	},
5995	{ } /* end */
5996};
5997
5998static struct snd_kcontrol_new alc883_chmode_mixer[] = {
5999	{
6000		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6001		.name = "Channel Mode",
6002		.info = alc_ch_mode_info,
6003		.get = alc_ch_mode_get,
6004		.put = alc_ch_mode_put,
6005	},
6006	{ } /* end */
6007};
6008
6009static struct hda_verb alc883_init_verbs[] = {
6010	/* ADC1: mute amp left and right */
6011	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6012	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
6013	/* ADC2: mute amp left and right */
6014	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6015	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
6016	/* Front mixer: unmute input/output amp left and right (volume = 0) */
6017	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6018	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6019	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6020	/* Rear mixer */
6021	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6022	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6023	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6024	/* CLFE mixer */
6025	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6026	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6027	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6028	/* Side mixer */
6029	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6030	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6031	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6032
6033	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6034	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6035	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6036	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
6037	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6038
6039	/* Front Pin: output 0 (0x0c) */
6040	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6041	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6042	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
6043	/* Rear Pin: output 1 (0x0d) */
6044	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6045	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6046	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
6047	/* CLFE Pin: output 2 (0x0e) */
6048	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6049	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6050	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
6051	/* Side Pin: output 3 (0x0f) */
6052	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6053	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6054	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
6055	/* Mic (rear) pin: input vref at 80% */
6056	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
6057	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
6058	/* Front Mic pin: input vref at 80% */
6059	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
6060	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
6061	/* Line In pin: input */
6062	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6063	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
6064	/* Line-2 In: Headphone output (output 0 - 0x0c) */
6065	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6066	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6067	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
6068	/* CD pin widget for input */
6069	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6070
6071	/* FIXME: use matrix-type input source selection */
6072	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
6073	/* Input mixer2 */
6074	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6075	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6076	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6077	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6078	/* Input mixer3 */
6079	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6080	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6081	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6082	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6083	{ }
6084};
6085
6086static struct hda_verb alc883_tagra_verbs[] = {
6087	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6088	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6089
6090	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6091	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6092
6093	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
6094	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
6095	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
6096
6097	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
6098	{0x01, AC_VERB_SET_GPIO_MASK, 0x03},
6099	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
6100	{0x01, AC_VERB_SET_GPIO_DATA, 0x03},
6101
6102	{ } /* end */
6103};
6104
6105static struct hda_verb alc883_lenovo_101e_verbs[] = {
6106	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
6107	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},
6108        {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},
6109	{ } /* end */
6110};
6111
6112static struct hda_verb alc883_lenovo_nb0763_verbs[] = {
6113        {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
6114	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6115        {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
6116        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6117	{ } /* end */
6118};
6119
6120static struct hda_verb alc888_lenovo_ms7195_verbs[] = {
6121	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6122	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6123	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
6124	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN},
6125	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT    | AC_USRSP_EN},
6126	{ } /* end */
6127};
6128
6129/* toggle front-jack and RCA according to the hp-jack state */
6130static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
6131{
6132 	unsigned int present;
6133
6134 	present = snd_hda_codec_read(codec, 0x1b, 0,
6135				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
6136	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6137				 0x80, present ? 0x80 : 0);
6138	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6139				 0x80, present ? 0x80 : 0);
6140	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
6141				 0x80, present ? 0x80 : 0);
6142	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
6143				 0x80, present ? 0x80 : 0);
6144
6145}
6146
6147/* toggle RCA according to the front-jack state */
6148static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
6149{
6150 	unsigned int present;
6151
6152 	present = snd_hda_codec_read(codec, 0x14, 0,
6153				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
6154	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
6155				 0x80, present ? 0x80 : 0);
6156	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
6157				 0x80, present ? 0x80 : 0);
6158
6159}
6160static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,
6161					     unsigned int res)
6162{
6163	if ((res >> 26) == ALC880_HP_EVENT)
6164		alc888_lenovo_ms7195_front_automute(codec);
6165	if ((res >> 26) == ALC880_FRONT_EVENT)
6166		alc888_lenovo_ms7195_rca_automute(codec);
6167}
6168
6169static struct hda_verb alc883_medion_md2_verbs[] = {
6170	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6171	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6172
6173	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6174
6175	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
6176	{ } /* end */
6177};
6178
6179/* toggle speaker-output according to the hp-jack state */
6180static void alc883_medion_md2_automute(struct hda_codec *codec)
6181{
6182 	unsigned int present;
6183
6184 	present = snd_hda_codec_read(codec, 0x14, 0,
6185				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
6186	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
6187				 0x80, present ? 0x80 : 0);
6188	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
6189				 0x80, present ? 0x80 : 0);
6190}
6191
6192static void alc883_medion_md2_unsol_event(struct hda_codec *codec,
6193					  unsigned int res)
6194{
6195	if ((res >> 26) == ALC880_HP_EVENT)
6196		alc883_medion_md2_automute(codec);
6197}
6198
6199/* toggle speaker-output according to the hp-jack state */
6200static void alc883_tagra_automute(struct hda_codec *codec)
6201{
6202 	unsigned int present;
6203	unsigned char bits;
6204
6205 	present = snd_hda_codec_read(codec, 0x14, 0,
6206				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
6207	bits = present ? 0x80 : 0;
6208	snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
6209				 0x80, bits);
6210	snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
6211				 0x80, bits);
6212	snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
6213			    present ? 1 : 3);
6214}
6215
6216static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
6217{
6218	if ((res >> 26) == ALC880_HP_EVENT)
6219		alc883_tagra_automute(codec);
6220}
6221
6222static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
6223{
6224 	unsigned int present;
6225	unsigned char bits;
6226
6227 	present = snd_hda_codec_read(codec, 0x14, 0,
6228				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
6229	bits = present ? 0x80 : 0;
6230	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
6231				 0x80, bits);
6232	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
6233				 0x80, bits);
6234}
6235
6236static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
6237{
6238 	unsigned int present;
6239	unsigned char bits;
6240
6241 	present = snd_hda_codec_read(codec, 0x1b, 0,
6242				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
6243	bits = present ? 0x80 : 0;
6244	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
6245				 0x80, bits);
6246	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
6247				 0x80, bits);
6248	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6249				 0x80, bits);
6250	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6251				 0x80, bits);
6252}
6253
6254static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
6255					   unsigned int res)
6256{
6257	if ((res >> 26) == ALC880_HP_EVENT)
6258		alc883_lenovo_101e_all_automute(codec);
6259	if ((res >> 26) == ALC880_FRONT_EVENT)
6260		alc883_lenovo_101e_ispeaker_automute(codec);
6261}
6262
6263/*
6264 * generic initialization of ADC, input mixers and output mixers
6265 */
6266static struct hda_verb alc883_auto_init_verbs[] = {
6267	/*
6268	 * Unmute ADC0-2 and set the default input to mic-in
6269	 */
6270	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
6271	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6272	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
6273	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6274
6275	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
6276	 * mixer widget
6277	 * Note: PASD motherboards uses the Line In 2 as the input for
6278	 * front panel mic (mic 2)
6279	 */
6280	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
6281	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6282	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6283	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6284	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
6285	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6286
6287	/*
6288	 * Set up output mixers (0x0c - 0x0f)
6289	 */
6290	/* set vol=0 to output mixers */
6291	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6292	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6293	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6294	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6295	/* set up input amps for analog loopback */
6296	/* Amp Indices: DAC = 0, mixer = 1 */
6297	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6298	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6299	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6300	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6301	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6302	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6303	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6304	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6305	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6306	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6307
6308	/* FIXME: use matrix-type input source selection */
6309	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
6310	/* Input mixer1 */
6311	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6312	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6313	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6314	/* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */
6315	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6316	/* Input mixer2 */
6317	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6318	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6319	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6320	/* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */
6321	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6322
6323	{ }
6324};
6325
6326/* capture mixer elements */
6327static struct snd_kcontrol_new alc883_capture_mixer[] = {
6328	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
6329	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
6330	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
6331	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
6332	{
6333		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6334		/* The multiple "Capture Source" controls confuse alsamixer
6335		 * So call somewhat different..
6336		 * FIXME: the controls appear in the "playback" view!
6337		 */
6338		/* .name = "Capture Source", */
6339		.name = "Input Source",
6340		.count = 2,
6341		.info = alc882_mux_enum_info,
6342		.get = alc882_mux_enum_get,
6343		.put = alc882_mux_enum_put,
6344	},
6345	{ } /* end */
6346};
6347
6348/* pcm configuration: identiacal with ALC880 */
6349#define alc883_pcm_analog_playback	alc880_pcm_analog_playback
6350#define alc883_pcm_analog_capture	alc880_pcm_analog_capture
6351#define alc883_pcm_digital_playback	alc880_pcm_digital_playback
6352#define alc883_pcm_digital_capture	alc880_pcm_digital_capture
6353
6354/*
6355 * configuration and preset
6356 */
6357static const char *alc883_models[ALC883_MODEL_LAST] = {
6358	[ALC883_3ST_2ch_DIG]	= "3stack-dig",
6359	[ALC883_3ST_6ch_DIG]	= "3stack-6ch-dig",
6360	[ALC883_3ST_6ch]	= "3stack-6ch",
6361	[ALC883_6ST_DIG]	= "6stack-dig",
6362	[ALC883_TARGA_DIG]	= "targa-dig",
6363	[ALC883_TARGA_2ch_DIG]	= "targa-2ch-dig",
6364	[ALC883_ACER]		= "acer",
6365	[ALC883_MEDION]		= "medion",
6366	[ALC883_MEDION_MD2]	= "medion-md2",
6367	[ALC883_LAPTOP_EAPD]	= "laptop-eapd",
6368	[ALC883_LENOVO_101E_2ch] = "lenovo-101e",
6369	[ALC883_LENOVO_NB0763]	= "lenovo-nb0763",
6370	[ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
6371	[ALC883_AUTO]		= "auto",
6372};
6373
6374static struct snd_pci_quirk alc883_cfg_tbl[] = {
6375	SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),
6376	SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
6377	SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
6378	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
6379	SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG),
6380	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
6381	SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
6382	SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
6383	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
6384	SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
6385	SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
6386	SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
6387	SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
6388	SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
6389	SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
6390	SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
6391	SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
6392	SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
6393	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
6394	SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER),
6395	SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
6396	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
6397	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
6398	SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
6399	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
6400	SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
6401	SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
6402	SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
6403	{}
6404};
6405
6406static struct alc_config_preset alc883_presets[] = {
6407	[ALC883_3ST_2ch_DIG] = {
6408		.mixers = { alc883_3ST_2ch_mixer },
6409		.init_verbs = { alc883_init_verbs },
6410		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6411		.dac_nids = alc883_dac_nids,
6412		.dig_out_nid = ALC883_DIGOUT_NID,
6413		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6414		.adc_nids = alc883_adc_nids,
6415		.dig_in_nid = ALC883_DIGIN_NID,
6416		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6417		.channel_mode = alc883_3ST_2ch_modes,
6418		.input_mux = &alc883_capture_source,
6419	},
6420	[ALC883_3ST_6ch_DIG] = {
6421		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
6422		.init_verbs = { alc883_init_verbs },
6423		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6424		.dac_nids = alc883_dac_nids,
6425		.dig_out_nid = ALC883_DIGOUT_NID,
6426		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6427		.adc_nids = alc883_adc_nids,
6428		.dig_in_nid = ALC883_DIGIN_NID,
6429		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
6430		.channel_mode = alc883_3ST_6ch_modes,
6431		.need_dac_fix = 1,
6432		.input_mux = &alc883_capture_source,
6433	},
6434	[ALC883_3ST_6ch] = {
6435		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
6436		.init_verbs = { alc883_init_verbs },
6437		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6438		.dac_nids = alc883_dac_nids,
6439		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6440		.adc_nids = alc883_adc_nids,
6441		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
6442		.channel_mode = alc883_3ST_6ch_modes,
6443		.need_dac_fix = 1,
6444		.input_mux = &alc883_capture_source,
6445	},
6446	[ALC883_6ST_DIG] = {
6447		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
6448		.init_verbs = { alc883_init_verbs },
6449		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6450		.dac_nids = alc883_dac_nids,
6451		.dig_out_nid = ALC883_DIGOUT_NID,
6452		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6453		.adc_nids = alc883_adc_nids,
6454		.dig_in_nid = ALC883_DIGIN_NID,
6455		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
6456		.channel_mode = alc883_sixstack_modes,
6457		.input_mux = &alc883_capture_source,
6458	},
6459	[ALC883_TARGA_DIG] = {
6460		.mixers = { alc883_tagra_mixer, alc883_chmode_mixer },
6461		.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
6462		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6463		.dac_nids = alc883_dac_nids,
6464		.dig_out_nid = ALC883_DIGOUT_NID,
6465		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6466		.adc_nids = alc883_adc_nids,
6467		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
6468		.channel_mode = alc883_3ST_6ch_modes,
6469		.need_dac_fix = 1,
6470		.input_mux = &alc883_capture_source,
6471		.unsol_event = alc883_tagra_unsol_event,
6472		.init_hook = alc883_tagra_automute,
6473	},
6474	[ALC883_TARGA_2ch_DIG] = {
6475		.mixers = { alc883_tagra_2ch_mixer},
6476		.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
6477		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6478		.dac_nids = alc883_dac_nids,
6479		.dig_out_nid = ALC883_DIGOUT_NID,
6480		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6481		.adc_nids = alc883_adc_nids,
6482		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6483		.channel_mode = alc883_3ST_2ch_modes,
6484		.input_mux = &alc883_capture_source,
6485		.unsol_event = alc883_tagra_unsol_event,
6486		.init_hook = alc883_tagra_automute,
6487	},
6488	[ALC883_ACER] = {
6489		.mixers = { alc883_base_mixer,
6490			    alc883_chmode_mixer },
6491		/* On TravelMate laptops, GPIO 0 enables the internal speaker
6492		 * and the headphone jack.  Turn this on and rely on the
6493		 * standard mute methods whenever the user wants to turn
6494		 * these outputs off.
6495		 */
6496		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
6497		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6498		.dac_nids = alc883_dac_nids,
6499		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6500		.adc_nids = alc883_adc_nids,
6501		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6502		.channel_mode = alc883_3ST_2ch_modes,
6503		.input_mux = &alc883_capture_source,
6504	},
6505	[ALC883_MEDION] = {
6506		.mixers = { alc883_fivestack_mixer,
6507			    alc883_chmode_mixer },
6508		.init_verbs = { alc883_init_verbs,
6509				alc883_medion_eapd_verbs },
6510		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6511		.dac_nids = alc883_dac_nids,
6512		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6513		.adc_nids = alc883_adc_nids,
6514		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
6515		.channel_mode = alc883_sixstack_modes,
6516		.input_mux = &alc883_capture_source,
6517	},
6518	[ALC883_MEDION_MD2] = {
6519		.mixers = { alc883_medion_md2_mixer},
6520		.init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs},
6521		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6522		.dac_nids = alc883_dac_nids,
6523		.dig_out_nid = ALC883_DIGOUT_NID,
6524		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6525		.adc_nids = alc883_adc_nids,
6526		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6527		.channel_mode = alc883_3ST_2ch_modes,
6528		.input_mux = &alc883_capture_source,
6529		.unsol_event = alc883_medion_md2_unsol_event,
6530		.init_hook = alc883_medion_md2_automute,
6531	},
6532	[ALC883_LAPTOP_EAPD] = {
6533		.mixers = { alc883_base_mixer,
6534			    alc883_chmode_mixer },
6535		.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
6536		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6537		.dac_nids = alc883_dac_nids,
6538		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6539		.adc_nids = alc883_adc_nids,
6540		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6541		.channel_mode = alc883_3ST_2ch_modes,
6542		.input_mux = &alc883_capture_source,
6543	},
6544	[ALC883_LENOVO_101E_2ch] = {
6545		.mixers = { alc883_lenovo_101e_2ch_mixer},
6546		.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
6547		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6548		.dac_nids = alc883_dac_nids,
6549		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6550		.adc_nids = alc883_adc_nids,
6551		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6552		.channel_mode = alc883_3ST_2ch_modes,
6553		.input_mux = &alc883_lenovo_101e_capture_source,
6554		.unsol_event = alc883_lenovo_101e_unsol_event,
6555		.init_hook = alc883_lenovo_101e_all_automute,
6556	},
6557	[ALC883_LENOVO_NB0763] = {
6558		.mixers = { alc883_lenovo_nb0763_mixer },
6559		.init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
6560		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6561		.dac_nids = alc883_dac_nids,
6562		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6563		.adc_nids = alc883_adc_nids,
6564		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6565		.channel_mode = alc883_3ST_2ch_modes,
6566		.need_dac_fix = 1,
6567		.input_mux = &alc883_lenovo_nb0763_capture_source,
6568		.unsol_event = alc883_medion_md2_unsol_event,
6569		.init_hook = alc883_medion_md2_automute,
6570	},
6571	[ALC888_LENOVO_MS7195_DIG] = {
6572		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
6573		.init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
6574		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6575		.dac_nids = alc883_dac_nids,
6576		.dig_out_nid = ALC883_DIGOUT_NID,
6577		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6578		.adc_nids = alc883_adc_nids,
6579		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
6580		.channel_mode = alc883_3ST_6ch_modes,
6581		.need_dac_fix = 1,
6582		.input_mux = &alc883_capture_source,
6583		.unsol_event = alc883_lenovo_ms7195_unsol_event,
6584		.init_hook = alc888_lenovo_ms7195_front_automute,
6585	},
6586};
6587
6588
6589/*
6590 * BIOS auto configuration
6591 */
6592static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
6593					      hda_nid_t nid, int pin_type,
6594					      int dac_idx)
6595{
6596	/* set as output */
6597	struct alc_spec *spec = codec->spec;
6598	int idx;
6599
6600	if (spec->multiout.dac_nids[dac_idx] == 0x25)
6601		idx = 4;
6602	else
6603		idx = spec->multiout.dac_nids[dac_idx] - 2;
6604
6605	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
6606			    pin_type);
6607	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
6608			    AMP_OUT_UNMUTE);
6609	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
6610
6611}
6612
6613static void alc883_auto_init_multi_out(struct hda_codec *codec)
6614{
6615	struct alc_spec *spec = codec->spec;
6616	int i;
6617
6618	alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
6619	for (i = 0; i <= HDA_SIDE; i++) {
6620		hda_nid_t nid = spec->autocfg.line_out_pins[i];
6621		int pin_type = get_pin_type(spec->autocfg.line_out_type);
6622		if (nid)
6623			alc883_auto_set_output_and_unmute(codec, nid, pin_type,
6624							  i);
6625	}
6626}
6627
6628static void alc883_auto_init_hp_out(struct hda_codec *codec)
6629{
6630	struct alc_spec *spec = codec->spec;
6631	hda_nid_t pin;
6632
6633	pin = spec->autocfg.hp_pins[0];
6634	if (pin) /* connect to front */
6635		/* use dac 0 */
6636		alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
6637}
6638
6639#define alc883_is_input_pin(nid)	alc880_is_input_pin(nid)
6640#define ALC883_PIN_CD_NID		ALC880_PIN_CD_NID
6641
6642static void alc883_auto_init_analog_input(struct hda_codec *codec)
6643{
6644	struct alc_spec *spec = codec->spec;
6645	int i;
6646
6647	for (i = 0; i < AUTO_PIN_LAST; i++) {
6648		hda_nid_t nid = spec->autocfg.input_pins[i];
6649		if (alc883_is_input_pin(nid)) {
6650			snd_hda_codec_write(codec, nid, 0,
6651					    AC_VERB_SET_PIN_WIDGET_CONTROL,
6652					    (i <= AUTO_PIN_FRONT_MIC ?
6653					     PIN_VREF80 : PIN_IN));
6654			if (nid != ALC883_PIN_CD_NID)
6655				snd_hda_codec_write(codec, nid, 0,
6656						    AC_VERB_SET_AMP_GAIN_MUTE,
6657						    AMP_OUT_MUTE);
6658		}
6659	}
6660}
6661
6662/* almost identical with ALC880 parser... */
6663static int alc883_parse_auto_config(struct hda_codec *codec)
6664{
6665	struct alc_spec *spec = codec->spec;
6666	int err = alc880_parse_auto_config(codec);
6667
6668	if (err < 0)
6669		return err;
6670	else if (err > 0)
6671		/* hack - override the init verbs */
6672		spec->init_verbs[0] = alc883_auto_init_verbs;
6673	spec->mixers[spec->num_mixers] = alc883_capture_mixer;
6674	spec->num_mixers++;
6675	return err;
6676}
6677
6678/* additional initialization for auto-configuration model */
6679static void alc883_auto_init(struct hda_codec *codec)
6680{
6681	alc883_auto_init_multi_out(codec);
6682	alc883_auto_init_hp_out(codec);
6683	alc883_auto_init_analog_input(codec);
6684}
6685
6686static int patch_alc883(struct hda_codec *codec)
6687{
6688	struct alc_spec *spec;
6689	int err, board_config;
6690
6691	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6692	if (spec == NULL)
6693		return -ENOMEM;
6694
6695	codec->spec = spec;
6696
6697	board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,
6698						  alc883_models,
6699						  alc883_cfg_tbl);
6700	if (board_config < 0) {
6701		printk(KERN_INFO "hda_codec: Unknown model for ALC883, "
6702		       "trying auto-probe from BIOS...\n");
6703		board_config = ALC883_AUTO;
6704	}
6705
6706	if (board_config == ALC883_AUTO) {
6707		/* automatic parse from the BIOS config */
6708		err = alc883_parse_auto_config(codec);
6709		if (err < 0) {
6710			alc_free(codec);
6711			return err;
6712		} else if (!err) {
6713			printk(KERN_INFO
6714			       "hda_codec: Cannot set up configuration "
6715			       "from BIOS.  Using base mode...\n");
6716			board_config = ALC883_3ST_2ch_DIG;
6717		}
6718	}
6719
6720	if (board_config != ALC883_AUTO)
6721		setup_preset(spec, &alc883_presets[board_config]);
6722
6723	spec->stream_name_analog = "ALC883 Analog";
6724	spec->stream_analog_playback = &alc883_pcm_analog_playback;
6725	spec->stream_analog_capture = &alc883_pcm_analog_capture;
6726
6727	spec->stream_name_digital = "ALC883 Digital";
6728	spec->stream_digital_playback = &alc883_pcm_digital_playback;
6729	spec->stream_digital_capture = &alc883_pcm_digital_capture;
6730
6731	if (!spec->adc_nids && spec->input_mux) {
6732		spec->adc_nids = alc883_adc_nids;
6733		spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
6734	}
6735
6736	codec->patch_ops = alc_patch_ops;
6737	if (board_config == ALC883_AUTO)
6738		spec->init_hook = alc883_auto_init;
6739
6740	return 0;
6741}
6742
6743/*
6744 * ALC262 support
6745 */
6746
6747#define ALC262_DIGOUT_NID	ALC880_DIGOUT_NID
6748#define ALC262_DIGIN_NID	ALC880_DIGIN_NID
6749
6750#define alc262_dac_nids		alc260_dac_nids
6751#define alc262_adc_nids		alc882_adc_nids
6752#define alc262_adc_nids_alt	alc882_adc_nids_alt
6753
6754#define alc262_modes		alc260_modes
6755#define alc262_capture_source	alc882_capture_source
6756
6757static struct snd_kcontrol_new alc262_base_mixer[] = {
6758	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6759	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
6760	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
6761	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
6762	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
6763	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
6764	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6765	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6766	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
6767	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
6768	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
6769	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
6770	/* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
6771	   HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
6772	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
6773	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6774	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
6775	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
6776	{ } /* end */
6777};
6778
6779static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
6780	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6781	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
6782	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
6783	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
6784	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
6785	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
6786	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6787	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6788	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
6789	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
6790	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
6791	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
6792	/* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
6793	   HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
6794	/*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
6795	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
6796	{ } /* end */
6797};
6798
6799static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
6800	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6801	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6802	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
6803	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
6804	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
6805
6806	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6807	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6808	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
6809	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
6810	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
6811	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
6812	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
6813	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
6814	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
6815	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
6816	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
6817	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
6818	HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
6819	HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
6820	{ } /* end */
6821};
6822
6823static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
6824	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6825	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
6826	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
6827	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6828	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
6829	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
6830	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
6831	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
6832	HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT),
6833	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
6834	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
6835	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
6836	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
6837	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
6838	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
6839	{ } /* end */
6840};
6841
6842static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
6843	HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6844	HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6845	HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT),
6846	{ } /* end */
6847};
6848
6849static struct snd_kcontrol_new alc262_sony_mixer[] = {
6850	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6851	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6852	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6853	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6854	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
6855	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
6856	{ } /* end */
6857};
6858
6859
6860
6861#define alc262_capture_mixer		alc882_capture_mixer
6862#define alc262_capture_alt_mixer	alc882_capture_alt_mixer
6863
6864/*
6865 * generic initialization of ADC, input mixers and output mixers
6866 */
6867static struct hda_verb alc262_init_verbs[] = {
6868	/*
6869	 * Unmute ADC0-2 and set the default input to mic-in
6870	 */
6871	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
6872	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6873	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
6874	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6875	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
6876	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6877
6878	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
6879	 * mixer widget
6880	 * Note: PASD motherboards uses the Line In 2 as the input for
6881	 * front panel mic (mic 2)
6882	 */
6883	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
6884	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6885	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6886	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6887	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
6888	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6889
6890	/*
6891	 * Set up output mixers (0x0c - 0x0e)
6892	 */
6893	/* set vol=0 to output mixers */
6894	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6895	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6896	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6897	/* set up input amps for analog loopback */
6898	/* Amp Indices: DAC = 0, mixer = 1 */
6899	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6900	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6901	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6902	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6903	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6904	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6905
6906	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6907	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6908	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6909	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6910	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6911	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6912
6913	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6914	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6915	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6916	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6917	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6918
6919	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
6920	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
6921
6922	/* FIXME: use matrix-type input source selection */
6923	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
6924	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
6925	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6926	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6927	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6928	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6929	/* Input mixer2 */
6930	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6931	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6932	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6933	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6934	/* Input mixer3 */
6935	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6936	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6937	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6938	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6939
6940	{ }
6941};
6942
6943static struct hda_verb alc262_hippo_unsol_verbs[] = {
6944	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6945	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6946	{}
6947};
6948
6949static struct hda_verb alc262_hippo1_unsol_verbs[] = {
6950	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6951	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
6952	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6953
6954	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6955	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6956	{}
6957};
6958
6959static struct hda_verb alc262_sony_unsol_verbs[] = {
6960	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6961	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
6962	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},	// Front Mic
6963
6964	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6965	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6966};
6967
6968/* mute/unmute internal speaker according to the hp jack and mute state */
6969static void alc262_hippo_automute(struct hda_codec *codec, int force)
6970{
6971	struct alc_spec *spec = codec->spec;
6972	unsigned int mute;
6973
6974	if (force || !spec->sense_updated) {
6975		unsigned int present;
6976		/* need to execute and sync at first */
6977		snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
6978		present = snd_hda_codec_read(codec, 0x15, 0,
6979				    	 AC_VERB_GET_PIN_SENSE, 0);
6980		spec->jack_present = (present & 0x80000000) != 0;
6981		spec->sense_updated = 1;
6982	}
6983	if (spec->jack_present) {
6984		/* mute internal speaker */
6985		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6986					 0x80, 0x80);
6987		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6988					 0x80, 0x80);
6989	} else {
6990		/* unmute internal speaker if necessary */
6991		mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
6992		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6993					 0x80, mute & 0x80);
6994		mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0);
6995		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6996					 0x80, mute & 0x80);
6997	}
6998}
6999
7000/* unsolicited event for HP jack sensing */
7001static void alc262_hippo_unsol_event(struct hda_codec *codec,
7002				       unsigned int res)
7003{
7004	if ((res >> 26) != ALC880_HP_EVENT)
7005		return;
7006	alc262_hippo_automute(codec, 1);
7007}
7008
7009static void alc262_hippo1_automute(struct hda_codec *codec, int force)
7010{
7011	struct alc_spec *spec = codec->spec;
7012	unsigned int mute;
7013
7014	if (force || !spec->sense_updated) {
7015		unsigned int present;
7016		/* need to execute and sync at first */
7017		snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
7018		present = snd_hda_codec_read(codec, 0x1b, 0,
7019				    	 AC_VERB_GET_PIN_SENSE, 0);
7020		spec->jack_present = (present & 0x80000000) != 0;
7021		spec->sense_updated = 1;
7022	}
7023	if (spec->jack_present) {
7024		/* mute internal speaker */
7025		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
7026					 0x80, 0x80);
7027		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
7028					 0x80, 0x80);
7029	} else {
7030		/* unmute internal speaker if necessary */
7031		mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
7032		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
7033					 0x80, mute & 0x80);
7034		mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0);
7035		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
7036					 0x80, mute & 0x80);
7037	}
7038}
7039
7040/* unsolicited event for HP jack sensing */
7041static void alc262_hippo1_unsol_event(struct hda_codec *codec,
7042				       unsigned int res)
7043{
7044	if ((res >> 26) != ALC880_HP_EVENT)
7045		return;
7046	alc262_hippo1_automute(codec, 1);
7047}
7048
7049/*
7050 * fujitsu model
7051 *  0x14 = headphone/spdif-out, 0x15 = internal speaker
7052 */
7053
7054#define ALC_HP_EVENT	0x37
7055
7056static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
7057	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
7058	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7059	{}
7060};
7061
7062static struct hda_input_mux alc262_fujitsu_capture_source = {
7063	.num_items = 2,
7064	.items = {
7065		{ "Mic", 0x0 },
7066		{ "CD", 0x4 },
7067	},
7068};
7069
7070static struct hda_input_mux alc262_HP_capture_source = {
7071	.num_items = 5,
7072	.items = {
7073		{ "Mic", 0x0 },
7074		{ "Front Mic", 0x3 },
7075		{ "Line", 0x2 },
7076		{ "CD", 0x4 },
7077		{ "AUX IN", 0x6 },
7078	},
7079};
7080
7081/* mute/unmute internal speaker according to the hp jack and mute state */
7082static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
7083{
7084	struct alc_spec *spec = codec->spec;
7085	unsigned int mute;
7086
7087	if (force || !spec->sense_updated) {
7088		unsigned int present;
7089		/* need to execute and sync at first */
7090		snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
7091		present = snd_hda_codec_read(codec, 0x14, 0,
7092				    	 AC_VERB_GET_PIN_SENSE, 0);
7093		spec->jack_present = (present & 0x80000000) != 0;
7094		spec->sense_updated = 1;
7095	}
7096	if (spec->jack_present) {
7097		/* mute internal speaker */
7098		snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
7099					 0x80, 0x80);
7100		snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
7101					 0x80, 0x80);
7102	} else {
7103		/* unmute internal speaker if necessary */
7104		mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
7105		snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
7106					 0x80, mute & 0x80);
7107		mute = snd_hda_codec_amp_read(codec, 0x14, 1, HDA_OUTPUT, 0);
7108		snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
7109					 0x80, mute & 0x80);
7110	}
7111}
7112
7113/* unsolicited event for HP jack sensing */
7114static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
7115				       unsigned int res)
7116{
7117	if ((res >> 26) != ALC_HP_EVENT)
7118		return;
7119	alc262_fujitsu_automute(codec, 1);
7120}
7121
7122/* bind volumes of both NID 0x0c and 0x0d */
7123static int alc262_fujitsu_master_vol_put(struct snd_kcontrol *kcontrol,
7124					 struct snd_ctl_elem_value *ucontrol)
7125{
7126	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
7127	long *valp = ucontrol->value.integer.value;
7128	int change;
7129
7130	change = snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
7131					  0x7f, valp[0] & 0x7f);
7132	change |= snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
7133					   0x7f, valp[1] & 0x7f);
7134	snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
7135				 0x7f, valp[0] & 0x7f);
7136	snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
7137				 0x7f, valp[1] & 0x7f);
7138	return change;
7139}
7140
7141/* bind hp and internal speaker mute (with plug check) */
7142static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
7143					 struct snd_ctl_elem_value *ucontrol)
7144{
7145	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
7146	long *valp = ucontrol->value.integer.value;
7147	int change;
7148
7149	change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
7150					  0x80, valp[0] ? 0 : 0x80);
7151	change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
7152					   0x80, valp[1] ? 0 : 0x80);
7153	if (change || codec->in_resume)
7154		alc262_fujitsu_automute(codec, codec->in_resume);
7155	return change;
7156}
7157
7158static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
7159	{
7160		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7161		.name = "Master Playback Volume",
7162		.info = snd_hda_mixer_amp_volume_info,
7163		.get = snd_hda_mixer_amp_volume_get,
7164		.put = alc262_fujitsu_master_vol_put,
7165		.tlv = { .c = snd_hda_mixer_amp_tlv },
7166		.private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
7167	},
7168	{
7169		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7170		.name = "Master Playback Switch",
7171		.info = snd_hda_mixer_amp_switch_info,
7172		.get = snd_hda_mixer_amp_switch_get,
7173		.put = alc262_fujitsu_master_sw_put,
7174		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
7175	},
7176	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7177	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7178	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7179	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7180	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7181	{ } /* end */
7182};
7183
7184/* additional init verbs for Benq laptops */
7185static struct hda_verb alc262_EAPD_verbs[] = {
7186	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
7187	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
7188	{}
7189};
7190
7191/* add playback controls from the parsed DAC table */
7192static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
7193					     const struct auto_pin_cfg *cfg)
7194{
7195	hda_nid_t nid;
7196	int err;
7197
7198	spec->multiout.num_dacs = 1;	/* only use one dac */
7199	spec->multiout.dac_nids = spec->private_dac_nids;
7200	spec->multiout.dac_nids[0] = 2;
7201
7202	nid = cfg->line_out_pins[0];
7203	if (nid) {
7204		err = add_control(spec, ALC_CTL_WIDGET_VOL,
7205				  "Front Playback Volume",
7206				  HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT));
7207		if (err < 0)
7208			return err;
7209		err = add_control(spec, ALC_CTL_WIDGET_MUTE,
7210				  "Front Playback Switch",
7211				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
7212		if (err < 0)
7213			return err;
7214	}
7215
7216	nid = cfg->speaker_pins[0];
7217	if (nid) {
7218		if (nid == 0x16) {
7219			err = add_control(spec, ALC_CTL_WIDGET_VOL,
7220					  "Speaker Playback Volume",
7221					  HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
7222							      HDA_OUTPUT));
7223			if (err < 0)
7224				return err;
7225			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
7226					  "Speaker Playback Switch",
7227					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
7228							      HDA_OUTPUT));
7229			if (err < 0)
7230				return err;
7231		} else {
7232			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
7233					  "Speaker Playback Switch",
7234					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
7235							      HDA_OUTPUT));
7236			if (err < 0)
7237				return err;
7238		}
7239	}
7240	nid = cfg->hp_pins[0];
7241	if (nid) {
7242		/* spec->multiout.hp_nid = 2; */
7243		if (nid == 0x16) {
7244			err = add_control(spec, ALC_CTL_WIDGET_VOL,
7245					  "Headphone Playback Volume",
7246					  HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
7247							      HDA_OUTPUT));
7248			if (err < 0)
7249				return err;
7250			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
7251					  "Headphone Playback Switch",
7252					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
7253							      HDA_OUTPUT));
7254			if (err < 0)
7255				return err;
7256		} else {
7257			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
7258					  "Headphone Playback Switch",
7259					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
7260							      HDA_OUTPUT));
7261			if (err < 0)
7262				return err;
7263		}
7264	}
7265	return 0;
7266}
7267
7268/* identical with ALC880 */
7269#define alc262_auto_create_analog_input_ctls \
7270	alc880_auto_create_analog_input_ctls
7271
7272/*
7273 * generic initialization of ADC, input mixers and output mixers
7274 */
7275static struct hda_verb alc262_volume_init_verbs[] = {
7276	/*
7277	 * Unmute ADC0-2 and set the default input to mic-in
7278	 */
7279	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7280	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7281	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7282	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7283	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7284	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7285
7286	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
7287	 * mixer widget
7288	 * Note: PASD motherboards uses the Line In 2 as the input for
7289	 * front panel mic (mic 2)
7290	 */
7291	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
7292	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7293	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7294	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7295	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7296	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
7297
7298	/*
7299	 * Set up output mixers (0x0c - 0x0f)
7300	 */
7301	/* set vol=0 to output mixers */
7302	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7303	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7304	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7305
7306	/* set up input amps for analog loopback */
7307	/* Amp Indices: DAC = 0, mixer = 1 */
7308	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7309	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7310	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7311	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7312	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7313	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7314
7315	/* FIXME: use matrix-type input source selection */
7316	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7317	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7318	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7319	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
7320	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
7321	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
7322	/* Input mixer2 */
7323	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7324	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
7325	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
7326	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
7327	/* Input mixer3 */
7328	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7329	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
7330	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
7331	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
7332
7333	{ }
7334};
7335
7336static struct hda_verb alc262_HP_BPC_init_verbs[] = {
7337	/*
7338	 * Unmute ADC0-2 and set the default input to mic-in
7339	 */
7340	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7341	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7342	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7343	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7344	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7345	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7346
7347	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
7348	 * mixer widget
7349	 * Note: PASD motherboards uses the Line In 2 as the input for
7350	 * front panel mic (mic 2)
7351	 */
7352	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
7353	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7354	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7355	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7356	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7357	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
7358	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
7359        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
7360
7361	/*
7362	 * Set up output mixers (0x0c - 0x0e)
7363	 */
7364	/* set vol=0 to output mixers */
7365	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7366	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7367	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7368
7369	/* set up input amps for analog loopback */
7370	/* Amp Indices: DAC = 0, mixer = 1 */
7371	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7372	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7373	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7374	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7375	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7376	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7377
7378	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
7379	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7380	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7381
7382	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7383	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7384
7385	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
7386	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7387
7388	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7389	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
7390        {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
7391	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7392	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7393
7394	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
7395	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7396        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7397	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
7398	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7399	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7400
7401
7402	/* FIXME: use matrix-type input source selection */
7403	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7404	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7405	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7406	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7407	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7408	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
7409	/* Input mixer2 */
7410	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7411	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7412	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7413	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
7414	/* Input mixer3 */
7415	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7416	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7417	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7418	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
7419
7420	{ }
7421};
7422
7423static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
7424	/*
7425	 * Unmute ADC0-2 and set the default input to mic-in
7426	 */
7427	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7428	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7429	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7430	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7431	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7432	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7433
7434	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
7435	 * mixer widget
7436	 * Note: PASD motherboards uses the Line In 2 as the input for front
7437	 * panel mic (mic 2)
7438	 */
7439	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
7440	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7441	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7442	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7443	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7444	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
7445	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
7446	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
7447	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
7448	/*
7449	 * Set up output mixers (0x0c - 0x0e)
7450	 */
7451	/* set vol=0 to output mixers */
7452	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7453	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7454	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7455
7456	/* set up input amps for analog loopback */
7457	/* Amp Indices: DAC = 0, mixer = 1 */
7458	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7459	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7460	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7461	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7462	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7463	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7464
7465
7466	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },	/* HP */
7467	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Mono */
7468	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* rear MIC */
7469	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },	/* Line in */
7470	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* Front MIC */
7471	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Line out */
7472	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },	/* CD in */
7473
7474	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7475	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7476
7477	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
7478	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
7479
7480	/* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
7481	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7482	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7483	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
7484	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7485	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7486
7487	/* FIXME: use matrix-type input source selection */
7488	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7489	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7490	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
7491	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
7492	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
7493	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
7494	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
7495        /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))},  */
7496	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
7497	/* Input mixer2 */
7498	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7499	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
7500	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7501	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7502	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
7503        /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
7504	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
7505	/* Input mixer3 */
7506	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7507	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
7508	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7509	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7510	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
7511        /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
7512	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
7513
7514	{ }
7515};
7516
7517/* pcm configuration: identiacal with ALC880 */
7518#define alc262_pcm_analog_playback	alc880_pcm_analog_playback
7519#define alc262_pcm_analog_capture	alc880_pcm_analog_capture
7520#define alc262_pcm_digital_playback	alc880_pcm_digital_playback
7521#define alc262_pcm_digital_capture	alc880_pcm_digital_capture
7522
7523/*
7524 * BIOS auto configuration
7525 */
7526static int alc262_parse_auto_config(struct hda_codec *codec)
7527{
7528	struct alc_spec *spec = codec->spec;
7529	int err;
7530	static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
7531
7532	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
7533					   alc262_ignore);
7534	if (err < 0)
7535		return err;
7536	if (!spec->autocfg.line_outs)
7537		return 0; /* can't find valid BIOS pin config */
7538	err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
7539	if (err < 0)
7540		return err;
7541	err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg);
7542	if (err < 0)
7543		return err;
7544
7545	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
7546
7547	if (spec->autocfg.dig_out_pin)
7548		spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
7549	if (spec->autocfg.dig_in_pin)
7550		spec->dig_in_nid = ALC262_DIGIN_NID;
7551
7552	if (spec->kctl_alloc)
7553		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
7554
7555	spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
7556	spec->num_mux_defs = 1;
7557	spec->input_mux = &spec->private_imux;
7558
7559	return 1;
7560}
7561
7562#define alc262_auto_init_multi_out	alc882_auto_init_multi_out
7563#define alc262_auto_init_hp_out		alc882_auto_init_hp_out
7564#define alc262_auto_init_analog_input	alc882_auto_init_analog_input
7565
7566
7567/* init callback for auto-configuration model -- overriding the default init */
7568static void alc262_auto_init(struct hda_codec *codec)
7569{
7570	alc262_auto_init_multi_out(codec);
7571	alc262_auto_init_hp_out(codec);
7572	alc262_auto_init_analog_input(codec);
7573}
7574
7575/*
7576 * configuration and preset
7577 */
7578static const char *alc262_models[ALC262_MODEL_LAST] = {
7579	[ALC262_BASIC]		= "basic",
7580	[ALC262_HIPPO]		= "hippo",
7581	[ALC262_HIPPO_1]	= "hippo_1",
7582	[ALC262_FUJITSU]	= "fujitsu",
7583	[ALC262_HP_BPC]		= "hp-bpc",
7584	[ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
7585	[ALC262_BENQ_ED8]	= "benq",
7586	[ALC262_BENQ_ED8]	= "sony-assamd",
7587	[ALC262_AUTO]		= "auto",
7588};
7589
7590static struct snd_pci_quirk alc262_cfg_tbl[] = {
7591	SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
7592	SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC),
7593	SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
7594	SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
7595	SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
7596	SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
7597	SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
7598	SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
7599	SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
7600	SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
7601	SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
7602	SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
7603	SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
7604	SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
7605	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
7606	SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
7607	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
7608	SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
7609	SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
7610	SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
7611	{}
7612};
7613
7614static struct alc_config_preset alc262_presets[] = {
7615	[ALC262_BASIC] = {
7616		.mixers = { alc262_base_mixer },
7617		.init_verbs = { alc262_init_verbs },
7618		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7619		.dac_nids = alc262_dac_nids,
7620		.hp_nid = 0x03,
7621		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7622		.channel_mode = alc262_modes,
7623		.input_mux = &alc262_capture_source,
7624	},
7625	[ALC262_HIPPO] = {
7626		.mixers = { alc262_base_mixer },
7627		.init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},
7628		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7629		.dac_nids = alc262_dac_nids,
7630		.hp_nid = 0x03,
7631		.dig_out_nid = ALC262_DIGOUT_NID,
7632		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7633		.channel_mode = alc262_modes,
7634		.input_mux = &alc262_capture_source,
7635		.unsol_event = alc262_hippo_unsol_event,
7636	},
7637	[ALC262_HIPPO_1] = {
7638		.mixers = { alc262_hippo1_mixer },
7639		.init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
7640		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7641		.dac_nids = alc262_dac_nids,
7642		.hp_nid = 0x02,
7643		.dig_out_nid = ALC262_DIGOUT_NID,
7644		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7645		.channel_mode = alc262_modes,
7646		.input_mux = &alc262_capture_source,
7647		.unsol_event = alc262_hippo1_unsol_event,
7648	},
7649	[ALC262_FUJITSU] = {
7650		.mixers = { alc262_fujitsu_mixer },
7651		.init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs },
7652		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7653		.dac_nids = alc262_dac_nids,
7654		.hp_nid = 0x03,
7655		.dig_out_nid = ALC262_DIGOUT_NID,
7656		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7657		.channel_mode = alc262_modes,
7658		.input_mux = &alc262_fujitsu_capture_source,
7659		.unsol_event = alc262_fujitsu_unsol_event,
7660	},
7661	[ALC262_HP_BPC] = {
7662		.mixers = { alc262_HP_BPC_mixer },
7663		.init_verbs = { alc262_HP_BPC_init_verbs },
7664		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7665		.dac_nids = alc262_dac_nids,
7666		.hp_nid = 0x03,
7667		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7668		.channel_mode = alc262_modes,
7669		.input_mux = &alc262_HP_capture_source,
7670	},
7671	[ALC262_HP_BPC_D7000_WF] = {
7672		.mixers = { alc262_HP_BPC_WildWest_mixer },
7673		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
7674		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7675		.dac_nids = alc262_dac_nids,
7676		.hp_nid = 0x03,
7677		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7678		.channel_mode = alc262_modes,
7679		.input_mux = &alc262_HP_capture_source,
7680	},
7681	[ALC262_HP_BPC_D7000_WL] = {
7682		.mixers = { alc262_HP_BPC_WildWest_mixer,
7683			    alc262_HP_BPC_WildWest_option_mixer },
7684		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
7685		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7686		.dac_nids = alc262_dac_nids,
7687		.hp_nid = 0x03,
7688		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7689		.channel_mode = alc262_modes,
7690		.input_mux = &alc262_HP_capture_source,
7691	},
7692	[ALC262_BENQ_ED8] = {
7693		.mixers = { alc262_base_mixer },
7694		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
7695		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7696		.dac_nids = alc262_dac_nids,
7697		.hp_nid = 0x03,
7698		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7699		.channel_mode = alc262_modes,
7700		.input_mux = &alc262_capture_source,
7701	},
7702	[ALC262_SONY_ASSAMD] = {
7703		.mixers = { alc262_sony_mixer },
7704		.init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
7705		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7706		.dac_nids = alc262_dac_nids,
7707		.hp_nid = 0x02,
7708		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7709		.channel_mode = alc262_modes,
7710		.input_mux = &alc262_capture_source,
7711		.unsol_event = alc262_hippo_unsol_event,
7712	},
7713};
7714
7715static int patch_alc262(struct hda_codec *codec)
7716{
7717	struct alc_spec *spec;
7718	int board_config;
7719	int err;
7720
7721	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
7722	if (spec == NULL)
7723		return -ENOMEM;
7724
7725	codec->spec = spec;
7726#if 0
7727	/* pshou 07/11/05  set a zero PCM sample to DAC when FIFO is
7728	 * under-run
7729	 */
7730	{
7731	int tmp;
7732	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
7733	tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
7734	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
7735	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
7736	}
7737#endif
7738
7739	board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
7740						  alc262_models,
7741						  alc262_cfg_tbl);
7742
7743	if (board_config < 0) {
7744		printk(KERN_INFO "hda_codec: Unknown model for ALC262, "
7745		       "trying auto-probe from BIOS...\n");
7746		board_config = ALC262_AUTO;
7747	}
7748
7749	if (board_config == ALC262_AUTO) {
7750		/* automatic parse from the BIOS config */
7751		err = alc262_parse_auto_config(codec);
7752		if (err < 0) {
7753			alc_free(codec);
7754			return err;
7755		} else if (!err) {
7756			printk(KERN_INFO
7757			       "hda_codec: Cannot set up configuration "
7758			       "from BIOS.  Using base mode...\n");
7759			board_config = ALC262_BASIC;
7760		}
7761	}
7762
7763	if (board_config != ALC262_AUTO)
7764		setup_preset(spec, &alc262_presets[board_config]);
7765
7766	spec->stream_name_analog = "ALC262 Analog";
7767	spec->stream_analog_playback = &alc262_pcm_analog_playback;
7768	spec->stream_analog_capture = &alc262_pcm_analog_capture;
7769
7770	spec->stream_name_digital = "ALC262 Digital";
7771	spec->stream_digital_playback = &alc262_pcm_digital_playback;
7772	spec->stream_digital_capture = &alc262_pcm_digital_capture;
7773
7774	if (!spec->adc_nids && spec->input_mux) {
7775		/* check whether NID 0x07 is valid */
7776		unsigned int wcap = get_wcaps(codec, 0x07);
7777
7778		/* get type */
7779		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
7780		if (wcap != AC_WID_AUD_IN) {
7781			spec->adc_nids = alc262_adc_nids_alt;
7782			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
7783			spec->mixers[spec->num_mixers] =
7784				alc262_capture_alt_mixer;
7785			spec->num_mixers++;
7786		} else {
7787			spec->adc_nids = alc262_adc_nids;
7788			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
7789			spec->mixers[spec->num_mixers] = alc262_capture_mixer;
7790			spec->num_mixers++;
7791		}
7792	}
7793
7794	codec->patch_ops = alc_patch_ops;
7795	if (board_config == ALC262_AUTO)
7796		spec->init_hook = alc262_auto_init;
7797
7798	return 0;
7799}
7800
7801/*
7802 *  ALC861 channel source setting (2/6 channel selection for 3-stack)
7803 */
7804
7805/*
7806 * set the path ways for 2 channel output
7807 * need to set the codec line out and mic 1 pin widgets to inputs
7808 */
7809static struct hda_verb alc861_threestack_ch2_init[] = {
7810	/* set pin widget 1Ah (line in) for input */
7811	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7812	/* set pin widget 18h (mic1/2) for input, for mic also enable
7813	 * the vref
7814	 */
7815	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7816
7817	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
7818#if 0
7819	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
7820	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
7821#endif
7822	{ } /* end */
7823};
7824/*
7825 * 6ch mode
7826 * need to set the codec line out and mic 1 pin widgets to outputs
7827 */
7828static struct hda_verb alc861_threestack_ch6_init[] = {
7829	/* set pin widget 1Ah (line in) for output (Back Surround)*/
7830	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7831	/* set pin widget 18h (mic1) for output (CLFE)*/
7832	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7833
7834	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
7835	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
7836
7837	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
7838#if 0
7839	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
7840	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
7841#endif
7842	{ } /* end */
7843};
7844
7845static struct hda_channel_mode alc861_threestack_modes[2] = {
7846	{ 2, alc861_threestack_ch2_init },
7847	{ 6, alc861_threestack_ch6_init },
7848};
7849/* Set mic1 as input and unmute the mixer */
7850static struct hda_verb alc861_uniwill_m31_ch2_init[] = {
7851	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7852	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
7853	{ } /* end */
7854};
7855/* Set mic1 as output and mute mixer */
7856static struct hda_verb alc861_uniwill_m31_ch4_init[] = {
7857	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7858	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
7859	{ } /* end */
7860};
7861
7862static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
7863	{ 2, alc861_uniwill_m31_ch2_init },
7864	{ 4, alc861_uniwill_m31_ch4_init },
7865};
7866
7867/* Set mic1 and line-in as input and unmute the mixer */
7868static struct hda_verb alc861_asus_ch2_init[] = {
7869	/* set pin widget 1Ah (line in) for input */
7870	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7871	/* set pin widget 18h (mic1/2) for input, for mic also enable
7872	 * the vref
7873	 */
7874	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7875
7876	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
7877#if 0
7878	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
7879	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
7880#endif
7881	{ } /* end */
7882};
7883/* Set mic1 nad line-in as output and mute mixer */
7884static struct hda_verb alc861_asus_ch6_init[] = {
7885	/* set pin widget 1Ah (line in) for output (Back Surround)*/
7886	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7887	/* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
7888	/* set pin widget 18h (mic1) for output (CLFE)*/
7889	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7890	/* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
7891	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
7892	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
7893
7894	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
7895#if 0
7896	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
7897	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
7898#endif
7899	{ } /* end */
7900};
7901
7902static struct hda_channel_mode alc861_asus_modes[2] = {
7903	{ 2, alc861_asus_ch2_init },
7904	{ 6, alc861_asus_ch6_init },
7905};
7906
7907/* patch-ALC861 */
7908
7909static struct snd_kcontrol_new alc861_base_mixer[] = {
7910        /* output mixer control */
7911	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
7912	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
7913	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
7914	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
7915	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
7916
7917        /*Input mixer control */
7918	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
7919	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
7920	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
7921	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
7922	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
7923	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
7924	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
7925	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
7926	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
7927	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
7928
7929        /* Capture mixer control */
7930	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7931	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7932	{
7933		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7934		.name = "Capture Source",
7935		.count = 1,
7936		.info = alc_mux_enum_info,
7937		.get = alc_mux_enum_get,
7938		.put = alc_mux_enum_put,
7939	},
7940	{ } /* end */
7941};
7942
7943static struct snd_kcontrol_new alc861_3ST_mixer[] = {
7944        /* output mixer control */
7945	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
7946	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
7947	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
7948	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
7949	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
7950
7951	/* Input mixer control */
7952	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
7953	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
7954	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
7955	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
7956	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
7957	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
7958	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
7959	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
7960	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
7961	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
7962
7963	/* Capture mixer control */
7964	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7965	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7966	{
7967		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7968		.name = "Capture Source",
7969		.count = 1,
7970		.info = alc_mux_enum_info,
7971		.get = alc_mux_enum_get,
7972		.put = alc_mux_enum_put,
7973	},
7974	{
7975		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7976		.name = "Channel Mode",
7977		.info = alc_ch_mode_info,
7978		.get = alc_ch_mode_get,
7979		.put = alc_ch_mode_put,
7980                .private_value = ARRAY_SIZE(alc861_threestack_modes),
7981	},
7982	{ } /* end */
7983};
7984
7985static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
7986        /* output mixer control */
7987	HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
7988	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
7989	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
7990
7991        /*Capture mixer control */
7992	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7993	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7994	{
7995		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7996		.name = "Capture Source",
7997		.count = 1,
7998		.info = alc_mux_enum_info,
7999		.get = alc_mux_enum_get,
8000		.put = alc_mux_enum_put,
8001	},
8002
8003	{ } /* end */
8004};
8005
8006static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
8007        /* output mixer control */
8008	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
8009	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
8010	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
8011	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
8012	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
8013
8014	/* Input mixer control */
8015	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
8016	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
8017	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
8018	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
8019	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
8020	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
8021	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
8022	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
8023	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
8024	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
8025
8026	/* Capture mixer control */
8027	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
8028	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
8029	{
8030		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8031		.name = "Capture Source",
8032		.count = 1,
8033		.info = alc_mux_enum_info,
8034		.get = alc_mux_enum_get,
8035		.put = alc_mux_enum_put,
8036	},
8037	{
8038		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8039		.name = "Channel Mode",
8040		.info = alc_ch_mode_info,
8041		.get = alc_ch_mode_get,
8042		.put = alc_ch_mode_put,
8043                .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
8044	},
8045	{ } /* end */
8046};
8047
8048static struct snd_kcontrol_new alc861_asus_mixer[] = {
8049        /* output mixer control */
8050	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
8051	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
8052	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
8053	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
8054	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
8055
8056	/* Input mixer control */
8057	HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
8058	HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8059	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
8060	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
8061	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
8062	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
8063	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
8064	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
8065	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
8066	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
8067
8068	/* Capture mixer control */
8069	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
8070	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
8071	{
8072		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8073		.name = "Capture Source",
8074		.count = 1,
8075		.info = alc_mux_enum_info,
8076		.get = alc_mux_enum_get,
8077		.put = alc_mux_enum_put,
8078	},
8079	{
8080		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8081		.name = "Channel Mode",
8082		.info = alc_ch_mode_info,
8083		.get = alc_ch_mode_get,
8084		.put = alc_ch_mode_put,
8085                .private_value = ARRAY_SIZE(alc861_asus_modes),
8086	},
8087	{ }
8088};
8089
8090/* additional mixer */
8091static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
8092	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
8093	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
8094	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT),
8095	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT),
8096	{ }
8097};
8098
8099/*
8100 * generic initialization of ADC, input mixers and output mixers
8101 */
8102static struct hda_verb alc861_base_init_verbs[] = {
8103	/*
8104	 * Unmute ADC0 and set the default input to mic-in
8105	 */
8106	/* port-A for surround (rear panel) */
8107	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8108	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
8109	/* port-B for mic-in (rear panel) with vref */
8110	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8111	/* port-C for line-in (rear panel) */
8112	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8113	/* port-D for Front */
8114	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8115	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
8116	/* port-E for HP out (front panel) */
8117	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
8118	/* route front PCM to HP */
8119	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
8120	/* port-F for mic-in (front panel) with vref */
8121	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8122	/* port-G for CLFE (rear panel) */
8123	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8124	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
8125	/* port-H for side (rear panel) */
8126	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8127	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
8128	/* CD-in */
8129	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8130	/* route front mic to ADC1*/
8131	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8132	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8133
8134	/* Unmute DAC0~3 & spdif out*/
8135	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8136	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8137	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8138	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8139	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8140
8141	/* Unmute Mixer 14 (mic) 1c (Line in)*/
8142	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8143        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8144	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8145        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8146
8147	/* Unmute Stereo Mixer 15 */
8148	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8149	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8150	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8151	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
8152
8153	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8154	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8155	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8156	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8157	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8158	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8159	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8160	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8161	/* hp used DAC 3 (Front) */
8162	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8163        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8164
8165	{ }
8166};
8167
8168static struct hda_verb alc861_threestack_init_verbs[] = {
8169	/*
8170	 * Unmute ADC0 and set the default input to mic-in
8171	 */
8172	/* port-A for surround (rear panel) */
8173	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8174	/* port-B for mic-in (rear panel) with vref */
8175	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8176	/* port-C for line-in (rear panel) */
8177	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8178	/* port-D for Front */
8179	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8180	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
8181	/* port-E for HP out (front panel) */
8182	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
8183	/* route front PCM to HP */
8184	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
8185	/* port-F for mic-in (front panel) with vref */
8186	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8187	/* port-G for CLFE (rear panel) */
8188	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8189	/* port-H for side (rear panel) */
8190	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8191	/* CD-in */
8192	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8193	/* route front mic to ADC1*/
8194	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8195	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8196	/* Unmute DAC0~3 & spdif out*/
8197	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8198	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8199	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8200	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8201	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8202
8203	/* Unmute Mixer 14 (mic) 1c (Line in)*/
8204	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8205        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8206	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8207        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8208
8209	/* Unmute Stereo Mixer 15 */
8210	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8211	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8212	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8213	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
8214
8215	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8216	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8217	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8218	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8219	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8220	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8221	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8222	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8223	/* hp used DAC 3 (Front) */
8224	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8225        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8226	{ }
8227};
8228
8229static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
8230	/*
8231	 * Unmute ADC0 and set the default input to mic-in
8232	 */
8233	/* port-A for surround (rear panel) */
8234	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8235	/* port-B for mic-in (rear panel) with vref */
8236	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8237	/* port-C for line-in (rear panel) */
8238	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8239	/* port-D for Front */
8240	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8241	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
8242	/* port-E for HP out (front panel) */
8243	/* this has to be set to VREF80 */
8244	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8245	/* route front PCM to HP */
8246	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
8247	/* port-F for mic-in (front panel) with vref */
8248	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8249	/* port-G for CLFE (rear panel) */
8250	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8251	/* port-H for side (rear panel) */
8252	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8253	/* CD-in */
8254	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8255	/* route front mic to ADC1*/
8256	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8257	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8258	/* Unmute DAC0~3 & spdif out*/
8259	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8260	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8261	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8262	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8263	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8264
8265	/* Unmute Mixer 14 (mic) 1c (Line in)*/
8266	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8267        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8268	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8269        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8270
8271	/* Unmute Stereo Mixer 15 */
8272	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8273	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8274	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8275	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
8276
8277	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8278	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8279	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8280	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8281	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8282	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8283	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8284	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8285	/* hp used DAC 3 (Front) */
8286	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8287        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8288	{ }
8289};
8290
8291static struct hda_verb alc861_asus_init_verbs[] = {
8292	/*
8293	 * Unmute ADC0 and set the default input to mic-in
8294	 */
8295	/* port-A for surround (rear panel)
8296	 * according to codec#0 this is the HP jack
8297	 */
8298	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
8299	/* route front PCM to HP */
8300	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
8301	/* port-B for mic-in (rear panel) with vref */
8302	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8303	/* port-C for line-in (rear panel) */
8304	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8305	/* port-D for Front */
8306	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8307	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
8308	/* port-E for HP out (front panel) */
8309	/* this has to be set to VREF80 */
8310	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8311	/* route front PCM to HP */
8312	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
8313	/* port-F for mic-in (front panel) with vref */
8314	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8315	/* port-G for CLFE (rear panel) */
8316	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8317	/* port-H for side (rear panel) */
8318	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8319	/* CD-in */
8320	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8321	/* route front mic to ADC1*/
8322	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8323	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8324	/* Unmute DAC0~3 & spdif out*/
8325	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8326	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8327	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8328	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8329	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8330	/* Unmute Mixer 14 (mic) 1c (Line in)*/
8331	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8332        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8333	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8334        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8335
8336	/* Unmute Stereo Mixer 15 */
8337	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8338	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8339	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8340	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
8341
8342	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8343	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8344	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8345	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8346	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8347	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8348	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8349	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8350	/* hp used DAC 3 (Front) */
8351	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8352	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8353	{ }
8354};
8355
8356/* additional init verbs for ASUS laptops */
8357static struct hda_verb alc861_asus_laptop_init_verbs[] = {
8358	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
8359	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
8360	{ }
8361};
8362
8363/*
8364 * generic initialization of ADC, input mixers and output mixers
8365 */
8366static struct hda_verb alc861_auto_init_verbs[] = {
8367	/*
8368	 * Unmute ADC0 and set the default input to mic-in
8369	 */
8370	/* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
8371	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8372
8373	/* Unmute DAC0~3 & spdif out*/
8374	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8375	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8376	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8377	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8378	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8379
8380	/* Unmute Mixer 14 (mic) 1c (Line in)*/
8381	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8382	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8383	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8384	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8385
8386	/* Unmute Stereo Mixer 15 */
8387	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8388	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8389	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8390	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
8391
8392	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8393	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8394	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8395	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8396	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8397	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8398	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8399	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8400
8401	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8402	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8403	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8404	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8405	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8406	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8407	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8408	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8409
8410	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},	/* set Mic 1 */
8411
8412	{ }
8413};
8414
8415static struct hda_verb alc861_toshiba_init_verbs[] = {
8416	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
8417
8418	{ }
8419};
8420
8421/* toggle speaker-output according to the hp-jack state */
8422static void alc861_toshiba_automute(struct hda_codec *codec)
8423{
8424	unsigned int present;
8425
8426	present = snd_hda_codec_read(codec, 0x0f, 0,
8427				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
8428	snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0,
8429				 0x80, present ? 0x80 : 0);
8430	snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0,
8431				 0x80, present ? 0x80 : 0);
8432	snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3,
8433				 0x80, present ? 0 : 0x80);
8434	snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3,
8435				 0x80, present ? 0 : 0x80);
8436}
8437
8438static void alc861_toshiba_unsol_event(struct hda_codec *codec,
8439				       unsigned int res)
8440{
8441	if ((res >> 26) == ALC880_HP_EVENT)
8442		alc861_toshiba_automute(codec);
8443}
8444
8445/* pcm configuration: identiacal with ALC880 */
8446#define alc861_pcm_analog_playback	alc880_pcm_analog_playback
8447#define alc861_pcm_analog_capture	alc880_pcm_analog_capture
8448#define alc861_pcm_digital_playback	alc880_pcm_digital_playback
8449#define alc861_pcm_digital_capture	alc880_pcm_digital_capture
8450
8451
8452#define ALC861_DIGOUT_NID	0x07
8453
8454static struct hda_channel_mode alc861_8ch_modes[1] = {
8455	{ 8, NULL }
8456};
8457
8458static hda_nid_t alc861_dac_nids[4] = {
8459	/* front, surround, clfe, side */
8460	0x03, 0x06, 0x05, 0x04
8461};
8462
8463static hda_nid_t alc660_dac_nids[3] = {
8464	/* front, clfe, surround */
8465	0x03, 0x05, 0x06
8466};
8467
8468static hda_nid_t alc861_adc_nids[1] = {
8469	/* ADC0-2 */
8470	0x08,
8471};
8472
8473static struct hda_input_mux alc861_capture_source = {
8474	.num_items = 5,
8475	.items = {
8476		{ "Mic", 0x0 },
8477		{ "Front Mic", 0x3 },
8478		{ "Line", 0x1 },
8479		{ "CD", 0x4 },
8480		{ "Mixer", 0x5 },
8481	},
8482};
8483
8484/* fill in the dac_nids table from the parsed pin configuration */
8485static int alc861_auto_fill_dac_nids(struct alc_spec *spec,
8486				     const struct auto_pin_cfg *cfg)
8487{
8488	int i;
8489	hda_nid_t nid;
8490
8491	spec->multiout.dac_nids = spec->private_dac_nids;
8492	for (i = 0; i < cfg->line_outs; i++) {
8493		nid = cfg->line_out_pins[i];
8494		if (nid) {
8495			if (i >= ARRAY_SIZE(alc861_dac_nids))
8496				continue;
8497			spec->multiout.dac_nids[i] = alc861_dac_nids[i];
8498		}
8499	}
8500	spec->multiout.num_dacs = cfg->line_outs;
8501	return 0;
8502}
8503
8504/* add playback controls from the parsed DAC table */
8505static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
8506					     const struct auto_pin_cfg *cfg)
8507{
8508	char name[32];
8509	static const char *chname[4] = {
8510		"Front", "Surround", NULL /*CLFE*/, "Side"
8511	};
8512	hda_nid_t nid;
8513	int i, idx, err;
8514
8515	for (i = 0; i < cfg->line_outs; i++) {
8516		nid = spec->multiout.dac_nids[i];
8517		if (!nid)
8518			continue;
8519		if (nid == 0x05) {
8520			/* Center/LFE */
8521			err = add_control(spec, ALC_CTL_BIND_MUTE,
8522					  "Center Playback Switch",
8523					  HDA_COMPOSE_AMP_VAL(nid, 1, 0,
8524							      HDA_OUTPUT));
8525			if (err < 0)
8526				return err;
8527			err = add_control(spec, ALC_CTL_BIND_MUTE,
8528					  "LFE Playback Switch",
8529					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
8530							      HDA_OUTPUT));
8531			if (err < 0)
8532				return err;
8533		} else {
8534			for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1;
8535			     idx++)
8536				if (nid == alc861_dac_nids[idx])
8537					break;
8538			sprintf(name, "%s Playback Switch", chname[idx]);
8539			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
8540					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
8541							      HDA_OUTPUT));
8542			if (err < 0)
8543				return err;
8544		}
8545	}
8546	return 0;
8547}
8548
8549static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
8550{
8551	int err;
8552	hda_nid_t nid;
8553
8554	if (!pin)
8555		return 0;
8556
8557	if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
8558		nid = 0x03;
8559		err = add_control(spec, ALC_CTL_WIDGET_MUTE,
8560				  "Headphone Playback Switch",
8561				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
8562		if (err < 0)
8563			return err;
8564		spec->multiout.hp_nid = nid;
8565	}
8566	return 0;
8567}
8568
8569/* create playback/capture controls for input pins */
8570static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
8571						const struct auto_pin_cfg *cfg)
8572{
8573	struct hda_input_mux *imux = &spec->private_imux;
8574	int i, err, idx, idx1;
8575
8576	for (i = 0; i < AUTO_PIN_LAST; i++) {
8577		switch (cfg->input_pins[i]) {
8578		case 0x0c:
8579			idx1 = 1;
8580			idx = 2;	/* Line In */
8581			break;
8582		case 0x0f:
8583			idx1 = 2;
8584			idx = 2;	/* Line In */
8585			break;
8586		case 0x0d:
8587			idx1 = 0;
8588			idx = 1;	/* Mic In */
8589			break;
8590		case 0x10:
8591			idx1 = 3;
8592			idx = 1;	/* Mic In */
8593			break;
8594		case 0x11:
8595			idx1 = 4;
8596			idx = 0;	/* CD */
8597			break;
8598		default:
8599			continue;
8600		}
8601
8602		err = new_analog_input(spec, cfg->input_pins[i],
8603				       auto_pin_cfg_labels[i], idx, 0x15);
8604		if (err < 0)
8605			return err;
8606
8607		imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
8608		imux->items[imux->num_items].index = idx1;
8609		imux->num_items++;
8610	}
8611	return 0;
8612}
8613
8614static struct snd_kcontrol_new alc861_capture_mixer[] = {
8615	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
8616	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
8617
8618	{
8619		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8620		/* The multiple "Capture Source" controls confuse alsamixer
8621		 * So call somewhat different..
8622		 *FIXME: the controls appear in the "playback" view!
8623		 */
8624		/* .name = "Capture Source", */
8625		.name = "Input Source",
8626		.count = 1,
8627		.info = alc_mux_enum_info,
8628		.get = alc_mux_enum_get,
8629		.put = alc_mux_enum_put,
8630	},
8631	{ } /* end */
8632};
8633
8634static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
8635					      hda_nid_t nid,
8636					      int pin_type, int dac_idx)
8637{
8638	/* set as output */
8639
8640	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
8641			    pin_type);
8642	snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE,
8643			    AMP_OUT_UNMUTE);
8644
8645}
8646
8647static void alc861_auto_init_multi_out(struct hda_codec *codec)
8648{
8649	struct alc_spec *spec = codec->spec;
8650	int i;
8651
8652	alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b);
8653	for (i = 0; i < spec->autocfg.line_outs; i++) {
8654		hda_nid_t nid = spec->autocfg.line_out_pins[i];
8655		int pin_type = get_pin_type(spec->autocfg.line_out_type);
8656		if (nid)
8657			alc861_auto_set_output_and_unmute(codec, nid, pin_type,
8658							  spec->multiout.dac_nids[i]);
8659	}
8660}
8661
8662static void alc861_auto_init_hp_out(struct hda_codec *codec)
8663{
8664	struct alc_spec *spec = codec->spec;
8665	hda_nid_t pin;
8666
8667	pin = spec->autocfg.hp_pins[0];
8668	if (pin) /* connect to front */
8669		alc861_auto_set_output_and_unmute(codec, pin, PIN_HP,
8670						  spec->multiout.dac_nids[0]);
8671}
8672
8673static void alc861_auto_init_analog_input(struct hda_codec *codec)
8674{
8675	struct alc_spec *spec = codec->spec;
8676	int i;
8677
8678	for (i = 0; i < AUTO_PIN_LAST; i++) {
8679		hda_nid_t nid = spec->autocfg.input_pins[i];
8680		if (nid >= 0x0c && nid <= 0x11) {
8681			snd_hda_codec_write(codec, nid, 0,
8682					    AC_VERB_SET_PIN_WIDGET_CONTROL,
8683					    i <= AUTO_PIN_FRONT_MIC ?
8684					    PIN_VREF80 : PIN_IN);
8685		}
8686	}
8687}
8688
8689/* parse the BIOS configuration and set up the alc_spec */
8690/* return 1 if successful, 0 if the proper config is not found,
8691 * or a negative error code
8692 */
8693static int alc861_parse_auto_config(struct hda_codec *codec)
8694{
8695	struct alc_spec *spec = codec->spec;
8696	int err;
8697	static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
8698
8699	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
8700					   alc861_ignore);
8701	if (err < 0)
8702		return err;
8703	if (!spec->autocfg.line_outs)
8704		return 0; /* can't find valid BIOS pin config */
8705
8706	err = alc861_auto_fill_dac_nids(spec, &spec->autocfg);
8707	if (err < 0)
8708		return err;
8709	err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg);
8710	if (err < 0)
8711		return err;
8712	err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
8713	if (err < 0)
8714		return err;
8715	err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg);
8716	if (err < 0)
8717		return err;
8718
8719	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
8720
8721	if (spec->autocfg.dig_out_pin)
8722		spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
8723
8724	if (spec->kctl_alloc)
8725		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
8726
8727	spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
8728
8729	spec->num_mux_defs = 1;
8730	spec->input_mux = &spec->private_imux;
8731
8732	spec->adc_nids = alc861_adc_nids;
8733	spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
8734	spec->mixers[spec->num_mixers] = alc861_capture_mixer;
8735	spec->num_mixers++;
8736
8737	return 1;
8738}
8739
8740/* additional initialization for auto-configuration model */
8741static void alc861_auto_init(struct hda_codec *codec)
8742{
8743	alc861_auto_init_multi_out(codec);
8744	alc861_auto_init_hp_out(codec);
8745	alc861_auto_init_analog_input(codec);
8746}
8747
8748
8749/*
8750 * configuration and preset
8751 */
8752static const char *alc861_models[ALC861_MODEL_LAST] = {
8753	[ALC861_3ST]		= "3stack",
8754	[ALC660_3ST]		= "3stack-660",
8755	[ALC861_3ST_DIG]	= "3stack-dig",
8756	[ALC861_6ST_DIG]	= "6stack-dig",
8757	[ALC861_UNIWILL_M31]	= "uniwill-m31",
8758	[ALC861_TOSHIBA]	= "toshiba",
8759	[ALC861_ASUS]		= "asus",
8760	[ALC861_ASUS_LAPTOP]	= "asus-laptop",
8761	[ALC861_AUTO]		= "auto",
8762};
8763
8764static struct snd_pci_quirk alc861_cfg_tbl[] = {
8765	SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
8766	SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
8767	SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
8768	SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
8769	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
8770	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
8771	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA),
8772	SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
8773	SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
8774	SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
8775	SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
8776	{}
8777};
8778
8779static struct alc_config_preset alc861_presets[] = {
8780	[ALC861_3ST] = {
8781		.mixers = { alc861_3ST_mixer },
8782		.init_verbs = { alc861_threestack_init_verbs },
8783		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8784		.dac_nids = alc861_dac_nids,
8785		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
8786		.channel_mode = alc861_threestack_modes,
8787		.need_dac_fix = 1,
8788		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8789		.adc_nids = alc861_adc_nids,
8790		.input_mux = &alc861_capture_source,
8791	},
8792	[ALC861_3ST_DIG] = {
8793		.mixers = { alc861_base_mixer },
8794		.init_verbs = { alc861_threestack_init_verbs },
8795		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8796		.dac_nids = alc861_dac_nids,
8797		.dig_out_nid = ALC861_DIGOUT_NID,
8798		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
8799		.channel_mode = alc861_threestack_modes,
8800		.need_dac_fix = 1,
8801		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8802		.adc_nids = alc861_adc_nids,
8803		.input_mux = &alc861_capture_source,
8804	},
8805	[ALC861_6ST_DIG] = {
8806		.mixers = { alc861_base_mixer },
8807		.init_verbs = { alc861_base_init_verbs },
8808		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8809		.dac_nids = alc861_dac_nids,
8810		.dig_out_nid = ALC861_DIGOUT_NID,
8811		.num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
8812		.channel_mode = alc861_8ch_modes,
8813		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8814		.adc_nids = alc861_adc_nids,
8815		.input_mux = &alc861_capture_source,
8816	},
8817	[ALC660_3ST] = {
8818		.mixers = { alc861_3ST_mixer },
8819		.init_verbs = { alc861_threestack_init_verbs },
8820		.num_dacs = ARRAY_SIZE(alc660_dac_nids),
8821		.dac_nids = alc660_dac_nids,
8822		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
8823		.channel_mode = alc861_threestack_modes,
8824		.need_dac_fix = 1,
8825		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8826		.adc_nids = alc861_adc_nids,
8827		.input_mux = &alc861_capture_source,
8828	},
8829	[ALC861_UNIWILL_M31] = {
8830		.mixers = { alc861_uniwill_m31_mixer },
8831		.init_verbs = { alc861_uniwill_m31_init_verbs },
8832		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8833		.dac_nids = alc861_dac_nids,
8834		.dig_out_nid = ALC861_DIGOUT_NID,
8835		.num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
8836		.channel_mode = alc861_uniwill_m31_modes,
8837		.need_dac_fix = 1,
8838		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8839		.adc_nids = alc861_adc_nids,
8840		.input_mux = &alc861_capture_source,
8841	},
8842	[ALC861_TOSHIBA] = {
8843		.mixers = { alc861_toshiba_mixer },
8844		.init_verbs = { alc861_base_init_verbs,
8845				alc861_toshiba_init_verbs },
8846		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8847		.dac_nids = alc861_dac_nids,
8848		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8849		.channel_mode = alc883_3ST_2ch_modes,
8850		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8851		.adc_nids = alc861_adc_nids,
8852		.input_mux = &alc861_capture_source,
8853		.unsol_event = alc861_toshiba_unsol_event,
8854		.init_hook = alc861_toshiba_automute,
8855	},
8856	[ALC861_ASUS] = {
8857		.mixers = { alc861_asus_mixer },
8858		.init_verbs = { alc861_asus_init_verbs },
8859		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8860		.dac_nids = alc861_dac_nids,
8861		.dig_out_nid = ALC861_DIGOUT_NID,
8862		.num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
8863		.channel_mode = alc861_asus_modes,
8864		.need_dac_fix = 1,
8865		.hp_nid = 0x06,
8866		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8867		.adc_nids = alc861_adc_nids,
8868		.input_mux = &alc861_capture_source,
8869	},
8870	[ALC861_ASUS_LAPTOP] = {
8871		.mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
8872		.init_verbs = { alc861_asus_init_verbs,
8873				alc861_asus_laptop_init_verbs },
8874		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8875		.dac_nids = alc861_dac_nids,
8876		.dig_out_nid = ALC861_DIGOUT_NID,
8877		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8878		.channel_mode = alc883_3ST_2ch_modes,
8879		.need_dac_fix = 1,
8880		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8881		.adc_nids = alc861_adc_nids,
8882		.input_mux = &alc861_capture_source,
8883	},
8884};
8885
8886
8887static int patch_alc861(struct hda_codec *codec)
8888{
8889	struct alc_spec *spec;
8890	int board_config;
8891	int err;
8892
8893	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
8894	if (spec == NULL)
8895		return -ENOMEM;
8896
8897	codec->spec = spec;
8898
8899        board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
8900						  alc861_models,
8901						  alc861_cfg_tbl);
8902
8903	if (board_config < 0) {
8904		printk(KERN_INFO "hda_codec: Unknown model for ALC861, "
8905		       "trying auto-probe from BIOS...\n");
8906		board_config = ALC861_AUTO;
8907	}
8908
8909	if (board_config == ALC861_AUTO) {
8910		/* automatic parse from the BIOS config */
8911		err = alc861_parse_auto_config(codec);
8912		if (err < 0) {
8913			alc_free(codec);
8914			return err;
8915		} else if (!err) {
8916			printk(KERN_INFO
8917			       "hda_codec: Cannot set up configuration "
8918			       "from BIOS.  Using base mode...\n");
8919		   board_config = ALC861_3ST_DIG;
8920		}
8921	}
8922
8923	if (board_config != ALC861_AUTO)
8924		setup_preset(spec, &alc861_presets[board_config]);
8925
8926	spec->stream_name_analog = "ALC861 Analog";
8927	spec->stream_analog_playback = &alc861_pcm_analog_playback;
8928	spec->stream_analog_capture = &alc861_pcm_analog_capture;
8929
8930	spec->stream_name_digital = "ALC861 Digital";
8931	spec->stream_digital_playback = &alc861_pcm_digital_playback;
8932	spec->stream_digital_capture = &alc861_pcm_digital_capture;
8933
8934	codec->patch_ops = alc_patch_ops;
8935	if (board_config == ALC861_AUTO)
8936		spec->init_hook = alc861_auto_init;
8937
8938	return 0;
8939}
8940
8941/*
8942 * ALC861-VD support
8943 *
8944 * Based on ALC882
8945 *
8946 * In addition, an independent DAC
8947 */
8948#define ALC861VD_DIGOUT_NID	0x06
8949
8950static hda_nid_t alc861vd_dac_nids[4] = {
8951	/* front, surr, clfe, side surr */
8952	0x02, 0x03, 0x04, 0x05
8953};
8954
8955/* dac_nids for ALC660vd are in a different order - according to
8956 * Realtek's driver.
8957 * This should probably tesult in a different mixer for 6stack models
8958 * of ALC660vd codecs, but for now there is only 3stack mixer
8959 * - and it is the same as in 861vd.
8960 * adc_nids in ALC660vd are (is) the same as in 861vd
8961 */
8962static hda_nid_t alc660vd_dac_nids[3] = {
8963	/* front, rear, clfe, rear_surr */
8964	0x02, 0x04, 0x03
8965};
8966
8967static hda_nid_t alc861vd_adc_nids[1] = {
8968	/* ADC0 */
8969	0x09,
8970};
8971
8972/* input MUX */
8973/* FIXME: should be a matrix-type input source selection */
8974static struct hda_input_mux alc861vd_capture_source = {
8975	.num_items = 4,
8976	.items = {
8977		{ "Mic", 0x0 },
8978		{ "Front Mic", 0x1 },
8979		{ "Line", 0x2 },
8980		{ "CD", 0x4 },
8981	},
8982};
8983
8984static struct hda_input_mux alc861vd_dallas_capture_source = {
8985	.num_items = 3,
8986	.items = {
8987		{ "Front Mic", 0x0 },
8988		{ "ATAPI Mic", 0x1 },
8989		{ "Line In", 0x5 },
8990	},
8991};
8992
8993#define alc861vd_mux_enum_info alc_mux_enum_info
8994#define alc861vd_mux_enum_get alc_mux_enum_get
8995
8996static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
8997				struct snd_ctl_elem_value *ucontrol)
8998{
8999	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9000	struct alc_spec *spec = codec->spec;
9001	const struct hda_input_mux *imux = spec->input_mux;
9002	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
9003	static hda_nid_t capture_mixers[1] = { 0x22 };
9004	hda_nid_t nid = capture_mixers[adc_idx];
9005	unsigned int *cur_val = &spec->cur_mux[adc_idx];
9006	unsigned int i, idx;
9007
9008	idx = ucontrol->value.enumerated.item[0];
9009	if (idx >= imux->num_items)
9010		idx = imux->num_items - 1;
9011	if (*cur_val == idx && !codec->in_resume)
9012		return 0;
9013	for (i = 0; i < imux->num_items; i++) {
9014		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
9015		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
9016				    v | (imux->items[i].index << 8));
9017	}
9018	*cur_val = idx;
9019	return 1;
9020}
9021
9022/*
9023 * 2ch mode
9024 */
9025static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
9026	{ 2, NULL }
9027};
9028
9029/*
9030 * 6ch mode
9031 */
9032static struct hda_verb alc861vd_6stack_ch6_init[] = {
9033	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
9034	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9035	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9036	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9037	{ } /* end */
9038};
9039
9040/*
9041 * 8ch mode
9042 */
9043static struct hda_verb alc861vd_6stack_ch8_init[] = {
9044	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9045	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9046	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9047	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9048	{ } /* end */
9049};
9050
9051static struct hda_channel_mode alc861vd_6stack_modes[2] = {
9052	{ 6, alc861vd_6stack_ch6_init },
9053	{ 8, alc861vd_6stack_ch8_init },
9054};
9055
9056static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
9057	{
9058		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9059		.name = "Channel Mode",
9060		.info = alc_ch_mode_info,
9061		.get = alc_ch_mode_get,
9062		.put = alc_ch_mode_put,
9063	},
9064	{ } /* end */
9065};
9066
9067static struct snd_kcontrol_new alc861vd_capture_mixer[] = {
9068	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
9069	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
9070
9071	{
9072		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9073		/* The multiple "Capture Source" controls confuse alsamixer
9074		 * So call somewhat different..
9075		 *FIXME: the controls appear in the "playback" view!
9076		 */
9077		/* .name = "Capture Source", */
9078		.name = "Input Source",
9079		.count = 1,
9080		.info = alc861vd_mux_enum_info,
9081		.get = alc861vd_mux_enum_get,
9082		.put = alc861vd_mux_enum_put,
9083	},
9084	{ } /* end */
9085};
9086
9087/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
9088 *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
9089 */
9090static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
9091	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
9092	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9093
9094	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
9095	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9096
9097	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
9098				HDA_OUTPUT),
9099	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
9100				HDA_OUTPUT),
9101	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9102	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9103
9104	HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
9105	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
9106
9107	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9108
9109	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
9110	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9111	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9112
9113	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
9114	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9115	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9116
9117	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9118	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9119
9120	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9121	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9122
9123	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
9124	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
9125
9126	{ } /* end */
9127};
9128
9129static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
9130	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
9131	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9132
9133	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9134
9135	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
9136	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9137	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9138
9139	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
9140	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9141	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9142
9143	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9144	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9145
9146	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9147	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9148
9149	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
9150	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
9151
9152	{ } /* end */
9153};
9154
9155static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
9156	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
9157	/*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
9158	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9159
9160	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9161
9162	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
9163	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9164	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9165
9166	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
9167	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9168	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9169
9170	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9171	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9172
9173	{ } /* end */
9174};
9175
9176/* Pin assignment: Front=0x14, HP = 0x15,
9177 *                 Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d
9178 */
9179static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
9180	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
9181	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9182	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
9183	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
9184	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9185	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9186	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9187	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9188	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT),
9189	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT),
9190	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
9191	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
9192	{
9193		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9194		/* .name = "Capture Source", */
9195		.name = "Input Source",
9196		.count = 1,
9197		.info = alc882_mux_enum_info,
9198		.get = alc882_mux_enum_get,
9199		.put = alc882_mux_enum_put,
9200	},
9201	{ } /* end */
9202};
9203
9204/*
9205 * generic initialization of ADC, input mixers and output mixers
9206 */
9207static struct hda_verb alc861vd_volume_init_verbs[] = {
9208	/*
9209	 * Unmute ADC0 and set the default input to mic-in
9210	 */
9211	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
9212	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9213
9214	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
9215	 * the analog-loopback mixer widget
9216	 */
9217	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
9218	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9219	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9220	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
9221	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
9222	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
9223
9224	/* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
9225	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9226	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9227	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
9228	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
9229
9230	/*
9231	 * Set up output mixers (0x02 - 0x05)
9232	 */
9233	/* set vol=0 to output mixers */
9234	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9235	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9236	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9237	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9238
9239	/* set up input amps for analog loopback */
9240	/* Amp Indices: DAC = 0, mixer = 1 */
9241	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9242	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9243	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9244	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9245	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9246	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9247	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9248	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9249
9250	{ }
9251};
9252
9253/*
9254 * 3-stack pin configuration:
9255 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
9256 */
9257static struct hda_verb alc861vd_3stack_init_verbs[] = {
9258	/*
9259	 * Set pin mode and muting
9260	 */
9261	/* set front pin widgets 0x14 for output */
9262	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9263	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9264	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9265
9266	/* Mic (rear) pin: input vref at 80% */
9267	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9268	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9269	/* Front Mic pin: input vref at 80% */
9270	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9271	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9272	/* Line In pin: input */
9273	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9274	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9275	/* Line-2 In: Headphone output (output 0 - 0x0c) */
9276	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9277	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9278	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9279	/* CD pin widget for input */
9280	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9281
9282	{ }
9283};
9284
9285/*
9286 * 6-stack pin configuration:
9287 */
9288static struct hda_verb alc861vd_6stack_init_verbs[] = {
9289	/*
9290	 * Set pin mode and muting
9291	 */
9292	/* set front pin widgets 0x14 for output */
9293	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9294	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9295	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9296
9297	/* Rear Pin: output 1 (0x0d) */
9298	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9299	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9300	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
9301	/* CLFE Pin: output 2 (0x0e) */
9302	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9303	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9304	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
9305	/* Side Pin: output 3 (0x0f) */
9306	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9307	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9308	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
9309
9310	/* Mic (rear) pin: input vref at 80% */
9311	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9312	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9313	/* Front Mic pin: input vref at 80% */
9314	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9315	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9316	/* Line In pin: input */
9317	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9318	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9319	/* Line-2 In: Headphone output (output 0 - 0x0c) */
9320	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9321	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9322	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9323	/* CD pin widget for input */
9324	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9325
9326	{ }
9327};
9328
9329static struct hda_verb alc861vd_eapd_verbs[] = {
9330	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
9331	{ }
9332};
9333
9334static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
9335	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9336	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9337	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
9338	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
9339	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
9340	{}
9341};
9342
9343/* toggle speaker-output according to the hp-jack state */
9344static void alc861vd_lenovo_hp_automute(struct hda_codec *codec)
9345{
9346	unsigned int present;
9347	unsigned char bits;
9348
9349	present = snd_hda_codec_read(codec, 0x1b, 0,
9350				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
9351	bits = present ? 0x80 : 0;
9352	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
9353				 0x80, bits);
9354	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
9355				 0x80, bits);
9356}
9357
9358static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
9359{
9360	unsigned int present;
9361	unsigned char bits;
9362
9363	present = snd_hda_codec_read(codec, 0x18, 0,
9364				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
9365	bits = present ? 0x80 : 0;
9366	snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1,
9367				 0x80, bits);
9368	snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1,
9369				 0x80, bits);
9370}
9371
9372static void alc861vd_lenovo_automute(struct hda_codec *codec)
9373{
9374	alc861vd_lenovo_hp_automute(codec);
9375	alc861vd_lenovo_mic_automute(codec);
9376}
9377
9378static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
9379					unsigned int res)
9380{
9381	switch (res >> 26) {
9382	case ALC880_HP_EVENT:
9383		alc861vd_lenovo_hp_automute(codec);
9384		break;
9385	case ALC880_MIC_EVENT:
9386		alc861vd_lenovo_mic_automute(codec);
9387		break;
9388	}
9389}
9390
9391static struct hda_verb alc861vd_dallas_verbs[] = {
9392	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9393	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9394	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9395	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9396
9397	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9398	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9399	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9400	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9401	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9402	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9403	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9404	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9405
9406	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9407	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9408	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9409	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9410	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9411	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9412	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9413	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9414
9415	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
9416	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9417	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
9418	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9419	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9420	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9421	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9422	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9423
9424	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9425	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
9426	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
9427	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
9428
9429	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9430	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
9431	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
9432
9433	{ } /* end */
9434};
9435
9436/* toggle speaker-output according to the hp-jack state */
9437static void alc861vd_dallas_automute(struct hda_codec *codec)
9438{
9439	unsigned int present;
9440
9441	present = snd_hda_codec_read(codec, 0x15, 0,
9442				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
9443	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
9444				 0x80, present ? 0x80 : 0);
9445	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
9446				 0x80, present ? 0x80 : 0);
9447}
9448
9449static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res)
9450{
9451	if ((res >> 26) == ALC880_HP_EVENT)
9452		alc861vd_dallas_automute(codec);
9453}
9454
9455/* pcm configuration: identiacal with ALC880 */
9456#define alc861vd_pcm_analog_playback	alc880_pcm_analog_playback
9457#define alc861vd_pcm_analog_capture	alc880_pcm_analog_capture
9458#define alc861vd_pcm_digital_playback	alc880_pcm_digital_playback
9459#define alc861vd_pcm_digital_capture	alc880_pcm_digital_capture
9460
9461/*
9462 * configuration and preset
9463 */
9464static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
9465	[ALC660VD_3ST]		= "3stack-660",
9466	[ALC861VD_3ST]		= "3stack",
9467	[ALC861VD_3ST_DIG]	= "3stack-digout",
9468	[ALC861VD_6ST_DIG]	= "6stack-digout",
9469	[ALC861VD_LENOVO]	= "lenovo",
9470	[ALC861VD_DALLAS]	= "dallas",
9471	[ALC861VD_AUTO]		= "auto",
9472};
9473
9474static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
9475	SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
9476	SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
9477	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST),
9478	SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
9479	SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
9480
9481	SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),
9482	SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
9483	SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
9484	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
9485	{}
9486};
9487
9488static struct alc_config_preset alc861vd_presets[] = {
9489	[ALC660VD_3ST] = {
9490		.mixers = { alc861vd_3st_mixer },
9491		.init_verbs = { alc861vd_volume_init_verbs,
9492				 alc861vd_3stack_init_verbs },
9493		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
9494		.dac_nids = alc660vd_dac_nids,
9495		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
9496		.adc_nids = alc861vd_adc_nids,
9497		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
9498		.channel_mode = alc861vd_3stack_2ch_modes,
9499		.input_mux = &alc861vd_capture_source,
9500	},
9501	[ALC861VD_3ST] = {
9502		.mixers = { alc861vd_3st_mixer },
9503		.init_verbs = { alc861vd_volume_init_verbs,
9504				 alc861vd_3stack_init_verbs },
9505		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
9506		.dac_nids = alc861vd_dac_nids,
9507		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
9508		.channel_mode = alc861vd_3stack_2ch_modes,
9509		.input_mux = &alc861vd_capture_source,
9510	},
9511	[ALC861VD_3ST_DIG] = {
9512		.mixers = { alc861vd_3st_mixer },
9513		.init_verbs = { alc861vd_volume_init_verbs,
9514		 		 alc861vd_3stack_init_verbs },
9515		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
9516		.dac_nids = alc861vd_dac_nids,
9517		.dig_out_nid = ALC861VD_DIGOUT_NID,
9518		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
9519		.channel_mode = alc861vd_3stack_2ch_modes,
9520		.input_mux = &alc861vd_capture_source,
9521	},
9522	[ALC861VD_6ST_DIG] = {
9523		.mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
9524		.init_verbs = { alc861vd_volume_init_verbs,
9525				alc861vd_6stack_init_verbs },
9526		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
9527		.dac_nids = alc861vd_dac_nids,
9528		.dig_out_nid = ALC861VD_DIGOUT_NID,
9529		.num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
9530		.channel_mode = alc861vd_6stack_modes,
9531		.input_mux = &alc861vd_capture_source,
9532	},
9533	[ALC861VD_LENOVO] = {
9534		.mixers = { alc861vd_lenovo_mixer },
9535		.init_verbs = { alc861vd_volume_init_verbs,
9536				alc861vd_3stack_init_verbs,
9537				alc861vd_eapd_verbs,
9538				alc861vd_lenovo_unsol_verbs },
9539		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
9540		.dac_nids = alc660vd_dac_nids,
9541		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
9542		.adc_nids = alc861vd_adc_nids,
9543		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
9544		.channel_mode = alc861vd_3stack_2ch_modes,
9545		.input_mux = &alc861vd_capture_source,
9546		.unsol_event = alc861vd_lenovo_unsol_event,
9547		.init_hook = alc861vd_lenovo_automute,
9548	},
9549	[ALC861VD_DALLAS] = {
9550		.mixers = { alc861vd_dallas_mixer },
9551		.init_verbs = { alc861vd_dallas_verbs },
9552		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
9553		.dac_nids = alc861vd_dac_nids,
9554		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
9555		.adc_nids = alc861vd_adc_nids,
9556		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
9557		.channel_mode = alc861vd_3stack_2ch_modes,
9558		.input_mux = &alc861vd_dallas_capture_source,
9559		.unsol_event = alc861vd_dallas_unsol_event,
9560		.init_hook = alc861vd_dallas_automute,
9561	},
9562};
9563
9564/*
9565 * BIOS auto configuration
9566 */
9567static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
9568				hda_nid_t nid, int pin_type, int dac_idx)
9569{
9570	/* set as output */
9571	snd_hda_codec_write(codec, nid, 0,
9572				AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
9573	snd_hda_codec_write(codec, nid, 0,
9574				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
9575}
9576
9577static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
9578{
9579	struct alc_spec *spec = codec->spec;
9580	int i;
9581
9582	alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
9583	for (i = 0; i <= HDA_SIDE; i++) {
9584		hda_nid_t nid = spec->autocfg.line_out_pins[i];
9585		int pin_type = get_pin_type(spec->autocfg.line_out_type);
9586		if (nid)
9587			alc861vd_auto_set_output_and_unmute(codec, nid,
9588							    pin_type, i);
9589	}
9590}
9591
9592
9593static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
9594{
9595	struct alc_spec *spec = codec->spec;
9596	hda_nid_t pin;
9597
9598	pin = spec->autocfg.hp_pins[0];
9599	if (pin) /* connect to front and  use dac 0 */
9600		alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
9601}
9602
9603#define alc861vd_is_input_pin(nid)	alc880_is_input_pin(nid)
9604#define ALC861VD_PIN_CD_NID		ALC880_PIN_CD_NID
9605
9606static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
9607{
9608	struct alc_spec *spec = codec->spec;
9609	int i;
9610
9611	for (i = 0; i < AUTO_PIN_LAST; i++) {
9612		hda_nid_t nid = spec->autocfg.input_pins[i];
9613		if (alc861vd_is_input_pin(nid)) {
9614			snd_hda_codec_write(codec, nid, 0,
9615					AC_VERB_SET_PIN_WIDGET_CONTROL,
9616					i <= AUTO_PIN_FRONT_MIC ?
9617							PIN_VREF80 : PIN_IN);
9618			if (nid != ALC861VD_PIN_CD_NID)
9619				snd_hda_codec_write(codec, nid, 0,
9620						AC_VERB_SET_AMP_GAIN_MUTE,
9621						AMP_OUT_MUTE);
9622		}
9623	}
9624}
9625
9626#define alc861vd_idx_to_mixer_vol(nid)		((nid) + 0x02)
9627#define alc861vd_idx_to_mixer_switch(nid)	((nid) + 0x0c)
9628
9629/* add playback controls from the parsed DAC table */
9630/* Based on ALC880 version. But ALC861VD has separate,
9631 * different NIDs for mute/unmute switch and volume control */
9632static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
9633					     const struct auto_pin_cfg *cfg)
9634{
9635	char name[32];
9636	static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
9637	hda_nid_t nid_v, nid_s;
9638	int i, err;
9639
9640	for (i = 0; i < cfg->line_outs; i++) {
9641		if (!spec->multiout.dac_nids[i])
9642			continue;
9643		nid_v = alc861vd_idx_to_mixer_vol(
9644				alc880_dac_to_idx(
9645					spec->multiout.dac_nids[i]));
9646		nid_s = alc861vd_idx_to_mixer_switch(
9647				alc880_dac_to_idx(
9648					spec->multiout.dac_nids[i]));
9649
9650		if (i == 2) {
9651			/* Center/LFE */
9652			err = add_control(spec, ALC_CTL_WIDGET_VOL,
9653					  "Center Playback Volume",
9654					  HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
9655							      HDA_OUTPUT));
9656			if (err < 0)
9657				return err;
9658			err = add_control(spec, ALC_CTL_WIDGET_VOL,
9659					  "LFE Playback Volume",
9660					  HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
9661							      HDA_OUTPUT));
9662			if (err < 0)
9663				return err;
9664			err = add_control(spec, ALC_CTL_BIND_MUTE,
9665					  "Center Playback Switch",
9666					  HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
9667							      HDA_INPUT));
9668			if (err < 0)
9669				return err;
9670			err = add_control(spec, ALC_CTL_BIND_MUTE,
9671					  "LFE Playback Switch",
9672					  HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
9673							      HDA_INPUT));
9674			if (err < 0)
9675				return err;
9676		} else {
9677			sprintf(name, "%s Playback Volume", chname[i]);
9678			err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
9679					  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
9680							      HDA_OUTPUT));
9681			if (err < 0)
9682				return err;
9683			sprintf(name, "%s Playback Switch", chname[i]);
9684			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
9685					  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
9686							      HDA_INPUT));
9687			if (err < 0)
9688				return err;
9689		}
9690	}
9691	return 0;
9692}
9693
9694/* add playback controls for speaker and HP outputs */
9695/* Based on ALC880 version. But ALC861VD has separate,
9696 * different NIDs for mute/unmute switch and volume control */
9697static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
9698					hda_nid_t pin, const char *pfx)
9699{
9700	hda_nid_t nid_v, nid_s;
9701	int err;
9702	char name[32];
9703
9704	if (!pin)
9705		return 0;
9706
9707	if (alc880_is_fixed_pin(pin)) {
9708		nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
9709		/* specify the DAC as the extra output */
9710		if (!spec->multiout.hp_nid)
9711			spec->multiout.hp_nid = nid_v;
9712		else
9713			spec->multiout.extra_out_nid[0] = nid_v;
9714		/* control HP volume/switch on the output mixer amp */
9715		nid_v = alc861vd_idx_to_mixer_vol(
9716				alc880_fixed_pin_idx(pin));
9717		nid_s = alc861vd_idx_to_mixer_switch(
9718				alc880_fixed_pin_idx(pin));
9719
9720		sprintf(name, "%s Playback Volume", pfx);
9721		err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
9722				  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
9723		if (err < 0)
9724			return err;
9725		sprintf(name, "%s Playback Switch", pfx);
9726		err = add_control(spec, ALC_CTL_BIND_MUTE, name,
9727				  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
9728		if (err < 0)
9729			return err;
9730	} else if (alc880_is_multi_pin(pin)) {
9731		/* set manual connection */
9732		/* we have only a switch on HP-out PIN */
9733		sprintf(name, "%s Playback Switch", pfx);
9734		err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
9735				  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
9736		if (err < 0)
9737			return err;
9738	}
9739	return 0;
9740}
9741
9742/* parse the BIOS configuration and set up the alc_spec
9743 * return 1 if successful, 0 if the proper config is not found,
9744 * or a negative error code
9745 * Based on ALC880 version - had to change it to override
9746 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
9747static int alc861vd_parse_auto_config(struct hda_codec *codec)
9748{
9749	struct alc_spec *spec = codec->spec;
9750	int err;
9751	static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
9752
9753	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
9754					   alc861vd_ignore);
9755	if (err < 0)
9756		return err;
9757	if (!spec->autocfg.line_outs)
9758		return 0; /* can't find valid BIOS pin config */
9759
9760	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
9761	if (err < 0)
9762		return err;
9763	err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
9764	if (err < 0)
9765		return err;
9766	err = alc861vd_auto_create_extra_out(spec,
9767					     spec->autocfg.speaker_pins[0],
9768					     "Speaker");
9769	if (err < 0)
9770		return err;
9771	err = alc861vd_auto_create_extra_out(spec,
9772					     spec->autocfg.hp_pins[0],
9773					     "Headphone");
9774	if (err < 0)
9775		return err;
9776	err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);
9777	if (err < 0)
9778		return err;
9779
9780	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
9781
9782	if (spec->autocfg.dig_out_pin)
9783		spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
9784
9785	if (spec->kctl_alloc)
9786		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
9787
9788	spec->init_verbs[spec->num_init_verbs++]
9789		= alc861vd_volume_init_verbs;
9790
9791	spec->num_mux_defs = 1;
9792	spec->input_mux = &spec->private_imux;
9793
9794	return 1;
9795}
9796
9797/* additional initialization for auto-configuration model */
9798static void alc861vd_auto_init(struct hda_codec *codec)
9799{
9800	alc861vd_auto_init_multi_out(codec);
9801	alc861vd_auto_init_hp_out(codec);
9802	alc861vd_auto_init_analog_input(codec);
9803}
9804
9805static int patch_alc861vd(struct hda_codec *codec)
9806{
9807	struct alc_spec *spec;
9808	int err, board_config;
9809
9810	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
9811	if (spec == NULL)
9812		return -ENOMEM;
9813
9814	codec->spec = spec;
9815
9816	board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
9817						  alc861vd_models,
9818						  alc861vd_cfg_tbl);
9819
9820	if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
9821		printk(KERN_INFO "hda_codec: Unknown model for ALC660VD/"
9822			"ALC861VD, trying auto-probe from BIOS...\n");
9823		board_config = ALC861VD_AUTO;
9824	}
9825
9826	if (board_config == ALC861VD_AUTO) {
9827		/* automatic parse from the BIOS config */
9828		err = alc861vd_parse_auto_config(codec);
9829		if (err < 0) {
9830			alc_free(codec);
9831			return err;
9832		} else if (!err) {
9833			printk(KERN_INFO
9834			       "hda_codec: Cannot set up configuration "
9835			       "from BIOS.  Using base mode...\n");
9836			board_config = ALC861VD_3ST;
9837		}
9838	}
9839
9840	if (board_config != ALC861VD_AUTO)
9841		setup_preset(spec, &alc861vd_presets[board_config]);
9842
9843	spec->stream_name_analog = "ALC861VD Analog";
9844	spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
9845	spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
9846
9847	spec->stream_name_digital = "ALC861VD Digital";
9848	spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
9849	spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
9850
9851	spec->adc_nids = alc861vd_adc_nids;
9852	spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
9853
9854	spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
9855	spec->num_mixers++;
9856
9857	codec->patch_ops = alc_patch_ops;
9858
9859	if (board_config == ALC861VD_AUTO)
9860		spec->init_hook = alc861vd_auto_init;
9861
9862	return 0;
9863}
9864
9865/*
9866 * ALC662 support
9867 *
9868 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
9869 * configuration.  Each pin widget can choose any input DACs and a mixer.
9870 * Each ADC is connected from a mixer of all inputs.  This makes possible
9871 * 6-channel independent captures.
9872 *
9873 * In addition, an independent DAC for the multi-playback (not used in this
9874 * driver yet).
9875 */
9876#define ALC662_DIGOUT_NID	0x06
9877#define ALC662_DIGIN_NID	0x0a
9878
9879static hda_nid_t alc662_dac_nids[4] = {
9880	/* front, rear, clfe, rear_surr */
9881	0x02, 0x03, 0x04
9882};
9883
9884static hda_nid_t alc662_adc_nids[1] = {
9885	/* ADC1-2 */
9886	0x09,
9887};
9888/* input MUX */
9889/* FIXME: should be a matrix-type input source selection */
9890
9891static struct hda_input_mux alc662_capture_source = {
9892	.num_items = 4,
9893	.items = {
9894		{ "Mic", 0x0 },
9895		{ "Front Mic", 0x1 },
9896		{ "Line", 0x2 },
9897		{ "CD", 0x4 },
9898	},
9899};
9900
9901static struct hda_input_mux alc662_lenovo_101e_capture_source = {
9902	.num_items = 2,
9903	.items = {
9904		{ "Mic", 0x1 },
9905		{ "Line", 0x2 },
9906	},
9907};
9908#define alc662_mux_enum_info alc_mux_enum_info
9909#define alc662_mux_enum_get alc_mux_enum_get
9910
9911static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol,
9912			       struct snd_ctl_elem_value *ucontrol)
9913{
9914	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9915	struct alc_spec *spec = codec->spec;
9916	const struct hda_input_mux *imux = spec->input_mux;
9917	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
9918	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
9919	hda_nid_t nid = capture_mixers[adc_idx];
9920	unsigned int *cur_val = &spec->cur_mux[adc_idx];
9921	unsigned int i, idx;
9922
9923	idx = ucontrol->value.enumerated.item[0];
9924	if (idx >= imux->num_items)
9925		idx = imux->num_items - 1;
9926	if (*cur_val == idx && !codec->in_resume)
9927		return 0;
9928	for (i = 0; i < imux->num_items; i++) {
9929		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
9930		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
9931				    v | (imux->items[i].index << 8));
9932	}
9933	*cur_val = idx;
9934	return 1;
9935}
9936/*
9937 * 2ch mode
9938 */
9939static struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
9940	{ 2, NULL }
9941};
9942
9943/*
9944 * 2ch mode
9945 */
9946static struct hda_verb alc662_3ST_ch2_init[] = {
9947	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
9948	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9949	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
9950	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9951	{ } /* end */
9952};
9953
9954/*
9955 * 6ch mode
9956 */
9957static struct hda_verb alc662_3ST_ch6_init[] = {
9958	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9959	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9960	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
9961	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9962	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9963	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
9964	{ } /* end */
9965};
9966
9967static struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
9968	{ 2, alc662_3ST_ch2_init },
9969	{ 6, alc662_3ST_ch6_init },
9970};
9971
9972/*
9973 * 2ch mode
9974 */
9975static struct hda_verb alc662_sixstack_ch6_init[] = {
9976	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
9977	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
9978	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9979	{ } /* end */
9980};
9981
9982/*
9983 * 6ch mode
9984 */
9985static struct hda_verb alc662_sixstack_ch8_init[] = {
9986	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9987	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9988	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9989	{ } /* end */
9990};
9991
9992static struct hda_channel_mode alc662_5stack_modes[2] = {
9993	{ 2, alc662_sixstack_ch6_init },
9994	{ 6, alc662_sixstack_ch8_init },
9995};
9996
9997/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
9998 *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
9999 */
10000
10001static struct snd_kcontrol_new alc662_base_mixer[] = {
10002	/* output mixer control */
10003	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
10004	HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT),
10005	HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
10006	HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT),
10007	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
10008	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
10009	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
10010	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
10011	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10012
10013	/*Input mixer control */
10014	HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
10015	HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
10016	HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
10017	HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
10018	HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
10019	HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
10020	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
10021	HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
10022
10023	/* Capture mixer control */
10024	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
10025	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
10026	{
10027		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10028		.name = "Capture Source",
10029		.count = 1,
10030		.info = alc_mux_enum_info,
10031		.get = alc_mux_enum_get,
10032		.put = alc_mux_enum_put,
10033	},
10034	{ } /* end */
10035};
10036
10037static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
10038	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
10039	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
10040	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10041	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10042	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10043	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10044	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10045	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10046	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10047	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
10048	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
10049	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
10050	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
10051	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
10052	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
10053	{
10054		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10055		/* .name = "Capture Source", */
10056		.name = "Input Source",
10057		.count = 1,
10058		.info = alc662_mux_enum_info,
10059		.get = alc662_mux_enum_get,
10060		.put = alc662_mux_enum_put,
10061	},
10062	{ } /* end */
10063};
10064
10065static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
10066	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
10067	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
10068	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
10069	HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),
10070	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
10071	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
10072	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
10073	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
10074	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10075	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10076	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10077	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10078	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10079	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10080	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10081	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
10082	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
10083	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
10084	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
10085	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
10086	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
10087	{
10088		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10089		/* .name = "Capture Source", */
10090		.name = "Input Source",
10091		.count = 1,
10092		.info = alc662_mux_enum_info,
10093		.get = alc662_mux_enum_get,
10094		.put = alc662_mux_enum_put,
10095	},
10096	{ } /* end */
10097};
10098
10099static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
10100	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
10101	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
10102	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
10103	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x03, 2, HDA_INPUT),
10104	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10105	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10106	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10107	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
10108	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
10109	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
10110	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
10111	{
10112		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10113		/* .name = "Capture Source", */
10114		.name = "Input Source",
10115		.count = 1,
10116		.info = alc662_mux_enum_info,
10117		.get = alc662_mux_enum_get,
10118		.put = alc662_mux_enum_put,
10119	},
10120	{ } /* end */
10121};
10122
10123static struct snd_kcontrol_new alc662_chmode_mixer[] = {
10124	{
10125		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10126		.name = "Channel Mode",
10127		.info = alc_ch_mode_info,
10128		.get = alc_ch_mode_get,
10129		.put = alc_ch_mode_put,
10130	},
10131	{ } /* end */
10132};
10133
10134static struct hda_verb alc662_init_verbs[] = {
10135	/* ADC: mute amp left and right */
10136	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
10137	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
10138	/* Front mixer: unmute input/output amp left and right (volume = 0) */
10139
10140	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10141	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10142	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
10143	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
10144	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
10145
10146	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10147	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10148	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10149	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10150	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10151	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10152
10153	/* Front Pin: output 0 (0x0c) */
10154	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10155	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10156
10157	/* Rear Pin: output 1 (0x0d) */
10158	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10159	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10160
10161	/* CLFE Pin: output 2 (0x0e) */
10162	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10163	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10164
10165	/* Mic (rear) pin: input vref at 80% */
10166	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
10167	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10168	/* Front Mic pin: input vref at 80% */
10169	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
10170	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10171	/* Line In pin: input */
10172	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
10173	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10174	/* Line-2 In: Headphone output (output 0 - 0x0c) */
10175	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10176	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10177	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
10178	/* CD pin widget for input */
10179	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
10180
10181	/* FIXME: use matrix-type input source selection */
10182	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
10183	/* Input mixer */
10184	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10185	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10186	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
10187	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
10188	{ }
10189};
10190
10191static struct hda_verb alc662_sue_init_verbs[] = {
10192	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
10193	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
10194        {}
10195};
10196
10197/*
10198 * generic initialization of ADC, input mixers and output mixers
10199 */
10200static struct hda_verb alc662_auto_init_verbs[] = {
10201	/*
10202	 * Unmute ADC and set the default input to mic-in
10203	 */
10204	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
10205	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10206
10207	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
10208	 * mixer widget
10209	 * Note: PASD motherboards uses the Line In 2 as the input for front
10210	 * panel mic (mic 2)
10211	 */
10212	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
10213	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10214	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10215	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
10216	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
10217	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
10218
10219	/*
10220	 * Set up output mixers (0x0c - 0x0f)
10221	 */
10222	/* set vol=0 to output mixers */
10223	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10224	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10225	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10226
10227	/* set up input amps for analog loopback */
10228	/* Amp Indices: DAC = 0, mixer = 1 */
10229	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10230	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10231	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10232	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10233	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10234	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10235
10236
10237	/* FIXME: use matrix-type input source selection */
10238	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
10239	/* Input mixer */
10240	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10241	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10242	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
10243	/*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/
10244	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
10245
10246	{ }
10247};
10248
10249/* capture mixer elements */
10250static struct snd_kcontrol_new alc662_capture_mixer[] = {
10251	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
10252	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
10253	{
10254		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10255		/* The multiple "Capture Source" controls confuse alsamixer
10256		 * So call somewhat different..
10257		 * FIXME: the controls appear in the "playback" view!
10258		 */
10259		/* .name = "Capture Source", */
10260		.name = "Input Source",
10261		.count = 1,
10262		.info = alc882_mux_enum_info,
10263		.get = alc882_mux_enum_get,
10264		.put = alc882_mux_enum_put,
10265	},
10266	{ } /* end */
10267};
10268
10269static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
10270{
10271	unsigned int present;
10272	unsigned char bits;
10273
10274	present = snd_hda_codec_read(codec, 0x14, 0,
10275				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
10276	bits = present ? 0x80 : 0;
10277	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
10278				 0x80, bits);
10279	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
10280				 0x80, bits);
10281}
10282
10283static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
10284{
10285	unsigned int present;
10286	unsigned char bits;
10287
10288 	present = snd_hda_codec_read(codec, 0x1b, 0,
10289				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
10290	bits = present ? 0x80 : 0;
10291	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
10292				 0x80, bits);
10293	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
10294				 0x80, bits);
10295	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
10296				 0x80, bits);
10297	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
10298				 0x80, bits);
10299}
10300
10301static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
10302					   unsigned int res)
10303{
10304	if ((res >> 26) == ALC880_HP_EVENT)
10305		alc662_lenovo_101e_all_automute(codec);
10306	if ((res >> 26) == ALC880_FRONT_EVENT)
10307		alc662_lenovo_101e_ispeaker_automute(codec);
10308}
10309
10310
10311/* pcm configuration: identiacal with ALC880 */
10312#define alc662_pcm_analog_playback	alc880_pcm_analog_playback
10313#define alc662_pcm_analog_capture	alc880_pcm_analog_capture
10314#define alc662_pcm_digital_playback	alc880_pcm_digital_playback
10315#define alc662_pcm_digital_capture	alc880_pcm_digital_capture
10316
10317/*
10318 * configuration and preset
10319 */
10320static const char *alc662_models[ALC662_MODEL_LAST] = {
10321	[ALC662_3ST_2ch_DIG]	= "3stack-dig",
10322	[ALC662_3ST_6ch_DIG]	= "3stack-6ch-dig",
10323	[ALC662_3ST_6ch]	= "3stack-6ch",
10324	[ALC662_5ST_DIG]	= "6stack-dig",
10325	[ALC662_LENOVO_101E]	= "lenovo-101e",
10326	[ALC662_AUTO]		= "auto",
10327};
10328
10329static struct snd_pci_quirk alc662_cfg_tbl[] = {
10330	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
10331	{}
10332};
10333
10334static struct alc_config_preset alc662_presets[] = {
10335	[ALC662_3ST_2ch_DIG] = {
10336		.mixers = { alc662_3ST_2ch_mixer },
10337		.init_verbs = { alc662_init_verbs },
10338		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
10339		.dac_nids = alc662_dac_nids,
10340		.dig_out_nid = ALC662_DIGOUT_NID,
10341		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
10342		.adc_nids = alc662_adc_nids,
10343		.dig_in_nid = ALC662_DIGIN_NID,
10344		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
10345		.channel_mode = alc662_3ST_2ch_modes,
10346		.input_mux = &alc662_capture_source,
10347	},
10348	[ALC662_3ST_6ch_DIG] = {
10349		.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
10350		.init_verbs = { alc662_init_verbs },
10351		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
10352		.dac_nids = alc662_dac_nids,
10353		.dig_out_nid = ALC662_DIGOUT_NID,
10354		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
10355		.adc_nids = alc662_adc_nids,
10356		.dig_in_nid = ALC662_DIGIN_NID,
10357		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
10358		.channel_mode = alc662_3ST_6ch_modes,
10359		.need_dac_fix = 1,
10360		.input_mux = &alc662_capture_source,
10361	},
10362	[ALC662_3ST_6ch] = {
10363		.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
10364		.init_verbs = { alc662_init_verbs },
10365		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
10366		.dac_nids = alc662_dac_nids,
10367		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
10368		.adc_nids = alc662_adc_nids,
10369		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
10370		.channel_mode = alc662_3ST_6ch_modes,
10371		.need_dac_fix = 1,
10372		.input_mux = &alc662_capture_source,
10373	},
10374	[ALC662_5ST_DIG] = {
10375		.mixers = { alc662_base_mixer, alc662_chmode_mixer },
10376		.init_verbs = { alc662_init_verbs },
10377		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
10378		.dac_nids = alc662_dac_nids,
10379		.dig_out_nid = ALC662_DIGOUT_NID,
10380		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
10381		.adc_nids = alc662_adc_nids,
10382		.dig_in_nid = ALC662_DIGIN_NID,
10383		.num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
10384		.channel_mode = alc662_5stack_modes,
10385		.input_mux = &alc662_capture_source,
10386	},
10387	[ALC662_LENOVO_101E] = {
10388		.mixers = { alc662_lenovo_101e_mixer },
10389		.init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
10390		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
10391		.dac_nids = alc662_dac_nids,
10392		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
10393		.adc_nids = alc662_adc_nids,
10394		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
10395		.channel_mode = alc662_3ST_2ch_modes,
10396		.input_mux = &alc662_lenovo_101e_capture_source,
10397		.unsol_event = alc662_lenovo_101e_unsol_event,
10398		.init_hook = alc662_lenovo_101e_all_automute,
10399	},
10400
10401};
10402
10403
10404/*
10405 * BIOS auto configuration
10406 */
10407
10408/* add playback controls from the parsed DAC table */
10409static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
10410					     const struct auto_pin_cfg *cfg)
10411{
10412	char name[32];
10413	static const char *chname[4] = {
10414		"Front", "Surround", NULL /*CLFE*/, "Side"
10415	};
10416	hda_nid_t nid;
10417	int i, err;
10418
10419	for (i = 0; i < cfg->line_outs; i++) {
10420		if (!spec->multiout.dac_nids[i])
10421			continue;
10422		nid = alc880_idx_to_dac(i);
10423		if (i == 2) {
10424			/* Center/LFE */
10425			err = add_control(spec, ALC_CTL_WIDGET_VOL,
10426					  "Center Playback Volume",
10427					  HDA_COMPOSE_AMP_VAL(nid, 1, 0,
10428							      HDA_OUTPUT));
10429			if (err < 0)
10430				return err;
10431			err = add_control(spec, ALC_CTL_WIDGET_VOL,
10432					  "LFE Playback Volume",
10433					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
10434							      HDA_OUTPUT));
10435			if (err < 0)
10436				return err;
10437			err = add_control(spec, ALC_CTL_BIND_MUTE,
10438					  "Center Playback Switch",
10439					  HDA_COMPOSE_AMP_VAL(nid, 1, 2,
10440							      HDA_INPUT));
10441			if (err < 0)
10442				return err;
10443			err = add_control(spec, ALC_CTL_BIND_MUTE,
10444					  "LFE Playback Switch",
10445					  HDA_COMPOSE_AMP_VAL(nid, 2, 2,
10446							      HDA_INPUT));
10447			if (err < 0)
10448				return err;
10449		} else {
10450			sprintf(name, "%s Playback Volume", chname[i]);
10451			err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
10452					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
10453							      HDA_OUTPUT));
10454			if (err < 0)
10455				return err;
10456			sprintf(name, "%s Playback Switch", chname[i]);
10457			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
10458					  HDA_COMPOSE_AMP_VAL(nid, 3, 2,
10459							      HDA_INPUT));
10460			if (err < 0)
10461				return err;
10462		}
10463	}
10464	return 0;
10465}
10466
10467/* add playback controls for speaker and HP outputs */
10468static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
10469					const char *pfx)
10470{
10471	hda_nid_t nid;
10472	int err;
10473	char name[32];
10474
10475	if (!pin)
10476		return 0;
10477
10478	if (alc880_is_fixed_pin(pin)) {
10479		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
10480                /* printk("DAC nid=%x\n",nid); */
10481		/* specify the DAC as the extra output */
10482		if (!spec->multiout.hp_nid)
10483			spec->multiout.hp_nid = nid;
10484		else
10485			spec->multiout.extra_out_nid[0] = nid;
10486		/* control HP volume/switch on the output mixer amp */
10487		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
10488		sprintf(name, "%s Playback Volume", pfx);
10489		err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
10490				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
10491		if (err < 0)
10492			return err;
10493		sprintf(name, "%s Playback Switch", pfx);
10494		err = add_control(spec, ALC_CTL_BIND_MUTE, name,
10495				  HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
10496		if (err < 0)
10497			return err;
10498	} else if (alc880_is_multi_pin(pin)) {
10499		/* set manual connection */
10500		/* we have only a switch on HP-out PIN */
10501		sprintf(name, "%s Playback Switch", pfx);
10502		err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
10503				  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
10504		if (err < 0)
10505			return err;
10506	}
10507	return 0;
10508}
10509
10510/* create playback/capture controls for input pins */
10511static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec,
10512						const struct auto_pin_cfg *cfg)
10513{
10514	struct hda_input_mux *imux = &spec->private_imux;
10515	int i, err, idx;
10516
10517	for (i = 0; i < AUTO_PIN_LAST; i++) {
10518		if (alc880_is_input_pin(cfg->input_pins[i])) {
10519			idx = alc880_input_pin_idx(cfg->input_pins[i]);
10520			err = new_analog_input(spec, cfg->input_pins[i],
10521					       auto_pin_cfg_labels[i],
10522					       idx, 0x0b);
10523			if (err < 0)
10524				return err;
10525			imux->items[imux->num_items].label =
10526				auto_pin_cfg_labels[i];
10527			imux->items[imux->num_items].index =
10528				alc880_input_pin_idx(cfg->input_pins[i]);
10529			imux->num_items++;
10530		}
10531	}
10532	return 0;
10533}
10534
10535static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
10536					      hda_nid_t nid, int pin_type,
10537					      int dac_idx)
10538{
10539	/* set as output */
10540	snd_hda_codec_write(codec, nid, 0,
10541			    AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
10542	snd_hda_codec_write(codec, nid, 0,
10543			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
10544	/* need the manual connection? */
10545	if (alc880_is_multi_pin(nid)) {
10546		struct alc_spec *spec = codec->spec;
10547		int idx = alc880_multi_pin_idx(nid);
10548		snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
10549				    AC_VERB_SET_CONNECT_SEL,
10550				    alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
10551	}
10552}
10553
10554static void alc662_auto_init_multi_out(struct hda_codec *codec)
10555{
10556	struct alc_spec *spec = codec->spec;
10557	int i;
10558
10559	for (i = 0; i <= HDA_SIDE; i++) {
10560		hda_nid_t nid = spec->autocfg.line_out_pins[i];
10561		int pin_type = get_pin_type(spec->autocfg.line_out_type);
10562		if (nid)
10563			alc662_auto_set_output_and_unmute(codec, nid, pin_type,
10564							  i);
10565	}
10566}
10567
10568static void alc662_auto_init_hp_out(struct hda_codec *codec)
10569{
10570	struct alc_spec *spec = codec->spec;
10571	hda_nid_t pin;
10572
10573	pin = spec->autocfg.hp_pins[0];
10574	if (pin) /* connect to front */
10575		/* use dac 0 */
10576		alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
10577}
10578
10579#define alc662_is_input_pin(nid)	alc880_is_input_pin(nid)
10580#define ALC662_PIN_CD_NID		ALC880_PIN_CD_NID
10581
10582static void alc662_auto_init_analog_input(struct hda_codec *codec)
10583{
10584	struct alc_spec *spec = codec->spec;
10585	int i;
10586
10587	for (i = 0; i < AUTO_PIN_LAST; i++) {
10588		hda_nid_t nid = spec->autocfg.input_pins[i];
10589		if (alc662_is_input_pin(nid)) {
10590			snd_hda_codec_write(codec, nid, 0,
10591					    AC_VERB_SET_PIN_WIDGET_CONTROL,
10592					    (i <= AUTO_PIN_FRONT_MIC ?
10593					     PIN_VREF80 : PIN_IN));
10594			if (nid != ALC662_PIN_CD_NID)
10595				snd_hda_codec_write(codec, nid, 0,
10596						    AC_VERB_SET_AMP_GAIN_MUTE,
10597						    AMP_OUT_MUTE);
10598		}
10599	}
10600}
10601
10602static int alc662_parse_auto_config(struct hda_codec *codec)
10603{
10604	struct alc_spec *spec = codec->spec;
10605	int err;
10606	static hda_nid_t alc662_ignore[] = { 0x1d, 0 };
10607
10608	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
10609					   alc662_ignore);
10610	if (err < 0)
10611		return err;
10612	if (!spec->autocfg.line_outs)
10613		return 0; /* can't find valid BIOS pin config */
10614
10615	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
10616	if (err < 0)
10617		return err;
10618	err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg);
10619	if (err < 0)
10620		return err;
10621	err = alc662_auto_create_extra_out(spec,
10622					   spec->autocfg.speaker_pins[0],
10623					   "Speaker");
10624	if (err < 0)
10625		return err;
10626	err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
10627					   "Headphone");
10628	if (err < 0)
10629		return err;
10630	err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg);
10631	if (err < 0)
10632		return err;
10633
10634	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
10635
10636	if (spec->autocfg.dig_out_pin)
10637		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
10638
10639	if (spec->kctl_alloc)
10640		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
10641
10642	spec->num_mux_defs = 1;
10643	spec->input_mux = &spec->private_imux;
10644
10645	if (err < 0)
10646		return err;
10647	else if (err > 0)
10648		/* hack - override the init verbs */
10649		spec->init_verbs[0] = alc662_auto_init_verbs;
10650	spec->mixers[spec->num_mixers] = alc662_capture_mixer;
10651	spec->num_mixers++;
10652	return err;
10653}
10654
10655/* additional initialization for auto-configuration model */
10656static void alc662_auto_init(struct hda_codec *codec)
10657{
10658	alc662_auto_init_multi_out(codec);
10659	alc662_auto_init_hp_out(codec);
10660	alc662_auto_init_analog_input(codec);
10661}
10662
10663static int patch_alc662(struct hda_codec *codec)
10664{
10665	struct alc_spec *spec;
10666	int err, board_config;
10667
10668	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
10669	if (!spec)
10670		return -ENOMEM;
10671
10672	codec->spec = spec;
10673
10674	board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
10675						  alc662_models,
10676			  	                  alc662_cfg_tbl);
10677	if (board_config < 0) {
10678		printk(KERN_INFO "hda_codec: Unknown model for ALC662, "
10679		       "trying auto-probe from BIOS...\n");
10680		board_config = ALC662_AUTO;
10681	}
10682
10683	if (board_config == ALC662_AUTO) {
10684		/* automatic parse from the BIOS config */
10685		err = alc662_parse_auto_config(codec);
10686		if (err < 0) {
10687			alc_free(codec);
10688			return err;
10689		} else if (err) {
10690			printk(KERN_INFO
10691			       "hda_codec: Cannot set up configuration "
10692			       "from BIOS.  Using base mode...\n");
10693			board_config = ALC662_3ST_2ch_DIG;
10694		}
10695	}
10696
10697	if (board_config != ALC662_AUTO)
10698		setup_preset(spec, &alc662_presets[board_config]);
10699
10700	spec->stream_name_analog = "ALC662 Analog";
10701	spec->stream_analog_playback = &alc662_pcm_analog_playback;
10702	spec->stream_analog_capture = &alc662_pcm_analog_capture;
10703
10704	spec->stream_name_digital = "ALC662 Digital";
10705	spec->stream_digital_playback = &alc662_pcm_digital_playback;
10706	spec->stream_digital_capture = &alc662_pcm_digital_capture;
10707
10708	if (!spec->adc_nids && spec->input_mux) {
10709		spec->adc_nids = alc662_adc_nids;
10710		spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
10711	}
10712
10713	codec->patch_ops = alc_patch_ops;
10714	if (board_config == ALC662_AUTO)
10715		spec->init_hook = alc662_auto_init;
10716
10717	return 0;
10718}
10719
10720/*
10721 * patch entries
10722 */
10723struct hda_codec_preset snd_hda_preset_realtek[] = {
10724	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
10725	{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
10726	{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
10727	  .patch = patch_alc861 },
10728	{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
10729	{ .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
10730	{ .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
10731	{ .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
10732	  .patch = patch_alc883 },
10733	{ .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
10734	  .patch = patch_alc662 },
10735	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
10736	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
10737	{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
10738	{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
10739	{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
10740	{} /* terminator */
10741};
10742