patch_realtek.c revision 7d87de2db2213e6e9413532445b14c92dae42c85
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, 0x7250, "MSI", ALC883_6ST_DIG),
6383	SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
6384	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
6385	SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
6386	SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
6387	SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
6388	SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
6389	SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
6390	SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
6391	SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
6392	SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
6393	SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
6394	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
6395	SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER),
6396	SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
6397	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
6398	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
6399	SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
6400	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
6401	SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
6402	SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
6403	SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
6404	{}
6405};
6406
6407static struct alc_config_preset alc883_presets[] = {
6408	[ALC883_3ST_2ch_DIG] = {
6409		.mixers = { alc883_3ST_2ch_mixer },
6410		.init_verbs = { alc883_init_verbs },
6411		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6412		.dac_nids = alc883_dac_nids,
6413		.dig_out_nid = ALC883_DIGOUT_NID,
6414		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6415		.adc_nids = alc883_adc_nids,
6416		.dig_in_nid = ALC883_DIGIN_NID,
6417		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6418		.channel_mode = alc883_3ST_2ch_modes,
6419		.input_mux = &alc883_capture_source,
6420	},
6421	[ALC883_3ST_6ch_DIG] = {
6422		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
6423		.init_verbs = { alc883_init_verbs },
6424		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6425		.dac_nids = alc883_dac_nids,
6426		.dig_out_nid = ALC883_DIGOUT_NID,
6427		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6428		.adc_nids = alc883_adc_nids,
6429		.dig_in_nid = ALC883_DIGIN_NID,
6430		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
6431		.channel_mode = alc883_3ST_6ch_modes,
6432		.need_dac_fix = 1,
6433		.input_mux = &alc883_capture_source,
6434	},
6435	[ALC883_3ST_6ch] = {
6436		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
6437		.init_verbs = { alc883_init_verbs },
6438		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6439		.dac_nids = alc883_dac_nids,
6440		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6441		.adc_nids = alc883_adc_nids,
6442		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
6443		.channel_mode = alc883_3ST_6ch_modes,
6444		.need_dac_fix = 1,
6445		.input_mux = &alc883_capture_source,
6446	},
6447	[ALC883_6ST_DIG] = {
6448		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
6449		.init_verbs = { alc883_init_verbs },
6450		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6451		.dac_nids = alc883_dac_nids,
6452		.dig_out_nid = ALC883_DIGOUT_NID,
6453		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6454		.adc_nids = alc883_adc_nids,
6455		.dig_in_nid = ALC883_DIGIN_NID,
6456		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
6457		.channel_mode = alc883_sixstack_modes,
6458		.input_mux = &alc883_capture_source,
6459	},
6460	[ALC883_TARGA_DIG] = {
6461		.mixers = { alc883_tagra_mixer, alc883_chmode_mixer },
6462		.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
6463		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6464		.dac_nids = alc883_dac_nids,
6465		.dig_out_nid = ALC883_DIGOUT_NID,
6466		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6467		.adc_nids = alc883_adc_nids,
6468		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
6469		.channel_mode = alc883_3ST_6ch_modes,
6470		.need_dac_fix = 1,
6471		.input_mux = &alc883_capture_source,
6472		.unsol_event = alc883_tagra_unsol_event,
6473		.init_hook = alc883_tagra_automute,
6474	},
6475	[ALC883_TARGA_2ch_DIG] = {
6476		.mixers = { alc883_tagra_2ch_mixer},
6477		.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
6478		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6479		.dac_nids = alc883_dac_nids,
6480		.dig_out_nid = ALC883_DIGOUT_NID,
6481		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6482		.adc_nids = alc883_adc_nids,
6483		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6484		.channel_mode = alc883_3ST_2ch_modes,
6485		.input_mux = &alc883_capture_source,
6486		.unsol_event = alc883_tagra_unsol_event,
6487		.init_hook = alc883_tagra_automute,
6488	},
6489	[ALC883_ACER] = {
6490		.mixers = { alc883_base_mixer,
6491			    alc883_chmode_mixer },
6492		/* On TravelMate laptops, GPIO 0 enables the internal speaker
6493		 * and the headphone jack.  Turn this on and rely on the
6494		 * standard mute methods whenever the user wants to turn
6495		 * these outputs off.
6496		 */
6497		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
6498		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6499		.dac_nids = alc883_dac_nids,
6500		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6501		.adc_nids = alc883_adc_nids,
6502		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6503		.channel_mode = alc883_3ST_2ch_modes,
6504		.input_mux = &alc883_capture_source,
6505	},
6506	[ALC883_MEDION] = {
6507		.mixers = { alc883_fivestack_mixer,
6508			    alc883_chmode_mixer },
6509		.init_verbs = { alc883_init_verbs,
6510				alc883_medion_eapd_verbs },
6511		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6512		.dac_nids = alc883_dac_nids,
6513		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6514		.adc_nids = alc883_adc_nids,
6515		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
6516		.channel_mode = alc883_sixstack_modes,
6517		.input_mux = &alc883_capture_source,
6518	},
6519	[ALC883_MEDION_MD2] = {
6520		.mixers = { alc883_medion_md2_mixer},
6521		.init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs},
6522		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6523		.dac_nids = alc883_dac_nids,
6524		.dig_out_nid = ALC883_DIGOUT_NID,
6525		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6526		.adc_nids = alc883_adc_nids,
6527		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6528		.channel_mode = alc883_3ST_2ch_modes,
6529		.input_mux = &alc883_capture_source,
6530		.unsol_event = alc883_medion_md2_unsol_event,
6531		.init_hook = alc883_medion_md2_automute,
6532	},
6533	[ALC883_LAPTOP_EAPD] = {
6534		.mixers = { alc883_base_mixer,
6535			    alc883_chmode_mixer },
6536		.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
6537		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6538		.dac_nids = alc883_dac_nids,
6539		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6540		.adc_nids = alc883_adc_nids,
6541		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6542		.channel_mode = alc883_3ST_2ch_modes,
6543		.input_mux = &alc883_capture_source,
6544	},
6545	[ALC883_LENOVO_101E_2ch] = {
6546		.mixers = { alc883_lenovo_101e_2ch_mixer},
6547		.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
6548		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6549		.dac_nids = alc883_dac_nids,
6550		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6551		.adc_nids = alc883_adc_nids,
6552		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6553		.channel_mode = alc883_3ST_2ch_modes,
6554		.input_mux = &alc883_lenovo_101e_capture_source,
6555		.unsol_event = alc883_lenovo_101e_unsol_event,
6556		.init_hook = alc883_lenovo_101e_all_automute,
6557	},
6558	[ALC883_LENOVO_NB0763] = {
6559		.mixers = { alc883_lenovo_nb0763_mixer },
6560		.init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
6561		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6562		.dac_nids = alc883_dac_nids,
6563		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6564		.adc_nids = alc883_adc_nids,
6565		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
6566		.channel_mode = alc883_3ST_2ch_modes,
6567		.need_dac_fix = 1,
6568		.input_mux = &alc883_lenovo_nb0763_capture_source,
6569		.unsol_event = alc883_medion_md2_unsol_event,
6570		.init_hook = alc883_medion_md2_automute,
6571	},
6572	[ALC888_LENOVO_MS7195_DIG] = {
6573		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
6574		.init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
6575		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
6576		.dac_nids = alc883_dac_nids,
6577		.dig_out_nid = ALC883_DIGOUT_NID,
6578		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
6579		.adc_nids = alc883_adc_nids,
6580		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
6581		.channel_mode = alc883_3ST_6ch_modes,
6582		.need_dac_fix = 1,
6583		.input_mux = &alc883_capture_source,
6584		.unsol_event = alc883_lenovo_ms7195_unsol_event,
6585		.init_hook = alc888_lenovo_ms7195_front_automute,
6586	},
6587};
6588
6589
6590/*
6591 * BIOS auto configuration
6592 */
6593static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
6594					      hda_nid_t nid, int pin_type,
6595					      int dac_idx)
6596{
6597	/* set as output */
6598	struct alc_spec *spec = codec->spec;
6599	int idx;
6600
6601	if (spec->multiout.dac_nids[dac_idx] == 0x25)
6602		idx = 4;
6603	else
6604		idx = spec->multiout.dac_nids[dac_idx] - 2;
6605
6606	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
6607			    pin_type);
6608	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
6609			    AMP_OUT_UNMUTE);
6610	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
6611
6612}
6613
6614static void alc883_auto_init_multi_out(struct hda_codec *codec)
6615{
6616	struct alc_spec *spec = codec->spec;
6617	int i;
6618
6619	alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
6620	for (i = 0; i <= HDA_SIDE; i++) {
6621		hda_nid_t nid = spec->autocfg.line_out_pins[i];
6622		int pin_type = get_pin_type(spec->autocfg.line_out_type);
6623		if (nid)
6624			alc883_auto_set_output_and_unmute(codec, nid, pin_type,
6625							  i);
6626	}
6627}
6628
6629static void alc883_auto_init_hp_out(struct hda_codec *codec)
6630{
6631	struct alc_spec *spec = codec->spec;
6632	hda_nid_t pin;
6633
6634	pin = spec->autocfg.hp_pins[0];
6635	if (pin) /* connect to front */
6636		/* use dac 0 */
6637		alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
6638}
6639
6640#define alc883_is_input_pin(nid)	alc880_is_input_pin(nid)
6641#define ALC883_PIN_CD_NID		ALC880_PIN_CD_NID
6642
6643static void alc883_auto_init_analog_input(struct hda_codec *codec)
6644{
6645	struct alc_spec *spec = codec->spec;
6646	int i;
6647
6648	for (i = 0; i < AUTO_PIN_LAST; i++) {
6649		hda_nid_t nid = spec->autocfg.input_pins[i];
6650		if (alc883_is_input_pin(nid)) {
6651			snd_hda_codec_write(codec, nid, 0,
6652					    AC_VERB_SET_PIN_WIDGET_CONTROL,
6653					    (i <= AUTO_PIN_FRONT_MIC ?
6654					     PIN_VREF80 : PIN_IN));
6655			if (nid != ALC883_PIN_CD_NID)
6656				snd_hda_codec_write(codec, nid, 0,
6657						    AC_VERB_SET_AMP_GAIN_MUTE,
6658						    AMP_OUT_MUTE);
6659		}
6660	}
6661}
6662
6663/* almost identical with ALC880 parser... */
6664static int alc883_parse_auto_config(struct hda_codec *codec)
6665{
6666	struct alc_spec *spec = codec->spec;
6667	int err = alc880_parse_auto_config(codec);
6668
6669	if (err < 0)
6670		return err;
6671	else if (err > 0)
6672		/* hack - override the init verbs */
6673		spec->init_verbs[0] = alc883_auto_init_verbs;
6674	spec->mixers[spec->num_mixers] = alc883_capture_mixer;
6675	spec->num_mixers++;
6676	return err;
6677}
6678
6679/* additional initialization for auto-configuration model */
6680static void alc883_auto_init(struct hda_codec *codec)
6681{
6682	alc883_auto_init_multi_out(codec);
6683	alc883_auto_init_hp_out(codec);
6684	alc883_auto_init_analog_input(codec);
6685}
6686
6687static int patch_alc883(struct hda_codec *codec)
6688{
6689	struct alc_spec *spec;
6690	int err, board_config;
6691
6692	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6693	if (spec == NULL)
6694		return -ENOMEM;
6695
6696	codec->spec = spec;
6697
6698	board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,
6699						  alc883_models,
6700						  alc883_cfg_tbl);
6701	if (board_config < 0) {
6702		printk(KERN_INFO "hda_codec: Unknown model for ALC883, "
6703		       "trying auto-probe from BIOS...\n");
6704		board_config = ALC883_AUTO;
6705	}
6706
6707	if (board_config == ALC883_AUTO) {
6708		/* automatic parse from the BIOS config */
6709		err = alc883_parse_auto_config(codec);
6710		if (err < 0) {
6711			alc_free(codec);
6712			return err;
6713		} else if (!err) {
6714			printk(KERN_INFO
6715			       "hda_codec: Cannot set up configuration "
6716			       "from BIOS.  Using base mode...\n");
6717			board_config = ALC883_3ST_2ch_DIG;
6718		}
6719	}
6720
6721	if (board_config != ALC883_AUTO)
6722		setup_preset(spec, &alc883_presets[board_config]);
6723
6724	spec->stream_name_analog = "ALC883 Analog";
6725	spec->stream_analog_playback = &alc883_pcm_analog_playback;
6726	spec->stream_analog_capture = &alc883_pcm_analog_capture;
6727
6728	spec->stream_name_digital = "ALC883 Digital";
6729	spec->stream_digital_playback = &alc883_pcm_digital_playback;
6730	spec->stream_digital_capture = &alc883_pcm_digital_capture;
6731
6732	if (!spec->adc_nids && spec->input_mux) {
6733		spec->adc_nids = alc883_adc_nids;
6734		spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
6735	}
6736
6737	codec->patch_ops = alc_patch_ops;
6738	if (board_config == ALC883_AUTO)
6739		spec->init_hook = alc883_auto_init;
6740
6741	return 0;
6742}
6743
6744/*
6745 * ALC262 support
6746 */
6747
6748#define ALC262_DIGOUT_NID	ALC880_DIGOUT_NID
6749#define ALC262_DIGIN_NID	ALC880_DIGIN_NID
6750
6751#define alc262_dac_nids		alc260_dac_nids
6752#define alc262_adc_nids		alc882_adc_nids
6753#define alc262_adc_nids_alt	alc882_adc_nids_alt
6754
6755#define alc262_modes		alc260_modes
6756#define alc262_capture_source	alc882_capture_source
6757
6758static struct snd_kcontrol_new alc262_base_mixer[] = {
6759	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6760	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
6761	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
6762	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
6763	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
6764	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
6765	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6766	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6767	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
6768	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
6769	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
6770	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
6771	/* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
6772	   HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
6773	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
6774	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6775	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
6776	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
6777	{ } /* end */
6778};
6779
6780static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
6781	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6782	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
6783	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
6784	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
6785	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
6786	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
6787	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6788	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6789	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
6790	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
6791	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
6792	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
6793	/* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
6794	   HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
6795	/*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
6796	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
6797	{ } /* end */
6798};
6799
6800static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
6801	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6802	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6803	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
6804	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
6805	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
6806
6807	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6808	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6809	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
6810	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
6811	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
6812	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
6813	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
6814	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
6815	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
6816	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
6817	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
6818	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
6819	HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
6820	HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
6821	{ } /* end */
6822};
6823
6824static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
6825	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6826	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
6827	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
6828	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6829	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
6830	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
6831	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
6832	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
6833	HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT),
6834	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
6835	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
6836	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
6837	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
6838	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
6839	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
6840	{ } /* end */
6841};
6842
6843static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
6844	HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6845	HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6846	HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT),
6847	{ } /* end */
6848};
6849
6850static struct snd_kcontrol_new alc262_sony_mixer[] = {
6851	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
6852	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6853	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6854	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6855	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
6856	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
6857	{ } /* end */
6858};
6859
6860
6861
6862#define alc262_capture_mixer		alc882_capture_mixer
6863#define alc262_capture_alt_mixer	alc882_capture_alt_mixer
6864
6865/*
6866 * generic initialization of ADC, input mixers and output mixers
6867 */
6868static struct hda_verb alc262_init_verbs[] = {
6869	/*
6870	 * Unmute ADC0-2 and set the default input to mic-in
6871	 */
6872	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
6873	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6874	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
6875	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6876	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
6877	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6878
6879	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
6880	 * mixer widget
6881	 * Note: PASD motherboards uses the Line In 2 as the input for
6882	 * front panel mic (mic 2)
6883	 */
6884	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
6885	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6886	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6887	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6888	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
6889	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6890
6891	/*
6892	 * Set up output mixers (0x0c - 0x0e)
6893	 */
6894	/* set vol=0 to output mixers */
6895	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6896	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6897	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6898	/* set up input amps for analog loopback */
6899	/* Amp Indices: DAC = 0, mixer = 1 */
6900	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6901	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6902	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6903	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6904	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6905	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6906
6907	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6908	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6909	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
6910	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6911	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6912	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6913
6914	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6915	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6916	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6917	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6918	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6919
6920	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
6921	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
6922
6923	/* FIXME: use matrix-type input source selection */
6924	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
6925	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
6926	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6927	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6928	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6929	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6930	/* Input mixer2 */
6931	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6932	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6933	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6934	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6935	/* Input mixer3 */
6936	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6937	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6938	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6939	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6940
6941	{ }
6942};
6943
6944static struct hda_verb alc262_hippo_unsol_verbs[] = {
6945	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6946	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6947	{}
6948};
6949
6950static struct hda_verb alc262_hippo1_unsol_verbs[] = {
6951	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6952	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
6953	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6954
6955	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6956	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6957	{}
6958};
6959
6960static struct hda_verb alc262_sony_unsol_verbs[] = {
6961	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6962	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
6963	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},	// Front Mic
6964
6965	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6966	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6967};
6968
6969/* mute/unmute internal speaker according to the hp jack and mute state */
6970static void alc262_hippo_automute(struct hda_codec *codec, int force)
6971{
6972	struct alc_spec *spec = codec->spec;
6973	unsigned int mute;
6974
6975	if (force || !spec->sense_updated) {
6976		unsigned int present;
6977		/* need to execute and sync at first */
6978		snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
6979		present = snd_hda_codec_read(codec, 0x15, 0,
6980				    	 AC_VERB_GET_PIN_SENSE, 0);
6981		spec->jack_present = (present & 0x80000000) != 0;
6982		spec->sense_updated = 1;
6983	}
6984	if (spec->jack_present) {
6985		/* mute internal speaker */
6986		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6987					 0x80, 0x80);
6988		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6989					 0x80, 0x80);
6990	} else {
6991		/* unmute internal speaker if necessary */
6992		mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
6993		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6994					 0x80, mute & 0x80);
6995		mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0);
6996		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6997					 0x80, mute & 0x80);
6998	}
6999}
7000
7001/* unsolicited event for HP jack sensing */
7002static void alc262_hippo_unsol_event(struct hda_codec *codec,
7003				       unsigned int res)
7004{
7005	if ((res >> 26) != ALC880_HP_EVENT)
7006		return;
7007	alc262_hippo_automute(codec, 1);
7008}
7009
7010static void alc262_hippo1_automute(struct hda_codec *codec, int force)
7011{
7012	struct alc_spec *spec = codec->spec;
7013	unsigned int mute;
7014
7015	if (force || !spec->sense_updated) {
7016		unsigned int present;
7017		/* need to execute and sync at first */
7018		snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
7019		present = snd_hda_codec_read(codec, 0x1b, 0,
7020				    	 AC_VERB_GET_PIN_SENSE, 0);
7021		spec->jack_present = (present & 0x80000000) != 0;
7022		spec->sense_updated = 1;
7023	}
7024	if (spec->jack_present) {
7025		/* mute internal speaker */
7026		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
7027					 0x80, 0x80);
7028		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
7029					 0x80, 0x80);
7030	} else {
7031		/* unmute internal speaker if necessary */
7032		mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
7033		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
7034					 0x80, mute & 0x80);
7035		mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0);
7036		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
7037					 0x80, mute & 0x80);
7038	}
7039}
7040
7041/* unsolicited event for HP jack sensing */
7042static void alc262_hippo1_unsol_event(struct hda_codec *codec,
7043				       unsigned int res)
7044{
7045	if ((res >> 26) != ALC880_HP_EVENT)
7046		return;
7047	alc262_hippo1_automute(codec, 1);
7048}
7049
7050/*
7051 * fujitsu model
7052 *  0x14 = headphone/spdif-out, 0x15 = internal speaker
7053 */
7054
7055#define ALC_HP_EVENT	0x37
7056
7057static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
7058	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
7059	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7060	{}
7061};
7062
7063static struct hda_input_mux alc262_fujitsu_capture_source = {
7064	.num_items = 2,
7065	.items = {
7066		{ "Mic", 0x0 },
7067		{ "CD", 0x4 },
7068	},
7069};
7070
7071static struct hda_input_mux alc262_HP_capture_source = {
7072	.num_items = 5,
7073	.items = {
7074		{ "Mic", 0x0 },
7075		{ "Front Mic", 0x3 },
7076		{ "Line", 0x2 },
7077		{ "CD", 0x4 },
7078		{ "AUX IN", 0x6 },
7079	},
7080};
7081
7082/* mute/unmute internal speaker according to the hp jack and mute state */
7083static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
7084{
7085	struct alc_spec *spec = codec->spec;
7086	unsigned int mute;
7087
7088	if (force || !spec->sense_updated) {
7089		unsigned int present;
7090		/* need to execute and sync at first */
7091		snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
7092		present = snd_hda_codec_read(codec, 0x14, 0,
7093				    	 AC_VERB_GET_PIN_SENSE, 0);
7094		spec->jack_present = (present & 0x80000000) != 0;
7095		spec->sense_updated = 1;
7096	}
7097	if (spec->jack_present) {
7098		/* mute internal speaker */
7099		snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
7100					 0x80, 0x80);
7101		snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
7102					 0x80, 0x80);
7103	} else {
7104		/* unmute internal speaker if necessary */
7105		mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
7106		snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
7107					 0x80, mute & 0x80);
7108		mute = snd_hda_codec_amp_read(codec, 0x14, 1, HDA_OUTPUT, 0);
7109		snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
7110					 0x80, mute & 0x80);
7111	}
7112}
7113
7114/* unsolicited event for HP jack sensing */
7115static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
7116				       unsigned int res)
7117{
7118	if ((res >> 26) != ALC_HP_EVENT)
7119		return;
7120	alc262_fujitsu_automute(codec, 1);
7121}
7122
7123/* bind volumes of both NID 0x0c and 0x0d */
7124static int alc262_fujitsu_master_vol_put(struct snd_kcontrol *kcontrol,
7125					 struct snd_ctl_elem_value *ucontrol)
7126{
7127	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
7128	long *valp = ucontrol->value.integer.value;
7129	int change;
7130
7131	change = snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
7132					  0x7f, valp[0] & 0x7f);
7133	change |= snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
7134					   0x7f, valp[1] & 0x7f);
7135	snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
7136				 0x7f, valp[0] & 0x7f);
7137	snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
7138				 0x7f, valp[1] & 0x7f);
7139	return change;
7140}
7141
7142/* bind hp and internal speaker mute (with plug check) */
7143static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
7144					 struct snd_ctl_elem_value *ucontrol)
7145{
7146	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
7147	long *valp = ucontrol->value.integer.value;
7148	int change;
7149
7150	change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
7151					  0x80, valp[0] ? 0 : 0x80);
7152	change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
7153					   0x80, valp[1] ? 0 : 0x80);
7154	if (change || codec->in_resume)
7155		alc262_fujitsu_automute(codec, codec->in_resume);
7156	return change;
7157}
7158
7159static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
7160	{
7161		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7162		.name = "Master Playback Volume",
7163		.info = snd_hda_mixer_amp_volume_info,
7164		.get = snd_hda_mixer_amp_volume_get,
7165		.put = alc262_fujitsu_master_vol_put,
7166		.tlv = { .c = snd_hda_mixer_amp_tlv },
7167		.private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
7168	},
7169	{
7170		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7171		.name = "Master Playback Switch",
7172		.info = snd_hda_mixer_amp_switch_info,
7173		.get = snd_hda_mixer_amp_switch_get,
7174		.put = alc262_fujitsu_master_sw_put,
7175		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
7176	},
7177	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7178	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7179	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7180	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7181	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7182	{ } /* end */
7183};
7184
7185/* additional init verbs for Benq laptops */
7186static struct hda_verb alc262_EAPD_verbs[] = {
7187	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
7188	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
7189	{}
7190};
7191
7192/* add playback controls from the parsed DAC table */
7193static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
7194					     const struct auto_pin_cfg *cfg)
7195{
7196	hda_nid_t nid;
7197	int err;
7198
7199	spec->multiout.num_dacs = 1;	/* only use one dac */
7200	spec->multiout.dac_nids = spec->private_dac_nids;
7201	spec->multiout.dac_nids[0] = 2;
7202
7203	nid = cfg->line_out_pins[0];
7204	if (nid) {
7205		err = add_control(spec, ALC_CTL_WIDGET_VOL,
7206				  "Front Playback Volume",
7207				  HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT));
7208		if (err < 0)
7209			return err;
7210		err = add_control(spec, ALC_CTL_WIDGET_MUTE,
7211				  "Front Playback Switch",
7212				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
7213		if (err < 0)
7214			return err;
7215	}
7216
7217	nid = cfg->speaker_pins[0];
7218	if (nid) {
7219		if (nid == 0x16) {
7220			err = add_control(spec, ALC_CTL_WIDGET_VOL,
7221					  "Speaker Playback Volume",
7222					  HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
7223							      HDA_OUTPUT));
7224			if (err < 0)
7225				return err;
7226			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
7227					  "Speaker Playback Switch",
7228					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
7229							      HDA_OUTPUT));
7230			if (err < 0)
7231				return err;
7232		} else {
7233			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
7234					  "Speaker Playback Switch",
7235					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
7236							      HDA_OUTPUT));
7237			if (err < 0)
7238				return err;
7239		}
7240	}
7241	nid = cfg->hp_pins[0];
7242	if (nid) {
7243		/* spec->multiout.hp_nid = 2; */
7244		if (nid == 0x16) {
7245			err = add_control(spec, ALC_CTL_WIDGET_VOL,
7246					  "Headphone Playback Volume",
7247					  HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
7248							      HDA_OUTPUT));
7249			if (err < 0)
7250				return err;
7251			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
7252					  "Headphone Playback Switch",
7253					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
7254							      HDA_OUTPUT));
7255			if (err < 0)
7256				return err;
7257		} else {
7258			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
7259					  "Headphone Playback Switch",
7260					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
7261							      HDA_OUTPUT));
7262			if (err < 0)
7263				return err;
7264		}
7265	}
7266	return 0;
7267}
7268
7269/* identical with ALC880 */
7270#define alc262_auto_create_analog_input_ctls \
7271	alc880_auto_create_analog_input_ctls
7272
7273/*
7274 * generic initialization of ADC, input mixers and output mixers
7275 */
7276static struct hda_verb alc262_volume_init_verbs[] = {
7277	/*
7278	 * Unmute ADC0-2 and set the default input to mic-in
7279	 */
7280	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7281	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7282	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7283	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7284	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7285	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7286
7287	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
7288	 * mixer widget
7289	 * Note: PASD motherboards uses the Line In 2 as the input for
7290	 * front panel mic (mic 2)
7291	 */
7292	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
7293	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7294	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7295	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7296	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7297	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
7298
7299	/*
7300	 * Set up output mixers (0x0c - 0x0f)
7301	 */
7302	/* set vol=0 to output mixers */
7303	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7304	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7305	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7306
7307	/* set up input amps for analog loopback */
7308	/* Amp Indices: DAC = 0, mixer = 1 */
7309	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7310	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7311	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7312	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7313	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7314	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7315
7316	/* FIXME: use matrix-type input source selection */
7317	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7318	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7319	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7320	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
7321	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
7322	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
7323	/* Input mixer2 */
7324	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7325	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
7326	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
7327	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
7328	/* Input mixer3 */
7329	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7330	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
7331	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
7332	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
7333
7334	{ }
7335};
7336
7337static struct hda_verb alc262_HP_BPC_init_verbs[] = {
7338	/*
7339	 * Unmute ADC0-2 and set the default input to mic-in
7340	 */
7341	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7342	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7343	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7344	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7345	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7346	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7347
7348	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
7349	 * mixer widget
7350	 * Note: PASD motherboards uses the Line In 2 as the input for
7351	 * front panel mic (mic 2)
7352	 */
7353	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
7354	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7355	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7356	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7357	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7358	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
7359	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
7360        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
7361
7362	/*
7363	 * Set up output mixers (0x0c - 0x0e)
7364	 */
7365	/* set vol=0 to output mixers */
7366	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7367	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7368	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7369
7370	/* set up input amps for analog loopback */
7371	/* Amp Indices: DAC = 0, mixer = 1 */
7372	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7373	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7374	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7375	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7376	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7377	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7378
7379	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
7380	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7381	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7382
7383	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7384	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7385
7386	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
7387	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7388
7389	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7390	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
7391        {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
7392	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7393	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7394
7395	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
7396	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7397        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7398	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
7399	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7400	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7401
7402
7403	/* FIXME: use matrix-type input source selection */
7404	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7405	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7406	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7407	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7408	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7409	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
7410	/* Input mixer2 */
7411	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7412	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7413	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7414	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
7415	/* Input mixer3 */
7416	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7417	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7418	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7419	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
7420
7421	{ }
7422};
7423
7424static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
7425	/*
7426	 * Unmute ADC0-2 and set the default input to mic-in
7427	 */
7428	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7429	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7430	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7431	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7432	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7433	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7434
7435	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
7436	 * mixer widget
7437	 * Note: PASD motherboards uses the Line In 2 as the input for front
7438	 * panel mic (mic 2)
7439	 */
7440	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
7441	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7442	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7443	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7444	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7445	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
7446	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
7447	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
7448	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
7449	/*
7450	 * Set up output mixers (0x0c - 0x0e)
7451	 */
7452	/* set vol=0 to output mixers */
7453	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7454	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7455	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7456
7457	/* set up input amps for analog loopback */
7458	/* Amp Indices: DAC = 0, mixer = 1 */
7459	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7460	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7461	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7462	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7463	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7464	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7465
7466
7467	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },	/* HP */
7468	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Mono */
7469	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* rear MIC */
7470	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },	/* Line in */
7471	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* Front MIC */
7472	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Line out */
7473	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },	/* CD in */
7474
7475	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7476	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7477
7478	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
7479	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
7480
7481	/* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
7482	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7483	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7484	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
7485	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7486	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
7487
7488	/* FIXME: use matrix-type input source selection */
7489	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7490	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7491	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
7492	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
7493	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
7494	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
7495	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
7496        /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))},  */
7497	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
7498	/* Input mixer2 */
7499	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7500	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
7501	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7502	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7503	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
7504        /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
7505	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
7506	/* Input mixer3 */
7507	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7508	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
7509	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7510	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7511	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
7512        /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
7513	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
7514
7515	{ }
7516};
7517
7518/* pcm configuration: identiacal with ALC880 */
7519#define alc262_pcm_analog_playback	alc880_pcm_analog_playback
7520#define alc262_pcm_analog_capture	alc880_pcm_analog_capture
7521#define alc262_pcm_digital_playback	alc880_pcm_digital_playback
7522#define alc262_pcm_digital_capture	alc880_pcm_digital_capture
7523
7524/*
7525 * BIOS auto configuration
7526 */
7527static int alc262_parse_auto_config(struct hda_codec *codec)
7528{
7529	struct alc_spec *spec = codec->spec;
7530	int err;
7531	static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
7532
7533	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
7534					   alc262_ignore);
7535	if (err < 0)
7536		return err;
7537	if (!spec->autocfg.line_outs)
7538		return 0; /* can't find valid BIOS pin config */
7539	err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
7540	if (err < 0)
7541		return err;
7542	err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg);
7543	if (err < 0)
7544		return err;
7545
7546	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
7547
7548	if (spec->autocfg.dig_out_pin)
7549		spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
7550	if (spec->autocfg.dig_in_pin)
7551		spec->dig_in_nid = ALC262_DIGIN_NID;
7552
7553	if (spec->kctl_alloc)
7554		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
7555
7556	spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
7557	spec->num_mux_defs = 1;
7558	spec->input_mux = &spec->private_imux;
7559
7560	return 1;
7561}
7562
7563#define alc262_auto_init_multi_out	alc882_auto_init_multi_out
7564#define alc262_auto_init_hp_out		alc882_auto_init_hp_out
7565#define alc262_auto_init_analog_input	alc882_auto_init_analog_input
7566
7567
7568/* init callback for auto-configuration model -- overriding the default init */
7569static void alc262_auto_init(struct hda_codec *codec)
7570{
7571	alc262_auto_init_multi_out(codec);
7572	alc262_auto_init_hp_out(codec);
7573	alc262_auto_init_analog_input(codec);
7574}
7575
7576/*
7577 * configuration and preset
7578 */
7579static const char *alc262_models[ALC262_MODEL_LAST] = {
7580	[ALC262_BASIC]		= "basic",
7581	[ALC262_HIPPO]		= "hippo",
7582	[ALC262_HIPPO_1]	= "hippo_1",
7583	[ALC262_FUJITSU]	= "fujitsu",
7584	[ALC262_HP_BPC]		= "hp-bpc",
7585	[ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
7586	[ALC262_BENQ_ED8]	= "benq",
7587	[ALC262_BENQ_ED8]	= "sony-assamd",
7588	[ALC262_AUTO]		= "auto",
7589};
7590
7591static struct snd_pci_quirk alc262_cfg_tbl[] = {
7592	SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
7593	SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC),
7594	SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
7595	SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC),
7596	SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC),
7597	SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
7598	SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC),
7599	SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
7600	SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC),
7601	SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
7602	SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
7603	SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
7604	SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
7605	SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
7606	SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
7607	SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
7608	SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
7609	SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
7610	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
7611	SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
7612	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
7613	SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
7614	SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
7615	SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
7616	{}
7617};
7618
7619static struct alc_config_preset alc262_presets[] = {
7620	[ALC262_BASIC] = {
7621		.mixers = { alc262_base_mixer },
7622		.init_verbs = { alc262_init_verbs },
7623		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7624		.dac_nids = alc262_dac_nids,
7625		.hp_nid = 0x03,
7626		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7627		.channel_mode = alc262_modes,
7628		.input_mux = &alc262_capture_source,
7629	},
7630	[ALC262_HIPPO] = {
7631		.mixers = { alc262_base_mixer },
7632		.init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},
7633		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7634		.dac_nids = alc262_dac_nids,
7635		.hp_nid = 0x03,
7636		.dig_out_nid = ALC262_DIGOUT_NID,
7637		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7638		.channel_mode = alc262_modes,
7639		.input_mux = &alc262_capture_source,
7640		.unsol_event = alc262_hippo_unsol_event,
7641	},
7642	[ALC262_HIPPO_1] = {
7643		.mixers = { alc262_hippo1_mixer },
7644		.init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
7645		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7646		.dac_nids = alc262_dac_nids,
7647		.hp_nid = 0x02,
7648		.dig_out_nid = ALC262_DIGOUT_NID,
7649		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7650		.channel_mode = alc262_modes,
7651		.input_mux = &alc262_capture_source,
7652		.unsol_event = alc262_hippo1_unsol_event,
7653	},
7654	[ALC262_FUJITSU] = {
7655		.mixers = { alc262_fujitsu_mixer },
7656		.init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs },
7657		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7658		.dac_nids = alc262_dac_nids,
7659		.hp_nid = 0x03,
7660		.dig_out_nid = ALC262_DIGOUT_NID,
7661		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7662		.channel_mode = alc262_modes,
7663		.input_mux = &alc262_fujitsu_capture_source,
7664		.unsol_event = alc262_fujitsu_unsol_event,
7665	},
7666	[ALC262_HP_BPC] = {
7667		.mixers = { alc262_HP_BPC_mixer },
7668		.init_verbs = { alc262_HP_BPC_init_verbs },
7669		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7670		.dac_nids = alc262_dac_nids,
7671		.hp_nid = 0x03,
7672		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7673		.channel_mode = alc262_modes,
7674		.input_mux = &alc262_HP_capture_source,
7675	},
7676	[ALC262_HP_BPC_D7000_WF] = {
7677		.mixers = { alc262_HP_BPC_WildWest_mixer },
7678		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
7679		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7680		.dac_nids = alc262_dac_nids,
7681		.hp_nid = 0x03,
7682		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7683		.channel_mode = alc262_modes,
7684		.input_mux = &alc262_HP_capture_source,
7685	},
7686	[ALC262_HP_BPC_D7000_WL] = {
7687		.mixers = { alc262_HP_BPC_WildWest_mixer,
7688			    alc262_HP_BPC_WildWest_option_mixer },
7689		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
7690		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7691		.dac_nids = alc262_dac_nids,
7692		.hp_nid = 0x03,
7693		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7694		.channel_mode = alc262_modes,
7695		.input_mux = &alc262_HP_capture_source,
7696	},
7697	[ALC262_BENQ_ED8] = {
7698		.mixers = { alc262_base_mixer },
7699		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
7700		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7701		.dac_nids = alc262_dac_nids,
7702		.hp_nid = 0x03,
7703		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7704		.channel_mode = alc262_modes,
7705		.input_mux = &alc262_capture_source,
7706	},
7707	[ALC262_SONY_ASSAMD] = {
7708		.mixers = { alc262_sony_mixer },
7709		.init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
7710		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
7711		.dac_nids = alc262_dac_nids,
7712		.hp_nid = 0x02,
7713		.num_channel_mode = ARRAY_SIZE(alc262_modes),
7714		.channel_mode = alc262_modes,
7715		.input_mux = &alc262_capture_source,
7716		.unsol_event = alc262_hippo_unsol_event,
7717	},
7718};
7719
7720static int patch_alc262(struct hda_codec *codec)
7721{
7722	struct alc_spec *spec;
7723	int board_config;
7724	int err;
7725
7726	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
7727	if (spec == NULL)
7728		return -ENOMEM;
7729
7730	codec->spec = spec;
7731#if 0
7732	/* pshou 07/11/05  set a zero PCM sample to DAC when FIFO is
7733	 * under-run
7734	 */
7735	{
7736	int tmp;
7737	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
7738	tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
7739	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
7740	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
7741	}
7742#endif
7743
7744	board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
7745						  alc262_models,
7746						  alc262_cfg_tbl);
7747
7748	if (board_config < 0) {
7749		printk(KERN_INFO "hda_codec: Unknown model for ALC262, "
7750		       "trying auto-probe from BIOS...\n");
7751		board_config = ALC262_AUTO;
7752	}
7753
7754	if (board_config == ALC262_AUTO) {
7755		/* automatic parse from the BIOS config */
7756		err = alc262_parse_auto_config(codec);
7757		if (err < 0) {
7758			alc_free(codec);
7759			return err;
7760		} else if (!err) {
7761			printk(KERN_INFO
7762			       "hda_codec: Cannot set up configuration "
7763			       "from BIOS.  Using base mode...\n");
7764			board_config = ALC262_BASIC;
7765		}
7766	}
7767
7768	if (board_config != ALC262_AUTO)
7769		setup_preset(spec, &alc262_presets[board_config]);
7770
7771	spec->stream_name_analog = "ALC262 Analog";
7772	spec->stream_analog_playback = &alc262_pcm_analog_playback;
7773	spec->stream_analog_capture = &alc262_pcm_analog_capture;
7774
7775	spec->stream_name_digital = "ALC262 Digital";
7776	spec->stream_digital_playback = &alc262_pcm_digital_playback;
7777	spec->stream_digital_capture = &alc262_pcm_digital_capture;
7778
7779	if (!spec->adc_nids && spec->input_mux) {
7780		/* check whether NID 0x07 is valid */
7781		unsigned int wcap = get_wcaps(codec, 0x07);
7782
7783		/* get type */
7784		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
7785		if (wcap != AC_WID_AUD_IN) {
7786			spec->adc_nids = alc262_adc_nids_alt;
7787			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
7788			spec->mixers[spec->num_mixers] =
7789				alc262_capture_alt_mixer;
7790			spec->num_mixers++;
7791		} else {
7792			spec->adc_nids = alc262_adc_nids;
7793			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
7794			spec->mixers[spec->num_mixers] = alc262_capture_mixer;
7795			spec->num_mixers++;
7796		}
7797	}
7798
7799	codec->patch_ops = alc_patch_ops;
7800	if (board_config == ALC262_AUTO)
7801		spec->init_hook = alc262_auto_init;
7802
7803	return 0;
7804}
7805
7806/*
7807 *  ALC861 channel source setting (2/6 channel selection for 3-stack)
7808 */
7809
7810/*
7811 * set the path ways for 2 channel output
7812 * need to set the codec line out and mic 1 pin widgets to inputs
7813 */
7814static struct hda_verb alc861_threestack_ch2_init[] = {
7815	/* set pin widget 1Ah (line in) for input */
7816	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7817	/* set pin widget 18h (mic1/2) for input, for mic also enable
7818	 * the vref
7819	 */
7820	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7821
7822	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
7823#if 0
7824	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
7825	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
7826#endif
7827	{ } /* end */
7828};
7829/*
7830 * 6ch mode
7831 * need to set the codec line out and mic 1 pin widgets to outputs
7832 */
7833static struct hda_verb alc861_threestack_ch6_init[] = {
7834	/* set pin widget 1Ah (line in) for output (Back Surround)*/
7835	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7836	/* set pin widget 18h (mic1) for output (CLFE)*/
7837	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7838
7839	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
7840	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
7841
7842	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
7843#if 0
7844	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
7845	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
7846#endif
7847	{ } /* end */
7848};
7849
7850static struct hda_channel_mode alc861_threestack_modes[2] = {
7851	{ 2, alc861_threestack_ch2_init },
7852	{ 6, alc861_threestack_ch6_init },
7853};
7854/* Set mic1 as input and unmute the mixer */
7855static struct hda_verb alc861_uniwill_m31_ch2_init[] = {
7856	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7857	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
7858	{ } /* end */
7859};
7860/* Set mic1 as output and mute mixer */
7861static struct hda_verb alc861_uniwill_m31_ch4_init[] = {
7862	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7863	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
7864	{ } /* end */
7865};
7866
7867static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
7868	{ 2, alc861_uniwill_m31_ch2_init },
7869	{ 4, alc861_uniwill_m31_ch4_init },
7870};
7871
7872/* Set mic1 and line-in as input and unmute the mixer */
7873static struct hda_verb alc861_asus_ch2_init[] = {
7874	/* set pin widget 1Ah (line in) for input */
7875	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7876	/* set pin widget 18h (mic1/2) for input, for mic also enable
7877	 * the vref
7878	 */
7879	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7880
7881	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
7882#if 0
7883	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
7884	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
7885#endif
7886	{ } /* end */
7887};
7888/* Set mic1 nad line-in as output and mute mixer */
7889static struct hda_verb alc861_asus_ch6_init[] = {
7890	/* set pin widget 1Ah (line in) for output (Back Surround)*/
7891	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7892	/* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
7893	/* set pin widget 18h (mic1) for output (CLFE)*/
7894	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7895	/* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
7896	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
7897	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
7898
7899	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
7900#if 0
7901	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
7902	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
7903#endif
7904	{ } /* end */
7905};
7906
7907static struct hda_channel_mode alc861_asus_modes[2] = {
7908	{ 2, alc861_asus_ch2_init },
7909	{ 6, alc861_asus_ch6_init },
7910};
7911
7912/* patch-ALC861 */
7913
7914static struct snd_kcontrol_new alc861_base_mixer[] = {
7915        /* output mixer control */
7916	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
7917	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
7918	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
7919	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
7920	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
7921
7922        /*Input mixer control */
7923	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
7924	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
7925	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
7926	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
7927	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
7928	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
7929	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
7930	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
7931	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
7932	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
7933
7934        /* Capture mixer control */
7935	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7936	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7937	{
7938		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7939		.name = "Capture Source",
7940		.count = 1,
7941		.info = alc_mux_enum_info,
7942		.get = alc_mux_enum_get,
7943		.put = alc_mux_enum_put,
7944	},
7945	{ } /* end */
7946};
7947
7948static struct snd_kcontrol_new alc861_3ST_mixer[] = {
7949        /* output mixer control */
7950	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
7951	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
7952	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
7953	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
7954	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
7955
7956	/* Input mixer control */
7957	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
7958	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
7959	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
7960	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
7961	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
7962	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
7963	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
7964	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
7965	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
7966	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
7967
7968	/* Capture mixer control */
7969	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7970	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7971	{
7972		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7973		.name = "Capture Source",
7974		.count = 1,
7975		.info = alc_mux_enum_info,
7976		.get = alc_mux_enum_get,
7977		.put = alc_mux_enum_put,
7978	},
7979	{
7980		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7981		.name = "Channel Mode",
7982		.info = alc_ch_mode_info,
7983		.get = alc_ch_mode_get,
7984		.put = alc_ch_mode_put,
7985                .private_value = ARRAY_SIZE(alc861_threestack_modes),
7986	},
7987	{ } /* end */
7988};
7989
7990static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
7991        /* output mixer control */
7992	HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
7993	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
7994	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
7995
7996        /*Capture mixer control */
7997	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7998	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7999	{
8000		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8001		.name = "Capture Source",
8002		.count = 1,
8003		.info = alc_mux_enum_info,
8004		.get = alc_mux_enum_get,
8005		.put = alc_mux_enum_put,
8006	},
8007
8008	{ } /* end */
8009};
8010
8011static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
8012        /* output mixer control */
8013	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
8014	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
8015	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
8016	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
8017	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
8018
8019	/* Input mixer control */
8020	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
8021	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
8022	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
8023	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
8024	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
8025	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
8026	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
8027	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
8028	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
8029	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
8030
8031	/* Capture mixer control */
8032	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
8033	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
8034	{
8035		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8036		.name = "Capture Source",
8037		.count = 1,
8038		.info = alc_mux_enum_info,
8039		.get = alc_mux_enum_get,
8040		.put = alc_mux_enum_put,
8041	},
8042	{
8043		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8044		.name = "Channel Mode",
8045		.info = alc_ch_mode_info,
8046		.get = alc_ch_mode_get,
8047		.put = alc_ch_mode_put,
8048                .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
8049	},
8050	{ } /* end */
8051};
8052
8053static struct snd_kcontrol_new alc861_asus_mixer[] = {
8054        /* output mixer control */
8055	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
8056	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
8057	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
8058	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
8059	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
8060
8061	/* Input mixer control */
8062	HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
8063	HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8064	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
8065	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
8066	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
8067	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
8068	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
8069	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
8070	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
8071	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
8072
8073	/* Capture mixer control */
8074	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
8075	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
8076	{
8077		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8078		.name = "Capture Source",
8079		.count = 1,
8080		.info = alc_mux_enum_info,
8081		.get = alc_mux_enum_get,
8082		.put = alc_mux_enum_put,
8083	},
8084	{
8085		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8086		.name = "Channel Mode",
8087		.info = alc_ch_mode_info,
8088		.get = alc_ch_mode_get,
8089		.put = alc_ch_mode_put,
8090                .private_value = ARRAY_SIZE(alc861_asus_modes),
8091	},
8092	{ }
8093};
8094
8095/* additional mixer */
8096static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
8097	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
8098	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
8099	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT),
8100	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT),
8101	{ }
8102};
8103
8104/*
8105 * generic initialization of ADC, input mixers and output mixers
8106 */
8107static struct hda_verb alc861_base_init_verbs[] = {
8108	/*
8109	 * Unmute ADC0 and set the default input to mic-in
8110	 */
8111	/* port-A for surround (rear panel) */
8112	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8113	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
8114	/* port-B for mic-in (rear panel) with vref */
8115	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8116	/* port-C for line-in (rear panel) */
8117	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8118	/* port-D for Front */
8119	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8120	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
8121	/* port-E for HP out (front panel) */
8122	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
8123	/* route front PCM to HP */
8124	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
8125	/* port-F for mic-in (front panel) with vref */
8126	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8127	/* port-G for CLFE (rear panel) */
8128	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8129	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
8130	/* port-H for side (rear panel) */
8131	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8132	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
8133	/* CD-in */
8134	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8135	/* route front mic to ADC1*/
8136	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8137	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8138
8139	/* Unmute DAC0~3 & spdif out*/
8140	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8141	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8142	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8143	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8144	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8145
8146	/* Unmute Mixer 14 (mic) 1c (Line in)*/
8147	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8148        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8149	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8150        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8151
8152	/* Unmute Stereo Mixer 15 */
8153	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8154	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8155	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8156	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
8157
8158	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8159	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8160	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8161	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8162	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8163	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8164	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8165	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8166	/* hp used DAC 3 (Front) */
8167	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8168        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8169
8170	{ }
8171};
8172
8173static struct hda_verb alc861_threestack_init_verbs[] = {
8174	/*
8175	 * Unmute ADC0 and set the default input to mic-in
8176	 */
8177	/* port-A for surround (rear panel) */
8178	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8179	/* port-B for mic-in (rear panel) with vref */
8180	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8181	/* port-C for line-in (rear panel) */
8182	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8183	/* port-D for Front */
8184	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8185	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
8186	/* port-E for HP out (front panel) */
8187	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
8188	/* route front PCM to HP */
8189	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
8190	/* port-F for mic-in (front panel) with vref */
8191	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8192	/* port-G for CLFE (rear panel) */
8193	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8194	/* port-H for side (rear panel) */
8195	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8196	/* CD-in */
8197	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8198	/* route front mic to ADC1*/
8199	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8200	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8201	/* Unmute DAC0~3 & spdif out*/
8202	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8203	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8204	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8205	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8206	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8207
8208	/* Unmute Mixer 14 (mic) 1c (Line in)*/
8209	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8210        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8211	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8212        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8213
8214	/* Unmute Stereo Mixer 15 */
8215	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8216	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8217	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8218	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
8219
8220	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8221	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8222	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8223	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8224	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8225	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8226	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8227	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8228	/* hp used DAC 3 (Front) */
8229	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8230        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8231	{ }
8232};
8233
8234static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
8235	/*
8236	 * Unmute ADC0 and set the default input to mic-in
8237	 */
8238	/* port-A for surround (rear panel) */
8239	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8240	/* port-B for mic-in (rear panel) with vref */
8241	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8242	/* port-C for line-in (rear panel) */
8243	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8244	/* port-D for Front */
8245	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8246	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
8247	/* port-E for HP out (front panel) */
8248	/* this has to be set to VREF80 */
8249	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8250	/* route front PCM to HP */
8251	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
8252	/* port-F for mic-in (front panel) with vref */
8253	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8254	/* port-G for CLFE (rear panel) */
8255	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8256	/* port-H for side (rear panel) */
8257	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8258	/* CD-in */
8259	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8260	/* route front mic to ADC1*/
8261	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8262	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8263	/* Unmute DAC0~3 & spdif out*/
8264	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8265	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8266	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8267	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8268	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8269
8270	/* Unmute Mixer 14 (mic) 1c (Line in)*/
8271	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8272        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8273	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8274        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8275
8276	/* Unmute Stereo Mixer 15 */
8277	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8278	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8279	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8280	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
8281
8282	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8283	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8284	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8285	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8286	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8287	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8288	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8289	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8290	/* hp used DAC 3 (Front) */
8291	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8292        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8293	{ }
8294};
8295
8296static struct hda_verb alc861_asus_init_verbs[] = {
8297	/*
8298	 * Unmute ADC0 and set the default input to mic-in
8299	 */
8300	/* port-A for surround (rear panel)
8301	 * according to codec#0 this is the HP jack
8302	 */
8303	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
8304	/* route front PCM to HP */
8305	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
8306	/* port-B for mic-in (rear panel) with vref */
8307	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8308	/* port-C for line-in (rear panel) */
8309	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8310	/* port-D for Front */
8311	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8312	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
8313	/* port-E for HP out (front panel) */
8314	/* this has to be set to VREF80 */
8315	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8316	/* route front PCM to HP */
8317	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
8318	/* port-F for mic-in (front panel) with vref */
8319	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
8320	/* port-G for CLFE (rear panel) */
8321	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8322	/* port-H for side (rear panel) */
8323	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
8324	/* CD-in */
8325	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
8326	/* route front mic to ADC1*/
8327	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8328	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8329	/* Unmute DAC0~3 & spdif out*/
8330	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8331	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8332	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8333	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8334	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8335	/* Unmute Mixer 14 (mic) 1c (Line in)*/
8336	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8337        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8338	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8339        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8340
8341	/* Unmute Stereo Mixer 15 */
8342	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8343	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8344	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8345	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
8346
8347	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8348	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8349	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8350	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8351	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8352	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8353	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8354	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8355	/* hp used DAC 3 (Front) */
8356	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8357	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8358	{ }
8359};
8360
8361/* additional init verbs for ASUS laptops */
8362static struct hda_verb alc861_asus_laptop_init_verbs[] = {
8363	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
8364	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
8365	{ }
8366};
8367
8368/*
8369 * generic initialization of ADC, input mixers and output mixers
8370 */
8371static struct hda_verb alc861_auto_init_verbs[] = {
8372	/*
8373	 * Unmute ADC0 and set the default input to mic-in
8374	 */
8375	/* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
8376	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8377
8378	/* Unmute DAC0~3 & spdif out*/
8379	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8380	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8381	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8382	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8383	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8384
8385	/* Unmute Mixer 14 (mic) 1c (Line in)*/
8386	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8387	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8388	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8389	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8390
8391	/* Unmute Stereo Mixer 15 */
8392	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8393	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8394	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8395	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
8396
8397	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8398	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8399	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8400	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8401	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8402	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8403	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8404	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8405
8406	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8407	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8408	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8409	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8410	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8411	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8412	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8413	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8414
8415	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},	/* set Mic 1 */
8416
8417	{ }
8418};
8419
8420static struct hda_verb alc861_toshiba_init_verbs[] = {
8421	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
8422
8423	{ }
8424};
8425
8426/* toggle speaker-output according to the hp-jack state */
8427static void alc861_toshiba_automute(struct hda_codec *codec)
8428{
8429	unsigned int present;
8430
8431	present = snd_hda_codec_read(codec, 0x0f, 0,
8432				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
8433	snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0,
8434				 0x80, present ? 0x80 : 0);
8435	snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0,
8436				 0x80, present ? 0x80 : 0);
8437	snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3,
8438				 0x80, present ? 0 : 0x80);
8439	snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3,
8440				 0x80, present ? 0 : 0x80);
8441}
8442
8443static void alc861_toshiba_unsol_event(struct hda_codec *codec,
8444				       unsigned int res)
8445{
8446	if ((res >> 26) == ALC880_HP_EVENT)
8447		alc861_toshiba_automute(codec);
8448}
8449
8450/* pcm configuration: identiacal with ALC880 */
8451#define alc861_pcm_analog_playback	alc880_pcm_analog_playback
8452#define alc861_pcm_analog_capture	alc880_pcm_analog_capture
8453#define alc861_pcm_digital_playback	alc880_pcm_digital_playback
8454#define alc861_pcm_digital_capture	alc880_pcm_digital_capture
8455
8456
8457#define ALC861_DIGOUT_NID	0x07
8458
8459static struct hda_channel_mode alc861_8ch_modes[1] = {
8460	{ 8, NULL }
8461};
8462
8463static hda_nid_t alc861_dac_nids[4] = {
8464	/* front, surround, clfe, side */
8465	0x03, 0x06, 0x05, 0x04
8466};
8467
8468static hda_nid_t alc660_dac_nids[3] = {
8469	/* front, clfe, surround */
8470	0x03, 0x05, 0x06
8471};
8472
8473static hda_nid_t alc861_adc_nids[1] = {
8474	/* ADC0-2 */
8475	0x08,
8476};
8477
8478static struct hda_input_mux alc861_capture_source = {
8479	.num_items = 5,
8480	.items = {
8481		{ "Mic", 0x0 },
8482		{ "Front Mic", 0x3 },
8483		{ "Line", 0x1 },
8484		{ "CD", 0x4 },
8485		{ "Mixer", 0x5 },
8486	},
8487};
8488
8489/* fill in the dac_nids table from the parsed pin configuration */
8490static int alc861_auto_fill_dac_nids(struct alc_spec *spec,
8491				     const struct auto_pin_cfg *cfg)
8492{
8493	int i;
8494	hda_nid_t nid;
8495
8496	spec->multiout.dac_nids = spec->private_dac_nids;
8497	for (i = 0; i < cfg->line_outs; i++) {
8498		nid = cfg->line_out_pins[i];
8499		if (nid) {
8500			if (i >= ARRAY_SIZE(alc861_dac_nids))
8501				continue;
8502			spec->multiout.dac_nids[i] = alc861_dac_nids[i];
8503		}
8504	}
8505	spec->multiout.num_dacs = cfg->line_outs;
8506	return 0;
8507}
8508
8509/* add playback controls from the parsed DAC table */
8510static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
8511					     const struct auto_pin_cfg *cfg)
8512{
8513	char name[32];
8514	static const char *chname[4] = {
8515		"Front", "Surround", NULL /*CLFE*/, "Side"
8516	};
8517	hda_nid_t nid;
8518	int i, idx, err;
8519
8520	for (i = 0; i < cfg->line_outs; i++) {
8521		nid = spec->multiout.dac_nids[i];
8522		if (!nid)
8523			continue;
8524		if (nid == 0x05) {
8525			/* Center/LFE */
8526			err = add_control(spec, ALC_CTL_BIND_MUTE,
8527					  "Center Playback Switch",
8528					  HDA_COMPOSE_AMP_VAL(nid, 1, 0,
8529							      HDA_OUTPUT));
8530			if (err < 0)
8531				return err;
8532			err = add_control(spec, ALC_CTL_BIND_MUTE,
8533					  "LFE Playback Switch",
8534					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
8535							      HDA_OUTPUT));
8536			if (err < 0)
8537				return err;
8538		} else {
8539			for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1;
8540			     idx++)
8541				if (nid == alc861_dac_nids[idx])
8542					break;
8543			sprintf(name, "%s Playback Switch", chname[idx]);
8544			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
8545					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
8546							      HDA_OUTPUT));
8547			if (err < 0)
8548				return err;
8549		}
8550	}
8551	return 0;
8552}
8553
8554static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
8555{
8556	int err;
8557	hda_nid_t nid;
8558
8559	if (!pin)
8560		return 0;
8561
8562	if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
8563		nid = 0x03;
8564		err = add_control(spec, ALC_CTL_WIDGET_MUTE,
8565				  "Headphone Playback Switch",
8566				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
8567		if (err < 0)
8568			return err;
8569		spec->multiout.hp_nid = nid;
8570	}
8571	return 0;
8572}
8573
8574/* create playback/capture controls for input pins */
8575static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
8576						const struct auto_pin_cfg *cfg)
8577{
8578	struct hda_input_mux *imux = &spec->private_imux;
8579	int i, err, idx, idx1;
8580
8581	for (i = 0; i < AUTO_PIN_LAST; i++) {
8582		switch (cfg->input_pins[i]) {
8583		case 0x0c:
8584			idx1 = 1;
8585			idx = 2;	/* Line In */
8586			break;
8587		case 0x0f:
8588			idx1 = 2;
8589			idx = 2;	/* Line In */
8590			break;
8591		case 0x0d:
8592			idx1 = 0;
8593			idx = 1;	/* Mic In */
8594			break;
8595		case 0x10:
8596			idx1 = 3;
8597			idx = 1;	/* Mic In */
8598			break;
8599		case 0x11:
8600			idx1 = 4;
8601			idx = 0;	/* CD */
8602			break;
8603		default:
8604			continue;
8605		}
8606
8607		err = new_analog_input(spec, cfg->input_pins[i],
8608				       auto_pin_cfg_labels[i], idx, 0x15);
8609		if (err < 0)
8610			return err;
8611
8612		imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
8613		imux->items[imux->num_items].index = idx1;
8614		imux->num_items++;
8615	}
8616	return 0;
8617}
8618
8619static struct snd_kcontrol_new alc861_capture_mixer[] = {
8620	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
8621	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
8622
8623	{
8624		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8625		/* The multiple "Capture Source" controls confuse alsamixer
8626		 * So call somewhat different..
8627		 *FIXME: the controls appear in the "playback" view!
8628		 */
8629		/* .name = "Capture Source", */
8630		.name = "Input Source",
8631		.count = 1,
8632		.info = alc_mux_enum_info,
8633		.get = alc_mux_enum_get,
8634		.put = alc_mux_enum_put,
8635	},
8636	{ } /* end */
8637};
8638
8639static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
8640					      hda_nid_t nid,
8641					      int pin_type, int dac_idx)
8642{
8643	/* set as output */
8644
8645	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
8646			    pin_type);
8647	snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE,
8648			    AMP_OUT_UNMUTE);
8649
8650}
8651
8652static void alc861_auto_init_multi_out(struct hda_codec *codec)
8653{
8654	struct alc_spec *spec = codec->spec;
8655	int i;
8656
8657	alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b);
8658	for (i = 0; i < spec->autocfg.line_outs; i++) {
8659		hda_nid_t nid = spec->autocfg.line_out_pins[i];
8660		int pin_type = get_pin_type(spec->autocfg.line_out_type);
8661		if (nid)
8662			alc861_auto_set_output_and_unmute(codec, nid, pin_type,
8663							  spec->multiout.dac_nids[i]);
8664	}
8665}
8666
8667static void alc861_auto_init_hp_out(struct hda_codec *codec)
8668{
8669	struct alc_spec *spec = codec->spec;
8670	hda_nid_t pin;
8671
8672	pin = spec->autocfg.hp_pins[0];
8673	if (pin) /* connect to front */
8674		alc861_auto_set_output_and_unmute(codec, pin, PIN_HP,
8675						  spec->multiout.dac_nids[0]);
8676}
8677
8678static void alc861_auto_init_analog_input(struct hda_codec *codec)
8679{
8680	struct alc_spec *spec = codec->spec;
8681	int i;
8682
8683	for (i = 0; i < AUTO_PIN_LAST; i++) {
8684		hda_nid_t nid = spec->autocfg.input_pins[i];
8685		if (nid >= 0x0c && nid <= 0x11) {
8686			snd_hda_codec_write(codec, nid, 0,
8687					    AC_VERB_SET_PIN_WIDGET_CONTROL,
8688					    i <= AUTO_PIN_FRONT_MIC ?
8689					    PIN_VREF80 : PIN_IN);
8690		}
8691	}
8692}
8693
8694/* parse the BIOS configuration and set up the alc_spec */
8695/* return 1 if successful, 0 if the proper config is not found,
8696 * or a negative error code
8697 */
8698static int alc861_parse_auto_config(struct hda_codec *codec)
8699{
8700	struct alc_spec *spec = codec->spec;
8701	int err;
8702	static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
8703
8704	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
8705					   alc861_ignore);
8706	if (err < 0)
8707		return err;
8708	if (!spec->autocfg.line_outs)
8709		return 0; /* can't find valid BIOS pin config */
8710
8711	err = alc861_auto_fill_dac_nids(spec, &spec->autocfg);
8712	if (err < 0)
8713		return err;
8714	err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg);
8715	if (err < 0)
8716		return err;
8717	err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
8718	if (err < 0)
8719		return err;
8720	err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg);
8721	if (err < 0)
8722		return err;
8723
8724	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
8725
8726	if (spec->autocfg.dig_out_pin)
8727		spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
8728
8729	if (spec->kctl_alloc)
8730		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
8731
8732	spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
8733
8734	spec->num_mux_defs = 1;
8735	spec->input_mux = &spec->private_imux;
8736
8737	spec->adc_nids = alc861_adc_nids;
8738	spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
8739	spec->mixers[spec->num_mixers] = alc861_capture_mixer;
8740	spec->num_mixers++;
8741
8742	return 1;
8743}
8744
8745/* additional initialization for auto-configuration model */
8746static void alc861_auto_init(struct hda_codec *codec)
8747{
8748	alc861_auto_init_multi_out(codec);
8749	alc861_auto_init_hp_out(codec);
8750	alc861_auto_init_analog_input(codec);
8751}
8752
8753
8754/*
8755 * configuration and preset
8756 */
8757static const char *alc861_models[ALC861_MODEL_LAST] = {
8758	[ALC861_3ST]		= "3stack",
8759	[ALC660_3ST]		= "3stack-660",
8760	[ALC861_3ST_DIG]	= "3stack-dig",
8761	[ALC861_6ST_DIG]	= "6stack-dig",
8762	[ALC861_UNIWILL_M31]	= "uniwill-m31",
8763	[ALC861_TOSHIBA]	= "toshiba",
8764	[ALC861_ASUS]		= "asus",
8765	[ALC861_ASUS_LAPTOP]	= "asus-laptop",
8766	[ALC861_AUTO]		= "auto",
8767};
8768
8769static struct snd_pci_quirk alc861_cfg_tbl[] = {
8770	SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
8771	SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
8772	SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
8773	SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
8774	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
8775	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
8776	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA),
8777	SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
8778	SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
8779	SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
8780	SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
8781	{}
8782};
8783
8784static struct alc_config_preset alc861_presets[] = {
8785	[ALC861_3ST] = {
8786		.mixers = { alc861_3ST_mixer },
8787		.init_verbs = { alc861_threestack_init_verbs },
8788		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8789		.dac_nids = alc861_dac_nids,
8790		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
8791		.channel_mode = alc861_threestack_modes,
8792		.need_dac_fix = 1,
8793		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8794		.adc_nids = alc861_adc_nids,
8795		.input_mux = &alc861_capture_source,
8796	},
8797	[ALC861_3ST_DIG] = {
8798		.mixers = { alc861_base_mixer },
8799		.init_verbs = { alc861_threestack_init_verbs },
8800		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8801		.dac_nids = alc861_dac_nids,
8802		.dig_out_nid = ALC861_DIGOUT_NID,
8803		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
8804		.channel_mode = alc861_threestack_modes,
8805		.need_dac_fix = 1,
8806		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8807		.adc_nids = alc861_adc_nids,
8808		.input_mux = &alc861_capture_source,
8809	},
8810	[ALC861_6ST_DIG] = {
8811		.mixers = { alc861_base_mixer },
8812		.init_verbs = { alc861_base_init_verbs },
8813		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8814		.dac_nids = alc861_dac_nids,
8815		.dig_out_nid = ALC861_DIGOUT_NID,
8816		.num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
8817		.channel_mode = alc861_8ch_modes,
8818		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8819		.adc_nids = alc861_adc_nids,
8820		.input_mux = &alc861_capture_source,
8821	},
8822	[ALC660_3ST] = {
8823		.mixers = { alc861_3ST_mixer },
8824		.init_verbs = { alc861_threestack_init_verbs },
8825		.num_dacs = ARRAY_SIZE(alc660_dac_nids),
8826		.dac_nids = alc660_dac_nids,
8827		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
8828		.channel_mode = alc861_threestack_modes,
8829		.need_dac_fix = 1,
8830		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8831		.adc_nids = alc861_adc_nids,
8832		.input_mux = &alc861_capture_source,
8833	},
8834	[ALC861_UNIWILL_M31] = {
8835		.mixers = { alc861_uniwill_m31_mixer },
8836		.init_verbs = { alc861_uniwill_m31_init_verbs },
8837		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8838		.dac_nids = alc861_dac_nids,
8839		.dig_out_nid = ALC861_DIGOUT_NID,
8840		.num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
8841		.channel_mode = alc861_uniwill_m31_modes,
8842		.need_dac_fix = 1,
8843		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8844		.adc_nids = alc861_adc_nids,
8845		.input_mux = &alc861_capture_source,
8846	},
8847	[ALC861_TOSHIBA] = {
8848		.mixers = { alc861_toshiba_mixer },
8849		.init_verbs = { alc861_base_init_verbs,
8850				alc861_toshiba_init_verbs },
8851		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8852		.dac_nids = alc861_dac_nids,
8853		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8854		.channel_mode = alc883_3ST_2ch_modes,
8855		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8856		.adc_nids = alc861_adc_nids,
8857		.input_mux = &alc861_capture_source,
8858		.unsol_event = alc861_toshiba_unsol_event,
8859		.init_hook = alc861_toshiba_automute,
8860	},
8861	[ALC861_ASUS] = {
8862		.mixers = { alc861_asus_mixer },
8863		.init_verbs = { alc861_asus_init_verbs },
8864		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8865		.dac_nids = alc861_dac_nids,
8866		.dig_out_nid = ALC861_DIGOUT_NID,
8867		.num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
8868		.channel_mode = alc861_asus_modes,
8869		.need_dac_fix = 1,
8870		.hp_nid = 0x06,
8871		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8872		.adc_nids = alc861_adc_nids,
8873		.input_mux = &alc861_capture_source,
8874	},
8875	[ALC861_ASUS_LAPTOP] = {
8876		.mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
8877		.init_verbs = { alc861_asus_init_verbs,
8878				alc861_asus_laptop_init_verbs },
8879		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
8880		.dac_nids = alc861_dac_nids,
8881		.dig_out_nid = ALC861_DIGOUT_NID,
8882		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
8883		.channel_mode = alc883_3ST_2ch_modes,
8884		.need_dac_fix = 1,
8885		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
8886		.adc_nids = alc861_adc_nids,
8887		.input_mux = &alc861_capture_source,
8888	},
8889};
8890
8891
8892static int patch_alc861(struct hda_codec *codec)
8893{
8894	struct alc_spec *spec;
8895	int board_config;
8896	int err;
8897
8898	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
8899	if (spec == NULL)
8900		return -ENOMEM;
8901
8902	codec->spec = spec;
8903
8904        board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
8905						  alc861_models,
8906						  alc861_cfg_tbl);
8907
8908	if (board_config < 0) {
8909		printk(KERN_INFO "hda_codec: Unknown model for ALC861, "
8910		       "trying auto-probe from BIOS...\n");
8911		board_config = ALC861_AUTO;
8912	}
8913
8914	if (board_config == ALC861_AUTO) {
8915		/* automatic parse from the BIOS config */
8916		err = alc861_parse_auto_config(codec);
8917		if (err < 0) {
8918			alc_free(codec);
8919			return err;
8920		} else if (!err) {
8921			printk(KERN_INFO
8922			       "hda_codec: Cannot set up configuration "
8923			       "from BIOS.  Using base mode...\n");
8924		   board_config = ALC861_3ST_DIG;
8925		}
8926	}
8927
8928	if (board_config != ALC861_AUTO)
8929		setup_preset(spec, &alc861_presets[board_config]);
8930
8931	spec->stream_name_analog = "ALC861 Analog";
8932	spec->stream_analog_playback = &alc861_pcm_analog_playback;
8933	spec->stream_analog_capture = &alc861_pcm_analog_capture;
8934
8935	spec->stream_name_digital = "ALC861 Digital";
8936	spec->stream_digital_playback = &alc861_pcm_digital_playback;
8937	spec->stream_digital_capture = &alc861_pcm_digital_capture;
8938
8939	codec->patch_ops = alc_patch_ops;
8940	if (board_config == ALC861_AUTO)
8941		spec->init_hook = alc861_auto_init;
8942
8943	return 0;
8944}
8945
8946/*
8947 * ALC861-VD support
8948 *
8949 * Based on ALC882
8950 *
8951 * In addition, an independent DAC
8952 */
8953#define ALC861VD_DIGOUT_NID	0x06
8954
8955static hda_nid_t alc861vd_dac_nids[4] = {
8956	/* front, surr, clfe, side surr */
8957	0x02, 0x03, 0x04, 0x05
8958};
8959
8960/* dac_nids for ALC660vd are in a different order - according to
8961 * Realtek's driver.
8962 * This should probably tesult in a different mixer for 6stack models
8963 * of ALC660vd codecs, but for now there is only 3stack mixer
8964 * - and it is the same as in 861vd.
8965 * adc_nids in ALC660vd are (is) the same as in 861vd
8966 */
8967static hda_nid_t alc660vd_dac_nids[3] = {
8968	/* front, rear, clfe, rear_surr */
8969	0x02, 0x04, 0x03
8970};
8971
8972static hda_nid_t alc861vd_adc_nids[1] = {
8973	/* ADC0 */
8974	0x09,
8975};
8976
8977/* input MUX */
8978/* FIXME: should be a matrix-type input source selection */
8979static struct hda_input_mux alc861vd_capture_source = {
8980	.num_items = 4,
8981	.items = {
8982		{ "Mic", 0x0 },
8983		{ "Front Mic", 0x1 },
8984		{ "Line", 0x2 },
8985		{ "CD", 0x4 },
8986	},
8987};
8988
8989static struct hda_input_mux alc861vd_dallas_capture_source = {
8990	.num_items = 3,
8991	.items = {
8992		{ "Front Mic", 0x0 },
8993		{ "ATAPI Mic", 0x1 },
8994		{ "Line In", 0x5 },
8995	},
8996};
8997
8998#define alc861vd_mux_enum_info alc_mux_enum_info
8999#define alc861vd_mux_enum_get alc_mux_enum_get
9000
9001static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
9002				struct snd_ctl_elem_value *ucontrol)
9003{
9004	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9005	struct alc_spec *spec = codec->spec;
9006	const struct hda_input_mux *imux = spec->input_mux;
9007	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
9008	static hda_nid_t capture_mixers[1] = { 0x22 };
9009	hda_nid_t nid = capture_mixers[adc_idx];
9010	unsigned int *cur_val = &spec->cur_mux[adc_idx];
9011	unsigned int i, idx;
9012
9013	idx = ucontrol->value.enumerated.item[0];
9014	if (idx >= imux->num_items)
9015		idx = imux->num_items - 1;
9016	if (*cur_val == idx && !codec->in_resume)
9017		return 0;
9018	for (i = 0; i < imux->num_items; i++) {
9019		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
9020		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
9021				    v | (imux->items[i].index << 8));
9022	}
9023	*cur_val = idx;
9024	return 1;
9025}
9026
9027/*
9028 * 2ch mode
9029 */
9030static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
9031	{ 2, NULL }
9032};
9033
9034/*
9035 * 6ch mode
9036 */
9037static struct hda_verb alc861vd_6stack_ch6_init[] = {
9038	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
9039	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9040	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9041	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9042	{ } /* end */
9043};
9044
9045/*
9046 * 8ch mode
9047 */
9048static struct hda_verb alc861vd_6stack_ch8_init[] = {
9049	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9050	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9051	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9052	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9053	{ } /* end */
9054};
9055
9056static struct hda_channel_mode alc861vd_6stack_modes[2] = {
9057	{ 6, alc861vd_6stack_ch6_init },
9058	{ 8, alc861vd_6stack_ch8_init },
9059};
9060
9061static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
9062	{
9063		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9064		.name = "Channel Mode",
9065		.info = alc_ch_mode_info,
9066		.get = alc_ch_mode_get,
9067		.put = alc_ch_mode_put,
9068	},
9069	{ } /* end */
9070};
9071
9072static struct snd_kcontrol_new alc861vd_capture_mixer[] = {
9073	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
9074	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
9075
9076	{
9077		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9078		/* The multiple "Capture Source" controls confuse alsamixer
9079		 * So call somewhat different..
9080		 *FIXME: the controls appear in the "playback" view!
9081		 */
9082		/* .name = "Capture Source", */
9083		.name = "Input Source",
9084		.count = 1,
9085		.info = alc861vd_mux_enum_info,
9086		.get = alc861vd_mux_enum_get,
9087		.put = alc861vd_mux_enum_put,
9088	},
9089	{ } /* end */
9090};
9091
9092/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
9093 *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
9094 */
9095static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
9096	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
9097	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9098
9099	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
9100	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
9101
9102	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
9103				HDA_OUTPUT),
9104	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
9105				HDA_OUTPUT),
9106	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
9107	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
9108
9109	HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
9110	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
9111
9112	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9113
9114	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
9115	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9116	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9117
9118	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
9119	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9120	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9121
9122	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9123	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9124
9125	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9126	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9127
9128	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
9129	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
9130
9131	{ } /* end */
9132};
9133
9134static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
9135	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
9136	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9137
9138	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9139
9140	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
9141	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9142	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9143
9144	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
9145	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9146	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9147
9148	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9149	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9150
9151	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9152	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9153
9154	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
9155	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
9156
9157	{ } /* end */
9158};
9159
9160static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
9161	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
9162	/*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
9163	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9164
9165	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
9166
9167	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
9168	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9169	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9170
9171	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
9172	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9173	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9174
9175	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
9176	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
9177
9178	{ } /* end */
9179};
9180
9181/* Pin assignment: Front=0x14, HP = 0x15,
9182 *                 Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d
9183 */
9184static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
9185	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
9186	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
9187	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
9188	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
9189	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9190	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9191	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
9192	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
9193	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT),
9194	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT),
9195	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
9196	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
9197	{
9198		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9199		/* .name = "Capture Source", */
9200		.name = "Input Source",
9201		.count = 1,
9202		.info = alc882_mux_enum_info,
9203		.get = alc882_mux_enum_get,
9204		.put = alc882_mux_enum_put,
9205	},
9206	{ } /* end */
9207};
9208
9209/*
9210 * generic initialization of ADC, input mixers and output mixers
9211 */
9212static struct hda_verb alc861vd_volume_init_verbs[] = {
9213	/*
9214	 * Unmute ADC0 and set the default input to mic-in
9215	 */
9216	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
9217	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9218
9219	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
9220	 * the analog-loopback mixer widget
9221	 */
9222	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
9223	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9224	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9225	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
9226	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
9227	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
9228
9229	/* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
9230	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9231	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9232	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
9233	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
9234
9235	/*
9236	 * Set up output mixers (0x02 - 0x05)
9237	 */
9238	/* set vol=0 to output mixers */
9239	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9240	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9241	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9242	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9243
9244	/* set up input amps for analog loopback */
9245	/* Amp Indices: DAC = 0, mixer = 1 */
9246	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9247	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9248	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9249	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9250	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9251	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9252	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9253	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9254
9255	{ }
9256};
9257
9258/*
9259 * 3-stack pin configuration:
9260 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
9261 */
9262static struct hda_verb alc861vd_3stack_init_verbs[] = {
9263	/*
9264	 * Set pin mode and muting
9265	 */
9266	/* set front pin widgets 0x14 for output */
9267	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9268	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9269	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9270
9271	/* Mic (rear) pin: input vref at 80% */
9272	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9273	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9274	/* Front Mic pin: input vref at 80% */
9275	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9276	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9277	/* Line In pin: input */
9278	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9279	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9280	/* Line-2 In: Headphone output (output 0 - 0x0c) */
9281	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9282	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9283	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9284	/* CD pin widget for input */
9285	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9286
9287	{ }
9288};
9289
9290/*
9291 * 6-stack pin configuration:
9292 */
9293static struct hda_verb alc861vd_6stack_init_verbs[] = {
9294	/*
9295	 * Set pin mode and muting
9296	 */
9297	/* set front pin widgets 0x14 for output */
9298	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9299	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9300	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9301
9302	/* Rear Pin: output 1 (0x0d) */
9303	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9304	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9305	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
9306	/* CLFE Pin: output 2 (0x0e) */
9307	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9308	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9309	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
9310	/* Side Pin: output 3 (0x0f) */
9311	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9312	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9313	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
9314
9315	/* Mic (rear) pin: input vref at 80% */
9316	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9317	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9318	/* Front Mic pin: input vref at 80% */
9319	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9320	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9321	/* Line In pin: input */
9322	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9323	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9324	/* Line-2 In: Headphone output (output 0 - 0x0c) */
9325	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9326	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9327	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9328	/* CD pin widget for input */
9329	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9330
9331	{ }
9332};
9333
9334static struct hda_verb alc861vd_eapd_verbs[] = {
9335	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
9336	{ }
9337};
9338
9339static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
9340	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9341	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9342	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
9343	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
9344	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
9345	{}
9346};
9347
9348/* toggle speaker-output according to the hp-jack state */
9349static void alc861vd_lenovo_hp_automute(struct hda_codec *codec)
9350{
9351	unsigned int present;
9352	unsigned char bits;
9353
9354	present = snd_hda_codec_read(codec, 0x1b, 0,
9355				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
9356	bits = present ? 0x80 : 0;
9357	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
9358				 0x80, bits);
9359	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
9360				 0x80, bits);
9361}
9362
9363static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
9364{
9365	unsigned int present;
9366	unsigned char bits;
9367
9368	present = snd_hda_codec_read(codec, 0x18, 0,
9369				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
9370	bits = present ? 0x80 : 0;
9371	snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1,
9372				 0x80, bits);
9373	snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1,
9374				 0x80, bits);
9375}
9376
9377static void alc861vd_lenovo_automute(struct hda_codec *codec)
9378{
9379	alc861vd_lenovo_hp_automute(codec);
9380	alc861vd_lenovo_mic_automute(codec);
9381}
9382
9383static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
9384					unsigned int res)
9385{
9386	switch (res >> 26) {
9387	case ALC880_HP_EVENT:
9388		alc861vd_lenovo_hp_automute(codec);
9389		break;
9390	case ALC880_MIC_EVENT:
9391		alc861vd_lenovo_mic_automute(codec);
9392		break;
9393	}
9394}
9395
9396static struct hda_verb alc861vd_dallas_verbs[] = {
9397	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9398	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9399	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9400	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9401
9402	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9403	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9404	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9405	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9406	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9407	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9408	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9409	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9410
9411	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9412	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9413	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9414	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9415	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9416	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9417	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9418	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9419
9420	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
9421	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9422	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
9423	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9424	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9425	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9426	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9427	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9428
9429	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9430	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
9431	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
9432	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
9433
9434	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9435	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
9436	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
9437
9438	{ } /* end */
9439};
9440
9441/* toggle speaker-output according to the hp-jack state */
9442static void alc861vd_dallas_automute(struct hda_codec *codec)
9443{
9444	unsigned int present;
9445
9446	present = snd_hda_codec_read(codec, 0x15, 0,
9447				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
9448	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
9449				 0x80, present ? 0x80 : 0);
9450	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
9451				 0x80, present ? 0x80 : 0);
9452}
9453
9454static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res)
9455{
9456	if ((res >> 26) == ALC880_HP_EVENT)
9457		alc861vd_dallas_automute(codec);
9458}
9459
9460/* pcm configuration: identiacal with ALC880 */
9461#define alc861vd_pcm_analog_playback	alc880_pcm_analog_playback
9462#define alc861vd_pcm_analog_capture	alc880_pcm_analog_capture
9463#define alc861vd_pcm_digital_playback	alc880_pcm_digital_playback
9464#define alc861vd_pcm_digital_capture	alc880_pcm_digital_capture
9465
9466/*
9467 * configuration and preset
9468 */
9469static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
9470	[ALC660VD_3ST]		= "3stack-660",
9471	[ALC861VD_3ST]		= "3stack",
9472	[ALC861VD_3ST_DIG]	= "3stack-digout",
9473	[ALC861VD_6ST_DIG]	= "6stack-digout",
9474	[ALC861VD_LENOVO]	= "lenovo",
9475	[ALC861VD_DALLAS]	= "dallas",
9476	[ALC861VD_AUTO]		= "auto",
9477};
9478
9479static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
9480	SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
9481	SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
9482	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST),
9483	SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
9484	SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
9485
9486	SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),
9487	SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
9488	SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
9489	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
9490	{}
9491};
9492
9493static struct alc_config_preset alc861vd_presets[] = {
9494	[ALC660VD_3ST] = {
9495		.mixers = { alc861vd_3st_mixer },
9496		.init_verbs = { alc861vd_volume_init_verbs,
9497				 alc861vd_3stack_init_verbs },
9498		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
9499		.dac_nids = alc660vd_dac_nids,
9500		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
9501		.adc_nids = alc861vd_adc_nids,
9502		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
9503		.channel_mode = alc861vd_3stack_2ch_modes,
9504		.input_mux = &alc861vd_capture_source,
9505	},
9506	[ALC861VD_3ST] = {
9507		.mixers = { alc861vd_3st_mixer },
9508		.init_verbs = { alc861vd_volume_init_verbs,
9509				 alc861vd_3stack_init_verbs },
9510		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
9511		.dac_nids = alc861vd_dac_nids,
9512		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
9513		.channel_mode = alc861vd_3stack_2ch_modes,
9514		.input_mux = &alc861vd_capture_source,
9515	},
9516	[ALC861VD_3ST_DIG] = {
9517		.mixers = { alc861vd_3st_mixer },
9518		.init_verbs = { alc861vd_volume_init_verbs,
9519		 		 alc861vd_3stack_init_verbs },
9520		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
9521		.dac_nids = alc861vd_dac_nids,
9522		.dig_out_nid = ALC861VD_DIGOUT_NID,
9523		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
9524		.channel_mode = alc861vd_3stack_2ch_modes,
9525		.input_mux = &alc861vd_capture_source,
9526	},
9527	[ALC861VD_6ST_DIG] = {
9528		.mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
9529		.init_verbs = { alc861vd_volume_init_verbs,
9530				alc861vd_6stack_init_verbs },
9531		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
9532		.dac_nids = alc861vd_dac_nids,
9533		.dig_out_nid = ALC861VD_DIGOUT_NID,
9534		.num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
9535		.channel_mode = alc861vd_6stack_modes,
9536		.input_mux = &alc861vd_capture_source,
9537	},
9538	[ALC861VD_LENOVO] = {
9539		.mixers = { alc861vd_lenovo_mixer },
9540		.init_verbs = { alc861vd_volume_init_verbs,
9541				alc861vd_3stack_init_verbs,
9542				alc861vd_eapd_verbs,
9543				alc861vd_lenovo_unsol_verbs },
9544		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
9545		.dac_nids = alc660vd_dac_nids,
9546		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
9547		.adc_nids = alc861vd_adc_nids,
9548		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
9549		.channel_mode = alc861vd_3stack_2ch_modes,
9550		.input_mux = &alc861vd_capture_source,
9551		.unsol_event = alc861vd_lenovo_unsol_event,
9552		.init_hook = alc861vd_lenovo_automute,
9553	},
9554	[ALC861VD_DALLAS] = {
9555		.mixers = { alc861vd_dallas_mixer },
9556		.init_verbs = { alc861vd_dallas_verbs },
9557		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
9558		.dac_nids = alc861vd_dac_nids,
9559		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
9560		.adc_nids = alc861vd_adc_nids,
9561		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
9562		.channel_mode = alc861vd_3stack_2ch_modes,
9563		.input_mux = &alc861vd_dallas_capture_source,
9564		.unsol_event = alc861vd_dallas_unsol_event,
9565		.init_hook = alc861vd_dallas_automute,
9566	},
9567};
9568
9569/*
9570 * BIOS auto configuration
9571 */
9572static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
9573				hda_nid_t nid, int pin_type, int dac_idx)
9574{
9575	/* set as output */
9576	snd_hda_codec_write(codec, nid, 0,
9577				AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
9578	snd_hda_codec_write(codec, nid, 0,
9579				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
9580}
9581
9582static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
9583{
9584	struct alc_spec *spec = codec->spec;
9585	int i;
9586
9587	alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
9588	for (i = 0; i <= HDA_SIDE; i++) {
9589		hda_nid_t nid = spec->autocfg.line_out_pins[i];
9590		int pin_type = get_pin_type(spec->autocfg.line_out_type);
9591		if (nid)
9592			alc861vd_auto_set_output_and_unmute(codec, nid,
9593							    pin_type, i);
9594	}
9595}
9596
9597
9598static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
9599{
9600	struct alc_spec *spec = codec->spec;
9601	hda_nid_t pin;
9602
9603	pin = spec->autocfg.hp_pins[0];
9604	if (pin) /* connect to front and  use dac 0 */
9605		alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
9606}
9607
9608#define alc861vd_is_input_pin(nid)	alc880_is_input_pin(nid)
9609#define ALC861VD_PIN_CD_NID		ALC880_PIN_CD_NID
9610
9611static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
9612{
9613	struct alc_spec *spec = codec->spec;
9614	int i;
9615
9616	for (i = 0; i < AUTO_PIN_LAST; i++) {
9617		hda_nid_t nid = spec->autocfg.input_pins[i];
9618		if (alc861vd_is_input_pin(nid)) {
9619			snd_hda_codec_write(codec, nid, 0,
9620					AC_VERB_SET_PIN_WIDGET_CONTROL,
9621					i <= AUTO_PIN_FRONT_MIC ?
9622							PIN_VREF80 : PIN_IN);
9623			if (nid != ALC861VD_PIN_CD_NID)
9624				snd_hda_codec_write(codec, nid, 0,
9625						AC_VERB_SET_AMP_GAIN_MUTE,
9626						AMP_OUT_MUTE);
9627		}
9628	}
9629}
9630
9631#define alc861vd_idx_to_mixer_vol(nid)		((nid) + 0x02)
9632#define alc861vd_idx_to_mixer_switch(nid)	((nid) + 0x0c)
9633
9634/* add playback controls from the parsed DAC table */
9635/* Based on ALC880 version. But ALC861VD has separate,
9636 * different NIDs for mute/unmute switch and volume control */
9637static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
9638					     const struct auto_pin_cfg *cfg)
9639{
9640	char name[32];
9641	static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
9642	hda_nid_t nid_v, nid_s;
9643	int i, err;
9644
9645	for (i = 0; i < cfg->line_outs; i++) {
9646		if (!spec->multiout.dac_nids[i])
9647			continue;
9648		nid_v = alc861vd_idx_to_mixer_vol(
9649				alc880_dac_to_idx(
9650					spec->multiout.dac_nids[i]));
9651		nid_s = alc861vd_idx_to_mixer_switch(
9652				alc880_dac_to_idx(
9653					spec->multiout.dac_nids[i]));
9654
9655		if (i == 2) {
9656			/* Center/LFE */
9657			err = add_control(spec, ALC_CTL_WIDGET_VOL,
9658					  "Center Playback Volume",
9659					  HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
9660							      HDA_OUTPUT));
9661			if (err < 0)
9662				return err;
9663			err = add_control(spec, ALC_CTL_WIDGET_VOL,
9664					  "LFE Playback Volume",
9665					  HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
9666							      HDA_OUTPUT));
9667			if (err < 0)
9668				return err;
9669			err = add_control(spec, ALC_CTL_BIND_MUTE,
9670					  "Center Playback Switch",
9671					  HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
9672							      HDA_INPUT));
9673			if (err < 0)
9674				return err;
9675			err = add_control(spec, ALC_CTL_BIND_MUTE,
9676					  "LFE Playback Switch",
9677					  HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
9678							      HDA_INPUT));
9679			if (err < 0)
9680				return err;
9681		} else {
9682			sprintf(name, "%s Playback Volume", chname[i]);
9683			err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
9684					  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
9685							      HDA_OUTPUT));
9686			if (err < 0)
9687				return err;
9688			sprintf(name, "%s Playback Switch", chname[i]);
9689			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
9690					  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
9691							      HDA_INPUT));
9692			if (err < 0)
9693				return err;
9694		}
9695	}
9696	return 0;
9697}
9698
9699/* add playback controls for speaker and HP outputs */
9700/* Based on ALC880 version. But ALC861VD has separate,
9701 * different NIDs for mute/unmute switch and volume control */
9702static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
9703					hda_nid_t pin, const char *pfx)
9704{
9705	hda_nid_t nid_v, nid_s;
9706	int err;
9707	char name[32];
9708
9709	if (!pin)
9710		return 0;
9711
9712	if (alc880_is_fixed_pin(pin)) {
9713		nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
9714		/* specify the DAC as the extra output */
9715		if (!spec->multiout.hp_nid)
9716			spec->multiout.hp_nid = nid_v;
9717		else
9718			spec->multiout.extra_out_nid[0] = nid_v;
9719		/* control HP volume/switch on the output mixer amp */
9720		nid_v = alc861vd_idx_to_mixer_vol(
9721				alc880_fixed_pin_idx(pin));
9722		nid_s = alc861vd_idx_to_mixer_switch(
9723				alc880_fixed_pin_idx(pin));
9724
9725		sprintf(name, "%s Playback Volume", pfx);
9726		err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
9727				  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
9728		if (err < 0)
9729			return err;
9730		sprintf(name, "%s Playback Switch", pfx);
9731		err = add_control(spec, ALC_CTL_BIND_MUTE, name,
9732				  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
9733		if (err < 0)
9734			return err;
9735	} else if (alc880_is_multi_pin(pin)) {
9736		/* set manual connection */
9737		/* we have only a switch on HP-out PIN */
9738		sprintf(name, "%s Playback Switch", pfx);
9739		err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
9740				  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
9741		if (err < 0)
9742			return err;
9743	}
9744	return 0;
9745}
9746
9747/* parse the BIOS configuration and set up the alc_spec
9748 * return 1 if successful, 0 if the proper config is not found,
9749 * or a negative error code
9750 * Based on ALC880 version - had to change it to override
9751 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
9752static int alc861vd_parse_auto_config(struct hda_codec *codec)
9753{
9754	struct alc_spec *spec = codec->spec;
9755	int err;
9756	static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
9757
9758	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
9759					   alc861vd_ignore);
9760	if (err < 0)
9761		return err;
9762	if (!spec->autocfg.line_outs)
9763		return 0; /* can't find valid BIOS pin config */
9764
9765	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
9766	if (err < 0)
9767		return err;
9768	err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
9769	if (err < 0)
9770		return err;
9771	err = alc861vd_auto_create_extra_out(spec,
9772					     spec->autocfg.speaker_pins[0],
9773					     "Speaker");
9774	if (err < 0)
9775		return err;
9776	err = alc861vd_auto_create_extra_out(spec,
9777					     spec->autocfg.hp_pins[0],
9778					     "Headphone");
9779	if (err < 0)
9780		return err;
9781	err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);
9782	if (err < 0)
9783		return err;
9784
9785	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
9786
9787	if (spec->autocfg.dig_out_pin)
9788		spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
9789
9790	if (spec->kctl_alloc)
9791		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
9792
9793	spec->init_verbs[spec->num_init_verbs++]
9794		= alc861vd_volume_init_verbs;
9795
9796	spec->num_mux_defs = 1;
9797	spec->input_mux = &spec->private_imux;
9798
9799	return 1;
9800}
9801
9802/* additional initialization for auto-configuration model */
9803static void alc861vd_auto_init(struct hda_codec *codec)
9804{
9805	alc861vd_auto_init_multi_out(codec);
9806	alc861vd_auto_init_hp_out(codec);
9807	alc861vd_auto_init_analog_input(codec);
9808}
9809
9810static int patch_alc861vd(struct hda_codec *codec)
9811{
9812	struct alc_spec *spec;
9813	int err, board_config;
9814
9815	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
9816	if (spec == NULL)
9817		return -ENOMEM;
9818
9819	codec->spec = spec;
9820
9821	board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
9822						  alc861vd_models,
9823						  alc861vd_cfg_tbl);
9824
9825	if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
9826		printk(KERN_INFO "hda_codec: Unknown model for ALC660VD/"
9827			"ALC861VD, trying auto-probe from BIOS...\n");
9828		board_config = ALC861VD_AUTO;
9829	}
9830
9831	if (board_config == ALC861VD_AUTO) {
9832		/* automatic parse from the BIOS config */
9833		err = alc861vd_parse_auto_config(codec);
9834		if (err < 0) {
9835			alc_free(codec);
9836			return err;
9837		} else if (!err) {
9838			printk(KERN_INFO
9839			       "hda_codec: Cannot set up configuration "
9840			       "from BIOS.  Using base mode...\n");
9841			board_config = ALC861VD_3ST;
9842		}
9843	}
9844
9845	if (board_config != ALC861VD_AUTO)
9846		setup_preset(spec, &alc861vd_presets[board_config]);
9847
9848	spec->stream_name_analog = "ALC861VD Analog";
9849	spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
9850	spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
9851
9852	spec->stream_name_digital = "ALC861VD Digital";
9853	spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
9854	spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
9855
9856	spec->adc_nids = alc861vd_adc_nids;
9857	spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
9858
9859	spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
9860	spec->num_mixers++;
9861
9862	codec->patch_ops = alc_patch_ops;
9863
9864	if (board_config == ALC861VD_AUTO)
9865		spec->init_hook = alc861vd_auto_init;
9866
9867	return 0;
9868}
9869
9870/*
9871 * ALC662 support
9872 *
9873 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
9874 * configuration.  Each pin widget can choose any input DACs and a mixer.
9875 * Each ADC is connected from a mixer of all inputs.  This makes possible
9876 * 6-channel independent captures.
9877 *
9878 * In addition, an independent DAC for the multi-playback (not used in this
9879 * driver yet).
9880 */
9881#define ALC662_DIGOUT_NID	0x06
9882#define ALC662_DIGIN_NID	0x0a
9883
9884static hda_nid_t alc662_dac_nids[4] = {
9885	/* front, rear, clfe, rear_surr */
9886	0x02, 0x03, 0x04
9887};
9888
9889static hda_nid_t alc662_adc_nids[1] = {
9890	/* ADC1-2 */
9891	0x09,
9892};
9893/* input MUX */
9894/* FIXME: should be a matrix-type input source selection */
9895
9896static struct hda_input_mux alc662_capture_source = {
9897	.num_items = 4,
9898	.items = {
9899		{ "Mic", 0x0 },
9900		{ "Front Mic", 0x1 },
9901		{ "Line", 0x2 },
9902		{ "CD", 0x4 },
9903	},
9904};
9905
9906static struct hda_input_mux alc662_lenovo_101e_capture_source = {
9907	.num_items = 2,
9908	.items = {
9909		{ "Mic", 0x1 },
9910		{ "Line", 0x2 },
9911	},
9912};
9913#define alc662_mux_enum_info alc_mux_enum_info
9914#define alc662_mux_enum_get alc_mux_enum_get
9915
9916static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol,
9917			       struct snd_ctl_elem_value *ucontrol)
9918{
9919	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9920	struct alc_spec *spec = codec->spec;
9921	const struct hda_input_mux *imux = spec->input_mux;
9922	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
9923	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
9924	hda_nid_t nid = capture_mixers[adc_idx];
9925	unsigned int *cur_val = &spec->cur_mux[adc_idx];
9926	unsigned int i, idx;
9927
9928	idx = ucontrol->value.enumerated.item[0];
9929	if (idx >= imux->num_items)
9930		idx = imux->num_items - 1;
9931	if (*cur_val == idx && !codec->in_resume)
9932		return 0;
9933	for (i = 0; i < imux->num_items; i++) {
9934		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
9935		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
9936				    v | (imux->items[i].index << 8));
9937	}
9938	*cur_val = idx;
9939	return 1;
9940}
9941/*
9942 * 2ch mode
9943 */
9944static struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
9945	{ 2, NULL }
9946};
9947
9948/*
9949 * 2ch mode
9950 */
9951static struct hda_verb alc662_3ST_ch2_init[] = {
9952	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
9953	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9954	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
9955	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9956	{ } /* end */
9957};
9958
9959/*
9960 * 6ch mode
9961 */
9962static struct hda_verb alc662_3ST_ch6_init[] = {
9963	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9964	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9965	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
9966	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9967	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9968	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
9969	{ } /* end */
9970};
9971
9972static struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
9973	{ 2, alc662_3ST_ch2_init },
9974	{ 6, alc662_3ST_ch6_init },
9975};
9976
9977/*
9978 * 2ch mode
9979 */
9980static struct hda_verb alc662_sixstack_ch6_init[] = {
9981	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
9982	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
9983	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9984	{ } /* end */
9985};
9986
9987/*
9988 * 6ch mode
9989 */
9990static struct hda_verb alc662_sixstack_ch8_init[] = {
9991	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9992	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9993	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9994	{ } /* end */
9995};
9996
9997static struct hda_channel_mode alc662_5stack_modes[2] = {
9998	{ 2, alc662_sixstack_ch6_init },
9999	{ 6, alc662_sixstack_ch8_init },
10000};
10001
10002/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
10003 *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
10004 */
10005
10006static struct snd_kcontrol_new alc662_base_mixer[] = {
10007	/* output mixer control */
10008	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
10009	HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT),
10010	HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
10011	HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT),
10012	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
10013	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
10014	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
10015	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
10016	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10017
10018	/*Input mixer control */
10019	HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
10020	HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
10021	HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
10022	HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
10023	HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
10024	HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
10025	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
10026	HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
10027
10028	/* Capture mixer control */
10029	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
10030	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
10031	{
10032		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10033		.name = "Capture Source",
10034		.count = 1,
10035		.info = alc_mux_enum_info,
10036		.get = alc_mux_enum_get,
10037		.put = alc_mux_enum_put,
10038	},
10039	{ } /* end */
10040};
10041
10042static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
10043	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
10044	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
10045	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10046	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10047	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10048	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10049	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10050	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10051	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10052	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
10053	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
10054	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
10055	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
10056	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
10057	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
10058	{
10059		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10060		/* .name = "Capture Source", */
10061		.name = "Input Source",
10062		.count = 1,
10063		.info = alc662_mux_enum_info,
10064		.get = alc662_mux_enum_get,
10065		.put = alc662_mux_enum_put,
10066	},
10067	{ } /* end */
10068};
10069
10070static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
10071	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
10072	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
10073	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
10074	HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),
10075	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
10076	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
10077	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
10078	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
10079	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10080	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10081	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10082	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10083	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10084	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10085	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10086	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
10087	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
10088	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
10089	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
10090	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
10091	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
10092	{
10093		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10094		/* .name = "Capture Source", */
10095		.name = "Input Source",
10096		.count = 1,
10097		.info = alc662_mux_enum_info,
10098		.get = alc662_mux_enum_get,
10099		.put = alc662_mux_enum_put,
10100	},
10101	{ } /* end */
10102};
10103
10104static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
10105	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
10106	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
10107	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
10108	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x03, 2, HDA_INPUT),
10109	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10110	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10111	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10112	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
10113	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
10114	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
10115	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
10116	{
10117		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10118		/* .name = "Capture Source", */
10119		.name = "Input Source",
10120		.count = 1,
10121		.info = alc662_mux_enum_info,
10122		.get = alc662_mux_enum_get,
10123		.put = alc662_mux_enum_put,
10124	},
10125	{ } /* end */
10126};
10127
10128static struct snd_kcontrol_new alc662_chmode_mixer[] = {
10129	{
10130		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10131		.name = "Channel Mode",
10132		.info = alc_ch_mode_info,
10133		.get = alc_ch_mode_get,
10134		.put = alc_ch_mode_put,
10135	},
10136	{ } /* end */
10137};
10138
10139static struct hda_verb alc662_init_verbs[] = {
10140	/* ADC: mute amp left and right */
10141	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
10142	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
10143	/* Front mixer: unmute input/output amp left and right (volume = 0) */
10144
10145	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10146	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10147	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
10148	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
10149	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
10150
10151	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10152	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10153	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10154	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10155	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10156	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10157
10158	/* Front Pin: output 0 (0x0c) */
10159	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10160	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10161
10162	/* Rear Pin: output 1 (0x0d) */
10163	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10164	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10165
10166	/* CLFE Pin: output 2 (0x0e) */
10167	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10168	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10169
10170	/* Mic (rear) pin: input vref at 80% */
10171	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
10172	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10173	/* Front Mic pin: input vref at 80% */
10174	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
10175	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10176	/* Line In pin: input */
10177	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
10178	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10179	/* Line-2 In: Headphone output (output 0 - 0x0c) */
10180	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10181	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10182	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
10183	/* CD pin widget for input */
10184	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
10185
10186	/* FIXME: use matrix-type input source selection */
10187	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
10188	/* Input mixer */
10189	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10190	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10191	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
10192	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
10193	{ }
10194};
10195
10196static struct hda_verb alc662_sue_init_verbs[] = {
10197	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
10198	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
10199        {}
10200};
10201
10202/*
10203 * generic initialization of ADC, input mixers and output mixers
10204 */
10205static struct hda_verb alc662_auto_init_verbs[] = {
10206	/*
10207	 * Unmute ADC and set the default input to mic-in
10208	 */
10209	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
10210	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10211
10212	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
10213	 * mixer widget
10214	 * Note: PASD motherboards uses the Line In 2 as the input for front
10215	 * panel mic (mic 2)
10216	 */
10217	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
10218	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10219	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10220	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
10221	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
10222	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
10223
10224	/*
10225	 * Set up output mixers (0x0c - 0x0f)
10226	 */
10227	/* set vol=0 to output mixers */
10228	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10229	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10230	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10231
10232	/* set up input amps for analog loopback */
10233	/* Amp Indices: DAC = 0, mixer = 1 */
10234	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10235	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10236	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10237	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10238	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10239	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10240
10241
10242	/* FIXME: use matrix-type input source selection */
10243	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
10244	/* Input mixer */
10245	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10246	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10247	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
10248	/*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/
10249	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
10250
10251	{ }
10252};
10253
10254/* capture mixer elements */
10255static struct snd_kcontrol_new alc662_capture_mixer[] = {
10256	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
10257	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
10258	{
10259		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10260		/* The multiple "Capture Source" controls confuse alsamixer
10261		 * So call somewhat different..
10262		 * FIXME: the controls appear in the "playback" view!
10263		 */
10264		/* .name = "Capture Source", */
10265		.name = "Input Source",
10266		.count = 1,
10267		.info = alc882_mux_enum_info,
10268		.get = alc882_mux_enum_get,
10269		.put = alc882_mux_enum_put,
10270	},
10271	{ } /* end */
10272};
10273
10274static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
10275{
10276	unsigned int present;
10277	unsigned char bits;
10278
10279	present = snd_hda_codec_read(codec, 0x14, 0,
10280				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
10281	bits = present ? 0x80 : 0;
10282	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
10283				 0x80, bits);
10284	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
10285				 0x80, bits);
10286}
10287
10288static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
10289{
10290	unsigned int present;
10291	unsigned char bits;
10292
10293 	present = snd_hda_codec_read(codec, 0x1b, 0,
10294				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
10295	bits = present ? 0x80 : 0;
10296	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
10297				 0x80, bits);
10298	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
10299				 0x80, bits);
10300	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
10301				 0x80, bits);
10302	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
10303				 0x80, bits);
10304}
10305
10306static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
10307					   unsigned int res)
10308{
10309	if ((res >> 26) == ALC880_HP_EVENT)
10310		alc662_lenovo_101e_all_automute(codec);
10311	if ((res >> 26) == ALC880_FRONT_EVENT)
10312		alc662_lenovo_101e_ispeaker_automute(codec);
10313}
10314
10315
10316/* pcm configuration: identiacal with ALC880 */
10317#define alc662_pcm_analog_playback	alc880_pcm_analog_playback
10318#define alc662_pcm_analog_capture	alc880_pcm_analog_capture
10319#define alc662_pcm_digital_playback	alc880_pcm_digital_playback
10320#define alc662_pcm_digital_capture	alc880_pcm_digital_capture
10321
10322/*
10323 * configuration and preset
10324 */
10325static const char *alc662_models[ALC662_MODEL_LAST] = {
10326	[ALC662_3ST_2ch_DIG]	= "3stack-dig",
10327	[ALC662_3ST_6ch_DIG]	= "3stack-6ch-dig",
10328	[ALC662_3ST_6ch]	= "3stack-6ch",
10329	[ALC662_5ST_DIG]	= "6stack-dig",
10330	[ALC662_LENOVO_101E]	= "lenovo-101e",
10331	[ALC662_AUTO]		= "auto",
10332};
10333
10334static struct snd_pci_quirk alc662_cfg_tbl[] = {
10335	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
10336	{}
10337};
10338
10339static struct alc_config_preset alc662_presets[] = {
10340	[ALC662_3ST_2ch_DIG] = {
10341		.mixers = { alc662_3ST_2ch_mixer },
10342		.init_verbs = { alc662_init_verbs },
10343		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
10344		.dac_nids = alc662_dac_nids,
10345		.dig_out_nid = ALC662_DIGOUT_NID,
10346		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
10347		.adc_nids = alc662_adc_nids,
10348		.dig_in_nid = ALC662_DIGIN_NID,
10349		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
10350		.channel_mode = alc662_3ST_2ch_modes,
10351		.input_mux = &alc662_capture_source,
10352	},
10353	[ALC662_3ST_6ch_DIG] = {
10354		.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
10355		.init_verbs = { alc662_init_verbs },
10356		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
10357		.dac_nids = alc662_dac_nids,
10358		.dig_out_nid = ALC662_DIGOUT_NID,
10359		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
10360		.adc_nids = alc662_adc_nids,
10361		.dig_in_nid = ALC662_DIGIN_NID,
10362		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
10363		.channel_mode = alc662_3ST_6ch_modes,
10364		.need_dac_fix = 1,
10365		.input_mux = &alc662_capture_source,
10366	},
10367	[ALC662_3ST_6ch] = {
10368		.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
10369		.init_verbs = { alc662_init_verbs },
10370		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
10371		.dac_nids = alc662_dac_nids,
10372		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
10373		.adc_nids = alc662_adc_nids,
10374		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
10375		.channel_mode = alc662_3ST_6ch_modes,
10376		.need_dac_fix = 1,
10377		.input_mux = &alc662_capture_source,
10378	},
10379	[ALC662_5ST_DIG] = {
10380		.mixers = { alc662_base_mixer, alc662_chmode_mixer },
10381		.init_verbs = { alc662_init_verbs },
10382		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
10383		.dac_nids = alc662_dac_nids,
10384		.dig_out_nid = ALC662_DIGOUT_NID,
10385		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
10386		.adc_nids = alc662_adc_nids,
10387		.dig_in_nid = ALC662_DIGIN_NID,
10388		.num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
10389		.channel_mode = alc662_5stack_modes,
10390		.input_mux = &alc662_capture_source,
10391	},
10392	[ALC662_LENOVO_101E] = {
10393		.mixers = { alc662_lenovo_101e_mixer },
10394		.init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
10395		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
10396		.dac_nids = alc662_dac_nids,
10397		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
10398		.adc_nids = alc662_adc_nids,
10399		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
10400		.channel_mode = alc662_3ST_2ch_modes,
10401		.input_mux = &alc662_lenovo_101e_capture_source,
10402		.unsol_event = alc662_lenovo_101e_unsol_event,
10403		.init_hook = alc662_lenovo_101e_all_automute,
10404	},
10405
10406};
10407
10408
10409/*
10410 * BIOS auto configuration
10411 */
10412
10413/* add playback controls from the parsed DAC table */
10414static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
10415					     const struct auto_pin_cfg *cfg)
10416{
10417	char name[32];
10418	static const char *chname[4] = {
10419		"Front", "Surround", NULL /*CLFE*/, "Side"
10420	};
10421	hda_nid_t nid;
10422	int i, err;
10423
10424	for (i = 0; i < cfg->line_outs; i++) {
10425		if (!spec->multiout.dac_nids[i])
10426			continue;
10427		nid = alc880_idx_to_dac(i);
10428		if (i == 2) {
10429			/* Center/LFE */
10430			err = add_control(spec, ALC_CTL_WIDGET_VOL,
10431					  "Center Playback Volume",
10432					  HDA_COMPOSE_AMP_VAL(nid, 1, 0,
10433							      HDA_OUTPUT));
10434			if (err < 0)
10435				return err;
10436			err = add_control(spec, ALC_CTL_WIDGET_VOL,
10437					  "LFE Playback Volume",
10438					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
10439							      HDA_OUTPUT));
10440			if (err < 0)
10441				return err;
10442			err = add_control(spec, ALC_CTL_BIND_MUTE,
10443					  "Center Playback Switch",
10444					  HDA_COMPOSE_AMP_VAL(nid, 1, 2,
10445							      HDA_INPUT));
10446			if (err < 0)
10447				return err;
10448			err = add_control(spec, ALC_CTL_BIND_MUTE,
10449					  "LFE Playback Switch",
10450					  HDA_COMPOSE_AMP_VAL(nid, 2, 2,
10451							      HDA_INPUT));
10452			if (err < 0)
10453				return err;
10454		} else {
10455			sprintf(name, "%s Playback Volume", chname[i]);
10456			err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
10457					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
10458							      HDA_OUTPUT));
10459			if (err < 0)
10460				return err;
10461			sprintf(name, "%s Playback Switch", chname[i]);
10462			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
10463					  HDA_COMPOSE_AMP_VAL(nid, 3, 2,
10464							      HDA_INPUT));
10465			if (err < 0)
10466				return err;
10467		}
10468	}
10469	return 0;
10470}
10471
10472/* add playback controls for speaker and HP outputs */
10473static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
10474					const char *pfx)
10475{
10476	hda_nid_t nid;
10477	int err;
10478	char name[32];
10479
10480	if (!pin)
10481		return 0;
10482
10483	if (alc880_is_fixed_pin(pin)) {
10484		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
10485                /* printk("DAC nid=%x\n",nid); */
10486		/* specify the DAC as the extra output */
10487		if (!spec->multiout.hp_nid)
10488			spec->multiout.hp_nid = nid;
10489		else
10490			spec->multiout.extra_out_nid[0] = nid;
10491		/* control HP volume/switch on the output mixer amp */
10492		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
10493		sprintf(name, "%s Playback Volume", pfx);
10494		err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
10495				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
10496		if (err < 0)
10497			return err;
10498		sprintf(name, "%s Playback Switch", pfx);
10499		err = add_control(spec, ALC_CTL_BIND_MUTE, name,
10500				  HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
10501		if (err < 0)
10502			return err;
10503	} else if (alc880_is_multi_pin(pin)) {
10504		/* set manual connection */
10505		/* we have only a switch on HP-out PIN */
10506		sprintf(name, "%s Playback Switch", pfx);
10507		err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
10508				  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
10509		if (err < 0)
10510			return err;
10511	}
10512	return 0;
10513}
10514
10515/* create playback/capture controls for input pins */
10516static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec,
10517						const struct auto_pin_cfg *cfg)
10518{
10519	struct hda_input_mux *imux = &spec->private_imux;
10520	int i, err, idx;
10521
10522	for (i = 0; i < AUTO_PIN_LAST; i++) {
10523		if (alc880_is_input_pin(cfg->input_pins[i])) {
10524			idx = alc880_input_pin_idx(cfg->input_pins[i]);
10525			err = new_analog_input(spec, cfg->input_pins[i],
10526					       auto_pin_cfg_labels[i],
10527					       idx, 0x0b);
10528			if (err < 0)
10529				return err;
10530			imux->items[imux->num_items].label =
10531				auto_pin_cfg_labels[i];
10532			imux->items[imux->num_items].index =
10533				alc880_input_pin_idx(cfg->input_pins[i]);
10534			imux->num_items++;
10535		}
10536	}
10537	return 0;
10538}
10539
10540static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
10541					      hda_nid_t nid, int pin_type,
10542					      int dac_idx)
10543{
10544	/* set as output */
10545	snd_hda_codec_write(codec, nid, 0,
10546			    AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
10547	snd_hda_codec_write(codec, nid, 0,
10548			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
10549	/* need the manual connection? */
10550	if (alc880_is_multi_pin(nid)) {
10551		struct alc_spec *spec = codec->spec;
10552		int idx = alc880_multi_pin_idx(nid);
10553		snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
10554				    AC_VERB_SET_CONNECT_SEL,
10555				    alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
10556	}
10557}
10558
10559static void alc662_auto_init_multi_out(struct hda_codec *codec)
10560{
10561	struct alc_spec *spec = codec->spec;
10562	int i;
10563
10564	for (i = 0; i <= HDA_SIDE; i++) {
10565		hda_nid_t nid = spec->autocfg.line_out_pins[i];
10566		int pin_type = get_pin_type(spec->autocfg.line_out_type);
10567		if (nid)
10568			alc662_auto_set_output_and_unmute(codec, nid, pin_type,
10569							  i);
10570	}
10571}
10572
10573static void alc662_auto_init_hp_out(struct hda_codec *codec)
10574{
10575	struct alc_spec *spec = codec->spec;
10576	hda_nid_t pin;
10577
10578	pin = spec->autocfg.hp_pins[0];
10579	if (pin) /* connect to front */
10580		/* use dac 0 */
10581		alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
10582}
10583
10584#define alc662_is_input_pin(nid)	alc880_is_input_pin(nid)
10585#define ALC662_PIN_CD_NID		ALC880_PIN_CD_NID
10586
10587static void alc662_auto_init_analog_input(struct hda_codec *codec)
10588{
10589	struct alc_spec *spec = codec->spec;
10590	int i;
10591
10592	for (i = 0; i < AUTO_PIN_LAST; i++) {
10593		hda_nid_t nid = spec->autocfg.input_pins[i];
10594		if (alc662_is_input_pin(nid)) {
10595			snd_hda_codec_write(codec, nid, 0,
10596					    AC_VERB_SET_PIN_WIDGET_CONTROL,
10597					    (i <= AUTO_PIN_FRONT_MIC ?
10598					     PIN_VREF80 : PIN_IN));
10599			if (nid != ALC662_PIN_CD_NID)
10600				snd_hda_codec_write(codec, nid, 0,
10601						    AC_VERB_SET_AMP_GAIN_MUTE,
10602						    AMP_OUT_MUTE);
10603		}
10604	}
10605}
10606
10607static int alc662_parse_auto_config(struct hda_codec *codec)
10608{
10609	struct alc_spec *spec = codec->spec;
10610	int err;
10611	static hda_nid_t alc662_ignore[] = { 0x1d, 0 };
10612
10613	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
10614					   alc662_ignore);
10615	if (err < 0)
10616		return err;
10617	if (!spec->autocfg.line_outs)
10618		return 0; /* can't find valid BIOS pin config */
10619
10620	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
10621	if (err < 0)
10622		return err;
10623	err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg);
10624	if (err < 0)
10625		return err;
10626	err = alc662_auto_create_extra_out(spec,
10627					   spec->autocfg.speaker_pins[0],
10628					   "Speaker");
10629	if (err < 0)
10630		return err;
10631	err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
10632					   "Headphone");
10633	if (err < 0)
10634		return err;
10635	err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg);
10636	if (err < 0)
10637		return err;
10638
10639	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
10640
10641	if (spec->autocfg.dig_out_pin)
10642		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
10643
10644	if (spec->kctl_alloc)
10645		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
10646
10647	spec->num_mux_defs = 1;
10648	spec->input_mux = &spec->private_imux;
10649
10650	if (err < 0)
10651		return err;
10652	else if (err > 0)
10653		/* hack - override the init verbs */
10654		spec->init_verbs[0] = alc662_auto_init_verbs;
10655	spec->mixers[spec->num_mixers] = alc662_capture_mixer;
10656	spec->num_mixers++;
10657	return err;
10658}
10659
10660/* additional initialization for auto-configuration model */
10661static void alc662_auto_init(struct hda_codec *codec)
10662{
10663	alc662_auto_init_multi_out(codec);
10664	alc662_auto_init_hp_out(codec);
10665	alc662_auto_init_analog_input(codec);
10666}
10667
10668static int patch_alc662(struct hda_codec *codec)
10669{
10670	struct alc_spec *spec;
10671	int err, board_config;
10672
10673	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
10674	if (!spec)
10675		return -ENOMEM;
10676
10677	codec->spec = spec;
10678
10679	board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
10680						  alc662_models,
10681			  	                  alc662_cfg_tbl);
10682	if (board_config < 0) {
10683		printk(KERN_INFO "hda_codec: Unknown model for ALC662, "
10684		       "trying auto-probe from BIOS...\n");
10685		board_config = ALC662_AUTO;
10686	}
10687
10688	if (board_config == ALC662_AUTO) {
10689		/* automatic parse from the BIOS config */
10690		err = alc662_parse_auto_config(codec);
10691		if (err < 0) {
10692			alc_free(codec);
10693			return err;
10694		} else if (err) {
10695			printk(KERN_INFO
10696			       "hda_codec: Cannot set up configuration "
10697			       "from BIOS.  Using base mode...\n");
10698			board_config = ALC662_3ST_2ch_DIG;
10699		}
10700	}
10701
10702	if (board_config != ALC662_AUTO)
10703		setup_preset(spec, &alc662_presets[board_config]);
10704
10705	spec->stream_name_analog = "ALC662 Analog";
10706	spec->stream_analog_playback = &alc662_pcm_analog_playback;
10707	spec->stream_analog_capture = &alc662_pcm_analog_capture;
10708
10709	spec->stream_name_digital = "ALC662 Digital";
10710	spec->stream_digital_playback = &alc662_pcm_digital_playback;
10711	spec->stream_digital_capture = &alc662_pcm_digital_capture;
10712
10713	if (!spec->adc_nids && spec->input_mux) {
10714		spec->adc_nids = alc662_adc_nids;
10715		spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
10716	}
10717
10718	codec->patch_ops = alc_patch_ops;
10719	if (board_config == ALC662_AUTO)
10720		spec->init_hook = alc662_auto_init;
10721
10722	return 0;
10723}
10724
10725/*
10726 * patch entries
10727 */
10728struct hda_codec_preset snd_hda_preset_realtek[] = {
10729	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
10730	{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
10731	{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
10732	  .patch = patch_alc861 },
10733	{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
10734	{ .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
10735	{ .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
10736	{ .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
10737	  .patch = patch_alc883 },
10738	{ .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
10739	  .patch = patch_alc662 },
10740	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
10741	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
10742	{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
10743	{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
10744	{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
10745	{} /* terminator */
10746};
10747