patch_realtek.c revision dc041e0b1fc918562aa3803cda166fee219a34d2
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_UNIWILL_DIG,
56	ALC880_UNIWILL,
57	ALC880_UNIWILL_P53,
58	ALC880_CLEVO,
59	ALC880_TCL_S700,
60	ALC880_LG,
61	ALC880_LG_LW,
62#ifdef CONFIG_SND_DEBUG
63	ALC880_TEST,
64#endif
65	ALC880_AUTO,
66	ALC880_MODEL_LAST /* last tag */
67};
68
69/* ALC260 models */
70enum {
71	ALC260_BASIC,
72	ALC260_HP,
73	ALC260_HP_3013,
74	ALC260_FUJITSU_S702X,
75	ALC260_ACER,
76#ifdef CONFIG_SND_DEBUG
77	ALC260_TEST,
78#endif
79	ALC260_AUTO,
80	ALC260_MODEL_LAST /* last tag */
81};
82
83/* ALC262 models */
84enum {
85	ALC262_BASIC,
86	ALC262_HIPPO,
87	ALC262_HIPPO_1,
88	ALC262_FUJITSU,
89	ALC262_HP_BPC,
90	ALC262_BENQ_ED8,
91	ALC262_AUTO,
92	ALC262_MODEL_LAST /* last tag */
93};
94
95/* ALC861 models */
96enum {
97	ALC861_3ST,
98	ALC660_3ST,
99	ALC861_3ST_DIG,
100	ALC861_6ST_DIG,
101	ALC861_UNIWILL_M31,
102	ALC861_TOSHIBA,
103	ALC861_ASUS,
104	ALC861_ASUS_LAPTOP,
105	ALC861_AUTO,
106	ALC861_MODEL_LAST,
107};
108
109/* ALC882 models */
110enum {
111	ALC882_3ST_DIG,
112	ALC882_6ST_DIG,
113	ALC882_ARIMA,
114	ALC882_AUTO,
115	ALC885_MACPRO,
116	ALC882_MODEL_LAST,
117};
118
119/* ALC883 models */
120enum {
121	ALC883_3ST_2ch_DIG,
122	ALC883_3ST_6ch_DIG,
123	ALC883_3ST_6ch,
124	ALC883_6ST_DIG,
125	ALC883_TARGA_DIG,
126	ALC883_TARGA_2ch_DIG,
127	ALC888_DEMO_BOARD,
128	ALC883_ACER,
129	ALC883_MEDION,
130	ALC883_LAPTOP_EAPD,
131	ALC883_AUTO,
132	ALC883_MODEL_LAST,
133};
134
135/* for GPIO Poll */
136#define GPIO_MASK	0x03
137
138struct alc_spec {
139	/* codec parameterization */
140	struct snd_kcontrol_new *mixers[5];	/* mixer arrays */
141	unsigned int num_mixers;
142
143	const struct hda_verb *init_verbs[5];	/* initialization verbs
144						 * don't forget NULL
145						 * termination!
146						 */
147	unsigned int num_init_verbs;
148
149	char *stream_name_analog;	/* analog PCM stream */
150	struct hda_pcm_stream *stream_analog_playback;
151	struct hda_pcm_stream *stream_analog_capture;
152
153	char *stream_name_digital;	/* digital PCM stream */
154	struct hda_pcm_stream *stream_digital_playback;
155	struct hda_pcm_stream *stream_digital_capture;
156
157	/* playback */
158	struct hda_multi_out multiout;	/* playback set-up
159					 * max_channels, dacs must be set
160					 * dig_out_nid and hp_nid are optional
161					 */
162
163	/* capture */
164	unsigned int num_adc_nids;
165	hda_nid_t *adc_nids;
166	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
167
168	/* capture source */
169	unsigned int num_mux_defs;
170	const struct hda_input_mux *input_mux;
171	unsigned int cur_mux[3];
172
173	/* channel model */
174	const struct hda_channel_mode *channel_mode;
175	int num_channel_mode;
176	int need_dac_fix;
177
178	/* PCM information */
179	struct hda_pcm pcm_rec[3];	/* used in alc_build_pcms() */
180
181	/* dynamic controls, init_verbs and input_mux */
182	struct auto_pin_cfg autocfg;
183	unsigned int num_kctl_alloc, num_kctl_used;
184	struct snd_kcontrol_new *kctl_alloc;
185	struct hda_input_mux private_imux;
186	hda_nid_t private_dac_nids[5];
187
188	/* hooks */
189	void (*init_hook)(struct hda_codec *codec);
190	void (*unsol_event)(struct hda_codec *codec, unsigned int res);
191
192	/* for pin sensing */
193	unsigned int sense_updated: 1;
194	unsigned int jack_present: 1;
195};
196
197/*
198 * configuration template - to be copied to the spec instance
199 */
200struct alc_config_preset {
201	struct snd_kcontrol_new *mixers[5]; /* should be identical size
202					     * with spec
203					     */
204	const struct hda_verb *init_verbs[5];
205	unsigned int num_dacs;
206	hda_nid_t *dac_nids;
207	hda_nid_t dig_out_nid;		/* optional */
208	hda_nid_t hp_nid;		/* optional */
209	unsigned int num_adc_nids;
210	hda_nid_t *adc_nids;
211	hda_nid_t dig_in_nid;
212	unsigned int num_channel_mode;
213	const struct hda_channel_mode *channel_mode;
214	int need_dac_fix;
215	unsigned int num_mux_defs;
216	const struct hda_input_mux *input_mux;
217	void (*unsol_event)(struct hda_codec *, unsigned int);
218	void (*init_hook)(struct hda_codec *);
219};
220
221
222/*
223 * input MUX handling
224 */
225static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
226			     struct snd_ctl_elem_info *uinfo)
227{
228	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
229	struct alc_spec *spec = codec->spec;
230	unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
231	if (mux_idx >= spec->num_mux_defs)
232		mux_idx = 0;
233	return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
234}
235
236static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
237			    struct snd_ctl_elem_value *ucontrol)
238{
239	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
240	struct alc_spec *spec = codec->spec;
241	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
242
243	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
244	return 0;
245}
246
247static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
248			    struct snd_ctl_elem_value *ucontrol)
249{
250	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
251	struct alc_spec *spec = codec->spec;
252	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
253	unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
254	return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
255				     spec->adc_nids[adc_idx],
256				     &spec->cur_mux[adc_idx]);
257}
258
259
260/*
261 * channel mode setting
262 */
263static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
264			    struct snd_ctl_elem_info *uinfo)
265{
266	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
267	struct alc_spec *spec = codec->spec;
268	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
269				    spec->num_channel_mode);
270}
271
272static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
273			   struct snd_ctl_elem_value *ucontrol)
274{
275	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
276	struct alc_spec *spec = codec->spec;
277	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
278				   spec->num_channel_mode,
279				   spec->multiout.max_channels);
280}
281
282static int alc_ch_mode_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	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
288				      spec->num_channel_mode,
289				      &spec->multiout.max_channels);
290	if (err >= 0 && spec->need_dac_fix)
291		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
292	return err;
293}
294
295/*
296 * Control the mode of pin widget settings via the mixer.  "pc" is used
297 * instead of "%" to avoid consequences of accidently treating the % as
298 * being part of a format specifier.  Maximum allowed length of a value is
299 * 63 characters plus NULL terminator.
300 *
301 * Note: some retasking pin complexes seem to ignore requests for input
302 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
303 * are requested.  Therefore order this list so that this behaviour will not
304 * cause problems when mixer clients move through the enum sequentially.
305 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
306 * March 2006.
307 */
308static char *alc_pin_mode_names[] = {
309	"Mic 50pc bias", "Mic 80pc bias",
310	"Line in", "Line out", "Headphone out",
311};
312static unsigned char alc_pin_mode_values[] = {
313	PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
314};
315/* The control can present all 5 options, or it can limit the options based
316 * in the pin being assumed to be exclusively an input or an output pin.  In
317 * addition, "input" pins may or may not process the mic bias option
318 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
319 * accept requests for bias as of chip versions up to March 2006) and/or
320 * wiring in the computer.
321 */
322#define ALC_PIN_DIR_IN              0x00
323#define ALC_PIN_DIR_OUT             0x01
324#define ALC_PIN_DIR_INOUT           0x02
325#define ALC_PIN_DIR_IN_NOMICBIAS    0x03
326#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
327
328/* Info about the pin modes supported by the different pin direction modes.
329 * For each direction the minimum and maximum values are given.
330 */
331static signed char alc_pin_mode_dir_info[5][2] = {
332	{ 0, 2 },    /* ALC_PIN_DIR_IN */
333	{ 3, 4 },    /* ALC_PIN_DIR_OUT */
334	{ 0, 4 },    /* ALC_PIN_DIR_INOUT */
335	{ 2, 2 },    /* ALC_PIN_DIR_IN_NOMICBIAS */
336	{ 2, 4 },    /* ALC_PIN_DIR_INOUT_NOMICBIAS */
337};
338#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
339#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
340#define alc_pin_mode_n_items(_dir) \
341	(alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
342
343static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
344			     struct snd_ctl_elem_info *uinfo)
345{
346	unsigned int item_num = uinfo->value.enumerated.item;
347	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
348
349	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
350	uinfo->count = 1;
351	uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
352
353	if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
354		item_num = alc_pin_mode_min(dir);
355	strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
356	return 0;
357}
358
359static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
360			    struct snd_ctl_elem_value *ucontrol)
361{
362	unsigned int i;
363	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
364	hda_nid_t nid = kcontrol->private_value & 0xffff;
365	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
366	long *valp = ucontrol->value.integer.value;
367	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
368						 AC_VERB_GET_PIN_WIDGET_CONTROL,
369						 0x00);
370
371	/* Find enumerated value for current pinctl setting */
372	i = alc_pin_mode_min(dir);
373	while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir))
374		i++;
375	*valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
376	return 0;
377}
378
379static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
380			    struct snd_ctl_elem_value *ucontrol)
381{
382	signed int change;
383	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
384	hda_nid_t nid = kcontrol->private_value & 0xffff;
385	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
386	long val = *ucontrol->value.integer.value;
387	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
388						 AC_VERB_GET_PIN_WIDGET_CONTROL,
389						 0x00);
390
391	if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
392		val = alc_pin_mode_min(dir);
393
394	change = pinctl != alc_pin_mode_values[val];
395	if (change) {
396		/* Set pin mode to that requested */
397		snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
398				    alc_pin_mode_values[val]);
399
400		/* Also enable the retasking pin's input/output as required
401		 * for the requested pin mode.  Enum values of 2 or less are
402		 * input modes.
403		 *
404		 * Dynamically switching the input/output buffers probably
405		 * reduces noise slightly (particularly on input) so we'll
406		 * do it.  However, having both input and output buffers
407		 * enabled simultaneously doesn't seem to be problematic if
408		 * this turns out to be necessary in the future.
409		 */
410		if (val <= 2) {
411			snd_hda_codec_write(codec, nid, 0,
412					    AC_VERB_SET_AMP_GAIN_MUTE,
413					    AMP_OUT_MUTE);
414			snd_hda_codec_write(codec, nid, 0,
415					    AC_VERB_SET_AMP_GAIN_MUTE,
416					    AMP_IN_UNMUTE(0));
417		} else {
418			snd_hda_codec_write(codec, nid, 0,
419					    AC_VERB_SET_AMP_GAIN_MUTE,
420					    AMP_IN_MUTE(0));
421			snd_hda_codec_write(codec, nid, 0,
422					    AC_VERB_SET_AMP_GAIN_MUTE,
423					    AMP_OUT_UNMUTE);
424		}
425	}
426	return change;
427}
428
429#define ALC_PIN_MODE(xname, nid, dir) \
430	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
431	  .info = alc_pin_mode_info, \
432	  .get = alc_pin_mode_get, \
433	  .put = alc_pin_mode_put, \
434	  .private_value = nid | (dir<<16) }
435
436/* A switch control for ALC260 GPIO pins.  Multiple GPIOs can be ganged
437 * together using a mask with more than one bit set.  This control is
438 * currently used only by the ALC260 test model.  At this stage they are not
439 * needed for any "production" models.
440 */
441#ifdef CONFIG_SND_DEBUG
442static int alc_gpio_data_info(struct snd_kcontrol *kcontrol,
443			      struct snd_ctl_elem_info *uinfo)
444{
445	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
446	uinfo->count = 1;
447	uinfo->value.integer.min = 0;
448	uinfo->value.integer.max = 1;
449	return 0;
450}
451static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
452			     struct snd_ctl_elem_value *ucontrol)
453{
454	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
455	hda_nid_t nid = kcontrol->private_value & 0xffff;
456	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
457	long *valp = ucontrol->value.integer.value;
458	unsigned int val = snd_hda_codec_read(codec, nid, 0,
459					      AC_VERB_GET_GPIO_DATA, 0x00);
460
461	*valp = (val & mask) != 0;
462	return 0;
463}
464static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
465			     struct snd_ctl_elem_value *ucontrol)
466{
467	signed int change;
468	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
469	hda_nid_t nid = kcontrol->private_value & 0xffff;
470	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
471	long val = *ucontrol->value.integer.value;
472	unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
473						    AC_VERB_GET_GPIO_DATA,
474						    0x00);
475
476	/* Set/unset the masked GPIO bit(s) as needed */
477	change = (val == 0 ? 0 : mask) != (gpio_data & mask);
478	if (val == 0)
479		gpio_data &= ~mask;
480	else
481		gpio_data |= mask;
482	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
483
484	return change;
485}
486#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
487	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
488	  .info = alc_gpio_data_info, \
489	  .get = alc_gpio_data_get, \
490	  .put = alc_gpio_data_put, \
491	  .private_value = nid | (mask<<16) }
492#endif   /* CONFIG_SND_DEBUG */
493
494/* A switch control to allow the enabling of the digital IO pins on the
495 * ALC260.  This is incredibly simplistic; the intention of this control is
496 * to provide something in the test model allowing digital outputs to be
497 * identified if present.  If models are found which can utilise these
498 * outputs a more complete mixer control can be devised for those models if
499 * necessary.
500 */
501#ifdef CONFIG_SND_DEBUG
502static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol,
503			       struct snd_ctl_elem_info *uinfo)
504{
505	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
506	uinfo->count = 1;
507	uinfo->value.integer.min = 0;
508	uinfo->value.integer.max = 1;
509	return 0;
510}
511static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
512			      struct snd_ctl_elem_value *ucontrol)
513{
514	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
515	hda_nid_t nid = kcontrol->private_value & 0xffff;
516	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
517	long *valp = ucontrol->value.integer.value;
518	unsigned int val = snd_hda_codec_read(codec, nid, 0,
519					      AC_VERB_GET_DIGI_CONVERT, 0x00);
520
521	*valp = (val & mask) != 0;
522	return 0;
523}
524static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
525			      struct snd_ctl_elem_value *ucontrol)
526{
527	signed int change;
528	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
529	hda_nid_t nid = kcontrol->private_value & 0xffff;
530	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
531	long val = *ucontrol->value.integer.value;
532	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
533						    AC_VERB_GET_DIGI_CONVERT,
534						    0x00);
535
536	/* Set/unset the masked control bit(s) as needed */
537	change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
538	if (val==0)
539		ctrl_data &= ~mask;
540	else
541		ctrl_data |= mask;
542	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
543			    ctrl_data);
544
545	return change;
546}
547#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
548	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
549	  .info = alc_spdif_ctrl_info, \
550	  .get = alc_spdif_ctrl_get, \
551	  .put = alc_spdif_ctrl_put, \
552	  .private_value = nid | (mask<<16) }
553#endif   /* CONFIG_SND_DEBUG */
554
555/*
556 * set up from the preset table
557 */
558static void setup_preset(struct alc_spec *spec,
559			 const struct alc_config_preset *preset)
560{
561	int i;
562
563	for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
564		spec->mixers[spec->num_mixers++] = preset->mixers[i];
565	for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
566	     i++)
567		spec->init_verbs[spec->num_init_verbs++] =
568			preset->init_verbs[i];
569
570	spec->channel_mode = preset->channel_mode;
571	spec->num_channel_mode = preset->num_channel_mode;
572	spec->need_dac_fix = preset->need_dac_fix;
573
574	spec->multiout.max_channels = spec->channel_mode[0].channels;
575
576	spec->multiout.num_dacs = preset->num_dacs;
577	spec->multiout.dac_nids = preset->dac_nids;
578	spec->multiout.dig_out_nid = preset->dig_out_nid;
579	spec->multiout.hp_nid = preset->hp_nid;
580
581	spec->num_mux_defs = preset->num_mux_defs;
582	if (! spec->num_mux_defs)
583		spec->num_mux_defs = 1;
584	spec->input_mux = preset->input_mux;
585
586	spec->num_adc_nids = preset->num_adc_nids;
587	spec->adc_nids = preset->adc_nids;
588	spec->dig_in_nid = preset->dig_in_nid;
589
590	spec->unsol_event = preset->unsol_event;
591	spec->init_hook = preset->init_hook;
592}
593
594/*
595 * ALC880 3-stack model
596 *
597 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
598 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
599 *                 F-Mic = 0x1b, HP = 0x19
600 */
601
602static hda_nid_t alc880_dac_nids[4] = {
603	/* front, rear, clfe, rear_surr */
604	0x02, 0x05, 0x04, 0x03
605};
606
607static hda_nid_t alc880_adc_nids[3] = {
608	/* ADC0-2 */
609	0x07, 0x08, 0x09,
610};
611
612/* The datasheet says the node 0x07 is connected from inputs,
613 * but it shows zero connection in the real implementation on some devices.
614 * Note: this is a 915GAV bug, fixed on 915GLV
615 */
616static hda_nid_t alc880_adc_nids_alt[2] = {
617	/* ADC1-2 */
618	0x08, 0x09,
619};
620
621#define ALC880_DIGOUT_NID	0x06
622#define ALC880_DIGIN_NID	0x0a
623
624static struct hda_input_mux alc880_capture_source = {
625	.num_items = 4,
626	.items = {
627		{ "Mic", 0x0 },
628		{ "Front Mic", 0x3 },
629		{ "Line", 0x2 },
630		{ "CD", 0x4 },
631	},
632};
633
634/* channel source setting (2/6 channel selection for 3-stack) */
635/* 2ch mode */
636static struct hda_verb alc880_threestack_ch2_init[] = {
637	/* set line-in to input, mute it */
638	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
639	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
640	/* set mic-in to input vref 80%, mute it */
641	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
642	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
643	{ } /* end */
644};
645
646/* 6ch mode */
647static struct hda_verb alc880_threestack_ch6_init[] = {
648	/* set line-in to output, unmute it */
649	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
650	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
651	/* set mic-in to output, unmute it */
652	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
653	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
654	{ } /* end */
655};
656
657static struct hda_channel_mode alc880_threestack_modes[2] = {
658	{ 2, alc880_threestack_ch2_init },
659	{ 6, alc880_threestack_ch6_init },
660};
661
662static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
663	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
664	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
665	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
666	HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
667	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
668	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
669	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
670	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
671	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
672	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
673	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
674	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
675	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
676	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
677	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
678	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
679	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
680	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
681	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
682	{
683		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
684		.name = "Channel Mode",
685		.info = alc_ch_mode_info,
686		.get = alc_ch_mode_get,
687		.put = alc_ch_mode_put,
688	},
689	{ } /* end */
690};
691
692/* capture mixer elements */
693static struct snd_kcontrol_new alc880_capture_mixer[] = {
694	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
695	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
696	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
697	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
698	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
699	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
700	{
701		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
702		/* The multiple "Capture Source" controls confuse alsamixer
703		 * So call somewhat different..
704		 * FIXME: the controls appear in the "playback" view!
705		 */
706		/* .name = "Capture Source", */
707		.name = "Input Source",
708		.count = 3,
709		.info = alc_mux_enum_info,
710		.get = alc_mux_enum_get,
711		.put = alc_mux_enum_put,
712	},
713	{ } /* end */
714};
715
716/* capture mixer elements (in case NID 0x07 not available) */
717static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {
718	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
719	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
720	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
721	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
722	{
723		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
724		/* The multiple "Capture Source" controls confuse alsamixer
725		 * So call somewhat different..
726		 * FIXME: the controls appear in the "playback" view!
727		 */
728		/* .name = "Capture Source", */
729		.name = "Input Source",
730		.count = 2,
731		.info = alc_mux_enum_info,
732		.get = alc_mux_enum_get,
733		.put = alc_mux_enum_put,
734	},
735	{ } /* end */
736};
737
738
739
740/*
741 * ALC880 5-stack model
742 *
743 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
744 *      Side = 0x02 (0xd)
745 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
746 *                 Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
747 */
748
749/* additional mixers to alc880_three_stack_mixer */
750static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
751	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
752	HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
753	{ } /* end */
754};
755
756/* channel source setting (6/8 channel selection for 5-stack) */
757/* 6ch mode */
758static struct hda_verb alc880_fivestack_ch6_init[] = {
759	/* set line-in to input, mute it */
760	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
761	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
762	{ } /* end */
763};
764
765/* 8ch mode */
766static struct hda_verb alc880_fivestack_ch8_init[] = {
767	/* set line-in to output, unmute it */
768	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
769	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
770	{ } /* end */
771};
772
773static struct hda_channel_mode alc880_fivestack_modes[2] = {
774	{ 6, alc880_fivestack_ch6_init },
775	{ 8, alc880_fivestack_ch8_init },
776};
777
778
779/*
780 * ALC880 6-stack model
781 *
782 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
783 *      Side = 0x05 (0x0f)
784 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
785 *   Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
786 */
787
788static hda_nid_t alc880_6st_dac_nids[4] = {
789	/* front, rear, clfe, rear_surr */
790	0x02, 0x03, 0x04, 0x05
791};
792
793static struct hda_input_mux alc880_6stack_capture_source = {
794	.num_items = 4,
795	.items = {
796		{ "Mic", 0x0 },
797		{ "Front Mic", 0x1 },
798		{ "Line", 0x2 },
799		{ "CD", 0x4 },
800	},
801};
802
803/* fixed 8-channels */
804static struct hda_channel_mode alc880_sixstack_modes[1] = {
805	{ 8, NULL },
806};
807
808static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
809	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
810	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
811	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
812	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
813	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
814	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
815	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
816	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
817	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
818	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
819	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
820	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
821	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
822	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
823	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
824	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
825	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
826	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
827	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
828	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
829	{
830		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
831		.name = "Channel Mode",
832		.info = alc_ch_mode_info,
833		.get = alc_ch_mode_get,
834		.put = alc_ch_mode_put,
835	},
836	{ } /* end */
837};
838
839
840/*
841 * ALC880 W810 model
842 *
843 * W810 has rear IO for:
844 * Front (DAC 02)
845 * Surround (DAC 03)
846 * Center/LFE (DAC 04)
847 * Digital out (06)
848 *
849 * The system also has a pair of internal speakers, and a headphone jack.
850 * These are both connected to Line2 on the codec, hence to DAC 02.
851 *
852 * There is a variable resistor to control the speaker or headphone
853 * volume. This is a hardware-only device without a software API.
854 *
855 * Plugging headphones in will disable the internal speakers. This is
856 * implemented in hardware, not via the driver using jack sense. In
857 * a similar fashion, plugging into the rear socket marked "front" will
858 * disable both the speakers and headphones.
859 *
860 * For input, there's a microphone jack, and an "audio in" jack.
861 * These may not do anything useful with this driver yet, because I
862 * haven't setup any initialization verbs for these yet...
863 */
864
865static hda_nid_t alc880_w810_dac_nids[3] = {
866	/* front, rear/surround, clfe */
867	0x02, 0x03, 0x04
868};
869
870/* fixed 6 channels */
871static struct hda_channel_mode alc880_w810_modes[1] = {
872	{ 6, NULL }
873};
874
875/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
876static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
877	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
878	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
879	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
880	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
881	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
882	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
883	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
884	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
885	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
886	{ } /* end */
887};
888
889
890/*
891 * Z710V model
892 *
893 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
894 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
895 *                 Line = 0x1a
896 */
897
898static hda_nid_t alc880_z71v_dac_nids[1] = {
899	0x02
900};
901#define ALC880_Z71V_HP_DAC	0x03
902
903/* fixed 2 channels */
904static struct hda_channel_mode alc880_2_jack_modes[1] = {
905	{ 2, NULL }
906};
907
908static struct snd_kcontrol_new alc880_z71v_mixer[] = {
909	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
910	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
911	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
912	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
913	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
914	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
915	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
916	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
917	{ } /* end */
918};
919
920
921/* FIXME! */
922/*
923 * ALC880 F1734 model
924 *
925 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
926 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
927 */
928
929static hda_nid_t alc880_f1734_dac_nids[1] = {
930	0x03
931};
932#define ALC880_F1734_HP_DAC	0x02
933
934static struct snd_kcontrol_new alc880_f1734_mixer[] = {
935	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
936	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
937	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
938	HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
939	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
940	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
941	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
942	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
943	{ } /* end */
944};
945
946
947/* FIXME! */
948/*
949 * ALC880 ASUS model
950 *
951 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
952 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
953 *  Mic = 0x18, Line = 0x1a
954 */
955
956#define alc880_asus_dac_nids	alc880_w810_dac_nids	/* identical with w810 */
957#define alc880_asus_modes	alc880_threestack_modes	/* 2/6 channel mode */
958
959static struct snd_kcontrol_new alc880_asus_mixer[] = {
960	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
961	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
962	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
963	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
964	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
965	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
966	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
967	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
968	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
969	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
970	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
971	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
972	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
973	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
974	{
975		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
976		.name = "Channel Mode",
977		.info = alc_ch_mode_info,
978		.get = alc_ch_mode_get,
979		.put = alc_ch_mode_put,
980	},
981	{ } /* end */
982};
983
984/* FIXME! */
985/*
986 * ALC880 ASUS W1V model
987 *
988 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
989 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
990 *  Mic = 0x18, Line = 0x1a, Line2 = 0x1b
991 */
992
993/* additional mixers to alc880_asus_mixer */
994static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
995	HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
996	HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
997	{ } /* end */
998};
999
1000/* additional mixers to alc880_asus_mixer */
1001static struct snd_kcontrol_new alc880_pcbeep_mixer[] = {
1002	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1003	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1004	{ } /* end */
1005};
1006
1007/* TCL S700 */
1008static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
1009	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1010	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1011	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
1012	HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
1013	HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
1014	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
1015	HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
1016	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
1017	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
1018	{
1019		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1020		/* The multiple "Capture Source" controls confuse alsamixer
1021		 * So call somewhat different..
1022		 * FIXME: the controls appear in the "playback" view!
1023		 */
1024		/* .name = "Capture Source", */
1025		.name = "Input Source",
1026		.count = 1,
1027		.info = alc_mux_enum_info,
1028		.get = alc_mux_enum_get,
1029		.put = alc_mux_enum_put,
1030	},
1031	{ } /* end */
1032};
1033
1034/* Uniwill */
1035static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
1036	HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1037	HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT),
1038	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1039	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
1040	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1041	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1042	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1043	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1044	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1045	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1046	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1047	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1048	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1049	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1050	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1051	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1052	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1053	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1054	{
1055		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1056		.name = "Channel Mode",
1057		.info = alc_ch_mode_info,
1058		.get = alc_ch_mode_get,
1059		.put = alc_ch_mode_put,
1060	},
1061	{ } /* end */
1062};
1063
1064static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
1065	HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1066	HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT),
1067	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1068	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
1069	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1070	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1071	{ } /* end */
1072};
1073
1074/*
1075 * build control elements
1076 */
1077static int alc_build_controls(struct hda_codec *codec)
1078{
1079	struct alc_spec *spec = codec->spec;
1080	int err;
1081	int i;
1082
1083	for (i = 0; i < spec->num_mixers; i++) {
1084		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1085		if (err < 0)
1086			return err;
1087	}
1088
1089	if (spec->multiout.dig_out_nid) {
1090		err = snd_hda_create_spdif_out_ctls(codec,
1091						    spec->multiout.dig_out_nid);
1092		if (err < 0)
1093			return err;
1094	}
1095	if (spec->dig_in_nid) {
1096		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1097		if (err < 0)
1098			return err;
1099	}
1100	return 0;
1101}
1102
1103
1104/*
1105 * initialize the codec volumes, etc
1106 */
1107
1108/*
1109 * generic initialization of ADC, input mixers and output mixers
1110 */
1111static struct hda_verb alc880_volume_init_verbs[] = {
1112	/*
1113	 * Unmute ADC0-2 and set the default input to mic-in
1114	 */
1115	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
1116	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1117	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
1118	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1119	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
1120	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1121
1122	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1123	 * mixer widget
1124	 * Note: PASD motherboards uses the Line In 2 as the input for front
1125	 * panel mic (mic 2)
1126	 */
1127	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
1128	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1129	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1130	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1131	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1132	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1133
1134	/*
1135	 * Set up output mixers (0x0c - 0x0f)
1136	 */
1137	/* set vol=0 to output mixers */
1138	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1139	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1140	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1141	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1142	/* set up input amps for analog loopback */
1143	/* Amp Indices: DAC = 0, mixer = 1 */
1144	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1145	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1146	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1147	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1148	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1149	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1150	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1151	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1152
1153	{ }
1154};
1155
1156/*
1157 * 3-stack pin configuration:
1158 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
1159 */
1160static struct hda_verb alc880_pin_3stack_init_verbs[] = {
1161	/*
1162	 * preset connection lists of input pins
1163	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
1164	 */
1165	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
1166	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1167	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
1168
1169	/*
1170	 * Set pin mode and muting
1171	 */
1172	/* set front pin widgets 0x14 for output */
1173	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1174	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1175	/* Mic1 (rear panel) pin widget for input and vref at 80% */
1176	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1177	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1178	/* Mic2 (as headphone out) for HP output */
1179	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1180	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1181	/* Line In pin widget for input */
1182	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1183	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1184	/* Line2 (as front mic) pin widget for input and vref at 80% */
1185	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1186	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1187	/* CD pin widget for input */
1188	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1189
1190	{ }
1191};
1192
1193/*
1194 * 5-stack pin configuration:
1195 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
1196 * line-in/side = 0x1a, f-mic = 0x1b
1197 */
1198static struct hda_verb alc880_pin_5stack_init_verbs[] = {
1199	/*
1200	 * preset connection lists of input pins
1201	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
1202	 */
1203	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1204	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
1205
1206	/*
1207	 * Set pin mode and muting
1208	 */
1209	/* set pin widgets 0x14-0x17 for output */
1210	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1211	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1212	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1213	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1214	/* unmute pins for output (no gain on this amp) */
1215	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1216	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1217	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1218	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1219
1220	/* Mic1 (rear panel) pin widget for input and vref at 80% */
1221	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1222	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1223	/* Mic2 (as headphone out) for HP output */
1224	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1225	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1226	/* Line In pin widget for input */
1227	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1228	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1229	/* Line2 (as front mic) pin widget for input and vref at 80% */
1230	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1231	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1232	/* CD pin widget for input */
1233	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1234
1235	{ }
1236};
1237
1238/*
1239 * W810 pin configuration:
1240 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
1241 */
1242static struct hda_verb alc880_pin_w810_init_verbs[] = {
1243	/* hphone/speaker input selector: front DAC */
1244	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
1245
1246	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1247	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1248	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1249	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1250	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1251	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1252
1253	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1254	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1255
1256	{ }
1257};
1258
1259/*
1260 * Z71V pin configuration:
1261 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
1262 */
1263static struct hda_verb alc880_pin_z71v_init_verbs[] = {
1264	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1265	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1266	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1267	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1268
1269	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1270	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1271	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1272	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1273
1274	{ }
1275};
1276
1277/*
1278 * 6-stack pin configuration:
1279 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
1280 * f-mic = 0x19, line = 0x1a, HP = 0x1b
1281 */
1282static struct hda_verb alc880_pin_6stack_init_verbs[] = {
1283	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1284
1285	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1286	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1287	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1288	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1289	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1290	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1291	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1292	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1293
1294	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1295	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1296	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1297	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1298	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1299	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1300	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1301	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1302	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1303
1304	{ }
1305};
1306
1307/*
1308 * Uniwill pin configuration:
1309 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
1310 * line = 0x1a
1311 */
1312static struct hda_verb alc880_uniwill_init_verbs[] = {
1313	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1314
1315	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1316	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1317	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1318	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1319	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1320	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1321	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1322	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1323	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1324	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1325	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1326	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1327	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1328	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1329
1330	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1331	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1332	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1333	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1334	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1335	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1336	/* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
1337	/* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
1338	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1339
1340	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
1341	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
1342
1343	{ }
1344};
1345
1346/*
1347* Uniwill P53
1348* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
1349 */
1350static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
1351	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1352
1353	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1354	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1355	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1356	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1357	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1358	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1359	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1360	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1361	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1362	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1363	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1364	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1365
1366	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1367	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1368	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1369	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1370	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1371	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1372
1373	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
1374	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
1375
1376	{ }
1377};
1378
1379/* toggle speaker-output according to the hp-jack state */
1380static void alc880_uniwill_automute(struct hda_codec *codec)
1381{
1382 	unsigned int present;
1383
1384 	present = snd_hda_codec_read(codec, 0x14, 0,
1385				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1386	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
1387				 0x80, present ? 0x80 : 0);
1388	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
1389				 0x80, present ? 0x80 : 0);
1390	snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0,
1391				 0x80, present ? 0x80 : 0);
1392	snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0,
1393				 0x80, present ? 0x80 : 0);
1394
1395	present = snd_hda_codec_read(codec, 0x18, 0,
1396				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1397	snd_hda_codec_write(codec, 0x0b, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1398			    0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
1399}
1400
1401static void alc880_uniwill_unsol_event(struct hda_codec *codec,
1402				       unsigned int res)
1403{
1404	/* Looks like the unsol event is incompatible with the standard
1405	 * definition.  4bit tag is placed at 28 bit!
1406	 */
1407	if ((res >> 28) == ALC880_HP_EVENT ||
1408	    (res >> 28) == ALC880_MIC_EVENT)
1409		alc880_uniwill_automute(codec);
1410}
1411
1412static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
1413{
1414 	unsigned int present;
1415
1416 	present = snd_hda_codec_read(codec, 0x14, 0,
1417				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1418
1419	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0,
1420				 0x80, present ? 0x80 : 0);
1421	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0,
1422				 0x80, present ? 0x80 : 0);
1423}
1424
1425static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
1426{
1427	unsigned int present;
1428
1429	present = snd_hda_codec_read(codec, 0x21, 0,
1430				     AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f;
1431
1432	snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
1433				 0x7f, present);
1434	snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
1435				 0x7f,  present);
1436
1437	snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
1438				 0x7f,  present);
1439	snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
1440				 0x7f, present);
1441
1442}
1443static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
1444					   unsigned int res)
1445{
1446	/* Looks like the unsol event is incompatible with the standard
1447	 * definition.  4bit tag is placed at 28 bit!
1448	 */
1449	if ((res >> 28) == ALC880_HP_EVENT)
1450		alc880_uniwill_p53_hp_automute(codec);
1451	if ((res >> 28) == ALC880_DCVOL_EVENT)
1452		alc880_uniwill_p53_dcvol_automute(codec);
1453}
1454
1455/* FIXME! */
1456/*
1457 * F1734 pin configuration:
1458 * HP = 0x14, speaker-out = 0x15, mic = 0x18
1459 */
1460static struct hda_verb alc880_pin_f1734_init_verbs[] = {
1461	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
1462	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
1463	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
1464	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1465
1466	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1467	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1468	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1469	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1470
1471	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1472	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1473	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1474	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1475	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1476	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1477	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1478	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1479	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1480
1481	{ }
1482};
1483
1484/* FIXME! */
1485/*
1486 * ASUS pin configuration:
1487 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
1488 */
1489static struct hda_verb alc880_pin_asus_init_verbs[] = {
1490	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
1491	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
1492	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
1493	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1494
1495	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1496	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1497	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1498	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1499	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1500	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1501	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1502	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1503
1504	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1505	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1506	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1507	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1508	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1509	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1510	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1511	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1512	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1513
1514	{ }
1515};
1516
1517/* Enable GPIO mask and set output */
1518static struct hda_verb alc880_gpio1_init_verbs[] = {
1519	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
1520	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
1521	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
1522
1523	{ }
1524};
1525
1526/* Enable GPIO mask and set output */
1527static struct hda_verb alc880_gpio2_init_verbs[] = {
1528	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
1529	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
1530	{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
1531
1532	{ }
1533};
1534
1535/* Clevo m520g init */
1536static struct hda_verb alc880_pin_clevo_init_verbs[] = {
1537	/* headphone output */
1538	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
1539	/* line-out */
1540	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1541	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1542	/* Line-in */
1543	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1544	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1545	/* CD */
1546	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1547	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1548	/* Mic1 (rear panel) */
1549	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1550	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1551	/* Mic2 (front panel) */
1552	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1553	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1554	/* headphone */
1555	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1556	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1557        /* change to EAPD mode */
1558	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1559	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
1560
1561	{ }
1562};
1563
1564static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
1565	/* change to EAPD mode */
1566	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1567	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
1568
1569	/* Headphone output */
1570	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1571	/* Front output*/
1572	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1573	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1574
1575	/* Line In pin widget for input */
1576	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1577	/* CD pin widget for input */
1578	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1579	/* Mic1 (rear panel) pin widget for input and vref at 80% */
1580	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1581
1582	/* change to EAPD mode */
1583	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1584	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
1585
1586	{ }
1587};
1588
1589/*
1590 * LG m1 express dual
1591 *
1592 * Pin assignment:
1593 *   Rear Line-In/Out (blue): 0x14
1594 *   Build-in Mic-In: 0x15
1595 *   Speaker-out: 0x17
1596 *   HP-Out (green): 0x1b
1597 *   Mic-In/Out (red): 0x19
1598 *   SPDIF-Out: 0x1e
1599 */
1600
1601/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
1602static hda_nid_t alc880_lg_dac_nids[3] = {
1603	0x05, 0x02, 0x03
1604};
1605
1606/* seems analog CD is not working */
1607static struct hda_input_mux alc880_lg_capture_source = {
1608	.num_items = 3,
1609	.items = {
1610		{ "Mic", 0x1 },
1611		{ "Line", 0x5 },
1612		{ "Internal Mic", 0x6 },
1613	},
1614};
1615
1616/* 2,4,6 channel modes */
1617static struct hda_verb alc880_lg_ch2_init[] = {
1618	/* set line-in and mic-in to input */
1619	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1620	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1621	{ }
1622};
1623
1624static struct hda_verb alc880_lg_ch4_init[] = {
1625	/* set line-in to out and mic-in to input */
1626	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
1627	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1628	{ }
1629};
1630
1631static struct hda_verb alc880_lg_ch6_init[] = {
1632	/* set line-in and mic-in to output */
1633	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
1634	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
1635	{ }
1636};
1637
1638static struct hda_channel_mode alc880_lg_ch_modes[3] = {
1639	{ 2, alc880_lg_ch2_init },
1640	{ 4, alc880_lg_ch4_init },
1641	{ 6, alc880_lg_ch6_init },
1642};
1643
1644static struct snd_kcontrol_new alc880_lg_mixer[] = {
1645	/* FIXME: it's not really "master" but front channels */
1646	HDA_CODEC_VOLUME("Master Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1647	HDA_BIND_MUTE("Master Playback Switch", 0x0f, 2, HDA_INPUT),
1648	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1649	HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
1650	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
1651	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
1652	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
1653	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
1654	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1655	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1656	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
1657	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
1658	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
1659	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
1660	{
1661		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1662		.name = "Channel Mode",
1663		.info = alc_ch_mode_info,
1664		.get = alc_ch_mode_get,
1665		.put = alc_ch_mode_put,
1666	},
1667	{ } /* end */
1668};
1669
1670static struct hda_verb alc880_lg_init_verbs[] = {
1671	/* set capture source to mic-in */
1672	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1673	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1674	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1675	/* mute all amp mixer inputs */
1676	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
1677	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
1678	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
1679	/* line-in to input */
1680	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1681	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1682	/* built-in mic */
1683	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1684	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1685	/* speaker-out */
1686	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1687	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1688	/* mic-in to input */
1689	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
1690	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1691	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1692	/* HP-out */
1693	{0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
1694	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1695	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1696	/* jack sense */
1697	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
1698	{ }
1699};
1700
1701/* toggle speaker-output according to the hp-jack state */
1702static void alc880_lg_automute(struct hda_codec *codec)
1703{
1704	unsigned int present;
1705
1706	present = snd_hda_codec_read(codec, 0x1b, 0,
1707				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1708	snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0,
1709				 0x80, present ? 0x80 : 0);
1710	snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0,
1711				 0x80, present ? 0x80 : 0);
1712}
1713
1714static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res)
1715{
1716	/* Looks like the unsol event is incompatible with the standard
1717	 * definition.  4bit tag is placed at 28 bit!
1718	 */
1719	if ((res >> 28) == 0x01)
1720		alc880_lg_automute(codec);
1721}
1722
1723/*
1724 * LG LW20
1725 *
1726 * Pin assignment:
1727 *   Speaker-out: 0x14
1728 *   Mic-In: 0x18
1729 *   Built-in Mic-In: 0x19 (?)
1730 *   HP-Out: 0x1b
1731 *   SPDIF-Out: 0x1e
1732 */
1733
1734/* seems analog CD is not working */
1735static struct hda_input_mux alc880_lg_lw_capture_source = {
1736	.num_items = 2,
1737	.items = {
1738		{ "Mic", 0x0 },
1739		{ "Internal Mic", 0x1 },
1740	},
1741};
1742
1743static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
1744	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1745	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
1746	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1747	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1748	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
1749	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
1750	{ } /* end */
1751};
1752
1753static struct hda_verb alc880_lg_lw_init_verbs[] = {
1754	/* set capture source to mic-in */
1755	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1756	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1757	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1758	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
1759	/* speaker-out */
1760	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1761	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1762	/* HP-out */
1763	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1764	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1765	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1766	/* mic-in to input */
1767	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1768	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1769	/* built-in mic */
1770	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1771	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1772	/* jack sense */
1773	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
1774	{ }
1775};
1776
1777/* toggle speaker-output according to the hp-jack state */
1778static void alc880_lg_lw_automute(struct hda_codec *codec)
1779{
1780	unsigned int present;
1781
1782	present = snd_hda_codec_read(codec, 0x1b, 0,
1783				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1784	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
1785				 0x80, present ? 0x80 : 0);
1786	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
1787				 0x80, present ? 0x80 : 0);
1788}
1789
1790static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
1791{
1792	/* Looks like the unsol event is incompatible with the standard
1793	 * definition.  4bit tag is placed at 28 bit!
1794	 */
1795	if ((res >> 28) == 0x01)
1796		alc880_lg_lw_automute(codec);
1797}
1798
1799/*
1800 * Common callbacks
1801 */
1802
1803static int alc_init(struct hda_codec *codec)
1804{
1805	struct alc_spec *spec = codec->spec;
1806	unsigned int i;
1807
1808	for (i = 0; i < spec->num_init_verbs; i++)
1809		snd_hda_sequence_write(codec, spec->init_verbs[i]);
1810
1811	if (spec->init_hook)
1812		spec->init_hook(codec);
1813
1814	return 0;
1815}
1816
1817static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
1818{
1819	struct alc_spec *spec = codec->spec;
1820
1821	if (spec->unsol_event)
1822		spec->unsol_event(codec, res);
1823}
1824
1825#ifdef CONFIG_PM
1826/*
1827 * resume
1828 */
1829static int alc_resume(struct hda_codec *codec)
1830{
1831	struct alc_spec *spec = codec->spec;
1832	int i;
1833
1834	alc_init(codec);
1835	for (i = 0; i < spec->num_mixers; i++)
1836		snd_hda_resume_ctls(codec, spec->mixers[i]);
1837	if (spec->multiout.dig_out_nid)
1838		snd_hda_resume_spdif_out(codec);
1839	if (spec->dig_in_nid)
1840		snd_hda_resume_spdif_in(codec);
1841
1842	return 0;
1843}
1844#endif
1845
1846/*
1847 * Analog playback callbacks
1848 */
1849static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
1850				    struct hda_codec *codec,
1851				    struct snd_pcm_substream *substream)
1852{
1853	struct alc_spec *spec = codec->spec;
1854	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
1855}
1856
1857static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
1858				       struct hda_codec *codec,
1859				       unsigned int stream_tag,
1860				       unsigned int format,
1861				       struct snd_pcm_substream *substream)
1862{
1863	struct alc_spec *spec = codec->spec;
1864	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
1865						stream_tag, format, substream);
1866}
1867
1868static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
1869				       struct hda_codec *codec,
1870				       struct snd_pcm_substream *substream)
1871{
1872	struct alc_spec *spec = codec->spec;
1873	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
1874}
1875
1876/*
1877 * Digital out
1878 */
1879static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
1880					struct hda_codec *codec,
1881					struct snd_pcm_substream *substream)
1882{
1883	struct alc_spec *spec = codec->spec;
1884	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
1885}
1886
1887static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
1888					 struct hda_codec *codec,
1889					 struct snd_pcm_substream *substream)
1890{
1891	struct alc_spec *spec = codec->spec;
1892	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
1893}
1894
1895/*
1896 * Analog capture
1897 */
1898static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
1899				      struct hda_codec *codec,
1900				      unsigned int stream_tag,
1901				      unsigned int format,
1902				      struct snd_pcm_substream *substream)
1903{
1904	struct alc_spec *spec = codec->spec;
1905
1906	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
1907				   stream_tag, 0, format);
1908	return 0;
1909}
1910
1911static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
1912				      struct hda_codec *codec,
1913				      struct snd_pcm_substream *substream)
1914{
1915	struct alc_spec *spec = codec->spec;
1916
1917	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
1918				   0, 0, 0);
1919	return 0;
1920}
1921
1922
1923/*
1924 */
1925static struct hda_pcm_stream alc880_pcm_analog_playback = {
1926	.substreams = 1,
1927	.channels_min = 2,
1928	.channels_max = 8,
1929	/* NID is set in alc_build_pcms */
1930	.ops = {
1931		.open = alc880_playback_pcm_open,
1932		.prepare = alc880_playback_pcm_prepare,
1933		.cleanup = alc880_playback_pcm_cleanup
1934	},
1935};
1936
1937static struct hda_pcm_stream alc880_pcm_analog_capture = {
1938	.substreams = 2,
1939	.channels_min = 2,
1940	.channels_max = 2,
1941	/* NID is set in alc_build_pcms */
1942	.ops = {
1943		.prepare = alc880_capture_pcm_prepare,
1944		.cleanup = alc880_capture_pcm_cleanup
1945	},
1946};
1947
1948static struct hda_pcm_stream alc880_pcm_digital_playback = {
1949	.substreams = 1,
1950	.channels_min = 2,
1951	.channels_max = 2,
1952	/* NID is set in alc_build_pcms */
1953	.ops = {
1954		.open = alc880_dig_playback_pcm_open,
1955		.close = alc880_dig_playback_pcm_close
1956	},
1957};
1958
1959static struct hda_pcm_stream alc880_pcm_digital_capture = {
1960	.substreams = 1,
1961	.channels_min = 2,
1962	.channels_max = 2,
1963	/* NID is set in alc_build_pcms */
1964};
1965
1966/* Used by alc_build_pcms to flag that a PCM has no playback stream */
1967static struct hda_pcm_stream alc_pcm_null_playback = {
1968	.substreams = 0,
1969	.channels_min = 0,
1970	.channels_max = 0,
1971};
1972
1973static int alc_build_pcms(struct hda_codec *codec)
1974{
1975	struct alc_spec *spec = codec->spec;
1976	struct hda_pcm *info = spec->pcm_rec;
1977	int i;
1978
1979	codec->num_pcms = 1;
1980	codec->pcm_info = info;
1981
1982	info->name = spec->stream_name_analog;
1983	if (spec->stream_analog_playback) {
1984		snd_assert(spec->multiout.dac_nids, return -EINVAL);
1985		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
1986		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
1987	}
1988	if (spec->stream_analog_capture) {
1989		snd_assert(spec->adc_nids, return -EINVAL);
1990		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
1991		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
1992	}
1993
1994	if (spec->channel_mode) {
1995		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
1996		for (i = 0; i < spec->num_channel_mode; i++) {
1997			if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
1998				info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
1999			}
2000		}
2001	}
2002
2003	/* SPDIF for stream index #1 */
2004	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
2005		codec->num_pcms = 2;
2006		info = spec->pcm_rec + 1;
2007		info->name = spec->stream_name_digital;
2008		if (spec->multiout.dig_out_nid &&
2009		    spec->stream_digital_playback) {
2010			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
2011			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2012		}
2013		if (spec->dig_in_nid &&
2014		    spec->stream_digital_capture) {
2015			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
2016			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2017		}
2018	}
2019
2020	/* If the use of more than one ADC is requested for the current
2021	 * model, configure a second analog capture-only PCM.
2022	 */
2023	/* Additional Analaog capture for index #2 */
2024	if (spec->num_adc_nids > 1 && spec->stream_analog_capture &&
2025	    spec->adc_nids) {
2026		codec->num_pcms = 3;
2027		info = spec->pcm_rec + 2;
2028		info->name = spec->stream_name_analog;
2029		/* No playback stream for second PCM */
2030		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback;
2031		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2032		if (spec->stream_analog_capture) {
2033			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
2034			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1];
2035		}
2036	}
2037
2038	return 0;
2039}
2040
2041static void alc_free(struct hda_codec *codec)
2042{
2043	struct alc_spec *spec = codec->spec;
2044	unsigned int i;
2045
2046	if (! spec)
2047		return;
2048
2049	if (spec->kctl_alloc) {
2050		for (i = 0; i < spec->num_kctl_used; i++)
2051			kfree(spec->kctl_alloc[i].name);
2052		kfree(spec->kctl_alloc);
2053	}
2054	kfree(spec);
2055}
2056
2057/*
2058 */
2059static struct hda_codec_ops alc_patch_ops = {
2060	.build_controls = alc_build_controls,
2061	.build_pcms = alc_build_pcms,
2062	.init = alc_init,
2063	.free = alc_free,
2064	.unsol_event = alc_unsol_event,
2065#ifdef CONFIG_PM
2066	.resume = alc_resume,
2067#endif
2068};
2069
2070
2071/*
2072 * Test configuration for debugging
2073 *
2074 * Almost all inputs/outputs are enabled.  I/O pins can be configured via
2075 * enum controls.
2076 */
2077#ifdef CONFIG_SND_DEBUG
2078static hda_nid_t alc880_test_dac_nids[4] = {
2079	0x02, 0x03, 0x04, 0x05
2080};
2081
2082static struct hda_input_mux alc880_test_capture_source = {
2083	.num_items = 7,
2084	.items = {
2085		{ "In-1", 0x0 },
2086		{ "In-2", 0x1 },
2087		{ "In-3", 0x2 },
2088		{ "In-4", 0x3 },
2089		{ "CD", 0x4 },
2090		{ "Front", 0x5 },
2091		{ "Surround", 0x6 },
2092	},
2093};
2094
2095static struct hda_channel_mode alc880_test_modes[4] = {
2096	{ 2, NULL },
2097	{ 4, NULL },
2098	{ 6, NULL },
2099	{ 8, NULL },
2100};
2101
2102static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
2103				 struct snd_ctl_elem_info *uinfo)
2104{
2105	static char *texts[] = {
2106		"N/A", "Line Out", "HP Out",
2107		"In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
2108	};
2109	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2110	uinfo->count = 1;
2111	uinfo->value.enumerated.items = 8;
2112	if (uinfo->value.enumerated.item >= 8)
2113		uinfo->value.enumerated.item = 7;
2114	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2115	return 0;
2116}
2117
2118static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
2119				struct snd_ctl_elem_value *ucontrol)
2120{
2121	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2122	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2123	unsigned int pin_ctl, item = 0;
2124
2125	pin_ctl = snd_hda_codec_read(codec, nid, 0,
2126				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2127	if (pin_ctl & AC_PINCTL_OUT_EN) {
2128		if (pin_ctl & AC_PINCTL_HP_EN)
2129			item = 2;
2130		else
2131			item = 1;
2132	} else if (pin_ctl & AC_PINCTL_IN_EN) {
2133		switch (pin_ctl & AC_PINCTL_VREFEN) {
2134		case AC_PINCTL_VREF_HIZ: item = 3; break;
2135		case AC_PINCTL_VREF_50:  item = 4; break;
2136		case AC_PINCTL_VREF_GRD: item = 5; break;
2137		case AC_PINCTL_VREF_80:  item = 6; break;
2138		case AC_PINCTL_VREF_100: item = 7; break;
2139		}
2140	}
2141	ucontrol->value.enumerated.item[0] = item;
2142	return 0;
2143}
2144
2145static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
2146				struct snd_ctl_elem_value *ucontrol)
2147{
2148	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2149	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2150	static unsigned int ctls[] = {
2151		0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
2152		AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
2153		AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
2154		AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
2155		AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
2156		AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
2157	};
2158	unsigned int old_ctl, new_ctl;
2159
2160	old_ctl = snd_hda_codec_read(codec, nid, 0,
2161				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2162	new_ctl = ctls[ucontrol->value.enumerated.item[0]];
2163	if (old_ctl != new_ctl) {
2164		snd_hda_codec_write(codec, nid, 0,
2165				    AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
2166		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2167				    (ucontrol->value.enumerated.item[0] >= 3 ?
2168				     0xb080 : 0xb000));
2169		return 1;
2170	}
2171	return 0;
2172}
2173
2174static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
2175				 struct snd_ctl_elem_info *uinfo)
2176{
2177	static char *texts[] = {
2178		"Front", "Surround", "CLFE", "Side"
2179	};
2180	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2181	uinfo->count = 1;
2182	uinfo->value.enumerated.items = 4;
2183	if (uinfo->value.enumerated.item >= 4)
2184		uinfo->value.enumerated.item = 3;
2185	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2186	return 0;
2187}
2188
2189static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
2190				struct snd_ctl_elem_value *ucontrol)
2191{
2192	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2193	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2194	unsigned int sel;
2195
2196	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
2197	ucontrol->value.enumerated.item[0] = sel & 3;
2198	return 0;
2199}
2200
2201static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
2202				struct snd_ctl_elem_value *ucontrol)
2203{
2204	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2205	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
2206	unsigned int sel;
2207
2208	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
2209	if (ucontrol->value.enumerated.item[0] != sel) {
2210		sel = ucontrol->value.enumerated.item[0] & 3;
2211		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
2212		return 1;
2213	}
2214	return 0;
2215}
2216
2217#define PIN_CTL_TEST(xname,nid) {			\
2218		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
2219			.name = xname,		       \
2220			.info = alc_test_pin_ctl_info, \
2221			.get = alc_test_pin_ctl_get,   \
2222			.put = alc_test_pin_ctl_put,   \
2223			.private_value = nid	       \
2224			}
2225
2226#define PIN_SRC_TEST(xname,nid) {			\
2227		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
2228			.name = xname,		       \
2229			.info = alc_test_pin_src_info, \
2230			.get = alc_test_pin_src_get,   \
2231			.put = alc_test_pin_src_put,   \
2232			.private_value = nid	       \
2233			}
2234
2235static struct snd_kcontrol_new alc880_test_mixer[] = {
2236	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2237	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2238	HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
2239	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2240	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2241	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2242	HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
2243	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
2244	PIN_CTL_TEST("Front Pin Mode", 0x14),
2245	PIN_CTL_TEST("Surround Pin Mode", 0x15),
2246	PIN_CTL_TEST("CLFE Pin Mode", 0x16),
2247	PIN_CTL_TEST("Side Pin Mode", 0x17),
2248	PIN_CTL_TEST("In-1 Pin Mode", 0x18),
2249	PIN_CTL_TEST("In-2 Pin Mode", 0x19),
2250	PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
2251	PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
2252	PIN_SRC_TEST("In-1 Pin Source", 0x18),
2253	PIN_SRC_TEST("In-2 Pin Source", 0x19),
2254	PIN_SRC_TEST("In-3 Pin Source", 0x1a),
2255	PIN_SRC_TEST("In-4 Pin Source", 0x1b),
2256	HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
2257	HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
2258	HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
2259	HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
2260	HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
2261	HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
2262	HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
2263	HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
2264	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
2265	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
2266	{
2267		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2268		.name = "Channel Mode",
2269		.info = alc_ch_mode_info,
2270		.get = alc_ch_mode_get,
2271		.put = alc_ch_mode_put,
2272	},
2273	{ } /* end */
2274};
2275
2276static struct hda_verb alc880_test_init_verbs[] = {
2277	/* Unmute inputs of 0x0c - 0x0f */
2278	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2279	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2280	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2281	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2282	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2283	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2284	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2285	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2286	/* Vol output for 0x0c-0x0f */
2287	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2288	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2289	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2290	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2291	/* Set output pins 0x14-0x17 */
2292	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2293	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2294	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2295	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2296	/* Unmute output pins 0x14-0x17 */
2297	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2298	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2299	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2300	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2301	/* Set input pins 0x18-0x1c */
2302	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2303	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2304	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2305	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2306	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2307	/* Mute input pins 0x18-0x1b */
2308	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2309	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2310	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2311	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2312	/* ADC set up */
2313	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2314	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
2315	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2316	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
2317	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2318	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
2319	/* Analog input/passthru */
2320	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2321	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2322	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2323	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2324	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2325	{ }
2326};
2327#endif
2328
2329/*
2330 */
2331
2332static const char *alc880_models[ALC880_MODEL_LAST] = {
2333	[ALC880_3ST]		= "3stack",
2334	[ALC880_TCL_S700]	= "tcl",
2335	[ALC880_3ST_DIG]	= "3stack-digout",
2336	[ALC880_CLEVO]		= "clevo",
2337	[ALC880_5ST]		= "5stack",
2338	[ALC880_5ST_DIG]	= "5stack-digout",
2339	[ALC880_W810]		= "w810",
2340	[ALC880_Z71V]		= "z71v",
2341	[ALC880_6ST]		= "6stack",
2342	[ALC880_6ST_DIG]	= "6stack-digout",
2343	[ALC880_ASUS]		= "asus",
2344	[ALC880_ASUS_W1V]	= "asus-w1v",
2345	[ALC880_ASUS_DIG]	= "asus-dig",
2346	[ALC880_ASUS_DIG2]	= "asus-dig2",
2347	[ALC880_UNIWILL_DIG]	= "uniwill",
2348	[ALC880_F1734]		= "F1734",
2349	[ALC880_LG]		= "lg",
2350	[ALC880_LG_LW]		= "lg-lw",
2351#ifdef CONFIG_SND_DEBUG
2352	[ALC880_TEST]		= "test",
2353#endif
2354	[ALC880_AUTO]		= "auto",
2355};
2356
2357static struct snd_pci_quirk alc880_cfg_tbl[] = {
2358	/* Broken BIOS configuration */
2359	SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG),
2360	SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
2361
2362	SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
2363	SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
2364	SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
2365	SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
2366	SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
2367	SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
2368	SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
2369	SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
2370	SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
2371
2372	SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
2373	SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
2374
2375	SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
2376	SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
2377	SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
2378	SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
2379	SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
2380	SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
2381	SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
2382	/* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
2383	SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
2384	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
2385	SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_5ST),
2386	SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
2387	SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
2388	SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
2389	SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS),
2390
2391	SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
2392	SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
2393	SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
2394	SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
2395	SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
2396	SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
2397	SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
2398	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
2399	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
2400	SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
2401	SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
2402	SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
2403	SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
2404	SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
2405	SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
2406	SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
2407	SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
2408	SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
2409
2410	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
2411	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
2412	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
2413	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),
2414
2415	SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
2416	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),
2417	SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
2418
2419	SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
2420	SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
2421	SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
2422	SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
2423
2424	SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
2425	SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
2426	SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
2427	SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
2428	SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
2429	SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
2430	SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
2431	SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
2432	SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
2433	SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
2434	SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST),
2435
2436	{}
2437};
2438
2439/*
2440 * ALC880 codec presets
2441 */
2442static struct alc_config_preset alc880_presets[] = {
2443	[ALC880_3ST] = {
2444		.mixers = { alc880_three_stack_mixer },
2445		.init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
2446		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2447		.dac_nids = alc880_dac_nids,
2448		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
2449		.channel_mode = alc880_threestack_modes,
2450		.need_dac_fix = 1,
2451		.input_mux = &alc880_capture_source,
2452	},
2453	[ALC880_3ST_DIG] = {
2454		.mixers = { alc880_three_stack_mixer },
2455		.init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
2456		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2457		.dac_nids = alc880_dac_nids,
2458		.dig_out_nid = ALC880_DIGOUT_NID,
2459		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
2460		.channel_mode = alc880_threestack_modes,
2461		.need_dac_fix = 1,
2462		.input_mux = &alc880_capture_source,
2463	},
2464	[ALC880_TCL_S700] = {
2465		.mixers = { alc880_tcl_s700_mixer },
2466		.init_verbs = { alc880_volume_init_verbs,
2467				alc880_pin_tcl_S700_init_verbs,
2468				alc880_gpio2_init_verbs },
2469		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2470		.dac_nids = alc880_dac_nids,
2471		.hp_nid = 0x03,
2472		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
2473		.channel_mode = alc880_2_jack_modes,
2474		.input_mux = &alc880_capture_source,
2475	},
2476	[ALC880_5ST] = {
2477		.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
2478		.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
2479		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2480		.dac_nids = alc880_dac_nids,
2481		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
2482		.channel_mode = alc880_fivestack_modes,
2483		.input_mux = &alc880_capture_source,
2484	},
2485	[ALC880_5ST_DIG] = {
2486		.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
2487		.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
2488		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2489		.dac_nids = alc880_dac_nids,
2490		.dig_out_nid = ALC880_DIGOUT_NID,
2491		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
2492		.channel_mode = alc880_fivestack_modes,
2493		.input_mux = &alc880_capture_source,
2494	},
2495	[ALC880_6ST] = {
2496		.mixers = { alc880_six_stack_mixer },
2497		.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
2498		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
2499		.dac_nids = alc880_6st_dac_nids,
2500		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
2501		.channel_mode = alc880_sixstack_modes,
2502		.input_mux = &alc880_6stack_capture_source,
2503	},
2504	[ALC880_6ST_DIG] = {
2505		.mixers = { alc880_six_stack_mixer },
2506		.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
2507		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
2508		.dac_nids = alc880_6st_dac_nids,
2509		.dig_out_nid = ALC880_DIGOUT_NID,
2510		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
2511		.channel_mode = alc880_sixstack_modes,
2512		.input_mux = &alc880_6stack_capture_source,
2513	},
2514	[ALC880_W810] = {
2515		.mixers = { alc880_w810_base_mixer },
2516		.init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs,
2517				alc880_gpio2_init_verbs },
2518		.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
2519		.dac_nids = alc880_w810_dac_nids,
2520		.dig_out_nid = ALC880_DIGOUT_NID,
2521		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
2522		.channel_mode = alc880_w810_modes,
2523		.input_mux = &alc880_capture_source,
2524	},
2525	[ALC880_Z71V] = {
2526		.mixers = { alc880_z71v_mixer },
2527		.init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs },
2528		.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
2529		.dac_nids = alc880_z71v_dac_nids,
2530		.dig_out_nid = ALC880_DIGOUT_NID,
2531		.hp_nid = 0x03,
2532		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
2533		.channel_mode = alc880_2_jack_modes,
2534		.input_mux = &alc880_capture_source,
2535	},
2536	[ALC880_F1734] = {
2537		.mixers = { alc880_f1734_mixer },
2538		.init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
2539		.num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
2540		.dac_nids = alc880_f1734_dac_nids,
2541		.hp_nid = 0x02,
2542		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
2543		.channel_mode = alc880_2_jack_modes,
2544		.input_mux = &alc880_capture_source,
2545	},
2546	[ALC880_ASUS] = {
2547		.mixers = { alc880_asus_mixer },
2548		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
2549				alc880_gpio1_init_verbs },
2550		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2551		.dac_nids = alc880_asus_dac_nids,
2552		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2553		.channel_mode = alc880_asus_modes,
2554		.need_dac_fix = 1,
2555		.input_mux = &alc880_capture_source,
2556	},
2557	[ALC880_ASUS_DIG] = {
2558		.mixers = { alc880_asus_mixer },
2559		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
2560				alc880_gpio1_init_verbs },
2561		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2562		.dac_nids = alc880_asus_dac_nids,
2563		.dig_out_nid = ALC880_DIGOUT_NID,
2564		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2565		.channel_mode = alc880_asus_modes,
2566		.need_dac_fix = 1,
2567		.input_mux = &alc880_capture_source,
2568	},
2569	[ALC880_ASUS_DIG2] = {
2570		.mixers = { alc880_asus_mixer },
2571		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
2572				alc880_gpio2_init_verbs }, /* use GPIO2 */
2573		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2574		.dac_nids = alc880_asus_dac_nids,
2575		.dig_out_nid = ALC880_DIGOUT_NID,
2576		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2577		.channel_mode = alc880_asus_modes,
2578		.need_dac_fix = 1,
2579		.input_mux = &alc880_capture_source,
2580	},
2581	[ALC880_ASUS_W1V] = {
2582		.mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
2583		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
2584				alc880_gpio1_init_verbs },
2585		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2586		.dac_nids = alc880_asus_dac_nids,
2587		.dig_out_nid = ALC880_DIGOUT_NID,
2588		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2589		.channel_mode = alc880_asus_modes,
2590		.need_dac_fix = 1,
2591		.input_mux = &alc880_capture_source,
2592	},
2593	[ALC880_UNIWILL_DIG] = {
2594		.mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
2595		.init_verbs = { alc880_volume_init_verbs,
2596				alc880_pin_asus_init_verbs },
2597		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2598		.dac_nids = alc880_asus_dac_nids,
2599		.dig_out_nid = ALC880_DIGOUT_NID,
2600		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2601		.channel_mode = alc880_asus_modes,
2602		.need_dac_fix = 1,
2603		.input_mux = &alc880_capture_source,
2604	},
2605	[ALC880_UNIWILL] = {
2606		.mixers = { alc880_uniwill_mixer },
2607		.init_verbs = { alc880_volume_init_verbs,
2608				alc880_uniwill_init_verbs },
2609		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2610		.dac_nids = alc880_asus_dac_nids,
2611		.dig_out_nid = ALC880_DIGOUT_NID,
2612		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
2613		.channel_mode = alc880_threestack_modes,
2614		.need_dac_fix = 1,
2615		.input_mux = &alc880_capture_source,
2616		.unsol_event = alc880_uniwill_unsol_event,
2617		.init_hook = alc880_uniwill_automute,
2618	},
2619	[ALC880_UNIWILL_P53] = {
2620		.mixers = { alc880_uniwill_p53_mixer },
2621		.init_verbs = { alc880_volume_init_verbs,
2622				alc880_uniwill_p53_init_verbs },
2623		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2624		.dac_nids = alc880_asus_dac_nids,
2625		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
2626		.channel_mode = alc880_w810_modes,
2627		.input_mux = &alc880_capture_source,
2628		.unsol_event = alc880_uniwill_p53_unsol_event,
2629		.init_hook = alc880_uniwill_p53_hp_automute,
2630	},
2631	[ALC880_CLEVO] = {
2632		.mixers = { alc880_three_stack_mixer },
2633		.init_verbs = { alc880_volume_init_verbs,
2634				alc880_pin_clevo_init_verbs },
2635		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
2636		.dac_nids = alc880_dac_nids,
2637		.hp_nid = 0x03,
2638		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
2639		.channel_mode = alc880_threestack_modes,
2640		.need_dac_fix = 1,
2641		.input_mux = &alc880_capture_source,
2642	},
2643	[ALC880_LG] = {
2644		.mixers = { alc880_lg_mixer },
2645		.init_verbs = { alc880_volume_init_verbs,
2646				alc880_lg_init_verbs },
2647		.num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
2648		.dac_nids = alc880_lg_dac_nids,
2649		.dig_out_nid = ALC880_DIGOUT_NID,
2650		.num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
2651		.channel_mode = alc880_lg_ch_modes,
2652		.need_dac_fix = 1,
2653		.input_mux = &alc880_lg_capture_source,
2654		.unsol_event = alc880_lg_unsol_event,
2655		.init_hook = alc880_lg_automute,
2656	},
2657	[ALC880_LG_LW] = {
2658		.mixers = { alc880_lg_lw_mixer },
2659		.init_verbs = { alc880_volume_init_verbs,
2660				alc880_lg_lw_init_verbs },
2661		.num_dacs = 1,
2662		.dac_nids = alc880_dac_nids,
2663		.dig_out_nid = ALC880_DIGOUT_NID,
2664		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
2665		.channel_mode = alc880_2_jack_modes,
2666		.input_mux = &alc880_lg_lw_capture_source,
2667		.unsol_event = alc880_lg_lw_unsol_event,
2668		.init_hook = alc880_lg_lw_automute,
2669	},
2670#ifdef CONFIG_SND_DEBUG
2671	[ALC880_TEST] = {
2672		.mixers = { alc880_test_mixer },
2673		.init_verbs = { alc880_test_init_verbs },
2674		.num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
2675		.dac_nids = alc880_test_dac_nids,
2676		.dig_out_nid = ALC880_DIGOUT_NID,
2677		.num_channel_mode = ARRAY_SIZE(alc880_test_modes),
2678		.channel_mode = alc880_test_modes,
2679		.input_mux = &alc880_test_capture_source,
2680	},
2681#endif
2682};
2683
2684/*
2685 * Automatic parse of I/O pins from the BIOS configuration
2686 */
2687
2688#define NUM_CONTROL_ALLOC	32
2689#define NUM_VERB_ALLOC		32
2690
2691enum {
2692	ALC_CTL_WIDGET_VOL,
2693	ALC_CTL_WIDGET_MUTE,
2694	ALC_CTL_BIND_MUTE,
2695};
2696static struct snd_kcontrol_new alc880_control_templates[] = {
2697	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2698	HDA_CODEC_MUTE(NULL, 0, 0, 0),
2699	HDA_BIND_MUTE(NULL, 0, 0, 0),
2700};
2701
2702/* add dynamic controls */
2703static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
2704{
2705	struct snd_kcontrol_new *knew;
2706
2707	if (spec->num_kctl_used >= spec->num_kctl_alloc) {
2708		int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
2709
2710		knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
2711		if (! knew)
2712			return -ENOMEM;
2713		if (spec->kctl_alloc) {
2714			memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
2715			kfree(spec->kctl_alloc);
2716		}
2717		spec->kctl_alloc = knew;
2718		spec->num_kctl_alloc = num;
2719	}
2720
2721	knew = &spec->kctl_alloc[spec->num_kctl_used];
2722	*knew = alc880_control_templates[type];
2723	knew->name = kstrdup(name, GFP_KERNEL);
2724	if (! knew->name)
2725		return -ENOMEM;
2726	knew->private_value = val;
2727	spec->num_kctl_used++;
2728	return 0;
2729}
2730
2731#define alc880_is_fixed_pin(nid)	((nid) >= 0x14 && (nid) <= 0x17)
2732#define alc880_fixed_pin_idx(nid)	((nid) - 0x14)
2733#define alc880_is_multi_pin(nid)	((nid) >= 0x18)
2734#define alc880_multi_pin_idx(nid)	((nid) - 0x18)
2735#define alc880_is_input_pin(nid)	((nid) >= 0x18)
2736#define alc880_input_pin_idx(nid)	((nid) - 0x18)
2737#define alc880_idx_to_dac(nid)		((nid) + 0x02)
2738#define alc880_dac_to_idx(nid)		((nid) - 0x02)
2739#define alc880_idx_to_mixer(nid)	((nid) + 0x0c)
2740#define alc880_idx_to_selector(nid)	((nid) + 0x10)
2741#define ALC880_PIN_CD_NID		0x1c
2742
2743/* fill in the dac_nids table from the parsed pin configuration */
2744static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
2745{
2746	hda_nid_t nid;
2747	int assigned[4];
2748	int i, j;
2749
2750	memset(assigned, 0, sizeof(assigned));
2751	spec->multiout.dac_nids = spec->private_dac_nids;
2752
2753	/* check the pins hardwired to audio widget */
2754	for (i = 0; i < cfg->line_outs; i++) {
2755		nid = cfg->line_out_pins[i];
2756		if (alc880_is_fixed_pin(nid)) {
2757			int idx = alc880_fixed_pin_idx(nid);
2758			spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
2759			assigned[idx] = 1;
2760		}
2761	}
2762	/* left pins can be connect to any audio widget */
2763	for (i = 0; i < cfg->line_outs; i++) {
2764		nid = cfg->line_out_pins[i];
2765		if (alc880_is_fixed_pin(nid))
2766			continue;
2767		/* search for an empty channel */
2768		for (j = 0; j < cfg->line_outs; j++) {
2769			if (! assigned[j]) {
2770				spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
2771				assigned[j] = 1;
2772				break;
2773			}
2774		}
2775	}
2776	spec->multiout.num_dacs = cfg->line_outs;
2777	return 0;
2778}
2779
2780/* add playback controls from the parsed DAC table */
2781static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
2782					     const struct auto_pin_cfg *cfg)
2783{
2784	char name[32];
2785	static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2786	hda_nid_t nid;
2787	int i, err;
2788
2789	for (i = 0; i < cfg->line_outs; i++) {
2790		if (! spec->multiout.dac_nids[i])
2791			continue;
2792		nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
2793		if (i == 2) {
2794			/* Center/LFE */
2795			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
2796					       HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
2797				return err;
2798			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
2799					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
2800				return err;
2801			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
2802					       HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
2803				return err;
2804			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
2805					       HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
2806				return err;
2807		} else {
2808			sprintf(name, "%s Playback Volume", chname[i]);
2809			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2810					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
2811				return err;
2812			sprintf(name, "%s Playback Switch", chname[i]);
2813			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
2814					       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2815				return err;
2816		}
2817	}
2818	return 0;
2819}
2820
2821/* add playback controls for speaker and HP outputs */
2822static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
2823					const char *pfx)
2824{
2825	hda_nid_t nid;
2826	int err;
2827	char name[32];
2828
2829	if (! pin)
2830		return 0;
2831
2832	if (alc880_is_fixed_pin(pin)) {
2833		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
2834		/* specify the DAC as the extra output */
2835		if (! spec->multiout.hp_nid)
2836			spec->multiout.hp_nid = nid;
2837		else
2838			spec->multiout.extra_out_nid[0] = nid;
2839		/* control HP volume/switch on the output mixer amp */
2840		nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
2841		sprintf(name, "%s Playback Volume", pfx);
2842		if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2843				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
2844			return err;
2845		sprintf(name, "%s Playback Switch", pfx);
2846		if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
2847				       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2848			return err;
2849	} else if (alc880_is_multi_pin(pin)) {
2850		/* set manual connection */
2851		/* we have only a switch on HP-out PIN */
2852		sprintf(name, "%s Playback Switch", pfx);
2853		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
2854				       HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
2855			return err;
2856	}
2857	return 0;
2858}
2859
2860/* create input playback/capture controls for the given pin */
2861static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname,
2862			    int idx, hda_nid_t mix_nid)
2863{
2864	char name[32];
2865	int err;
2866
2867	sprintf(name, "%s Playback Volume", ctlname);
2868	if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2869			       HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
2870		return err;
2871	sprintf(name, "%s Playback Switch", ctlname);
2872	if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
2873			       HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
2874		return err;
2875	return 0;
2876}
2877
2878/* create playback/capture controls for input pins */
2879static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
2880						const struct auto_pin_cfg *cfg)
2881{
2882	struct hda_input_mux *imux = &spec->private_imux;
2883	int i, err, idx;
2884
2885	for (i = 0; i < AUTO_PIN_LAST; i++) {
2886		if (alc880_is_input_pin(cfg->input_pins[i])) {
2887			idx = alc880_input_pin_idx(cfg->input_pins[i]);
2888			err = new_analog_input(spec, cfg->input_pins[i],
2889					       auto_pin_cfg_labels[i],
2890					       idx, 0x0b);
2891			if (err < 0)
2892				return err;
2893			imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2894			imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
2895			imux->num_items++;
2896		}
2897	}
2898	return 0;
2899}
2900
2901static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
2902					      hda_nid_t nid, int pin_type,
2903					      int dac_idx)
2904{
2905	/* set as output */
2906	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2907	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2908	/* need the manual connection? */
2909	if (alc880_is_multi_pin(nid)) {
2910		struct alc_spec *spec = codec->spec;
2911		int idx = alc880_multi_pin_idx(nid);
2912		snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
2913				    AC_VERB_SET_CONNECT_SEL,
2914				    alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
2915	}
2916}
2917
2918static void alc880_auto_init_multi_out(struct hda_codec *codec)
2919{
2920	struct alc_spec *spec = codec->spec;
2921	int i;
2922
2923	for (i = 0; i < spec->autocfg.line_outs; i++) {
2924		hda_nid_t nid = spec->autocfg.line_out_pins[i];
2925		alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2926	}
2927}
2928
2929static void alc880_auto_init_extra_out(struct hda_codec *codec)
2930{
2931	struct alc_spec *spec = codec->spec;
2932	hda_nid_t pin;
2933
2934	pin = spec->autocfg.speaker_pins[0];
2935	if (pin) /* connect to front */
2936		alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2937	pin = spec->autocfg.hp_pins[0];
2938	if (pin) /* connect to front */
2939		alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2940}
2941
2942static void alc880_auto_init_analog_input(struct hda_codec *codec)
2943{
2944	struct alc_spec *spec = codec->spec;
2945	int i;
2946
2947	for (i = 0; i < AUTO_PIN_LAST; i++) {
2948		hda_nid_t nid = spec->autocfg.input_pins[i];
2949		if (alc880_is_input_pin(nid)) {
2950			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2951					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2952			if (nid != ALC880_PIN_CD_NID)
2953				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2954						    AMP_OUT_MUTE);
2955		}
2956	}
2957}
2958
2959/* parse the BIOS configuration and set up the alc_spec */
2960/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2961static int alc880_parse_auto_config(struct hda_codec *codec)
2962{
2963	struct alc_spec *spec = codec->spec;
2964	int err;
2965	static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
2966
2967	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
2968						alc880_ignore)) < 0)
2969		return err;
2970	if (! spec->autocfg.line_outs)
2971		return 0; /* can't find valid BIOS pin config */
2972
2973	if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
2974	    (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2975	    (err = alc880_auto_create_extra_out(spec,
2976						spec->autocfg.speaker_pins[0],
2977						"Speaker")) < 0 ||
2978	    (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
2979						"Headphone")) < 0 ||
2980	    (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2981		return err;
2982
2983	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2984
2985	if (spec->autocfg.dig_out_pin)
2986		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
2987	if (spec->autocfg.dig_in_pin)
2988		spec->dig_in_nid = ALC880_DIGIN_NID;
2989
2990	if (spec->kctl_alloc)
2991		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2992
2993	spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
2994
2995	spec->num_mux_defs = 1;
2996	spec->input_mux = &spec->private_imux;
2997
2998	return 1;
2999}
3000
3001/* additional initialization for auto-configuration model */
3002static void alc880_auto_init(struct hda_codec *codec)
3003{
3004	alc880_auto_init_multi_out(codec);
3005	alc880_auto_init_extra_out(codec);
3006	alc880_auto_init_analog_input(codec);
3007}
3008
3009/*
3010 * OK, here we have finally the patch for ALC880
3011 */
3012
3013static int patch_alc880(struct hda_codec *codec)
3014{
3015	struct alc_spec *spec;
3016	int board_config;
3017	int err;
3018
3019	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3020	if (spec == NULL)
3021		return -ENOMEM;
3022
3023	codec->spec = spec;
3024
3025	board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
3026						  alc880_models,
3027						  alc880_cfg_tbl);
3028	if (board_config < 0) {
3029		printk(KERN_INFO "hda_codec: Unknown model for ALC880, "
3030		       "trying auto-probe from BIOS...\n");
3031		board_config = ALC880_AUTO;
3032	}
3033
3034	if (board_config == ALC880_AUTO) {
3035		/* automatic parse from the BIOS config */
3036		err = alc880_parse_auto_config(codec);
3037		if (err < 0) {
3038			alc_free(codec);
3039			return err;
3040		} else if (! err) {
3041			printk(KERN_INFO
3042			       "hda_codec: Cannot set up configuration "
3043			       "from BIOS.  Using 3-stack mode...\n");
3044			board_config = ALC880_3ST;
3045		}
3046	}
3047
3048	if (board_config != ALC880_AUTO)
3049		setup_preset(spec, &alc880_presets[board_config]);
3050
3051	spec->stream_name_analog = "ALC880 Analog";
3052	spec->stream_analog_playback = &alc880_pcm_analog_playback;
3053	spec->stream_analog_capture = &alc880_pcm_analog_capture;
3054
3055	spec->stream_name_digital = "ALC880 Digital";
3056	spec->stream_digital_playback = &alc880_pcm_digital_playback;
3057	spec->stream_digital_capture = &alc880_pcm_digital_capture;
3058
3059	if (! spec->adc_nids && spec->input_mux) {
3060		/* check whether NID 0x07 is valid */
3061		unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
3062		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3063		if (wcap != AC_WID_AUD_IN) {
3064			spec->adc_nids = alc880_adc_nids_alt;
3065			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
3066			spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
3067			spec->num_mixers++;
3068		} else {
3069			spec->adc_nids = alc880_adc_nids;
3070			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
3071			spec->mixers[spec->num_mixers] = alc880_capture_mixer;
3072			spec->num_mixers++;
3073		}
3074	}
3075
3076	codec->patch_ops = alc_patch_ops;
3077	if (board_config == ALC880_AUTO)
3078		spec->init_hook = alc880_auto_init;
3079
3080	return 0;
3081}
3082
3083
3084/*
3085 * ALC260 support
3086 */
3087
3088static hda_nid_t alc260_dac_nids[1] = {
3089	/* front */
3090	0x02,
3091};
3092
3093static hda_nid_t alc260_adc_nids[1] = {
3094	/* ADC0 */
3095	0x04,
3096};
3097
3098static hda_nid_t alc260_adc_nids_alt[1] = {
3099	/* ADC1 */
3100	0x05,
3101};
3102
3103static hda_nid_t alc260_hp_adc_nids[2] = {
3104	/* ADC1, 0 */
3105	0x05, 0x04
3106};
3107
3108/* NIDs used when simultaneous access to both ADCs makes sense.  Note that
3109 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
3110 */
3111static hda_nid_t alc260_dual_adc_nids[2] = {
3112	/* ADC0, ADC1 */
3113	0x04, 0x05
3114};
3115
3116#define ALC260_DIGOUT_NID	0x03
3117#define ALC260_DIGIN_NID	0x06
3118
3119static struct hda_input_mux alc260_capture_source = {
3120	.num_items = 4,
3121	.items = {
3122		{ "Mic", 0x0 },
3123		{ "Front Mic", 0x1 },
3124		{ "Line", 0x2 },
3125		{ "CD", 0x4 },
3126	},
3127};
3128
3129/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
3130 * headphone jack and the internal CD lines since these are the only pins at
3131 * which audio can appear.  For flexibility, also allow the option of
3132 * recording the mixer output on the second ADC (ADC0 doesn't have a
3133 * connection to the mixer output).
3134 */
3135static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
3136	{
3137		.num_items = 3,
3138		.items = {
3139			{ "Mic/Line", 0x0 },
3140			{ "CD", 0x4 },
3141			{ "Headphone", 0x2 },
3142		},
3143	},
3144	{
3145		.num_items = 4,
3146		.items = {
3147			{ "Mic/Line", 0x0 },
3148			{ "CD", 0x4 },
3149			{ "Headphone", 0x2 },
3150			{ "Mixer", 0x5 },
3151		},
3152	},
3153
3154};
3155
3156/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
3157 * the Fujitsu S702x, but jacks are marked differently.
3158 */
3159static struct hda_input_mux alc260_acer_capture_sources[2] = {
3160	{
3161		.num_items = 4,
3162		.items = {
3163			{ "Mic", 0x0 },
3164			{ "Line", 0x2 },
3165			{ "CD", 0x4 },
3166			{ "Headphone", 0x5 },
3167		},
3168	},
3169	{
3170		.num_items = 5,
3171		.items = {
3172			{ "Mic", 0x0 },
3173			{ "Line", 0x2 },
3174			{ "CD", 0x4 },
3175			{ "Headphone", 0x6 },
3176			{ "Mixer", 0x5 },
3177		},
3178	},
3179};
3180/*
3181 * This is just place-holder, so there's something for alc_build_pcms to look
3182 * at when it calculates the maximum number of channels. ALC260 has no mixer
3183 * element which allows changing the channel mode, so the verb list is
3184 * never used.
3185 */
3186static struct hda_channel_mode alc260_modes[1] = {
3187	{ 2, NULL },
3188};
3189
3190
3191/* Mixer combinations
3192 *
3193 * basic: base_output + input + pc_beep + capture
3194 * HP: base_output + input + capture_alt
3195 * HP_3013: hp_3013 + input + capture
3196 * fujitsu: fujitsu + capture
3197 * acer: acer + capture
3198 */
3199
3200static struct snd_kcontrol_new alc260_base_output_mixer[] = {
3201	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3202	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
3203	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
3204	HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
3205	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
3206	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
3207	{ } /* end */
3208};
3209
3210static struct snd_kcontrol_new alc260_input_mixer[] = {
3211	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
3212	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
3213	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
3214	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
3215	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
3216	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
3217	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
3218	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
3219	{ } /* end */
3220};
3221
3222static struct snd_kcontrol_new alc260_pc_beep_mixer[] = {
3223	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
3224	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
3225	{ } /* end */
3226};
3227
3228static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
3229	HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
3230	HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
3231	HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
3232	HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
3233	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3234	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
3235	HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
3236	HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
3237	{ } /* end */
3238};
3239
3240/* Fujitsu S702x series laptops.  ALC260 pin usage: Mic/Line jack = 0x12,
3241 * HP jack = 0x14, CD audio =  0x16, internal speaker = 0x10.
3242 */
3243static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
3244	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3245	HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
3246	ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
3247	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
3248	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
3249	HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
3250	HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
3251	ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
3252	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
3253	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
3254	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
3255	HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),
3256	{ } /* end */
3257};
3258
3259/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks.  Note that current
3260 * versions of the ALC260 don't act on requests to enable mic bias from NID
3261 * 0x0f (used to drive the headphone jack in these laptops).  The ALC260
3262 * datasheet doesn't mention this restriction.  At this stage it's not clear
3263 * whether this behaviour is intentional or is a hardware bug in chip
3264 * revisions available in early 2006.  Therefore for now allow the
3265 * "Headphone Jack Mode" control to span all choices, but if it turns out
3266 * that the lack of mic bias for this NID is intentional we could change the
3267 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
3268 *
3269 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
3270 * don't appear to make the mic bias available from the "line" jack, even
3271 * though the NID used for this jack (0x14) can supply it.  The theory is
3272 * that perhaps Acer have included blocking capacitors between the ALC260
3273 * and the output jack.  If this turns out to be the case for all such
3274 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
3275 * to ALC_PIN_DIR_INOUT_NOMICBIAS.
3276 *
3277 * The C20x Tablet series have a mono internal speaker which is controlled
3278 * via the chip's Mono sum widget and pin complex, so include the necessary
3279 * controls for such models.  On models without a "mono speaker" the control
3280 * won't do anything.
3281 */
3282static struct snd_kcontrol_new alc260_acer_mixer[] = {
3283	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3284	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
3285	ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
3286	HDA_CODEC_VOLUME_MONO("Mono Speaker Playback Volume", 0x0a, 1, 0x0,
3287			      HDA_OUTPUT),
3288	HDA_BIND_MUTE_MONO("Mono Speaker Playback Switch", 0x0a, 1, 2,
3289			   HDA_INPUT),
3290	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
3291	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
3292	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
3293	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
3294	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
3295	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
3296	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
3297	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
3298	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
3299	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
3300	{ } /* end */
3301};
3302
3303/* capture mixer elements */
3304static struct snd_kcontrol_new alc260_capture_mixer[] = {
3305	HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
3306	HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
3307	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),
3308	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),
3309	{
3310		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3311		/* The multiple "Capture Source" controls confuse alsamixer
3312		 * So call somewhat different..
3313		 * FIXME: the controls appear in the "playback" view!
3314		 */
3315		/* .name = "Capture Source", */
3316		.name = "Input Source",
3317		.count = 2,
3318		.info = alc_mux_enum_info,
3319		.get = alc_mux_enum_get,
3320		.put = alc_mux_enum_put,
3321	},
3322	{ } /* end */
3323};
3324
3325static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {
3326	HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
3327	HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
3328	{
3329		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3330		/* The multiple "Capture Source" controls confuse alsamixer
3331		 * So call somewhat different..
3332		 * FIXME: the controls appear in the "playback" view!
3333		 */
3334		/* .name = "Capture Source", */
3335		.name = "Input Source",
3336		.count = 1,
3337		.info = alc_mux_enum_info,
3338		.get = alc_mux_enum_get,
3339		.put = alc_mux_enum_put,
3340	},
3341	{ } /* end */
3342};
3343
3344/*
3345 * initialization verbs
3346 */
3347static struct hda_verb alc260_init_verbs[] = {
3348	/* Line In pin widget for input */
3349	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3350	/* CD pin widget for input */
3351	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3352	/* Mic1 (rear panel) pin widget for input and vref at 80% */
3353	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3354	/* Mic2 (front panel) pin widget for input and vref at 80% */
3355	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3356	/* LINE-2 is used for line-out in rear */
3357	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3358	/* select line-out */
3359	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
3360	/* LINE-OUT pin */
3361	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3362	/* enable HP */
3363	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3364	/* enable Mono */
3365	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3366	/* mute capture amp left and right */
3367	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3368	/* set connection select to line in (default select for this ADC) */
3369	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
3370	/* mute capture amp left and right */
3371	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3372	/* set connection select to line in (default select for this ADC) */
3373	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
3374	/* set vol=0 Line-Out mixer amp left and right */
3375	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3376	/* unmute pin widget amp left and right (no gain on this amp) */
3377	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3378	/* set vol=0 HP mixer amp left and right */
3379	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3380	/* unmute pin widget amp left and right (no gain on this amp) */
3381	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3382	/* set vol=0 Mono mixer amp left and right */
3383	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3384	/* unmute pin widget amp left and right (no gain on this amp) */
3385	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3386	/* unmute LINE-2 out pin */
3387	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3388	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
3389	/* mute CD */
3390	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3391	/* mute Line In */
3392	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3393	/* mute Mic */
3394	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3395	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
3396	/* mute Front out path */
3397	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3398	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3399	/* mute Headphone out path */
3400	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3401	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3402	/* mute Mono out path */
3403	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3404	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3405	{ }
3406};
3407
3408#if 0 /* should be identical with alc260_init_verbs? */
3409static struct hda_verb alc260_hp_init_verbs[] = {
3410	/* Headphone and output */
3411	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
3412	/* mono output */
3413	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3414	/* Mic1 (rear panel) pin widget for input and vref at 80% */
3415	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3416	/* Mic2 (front panel) pin widget for input and vref at 80% */
3417	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3418	/* Line In pin widget for input */
3419	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3420	/* Line-2 pin widget for output */
3421	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3422	/* CD pin widget for input */
3423	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3424	/* unmute amp left and right */
3425	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
3426	/* set connection select to line in (default select for this ADC) */
3427	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
3428	/* unmute Line-Out mixer amp left and right (volume = 0) */
3429	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
3430	/* mute pin widget amp left and right (no gain on this amp) */
3431	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3432	/* unmute HP mixer amp left and right (volume = 0) */
3433	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
3434	/* mute pin widget amp left and right (no gain on this amp) */
3435	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3436	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
3437	/* unmute CD */
3438	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
3439	/* unmute Line In */
3440	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
3441	/* unmute Mic */
3442	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3443	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
3444	/* Unmute Front out path */
3445	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3446	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3447	/* Unmute Headphone out path */
3448	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3449	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3450	/* Unmute Mono out path */
3451	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3452	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3453	{ }
3454};
3455#endif
3456
3457static struct hda_verb alc260_hp_3013_init_verbs[] = {
3458	/* Line out and output */
3459	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3460	/* mono output */
3461	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3462	/* Mic1 (rear panel) pin widget for input and vref at 80% */
3463	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3464	/* Mic2 (front panel) pin widget for input and vref at 80% */
3465	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3466	/* Line In pin widget for input */
3467	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3468	/* Headphone pin widget for output */
3469	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
3470	/* CD pin widget for input */
3471	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3472	/* unmute amp left and right */
3473	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
3474	/* set connection select to line in (default select for this ADC) */
3475	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
3476	/* unmute Line-Out mixer amp left and right (volume = 0) */
3477	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
3478	/* mute pin widget amp left and right (no gain on this amp) */
3479	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3480	/* unmute HP mixer amp left and right (volume = 0) */
3481	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
3482	/* mute pin widget amp left and right (no gain on this amp) */
3483	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3484	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
3485	/* unmute CD */
3486	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
3487	/* unmute Line In */
3488	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
3489	/* unmute Mic */
3490	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3491	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
3492	/* Unmute Front out path */
3493	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3494	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3495	/* Unmute Headphone out path */
3496	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3497	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3498	/* Unmute Mono out path */
3499	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3500	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3501	{ }
3502};
3503
3504/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
3505 * laptops.  ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
3506 * audio = 0x16, internal speaker = 0x10.
3507 */
3508static struct hda_verb alc260_fujitsu_init_verbs[] = {
3509	/* Disable all GPIOs */
3510	{0x01, AC_VERB_SET_GPIO_MASK, 0},
3511	/* Internal speaker is connected to headphone pin */
3512	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3513	/* Headphone/Line-out jack connects to Line1 pin; make it an output */
3514	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3515	/* Mic/Line-in jack is connected to mic1 pin, so make it an input */
3516	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3517	/* Ensure all other unused pins are disabled and muted. */
3518	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3519	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3520	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3521	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3522	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3523	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3524	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3525	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3526
3527	/* Disable digital (SPDIF) pins */
3528	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
3529	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
3530
3531	/* Ensure Line1 pin widget takes its input from the OUT1 sum bus
3532	 * when acting as an output.
3533	 */
3534	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
3535
3536	/* Start with output sum widgets muted and their output gains at min */
3537	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3538	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3539	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3540	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3541	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3542	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3543	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3544	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3545	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3546
3547	/* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
3548	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3549	/* Unmute Line1 pin widget output buffer since it starts as an output.
3550	 * If the pin mode is changed by the user the pin mode control will
3551	 * take care of enabling the pin's input/output buffers as needed.
3552	 * Therefore there's no need to enable the input buffer at this
3553	 * stage.
3554	 */
3555	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3556	/* Unmute input buffer of pin widget used for Line-in (no equiv
3557	 * mixer ctrl)
3558	 */
3559	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3560
3561	/* Mute capture amp left and right */
3562	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3563	/* Set ADC connection select to match default mixer setting - line
3564	 * in (on mic1 pin)
3565	 */
3566	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
3567
3568	/* Do the same for the second ADC: mute capture input amp and
3569	 * set ADC connection to line in (on mic1 pin)
3570	 */
3571	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3572	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
3573
3574	/* Mute all inputs to mixer widget (even unconnected ones) */
3575	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
3576	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
3577	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
3578	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
3579	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
3580	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
3581	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
3582	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
3583
3584	{ }
3585};
3586
3587/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
3588 * similar laptops (adapted from Fujitsu init verbs).
3589 */
3590static struct hda_verb alc260_acer_init_verbs[] = {
3591	/* On TravelMate laptops, GPIO 0 enables the internal speaker and
3592	 * the headphone jack.  Turn this on and rely on the standard mute
3593	 * methods whenever the user wants to turn these outputs off.
3594	 */
3595	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
3596	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
3597	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
3598	/* Internal speaker/Headphone jack is connected to Line-out pin */
3599	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3600	/* Internal microphone/Mic jack is connected to Mic1 pin */
3601	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
3602	/* Line In jack is connected to Line1 pin */
3603	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3604	/* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
3605	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3606	/* Ensure all other unused pins are disabled and muted. */
3607	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3608	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3609	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3610	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3611	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3612	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3613	/* Disable digital (SPDIF) pins */
3614	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
3615	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
3616
3617	/* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
3618	 * bus when acting as outputs.
3619	 */
3620	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
3621	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
3622
3623	/* Start with output sum widgets muted and their output gains at min */
3624	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3625	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3626	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3627	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3628	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3629	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3630	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3631	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3632	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3633
3634	/* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */
3635	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3636	/* Unmute mono pin widget amp output (no equiv mixer ctrl) */
3637	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3638	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
3639	 * inputs. If the pin mode is changed by the user the pin mode control
3640	 * will take care of enabling the pin's input/output buffers as needed.
3641	 * Therefore there's no need to enable the input buffer at this
3642	 * stage.
3643	 */
3644	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3645	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3646
3647	/* Mute capture amp left and right */
3648	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3649	/* Set ADC connection select to match default mixer setting - mic
3650	 * (on mic1 pin)
3651	 */
3652	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
3653
3654	/* Do similar with the second ADC: mute capture input amp and
3655	 * set ADC connection to mic to match ALSA's default state.
3656	 */
3657	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3658	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
3659
3660	/* Mute all inputs to mixer widget (even unconnected ones) */
3661	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
3662	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
3663	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
3664	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
3665	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
3666	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
3667	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
3668	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
3669
3670	{ }
3671};
3672
3673/* Test configuration for debugging, modelled after the ALC880 test
3674 * configuration.
3675 */
3676#ifdef CONFIG_SND_DEBUG
3677static hda_nid_t alc260_test_dac_nids[1] = {
3678	0x02,
3679};
3680static hda_nid_t alc260_test_adc_nids[2] = {
3681	0x04, 0x05,
3682};
3683/* For testing the ALC260, each input MUX needs its own definition since
3684 * the signal assignments are different.  This assumes that the first ADC
3685 * is NID 0x04.
3686 */
3687static struct hda_input_mux alc260_test_capture_sources[2] = {
3688	{
3689		.num_items = 7,
3690		.items = {
3691			{ "MIC1 pin", 0x0 },
3692			{ "MIC2 pin", 0x1 },
3693			{ "LINE1 pin", 0x2 },
3694			{ "LINE2 pin", 0x3 },
3695			{ "CD pin", 0x4 },
3696			{ "LINE-OUT pin", 0x5 },
3697			{ "HP-OUT pin", 0x6 },
3698		},
3699        },
3700	{
3701		.num_items = 8,
3702		.items = {
3703			{ "MIC1 pin", 0x0 },
3704			{ "MIC2 pin", 0x1 },
3705			{ "LINE1 pin", 0x2 },
3706			{ "LINE2 pin", 0x3 },
3707			{ "CD pin", 0x4 },
3708			{ "Mixer", 0x5 },
3709			{ "LINE-OUT pin", 0x6 },
3710			{ "HP-OUT pin", 0x7 },
3711		},
3712        },
3713};
3714static struct snd_kcontrol_new alc260_test_mixer[] = {
3715	/* Output driver widgets */
3716	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
3717	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
3718	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
3719	HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
3720	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3721	HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
3722
3723	/* Modes for retasking pin widgets
3724	 * Note: the ALC260 doesn't seem to act on requests to enable mic
3725         * bias from NIDs 0x0f and 0x10.  The ALC260 datasheet doesn't
3726         * mention this restriction.  At this stage it's not clear whether
3727         * this behaviour is intentional or is a hardware bug in chip
3728         * revisions available at least up until early 2006.  Therefore for
3729         * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
3730         * choices, but if it turns out that the lack of mic bias for these
3731         * NIDs is intentional we could change their modes from
3732         * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
3733	 */
3734	ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
3735	ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
3736	ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
3737	ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
3738	ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
3739	ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
3740
3741	/* Loopback mixer controls */
3742	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
3743	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
3744	HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
3745	HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
3746	HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
3747	HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
3748	HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
3749	HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
3750	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
3751	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
3752	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
3753	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
3754	HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
3755	HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
3756	HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
3757	HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
3758
3759	/* Controls for GPIO pins, assuming they are configured as outputs */
3760	ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
3761	ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
3762	ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
3763	ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
3764
3765	/* Switches to allow the digital IO pins to be enabled.  The datasheet
3766	 * is ambigious as to which NID is which; testing on laptops which
3767	 * make this output available should provide clarification.
3768	 */
3769	ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
3770	ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
3771
3772	{ } /* end */
3773};
3774static struct hda_verb alc260_test_init_verbs[] = {
3775	/* Enable all GPIOs as outputs with an initial value of 0 */
3776	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
3777	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
3778	{0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
3779
3780	/* Enable retasking pins as output, initially without power amp */
3781	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3782	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3783	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3784	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3785	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3786	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3787
3788	/* Disable digital (SPDIF) pins initially, but users can enable
3789	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
3790	 * payload also sets the generation to 0, output to be in "consumer"
3791	 * PCM format, copyright asserted, no pre-emphasis and no validity
3792	 * control.
3793	 */
3794	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
3795	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
3796
3797	/* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
3798	 * OUT1 sum bus when acting as an output.
3799	 */
3800	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
3801	{0x0c, AC_VERB_SET_CONNECT_SEL, 0},
3802	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
3803	{0x0e, AC_VERB_SET_CONNECT_SEL, 0},
3804
3805	/* Start with output sum widgets muted and their output gains at min */
3806	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3807	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3808	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3809	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3810	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3811	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3812	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3813	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3814	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3815
3816	/* Unmute retasking pin widget output buffers since the default
3817	 * state appears to be output.  As the pin mode is changed by the
3818	 * user the pin mode control will take care of enabling the pin's
3819	 * input/output buffers as needed.
3820	 */
3821	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3822	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3823	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3824	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3825	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3826	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3827	/* Also unmute the mono-out pin widget */
3828	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3829
3830	/* Mute capture amp left and right */
3831	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3832	/* Set ADC connection select to match default mixer setting (mic1
3833	 * pin)
3834	 */
3835	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
3836
3837	/* Do the same for the second ADC: mute capture input amp and
3838	 * set ADC connection to mic1 pin
3839	 */
3840	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3841	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
3842
3843	/* Mute all inputs to mixer widget (even unconnected ones) */
3844	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
3845	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
3846	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
3847	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
3848	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
3849	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
3850	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
3851	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
3852
3853	{ }
3854};
3855#endif
3856
3857static struct hda_pcm_stream alc260_pcm_analog_playback = {
3858	.substreams = 1,
3859	.channels_min = 2,
3860	.channels_max = 2,
3861};
3862
3863static struct hda_pcm_stream alc260_pcm_analog_capture = {
3864	.substreams = 1,
3865	.channels_min = 2,
3866	.channels_max = 2,
3867};
3868
3869#define alc260_pcm_digital_playback	alc880_pcm_digital_playback
3870#define alc260_pcm_digital_capture	alc880_pcm_digital_capture
3871
3872/*
3873 * for BIOS auto-configuration
3874 */
3875
3876static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
3877					const char *pfx)
3878{
3879	hda_nid_t nid_vol;
3880	unsigned long vol_val, sw_val;
3881	char name[32];
3882	int err;
3883
3884	if (nid >= 0x0f && nid < 0x11) {
3885		nid_vol = nid - 0x7;
3886		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
3887		sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3888	} else if (nid == 0x11) {
3889		nid_vol = nid - 0x7;
3890		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
3891		sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
3892	} else if (nid >= 0x12 && nid <= 0x15) {
3893		nid_vol = 0x08;
3894		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
3895		sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3896	} else
3897		return 0; /* N/A */
3898
3899	snprintf(name, sizeof(name), "%s Playback Volume", pfx);
3900	if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val)) < 0)
3901		return err;
3902	snprintf(name, sizeof(name), "%s Playback Switch", pfx);
3903	if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val)) < 0)
3904		return err;
3905	return 1;
3906}
3907
3908/* add playback controls from the parsed DAC table */
3909static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
3910					     const struct auto_pin_cfg *cfg)
3911{
3912	hda_nid_t nid;
3913	int err;
3914
3915	spec->multiout.num_dacs = 1;
3916	spec->multiout.dac_nids = spec->private_dac_nids;
3917	spec->multiout.dac_nids[0] = 0x02;
3918
3919	nid = cfg->line_out_pins[0];
3920	if (nid) {
3921		err = alc260_add_playback_controls(spec, nid, "Front");
3922		if (err < 0)
3923			return err;
3924	}
3925
3926	nid = cfg->speaker_pins[0];
3927	if (nid) {
3928		err = alc260_add_playback_controls(spec, nid, "Speaker");
3929		if (err < 0)
3930			return err;
3931	}
3932
3933	nid = cfg->hp_pins[0];
3934	if (nid) {
3935		err = alc260_add_playback_controls(spec, nid, "Headphone");
3936		if (err < 0)
3937			return err;
3938	}
3939	return 0;
3940}
3941
3942/* create playback/capture controls for input pins */
3943static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
3944						const struct auto_pin_cfg *cfg)
3945{
3946	struct hda_input_mux *imux = &spec->private_imux;
3947	int i, err, idx;
3948
3949	for (i = 0; i < AUTO_PIN_LAST; i++) {
3950		if (cfg->input_pins[i] >= 0x12) {
3951			idx = cfg->input_pins[i] - 0x12;
3952			err = new_analog_input(spec, cfg->input_pins[i],
3953					       auto_pin_cfg_labels[i], idx, 0x07);
3954			if (err < 0)
3955				return err;
3956			imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
3957			imux->items[imux->num_items].index = idx;
3958			imux->num_items++;
3959		}
3960		if ((cfg->input_pins[i] >= 0x0f) && (cfg->input_pins[i] <= 0x10)){
3961			idx = cfg->input_pins[i] - 0x09;
3962			err = new_analog_input(spec, cfg->input_pins[i],
3963					       auto_pin_cfg_labels[i], idx, 0x07);
3964			if (err < 0)
3965				return err;
3966			imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
3967			imux->items[imux->num_items].index = idx;
3968			imux->num_items++;
3969		}
3970	}
3971	return 0;
3972}
3973
3974static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
3975					      hda_nid_t nid, int pin_type,
3976					      int sel_idx)
3977{
3978	/* set as output */
3979	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3980	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3981	/* need the manual connection? */
3982	if (nid >= 0x12) {
3983		int idx = nid - 0x12;
3984		snd_hda_codec_write(codec, idx + 0x0b, 0,
3985				    AC_VERB_SET_CONNECT_SEL, sel_idx);
3986
3987	}
3988}
3989
3990static void alc260_auto_init_multi_out(struct hda_codec *codec)
3991{
3992	struct alc_spec *spec = codec->spec;
3993	hda_nid_t nid;
3994
3995	nid = spec->autocfg.line_out_pins[0];
3996	if (nid)
3997		alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3998
3999	nid = spec->autocfg.speaker_pins[0];
4000	if (nid)
4001		alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
4002
4003	nid = spec->autocfg.hp_pins[0];
4004	if (nid)
4005		alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
4006}
4007
4008#define ALC260_PIN_CD_NID		0x16
4009static void alc260_auto_init_analog_input(struct hda_codec *codec)
4010{
4011	struct alc_spec *spec = codec->spec;
4012	int i;
4013
4014	for (i = 0; i < AUTO_PIN_LAST; i++) {
4015		hda_nid_t nid = spec->autocfg.input_pins[i];
4016		if (nid >= 0x12) {
4017			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4018					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
4019			if (nid != ALC260_PIN_CD_NID)
4020				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
4021						    AMP_OUT_MUTE);
4022		}
4023	}
4024}
4025
4026/*
4027 * generic initialization of ADC, input mixers and output mixers
4028 */
4029static struct hda_verb alc260_volume_init_verbs[] = {
4030	/*
4031	 * Unmute ADC0-1 and set the default input to mic-in
4032	 */
4033	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
4034	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4035	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
4036	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4037
4038	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4039	 * mixer widget
4040	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
4041	 * mic (mic 2)
4042	 */
4043	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
4044	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4045	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4046	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4047	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4048	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
4049
4050	/*
4051	 * Set up output mixers (0x08 - 0x0a)
4052	 */
4053	/* set vol=0 to output mixers */
4054	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4055	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4056	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4057	/* set up input amps for analog loopback */
4058	/* Amp Indices: DAC = 0, mixer = 1 */
4059	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4060	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4061	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4062	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4063	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4064	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4065
4066	{ }
4067};
4068
4069static int alc260_parse_auto_config(struct hda_codec *codec)
4070{
4071	struct alc_spec *spec = codec->spec;
4072	unsigned int wcap;
4073	int err;
4074	static hda_nid_t alc260_ignore[] = { 0x17, 0 };
4075
4076	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4077						alc260_ignore)) < 0)
4078		return err;
4079	if ((err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0)
4080		return err;
4081	if (! spec->kctl_alloc)
4082		return 0; /* can't find valid BIOS pin config */
4083	if ((err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
4084		return err;
4085
4086	spec->multiout.max_channels = 2;
4087
4088	if (spec->autocfg.dig_out_pin)
4089		spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
4090	if (spec->kctl_alloc)
4091		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4092
4093	spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
4094
4095	spec->num_mux_defs = 1;
4096	spec->input_mux = &spec->private_imux;
4097
4098	/* check whether NID 0x04 is valid */
4099	wcap = get_wcaps(codec, 0x04);
4100	wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
4101	if (wcap != AC_WID_AUD_IN) {
4102		spec->adc_nids = alc260_adc_nids_alt;
4103		spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
4104		spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
4105	} else {
4106		spec->adc_nids = alc260_adc_nids;
4107		spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
4108		spec->mixers[spec->num_mixers] = alc260_capture_mixer;
4109	}
4110	spec->num_mixers++;
4111
4112	return 1;
4113}
4114
4115/* additional initialization for auto-configuration model */
4116static void alc260_auto_init(struct hda_codec *codec)
4117{
4118	alc260_auto_init_multi_out(codec);
4119	alc260_auto_init_analog_input(codec);
4120}
4121
4122/*
4123 * ALC260 configurations
4124 */
4125static const char *alc260_models[ALC260_MODEL_LAST] = {
4126	[ALC260_BASIC]		= "basic",
4127	[ALC260_HP]		= "hp",
4128	[ALC260_HP_3013]	= "hp-3013",
4129	[ALC260_FUJITSU_S702X]	= "fujitsu",
4130	[ALC260_ACER]		= "acer",
4131#ifdef CONFIG_SND_DEBUG
4132	[ALC260_TEST]		= "test",
4133#endif
4134	[ALC260_AUTO]		= "auto",
4135};
4136
4137static struct snd_pci_quirk alc260_cfg_tbl[] = {
4138	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
4139	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
4140	SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
4141	SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP),
4142	SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013),
4143	SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
4144	SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
4145	SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
4146	SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
4147	SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
4148	SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
4149	SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
4150	SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
4151	SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
4152	{}
4153};
4154
4155static struct alc_config_preset alc260_presets[] = {
4156	[ALC260_BASIC] = {
4157		.mixers = { alc260_base_output_mixer,
4158			    alc260_input_mixer,
4159			    alc260_pc_beep_mixer,
4160			    alc260_capture_mixer },
4161		.init_verbs = { alc260_init_verbs },
4162		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4163		.dac_nids = alc260_dac_nids,
4164		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
4165		.adc_nids = alc260_adc_nids,
4166		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4167		.channel_mode = alc260_modes,
4168		.input_mux = &alc260_capture_source,
4169	},
4170	[ALC260_HP] = {
4171		.mixers = { alc260_base_output_mixer,
4172			    alc260_input_mixer,
4173			    alc260_capture_alt_mixer },
4174		.init_verbs = { alc260_init_verbs },
4175		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4176		.dac_nids = alc260_dac_nids,
4177		.num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
4178		.adc_nids = alc260_hp_adc_nids,
4179		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4180		.channel_mode = alc260_modes,
4181		.input_mux = &alc260_capture_source,
4182	},
4183	[ALC260_HP_3013] = {
4184		.mixers = { alc260_hp_3013_mixer,
4185			    alc260_input_mixer,
4186			    alc260_capture_alt_mixer },
4187		.init_verbs = { alc260_hp_3013_init_verbs },
4188		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4189		.dac_nids = alc260_dac_nids,
4190		.num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
4191		.adc_nids = alc260_hp_adc_nids,
4192		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4193		.channel_mode = alc260_modes,
4194		.input_mux = &alc260_capture_source,
4195	},
4196	[ALC260_FUJITSU_S702X] = {
4197		.mixers = { alc260_fujitsu_mixer,
4198			    alc260_capture_mixer },
4199		.init_verbs = { alc260_fujitsu_init_verbs },
4200		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4201		.dac_nids = alc260_dac_nids,
4202		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
4203		.adc_nids = alc260_dual_adc_nids,
4204		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4205		.channel_mode = alc260_modes,
4206		.num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
4207		.input_mux = alc260_fujitsu_capture_sources,
4208	},
4209	[ALC260_ACER] = {
4210		.mixers = { alc260_acer_mixer,
4211			    alc260_capture_mixer },
4212		.init_verbs = { alc260_acer_init_verbs },
4213		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
4214		.dac_nids = alc260_dac_nids,
4215		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
4216		.adc_nids = alc260_dual_adc_nids,
4217		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4218		.channel_mode = alc260_modes,
4219		.num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
4220		.input_mux = alc260_acer_capture_sources,
4221	},
4222#ifdef CONFIG_SND_DEBUG
4223	[ALC260_TEST] = {
4224		.mixers = { alc260_test_mixer,
4225			    alc260_capture_mixer },
4226		.init_verbs = { alc260_test_init_verbs },
4227		.num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
4228		.dac_nids = alc260_test_dac_nids,
4229		.num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
4230		.adc_nids = alc260_test_adc_nids,
4231		.num_channel_mode = ARRAY_SIZE(alc260_modes),
4232		.channel_mode = alc260_modes,
4233		.num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
4234		.input_mux = alc260_test_capture_sources,
4235	},
4236#endif
4237};
4238
4239static int patch_alc260(struct hda_codec *codec)
4240{
4241	struct alc_spec *spec;
4242	int err, board_config;
4243
4244	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4245	if (spec == NULL)
4246		return -ENOMEM;
4247
4248	codec->spec = spec;
4249
4250	board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
4251						  alc260_models,
4252						  alc260_cfg_tbl);
4253	if (board_config < 0) {
4254		snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, "
4255			   "trying auto-probe from BIOS...\n");
4256		board_config = ALC260_AUTO;
4257	}
4258
4259	if (board_config == ALC260_AUTO) {
4260		/* automatic parse from the BIOS config */
4261		err = alc260_parse_auto_config(codec);
4262		if (err < 0) {
4263			alc_free(codec);
4264			return err;
4265		} else if (! err) {
4266			printk(KERN_INFO
4267			       "hda_codec: Cannot set up configuration "
4268			       "from BIOS.  Using base mode...\n");
4269			board_config = ALC260_BASIC;
4270		}
4271	}
4272
4273	if (board_config != ALC260_AUTO)
4274		setup_preset(spec, &alc260_presets[board_config]);
4275
4276	spec->stream_name_analog = "ALC260 Analog";
4277	spec->stream_analog_playback = &alc260_pcm_analog_playback;
4278	spec->stream_analog_capture = &alc260_pcm_analog_capture;
4279
4280	spec->stream_name_digital = "ALC260 Digital";
4281	spec->stream_digital_playback = &alc260_pcm_digital_playback;
4282	spec->stream_digital_capture = &alc260_pcm_digital_capture;
4283
4284	codec->patch_ops = alc_patch_ops;
4285	if (board_config == ALC260_AUTO)
4286		spec->init_hook = alc260_auto_init;
4287
4288	return 0;
4289}
4290
4291
4292/*
4293 * ALC882 support
4294 *
4295 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
4296 * configuration.  Each pin widget can choose any input DACs and a mixer.
4297 * Each ADC is connected from a mixer of all inputs.  This makes possible
4298 * 6-channel independent captures.
4299 *
4300 * In addition, an independent DAC for the multi-playback (not used in this
4301 * driver yet).
4302 */
4303#define ALC882_DIGOUT_NID	0x06
4304#define ALC882_DIGIN_NID	0x0a
4305
4306static struct hda_channel_mode alc882_ch_modes[1] = {
4307	{ 8, NULL }
4308};
4309
4310static hda_nid_t alc882_dac_nids[4] = {
4311	/* front, rear, clfe, rear_surr */
4312	0x02, 0x03, 0x04, 0x05
4313};
4314
4315/* identical with ALC880 */
4316#define alc882_adc_nids		alc880_adc_nids
4317#define alc882_adc_nids_alt	alc880_adc_nids_alt
4318
4319/* input MUX */
4320/* FIXME: should be a matrix-type input source selection */
4321
4322static struct hda_input_mux alc882_capture_source = {
4323	.num_items = 4,
4324	.items = {
4325		{ "Mic", 0x0 },
4326		{ "Front Mic", 0x1 },
4327		{ "Line", 0x2 },
4328		{ "CD", 0x4 },
4329	},
4330};
4331#define alc882_mux_enum_info alc_mux_enum_info
4332#define alc882_mux_enum_get alc_mux_enum_get
4333
4334static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
4335{
4336	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4337	struct alc_spec *spec = codec->spec;
4338	const struct hda_input_mux *imux = spec->input_mux;
4339	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
4340	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
4341	hda_nid_t nid = capture_mixers[adc_idx];
4342	unsigned int *cur_val = &spec->cur_mux[adc_idx];
4343	unsigned int i, idx;
4344
4345	idx = ucontrol->value.enumerated.item[0];
4346	if (idx >= imux->num_items)
4347		idx = imux->num_items - 1;
4348	if (*cur_val == idx && ! codec->in_resume)
4349		return 0;
4350	for (i = 0; i < imux->num_items; i++) {
4351		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
4352		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
4353				    v | (imux->items[i].index << 8));
4354	}
4355	*cur_val = idx;
4356	return 1;
4357}
4358
4359/*
4360 * 6ch mode
4361 */
4362static struct hda_verb alc882_sixstack_ch6_init[] = {
4363	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4364	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4365	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4366	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4367	{ } /* end */
4368};
4369
4370/*
4371 * 8ch mode
4372 */
4373static struct hda_verb alc882_sixstack_ch8_init[] = {
4374	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4375	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4376	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4377	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
4378	{ } /* end */
4379};
4380
4381static struct hda_channel_mode alc882_sixstack_modes[2] = {
4382	{ 6, alc882_sixstack_ch6_init },
4383	{ 8, alc882_sixstack_ch8_init },
4384};
4385
4386/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
4387 *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
4388 */
4389static struct snd_kcontrol_new alc882_base_mixer[] = {
4390	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4391	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4392	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
4393	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
4394	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
4395	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
4396	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
4397	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
4398	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
4399	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
4400	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
4401	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
4402	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
4403	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4404	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4405	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
4406	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4407	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
4408	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
4409	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
4410	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
4411	{ } /* end */
4412};
4413
4414static struct snd_kcontrol_new alc882_chmode_mixer[] = {
4415	{
4416		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4417		.name = "Channel Mode",
4418		.info = alc_ch_mode_info,
4419		.get = alc_ch_mode_get,
4420		.put = alc_ch_mode_put,
4421	},
4422	{ } /* end */
4423};
4424
4425static struct hda_verb alc882_init_verbs[] = {
4426	/* Front mixer: unmute input/output amp left and right (volume = 0) */
4427	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4428	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4429	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4430	/* Rear mixer */
4431	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4432	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4433	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4434	/* CLFE mixer */
4435	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4436	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4437	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4438	/* Side mixer */
4439	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4440	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4441	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4442
4443	/* Front Pin: output 0 (0x0c) */
4444	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4445	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4446	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
4447	/* Rear Pin: output 1 (0x0d) */
4448	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4449	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4450	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
4451	/* CLFE Pin: output 2 (0x0e) */
4452	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4453	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4454	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
4455	/* Side Pin: output 3 (0x0f) */
4456	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4457	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4458	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
4459	/* Mic (rear) pin: input vref at 80% */
4460	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4461	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4462	/* Front Mic pin: input vref at 80% */
4463	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4464	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4465	/* Line In pin: input */
4466	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4467	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4468	/* Line-2 In: Headphone output (output 0 - 0x0c) */
4469	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4470	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4471	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
4472	/* CD pin widget for input */
4473	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4474
4475	/* FIXME: use matrix-type input source selection */
4476	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4477	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4478	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4479	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4480	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4481	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4482	/* Input mixer2 */
4483	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4484	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4485	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4486	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4487	/* Input mixer3 */
4488	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4489	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4490	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4491	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4492	/* ADC1: mute amp left and right */
4493	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4494	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4495	/* ADC2: mute amp left and right */
4496	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4497	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4498	/* ADC3: mute amp left and right */
4499	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4500	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4501
4502	{ }
4503};
4504
4505static struct hda_verb alc882_eapd_verbs[] = {
4506	/* change to EAPD mode */
4507	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
4508	{0x20, AC_VERB_SET_PROC_COEF, 0x3060},
4509	{ }
4510};
4511
4512/* Mac Pro test */
4513static struct snd_kcontrol_new alc882_macpro_mixer[] = {
4514	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4515	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4516	HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
4517	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
4518	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
4519	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
4520	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
4521	{ } /* end */
4522};
4523
4524static struct hda_verb alc882_macpro_init_verbs[] = {
4525	/* Front mixer: unmute input/output amp left and right (volume = 0) */
4526	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4527	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4528	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4529	/* Front Pin: output 0 (0x0c) */
4530	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4531	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4532	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
4533	/* Front Mic pin: input vref at 80% */
4534	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4535	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4536	/* Speaker:  output */
4537	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4538	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4539	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
4540	/* Headphone output (output 0 - 0x0c) */
4541	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4542	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4543	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
4544
4545	/* FIXME: use matrix-type input source selection */
4546	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4547	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4548	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4549	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4550	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4551	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4552	/* Input mixer2 */
4553	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4554	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4555	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4556	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4557	/* Input mixer3 */
4558	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4559	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4560	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4561	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4562	/* ADC1: mute amp left and right */
4563	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4564	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4565	/* ADC2: mute amp left and right */
4566	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4567	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4568	/* ADC3: mute amp left and right */
4569	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4570	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4571
4572	{ }
4573};
4574static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
4575{
4576	unsigned int gpiostate, gpiomask, gpiodir;
4577
4578	gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
4579				       AC_VERB_GET_GPIO_DATA, 0);
4580
4581	if (!muted)
4582		gpiostate |= (1 << pin);
4583	else
4584		gpiostate &= ~(1 << pin);
4585
4586	gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
4587				      AC_VERB_GET_GPIO_MASK, 0);
4588	gpiomask |= (1 << pin);
4589
4590	gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
4591				     AC_VERB_GET_GPIO_DIRECTION, 0);
4592	gpiodir |= (1 << pin);
4593
4594
4595	snd_hda_codec_write(codec, codec->afg, 0,
4596			    AC_VERB_SET_GPIO_MASK, gpiomask);
4597	snd_hda_codec_write(codec, codec->afg, 0,
4598			    AC_VERB_SET_GPIO_DIRECTION, gpiodir);
4599
4600	msleep(1);
4601
4602	snd_hda_codec_write(codec, codec->afg, 0,
4603			    AC_VERB_SET_GPIO_DATA, gpiostate);
4604}
4605
4606/*
4607 * generic initialization of ADC, input mixers and output mixers
4608 */
4609static struct hda_verb alc882_auto_init_verbs[] = {
4610	/*
4611	 * Unmute ADC0-2 and set the default input to mic-in
4612	 */
4613	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4614	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4615	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4616	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4617	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4618	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4619
4620	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4621	 * mixer widget
4622	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
4623	 * mic (mic 2)
4624	 */
4625	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
4626	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4627	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4628	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4629	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4630	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
4631
4632	/*
4633	 * Set up output mixers (0x0c - 0x0f)
4634	 */
4635	/* set vol=0 to output mixers */
4636	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4637	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4638	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4639	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4640	/* set up input amps for analog loopback */
4641	/* Amp Indices: DAC = 0, mixer = 1 */
4642	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4643	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4644	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4645	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4646	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4647	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4648	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4649	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4650	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4651	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4652
4653	/* FIXME: use matrix-type input source selection */
4654	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4655	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4656	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4657	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4658	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4659	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4660	/* Input mixer2 */
4661	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4662	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4663	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4664	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4665	/* Input mixer3 */
4666	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4667	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4668	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4669	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4670
4671	{ }
4672};
4673
4674/* capture mixer elements */
4675static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
4676	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4677	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4678	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
4679	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
4680	{
4681		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4682		/* The multiple "Capture Source" controls confuse alsamixer
4683		 * So call somewhat different..
4684		 * FIXME: the controls appear in the "playback" view!
4685		 */
4686		/* .name = "Capture Source", */
4687		.name = "Input Source",
4688		.count = 2,
4689		.info = alc882_mux_enum_info,
4690		.get = alc882_mux_enum_get,
4691		.put = alc882_mux_enum_put,
4692	},
4693	{ } /* end */
4694};
4695
4696static struct snd_kcontrol_new alc882_capture_mixer[] = {
4697	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
4698	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
4699	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
4700	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
4701	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
4702	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
4703	{
4704		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4705		/* The multiple "Capture Source" controls confuse alsamixer
4706		 * So call somewhat different..
4707		 * FIXME: the controls appear in the "playback" view!
4708		 */
4709		/* .name = "Capture Source", */
4710		.name = "Input Source",
4711		.count = 3,
4712		.info = alc882_mux_enum_info,
4713		.get = alc882_mux_enum_get,
4714		.put = alc882_mux_enum_put,
4715	},
4716	{ } /* end */
4717};
4718
4719/* pcm configuration: identiacal with ALC880 */
4720#define alc882_pcm_analog_playback	alc880_pcm_analog_playback
4721#define alc882_pcm_analog_capture	alc880_pcm_analog_capture
4722#define alc882_pcm_digital_playback	alc880_pcm_digital_playback
4723#define alc882_pcm_digital_capture	alc880_pcm_digital_capture
4724
4725/*
4726 * configuration and preset
4727 */
4728static const char *alc882_models[ALC882_MODEL_LAST] = {
4729	[ALC882_3ST_DIG]	= "3stack-dig",
4730	[ALC882_6ST_DIG]	= "6stack-dig",
4731	[ALC882_ARIMA]		= "arima",
4732	[ALC885_MACPRO]		= "macpro",
4733	[ALC882_AUTO]		= "auto",
4734};
4735
4736static struct snd_pci_quirk alc882_cfg_tbl[] = {
4737	SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
4738	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
4739	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
4740	SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA),
4741	{}
4742};
4743
4744static struct alc_config_preset alc882_presets[] = {
4745	[ALC882_3ST_DIG] = {
4746		.mixers = { alc882_base_mixer },
4747		.init_verbs = { alc882_init_verbs },
4748		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
4749		.dac_nids = alc882_dac_nids,
4750		.dig_out_nid = ALC882_DIGOUT_NID,
4751		.dig_in_nid = ALC882_DIGIN_NID,
4752		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
4753		.channel_mode = alc882_ch_modes,
4754		.need_dac_fix = 1,
4755		.input_mux = &alc882_capture_source,
4756	},
4757	[ALC882_6ST_DIG] = {
4758		.mixers = { alc882_base_mixer, alc882_chmode_mixer },
4759		.init_verbs = { alc882_init_verbs },
4760		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
4761		.dac_nids = alc882_dac_nids,
4762		.dig_out_nid = ALC882_DIGOUT_NID,
4763		.dig_in_nid = ALC882_DIGIN_NID,
4764		.num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
4765		.channel_mode = alc882_sixstack_modes,
4766		.input_mux = &alc882_capture_source,
4767	},
4768	[ALC882_ARIMA] = {
4769		.mixers = { alc882_base_mixer, alc882_chmode_mixer },
4770		.init_verbs = { alc882_init_verbs, alc882_eapd_verbs },
4771		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
4772		.dac_nids = alc882_dac_nids,
4773		.num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
4774		.channel_mode = alc882_sixstack_modes,
4775		.input_mux = &alc882_capture_source,
4776	},
4777	[ALC885_MACPRO] = {
4778		.mixers = { alc882_macpro_mixer },
4779		.init_verbs = { alc882_macpro_init_verbs },
4780		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
4781		.dac_nids = alc882_dac_nids,
4782		.dig_out_nid = ALC882_DIGOUT_NID,
4783		.dig_in_nid = ALC882_DIGIN_NID,
4784		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
4785		.channel_mode = alc882_ch_modes,
4786		.input_mux = &alc882_capture_source,
4787	},
4788};
4789
4790
4791/*
4792 * BIOS auto configuration
4793 */
4794static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
4795					      hda_nid_t nid, int pin_type,
4796					      int dac_idx)
4797{
4798	/* set as output */
4799	struct alc_spec *spec = codec->spec;
4800	int idx;
4801
4802	if (spec->multiout.dac_nids[dac_idx] == 0x25)
4803		idx = 4;
4804	else
4805		idx = spec->multiout.dac_nids[dac_idx] - 2;
4806
4807	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
4808	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
4809	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
4810
4811}
4812
4813static void alc882_auto_init_multi_out(struct hda_codec *codec)
4814{
4815	struct alc_spec *spec = codec->spec;
4816	int i;
4817
4818	for (i = 0; i <= HDA_SIDE; i++) {
4819		hda_nid_t nid = spec->autocfg.line_out_pins[i];
4820		if (nid)
4821			alc882_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
4822	}
4823}
4824
4825static void alc882_auto_init_hp_out(struct hda_codec *codec)
4826{
4827	struct alc_spec *spec = codec->spec;
4828	hda_nid_t pin;
4829
4830	pin = spec->autocfg.hp_pins[0];
4831	if (pin) /* connect to front */
4832		alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */
4833}
4834
4835#define alc882_is_input_pin(nid)	alc880_is_input_pin(nid)
4836#define ALC882_PIN_CD_NID		ALC880_PIN_CD_NID
4837
4838static void alc882_auto_init_analog_input(struct hda_codec *codec)
4839{
4840	struct alc_spec *spec = codec->spec;
4841	int i;
4842
4843	for (i = 0; i < AUTO_PIN_LAST; i++) {
4844		hda_nid_t nid = spec->autocfg.input_pins[i];
4845		if (alc882_is_input_pin(nid)) {
4846			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4847					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
4848			if (nid != ALC882_PIN_CD_NID)
4849				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
4850						    AMP_OUT_MUTE);
4851		}
4852	}
4853}
4854
4855/* almost identical with ALC880 parser... */
4856static int alc882_parse_auto_config(struct hda_codec *codec)
4857{
4858	struct alc_spec *spec = codec->spec;
4859	int err = alc880_parse_auto_config(codec);
4860
4861	if (err < 0)
4862		return err;
4863	else if (err > 0)
4864		/* hack - override the init verbs */
4865		spec->init_verbs[0] = alc882_auto_init_verbs;
4866	return err;
4867}
4868
4869/* additional initialization for auto-configuration model */
4870static void alc882_auto_init(struct hda_codec *codec)
4871{
4872	alc882_auto_init_multi_out(codec);
4873	alc882_auto_init_hp_out(codec);
4874	alc882_auto_init_analog_input(codec);
4875}
4876
4877static int patch_alc882(struct hda_codec *codec)
4878{
4879	struct alc_spec *spec;
4880	int err, board_config;
4881
4882	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4883	if (spec == NULL)
4884		return -ENOMEM;
4885
4886	codec->spec = spec;
4887
4888	board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
4889						  alc882_models,
4890						  alc882_cfg_tbl);
4891
4892	if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
4893		printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
4894		       "trying auto-probe from BIOS...\n");
4895		board_config = ALC882_AUTO;
4896	}
4897
4898	if (board_config == ALC882_AUTO) {
4899		/* automatic parse from the BIOS config */
4900		err = alc882_parse_auto_config(codec);
4901		if (err < 0) {
4902			alc_free(codec);
4903			return err;
4904		} else if (! err) {
4905			printk(KERN_INFO
4906			       "hda_codec: Cannot set up configuration "
4907			       "from BIOS.  Using base mode...\n");
4908			board_config = ALC882_3ST_DIG;
4909		}
4910	}
4911
4912	if (board_config != ALC882_AUTO)
4913		setup_preset(spec, &alc882_presets[board_config]);
4914
4915	if (board_config == ALC885_MACPRO) {
4916		alc882_gpio_mute(codec, 0, 0);
4917		alc882_gpio_mute(codec, 1, 0);
4918	}
4919
4920	spec->stream_name_analog = "ALC882 Analog";
4921	spec->stream_analog_playback = &alc882_pcm_analog_playback;
4922	spec->stream_analog_capture = &alc882_pcm_analog_capture;
4923
4924	spec->stream_name_digital = "ALC882 Digital";
4925	spec->stream_digital_playback = &alc882_pcm_digital_playback;
4926	spec->stream_digital_capture = &alc882_pcm_digital_capture;
4927
4928	if (! spec->adc_nids && spec->input_mux) {
4929		/* check whether NID 0x07 is valid */
4930		unsigned int wcap = get_wcaps(codec, 0x07);
4931		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
4932		if (wcap != AC_WID_AUD_IN) {
4933			spec->adc_nids = alc882_adc_nids_alt;
4934			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
4935			spec->mixers[spec->num_mixers] = alc882_capture_alt_mixer;
4936			spec->num_mixers++;
4937		} else {
4938			spec->adc_nids = alc882_adc_nids;
4939			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
4940			spec->mixers[spec->num_mixers] = alc882_capture_mixer;
4941			spec->num_mixers++;
4942		}
4943	}
4944
4945	codec->patch_ops = alc_patch_ops;
4946	if (board_config == ALC882_AUTO)
4947		spec->init_hook = alc882_auto_init;
4948
4949	return 0;
4950}
4951
4952/*
4953 * ALC883 support
4954 *
4955 * ALC883 is almost identical with ALC880 but has cleaner and more flexible
4956 * configuration.  Each pin widget can choose any input DACs and a mixer.
4957 * Each ADC is connected from a mixer of all inputs.  This makes possible
4958 * 6-channel independent captures.
4959 *
4960 * In addition, an independent DAC for the multi-playback (not used in this
4961 * driver yet).
4962 */
4963#define ALC883_DIGOUT_NID	0x06
4964#define ALC883_DIGIN_NID	0x0a
4965
4966static hda_nid_t alc883_dac_nids[4] = {
4967	/* front, rear, clfe, rear_surr */
4968	0x02, 0x04, 0x03, 0x05
4969};
4970
4971static hda_nid_t alc883_adc_nids[2] = {
4972	/* ADC1-2 */
4973	0x08, 0x09,
4974};
4975/* input MUX */
4976/* FIXME: should be a matrix-type input source selection */
4977
4978static struct hda_input_mux alc883_capture_source = {
4979	.num_items = 4,
4980	.items = {
4981		{ "Mic", 0x0 },
4982		{ "Front Mic", 0x1 },
4983		{ "Line", 0x2 },
4984		{ "CD", 0x4 },
4985	},
4986};
4987#define alc883_mux_enum_info alc_mux_enum_info
4988#define alc883_mux_enum_get alc_mux_enum_get
4989
4990static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol,
4991			       struct snd_ctl_elem_value *ucontrol)
4992{
4993	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4994	struct alc_spec *spec = codec->spec;
4995	const struct hda_input_mux *imux = spec->input_mux;
4996	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
4997	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
4998	hda_nid_t nid = capture_mixers[adc_idx];
4999	unsigned int *cur_val = &spec->cur_mux[adc_idx];
5000	unsigned int i, idx;
5001
5002	idx = ucontrol->value.enumerated.item[0];
5003	if (idx >= imux->num_items)
5004		idx = imux->num_items - 1;
5005	if (*cur_val == idx && ! codec->in_resume)
5006		return 0;
5007	for (i = 0; i < imux->num_items; i++) {
5008		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
5009		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
5010				    v | (imux->items[i].index << 8));
5011	}
5012	*cur_val = idx;
5013	return 1;
5014}
5015/*
5016 * 2ch mode
5017 */
5018static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
5019	{ 2, NULL }
5020};
5021
5022/*
5023 * 2ch mode
5024 */
5025static struct hda_verb alc883_3ST_ch2_init[] = {
5026	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
5027	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
5028	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
5029	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
5030	{ } /* end */
5031};
5032
5033/*
5034 * 6ch mode
5035 */
5036static struct hda_verb alc883_3ST_ch6_init[] = {
5037	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5038	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
5039	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
5040	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5041	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
5042	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
5043	{ } /* end */
5044};
5045
5046static struct hda_channel_mode alc883_3ST_6ch_modes[2] = {
5047	{ 2, alc883_3ST_ch2_init },
5048	{ 6, alc883_3ST_ch6_init },
5049};
5050
5051/*
5052 * 6ch mode
5053 */
5054static struct hda_verb alc883_sixstack_ch6_init[] = {
5055	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
5056	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5057	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5058	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5059	{ } /* end */
5060};
5061
5062/*
5063 * 8ch mode
5064 */
5065static struct hda_verb alc883_sixstack_ch8_init[] = {
5066	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5067	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5068	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5069	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
5070	{ } /* end */
5071};
5072
5073static struct hda_channel_mode alc883_sixstack_modes[2] = {
5074	{ 6, alc883_sixstack_ch6_init },
5075	{ 8, alc883_sixstack_ch8_init },
5076};
5077
5078static struct hda_verb alc883_medion_eapd_verbs[] = {
5079        /* eanable EAPD on medion laptop */
5080	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
5081	{0x20, AC_VERB_SET_PROC_COEF, 0x3070},
5082	{ }
5083};
5084
5085/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
5086 *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
5087 */
5088
5089static struct snd_kcontrol_new alc883_base_mixer[] = {
5090	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5091	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5092	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5093	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
5094	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5095	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5096	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
5097	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
5098	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
5099	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
5100	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5101	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5102	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5103	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5104	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5105	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5106	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5107	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5108	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5109	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5110	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5111	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5112	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5113	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5114	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5115	{
5116		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5117		/* .name = "Capture Source", */
5118		.name = "Input Source",
5119		.count = 2,
5120		.info = alc883_mux_enum_info,
5121		.get = alc883_mux_enum_get,
5122		.put = alc883_mux_enum_put,
5123	},
5124	{ } /* end */
5125};
5126
5127static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
5128	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5129	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5130	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5131	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5132	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5133	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5134	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5135	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5136	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5137	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5138	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5139	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5140	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5141	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5142	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5143	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5144	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5145	{
5146		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5147		/* .name = "Capture Source", */
5148		.name = "Input Source",
5149		.count = 2,
5150		.info = alc883_mux_enum_info,
5151		.get = alc883_mux_enum_get,
5152		.put = alc883_mux_enum_put,
5153	},
5154	{ } /* end */
5155};
5156
5157static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
5158	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5159	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
5160	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5161	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
5162	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5163	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5164	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
5165	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
5166	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5167	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5168	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5169	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5170	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5171	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5172	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5173	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5174	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5175	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5176	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5177	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5178	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5179	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5180	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5181	{
5182		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5183		/* .name = "Capture Source", */
5184		.name = "Input Source",
5185		.count = 2,
5186		.info = alc883_mux_enum_info,
5187		.get = alc883_mux_enum_get,
5188		.put = alc883_mux_enum_put,
5189	},
5190	{ } /* end */
5191};
5192
5193static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
5194	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5195	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5196	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5197	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
5198	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5199	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5200	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
5201	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
5202	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5203	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5204	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5205	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5206	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5207	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5208	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5209	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5210	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5211	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5212	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5213	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5214	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5215
5216	{
5217		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5218		/* .name = "Capture Source", */
5219		.name = "Input Source",
5220		.count = 1,
5221		.info = alc883_mux_enum_info,
5222		.get = alc883_mux_enum_get,
5223		.put = alc883_mux_enum_put,
5224	},
5225	{ } /* end */
5226};
5227
5228static struct snd_kcontrol_new alc883_tagra_mixer[] = {
5229	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5230	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5231	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5232	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5233	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
5234	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5235	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5236	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
5237	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
5238	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5239	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5240	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5241	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5242	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5243	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5244	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5245	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5246	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5247	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5248	{
5249		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5250		/* .name = "Capture Source", */
5251		.name = "Input Source",
5252		.count = 2,
5253		.info = alc883_mux_enum_info,
5254		.get = alc883_mux_enum_get,
5255		.put = alc883_mux_enum_put,
5256	},
5257	{ } /* end */
5258};
5259
5260static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
5261	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5262	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5263	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5264	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5265	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5266	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5267	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5268	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5269	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5270	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5271	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5272	{
5273		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5274		/* .name = "Capture Source", */
5275		.name = "Input Source",
5276		.count = 2,
5277		.info = alc883_mux_enum_info,
5278		.get = alc883_mux_enum_get,
5279		.put = alc883_mux_enum_put,
5280	},
5281	{ } /* end */
5282};
5283
5284static struct snd_kcontrol_new alc883_chmode_mixer[] = {
5285	{
5286		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5287		.name = "Channel Mode",
5288		.info = alc_ch_mode_info,
5289		.get = alc_ch_mode_get,
5290		.put = alc_ch_mode_put,
5291	},
5292	{ } /* end */
5293};
5294
5295static struct hda_verb alc883_init_verbs[] = {
5296	/* ADC1: mute amp left and right */
5297	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5298	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
5299	/* ADC2: mute amp left and right */
5300	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5301	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
5302	/* Front mixer: unmute input/output amp left and right (volume = 0) */
5303	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5304	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5305	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5306	/* Rear mixer */
5307	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5308	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5309	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5310	/* CLFE mixer */
5311	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5312	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5313	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5314	/* Side mixer */
5315	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5316	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5317	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5318
5319	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5320	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5321	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
5322	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
5323	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
5324
5325	/* Front Pin: output 0 (0x0c) */
5326	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5327	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5328	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
5329	/* Rear Pin: output 1 (0x0d) */
5330	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5331	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5332	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
5333	/* CLFE Pin: output 2 (0x0e) */
5334	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5335	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5336	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
5337	/* Side Pin: output 3 (0x0f) */
5338	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5339	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5340	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
5341	/* Mic (rear) pin: input vref at 80% */
5342	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5343	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5344	/* Front Mic pin: input vref at 80% */
5345	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5346	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5347	/* Line In pin: input */
5348	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5349	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5350	/* Line-2 In: Headphone output (output 0 - 0x0c) */
5351	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5352	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5353	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
5354	/* CD pin widget for input */
5355	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5356
5357	/* FIXME: use matrix-type input source selection */
5358	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
5359	/* Input mixer2 */
5360	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5361	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5362	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
5363	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
5364	/* Input mixer3 */
5365	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5366	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5367	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
5368	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
5369	{ }
5370};
5371
5372static struct hda_verb alc883_tagra_verbs[] = {
5373	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5374	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5375
5376	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5377	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5378
5379	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
5380	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
5381	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
5382
5383	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
5384	{0x01, AC_VERB_SET_GPIO_MASK, 0x03},
5385	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
5386	{0x01, AC_VERB_SET_GPIO_DATA, 0x03},
5387
5388	{ } /* end */
5389};
5390
5391/* toggle speaker-output according to the hp-jack state */
5392static void alc883_tagra_automute(struct hda_codec *codec)
5393{
5394 	unsigned int present;
5395
5396 	present = snd_hda_codec_read(codec, 0x14, 0,
5397				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
5398	snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
5399				 0x80, present ? 0x80 : 0);
5400	snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
5401				 0x80, present ? 0x80 : 0);
5402	snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3);
5403}
5404
5405static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
5406{
5407	if ((res >> 26) == ALC880_HP_EVENT)
5408		alc883_tagra_automute(codec);
5409}
5410
5411/*
5412 * generic initialization of ADC, input mixers and output mixers
5413 */
5414static struct hda_verb alc883_auto_init_verbs[] = {
5415	/*
5416	 * Unmute ADC0-2 and set the default input to mic-in
5417	 */
5418	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
5419	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5420	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
5421	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5422
5423	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
5424	 * mixer widget
5425	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
5426	 * mic (mic 2)
5427	 */
5428	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
5429	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5430	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5431	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
5432	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
5433	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
5434
5435	/*
5436	 * Set up output mixers (0x0c - 0x0f)
5437	 */
5438	/* set vol=0 to output mixers */
5439	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5440	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5441	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5442	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5443	/* set up input amps for analog loopback */
5444	/* Amp Indices: DAC = 0, mixer = 1 */
5445	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5446	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5447	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5448	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5449	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5450	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5451	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5452	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5453	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5454	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5455
5456	/* FIXME: use matrix-type input source selection */
5457	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
5458	/* Input mixer1 */
5459	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5460	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5461	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
5462	//{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
5463	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
5464	/* Input mixer2 */
5465	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5466	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5467	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
5468	//{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
5469	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
5470
5471	{ }
5472};
5473
5474/* capture mixer elements */
5475static struct snd_kcontrol_new alc883_capture_mixer[] = {
5476	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5477	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5478	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5479	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5480	{
5481		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5482		/* The multiple "Capture Source" controls confuse alsamixer
5483		 * So call somewhat different..
5484		 * FIXME: the controls appear in the "playback" view!
5485		 */
5486		/* .name = "Capture Source", */
5487		.name = "Input Source",
5488		.count = 2,
5489		.info = alc882_mux_enum_info,
5490		.get = alc882_mux_enum_get,
5491		.put = alc882_mux_enum_put,
5492	},
5493	{ } /* end */
5494};
5495
5496/* pcm configuration: identiacal with ALC880 */
5497#define alc883_pcm_analog_playback	alc880_pcm_analog_playback
5498#define alc883_pcm_analog_capture	alc880_pcm_analog_capture
5499#define alc883_pcm_digital_playback	alc880_pcm_digital_playback
5500#define alc883_pcm_digital_capture	alc880_pcm_digital_capture
5501
5502/*
5503 * configuration and preset
5504 */
5505static const char *alc883_models[ALC883_MODEL_LAST] = {
5506	[ALC883_3ST_2ch_DIG]	= "3stack-dig",
5507	[ALC883_3ST_6ch_DIG]	= "3stack-6ch-dig",
5508	[ALC883_3ST_6ch]	= "3stack-6ch",
5509	[ALC883_6ST_DIG]	= "6stack-dig",
5510	[ALC883_TARGA_DIG]	= "targa-dig",
5511	[ALC883_TARGA_2ch_DIG]	= "targa-2ch-dig",
5512	[ALC888_DEMO_BOARD]	= "6stack-dig-demo",
5513	[ALC883_ACER]		= "acer",
5514	[ALC883_MEDION]		= "medion",
5515	[ALC883_LAPTOP_EAPD]	= "laptop-eapd",
5516	[ALC883_AUTO]		= "auto",
5517};
5518
5519static struct snd_pci_quirk alc883_cfg_tbl[] = {
5520	SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),
5521	SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
5522	SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
5523	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
5524	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
5525	SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
5526	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
5527	SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
5528	SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
5529	SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
5530	SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
5531	SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
5532	SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
5533	SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
5534	SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
5535	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
5536	SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER),
5537	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
5538	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
5539	SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
5540	{}
5541};
5542
5543static struct alc_config_preset alc883_presets[] = {
5544	[ALC883_3ST_2ch_DIG] = {
5545		.mixers = { alc883_3ST_2ch_mixer },
5546		.init_verbs = { alc883_init_verbs },
5547		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
5548		.dac_nids = alc883_dac_nids,
5549		.dig_out_nid = ALC883_DIGOUT_NID,
5550		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5551		.adc_nids = alc883_adc_nids,
5552		.dig_in_nid = ALC883_DIGIN_NID,
5553		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
5554		.channel_mode = alc883_3ST_2ch_modes,
5555		.input_mux = &alc883_capture_source,
5556	},
5557	[ALC883_3ST_6ch_DIG] = {
5558		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
5559		.init_verbs = { alc883_init_verbs },
5560		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
5561		.dac_nids = alc883_dac_nids,
5562		.dig_out_nid = ALC883_DIGOUT_NID,
5563		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5564		.adc_nids = alc883_adc_nids,
5565		.dig_in_nid = ALC883_DIGIN_NID,
5566		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
5567		.channel_mode = alc883_3ST_6ch_modes,
5568		.need_dac_fix = 1,
5569		.input_mux = &alc883_capture_source,
5570	},
5571	[ALC883_3ST_6ch] = {
5572		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
5573		.init_verbs = { alc883_init_verbs },
5574		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
5575		.dac_nids = alc883_dac_nids,
5576		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5577		.adc_nids = alc883_adc_nids,
5578		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
5579		.channel_mode = alc883_3ST_6ch_modes,
5580		.need_dac_fix = 1,
5581		.input_mux = &alc883_capture_source,
5582	},
5583	[ALC883_6ST_DIG] = {
5584		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
5585		.init_verbs = { alc883_init_verbs },
5586		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
5587		.dac_nids = alc883_dac_nids,
5588		.dig_out_nid = ALC883_DIGOUT_NID,
5589		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5590		.adc_nids = alc883_adc_nids,
5591		.dig_in_nid = ALC883_DIGIN_NID,
5592		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
5593		.channel_mode = alc883_sixstack_modes,
5594		.input_mux = &alc883_capture_source,
5595	},
5596	[ALC883_TARGA_DIG] = {
5597		.mixers = { alc883_tagra_mixer, alc883_chmode_mixer },
5598		.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
5599		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
5600		.dac_nids = alc883_dac_nids,
5601		.dig_out_nid = ALC883_DIGOUT_NID,
5602		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5603		.adc_nids = alc883_adc_nids,
5604		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
5605		.channel_mode = alc883_3ST_6ch_modes,
5606		.need_dac_fix = 1,
5607		.input_mux = &alc883_capture_source,
5608		.unsol_event = alc883_tagra_unsol_event,
5609		.init_hook = alc883_tagra_automute,
5610	},
5611	[ALC883_TARGA_2ch_DIG] = {
5612		.mixers = { alc883_tagra_2ch_mixer},
5613		.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
5614		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
5615		.dac_nids = alc883_dac_nids,
5616		.dig_out_nid = ALC883_DIGOUT_NID,
5617		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5618		.adc_nids = alc883_adc_nids,
5619		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
5620		.channel_mode = alc883_3ST_2ch_modes,
5621		.input_mux = &alc883_capture_source,
5622		.unsol_event = alc883_tagra_unsol_event,
5623		.init_hook = alc883_tagra_automute,
5624	},
5625	[ALC888_DEMO_BOARD] = {
5626		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
5627		.init_verbs = { alc883_init_verbs },
5628		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
5629		.dac_nids = alc883_dac_nids,
5630		.dig_out_nid = ALC883_DIGOUT_NID,
5631		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5632		.adc_nids = alc883_adc_nids,
5633		.dig_in_nid = ALC883_DIGIN_NID,
5634		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
5635		.channel_mode = alc883_sixstack_modes,
5636		.input_mux = &alc883_capture_source,
5637	},
5638	[ALC883_ACER] = {
5639		.mixers = { alc883_base_mixer,
5640			    alc883_chmode_mixer },
5641		/* On TravelMate laptops, GPIO 0 enables the internal speaker
5642		 * and the headphone jack.  Turn this on and rely on the
5643		 * standard mute methods whenever the user wants to turn
5644		 * these outputs off.
5645		 */
5646		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
5647		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
5648		.dac_nids = alc883_dac_nids,
5649		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5650		.adc_nids = alc883_adc_nids,
5651		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
5652		.channel_mode = alc883_3ST_2ch_modes,
5653		.input_mux = &alc883_capture_source,
5654	},
5655	[ALC883_MEDION] = {
5656		.mixers = { alc883_fivestack_mixer,
5657			    alc883_chmode_mixer },
5658		.init_verbs = { alc883_init_verbs,
5659				alc883_medion_eapd_verbs },
5660		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
5661		.dac_nids = alc883_dac_nids,
5662		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5663		.adc_nids = alc883_adc_nids,
5664		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
5665		.channel_mode = alc883_sixstack_modes,
5666		.input_mux = &alc883_capture_source,
5667	},
5668	[ALC883_LAPTOP_EAPD] = {
5669		.mixers = { alc883_base_mixer,
5670			    alc883_chmode_mixer },
5671		.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
5672		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
5673		.dac_nids = alc883_dac_nids,
5674		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5675		.adc_nids = alc883_adc_nids,
5676		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
5677		.channel_mode = alc883_3ST_2ch_modes,
5678		.input_mux = &alc883_capture_source,
5679	},
5680};
5681
5682
5683/*
5684 * BIOS auto configuration
5685 */
5686static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
5687					      hda_nid_t nid, int pin_type,
5688					      int dac_idx)
5689{
5690	/* set as output */
5691	struct alc_spec *spec = codec->spec;
5692	int idx;
5693
5694	if (spec->multiout.dac_nids[dac_idx] == 0x25)
5695		idx = 4;
5696	else
5697		idx = spec->multiout.dac_nids[dac_idx] - 2;
5698
5699	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5700			    pin_type);
5701	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
5702			    AMP_OUT_UNMUTE);
5703	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
5704
5705}
5706
5707static void alc883_auto_init_multi_out(struct hda_codec *codec)
5708{
5709	struct alc_spec *spec = codec->spec;
5710	int i;
5711
5712	for (i = 0; i <= HDA_SIDE; i++) {
5713		hda_nid_t nid = spec->autocfg.line_out_pins[i];
5714		if (nid)
5715			alc883_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
5716	}
5717}
5718
5719static void alc883_auto_init_hp_out(struct hda_codec *codec)
5720{
5721	struct alc_spec *spec = codec->spec;
5722	hda_nid_t pin;
5723
5724	pin = spec->autocfg.hp_pins[0];
5725	if (pin) /* connect to front */
5726		/* use dac 0 */
5727		alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
5728}
5729
5730#define alc883_is_input_pin(nid)	alc880_is_input_pin(nid)
5731#define ALC883_PIN_CD_NID		ALC880_PIN_CD_NID
5732
5733static void alc883_auto_init_analog_input(struct hda_codec *codec)
5734{
5735	struct alc_spec *spec = codec->spec;
5736	int i;
5737
5738	for (i = 0; i < AUTO_PIN_LAST; i++) {
5739		hda_nid_t nid = spec->autocfg.input_pins[i];
5740		if (alc883_is_input_pin(nid)) {
5741			snd_hda_codec_write(codec, nid, 0,
5742					    AC_VERB_SET_PIN_WIDGET_CONTROL,
5743					    (i <= AUTO_PIN_FRONT_MIC ?
5744					     PIN_VREF80 : PIN_IN));
5745			if (nid != ALC883_PIN_CD_NID)
5746				snd_hda_codec_write(codec, nid, 0,
5747						    AC_VERB_SET_AMP_GAIN_MUTE,
5748						    AMP_OUT_MUTE);
5749		}
5750	}
5751}
5752
5753/* almost identical with ALC880 parser... */
5754static int alc883_parse_auto_config(struct hda_codec *codec)
5755{
5756	struct alc_spec *spec = codec->spec;
5757	int err = alc880_parse_auto_config(codec);
5758
5759	if (err < 0)
5760		return err;
5761	else if (err > 0)
5762		/* hack - override the init verbs */
5763		spec->init_verbs[0] = alc883_auto_init_verbs;
5764                spec->mixers[spec->num_mixers] = alc883_capture_mixer;
5765		spec->num_mixers++;
5766	return err;
5767}
5768
5769/* additional initialization for auto-configuration model */
5770static void alc883_auto_init(struct hda_codec *codec)
5771{
5772	alc883_auto_init_multi_out(codec);
5773	alc883_auto_init_hp_out(codec);
5774	alc883_auto_init_analog_input(codec);
5775}
5776
5777static int patch_alc883(struct hda_codec *codec)
5778{
5779	struct alc_spec *spec;
5780	int err, board_config;
5781
5782	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5783	if (spec == NULL)
5784		return -ENOMEM;
5785
5786	codec->spec = spec;
5787
5788	board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,
5789						  alc883_models,
5790						  alc883_cfg_tbl);
5791	if (board_config < 0) {
5792		printk(KERN_INFO "hda_codec: Unknown model for ALC883, "
5793		       "trying auto-probe from BIOS...\n");
5794		board_config = ALC883_AUTO;
5795	}
5796
5797	if (board_config == ALC883_AUTO) {
5798		/* automatic parse from the BIOS config */
5799		err = alc883_parse_auto_config(codec);
5800		if (err < 0) {
5801			alc_free(codec);
5802			return err;
5803		} else if (! err) {
5804			printk(KERN_INFO
5805			       "hda_codec: Cannot set up configuration "
5806			       "from BIOS.  Using base mode...\n");
5807			board_config = ALC883_3ST_2ch_DIG;
5808		}
5809	}
5810
5811	if (board_config != ALC883_AUTO)
5812		setup_preset(spec, &alc883_presets[board_config]);
5813
5814	spec->stream_name_analog = "ALC883 Analog";
5815	spec->stream_analog_playback = &alc883_pcm_analog_playback;
5816	spec->stream_analog_capture = &alc883_pcm_analog_capture;
5817
5818	spec->stream_name_digital = "ALC883 Digital";
5819	spec->stream_digital_playback = &alc883_pcm_digital_playback;
5820	spec->stream_digital_capture = &alc883_pcm_digital_capture;
5821
5822	if (! spec->adc_nids && spec->input_mux) {
5823		spec->adc_nids = alc883_adc_nids;
5824		spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
5825	}
5826
5827	codec->patch_ops = alc_patch_ops;
5828	if (board_config == ALC883_AUTO)
5829		spec->init_hook = alc883_auto_init;
5830
5831	return 0;
5832}
5833
5834/*
5835 * ALC262 support
5836 */
5837
5838#define ALC262_DIGOUT_NID	ALC880_DIGOUT_NID
5839#define ALC262_DIGIN_NID	ALC880_DIGIN_NID
5840
5841#define alc262_dac_nids		alc260_dac_nids
5842#define alc262_adc_nids		alc882_adc_nids
5843#define alc262_adc_nids_alt	alc882_adc_nids_alt
5844
5845#define alc262_modes		alc260_modes
5846#define alc262_capture_source	alc882_capture_source
5847
5848static struct snd_kcontrol_new alc262_base_mixer[] = {
5849	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5850	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5851	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5852	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5853	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5854	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5855	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5856	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5857	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
5858	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
5859	/* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
5860	   HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
5861	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
5862	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
5863	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5864	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
5865	{ } /* end */
5866};
5867
5868static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
5869	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5870	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5871	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5872	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5873	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5874	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5875	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5876	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5877	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
5878	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
5879	/* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
5880	   HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
5881	/*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
5882	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5883	{ } /* end */
5884};
5885
5886static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
5887	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5888	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
5889	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5890	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5891	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
5892
5893	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5894	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5895	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
5896	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
5897	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5898	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5899	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5900	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5901	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
5902	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
5903	HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
5904	HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
5905	{ } /* end */
5906};
5907
5908#define alc262_capture_mixer		alc882_capture_mixer
5909#define alc262_capture_alt_mixer	alc882_capture_alt_mixer
5910
5911/*
5912 * generic initialization of ADC, input mixers and output mixers
5913 */
5914static struct hda_verb alc262_init_verbs[] = {
5915	/*
5916	 * Unmute ADC0-2 and set the default input to mic-in
5917	 */
5918	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
5919	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5920	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
5921	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5922	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
5923	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5924
5925	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
5926	 * mixer widget
5927	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
5928	 * mic (mic 2)
5929	 */
5930	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
5931	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5932	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5933	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
5934	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
5935	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
5936
5937	/*
5938	 * Set up output mixers (0x0c - 0x0e)
5939	 */
5940	/* set vol=0 to output mixers */
5941	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5942	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5943	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5944	/* set up input amps for analog loopback */
5945	/* Amp Indices: DAC = 0, mixer = 1 */
5946	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5947	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5948	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5949	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5950	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5951	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5952
5953	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5954	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
5955	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5956	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5957	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5958	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5959
5960	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
5961	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
5962	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
5963	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
5964	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
5965
5966	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
5967	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
5968
5969	/* FIXME: use matrix-type input source selection */
5970	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
5971	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
5972	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5973	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
5974	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
5975	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
5976	/* Input mixer2 */
5977	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5978	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
5979	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
5980	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
5981	/* Input mixer3 */
5982	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5983	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
5984	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
5985	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
5986
5987	{ }
5988};
5989
5990static struct hda_verb alc262_hippo_unsol_verbs[] = {
5991	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5992	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5993	{}
5994};
5995
5996static struct hda_verb alc262_hippo1_unsol_verbs[] = {
5997	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
5998	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
5999	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6000
6001	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6002	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6003	{}
6004};
6005
6006/* mute/unmute internal speaker according to the hp jack and mute state */
6007static void alc262_hippo_automute(struct hda_codec *codec, int force)
6008{
6009	struct alc_spec *spec = codec->spec;
6010	unsigned int mute;
6011
6012	if (force || ! spec->sense_updated) {
6013		unsigned int present;
6014		/* need to execute and sync at first */
6015		snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
6016		present = snd_hda_codec_read(codec, 0x15, 0,
6017				    	 AC_VERB_GET_PIN_SENSE, 0);
6018		spec->jack_present = (present & 0x80000000) != 0;
6019		spec->sense_updated = 1;
6020	}
6021	if (spec->jack_present) {
6022		/* mute internal speaker */
6023		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6024					 0x80, 0x80);
6025		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6026					 0x80, 0x80);
6027	} else {
6028		/* unmute internal speaker if necessary */
6029		mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
6030		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6031					 0x80, mute & 0x80);
6032		mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0);
6033		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6034					 0x80, mute & 0x80);
6035	}
6036}
6037
6038/* unsolicited event for HP jack sensing */
6039static void alc262_hippo_unsol_event(struct hda_codec *codec,
6040				       unsigned int res)
6041{
6042	if ((res >> 26) != ALC880_HP_EVENT)
6043		return;
6044	alc262_hippo_automute(codec, 1);
6045}
6046
6047static void alc262_hippo1_automute(struct hda_codec *codec, int force)
6048{
6049	struct alc_spec *spec = codec->spec;
6050	unsigned int mute;
6051
6052	if (force || ! spec->sense_updated) {
6053		unsigned int present;
6054		/* need to execute and sync at first */
6055		snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
6056		present = snd_hda_codec_read(codec, 0x1b, 0,
6057				    	 AC_VERB_GET_PIN_SENSE, 0);
6058		spec->jack_present = (present & 0x80000000) != 0;
6059		spec->sense_updated = 1;
6060	}
6061	if (spec->jack_present) {
6062		/* mute internal speaker */
6063		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6064					 0x80, 0x80);
6065		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6066					 0x80, 0x80);
6067	} else {
6068		/* unmute internal speaker if necessary */
6069		mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
6070		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6071					 0x80, mute & 0x80);
6072		mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0);
6073		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6074					 0x80, mute & 0x80);
6075	}
6076}
6077
6078/* unsolicited event for HP jack sensing */
6079static void alc262_hippo1_unsol_event(struct hda_codec *codec,
6080				       unsigned int res)
6081{
6082	if ((res >> 26) != ALC880_HP_EVENT)
6083		return;
6084	alc262_hippo1_automute(codec, 1);
6085}
6086
6087/*
6088 * fujitsu model
6089 *  0x14 = headphone/spdif-out, 0x15 = internal speaker
6090 */
6091
6092#define ALC_HP_EVENT	0x37
6093
6094static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
6095	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
6096	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6097	{}
6098};
6099
6100static struct hda_input_mux alc262_fujitsu_capture_source = {
6101	.num_items = 2,
6102	.items = {
6103		{ "Mic", 0x0 },
6104		{ "CD", 0x4 },
6105	},
6106};
6107
6108static struct hda_input_mux alc262_HP_capture_source = {
6109	.num_items = 5,
6110	.items = {
6111		{ "Mic", 0x0 },
6112		{ "Front Mic", 0x3 },
6113		{ "Line", 0x2 },
6114		{ "CD", 0x4 },
6115		{ "AUX IN", 0x6 },
6116	},
6117};
6118
6119/* mute/unmute internal speaker according to the hp jack and mute state */
6120static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
6121{
6122	struct alc_spec *spec = codec->spec;
6123	unsigned int mute;
6124
6125	if (force || ! spec->sense_updated) {
6126		unsigned int present;
6127		/* need to execute and sync at first */
6128		snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
6129		present = snd_hda_codec_read(codec, 0x14, 0,
6130				    	 AC_VERB_GET_PIN_SENSE, 0);
6131		spec->jack_present = (present & 0x80000000) != 0;
6132		spec->sense_updated = 1;
6133	}
6134	if (spec->jack_present) {
6135		/* mute internal speaker */
6136		snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
6137					 0x80, 0x80);
6138		snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
6139					 0x80, 0x80);
6140	} else {
6141		/* unmute internal speaker if necessary */
6142		mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
6143		snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
6144					 0x80, mute & 0x80);
6145		mute = snd_hda_codec_amp_read(codec, 0x14, 1, HDA_OUTPUT, 0);
6146		snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
6147					 0x80, mute & 0x80);
6148	}
6149}
6150
6151/* unsolicited event for HP jack sensing */
6152static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
6153				       unsigned int res)
6154{
6155	if ((res >> 26) != ALC_HP_EVENT)
6156		return;
6157	alc262_fujitsu_automute(codec, 1);
6158}
6159
6160/* bind volumes of both NID 0x0c and 0x0d */
6161static int alc262_fujitsu_master_vol_put(struct snd_kcontrol *kcontrol,
6162					 struct snd_ctl_elem_value *ucontrol)
6163{
6164	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
6165	long *valp = ucontrol->value.integer.value;
6166	int change;
6167
6168	change = snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
6169					  0x7f, valp[0] & 0x7f);
6170	change |= snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
6171					   0x7f, valp[1] & 0x7f);
6172	snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
6173				 0x7f, valp[0] & 0x7f);
6174	snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
6175				 0x7f, valp[1] & 0x7f);
6176	return change;
6177}
6178
6179/* bind hp and internal speaker mute (with plug check) */
6180static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
6181					 struct snd_ctl_elem_value *ucontrol)
6182{
6183	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
6184	long *valp = ucontrol->value.integer.value;
6185	int change;
6186
6187	change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6188					  0x80, valp[0] ? 0 : 0x80);
6189	change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6190					   0x80, valp[1] ? 0 : 0x80);
6191	if (change || codec->in_resume)
6192		alc262_fujitsu_automute(codec, codec->in_resume);
6193	return change;
6194}
6195
6196static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
6197	{
6198		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6199		.name = "Master Playback Volume",
6200		.info = snd_hda_mixer_amp_volume_info,
6201		.get = snd_hda_mixer_amp_volume_get,
6202		.put = alc262_fujitsu_master_vol_put,
6203		.tlv = { .c = snd_hda_mixer_amp_tlv },
6204		.private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
6205	},
6206	{
6207		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6208		.name = "Master Playback Switch",
6209		.info = snd_hda_mixer_amp_switch_info,
6210		.get = snd_hda_mixer_amp_switch_get,
6211		.put = alc262_fujitsu_master_sw_put,
6212		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
6213	},
6214	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
6215	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
6216	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
6217	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
6218	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
6219	{ } /* end */
6220};
6221
6222/* additional init verbs for Benq laptops */
6223static struct hda_verb alc262_EAPD_verbs[] = {
6224	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
6225	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
6226	{}
6227};
6228
6229/* add playback controls from the parsed DAC table */
6230static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
6231{
6232	hda_nid_t nid;
6233	int err;
6234
6235	spec->multiout.num_dacs = 1;	/* only use one dac */
6236	spec->multiout.dac_nids = spec->private_dac_nids;
6237	spec->multiout.dac_nids[0] = 2;
6238
6239	nid = cfg->line_out_pins[0];
6240	if (nid) {
6241		if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Front Playback Volume",
6242				       HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
6243			return err;
6244		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Front Playback Switch",
6245				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
6246			return err;
6247	}
6248
6249	nid = cfg->speaker_pins[0];
6250	if (nid) {
6251		if (nid == 0x16) {
6252			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
6253					       HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
6254				return err;
6255			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
6256					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
6257				return err;
6258		} else {
6259			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
6260					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
6261				return err;
6262		}
6263	}
6264	nid = cfg->hp_pins[0];
6265	if (nid) {
6266		/* spec->multiout.hp_nid = 2; */
6267		if (nid == 0x16) {
6268			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
6269					       HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
6270				return err;
6271			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
6272					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
6273				return err;
6274		} else {
6275			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
6276					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
6277				return err;
6278		}
6279	}
6280	return 0;
6281}
6282
6283/* identical with ALC880 */
6284#define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls
6285
6286/*
6287 * generic initialization of ADC, input mixers and output mixers
6288 */
6289static struct hda_verb alc262_volume_init_verbs[] = {
6290	/*
6291	 * Unmute ADC0-2 and set the default input to mic-in
6292	 */
6293	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
6294	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6295	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
6296	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6297	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
6298	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6299
6300	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
6301	 * mixer widget
6302	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
6303	 * mic (mic 2)
6304	 */
6305	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
6306	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6307	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6308	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6309	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
6310	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6311
6312	/*
6313	 * Set up output mixers (0x0c - 0x0f)
6314	 */
6315	/* set vol=0 to output mixers */
6316	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6317	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6318	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6319
6320	/* set up input amps for analog loopback */
6321	/* Amp Indices: DAC = 0, mixer = 1 */
6322	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6323	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6324	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6325	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6326	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6327	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6328
6329	/* FIXME: use matrix-type input source selection */
6330	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
6331	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
6332	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6333	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6334	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6335	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6336	/* Input mixer2 */
6337	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6338	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6339	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6340	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6341	/* Input mixer3 */
6342	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6343	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
6344	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
6345	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
6346
6347	{ }
6348};
6349
6350static struct hda_verb alc262_HP_BPC_init_verbs[] = {
6351	/*
6352	 * Unmute ADC0-2 and set the default input to mic-in
6353	 */
6354	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
6355	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6356	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
6357	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6358	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
6359	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6360
6361	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
6362	 * mixer widget
6363	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
6364	 * mic (mic 2)
6365	 */
6366	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
6367	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6368	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6369	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6370	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
6371	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6372	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
6373        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
6374
6375	/*
6376	 * Set up output mixers (0x0c - 0x0e)
6377	 */
6378	/* set vol=0 to output mixers */
6379	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6380	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6381	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6382
6383	/* set up input amps for analog loopback */
6384	/* Amp Indices: DAC = 0, mixer = 1 */
6385	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6386	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6387	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6388	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6389	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6390	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6391
6392	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6393	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6394	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6395
6396	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6397	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6398
6399	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
6400	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
6401
6402	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6403	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6404        {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6405	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6406	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6407
6408	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
6409	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
6410        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
6411	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
6412	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
6413	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
6414
6415
6416	/* FIXME: use matrix-type input source selection */
6417	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
6418	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
6419	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6420	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
6421	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
6422	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
6423	/* Input mixer2 */
6424	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6425	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
6426	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
6427	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
6428	/* Input mixer3 */
6429	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6430	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
6431	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
6432	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
6433
6434	{ }
6435};
6436
6437/* pcm configuration: identiacal with ALC880 */
6438#define alc262_pcm_analog_playback	alc880_pcm_analog_playback
6439#define alc262_pcm_analog_capture	alc880_pcm_analog_capture
6440#define alc262_pcm_digital_playback	alc880_pcm_digital_playback
6441#define alc262_pcm_digital_capture	alc880_pcm_digital_capture
6442
6443/*
6444 * BIOS auto configuration
6445 */
6446static int alc262_parse_auto_config(struct hda_codec *codec)
6447{
6448	struct alc_spec *spec = codec->spec;
6449	int err;
6450	static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
6451
6452	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
6453						alc262_ignore)) < 0)
6454		return err;
6455	if (! spec->autocfg.line_outs)
6456		return 0; /* can't find valid BIOS pin config */
6457	if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
6458	    (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
6459		return err;
6460
6461	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
6462
6463	if (spec->autocfg.dig_out_pin)
6464		spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
6465	if (spec->autocfg.dig_in_pin)
6466		spec->dig_in_nid = ALC262_DIGIN_NID;
6467
6468	if (spec->kctl_alloc)
6469		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
6470
6471	spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
6472	spec->num_mux_defs = 1;
6473	spec->input_mux = &spec->private_imux;
6474
6475	return 1;
6476}
6477
6478#define alc262_auto_init_multi_out	alc882_auto_init_multi_out
6479#define alc262_auto_init_hp_out		alc882_auto_init_hp_out
6480#define alc262_auto_init_analog_input	alc882_auto_init_analog_input
6481
6482
6483/* init callback for auto-configuration model -- overriding the default init */
6484static void alc262_auto_init(struct hda_codec *codec)
6485{
6486	alc262_auto_init_multi_out(codec);
6487	alc262_auto_init_hp_out(codec);
6488	alc262_auto_init_analog_input(codec);
6489}
6490
6491/*
6492 * configuration and preset
6493 */
6494static const char *alc262_models[ALC262_MODEL_LAST] = {
6495	[ALC262_BASIC]		= "basic",
6496	[ALC262_HIPPO]		= "hippo",
6497	[ALC262_HIPPO_1]	= "hippo_1",
6498	[ALC262_FUJITSU]	= "fujitsu",
6499	[ALC262_HP_BPC]		= "hp-bpc",
6500	[ALC262_BENQ_ED8]	= "benq",
6501	[ALC262_AUTO]		= "auto",
6502};
6503
6504static struct snd_pci_quirk alc262_cfg_tbl[] = {
6505	SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
6506	SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC),
6507	SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
6508	SND_PCI_QUIRK(0x103c, 0x2801, "HP q954", ALC262_HP_BPC),
6509	SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
6510	SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
6511	SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
6512	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
6513	SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
6514	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
6515	{}
6516};
6517
6518static struct alc_config_preset alc262_presets[] = {
6519	[ALC262_BASIC] = {
6520		.mixers = { alc262_base_mixer },
6521		.init_verbs = { alc262_init_verbs },
6522		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
6523		.dac_nids = alc262_dac_nids,
6524		.hp_nid = 0x03,
6525		.num_channel_mode = ARRAY_SIZE(alc262_modes),
6526		.channel_mode = alc262_modes,
6527		.input_mux = &alc262_capture_source,
6528	},
6529	[ALC262_HIPPO] = {
6530		.mixers = { alc262_base_mixer },
6531		.init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},
6532		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
6533		.dac_nids = alc262_dac_nids,
6534		.hp_nid = 0x03,
6535		.dig_out_nid = ALC262_DIGOUT_NID,
6536		.num_channel_mode = ARRAY_SIZE(alc262_modes),
6537		.channel_mode = alc262_modes,
6538		.input_mux = &alc262_capture_source,
6539		.unsol_event = alc262_hippo_unsol_event,
6540	},
6541	[ALC262_HIPPO_1] = {
6542		.mixers = { alc262_hippo1_mixer },
6543		.init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
6544		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
6545		.dac_nids = alc262_dac_nids,
6546		.hp_nid = 0x02,
6547		.dig_out_nid = ALC262_DIGOUT_NID,
6548		.num_channel_mode = ARRAY_SIZE(alc262_modes),
6549		.channel_mode = alc262_modes,
6550		.input_mux = &alc262_capture_source,
6551		.unsol_event = alc262_hippo1_unsol_event,
6552	},
6553	[ALC262_FUJITSU] = {
6554		.mixers = { alc262_fujitsu_mixer },
6555		.init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs },
6556		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
6557		.dac_nids = alc262_dac_nids,
6558		.hp_nid = 0x03,
6559		.dig_out_nid = ALC262_DIGOUT_NID,
6560		.num_channel_mode = ARRAY_SIZE(alc262_modes),
6561		.channel_mode = alc262_modes,
6562		.input_mux = &alc262_fujitsu_capture_source,
6563		.unsol_event = alc262_fujitsu_unsol_event,
6564	},
6565	[ALC262_HP_BPC] = {
6566		.mixers = { alc262_HP_BPC_mixer },
6567		.init_verbs = { alc262_HP_BPC_init_verbs },
6568		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
6569		.dac_nids = alc262_dac_nids,
6570		.hp_nid = 0x03,
6571		.num_channel_mode = ARRAY_SIZE(alc262_modes),
6572		.channel_mode = alc262_modes,
6573		.input_mux = &alc262_HP_capture_source,
6574	},
6575	[ALC262_BENQ_ED8] = {
6576		.mixers = { alc262_base_mixer },
6577		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
6578		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
6579		.dac_nids = alc262_dac_nids,
6580		.hp_nid = 0x03,
6581		.num_channel_mode = ARRAY_SIZE(alc262_modes),
6582		.channel_mode = alc262_modes,
6583		.input_mux = &alc262_capture_source,
6584	},
6585};
6586
6587static int patch_alc262(struct hda_codec *codec)
6588{
6589	struct alc_spec *spec;
6590	int board_config;
6591	int err;
6592
6593	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6594	if (spec == NULL)
6595		return -ENOMEM;
6596
6597	codec->spec = spec;
6598#if 0
6599	/* pshou 07/11/05  set a zero PCM sample to DAC when FIFO is under-run */
6600	{
6601	int tmp;
6602	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
6603	tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
6604	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
6605	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
6606	}
6607#endif
6608
6609	board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
6610						  alc262_models,
6611						  alc262_cfg_tbl);
6612
6613	if (board_config < 0) {
6614		printk(KERN_INFO "hda_codec: Unknown model for ALC262, "
6615		       "trying auto-probe from BIOS...\n");
6616		board_config = ALC262_AUTO;
6617	}
6618
6619	if (board_config == ALC262_AUTO) {
6620		/* automatic parse from the BIOS config */
6621		err = alc262_parse_auto_config(codec);
6622		if (err < 0) {
6623			alc_free(codec);
6624			return err;
6625		} else if (! err) {
6626			printk(KERN_INFO
6627			       "hda_codec: Cannot set up configuration "
6628			       "from BIOS.  Using base mode...\n");
6629			board_config = ALC262_BASIC;
6630		}
6631	}
6632
6633	if (board_config != ALC262_AUTO)
6634		setup_preset(spec, &alc262_presets[board_config]);
6635
6636	spec->stream_name_analog = "ALC262 Analog";
6637	spec->stream_analog_playback = &alc262_pcm_analog_playback;
6638	spec->stream_analog_capture = &alc262_pcm_analog_capture;
6639
6640	spec->stream_name_digital = "ALC262 Digital";
6641	spec->stream_digital_playback = &alc262_pcm_digital_playback;
6642	spec->stream_digital_capture = &alc262_pcm_digital_capture;
6643
6644	if (! spec->adc_nids && spec->input_mux) {
6645		/* check whether NID 0x07 is valid */
6646		unsigned int wcap = get_wcaps(codec, 0x07);
6647
6648		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
6649		if (wcap != AC_WID_AUD_IN) {
6650			spec->adc_nids = alc262_adc_nids_alt;
6651			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
6652			spec->mixers[spec->num_mixers] = alc262_capture_alt_mixer;
6653			spec->num_mixers++;
6654		} else {
6655			spec->adc_nids = alc262_adc_nids;
6656			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
6657			spec->mixers[spec->num_mixers] = alc262_capture_mixer;
6658			spec->num_mixers++;
6659		}
6660	}
6661
6662	codec->patch_ops = alc_patch_ops;
6663	if (board_config == ALC262_AUTO)
6664		spec->init_hook = alc262_auto_init;
6665
6666	return 0;
6667}
6668
6669/*
6670 *  ALC861 channel source setting (2/6 channel selection for 3-stack)
6671 */
6672
6673/*
6674 * set the path ways for 2 channel output
6675 * need to set the codec line out and mic 1 pin widgets to inputs
6676 */
6677static struct hda_verb alc861_threestack_ch2_init[] = {
6678	/* set pin widget 1Ah (line in) for input */
6679	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
6680	/* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
6681	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
6682
6683	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
6684#if 0
6685	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
6686	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
6687#endif
6688	{ } /* end */
6689};
6690/*
6691 * 6ch mode
6692 * need to set the codec line out and mic 1 pin widgets to outputs
6693 */
6694static struct hda_verb alc861_threestack_ch6_init[] = {
6695	/* set pin widget 1Ah (line in) for output (Back Surround)*/
6696	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6697	/* set pin widget 18h (mic1) for output (CLFE)*/
6698	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6699
6700	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
6701	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
6702
6703	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
6704#if 0
6705	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
6706	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
6707#endif
6708	{ } /* end */
6709};
6710
6711static struct hda_channel_mode alc861_threestack_modes[2] = {
6712	{ 2, alc861_threestack_ch2_init },
6713	{ 6, alc861_threestack_ch6_init },
6714};
6715/* Set mic1 as input and unmute the mixer */
6716static struct hda_verb alc861_uniwill_m31_ch2_init[] = {
6717	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
6718	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
6719	{ } /* end */
6720};
6721/* Set mic1 as output and mute mixer */
6722static struct hda_verb alc861_uniwill_m31_ch4_init[] = {
6723	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6724	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
6725	{ } /* end */
6726};
6727
6728static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
6729	{ 2, alc861_uniwill_m31_ch2_init },
6730	{ 4, alc861_uniwill_m31_ch4_init },
6731};
6732
6733/* Set mic1 and line-in as input and unmute the mixer */
6734static struct hda_verb alc861_asus_ch2_init[] = {
6735	/* set pin widget 1Ah (line in) for input */
6736	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
6737	/* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
6738	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
6739
6740	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
6741#if 0
6742	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
6743	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
6744#endif
6745	{ } /* end */
6746};
6747/* Set mic1 nad line-in as output and mute mixer */
6748static struct hda_verb alc861_asus_ch6_init[] = {
6749	/* set pin widget 1Ah (line in) for output (Back Surround)*/
6750	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6751	/* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
6752	/* set pin widget 18h (mic1) for output (CLFE)*/
6753	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6754	/* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
6755	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
6756	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
6757
6758	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
6759#if 0
6760	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
6761	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
6762#endif
6763	{ } /* end */
6764};
6765
6766static struct hda_channel_mode alc861_asus_modes[2] = {
6767	{ 2, alc861_asus_ch2_init },
6768	{ 6, alc861_asus_ch6_init },
6769};
6770
6771/* patch-ALC861 */
6772
6773static struct snd_kcontrol_new alc861_base_mixer[] = {
6774        /* output mixer control */
6775	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
6776	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
6777	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
6778	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
6779	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
6780
6781        /*Input mixer control */
6782	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
6783	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
6784	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
6785	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
6786	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
6787	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
6788	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
6789	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
6790	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
6791	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
6792
6793        /* Capture mixer control */
6794	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
6795	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
6796	{
6797		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6798		.name = "Capture Source",
6799		.count = 1,
6800		.info = alc_mux_enum_info,
6801		.get = alc_mux_enum_get,
6802		.put = alc_mux_enum_put,
6803	},
6804	{ } /* end */
6805};
6806
6807static struct snd_kcontrol_new alc861_3ST_mixer[] = {
6808        /* output mixer control */
6809	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
6810	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
6811	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
6812	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
6813	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
6814
6815	/* Input mixer control */
6816	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
6817	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
6818	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
6819	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
6820	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
6821	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
6822	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
6823	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
6824	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
6825	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
6826
6827	/* Capture mixer control */
6828	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
6829	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
6830	{
6831		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6832		.name = "Capture Source",
6833		.count = 1,
6834		.info = alc_mux_enum_info,
6835		.get = alc_mux_enum_get,
6836		.put = alc_mux_enum_put,
6837	},
6838	{
6839		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6840		.name = "Channel Mode",
6841		.info = alc_ch_mode_info,
6842		.get = alc_ch_mode_get,
6843		.put = alc_ch_mode_put,
6844                .private_value = ARRAY_SIZE(alc861_threestack_modes),
6845	},
6846	{ } /* end */
6847};
6848
6849static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
6850        /* output mixer control */
6851	HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
6852	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
6853	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
6854
6855        /*Capture mixer control */
6856	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
6857	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
6858	{
6859		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6860		.name = "Capture Source",
6861		.count = 1,
6862		.info = alc_mux_enum_info,
6863		.get = alc_mux_enum_get,
6864		.put = alc_mux_enum_put,
6865	},
6866
6867	{ } /* end */
6868};
6869
6870static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
6871        /* output mixer control */
6872	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
6873	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
6874	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
6875	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
6876	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
6877
6878	/* Input mixer control */
6879	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
6880	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
6881	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
6882	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
6883	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
6884	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
6885	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
6886	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
6887	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
6888	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
6889
6890	/* Capture mixer control */
6891	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
6892	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
6893	{
6894		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6895		.name = "Capture Source",
6896		.count = 1,
6897		.info = alc_mux_enum_info,
6898		.get = alc_mux_enum_get,
6899		.put = alc_mux_enum_put,
6900	},
6901	{
6902		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6903		.name = "Channel Mode",
6904		.info = alc_ch_mode_info,
6905		.get = alc_ch_mode_get,
6906		.put = alc_ch_mode_put,
6907                .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
6908	},
6909	{ } /* end */
6910};
6911
6912static struct snd_kcontrol_new alc861_asus_mixer[] = {
6913        /* output mixer control */
6914	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
6915	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
6916	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
6917	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
6918	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
6919
6920	/* Input mixer control */
6921	HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
6922	HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
6923	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
6924	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
6925	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
6926	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
6927	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
6928	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
6929	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
6930	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), /* was HDA_INPUT (why?) */
6931
6932	/* Capture mixer control */
6933	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
6934	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
6935	{
6936		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6937		.name = "Capture Source",
6938		.count = 1,
6939		.info = alc_mux_enum_info,
6940		.get = alc_mux_enum_get,
6941		.put = alc_mux_enum_put,
6942	},
6943	{
6944		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6945		.name = "Channel Mode",
6946		.info = alc_ch_mode_info,
6947		.get = alc_ch_mode_get,
6948		.put = alc_ch_mode_put,
6949                .private_value = ARRAY_SIZE(alc861_asus_modes),
6950	},
6951	{ }
6952};
6953
6954/* additional mixer */
6955static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
6956	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
6957	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
6958	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT),
6959	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT),
6960	{ }
6961};
6962
6963/*
6964 * generic initialization of ADC, input mixers and output mixers
6965 */
6966static struct hda_verb alc861_base_init_verbs[] = {
6967	/*
6968	 * Unmute ADC0 and set the default input to mic-in
6969	 */
6970	/* port-A for surround (rear panel) */
6971	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6972	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
6973	/* port-B for mic-in (rear panel) with vref */
6974	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
6975	/* port-C for line-in (rear panel) */
6976	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
6977	/* port-D for Front */
6978	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6979	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
6980	/* port-E for HP out (front panel) */
6981	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
6982	/* route front PCM to HP */
6983	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
6984	/* port-F for mic-in (front panel) with vref */
6985	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
6986	/* port-G for CLFE (rear panel) */
6987	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6988	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
6989	/* port-H for side (rear panel) */
6990	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6991	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
6992	/* CD-in */
6993	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
6994	/* route front mic to ADC1*/
6995	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
6996	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6997
6998	/* Unmute DAC0~3 & spdif out*/
6999	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7000	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7001	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7002	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7003	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7004
7005	/* Unmute Mixer 14 (mic) 1c (Line in)*/
7006	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7007        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7008	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7009        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7010
7011	/* Unmute Stereo Mixer 15 */
7012	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7013	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7014	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7015	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, //Output 0~12 step
7016
7017	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7018	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7019	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7020	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7021	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7022	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7023	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7024	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7025	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
7026        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7027
7028	{ }
7029};
7030
7031static struct hda_verb alc861_threestack_init_verbs[] = {
7032	/*
7033	 * Unmute ADC0 and set the default input to mic-in
7034	 */
7035	/* port-A for surround (rear panel) */
7036	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7037	/* port-B for mic-in (rear panel) with vref */
7038	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7039	/* port-C for line-in (rear panel) */
7040	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7041	/* port-D for Front */
7042	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7043	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
7044	/* port-E for HP out (front panel) */
7045	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
7046	/* route front PCM to HP */
7047	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
7048	/* port-F for mic-in (front panel) with vref */
7049	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7050	/* port-G for CLFE (rear panel) */
7051	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7052	/* port-H for side (rear panel) */
7053	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7054	/* CD-in */
7055	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7056	/* route front mic to ADC1*/
7057	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7058	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7059	/* Unmute DAC0~3 & spdif out*/
7060	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7061	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7062	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7063	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7064	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7065
7066	/* Unmute Mixer 14 (mic) 1c (Line in)*/
7067	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7068        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7069	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7070        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7071
7072	/* Unmute Stereo Mixer 15 */
7073	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7074	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7075	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7076	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, //Output 0~12 step
7077
7078	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7079	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7080	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7081	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7082	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7083	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7084	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7085	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7086	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
7087        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7088	{ }
7089};
7090
7091static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
7092	/*
7093	 * Unmute ADC0 and set the default input to mic-in
7094	 */
7095	/* port-A for surround (rear panel) */
7096	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7097	/* port-B for mic-in (rear panel) with vref */
7098	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7099	/* port-C for line-in (rear panel) */
7100	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7101	/* port-D for Front */
7102	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7103	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
7104	/* port-E for HP out (front panel) */
7105	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, // this has to be set to VREF80
7106	/* route front PCM to HP */
7107	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
7108	/* port-F for mic-in (front panel) with vref */
7109	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7110	/* port-G for CLFE (rear panel) */
7111	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7112	/* port-H for side (rear panel) */
7113	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7114	/* CD-in */
7115	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7116	/* route front mic to ADC1*/
7117	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7118	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7119	/* Unmute DAC0~3 & spdif out*/
7120	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7121	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7122	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7123	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7124	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7125
7126	/* Unmute Mixer 14 (mic) 1c (Line in)*/
7127	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7128        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7129	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7130        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7131
7132	/* Unmute Stereo Mixer 15 */
7133	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7134	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7135	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7136	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, //Output 0~12 step
7137
7138	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7139	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7140	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7141	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7142	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7143	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7144	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7145	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7146	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
7147        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7148	{ }
7149};
7150
7151static struct hda_verb alc861_asus_init_verbs[] = {
7152	/*
7153	 * Unmute ADC0 and set the default input to mic-in
7154	 */
7155	/* port-A for surround (rear panel) | according to codec#0 this is the HP jack*/
7156	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
7157	/* route front PCM to HP */
7158	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
7159	/* port-B for mic-in (rear panel) with vref */
7160	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7161	/* port-C for line-in (rear panel) */
7162	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7163	/* port-D for Front */
7164	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7165	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
7166	/* port-E for HP out (front panel) */
7167	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* this has to be set to VREF80 */
7168	/* route front PCM to HP */
7169	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
7170	/* port-F for mic-in (front panel) with vref */
7171	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7172	/* port-G for CLFE (rear panel) */
7173	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7174	/* port-H for side (rear panel) */
7175	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7176	/* CD-in */
7177	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7178	/* route front mic to ADC1*/
7179	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7180	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7181	/* Unmute DAC0~3 & spdif out*/
7182	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7183	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7184	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7185	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7186	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7187	/* Unmute Mixer 14 (mic) 1c (Line in)*/
7188	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7189        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7190	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7191        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7192
7193	/* Unmute Stereo Mixer 15 */
7194	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7195	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7196	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7197	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, /* Output 0~12 step */
7198
7199	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7200	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7201	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7202	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7203	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7204	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7205	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7206	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7207	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, /* hp used DAC 3 (Front) */
7208	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7209	{ }
7210};
7211
7212/* additional init verbs for ASUS laptops */
7213static struct hda_verb alc861_asus_laptop_init_verbs[] = {
7214	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
7215	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
7216	{ }
7217};
7218
7219/*
7220 * generic initialization of ADC, input mixers and output mixers
7221 */
7222static struct hda_verb alc861_auto_init_verbs[] = {
7223	/*
7224	 * Unmute ADC0 and set the default input to mic-in
7225	 */
7226//	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7227	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7228
7229	/* Unmute DAC0~3 & spdif out*/
7230	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7231	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7232	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7233	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7234	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7235
7236	/* Unmute Mixer 14 (mic) 1c (Line in)*/
7237	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7238	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7239	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7240	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7241
7242	/* Unmute Stereo Mixer 15 */
7243	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7244	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7245	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7246	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
7247
7248	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7249	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7250	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7251	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7252	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7253	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7254	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7255	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7256
7257	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7258	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7259	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7260	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7261	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7262	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7263	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7264	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7265
7266	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},	// set Mic 1
7267
7268	{ }
7269};
7270
7271static struct hda_verb alc861_toshiba_init_verbs[] = {
7272	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
7273
7274	{ }
7275};
7276
7277/* toggle speaker-output according to the hp-jack state */
7278static void alc861_toshiba_automute(struct hda_codec *codec)
7279{
7280	unsigned int present;
7281
7282	present = snd_hda_codec_read(codec, 0x0f, 0,
7283				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7284	snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0,
7285				 0x80, present ? 0x80 : 0);
7286	snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0,
7287				 0x80, present ? 0x80 : 0);
7288	snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3,
7289				 0x80, present ? 0 : 0x80);
7290	snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3,
7291				 0x80, present ? 0 : 0x80);
7292}
7293
7294static void alc861_toshiba_unsol_event(struct hda_codec *codec,
7295				       unsigned int res)
7296{
7297	/* Looks like the unsol event is incompatible with the standard
7298	 * definition.  6bit tag is placed at 26 bit!
7299	 */
7300	if ((res >> 26) == ALC880_HP_EVENT)
7301		alc861_toshiba_automute(codec);
7302}
7303
7304/* pcm configuration: identiacal with ALC880 */
7305#define alc861_pcm_analog_playback	alc880_pcm_analog_playback
7306#define alc861_pcm_analog_capture	alc880_pcm_analog_capture
7307#define alc861_pcm_digital_playback	alc880_pcm_digital_playback
7308#define alc861_pcm_digital_capture	alc880_pcm_digital_capture
7309
7310
7311#define ALC861_DIGOUT_NID	0x07
7312
7313static struct hda_channel_mode alc861_8ch_modes[1] = {
7314	{ 8, NULL }
7315};
7316
7317static hda_nid_t alc861_dac_nids[4] = {
7318	/* front, surround, clfe, side */
7319	0x03, 0x06, 0x05, 0x04
7320};
7321
7322static hda_nid_t alc660_dac_nids[3] = {
7323	/* front, clfe, surround */
7324	0x03, 0x05, 0x06
7325};
7326
7327static hda_nid_t alc861_adc_nids[1] = {
7328	/* ADC0-2 */
7329	0x08,
7330};
7331
7332static struct hda_input_mux alc861_capture_source = {
7333	.num_items = 5,
7334	.items = {
7335		{ "Mic", 0x0 },
7336		{ "Front Mic", 0x3 },
7337		{ "Line", 0x1 },
7338		{ "CD", 0x4 },
7339		{ "Mixer", 0x5 },
7340	},
7341};
7342
7343/* fill in the dac_nids table from the parsed pin configuration */
7344static int alc861_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
7345{
7346	int i;
7347	hda_nid_t nid;
7348
7349	spec->multiout.dac_nids = spec->private_dac_nids;
7350	for (i = 0; i < cfg->line_outs; i++) {
7351		nid = cfg->line_out_pins[i];
7352		if (nid) {
7353			if (i >= ARRAY_SIZE(alc861_dac_nids))
7354				continue;
7355			spec->multiout.dac_nids[i] = alc861_dac_nids[i];
7356		}
7357	}
7358	spec->multiout.num_dacs = cfg->line_outs;
7359	return 0;
7360}
7361
7362/* add playback controls from the parsed DAC table */
7363static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
7364					     const struct auto_pin_cfg *cfg)
7365{
7366	char name[32];
7367	static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
7368	hda_nid_t nid;
7369	int i, idx, err;
7370
7371	for (i = 0; i < cfg->line_outs; i++) {
7372		nid = spec->multiout.dac_nids[i];
7373		if (! nid)
7374			continue;
7375		if (nid == 0x05) {
7376			/* Center/LFE */
7377			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
7378					       HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
7379				return err;
7380			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
7381					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
7382				return err;
7383		} else {
7384			for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; idx++)
7385				if (nid == alc861_dac_nids[idx])
7386					break;
7387			sprintf(name, "%s Playback Switch", chname[idx]);
7388			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
7389					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
7390				return err;
7391		}
7392	}
7393	return 0;
7394}
7395
7396static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
7397{
7398	int err;
7399	hda_nid_t nid;
7400
7401	if (! pin)
7402		return 0;
7403
7404	if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
7405		nid = 0x03;
7406		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
7407				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
7408			return err;
7409		spec->multiout.hp_nid = nid;
7410	}
7411	return 0;
7412}
7413
7414/* create playback/capture controls for input pins */
7415static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
7416{
7417	struct hda_input_mux *imux = &spec->private_imux;
7418	int i, err, idx, idx1;
7419
7420	for (i = 0; i < AUTO_PIN_LAST; i++) {
7421		switch(cfg->input_pins[i]) {
7422		case 0x0c:
7423			idx1 = 1;
7424			idx = 2;	// Line In
7425			break;
7426		case 0x0f:
7427			idx1 = 2;
7428			idx = 2;	// Line In
7429			break;
7430		case 0x0d:
7431			idx1 = 0;
7432			idx = 1;	// Mic In
7433			break;
7434		case 0x10:
7435			idx1 = 3;
7436			idx = 1;	// Mic In
7437			break;
7438		case 0x11:
7439			idx1 = 4;
7440			idx = 0;	// CD
7441			break;
7442		default:
7443			continue;
7444		}
7445
7446		err = new_analog_input(spec, cfg->input_pins[i],
7447				       auto_pin_cfg_labels[i], idx, 0x15);
7448		if (err < 0)
7449			return err;
7450
7451		imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
7452		imux->items[imux->num_items].index = idx1;
7453		imux->num_items++;
7454	}
7455	return 0;
7456}
7457
7458static struct snd_kcontrol_new alc861_capture_mixer[] = {
7459	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7460	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7461
7462	{
7463		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7464		/* The multiple "Capture Source" controls confuse alsamixer
7465		 * So call somewhat different..
7466		 *FIXME: the controls appear in the "playback" view!
7467		 */
7468		/* .name = "Capture Source", */
7469		.name = "Input Source",
7470		.count = 1,
7471		.info = alc_mux_enum_info,
7472		.get = alc_mux_enum_get,
7473		.put = alc_mux_enum_put,
7474	},
7475	{ } /* end */
7476};
7477
7478static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid,
7479					      int pin_type, int dac_idx)
7480{
7481	/* set as output */
7482
7483	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
7484	snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
7485
7486}
7487
7488static void alc861_auto_init_multi_out(struct hda_codec *codec)
7489{
7490	struct alc_spec *spec = codec->spec;
7491	int i;
7492
7493	for (i = 0; i < spec->autocfg.line_outs; i++) {
7494		hda_nid_t nid = spec->autocfg.line_out_pins[i];
7495		if (nid)
7496			alc861_auto_set_output_and_unmute(codec, nid, PIN_OUT, spec->multiout.dac_nids[i]);
7497	}
7498}
7499
7500static void alc861_auto_init_hp_out(struct hda_codec *codec)
7501{
7502	struct alc_spec *spec = codec->spec;
7503	hda_nid_t pin;
7504
7505	pin = spec->autocfg.hp_pins[0];
7506	if (pin) /* connect to front */
7507		alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]);
7508}
7509
7510static void alc861_auto_init_analog_input(struct hda_codec *codec)
7511{
7512	struct alc_spec *spec = codec->spec;
7513	int i;
7514
7515	for (i = 0; i < AUTO_PIN_LAST; i++) {
7516		hda_nid_t nid = spec->autocfg.input_pins[i];
7517		if ((nid>=0x0c) && (nid <=0x11)) {
7518			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
7519					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
7520		}
7521	}
7522}
7523
7524/* parse the BIOS configuration and set up the alc_spec */
7525/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
7526static int alc861_parse_auto_config(struct hda_codec *codec)
7527{
7528	struct alc_spec *spec = codec->spec;
7529	int err;
7530	static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
7531
7532	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
7533						alc861_ignore)) < 0)
7534		return err;
7535	if (! spec->autocfg.line_outs)
7536		return 0; /* can't find valid BIOS pin config */
7537
7538	if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
7539	    (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
7540	    (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0])) < 0 ||
7541	    (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
7542		return err;
7543
7544	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
7545
7546	if (spec->autocfg.dig_out_pin)
7547		spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
7548
7549	if (spec->kctl_alloc)
7550		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
7551
7552	spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
7553
7554	spec->num_mux_defs = 1;
7555	spec->input_mux = &spec->private_imux;
7556
7557	spec->adc_nids = alc861_adc_nids;
7558	spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
7559	spec->mixers[spec->num_mixers] = alc861_capture_mixer;
7560	spec->num_mixers++;
7561
7562	return 1;
7563}
7564
7565/* additional initialization for auto-configuration model */
7566static void alc861_auto_init(struct hda_codec *codec)
7567{
7568	alc861_auto_init_multi_out(codec);
7569	alc861_auto_init_hp_out(codec);
7570	alc861_auto_init_analog_input(codec);
7571}
7572
7573
7574/*
7575 * configuration and preset
7576 */
7577static const char *alc861_models[ALC861_MODEL_LAST] = {
7578	[ALC861_3ST]		= "3stack",
7579	[ALC660_3ST]		= "3stack-660",
7580	[ALC861_3ST_DIG]	= "3stack-dig",
7581	[ALC861_6ST_DIG]	= "6stack-dig",
7582	[ALC861_UNIWILL_M31]	= "uniwill-m31",
7583	[ALC861_TOSHIBA]	= "toshiba",
7584	[ALC861_ASUS]		= "asus",
7585	[ALC861_ASUS_LAPTOP]	= "asus-laptop",
7586	[ALC861_AUTO]		= "auto",
7587};
7588
7589static struct snd_pci_quirk alc861_cfg_tbl[] = {
7590	SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
7591	SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
7592	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
7593	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660_3ST),
7594	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA),
7595	SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
7596	SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
7597	{}
7598};
7599
7600static struct alc_config_preset alc861_presets[] = {
7601	[ALC861_3ST] = {
7602		.mixers = { alc861_3ST_mixer },
7603		.init_verbs = { alc861_threestack_init_verbs },
7604		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
7605		.dac_nids = alc861_dac_nids,
7606		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
7607		.channel_mode = alc861_threestack_modes,
7608		.need_dac_fix = 1,
7609		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7610		.adc_nids = alc861_adc_nids,
7611		.input_mux = &alc861_capture_source,
7612	},
7613	[ALC861_3ST_DIG] = {
7614		.mixers = { alc861_base_mixer },
7615		.init_verbs = { alc861_threestack_init_verbs },
7616		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
7617		.dac_nids = alc861_dac_nids,
7618		.dig_out_nid = ALC861_DIGOUT_NID,
7619		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
7620		.channel_mode = alc861_threestack_modes,
7621		.need_dac_fix = 1,
7622		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7623		.adc_nids = alc861_adc_nids,
7624		.input_mux = &alc861_capture_source,
7625	},
7626	[ALC861_6ST_DIG] = {
7627		.mixers = { alc861_base_mixer },
7628		.init_verbs = { alc861_base_init_verbs },
7629		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
7630		.dac_nids = alc861_dac_nids,
7631		.dig_out_nid = ALC861_DIGOUT_NID,
7632		.num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
7633		.channel_mode = alc861_8ch_modes,
7634		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7635		.adc_nids = alc861_adc_nids,
7636		.input_mux = &alc861_capture_source,
7637	},
7638	[ALC660_3ST] = {
7639		.mixers = { alc861_3ST_mixer },
7640		.init_verbs = { alc861_threestack_init_verbs },
7641		.num_dacs = ARRAY_SIZE(alc660_dac_nids),
7642		.dac_nids = alc660_dac_nids,
7643		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
7644		.channel_mode = alc861_threestack_modes,
7645		.need_dac_fix = 1,
7646		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7647		.adc_nids = alc861_adc_nids,
7648		.input_mux = &alc861_capture_source,
7649	},
7650	[ALC861_UNIWILL_M31] = {
7651		.mixers = { alc861_uniwill_m31_mixer },
7652		.init_verbs = { alc861_uniwill_m31_init_verbs },
7653		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
7654		.dac_nids = alc861_dac_nids,
7655		.dig_out_nid = ALC861_DIGOUT_NID,
7656		.num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
7657		.channel_mode = alc861_uniwill_m31_modes,
7658		.need_dac_fix = 1,
7659		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7660		.adc_nids = alc861_adc_nids,
7661		.input_mux = &alc861_capture_source,
7662	},
7663	[ALC861_TOSHIBA] = {
7664		.mixers = { alc861_toshiba_mixer },
7665		.init_verbs = { alc861_base_init_verbs, alc861_toshiba_init_verbs },
7666		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
7667		.dac_nids = alc861_dac_nids,
7668		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
7669		.channel_mode = alc883_3ST_2ch_modes,
7670		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7671		.adc_nids = alc861_adc_nids,
7672		.input_mux = &alc861_capture_source,
7673		.unsol_event = alc861_toshiba_unsol_event,
7674		.init_hook = alc861_toshiba_automute,
7675	},
7676	[ALC861_ASUS] = {
7677		.mixers = { alc861_asus_mixer },
7678		.init_verbs = { alc861_asus_init_verbs },
7679		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
7680		.dac_nids = alc861_dac_nids,
7681		.dig_out_nid = ALC861_DIGOUT_NID,
7682		.num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
7683		.channel_mode = alc861_asus_modes,
7684		.need_dac_fix = 1,
7685		.hp_nid = 0x06,
7686		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7687		.adc_nids = alc861_adc_nids,
7688		.input_mux = &alc861_capture_source,
7689	},
7690	[ALC861_ASUS_LAPTOP] = {
7691		.mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
7692		.init_verbs = { alc861_asus_init_verbs,
7693				alc861_asus_laptop_init_verbs },
7694		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
7695		.dac_nids = alc861_dac_nids,
7696		.dig_out_nid = ALC861_DIGOUT_NID,
7697		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
7698		.channel_mode = alc883_3ST_2ch_modes,
7699		.need_dac_fix = 1,
7700		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7701		.adc_nids = alc861_adc_nids,
7702		.input_mux = &alc861_capture_source,
7703	},
7704};
7705
7706
7707static int patch_alc861(struct hda_codec *codec)
7708{
7709	struct alc_spec *spec;
7710	int board_config;
7711	int err;
7712
7713	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
7714	if (spec == NULL)
7715		return -ENOMEM;
7716
7717	codec->spec = spec;
7718
7719        board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
7720						  alc861_models,
7721						  alc861_cfg_tbl);
7722
7723	if (board_config < 0) {
7724		printk(KERN_INFO "hda_codec: Unknown model for ALC861, "
7725		       "trying auto-probe from BIOS...\n");
7726		board_config = ALC861_AUTO;
7727	}
7728
7729	if (board_config == ALC861_AUTO) {
7730		/* automatic parse from the BIOS config */
7731		err = alc861_parse_auto_config(codec);
7732		if (err < 0) {
7733			alc_free(codec);
7734			return err;
7735		} else if (! err) {
7736			printk(KERN_INFO
7737			       "hda_codec: Cannot set up configuration "
7738			       "from BIOS.  Using base mode...\n");
7739		   board_config = ALC861_3ST_DIG;
7740		}
7741	}
7742
7743	if (board_config != ALC861_AUTO)
7744		setup_preset(spec, &alc861_presets[board_config]);
7745
7746	spec->stream_name_analog = "ALC861 Analog";
7747	spec->stream_analog_playback = &alc861_pcm_analog_playback;
7748	spec->stream_analog_capture = &alc861_pcm_analog_capture;
7749
7750	spec->stream_name_digital = "ALC861 Digital";
7751	spec->stream_digital_playback = &alc861_pcm_digital_playback;
7752	spec->stream_digital_capture = &alc861_pcm_digital_capture;
7753
7754	codec->patch_ops = alc_patch_ops;
7755	if (board_config == ALC861_AUTO)
7756		spec->init_hook = alc861_auto_init;
7757
7758	return 0;
7759}
7760
7761/*
7762 * patch entries
7763 */
7764struct hda_codec_preset snd_hda_preset_realtek[] = {
7765	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
7766	{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
7767 	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
7768	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
7769	{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
7770	{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
7771	{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
7772	{ .id = 0x10ec0861, .rev = 0x100300, .name = "ALC861",
7773	  .patch = patch_alc861 },
7774	{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
7775	  .patch = patch_alc861 },
7776	{ .id = 0x10ec0660, .name = "ALC660", .patch = patch_alc861 },
7777	{} /* terminator */
7778};
7779