patch_realtek.c revision 8b33a5aa08c4e462360d812386dcecc0467efd7b
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 *
10 *  This driver is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License as published by
12 *  the Free Software Foundation; either version 2 of the License, or
13 *  (at your option) any later version.
14 *
15 *  This driver is distributed in the hope that it will be useful,
16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *  GNU General Public License for more details.
19 *
20 *  You should have received a copy of the GNU General Public License
21 *  along with this program; if not, write to the Free Software
22 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23 */
24
25#include <sound/driver.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
30#include <sound/core.h>
31#include "hda_codec.h"
32#include "hda_local.h"
33
34
35/* ALC880 board config type */
36enum {
37	ALC880_3ST,
38	ALC880_3ST_DIG,
39	ALC880_5ST,
40	ALC880_5ST_DIG,
41	ALC880_W810,
42	ALC880_Z71V,
43	ALC880_6ST,
44	ALC880_6ST_DIG,
45	ALC880_F1734,
46	ALC880_ASUS,
47	ALC880_ASUS_DIG,
48	ALC880_ASUS_W1V,
49	ALC880_ASUS_DIG2,
50	ALC880_UNIWILL_DIG,
51	ALC880_CLEVO,
52	ALC880_TCL_S700,
53#ifdef CONFIG_SND_DEBUG
54	ALC880_TEST,
55#endif
56	ALC880_AUTO,
57	ALC880_MODEL_LAST /* last tag */
58};
59
60/* ALC260 models */
61enum {
62	ALC260_BASIC,
63	ALC260_HP,
64	ALC260_HP_3013,
65	ALC260_FUJITSU_S702X,
66	ALC260_AUTO,
67	ALC260_MODEL_LAST /* last tag */
68};
69
70/* ALC262 models */
71enum {
72	ALC262_BASIC,
73	ALC262_AUTO,
74	ALC262_MODEL_LAST /* last tag */
75};
76
77/* ALC861 models */
78enum {
79	ALC861_3ST,
80	ALC861_3ST_DIG,
81	ALC861_6ST_DIG,
82	ALC861_AUTO,
83	ALC861_MODEL_LAST,
84};
85
86/* ALC882 models */
87enum {
88	ALC882_3ST_DIG,
89	ALC882_6ST_DIG,
90	ALC882_AUTO,
91	ALC882_MODEL_LAST,
92};
93
94/* for GPIO Poll */
95#define GPIO_MASK	0x03
96
97struct alc_spec {
98	/* codec parameterization */
99	struct snd_kcontrol_new *mixers[5];	/* mixer arrays */
100	unsigned int num_mixers;
101
102	const struct hda_verb *init_verbs[5];	/* initialization verbs
103						 * don't forget NULL termination!
104						 */
105	unsigned int num_init_verbs;
106
107	char *stream_name_analog;	/* analog PCM stream */
108	struct hda_pcm_stream *stream_analog_playback;
109	struct hda_pcm_stream *stream_analog_capture;
110
111	char *stream_name_digital;	/* digital PCM stream */
112	struct hda_pcm_stream *stream_digital_playback;
113	struct hda_pcm_stream *stream_digital_capture;
114
115	/* playback */
116	struct hda_multi_out multiout;	/* playback set-up
117					 * max_channels, dacs must be set
118					 * dig_out_nid and hp_nid are optional
119					 */
120
121	/* capture */
122	unsigned int num_adc_nids;
123	hda_nid_t *adc_nids;
124	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
125
126	/* capture source */
127	const struct hda_input_mux *input_mux;
128	unsigned int cur_mux[3];
129
130	/* channel model */
131	const struct hda_channel_mode *channel_mode;
132	int num_channel_mode;
133
134	/* PCM information */
135	struct hda_pcm pcm_rec[3];	/* used in alc_build_pcms() */
136
137	/* dynamic controls, init_verbs and input_mux */
138	struct auto_pin_cfg autocfg;
139	unsigned int num_kctl_alloc, num_kctl_used;
140	struct snd_kcontrol_new *kctl_alloc;
141	struct hda_input_mux private_imux;
142	hda_nid_t private_dac_nids[5];
143};
144
145/*
146 * configuration template - to be copied to the spec instance
147 */
148struct alc_config_preset {
149	struct snd_kcontrol_new *mixers[5]; /* should be identical size with spec */
150	const struct hda_verb *init_verbs[5];
151	unsigned int num_dacs;
152	hda_nid_t *dac_nids;
153	hda_nid_t dig_out_nid;		/* optional */
154	hda_nid_t hp_nid;		/* optional */
155	unsigned int num_adc_nids;
156	hda_nid_t *adc_nids;
157	hda_nid_t dig_in_nid;
158	unsigned int num_channel_mode;
159	const struct hda_channel_mode *channel_mode;
160	const struct hda_input_mux *input_mux;
161};
162
163
164/*
165 * input MUX handling
166 */
167static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
168{
169	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
170	struct alc_spec *spec = codec->spec;
171	return snd_hda_input_mux_info(spec->input_mux, uinfo);
172}
173
174static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
175{
176	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
177	struct alc_spec *spec = codec->spec;
178	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
179
180	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
181	return 0;
182}
183
184static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
185{
186	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
187	struct alc_spec *spec = codec->spec;
188	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
189	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
190				     spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
191}
192
193
194/*
195 * channel mode setting
196 */
197static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
198{
199	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
200	struct alc_spec *spec = codec->spec;
201	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
202				    spec->num_channel_mode);
203}
204
205static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
206{
207	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
208	struct alc_spec *spec = codec->spec;
209	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
210				   spec->num_channel_mode, spec->multiout.max_channels);
211}
212
213static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
214{
215	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
216	struct alc_spec *spec = codec->spec;
217	return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
218				   spec->num_channel_mode, &spec->multiout.max_channels);
219}
220
221/*
222 * Control the mode of pin widget settings via the mixer.  "pc" is used
223 * instead of "%" to avoid consequences of accidently treating the % as
224 * being part of a format specifier.  Maximum allowed length of a value is
225 * 63 characters plus NULL terminator.
226 */
227static char *alc_pin_mode_names[] = {
228	"Line in", "Mic 80pc bias", "Mic 50pc bias",
229	"Line out", "Headphone out",
230};
231static unsigned char alc_pin_mode_values[] = {
232	PIN_IN, PIN_VREF80, PIN_VREF50, PIN_OUT, PIN_HP,
233};
234/* The control can present all 5 options, or it can limit the options based
235 * in the pin being assumed to be exclusively an input or an output pin.
236 */
237#define ALC_PIN_DIR_IN    0x00
238#define ALC_PIN_DIR_OUT   0x01
239#define ALC_PIN_DIR_INOUT 0x02
240
241/* Info about the pin modes supported by the three different pin directions.
242 * For each direction the minimum and maximum values are given.
243 */
244static signed char alc_pin_mode_dir_info[3][2] = {
245	{ 0, 2 },    /* ALC_PIN_DIR_IN */
246	{ 3, 4 },    /* ALC_PIN_DIR_OUT */
247	{ 0, 4 },    /* ALC_PIN_DIR_INOUT */
248};
249#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
250#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
251#define alc_pin_mode_n_items(_dir) \
252	(alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
253
254static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
255{
256	unsigned int item_num = uinfo->value.enumerated.item;
257	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
258
259	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
260	uinfo->count = 1;
261	uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
262
263	if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
264		item_num = alc_pin_mode_min(dir);
265	strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
266	return 0;
267}
268
269static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
270{
271	unsigned int i;
272	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
273	hda_nid_t nid = kcontrol->private_value & 0xffff;
274	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
275	long *valp = ucontrol->value.integer.value;
276	unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00);
277
278	/* Find enumerated value for current pinctl setting */
279	i = alc_pin_mode_min(dir);
280	while (alc_pin_mode_values[i]!=pinctl && i<=alc_pin_mode_max(dir))
281		i++;
282	*valp = i<=alc_pin_mode_max(dir)?i:alc_pin_mode_min(dir);
283	return 0;
284}
285
286static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
287{
288	signed int change;
289	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
290	hda_nid_t nid = kcontrol->private_value & 0xffff;
291	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
292	long val = *ucontrol->value.integer.value;
293	unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00);
294
295	if (val<alc_pin_mode_min(dir) || val>alc_pin_mode_max(dir))
296		val = alc_pin_mode_min(dir);
297
298	change = pinctl != alc_pin_mode_values[val];
299	if (change)
300		snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
301			alc_pin_mode_values[val]);
302	return change;
303}
304
305#define ALC_PIN_MODE(xname, nid, dir) \
306	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
307	  .info = alc_pin_mode_info, \
308	  .get = alc_pin_mode_get, \
309	  .put = alc_pin_mode_put, \
310	  .private_value = nid | (dir<<16) }
311
312/*
313 * set up from the preset table
314 */
315static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *preset)
316{
317	int i;
318
319	for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
320		spec->mixers[spec->num_mixers++] = preset->mixers[i];
321	for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; i++)
322		spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
323
324	spec->channel_mode = preset->channel_mode;
325	spec->num_channel_mode = preset->num_channel_mode;
326
327	spec->multiout.max_channels = spec->channel_mode[0].channels;
328
329	spec->multiout.num_dacs = preset->num_dacs;
330	spec->multiout.dac_nids = preset->dac_nids;
331	spec->multiout.dig_out_nid = preset->dig_out_nid;
332	spec->multiout.hp_nid = preset->hp_nid;
333
334	spec->input_mux = preset->input_mux;
335
336	spec->num_adc_nids = preset->num_adc_nids;
337	spec->adc_nids = preset->adc_nids;
338	spec->dig_in_nid = preset->dig_in_nid;
339}
340
341/*
342 * ALC880 3-stack model
343 *
344 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
345 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
346 *                 HP = 0x19
347 */
348
349static hda_nid_t alc880_dac_nids[4] = {
350	/* front, rear, clfe, rear_surr */
351	0x02, 0x05, 0x04, 0x03
352};
353
354static hda_nid_t alc880_adc_nids[3] = {
355	/* ADC0-2 */
356	0x07, 0x08, 0x09,
357};
358
359/* The datasheet says the node 0x07 is connected from inputs,
360 * but it shows zero connection in the real implementation on some devices.
361 * Note: this is a 915GAV bug, fixed on 915GLV
362 */
363static hda_nid_t alc880_adc_nids_alt[2] = {
364	/* ADC1-2 */
365	0x08, 0x09,
366};
367
368#define ALC880_DIGOUT_NID	0x06
369#define ALC880_DIGIN_NID	0x0a
370
371static struct hda_input_mux alc880_capture_source = {
372	.num_items = 4,
373	.items = {
374		{ "Mic", 0x0 },
375		{ "Front Mic", 0x3 },
376		{ "Line", 0x2 },
377		{ "CD", 0x4 },
378	},
379};
380
381/* channel source setting (2/6 channel selection for 3-stack) */
382/* 2ch mode */
383static struct hda_verb alc880_threestack_ch2_init[] = {
384	/* set line-in to input, mute it */
385	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
386	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
387	/* set mic-in to input vref 80%, mute it */
388	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
389	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
390	{ } /* end */
391};
392
393/* 6ch mode */
394static struct hda_verb alc880_threestack_ch6_init[] = {
395	/* set line-in to output, unmute it */
396	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
397	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
398	/* set mic-in to output, unmute it */
399	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
400	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
401	{ } /* end */
402};
403
404static struct hda_channel_mode alc880_threestack_modes[2] = {
405	{ 2, alc880_threestack_ch2_init },
406	{ 6, alc880_threestack_ch6_init },
407};
408
409static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
410	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
411	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
412	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
413	HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
414	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
415	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
416	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
417	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
418	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
419	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
420	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
421	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
422	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
423	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
424	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
425	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
426	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
427	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
428	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
429	{
430		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
431		.name = "Channel Mode",
432		.info = alc_ch_mode_info,
433		.get = alc_ch_mode_get,
434		.put = alc_ch_mode_put,
435	},
436	{ } /* end */
437};
438
439/* capture mixer elements */
440static struct snd_kcontrol_new alc880_capture_mixer[] = {
441	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
442	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
443	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
444	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
445	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
446	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
447	{
448		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
449		/* The multiple "Capture Source" controls confuse alsamixer
450		 * So call somewhat different..
451		 * FIXME: the controls appear in the "playback" view!
452		 */
453		/* .name = "Capture Source", */
454		.name = "Input Source",
455		.count = 3,
456		.info = alc_mux_enum_info,
457		.get = alc_mux_enum_get,
458		.put = alc_mux_enum_put,
459	},
460	{ } /* end */
461};
462
463/* capture mixer elements (in case NID 0x07 not available) */
464static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {
465	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
466	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
467	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
468	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
469	{
470		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
471		/* The multiple "Capture Source" controls confuse alsamixer
472		 * So call somewhat different..
473		 * FIXME: the controls appear in the "playback" view!
474		 */
475		/* .name = "Capture Source", */
476		.name = "Input Source",
477		.count = 2,
478		.info = alc_mux_enum_info,
479		.get = alc_mux_enum_get,
480		.put = alc_mux_enum_put,
481	},
482	{ } /* end */
483};
484
485
486
487/*
488 * ALC880 5-stack model
489 *
490 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
491 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
492 *                 Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
493 */
494
495/* additional mixers to alc880_three_stack_mixer */
496static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
497	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
498	HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
499	{ } /* end */
500};
501
502/* channel source setting (6/8 channel selection for 5-stack) */
503/* 6ch mode */
504static struct hda_verb alc880_fivestack_ch6_init[] = {
505	/* set line-in to input, mute it */
506	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
507	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
508	{ } /* end */
509};
510
511/* 8ch mode */
512static struct hda_verb alc880_fivestack_ch8_init[] = {
513	/* set line-in to output, unmute it */
514	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
515	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
516	{ } /* end */
517};
518
519static struct hda_channel_mode alc880_fivestack_modes[2] = {
520	{ 6, alc880_fivestack_ch6_init },
521	{ 8, alc880_fivestack_ch8_init },
522};
523
524
525/*
526 * ALC880 6-stack model
527 *
528 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
529 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
530 *   Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
531 */
532
533static hda_nid_t alc880_6st_dac_nids[4] = {
534	/* front, rear, clfe, rear_surr */
535	0x02, 0x03, 0x04, 0x05
536};
537
538static struct hda_input_mux alc880_6stack_capture_source = {
539	.num_items = 4,
540	.items = {
541		{ "Mic", 0x0 },
542		{ "Front Mic", 0x1 },
543		{ "Line", 0x2 },
544		{ "CD", 0x4 },
545	},
546};
547
548/* fixed 8-channels */
549static struct hda_channel_mode alc880_sixstack_modes[1] = {
550	{ 8, NULL },
551};
552
553static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
554	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
555	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
556	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
557	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
558	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
559	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
560	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
561	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
562	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
563	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
564	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
565	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
566	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
567	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
568	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
569	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
570	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
571	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
572	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
573	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
574	{
575		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
576		.name = "Channel Mode",
577		.info = alc_ch_mode_info,
578		.get = alc_ch_mode_get,
579		.put = alc_ch_mode_put,
580	},
581	{ } /* end */
582};
583
584
585/*
586 * ALC880 W810 model
587 *
588 * W810 has rear IO for:
589 * Front (DAC 02)
590 * Surround (DAC 03)
591 * Center/LFE (DAC 04)
592 * Digital out (06)
593 *
594 * The system also has a pair of internal speakers, and a headphone jack.
595 * These are both connected to Line2 on the codec, hence to DAC 02.
596 *
597 * There is a variable resistor to control the speaker or headphone
598 * volume. This is a hardware-only device without a software API.
599 *
600 * Plugging headphones in will disable the internal speakers. This is
601 * implemented in hardware, not via the driver using jack sense. In
602 * a similar fashion, plugging into the rear socket marked "front" will
603 * disable both the speakers and headphones.
604 *
605 * For input, there's a microphone jack, and an "audio in" jack.
606 * These may not do anything useful with this driver yet, because I
607 * haven't setup any initialization verbs for these yet...
608 */
609
610static hda_nid_t alc880_w810_dac_nids[3] = {
611	/* front, rear/surround, clfe */
612	0x02, 0x03, 0x04
613};
614
615/* fixed 6 channels */
616static struct hda_channel_mode alc880_w810_modes[1] = {
617	{ 6, NULL }
618};
619
620/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
621static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
622	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
623	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
624	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
625	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
626	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
627	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
628	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
629	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
630	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
631	{ } /* end */
632};
633
634
635/*
636 * Z710V model
637 *
638 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
639 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
640 */
641
642static hda_nid_t alc880_z71v_dac_nids[1] = {
643	0x02
644};
645#define ALC880_Z71V_HP_DAC	0x03
646
647/* fixed 2 channels */
648static struct hda_channel_mode alc880_2_jack_modes[1] = {
649	{ 2, NULL }
650};
651
652static struct snd_kcontrol_new alc880_z71v_mixer[] = {
653	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
654	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
655	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
656	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
657	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
658	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
659	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
660	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
661	{ } /* end */
662};
663
664
665/* FIXME! */
666/*
667 * ALC880 F1734 model
668 *
669 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
670 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
671 */
672
673static hda_nid_t alc880_f1734_dac_nids[1] = {
674	0x03
675};
676#define ALC880_F1734_HP_DAC	0x02
677
678static struct snd_kcontrol_new alc880_f1734_mixer[] = {
679	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
680	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
681	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
682	HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
683	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
684	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
685	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
686	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
687	{ } /* end */
688};
689
690
691/* FIXME! */
692/*
693 * ALC880 ASUS model
694 *
695 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
696 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
697 *  Mic = 0x18, Line = 0x1a
698 */
699
700#define alc880_asus_dac_nids	alc880_w810_dac_nids	/* identical with w810 */
701#define alc880_asus_modes	alc880_threestack_modes	/* 2/6 channel mode */
702
703static struct snd_kcontrol_new alc880_asus_mixer[] = {
704	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
705	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
706	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
707	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
708	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
709	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
710	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
711	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
712	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
713	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
714	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
715	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
716	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
717	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
718	{
719		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
720		.name = "Channel Mode",
721		.info = alc_ch_mode_info,
722		.get = alc_ch_mode_get,
723		.put = alc_ch_mode_put,
724	},
725	{ } /* end */
726};
727
728/* FIXME! */
729/*
730 * ALC880 ASUS W1V model
731 *
732 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
733 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
734 *  Mic = 0x18, Line = 0x1a, Line2 = 0x1b
735 */
736
737/* additional mixers to alc880_asus_mixer */
738static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
739	HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
740	HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
741	{ } /* end */
742};
743
744/* additional mixers to alc880_asus_mixer */
745static struct snd_kcontrol_new alc880_pcbeep_mixer[] = {
746	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
747	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
748	{ } /* end */
749};
750
751/* TCL S700 */
752static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
753	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
754	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
755	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
756	HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
757	HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
758	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
759	HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
760	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
761	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
762	{
763		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
764		/* The multiple "Capture Source" controls confuse alsamixer
765		 * So call somewhat different..
766		 * FIXME: the controls appear in the "playback" view!
767		 */
768		/* .name = "Capture Source", */
769		.name = "Input Source",
770		.count = 1,
771		.info = alc_mux_enum_info,
772		.get = alc_mux_enum_get,
773		.put = alc_mux_enum_put,
774	},
775	{ } /* end */
776};
777
778/*
779 * build control elements
780 */
781static int alc_build_controls(struct hda_codec *codec)
782{
783	struct alc_spec *spec = codec->spec;
784	int err;
785	int i;
786
787	for (i = 0; i < spec->num_mixers; i++) {
788		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
789		if (err < 0)
790			return err;
791	}
792
793	if (spec->multiout.dig_out_nid) {
794		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
795		if (err < 0)
796			return err;
797	}
798	if (spec->dig_in_nid) {
799		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
800		if (err < 0)
801			return err;
802	}
803	return 0;
804}
805
806
807/*
808 * initialize the codec volumes, etc
809 */
810
811/*
812 * generic initialization of ADC, input mixers and output mixers
813 */
814static struct hda_verb alc880_volume_init_verbs[] = {
815	/*
816	 * Unmute ADC0-2 and set the default input to mic-in
817	 */
818	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
819	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
820	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
821	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
822	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
823	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
824
825	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
826	 * mixer widget
827	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
828	 * mic (mic 2)
829	 */
830	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
831	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
832	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
833	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
834	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
835	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
836
837	/*
838	 * Set up output mixers (0x0c - 0x0f)
839	 */
840	/* set vol=0 to output mixers */
841	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
842	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
843	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
844	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
845	/* set up input amps for analog loopback */
846	/* Amp Indices: DAC = 0, mixer = 1 */
847	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
848	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
849	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
850	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
851	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
852	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
853	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
854	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
855
856	{ }
857};
858
859/*
860 * 3-stack pin configuration:
861 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
862 */
863static struct hda_verb alc880_pin_3stack_init_verbs[] = {
864	/*
865	 * preset connection lists of input pins
866	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
867	 */
868	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
869	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
870	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
871
872	/*
873	 * Set pin mode and muting
874	 */
875	/* set front pin widgets 0x14 for output */
876	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
877	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
878	/* Mic1 (rear panel) pin widget for input and vref at 80% */
879	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
880	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
881	/* Mic2 (as headphone out) for HP output */
882	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
883	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
884	/* Line In pin widget for input */
885	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
886	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
887	/* Line2 (as front mic) pin widget for input and vref at 80% */
888	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
889	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
890	/* CD pin widget for input */
891	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
892
893	{ }
894};
895
896/*
897 * 5-stack pin configuration:
898 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
899 * line-in/side = 0x1a, f-mic = 0x1b
900 */
901static struct hda_verb alc880_pin_5stack_init_verbs[] = {
902	/*
903	 * preset connection lists of input pins
904	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
905	 */
906	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
907	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
908
909	/*
910	 * Set pin mode and muting
911	 */
912	/* set pin widgets 0x14-0x17 for output */
913	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
914	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
915	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
916	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
917	/* unmute pins for output (no gain on this amp) */
918	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
919	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
920	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
921	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
922
923	/* Mic1 (rear panel) pin widget for input and vref at 80% */
924	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
925	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
926	/* Mic2 (as headphone out) for HP output */
927	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
928	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
929	/* Line In pin widget for input */
930	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
931	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
932	/* Line2 (as front mic) pin widget for input and vref at 80% */
933	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
934	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
935	/* CD pin widget for input */
936	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
937
938	{ }
939};
940
941/*
942 * W810 pin configuration:
943 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
944 */
945static struct hda_verb alc880_pin_w810_init_verbs[] = {
946	/* hphone/speaker input selector: front DAC */
947	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
948
949	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
950	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
951	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
952	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
953	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
954	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
955
956	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
957	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
958
959	{ }
960};
961
962/*
963 * Z71V pin configuration:
964 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
965 */
966static struct hda_verb alc880_pin_z71v_init_verbs[] = {
967	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
968	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
969	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
970	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
971
972	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
973	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
974	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
975	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
976
977	{ }
978};
979
980/*
981 * 6-stack pin configuration:
982 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
983 * line = 0x1a, HP = 0x1b
984 */
985static struct hda_verb alc880_pin_6stack_init_verbs[] = {
986	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
987
988	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
989	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
990	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
991	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
992	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
993	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
994	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
995	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
996
997	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
998	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
999	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1000	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1001	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1002	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1003	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1004	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1005	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1006
1007	{ }
1008};
1009
1010/* FIXME! */
1011/*
1012 * F1734 pin configuration:
1013 * HP = 0x14, speaker-out = 0x15, mic = 0x18
1014 */
1015static struct hda_verb alc880_pin_f1734_init_verbs[] = {
1016	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
1017	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
1018	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
1019	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1020
1021	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1022	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1023	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1024	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1025
1026	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1027	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1028	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1029	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1030	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1031	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1032	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1033	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1034	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1035
1036	{ }
1037};
1038
1039/* FIXME! */
1040/*
1041 * ASUS pin configuration:
1042 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
1043 */
1044static struct hda_verb alc880_pin_asus_init_verbs[] = {
1045	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
1046	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
1047	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
1048	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1049
1050	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1051	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1052	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1053	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1054	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1055	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1056	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1057	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1058
1059	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1060	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1061	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1062	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1063	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1064	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1065	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1066	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1067	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1068
1069	{ }
1070};
1071
1072/* Enable GPIO mask and set output */
1073static struct hda_verb alc880_gpio1_init_verbs[] = {
1074	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
1075	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
1076	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
1077
1078	{ }
1079};
1080
1081/* Enable GPIO mask and set output */
1082static struct hda_verb alc880_gpio2_init_verbs[] = {
1083	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
1084	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
1085	{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
1086
1087	{ }
1088};
1089
1090/* Clevo m520g init */
1091static struct hda_verb alc880_pin_clevo_init_verbs[] = {
1092	/* headphone output */
1093	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
1094	/* line-out */
1095	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1096	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1097	/* Line-in */
1098	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1099	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1100	/* CD */
1101	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1102	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1103	/* Mic1 (rear panel) */
1104	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1105	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1106	/* Mic2 (front panel) */
1107	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1108	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1109	/* headphone */
1110	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1111	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1112        /* change to EAPD mode */
1113	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1114	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
1115
1116	{ }
1117};
1118
1119static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
1120	/* Headphone output */
1121	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1122	/* Front output*/
1123	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1124	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1125
1126	/* Line In pin widget for input */
1127	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1128	/* CD pin widget for input */
1129	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1130	/* Mic1 (rear panel) pin widget for input and vref at 80% */
1131	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1132
1133	/* change to EAPD mode */
1134	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1135	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
1136
1137	{ }
1138};
1139
1140/*
1141 */
1142
1143static int alc_init(struct hda_codec *codec)
1144{
1145	struct alc_spec *spec = codec->spec;
1146	unsigned int i;
1147
1148	for (i = 0; i < spec->num_init_verbs; i++)
1149		snd_hda_sequence_write(codec, spec->init_verbs[i]);
1150	return 0;
1151}
1152
1153#ifdef CONFIG_PM
1154/*
1155 * resume
1156 */
1157static int alc_resume(struct hda_codec *codec)
1158{
1159	struct alc_spec *spec = codec->spec;
1160	int i;
1161
1162	alc_init(codec);
1163	for (i = 0; i < spec->num_mixers; i++)
1164		snd_hda_resume_ctls(codec, spec->mixers[i]);
1165	if (spec->multiout.dig_out_nid)
1166		snd_hda_resume_spdif_out(codec);
1167	if (spec->dig_in_nid)
1168		snd_hda_resume_spdif_in(codec);
1169
1170	return 0;
1171}
1172#endif
1173
1174/*
1175 * Analog playback callbacks
1176 */
1177static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
1178				    struct hda_codec *codec,
1179				    struct snd_pcm_substream *substream)
1180{
1181	struct alc_spec *spec = codec->spec;
1182	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
1183}
1184
1185static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
1186				       struct hda_codec *codec,
1187				       unsigned int stream_tag,
1188				       unsigned int format,
1189				       struct snd_pcm_substream *substream)
1190{
1191	struct alc_spec *spec = codec->spec;
1192	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
1193						format, substream);
1194}
1195
1196static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
1197				       struct hda_codec *codec,
1198				       struct snd_pcm_substream *substream)
1199{
1200	struct alc_spec *spec = codec->spec;
1201	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
1202}
1203
1204/*
1205 * Digital out
1206 */
1207static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
1208					struct hda_codec *codec,
1209					struct snd_pcm_substream *substream)
1210{
1211	struct alc_spec *spec = codec->spec;
1212	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
1213}
1214
1215static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
1216					 struct hda_codec *codec,
1217					 struct snd_pcm_substream *substream)
1218{
1219	struct alc_spec *spec = codec->spec;
1220	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
1221}
1222
1223/*
1224 * Analog capture
1225 */
1226static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
1227				      struct hda_codec *codec,
1228				      unsigned int stream_tag,
1229				      unsigned int format,
1230				      struct snd_pcm_substream *substream)
1231{
1232	struct alc_spec *spec = codec->spec;
1233
1234	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
1235				   stream_tag, 0, format);
1236	return 0;
1237}
1238
1239static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
1240				      struct hda_codec *codec,
1241				      struct snd_pcm_substream *substream)
1242{
1243	struct alc_spec *spec = codec->spec;
1244
1245	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
1246	return 0;
1247}
1248
1249
1250/*
1251 */
1252static struct hda_pcm_stream alc880_pcm_analog_playback = {
1253	.substreams = 1,
1254	.channels_min = 2,
1255	.channels_max = 8,
1256	/* NID is set in alc_build_pcms */
1257	.ops = {
1258		.open = alc880_playback_pcm_open,
1259		.prepare = alc880_playback_pcm_prepare,
1260		.cleanup = alc880_playback_pcm_cleanup
1261	},
1262};
1263
1264static struct hda_pcm_stream alc880_pcm_analog_capture = {
1265	.substreams = 2,
1266	.channels_min = 2,
1267	.channels_max = 2,
1268	/* NID is set in alc_build_pcms */
1269	.ops = {
1270		.prepare = alc880_capture_pcm_prepare,
1271		.cleanup = alc880_capture_pcm_cleanup
1272	},
1273};
1274
1275static struct hda_pcm_stream alc880_pcm_digital_playback = {
1276	.substreams = 1,
1277	.channels_min = 2,
1278	.channels_max = 2,
1279	/* NID is set in alc_build_pcms */
1280	.ops = {
1281		.open = alc880_dig_playback_pcm_open,
1282		.close = alc880_dig_playback_pcm_close
1283	},
1284};
1285
1286static struct hda_pcm_stream alc880_pcm_digital_capture = {
1287	.substreams = 1,
1288	.channels_min = 2,
1289	.channels_max = 2,
1290	/* NID is set in alc_build_pcms */
1291};
1292
1293/* Used by alc_build_pcms to flag that a PCM has no playback stream */
1294static struct hda_pcm_stream alc_pcm_null_playback = {
1295	.substreams = 0,
1296	.channels_min = 0,
1297	.channels_max = 0,
1298};
1299
1300static int alc_build_pcms(struct hda_codec *codec)
1301{
1302	struct alc_spec *spec = codec->spec;
1303	struct hda_pcm *info = spec->pcm_rec;
1304	int i;
1305
1306	codec->num_pcms = 1;
1307	codec->pcm_info = info;
1308
1309	info->name = spec->stream_name_analog;
1310	if (spec->stream_analog_playback) {
1311		snd_assert(spec->multiout.dac_nids, return -EINVAL);
1312		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
1313		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
1314	}
1315	if (spec->stream_analog_capture) {
1316		snd_assert(spec->adc_nids, return -EINVAL);
1317		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
1318		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
1319	}
1320
1321	if (spec->channel_mode) {
1322		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
1323		for (i = 0; i < spec->num_channel_mode; i++) {
1324			if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
1325				info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
1326			}
1327		}
1328	}
1329
1330	/* If the use of more than one ADC is requested for the current
1331	 * model, configure a second analog capture-only PCM.
1332	 */
1333	if (spec->num_adc_nids > 1) {
1334		codec->num_pcms++;
1335		info++;
1336		info->name = spec->stream_name_analog;
1337		/* No playback stream for second PCM */
1338		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback;
1339		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
1340		if (spec->stream_analog_capture) {
1341			snd_assert(spec->adc_nids, return -EINVAL);
1342			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
1343			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1];
1344		}
1345	}
1346
1347	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
1348		codec->num_pcms++;
1349		info++;
1350		info->name = spec->stream_name_digital;
1351		if (spec->multiout.dig_out_nid &&
1352		    spec->stream_digital_playback) {
1353			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
1354			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
1355		}
1356		if (spec->dig_in_nid &&
1357		    spec->stream_digital_capture) {
1358			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
1359			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
1360		}
1361	}
1362
1363	return 0;
1364}
1365
1366static void alc_free(struct hda_codec *codec)
1367{
1368	struct alc_spec *spec = codec->spec;
1369	unsigned int i;
1370
1371	if (! spec)
1372		return;
1373
1374	if (spec->kctl_alloc) {
1375		for (i = 0; i < spec->num_kctl_used; i++)
1376			kfree(spec->kctl_alloc[i].name);
1377		kfree(spec->kctl_alloc);
1378	}
1379	kfree(spec);
1380}
1381
1382/*
1383 */
1384static struct hda_codec_ops alc_patch_ops = {
1385	.build_controls = alc_build_controls,
1386	.build_pcms = alc_build_pcms,
1387	.init = alc_init,
1388	.free = alc_free,
1389#ifdef CONFIG_PM
1390	.resume = alc_resume,
1391#endif
1392};
1393
1394
1395/*
1396 * Test configuration for debugging
1397 *
1398 * Almost all inputs/outputs are enabled.  I/O pins can be configured via
1399 * enum controls.
1400 */
1401#ifdef CONFIG_SND_DEBUG
1402static hda_nid_t alc880_test_dac_nids[4] = {
1403	0x02, 0x03, 0x04, 0x05
1404};
1405
1406static struct hda_input_mux alc880_test_capture_source = {
1407	.num_items = 5,
1408	.items = {
1409		{ "In-1", 0x0 },
1410		{ "In-2", 0x1 },
1411		{ "In-3", 0x2 },
1412		{ "In-4", 0x3 },
1413		{ "CD", 0x4 },
1414	},
1415};
1416
1417static struct hda_channel_mode alc880_test_modes[4] = {
1418	{ 2, NULL },
1419	{ 4, NULL },
1420	{ 6, NULL },
1421	{ 8, NULL },
1422};
1423
1424static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1425{
1426	static char *texts[] = {
1427		"N/A", "Line Out", "HP Out",
1428		"In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
1429	};
1430	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1431	uinfo->count = 1;
1432	uinfo->value.enumerated.items = 8;
1433	if (uinfo->value.enumerated.item >= 8)
1434		uinfo->value.enumerated.item = 7;
1435	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1436	return 0;
1437}
1438
1439static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1440{
1441	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1442	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1443	unsigned int pin_ctl, item = 0;
1444
1445	pin_ctl = snd_hda_codec_read(codec, nid, 0,
1446				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1447	if (pin_ctl & AC_PINCTL_OUT_EN) {
1448		if (pin_ctl & AC_PINCTL_HP_EN)
1449			item = 2;
1450		else
1451			item = 1;
1452	} else if (pin_ctl & AC_PINCTL_IN_EN) {
1453		switch (pin_ctl & AC_PINCTL_VREFEN) {
1454		case AC_PINCTL_VREF_HIZ: item = 3; break;
1455		case AC_PINCTL_VREF_50:  item = 4; break;
1456		case AC_PINCTL_VREF_GRD: item = 5; break;
1457		case AC_PINCTL_VREF_80:  item = 6; break;
1458		case AC_PINCTL_VREF_100: item = 7; break;
1459		}
1460	}
1461	ucontrol->value.enumerated.item[0] = item;
1462	return 0;
1463}
1464
1465static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1466{
1467	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1468	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1469	static unsigned int ctls[] = {
1470		0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
1471		AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
1472		AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
1473		AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
1474		AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
1475		AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
1476	};
1477	unsigned int old_ctl, new_ctl;
1478
1479	old_ctl = snd_hda_codec_read(codec, nid, 0,
1480				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1481	new_ctl = ctls[ucontrol->value.enumerated.item[0]];
1482	if (old_ctl != new_ctl) {
1483		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
1484		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1485				    ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000);
1486		return 1;
1487	}
1488	return 0;
1489}
1490
1491static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1492{
1493	static char *texts[] = {
1494		"Front", "Surround", "CLFE", "Side"
1495	};
1496	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1497	uinfo->count = 1;
1498	uinfo->value.enumerated.items = 4;
1499	if (uinfo->value.enumerated.item >= 4)
1500		uinfo->value.enumerated.item = 3;
1501	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1502	return 0;
1503}
1504
1505static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1506{
1507	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1508	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1509	unsigned int sel;
1510
1511	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
1512	ucontrol->value.enumerated.item[0] = sel & 3;
1513	return 0;
1514}
1515
1516static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1517{
1518	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1519	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1520	unsigned int sel;
1521
1522	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
1523	if (ucontrol->value.enumerated.item[0] != sel) {
1524		sel = ucontrol->value.enumerated.item[0] & 3;
1525		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
1526		return 1;
1527	}
1528	return 0;
1529}
1530
1531#define PIN_CTL_TEST(xname,nid) {			\
1532		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
1533			.name = xname,		       \
1534			.info = alc_test_pin_ctl_info, \
1535			.get = alc_test_pin_ctl_get,   \
1536			.put = alc_test_pin_ctl_put,   \
1537			.private_value = nid	       \
1538			}
1539
1540#define PIN_SRC_TEST(xname,nid) {			\
1541		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
1542			.name = xname,		       \
1543			.info = alc_test_pin_src_info, \
1544			.get = alc_test_pin_src_get,   \
1545			.put = alc_test_pin_src_put,   \
1546			.private_value = nid	       \
1547			}
1548
1549static struct snd_kcontrol_new alc880_test_mixer[] = {
1550	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1551	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1552	HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
1553	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1554	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1555	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1556	HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
1557	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
1558	PIN_CTL_TEST("Front Pin Mode", 0x14),
1559	PIN_CTL_TEST("Surround Pin Mode", 0x15),
1560	PIN_CTL_TEST("CLFE Pin Mode", 0x16),
1561	PIN_CTL_TEST("Side Pin Mode", 0x17),
1562	PIN_CTL_TEST("In-1 Pin Mode", 0x18),
1563	PIN_CTL_TEST("In-2 Pin Mode", 0x19),
1564	PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
1565	PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
1566	PIN_SRC_TEST("In-1 Pin Source", 0x18),
1567	PIN_SRC_TEST("In-2 Pin Source", 0x19),
1568	PIN_SRC_TEST("In-3 Pin Source", 0x1a),
1569	PIN_SRC_TEST("In-4 Pin Source", 0x1b),
1570	HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
1571	HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
1572	HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
1573	HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
1574	HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
1575	HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
1576	HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
1577	HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
1578	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
1579	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
1580	{
1581		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1582		.name = "Channel Mode",
1583		.info = alc_ch_mode_info,
1584		.get = alc_ch_mode_get,
1585		.put = alc_ch_mode_put,
1586	},
1587	{ } /* end */
1588};
1589
1590static struct hda_verb alc880_test_init_verbs[] = {
1591	/* Unmute inputs of 0x0c - 0x0f */
1592	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1593	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1594	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1595	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1596	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1597	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1598	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1599	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1600	/* Vol output for 0x0c-0x0f */
1601	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1602	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1603	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1604	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1605	/* Set output pins 0x14-0x17 */
1606	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1607	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1608	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1609	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1610	/* Unmute output pins 0x14-0x17 */
1611	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1612	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1613	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1614	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1615	/* Set input pins 0x18-0x1c */
1616	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1617	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1618	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1619	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1620	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1621	/* Mute input pins 0x18-0x1b */
1622	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1623	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1624	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1625	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1626	/* ADC set up */
1627	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1628	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
1629	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1630	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
1631	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1632	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
1633	/* Analog input/passthru */
1634	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1635	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1636	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1637	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1638	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1639	{ }
1640};
1641#endif
1642
1643/*
1644 */
1645
1646static struct hda_board_config alc880_cfg_tbl[] = {
1647	/* Back 3 jack, front 2 jack */
1648	{ .modelname = "3stack", .config = ALC880_3ST },
1649	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST },
1650	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST },
1651	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST },
1652	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST },
1653	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST },
1654	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST },
1655	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST },
1656	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST },
1657	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST },
1658	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST },
1659	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST },
1660	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST },
1661	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST },
1662	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST },
1663	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST },
1664	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST },
1665	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST },
1666	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST },
1667	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
1668	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
1669	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
1670	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
1671	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
1672	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
1673	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
1674	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
1675	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
1676	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
1677	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
1678	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
1679	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
1680	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
1681	/* TCL S700 */
1682	{ .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 },
1683
1684	/* Back 3 jack, front 2 jack (Internal add Aux-In) */
1685	{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
1686	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST },
1687	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST },
1688
1689	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
1690	{ .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
1691	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
1692	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG },
1693	/* Clevo m520G NB */
1694	{ .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, .config = ALC880_CLEVO },
1695
1696	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
1697	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
1698	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
1699	{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
1700
1701	/* Back 5 jack, front 2 jack */
1702	{ .modelname = "5stack", .config = ALC880_5ST },
1703	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
1704	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
1705	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
1706	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
1707	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
1708
1709	/* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
1710	{ .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
1711	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
1712	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
1713	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
1714	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
1715	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
1716	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
1717	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
1718	{ .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
1719	{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
1720	/* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */
1721	{ .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
1722	/* note subvendor = 0 below */
1723	/* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */
1724
1725	{ .modelname = "w810", .config = ALC880_W810 },
1726	{ .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
1727
1728	{ .modelname = "z71v", .config = ALC880_Z71V },
1729	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
1730
1731	{ .modelname = "6stack", .config = ALC880_6ST },
1732	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x8196, .config = ALC880_6ST }, /* ASUS P5GD1-HVM */
1733	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x81b4, .config = ALC880_6ST },
1734	{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
1735	{ .pci_subvendor = 0x1458, .pci_subdevice = 0xa102, .config = ALC880_6ST }, /* Gigabyte K8N51 */
1736
1737	{ .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
1738	{ .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
1739	{ .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
1740	{ .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
1741	{ .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
1742	{ .pci_subvendor = 0x1039, .pci_subdevice = 0x1234, .config = ALC880_6ST_DIG },
1743	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0077, .config = ALC880_6ST_DIG },
1744	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0078, .config = ALC880_6ST_DIG },
1745	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG },
1746	{ .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */
1747
1748	{ .modelname = "asus", .config = ALC880_ASUS },
1749	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
1750	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
1751	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
1752	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
1753	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG },
1754	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
1755	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
1756	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
1757	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
1758	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
1759	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
1760	{ .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 },
1761
1762	{ .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
1763	{ .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
1764
1765	{ .modelname = "F1734", .config = ALC880_F1734 },
1766	{ .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
1767	{ .pci_subvendor = 0x1584, .pci_subdevice = 0x9054, .config = ALC880_F1734 },
1768
1769#ifdef CONFIG_SND_DEBUG
1770	{ .modelname = "test", .config = ALC880_TEST },
1771#endif
1772	{ .modelname = "auto", .config = ALC880_AUTO },
1773
1774	{}
1775};
1776
1777/*
1778 * ALC880 codec presets
1779 */
1780static struct alc_config_preset alc880_presets[] = {
1781	[ALC880_3ST] = {
1782		.mixers = { alc880_three_stack_mixer },
1783		.init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
1784		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
1785		.dac_nids = alc880_dac_nids,
1786		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1787		.channel_mode = alc880_threestack_modes,
1788		.input_mux = &alc880_capture_source,
1789	},
1790	[ALC880_3ST_DIG] = {
1791		.mixers = { alc880_three_stack_mixer },
1792		.init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
1793		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
1794		.dac_nids = alc880_dac_nids,
1795		.dig_out_nid = ALC880_DIGOUT_NID,
1796		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1797		.channel_mode = alc880_threestack_modes,
1798		.input_mux = &alc880_capture_source,
1799	},
1800	[ALC880_TCL_S700] = {
1801		.mixers = { alc880_tcl_s700_mixer },
1802		.init_verbs = { alc880_volume_init_verbs,
1803				alc880_pin_tcl_S700_init_verbs,
1804				alc880_gpio2_init_verbs },
1805		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
1806		.dac_nids = alc880_dac_nids,
1807		.hp_nid = 0x03,
1808		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1809		.channel_mode = alc880_2_jack_modes,
1810		.input_mux = &alc880_capture_source,
1811	},
1812	[ALC880_5ST] = {
1813		.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
1814		.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
1815		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
1816		.dac_nids = alc880_dac_nids,
1817		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
1818		.channel_mode = alc880_fivestack_modes,
1819		.input_mux = &alc880_capture_source,
1820	},
1821	[ALC880_5ST_DIG] = {
1822		.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
1823		.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
1824		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
1825		.dac_nids = alc880_dac_nids,
1826		.dig_out_nid = ALC880_DIGOUT_NID,
1827		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
1828		.channel_mode = alc880_fivestack_modes,
1829		.input_mux = &alc880_capture_source,
1830	},
1831	[ALC880_6ST] = {
1832		.mixers = { alc880_six_stack_mixer },
1833		.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
1834		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
1835		.dac_nids = alc880_6st_dac_nids,
1836		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
1837		.channel_mode = alc880_sixstack_modes,
1838		.input_mux = &alc880_6stack_capture_source,
1839	},
1840	[ALC880_6ST_DIG] = {
1841		.mixers = { alc880_six_stack_mixer },
1842		.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
1843		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
1844		.dac_nids = alc880_6st_dac_nids,
1845		.dig_out_nid = ALC880_DIGOUT_NID,
1846		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
1847		.channel_mode = alc880_sixstack_modes,
1848		.input_mux = &alc880_6stack_capture_source,
1849	},
1850	[ALC880_W810] = {
1851		.mixers = { alc880_w810_base_mixer },
1852		.init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs,
1853				alc880_gpio2_init_verbs },
1854		.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
1855		.dac_nids = alc880_w810_dac_nids,
1856		.dig_out_nid = ALC880_DIGOUT_NID,
1857		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
1858		.channel_mode = alc880_w810_modes,
1859		.input_mux = &alc880_capture_source,
1860	},
1861	[ALC880_Z71V] = {
1862		.mixers = { alc880_z71v_mixer },
1863		.init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs },
1864		.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
1865		.dac_nids = alc880_z71v_dac_nids,
1866		.dig_out_nid = ALC880_DIGOUT_NID,
1867		.hp_nid = 0x03,
1868		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1869		.channel_mode = alc880_2_jack_modes,
1870		.input_mux = &alc880_capture_source,
1871	},
1872	[ALC880_F1734] = {
1873		.mixers = { alc880_f1734_mixer },
1874		.init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
1875		.num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
1876		.dac_nids = alc880_f1734_dac_nids,
1877		.hp_nid = 0x02,
1878		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1879		.channel_mode = alc880_2_jack_modes,
1880		.input_mux = &alc880_capture_source,
1881	},
1882	[ALC880_ASUS] = {
1883		.mixers = { alc880_asus_mixer },
1884		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1885				alc880_gpio1_init_verbs },
1886		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1887		.dac_nids = alc880_asus_dac_nids,
1888		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1889		.channel_mode = alc880_asus_modes,
1890		.input_mux = &alc880_capture_source,
1891	},
1892	[ALC880_ASUS_DIG] = {
1893		.mixers = { alc880_asus_mixer },
1894		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1895				alc880_gpio1_init_verbs },
1896		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1897		.dac_nids = alc880_asus_dac_nids,
1898		.dig_out_nid = ALC880_DIGOUT_NID,
1899		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1900		.channel_mode = alc880_asus_modes,
1901		.input_mux = &alc880_capture_source,
1902	},
1903	[ALC880_ASUS_DIG2] = {
1904		.mixers = { alc880_asus_mixer },
1905		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1906				alc880_gpio2_init_verbs }, /* use GPIO2 */
1907		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1908		.dac_nids = alc880_asus_dac_nids,
1909		.dig_out_nid = ALC880_DIGOUT_NID,
1910		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1911		.channel_mode = alc880_asus_modes,
1912		.input_mux = &alc880_capture_source,
1913	},
1914	[ALC880_ASUS_W1V] = {
1915		.mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
1916		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1917				alc880_gpio1_init_verbs },
1918		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1919		.dac_nids = alc880_asus_dac_nids,
1920		.dig_out_nid = ALC880_DIGOUT_NID,
1921		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1922		.channel_mode = alc880_asus_modes,
1923		.input_mux = &alc880_capture_source,
1924	},
1925	[ALC880_UNIWILL_DIG] = {
1926		.mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
1927		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
1928		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1929		.dac_nids = alc880_asus_dac_nids,
1930		.dig_out_nid = ALC880_DIGOUT_NID,
1931		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1932		.channel_mode = alc880_asus_modes,
1933		.input_mux = &alc880_capture_source,
1934	},
1935	[ALC880_CLEVO] = {
1936		.mixers = { alc880_three_stack_mixer },
1937		.init_verbs = { alc880_volume_init_verbs,
1938				alc880_pin_clevo_init_verbs },
1939		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
1940		.dac_nids = alc880_dac_nids,
1941		.hp_nid = 0x03,
1942		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1943		.channel_mode = alc880_threestack_modes,
1944		.input_mux = &alc880_capture_source,
1945	},
1946#ifdef CONFIG_SND_DEBUG
1947	[ALC880_TEST] = {
1948		.mixers = { alc880_test_mixer },
1949		.init_verbs = { alc880_test_init_verbs },
1950		.num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
1951		.dac_nids = alc880_test_dac_nids,
1952		.dig_out_nid = ALC880_DIGOUT_NID,
1953		.num_channel_mode = ARRAY_SIZE(alc880_test_modes),
1954		.channel_mode = alc880_test_modes,
1955		.input_mux = &alc880_test_capture_source,
1956	},
1957#endif
1958};
1959
1960/*
1961 * Automatic parse of I/O pins from the BIOS configuration
1962 */
1963
1964#define NUM_CONTROL_ALLOC	32
1965#define NUM_VERB_ALLOC		32
1966
1967enum {
1968	ALC_CTL_WIDGET_VOL,
1969	ALC_CTL_WIDGET_MUTE,
1970	ALC_CTL_BIND_MUTE,
1971};
1972static struct snd_kcontrol_new alc880_control_templates[] = {
1973	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
1974	HDA_CODEC_MUTE(NULL, 0, 0, 0),
1975	HDA_BIND_MUTE(NULL, 0, 0, 0),
1976};
1977
1978/* add dynamic controls */
1979static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
1980{
1981	struct snd_kcontrol_new *knew;
1982
1983	if (spec->num_kctl_used >= spec->num_kctl_alloc) {
1984		int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
1985
1986		knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
1987		if (! knew)
1988			return -ENOMEM;
1989		if (spec->kctl_alloc) {
1990			memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
1991			kfree(spec->kctl_alloc);
1992		}
1993		spec->kctl_alloc = knew;
1994		spec->num_kctl_alloc = num;
1995	}
1996
1997	knew = &spec->kctl_alloc[spec->num_kctl_used];
1998	*knew = alc880_control_templates[type];
1999	knew->name = kstrdup(name, GFP_KERNEL);
2000	if (! knew->name)
2001		return -ENOMEM;
2002	knew->private_value = val;
2003	spec->num_kctl_used++;
2004	return 0;
2005}
2006
2007#define alc880_is_fixed_pin(nid)	((nid) >= 0x14 && (nid) <= 0x17)
2008#define alc880_fixed_pin_idx(nid)	((nid) - 0x14)
2009#define alc880_is_multi_pin(nid)	((nid) >= 0x18)
2010#define alc880_multi_pin_idx(nid)	((nid) - 0x18)
2011#define alc880_is_input_pin(nid)	((nid) >= 0x18)
2012#define alc880_input_pin_idx(nid)	((nid) - 0x18)
2013#define alc880_idx_to_dac(nid)		((nid) + 0x02)
2014#define alc880_dac_to_idx(nid)		((nid) - 0x02)
2015#define alc880_idx_to_mixer(nid)	((nid) + 0x0c)
2016#define alc880_idx_to_selector(nid)	((nid) + 0x10)
2017#define ALC880_PIN_CD_NID		0x1c
2018
2019/* fill in the dac_nids table from the parsed pin configuration */
2020static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
2021{
2022	hda_nid_t nid;
2023	int assigned[4];
2024	int i, j;
2025
2026	memset(assigned, 0, sizeof(assigned));
2027	spec->multiout.dac_nids = spec->private_dac_nids;
2028
2029	/* check the pins hardwired to audio widget */
2030	for (i = 0; i < cfg->line_outs; i++) {
2031		nid = cfg->line_out_pins[i];
2032		if (alc880_is_fixed_pin(nid)) {
2033			int idx = alc880_fixed_pin_idx(nid);
2034			spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
2035			assigned[idx] = 1;
2036		}
2037	}
2038	/* left pins can be connect to any audio widget */
2039	for (i = 0; i < cfg->line_outs; i++) {
2040		nid = cfg->line_out_pins[i];
2041		if (alc880_is_fixed_pin(nid))
2042			continue;
2043		/* search for an empty channel */
2044		for (j = 0; j < cfg->line_outs; j++) {
2045			if (! assigned[j]) {
2046				spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
2047				assigned[j] = 1;
2048				break;
2049			}
2050		}
2051	}
2052	spec->multiout.num_dacs = cfg->line_outs;
2053	return 0;
2054}
2055
2056/* add playback controls from the parsed DAC table */
2057static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
2058					     const struct auto_pin_cfg *cfg)
2059{
2060	char name[32];
2061	static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2062	hda_nid_t nid;
2063	int i, err;
2064
2065	for (i = 0; i < cfg->line_outs; i++) {
2066		if (! spec->multiout.dac_nids[i])
2067			continue;
2068		nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
2069		if (i == 2) {
2070			/* Center/LFE */
2071			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
2072					       HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
2073				return err;
2074			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
2075					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
2076				return err;
2077			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
2078					       HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
2079				return err;
2080			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
2081					       HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
2082				return err;
2083		} else {
2084			sprintf(name, "%s Playback Volume", chname[i]);
2085			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2086					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
2087				return err;
2088			sprintf(name, "%s Playback Switch", chname[i]);
2089			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
2090					       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2091				return err;
2092		}
2093	}
2094	return 0;
2095}
2096
2097/* add playback controls for speaker and HP outputs */
2098static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
2099					const char *pfx)
2100{
2101	hda_nid_t nid;
2102	int err;
2103	char name[32];
2104
2105	if (! pin)
2106		return 0;
2107
2108	if (alc880_is_fixed_pin(pin)) {
2109		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
2110		if (! spec->multiout.dac_nids[0]) {
2111			/* use this as the primary output */
2112			spec->multiout.dac_nids[0] = nid;
2113			if (! spec->multiout.num_dacs)
2114				spec->multiout.num_dacs = 1;
2115		} else
2116			/* specify the DAC as the extra output */
2117			spec->multiout.hp_nid = nid;
2118		/* control HP volume/switch on the output mixer amp */
2119		nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
2120		sprintf(name, "%s Playback Volume", pfx);
2121		if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2122				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
2123			return err;
2124		sprintf(name, "%s Playback Switch", pfx);
2125		if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
2126				       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2127			return err;
2128	} else if (alc880_is_multi_pin(pin)) {
2129		/* set manual connection */
2130		if (! spec->multiout.dac_nids[0]) {
2131			/* use this as the primary output */
2132			spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin));
2133			if (! spec->multiout.num_dacs)
2134				spec->multiout.num_dacs = 1;
2135		}
2136		/* we have only a switch on HP-out PIN */
2137		sprintf(name, "%s Playback Switch", pfx);
2138		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
2139				       HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
2140			return err;
2141	}
2142	return 0;
2143}
2144
2145/* create input playback/capture controls for the given pin */
2146static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname,
2147			    int idx, hda_nid_t mix_nid)
2148{
2149	char name[32];
2150	int err;
2151
2152	sprintf(name, "%s Playback Volume", ctlname);
2153	if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2154			       HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
2155		return err;
2156	sprintf(name, "%s Playback Switch", ctlname);
2157	if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
2158			       HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
2159		return err;
2160	return 0;
2161}
2162
2163/* create playback/capture controls for input pins */
2164static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
2165						const struct auto_pin_cfg *cfg)
2166{
2167	struct hda_input_mux *imux = &spec->private_imux;
2168	int i, err, idx;
2169
2170	for (i = 0; i < AUTO_PIN_LAST; i++) {
2171		if (alc880_is_input_pin(cfg->input_pins[i])) {
2172			idx = alc880_input_pin_idx(cfg->input_pins[i]);
2173			err = new_analog_input(spec, cfg->input_pins[i],
2174					       auto_pin_cfg_labels[i],
2175					       idx, 0x0b);
2176			if (err < 0)
2177				return err;
2178			imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2179			imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
2180			imux->num_items++;
2181		}
2182	}
2183	return 0;
2184}
2185
2186static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
2187					      hda_nid_t nid, int pin_type,
2188					      int dac_idx)
2189{
2190	/* set as output */
2191	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2192	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2193	/* need the manual connection? */
2194	if (alc880_is_multi_pin(nid)) {
2195		struct alc_spec *spec = codec->spec;
2196		int idx = alc880_multi_pin_idx(nid);
2197		snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
2198				    AC_VERB_SET_CONNECT_SEL,
2199				    alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
2200	}
2201}
2202
2203static void alc880_auto_init_multi_out(struct hda_codec *codec)
2204{
2205	struct alc_spec *spec = codec->spec;
2206	int i;
2207
2208	for (i = 0; i < spec->autocfg.line_outs; i++) {
2209		hda_nid_t nid = spec->autocfg.line_out_pins[i];
2210		alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2211	}
2212}
2213
2214static void alc880_auto_init_extra_out(struct hda_codec *codec)
2215{
2216	struct alc_spec *spec = codec->spec;
2217	hda_nid_t pin;
2218
2219	pin = spec->autocfg.speaker_pin;
2220	if (pin) /* connect to front */
2221		alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2222	pin = spec->autocfg.hp_pin;
2223	if (pin) /* connect to front */
2224		alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2225}
2226
2227static void alc880_auto_init_analog_input(struct hda_codec *codec)
2228{
2229	struct alc_spec *spec = codec->spec;
2230	int i;
2231
2232	for (i = 0; i < AUTO_PIN_LAST; i++) {
2233		hda_nid_t nid = spec->autocfg.input_pins[i];
2234		if (alc880_is_input_pin(nid)) {
2235			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2236					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2237			if (nid != ALC880_PIN_CD_NID)
2238				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2239						    AMP_OUT_MUTE);
2240		}
2241	}
2242}
2243
2244/* parse the BIOS configuration and set up the alc_spec */
2245/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2246static int alc880_parse_auto_config(struct hda_codec *codec)
2247{
2248	struct alc_spec *spec = codec->spec;
2249	int err;
2250	static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
2251
2252	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
2253						alc880_ignore)) < 0)
2254		return err;
2255	if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
2256	    ! spec->autocfg.hp_pin)
2257		return 0; /* can't find valid BIOS pin config */
2258
2259	if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
2260	    (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2261	    (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
2262						"Speaker")) < 0 ||
2263	    (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
2264						"Headphone")) < 0 ||
2265	    (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2266		return err;
2267
2268	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2269
2270	if (spec->autocfg.dig_out_pin)
2271		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
2272	if (spec->autocfg.dig_in_pin)
2273		spec->dig_in_nid = ALC880_DIGIN_NID;
2274
2275	if (spec->kctl_alloc)
2276		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2277
2278	spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
2279
2280	spec->input_mux = &spec->private_imux;
2281
2282	return 1;
2283}
2284
2285/* init callback for auto-configuration model -- overriding the default init */
2286static int alc880_auto_init(struct hda_codec *codec)
2287{
2288	alc_init(codec);
2289	alc880_auto_init_multi_out(codec);
2290	alc880_auto_init_extra_out(codec);
2291	alc880_auto_init_analog_input(codec);
2292	return 0;
2293}
2294
2295/*
2296 * OK, here we have finally the patch for ALC880
2297 */
2298
2299static int patch_alc880(struct hda_codec *codec)
2300{
2301	struct alc_spec *spec;
2302	int board_config;
2303	int err;
2304
2305	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2306	if (spec == NULL)
2307		return -ENOMEM;
2308
2309	codec->spec = spec;
2310
2311	board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
2312	if (board_config < 0 || board_config >= ALC880_MODEL_LAST) {
2313		printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
2314		board_config = ALC880_AUTO;
2315	}
2316
2317	if (board_config == ALC880_AUTO) {
2318		/* automatic parse from the BIOS config */
2319		err = alc880_parse_auto_config(codec);
2320		if (err < 0) {
2321			alc_free(codec);
2322			return err;
2323		} else if (! err) {
2324			printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS.  Using 3-stack mode...\n");
2325			board_config = ALC880_3ST;
2326		}
2327	}
2328
2329	if (board_config != ALC880_AUTO)
2330		setup_preset(spec, &alc880_presets[board_config]);
2331
2332	spec->stream_name_analog = "ALC880 Analog";
2333	spec->stream_analog_playback = &alc880_pcm_analog_playback;
2334	spec->stream_analog_capture = &alc880_pcm_analog_capture;
2335
2336	spec->stream_name_digital = "ALC880 Digital";
2337	spec->stream_digital_playback = &alc880_pcm_digital_playback;
2338	spec->stream_digital_capture = &alc880_pcm_digital_capture;
2339
2340	if (! spec->adc_nids && spec->input_mux) {
2341		/* check whether NID 0x07 is valid */
2342		unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
2343		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
2344		if (wcap != AC_WID_AUD_IN) {
2345			spec->adc_nids = alc880_adc_nids_alt;
2346			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
2347			spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
2348			spec->num_mixers++;
2349		} else {
2350			spec->adc_nids = alc880_adc_nids;
2351			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
2352			spec->mixers[spec->num_mixers] = alc880_capture_mixer;
2353			spec->num_mixers++;
2354		}
2355	}
2356
2357	codec->patch_ops = alc_patch_ops;
2358	if (board_config == ALC880_AUTO)
2359		codec->patch_ops.init = alc880_auto_init;
2360
2361	return 0;
2362}
2363
2364
2365/*
2366 * ALC260 support
2367 */
2368
2369static hda_nid_t alc260_dac_nids[1] = {
2370	/* front */
2371	0x02,
2372};
2373
2374static hda_nid_t alc260_adc_nids[1] = {
2375	/* ADC0 */
2376	0x04,
2377};
2378
2379static hda_nid_t alc260_adc_nids_alt[1] = {
2380	/* ADC1 */
2381	0x05,
2382};
2383
2384static hda_nid_t alc260_hp_adc_nids[2] = {
2385	/* ADC1, 0 */
2386	0x05, 0x04
2387};
2388
2389static hda_nid_t alc260_fujitsu_adc_nids[2] = {
2390	/* ADC0, ADC1 */
2391	0x04, 0x05
2392};
2393
2394#define ALC260_DIGOUT_NID	0x03
2395#define ALC260_DIGIN_NID	0x06
2396
2397static struct hda_input_mux alc260_capture_source = {
2398	.num_items = 4,
2399	.items = {
2400		{ "Mic", 0x0 },
2401		{ "Front Mic", 0x1 },
2402		{ "Line", 0x2 },
2403		{ "CD", 0x4 },
2404	},
2405};
2406
2407/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack
2408 * and the internal CD lines.
2409 */
2410static struct hda_input_mux alc260_fujitsu_capture_source = {
2411	.num_items = 3,
2412	.items = {
2413		{ "Mic/Line", 0x0 },
2414		{ "CD", 0x4 },
2415		{ "Headphone", 0x2 },
2416	},
2417};
2418
2419/*
2420 * This is just place-holder, so there's something for alc_build_pcms to look
2421 * at when it calculates the maximum number of channels. ALC260 has no mixer
2422 * element which allows changing the channel mode, so the verb list is
2423 * never used.
2424 */
2425static struct hda_channel_mode alc260_modes[1] = {
2426	{ 2, NULL },
2427};
2428
2429
2430/* Mixer combinations
2431 *
2432 * basic: base_output + input + pc_beep + capture
2433 * HP: base_output + input + capture_alt
2434 * HP_3013: hp_3013 + input + capture
2435 * fujitsu: fujitsu + capture
2436 */
2437
2438static struct snd_kcontrol_new alc260_base_output_mixer[] = {
2439	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2440	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
2441	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2442	HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
2443	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2444	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2445	{ } /* end */
2446};
2447
2448static struct snd_kcontrol_new alc260_input_mixer[] = {
2449	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2450	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2451	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
2452	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
2453	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
2454	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
2455	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
2456	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
2457	{ } /* end */
2458};
2459
2460static struct snd_kcontrol_new alc260_pc_beep_mixer[] = {
2461	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
2462	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
2463	{ } /* end */
2464};
2465
2466static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
2467	HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2468	HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
2469	HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
2470	HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
2471	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2472	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
2473	HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2474	HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
2475	{ } /* end */
2476};
2477
2478static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
2479	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2480	HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
2481	ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
2482	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2483	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2484	HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
2485	HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
2486	ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
2487	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
2488	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
2489	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2490	HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),
2491	{ } /* end */
2492};
2493
2494/* capture mixer elements */
2495static struct snd_kcontrol_new alc260_capture_mixer[] = {
2496	HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
2497	HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
2498	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),
2499	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),
2500	{
2501		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2502		/* The multiple "Capture Source" controls confuse alsamixer
2503		 * So call somewhat different..
2504		 * FIXME: the controls appear in the "playback" view!
2505		 */
2506		/* .name = "Capture Source", */
2507		.name = "Input Source",
2508		.count = 2,
2509		.info = alc_mux_enum_info,
2510		.get = alc_mux_enum_get,
2511		.put = alc_mux_enum_put,
2512	},
2513	{ } /* end */
2514};
2515
2516static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {
2517	HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
2518	HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
2519	{
2520		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2521		/* The multiple "Capture Source" controls confuse alsamixer
2522		 * So call somewhat different..
2523		 * FIXME: the controls appear in the "playback" view!
2524		 */
2525		/* .name = "Capture Source", */
2526		.name = "Input Source",
2527		.count = 1,
2528		.info = alc_mux_enum_info,
2529		.get = alc_mux_enum_get,
2530		.put = alc_mux_enum_put,
2531	},
2532	{ } /* end */
2533};
2534
2535/*
2536 * initialization verbs
2537 */
2538static struct hda_verb alc260_init_verbs[] = {
2539	/* Line In pin widget for input */
2540	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2541	/* CD pin widget for input */
2542	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2543	/* Mic1 (rear panel) pin widget for input and vref at 80% */
2544	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2545	/* Mic2 (front panel) pin widget for input and vref at 80% */
2546	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2547	/* LINE-2 is used for line-out in rear */
2548	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2549	/* select line-out */
2550	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
2551	/* LINE-OUT pin */
2552	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2553	/* enable HP */
2554	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2555	/* enable Mono */
2556	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2557	/* mute capture amp left and right */
2558	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2559	/* set connection select to line in (default select for this ADC) */
2560	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2561	/* mute capture amp left and right */
2562	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2563	/* set connection select to line in (default select for this ADC) */
2564	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
2565	/* set vol=0 Line-Out mixer amp left and right */
2566	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2567	/* unmute pin widget amp left and right (no gain on this amp) */
2568	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2569	/* set vol=0 HP mixer amp left and right */
2570	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2571	/* unmute pin widget amp left and right (no gain on this amp) */
2572	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2573	/* set vol=0 Mono mixer amp left and right */
2574	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2575	/* unmute pin widget amp left and right (no gain on this amp) */
2576	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2577	/* unmute LINE-2 out pin */
2578	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2579	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2580	/* mute CD */
2581	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
2582	/* mute Line In */
2583	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2584	/* mute Mic */
2585	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2586	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2587	/* mute Front out path */
2588	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2589	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2590	/* mute Headphone out path */
2591	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2592	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2593	/* mute Mono out path */
2594	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2595	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2596	{ }
2597};
2598
2599static struct hda_verb alc260_hp_init_verbs[] = {
2600	/* Headphone and output */
2601	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
2602	/* mono output */
2603	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2604	/* Mic1 (rear panel) pin widget for input and vref at 80% */
2605	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2606	/* Mic2 (front panel) pin widget for input and vref at 80% */
2607	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2608	/* Line In pin widget for input */
2609	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2610	/* Line-2 pin widget for output */
2611	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2612	/* CD pin widget for input */
2613	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2614	/* unmute amp left and right */
2615	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
2616	/* set connection select to line in (default select for this ADC) */
2617	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2618	/* unmute Line-Out mixer amp left and right (volume = 0) */
2619	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2620	/* mute pin widget amp left and right (no gain on this amp) */
2621	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2622	/* unmute HP mixer amp left and right (volume = 0) */
2623	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2624	/* mute pin widget amp left and right (no gain on this amp) */
2625	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2626	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2627	/* unmute CD */
2628	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
2629	/* unmute Line In */
2630	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
2631	/* unmute Mic */
2632	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2633	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2634	/* Unmute Front out path */
2635	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2636	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2637	/* Unmute Headphone out path */
2638	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2639	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2640	/* Unmute Mono out path */
2641	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2642	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2643	{ }
2644};
2645
2646static struct hda_verb alc260_hp_3013_init_verbs[] = {
2647	/* Line out and output */
2648	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2649	/* mono output */
2650	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2651	/* Mic1 (rear panel) pin widget for input and vref at 80% */
2652	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2653	/* Mic2 (front panel) pin widget for input and vref at 80% */
2654	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2655	/* Line In pin widget for input */
2656	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2657	/* Headphone pin widget for output */
2658	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
2659	/* CD pin widget for input */
2660	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2661	/* unmute amp left and right */
2662	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
2663	/* set connection select to line in (default select for this ADC) */
2664	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2665	/* unmute Line-Out mixer amp left and right (volume = 0) */
2666	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2667	/* mute pin widget amp left and right (no gain on this amp) */
2668	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2669	/* unmute HP mixer amp left and right (volume = 0) */
2670	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2671	/* mute pin widget amp left and right (no gain on this amp) */
2672	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2673	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2674	/* unmute CD */
2675	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
2676	/* unmute Line In */
2677	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
2678	/* unmute Mic */
2679	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2680	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2681	/* Unmute Front out path */
2682	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2683	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2684	/* Unmute Headphone out path */
2685	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2686	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2687	/* Unmute Mono out path */
2688	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2689	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2690	{ }
2691};
2692
2693/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
2694 * laptops.
2695 */
2696static struct hda_verb alc260_fujitsu_init_verbs[] = {
2697	/* Disable all GPIOs */
2698	{0x01, AC_VERB_SET_GPIO_MASK, 0},
2699	/* Internal speaker is connected to headphone pin */
2700	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2701	/* Headphone/Line-out jack connects to Line1 pin; make it an output */
2702	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2703        /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
2704        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2705        /* Ensure all other unused pins are disabled and muted.
2706	 * Note: trying to set widget 0x15 to anything blocks all audio
2707	 * output for some reason, so just leave that at the default.
2708	 */
2709        {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2710        {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2711	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2712        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2713	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2714        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2715        /* Disable digital (SPDIF) pins */
2716        {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
2717        {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
2718
2719        /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
2720         * when acting as an output.
2721         */
2722        {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
2723
2724        /* Start with output sum widgets muted and their output gains at min */
2725	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2726	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2727	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2728	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2729	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2730	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2731	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2732	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2733	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2734
2735        /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
2736        {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2737        /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */
2738        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2739        /* Unmute Line1 pin widget input for when this pin is used as input
2740         * (no equiv mixer ctrl).  Having input and output unmuted doesn't
2741         * seem to cause a problem.
2742         */
2743        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2744	/* Unmute pin widget used for Line-in (no equiv mixer ctrl) */
2745        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2746
2747        /* Mute capture amp left and right */
2748        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2749        /* Set ADC connection select to match default mixer setting - line
2750         * in (on mic1 pin)
2751         */
2752        {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
2753
2754        /* Do the same for the second ADC: mute capture input amp and
2755         * set ADC connection to line in
2756         */
2757        {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2758        {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
2759
2760        /* Mute all inputs to mixer widget (even unconnected ones) */
2761        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
2762        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
2763        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
2764        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
2765        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
2766        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
2767        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
2768        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
2769
2770	{ }
2771};
2772
2773static struct hda_pcm_stream alc260_pcm_analog_playback = {
2774	.substreams = 1,
2775	.channels_min = 2,
2776	.channels_max = 2,
2777};
2778
2779static struct hda_pcm_stream alc260_pcm_analog_capture = {
2780	.substreams = 1,
2781	.channels_min = 2,
2782	.channels_max = 2,
2783};
2784
2785#define alc260_pcm_digital_playback	alc880_pcm_digital_playback
2786#define alc260_pcm_digital_capture	alc880_pcm_digital_capture
2787
2788/*
2789 * for BIOS auto-configuration
2790 */
2791
2792static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
2793					const char *pfx)
2794{
2795	hda_nid_t nid_vol;
2796	unsigned long vol_val, sw_val;
2797	char name[32];
2798	int err;
2799
2800	if (nid >= 0x0f && nid < 0x11) {
2801		nid_vol = nid - 0x7;
2802		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
2803		sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2804	} else if (nid == 0x11) {
2805		nid_vol = nid - 0x7;
2806		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
2807		sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
2808	} else if (nid >= 0x12 && nid <= 0x15) {
2809		nid_vol = 0x08;
2810		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
2811		sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2812	} else
2813		return 0; /* N/A */
2814
2815	snprintf(name, sizeof(name), "%s Playback Volume", pfx);
2816	if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val)) < 0)
2817		return err;
2818	snprintf(name, sizeof(name), "%s Playback Switch", pfx);
2819	if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val)) < 0)
2820		return err;
2821	return 1;
2822}
2823
2824/* add playback controls from the parsed DAC table */
2825static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
2826					     const struct auto_pin_cfg *cfg)
2827{
2828	hda_nid_t nid;
2829	int err;
2830
2831	spec->multiout.num_dacs = 1;
2832	spec->multiout.dac_nids = spec->private_dac_nids;
2833	spec->multiout.dac_nids[0] = 0x02;
2834
2835	nid = cfg->line_out_pins[0];
2836	if (nid) {
2837		err = alc260_add_playback_controls(spec, nid, "Front");
2838		if (err < 0)
2839			return err;
2840	}
2841
2842	nid = cfg->speaker_pin;
2843	if (nid) {
2844		err = alc260_add_playback_controls(spec, nid, "Speaker");
2845		if (err < 0)
2846			return err;
2847	}
2848
2849	nid = cfg->hp_pin;
2850	if (nid) {
2851		err = alc260_add_playback_controls(spec, nid, "Headphone");
2852		if (err < 0)
2853			return err;
2854	}
2855	return 0;
2856}
2857
2858/* create playback/capture controls for input pins */
2859static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
2860						const struct auto_pin_cfg *cfg)
2861{
2862	struct hda_input_mux *imux = &spec->private_imux;
2863	int i, err, idx;
2864
2865	for (i = 0; i < AUTO_PIN_LAST; i++) {
2866		if (cfg->input_pins[i] >= 0x12) {
2867			idx = cfg->input_pins[i] - 0x12;
2868			err = new_analog_input(spec, cfg->input_pins[i],
2869					       auto_pin_cfg_labels[i], idx, 0x07);
2870			if (err < 0)
2871				return err;
2872			imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2873			imux->items[imux->num_items].index = idx;
2874			imux->num_items++;
2875		}
2876		if ((cfg->input_pins[i] >= 0x0f) && (cfg->input_pins[i] <= 0x10)){
2877			idx = cfg->input_pins[i] - 0x09;
2878			err = new_analog_input(spec, cfg->input_pins[i],
2879					       auto_pin_cfg_labels[i], idx, 0x07);
2880			if (err < 0)
2881				return err;
2882			imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2883			imux->items[imux->num_items].index = idx;
2884			imux->num_items++;
2885		}
2886	}
2887	return 0;
2888}
2889
2890static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
2891					      hda_nid_t nid, int pin_type,
2892					      int sel_idx)
2893{
2894	/* set as output */
2895	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2896	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2897	/* need the manual connection? */
2898	if (nid >= 0x12) {
2899		int idx = nid - 0x12;
2900		snd_hda_codec_write(codec, idx + 0x0b, 0,
2901				    AC_VERB_SET_CONNECT_SEL, sel_idx);
2902
2903	}
2904}
2905
2906static void alc260_auto_init_multi_out(struct hda_codec *codec)
2907{
2908	struct alc_spec *spec = codec->spec;
2909	hda_nid_t nid;
2910
2911	nid = spec->autocfg.line_out_pins[0];
2912	if (nid)
2913		alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
2914
2915	nid = spec->autocfg.speaker_pin;
2916	if (nid)
2917		alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
2918
2919	nid = spec->autocfg.hp_pin;
2920	if (nid)
2921		alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
2922}
2923
2924#define ALC260_PIN_CD_NID		0x16
2925static void alc260_auto_init_analog_input(struct hda_codec *codec)
2926{
2927	struct alc_spec *spec = codec->spec;
2928	int i;
2929
2930	for (i = 0; i < AUTO_PIN_LAST; i++) {
2931		hda_nid_t nid = spec->autocfg.input_pins[i];
2932		if (nid >= 0x12) {
2933			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2934					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2935			if (nid != ALC260_PIN_CD_NID)
2936				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2937						    AMP_OUT_MUTE);
2938		}
2939	}
2940}
2941
2942/*
2943 * generic initialization of ADC, input mixers and output mixers
2944 */
2945static struct hda_verb alc260_volume_init_verbs[] = {
2946	/*
2947	 * Unmute ADC0-1 and set the default input to mic-in
2948	 */
2949	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
2950	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2951	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
2952	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2953
2954	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
2955	 * mixer widget
2956	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
2957	 * mic (mic 2)
2958	 */
2959	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
2960	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2961	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2962	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2963	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
2964	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
2965
2966	/*
2967	 * Set up output mixers (0x08 - 0x0a)
2968	 */
2969	/* set vol=0 to output mixers */
2970	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2971	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2972	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2973	/* set up input amps for analog loopback */
2974	/* Amp Indices: DAC = 0, mixer = 1 */
2975	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2976	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2977	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2978	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2979	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2980	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2981
2982	{ }
2983};
2984
2985static int alc260_parse_auto_config(struct hda_codec *codec)
2986{
2987	struct alc_spec *spec = codec->spec;
2988	unsigned int wcap;
2989	int err;
2990	static hda_nid_t alc260_ignore[] = { 0x17, 0 };
2991
2992	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
2993						alc260_ignore)) < 0)
2994		return err;
2995	if ((err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0)
2996		return err;
2997	if (! spec->kctl_alloc)
2998		return 0; /* can't find valid BIOS pin config */
2999	if ((err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
3000		return err;
3001
3002	spec->multiout.max_channels = 2;
3003
3004	if (spec->autocfg.dig_out_pin)
3005		spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
3006	if (spec->kctl_alloc)
3007		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
3008
3009	spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
3010
3011	spec->input_mux = &spec->private_imux;
3012
3013	/* check whether NID 0x04 is valid */
3014	wcap = get_wcaps(codec, 0x04);
3015	wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3016	if (wcap != AC_WID_AUD_IN) {
3017		spec->adc_nids = alc260_adc_nids_alt;
3018		spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
3019		spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
3020	} else {
3021		spec->adc_nids = alc260_adc_nids;
3022		spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
3023		spec->mixers[spec->num_mixers] = alc260_capture_mixer;
3024	}
3025	spec->num_mixers++;
3026
3027	return 1;
3028}
3029
3030/* init callback for auto-configuration model -- overriding the default init */
3031static int alc260_auto_init(struct hda_codec *codec)
3032{
3033	alc_init(codec);
3034	alc260_auto_init_multi_out(codec);
3035	alc260_auto_init_analog_input(codec);
3036	return 0;
3037}
3038
3039/*
3040 * ALC260 configurations
3041 */
3042static struct hda_board_config alc260_cfg_tbl[] = {
3043	{ .modelname = "basic", .config = ALC260_BASIC },
3044	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb,
3045	  .config = ALC260_BASIC }, /* Sony VAIO */
3046	{ .modelname = "hp", .config = ALC260_HP },
3047	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP },
3048	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
3049	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP },
3050	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 },
3051	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP },
3052	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP },
3053	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP },
3054	{ .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X },
3055	{ .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X },
3056	{ .modelname = "auto", .config = ALC260_AUTO },
3057	{}
3058};
3059
3060static struct alc_config_preset alc260_presets[] = {
3061	[ALC260_BASIC] = {
3062		.mixers = { alc260_base_output_mixer,
3063			    alc260_input_mixer,
3064			    alc260_pc_beep_mixer,
3065			    alc260_capture_mixer },
3066		.init_verbs = { alc260_init_verbs },
3067		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
3068		.dac_nids = alc260_dac_nids,
3069		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
3070		.adc_nids = alc260_adc_nids,
3071		.num_channel_mode = ARRAY_SIZE(alc260_modes),
3072		.channel_mode = alc260_modes,
3073		.input_mux = &alc260_capture_source,
3074	},
3075	[ALC260_HP] = {
3076		.mixers = { alc260_base_output_mixer,
3077			    alc260_input_mixer,
3078			    alc260_capture_alt_mixer },
3079		.init_verbs = { alc260_hp_init_verbs },
3080		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
3081		.dac_nids = alc260_dac_nids,
3082		.num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
3083		.adc_nids = alc260_hp_adc_nids,
3084		.num_channel_mode = ARRAY_SIZE(alc260_modes),
3085		.channel_mode = alc260_modes,
3086		.input_mux = &alc260_capture_source,
3087	},
3088	[ALC260_HP_3013] = {
3089		.mixers = { alc260_hp_3013_mixer,
3090			    alc260_input_mixer,
3091			    alc260_capture_alt_mixer },
3092		.init_verbs = { alc260_hp_3013_init_verbs },
3093		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
3094		.dac_nids = alc260_dac_nids,
3095		.num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
3096		.adc_nids = alc260_hp_adc_nids,
3097		.num_channel_mode = ARRAY_SIZE(alc260_modes),
3098		.channel_mode = alc260_modes,
3099		.input_mux = &alc260_capture_source,
3100	},
3101	[ALC260_FUJITSU_S702X] = {
3102		.mixers = { alc260_fujitsu_mixer,
3103			    alc260_capture_mixer },
3104		.init_verbs = { alc260_fujitsu_init_verbs },
3105		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
3106		.dac_nids = alc260_dac_nids,
3107		.num_adc_nids = ARRAY_SIZE(alc260_fujitsu_adc_nids),
3108		.adc_nids = alc260_fujitsu_adc_nids,
3109		.num_channel_mode = ARRAY_SIZE(alc260_modes),
3110		.channel_mode = alc260_modes,
3111		.input_mux = &alc260_fujitsu_capture_source,
3112	},
3113};
3114
3115static int patch_alc260(struct hda_codec *codec)
3116{
3117	struct alc_spec *spec;
3118	int err, board_config;
3119
3120	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3121	if (spec == NULL)
3122		return -ENOMEM;
3123
3124	codec->spec = spec;
3125
3126	board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
3127	if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
3128		snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
3129		board_config = ALC260_AUTO;
3130	}
3131
3132	if (board_config == ALC260_AUTO) {
3133		/* automatic parse from the BIOS config */
3134		err = alc260_parse_auto_config(codec);
3135		if (err < 0) {
3136			alc_free(codec);
3137			return err;
3138		} else if (! err) {
3139			printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS.  Using base mode...\n");
3140			board_config = ALC260_BASIC;
3141		}
3142	}
3143
3144	if (board_config != ALC260_AUTO)
3145		setup_preset(spec, &alc260_presets[board_config]);
3146
3147	spec->stream_name_analog = "ALC260 Analog";
3148	spec->stream_analog_playback = &alc260_pcm_analog_playback;
3149	spec->stream_analog_capture = &alc260_pcm_analog_capture;
3150
3151	spec->stream_name_digital = "ALC260 Digital";
3152	spec->stream_digital_playback = &alc260_pcm_digital_playback;
3153	spec->stream_digital_capture = &alc260_pcm_digital_capture;
3154
3155	codec->patch_ops = alc_patch_ops;
3156	if (board_config == ALC260_AUTO)
3157		codec->patch_ops.init = alc260_auto_init;
3158
3159	return 0;
3160}
3161
3162
3163/*
3164 * ALC882 support
3165 *
3166 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3167 * configuration.  Each pin widget can choose any input DACs and a mixer.
3168 * Each ADC is connected from a mixer of all inputs.  This makes possible
3169 * 6-channel independent captures.
3170 *
3171 * In addition, an independent DAC for the multi-playback (not used in this
3172 * driver yet).
3173 */
3174#define ALC882_DIGOUT_NID	0x06
3175#define ALC882_DIGIN_NID	0x0a
3176
3177static struct hda_channel_mode alc882_ch_modes[1] = {
3178	{ 8, NULL }
3179};
3180
3181static hda_nid_t alc882_dac_nids[4] = {
3182	/* front, rear, clfe, rear_surr */
3183	0x02, 0x03, 0x04, 0x05
3184};
3185
3186/* identical with ALC880 */
3187#define alc882_adc_nids		alc880_adc_nids
3188#define alc882_adc_nids_alt	alc880_adc_nids_alt
3189
3190/* input MUX */
3191/* FIXME: should be a matrix-type input source selection */
3192
3193static struct hda_input_mux alc882_capture_source = {
3194	.num_items = 4,
3195	.items = {
3196		{ "Mic", 0x0 },
3197		{ "Front Mic", 0x1 },
3198		{ "Line", 0x2 },
3199		{ "CD", 0x4 },
3200	},
3201};
3202
3203#define alc882_mux_enum_info alc_mux_enum_info
3204#define alc882_mux_enum_get alc_mux_enum_get
3205
3206static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3207{
3208	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3209	struct alc_spec *spec = codec->spec;
3210	const struct hda_input_mux *imux = spec->input_mux;
3211	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3212	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
3213	hda_nid_t nid = capture_mixers[adc_idx];
3214	unsigned int *cur_val = &spec->cur_mux[adc_idx];
3215	unsigned int i, idx;
3216
3217	idx = ucontrol->value.enumerated.item[0];
3218	if (idx >= imux->num_items)
3219		idx = imux->num_items - 1;
3220	if (*cur_val == idx && ! codec->in_resume)
3221		return 0;
3222	for (i = 0; i < imux->num_items; i++) {
3223		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
3224		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3225				    v | (imux->items[i].index << 8));
3226	}
3227	*cur_val = idx;
3228	return 1;
3229}
3230
3231/*
3232 * 6ch mode
3233 */
3234static struct hda_verb alc882_sixstack_ch6_init[] = {
3235	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
3236	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3237	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3238	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3239	{ } /* end */
3240};
3241
3242/*
3243 * 8ch mode
3244 */
3245static struct hda_verb alc882_sixstack_ch8_init[] = {
3246	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3247	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3248	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3249	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3250	{ } /* end */
3251};
3252
3253static struct hda_channel_mode alc882_sixstack_modes[2] = {
3254	{ 6, alc882_sixstack_ch6_init },
3255	{ 8, alc882_sixstack_ch8_init },
3256};
3257
3258/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
3259 *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
3260 */
3261static struct snd_kcontrol_new alc882_base_mixer[] = {
3262	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3263	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3264	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3265	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
3266	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3267	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3268	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3269	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3270	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3271	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
3272	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
3273	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3274	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3275	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3276	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3277	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3278	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3279	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3280	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3281	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
3282	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
3283	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
3284	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
3285	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
3286	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
3287	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
3288	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
3289	{
3290		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3291		/* .name = "Capture Source", */
3292		.name = "Input Source",
3293		.count = 3,
3294		.info = alc882_mux_enum_info,
3295		.get = alc882_mux_enum_get,
3296		.put = alc882_mux_enum_put,
3297	},
3298	{ } /* end */
3299};
3300
3301static struct snd_kcontrol_new alc882_chmode_mixer[] = {
3302	{
3303		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3304		.name = "Channel Mode",
3305		.info = alc_ch_mode_info,
3306		.get = alc_ch_mode_get,
3307		.put = alc_ch_mode_put,
3308	},
3309	{ } /* end */
3310};
3311
3312static struct hda_verb alc882_init_verbs[] = {
3313	/* Front mixer: unmute input/output amp left and right (volume = 0) */
3314	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3315	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3316	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3317	/* Rear mixer */
3318	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3319	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3320	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3321	/* CLFE mixer */
3322	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3323	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3324	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3325	/* Side mixer */
3326	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3327	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3328	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3329
3330	/* Front Pin: output 0 (0x0c) */
3331	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3332	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3333	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
3334	/* Rear Pin: output 1 (0x0d) */
3335	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3336	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3337	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
3338	/* CLFE Pin: output 2 (0x0e) */
3339	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3340	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3341	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
3342	/* Side Pin: output 3 (0x0f) */
3343	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3344	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3345	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
3346	/* Mic (rear) pin: input vref at 80% */
3347	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3348	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3349	/* Front Mic pin: input vref at 80% */
3350	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3351	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3352	/* Line In pin: input */
3353	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3354	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3355	/* Line-2 In: Headphone output (output 0 - 0x0c) */
3356	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3357	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3358	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
3359	/* CD pin widget for input */
3360	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3361
3362	/* FIXME: use matrix-type input source selection */
3363	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3364	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3365	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3366	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3367	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3368	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3369	/* Input mixer2 */
3370	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3371	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3372	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3373	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3374	/* Input mixer3 */
3375	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3376	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3377	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3378	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3379	/* ADC1: mute amp left and right */
3380	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3381	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3382	/* ADC2: mute amp left and right */
3383	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3384	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3385	/* ADC3: mute amp left and right */
3386	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3387	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3388
3389	{ }
3390};
3391
3392/*
3393 * generic initialization of ADC, input mixers and output mixers
3394 */
3395static struct hda_verb alc882_auto_init_verbs[] = {
3396	/*
3397	 * Unmute ADC0-2 and set the default input to mic-in
3398	 */
3399	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3400	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3401	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3402	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3403	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3404	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3405
3406	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3407	 * mixer widget
3408	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3409	 * mic (mic 2)
3410	 */
3411	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3412	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3413	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3414	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3415	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3416	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3417
3418	/*
3419	 * Set up output mixers (0x0c - 0x0f)
3420	 */
3421	/* set vol=0 to output mixers */
3422	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3423	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3424	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3425	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3426	/* set up input amps for analog loopback */
3427	/* Amp Indices: DAC = 0, mixer = 1 */
3428	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3429	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3430	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3431	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3432	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3433	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3434	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3435	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3436	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3437	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3438
3439	/* FIXME: use matrix-type input source selection */
3440	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3441	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3442	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3443	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3444	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3445	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3446	/* Input mixer2 */
3447	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3448	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3449	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3450	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3451	/* Input mixer3 */
3452	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3453	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3454	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3455	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3456
3457	{ }
3458};
3459
3460/* capture mixer elements */
3461static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
3462	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3463	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3464	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
3465	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
3466	{
3467		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3468		/* The multiple "Capture Source" controls confuse alsamixer
3469		 * So call somewhat different..
3470		 * FIXME: the controls appear in the "playback" view!
3471		 */
3472		/* .name = "Capture Source", */
3473		.name = "Input Source",
3474		.count = 2,
3475		.info = alc882_mux_enum_info,
3476		.get = alc882_mux_enum_get,
3477		.put = alc882_mux_enum_put,
3478	},
3479	{ } /* end */
3480};
3481
3482static struct snd_kcontrol_new alc882_capture_mixer[] = {
3483	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
3484	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
3485	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
3486	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
3487	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
3488	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
3489	{
3490		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3491		/* The multiple "Capture Source" controls confuse alsamixer
3492		 * So call somewhat different..
3493		 * FIXME: the controls appear in the "playback" view!
3494		 */
3495		/* .name = "Capture Source", */
3496		.name = "Input Source",
3497		.count = 3,
3498		.info = alc882_mux_enum_info,
3499		.get = alc882_mux_enum_get,
3500		.put = alc882_mux_enum_put,
3501	},
3502	{ } /* end */
3503};
3504
3505/* pcm configuration: identiacal with ALC880 */
3506#define alc882_pcm_analog_playback	alc880_pcm_analog_playback
3507#define alc882_pcm_analog_capture	alc880_pcm_analog_capture
3508#define alc882_pcm_digital_playback	alc880_pcm_digital_playback
3509#define alc882_pcm_digital_capture	alc880_pcm_digital_capture
3510
3511/*
3512 * configuration and preset
3513 */
3514static struct hda_board_config alc882_cfg_tbl[] = {
3515	{ .modelname = "3stack-dig", .config = ALC882_3ST_DIG },
3516	{ .modelname = "6stack-dig", .config = ALC882_6ST_DIG },
3517	{ .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* MSI  */
3518	{ .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* Foxconn */
3519	{ .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS */
3520	{ .modelname = "auto", .config = ALC882_AUTO },
3521	{}
3522};
3523
3524static struct alc_config_preset alc882_presets[] = {
3525	[ALC882_3ST_DIG] = {
3526		.mixers = { alc882_base_mixer },
3527		.init_verbs = { alc882_init_verbs },
3528		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
3529		.dac_nids = alc882_dac_nids,
3530		.dig_out_nid = ALC882_DIGOUT_NID,
3531		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
3532		.adc_nids = alc882_adc_nids,
3533		.dig_in_nid = ALC882_DIGIN_NID,
3534		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
3535		.channel_mode = alc882_ch_modes,
3536		.input_mux = &alc882_capture_source,
3537	},
3538	[ALC882_6ST_DIG] = {
3539		.mixers = { alc882_base_mixer, alc882_chmode_mixer },
3540		.init_verbs = { alc882_init_verbs },
3541		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
3542		.dac_nids = alc882_dac_nids,
3543		.dig_out_nid = ALC882_DIGOUT_NID,
3544		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
3545		.adc_nids = alc882_adc_nids,
3546		.dig_in_nid = ALC882_DIGIN_NID,
3547		.num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
3548		.channel_mode = alc882_sixstack_modes,
3549		.input_mux = &alc882_capture_source,
3550	},
3551};
3552
3553
3554/*
3555 * BIOS auto configuration
3556 */
3557static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
3558					      hda_nid_t nid, int pin_type,
3559					      int dac_idx)
3560{
3561	/* set as output */
3562	struct alc_spec *spec = codec->spec;
3563	int idx;
3564
3565	if (spec->multiout.dac_nids[dac_idx] == 0x25)
3566		idx = 4;
3567	else
3568		idx = spec->multiout.dac_nids[dac_idx] - 2;
3569
3570	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3571	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3572	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
3573
3574}
3575
3576static void alc882_auto_init_multi_out(struct hda_codec *codec)
3577{
3578	struct alc_spec *spec = codec->spec;
3579	int i;
3580
3581	for (i = 0; i <= HDA_SIDE; i++) {
3582		hda_nid_t nid = spec->autocfg.line_out_pins[i];
3583		if (nid)
3584			alc882_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
3585	}
3586}
3587
3588static void alc882_auto_init_hp_out(struct hda_codec *codec)
3589{
3590	struct alc_spec *spec = codec->spec;
3591	hda_nid_t pin;
3592
3593	pin = spec->autocfg.hp_pin;
3594	if (pin) /* connect to front */
3595		alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */
3596}
3597
3598#define alc882_is_input_pin(nid)	alc880_is_input_pin(nid)
3599#define ALC882_PIN_CD_NID		ALC880_PIN_CD_NID
3600
3601static void alc882_auto_init_analog_input(struct hda_codec *codec)
3602{
3603	struct alc_spec *spec = codec->spec;
3604	int i;
3605
3606	for (i = 0; i < AUTO_PIN_LAST; i++) {
3607		hda_nid_t nid = spec->autocfg.input_pins[i];
3608		if (alc882_is_input_pin(nid)) {
3609			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3610					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
3611			if (nid != ALC882_PIN_CD_NID)
3612				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3613						    AMP_OUT_MUTE);
3614		}
3615	}
3616}
3617
3618/* almost identical with ALC880 parser... */
3619static int alc882_parse_auto_config(struct hda_codec *codec)
3620{
3621	struct alc_spec *spec = codec->spec;
3622	int err = alc880_parse_auto_config(codec);
3623
3624	if (err < 0)
3625		return err;
3626	else if (err > 0)
3627		/* hack - override the init verbs */
3628		spec->init_verbs[0] = alc882_auto_init_verbs;
3629	return err;
3630}
3631
3632/* init callback for auto-configuration model -- overriding the default init */
3633static int alc882_auto_init(struct hda_codec *codec)
3634{
3635	alc_init(codec);
3636	alc882_auto_init_multi_out(codec);
3637	alc882_auto_init_hp_out(codec);
3638	alc882_auto_init_analog_input(codec);
3639	return 0;
3640}
3641
3642/*
3643 *  ALC882 Headphone poll in 3.5.1a or 3.5.2
3644 */
3645
3646static int patch_alc882(struct hda_codec *codec)
3647{
3648	struct alc_spec *spec;
3649	int err, board_config;
3650
3651	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3652	if (spec == NULL)
3653		return -ENOMEM;
3654
3655	codec->spec = spec;
3656
3657	board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl);
3658
3659	if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
3660		printk(KERN_INFO "hda_codec: Unknown model for ALC882, trying auto-probe from BIOS...\n");
3661		board_config = ALC882_AUTO;
3662	}
3663
3664	if (board_config == ALC882_AUTO) {
3665		/* automatic parse from the BIOS config */
3666		err = alc882_parse_auto_config(codec);
3667		if (err < 0) {
3668			alc_free(codec);
3669			return err;
3670		} else if (! err) {
3671			printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS.  Using base mode...\n");
3672			board_config = ALC882_3ST_DIG;
3673		}
3674	}
3675
3676	if (board_config != ALC882_AUTO)
3677		setup_preset(spec, &alc882_presets[board_config]);
3678
3679	spec->stream_name_analog = "ALC882 Analog";
3680	spec->stream_analog_playback = &alc882_pcm_analog_playback;
3681	spec->stream_analog_capture = &alc882_pcm_analog_capture;
3682
3683	spec->stream_name_digital = "ALC882 Digital";
3684	spec->stream_digital_playback = &alc882_pcm_digital_playback;
3685	spec->stream_digital_capture = &alc882_pcm_digital_capture;
3686
3687	if (! spec->adc_nids && spec->input_mux) {
3688		/* check whether NID 0x07 is valid */
3689		unsigned int wcap = get_wcaps(codec, 0x07);
3690		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3691		if (wcap != AC_WID_AUD_IN) {
3692			spec->adc_nids = alc882_adc_nids_alt;
3693			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
3694			spec->mixers[spec->num_mixers] = alc882_capture_alt_mixer;
3695			spec->num_mixers++;
3696		} else {
3697			spec->adc_nids = alc882_adc_nids;
3698			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
3699			spec->mixers[spec->num_mixers] = alc882_capture_mixer;
3700			spec->num_mixers++;
3701		}
3702	}
3703
3704	codec->patch_ops = alc_patch_ops;
3705	if (board_config == ALC882_AUTO)
3706		codec->patch_ops.init = alc882_auto_init;
3707
3708	return 0;
3709}
3710
3711/*
3712 * ALC262 support
3713 */
3714
3715#define ALC262_DIGOUT_NID	ALC880_DIGOUT_NID
3716#define ALC262_DIGIN_NID	ALC880_DIGIN_NID
3717
3718#define alc262_dac_nids		alc260_dac_nids
3719#define alc262_adc_nids		alc882_adc_nids
3720#define alc262_adc_nids_alt	alc882_adc_nids_alt
3721
3722#define alc262_modes		alc260_modes
3723#define alc262_capture_source	alc882_capture_source
3724
3725static struct snd_kcontrol_new alc262_base_mixer[] = {
3726	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3727	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
3728	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3729	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3730	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3731	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3732	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3733	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3734	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
3735	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
3736	/* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
3737	   HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
3738	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
3739	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
3740	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3741	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
3742	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3743	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3744	{
3745		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3746		.name = "Capture Source",
3747		.count = 1,
3748		.info = alc882_mux_enum_info,
3749		.get = alc882_mux_enum_get,
3750		.put = alc882_mux_enum_put,
3751	},
3752	{ } /* end */
3753};
3754
3755#define alc262_capture_mixer		alc882_capture_mixer
3756#define alc262_capture_alt_mixer	alc882_capture_alt_mixer
3757
3758/*
3759 * generic initialization of ADC, input mixers and output mixers
3760 */
3761static struct hda_verb alc262_init_verbs[] = {
3762	/*
3763	 * Unmute ADC0-2 and set the default input to mic-in
3764	 */
3765	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3766	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3767	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3768	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3769	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3770	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3771
3772	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3773	 * mixer widget
3774	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3775	 * mic (mic 2)
3776	 */
3777	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3778	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3779	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3780	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3781	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3782	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3783
3784	/*
3785	 * Set up output mixers (0x0c - 0x0e)
3786	 */
3787	/* set vol=0 to output mixers */
3788	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3789	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3790	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3791	/* set up input amps for analog loopback */
3792	/* Amp Indices: DAC = 0, mixer = 1 */
3793	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3794	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3795	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3796	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3797	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3798	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3799
3800	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3801	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
3802	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3803	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3804	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3805	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3806
3807	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3808	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3809	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3810	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3811	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3812
3813	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
3814	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
3815
3816	/* FIXME: use matrix-type input source selection */
3817	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3818	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3819	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3820	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3821	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3822	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3823	/* Input mixer2 */
3824	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3825	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3826	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3827	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3828	/* Input mixer3 */
3829	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3830	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3831	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3832	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3833
3834	{ }
3835};
3836
3837/* add playback controls from the parsed DAC table */
3838static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
3839{
3840	hda_nid_t nid;
3841	int err;
3842
3843	spec->multiout.num_dacs = 1;	/* only use one dac */
3844	spec->multiout.dac_nids = spec->private_dac_nids;
3845	spec->multiout.dac_nids[0] = 2;
3846
3847	nid = cfg->line_out_pins[0];
3848	if (nid) {
3849		if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Front Playback Volume",
3850				       HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
3851			return err;
3852		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Front Playback Switch",
3853				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
3854			return err;
3855	}
3856
3857	nid = cfg->speaker_pin;
3858	if (nid) {
3859		if (nid == 0x16) {
3860			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
3861					       HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
3862				return err;
3863			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
3864					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
3865				return err;
3866		} else {
3867			if (! cfg->line_out_pins[0])
3868				if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
3869					       HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
3870					return err;
3871			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
3872					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
3873				return err;
3874		}
3875	}
3876	nid = cfg->hp_pin;
3877	if (nid) {
3878		/* spec->multiout.hp_nid = 2; */
3879		if (nid == 0x16) {
3880			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
3881					       HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
3882				return err;
3883			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
3884					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
3885				return err;
3886		} else {
3887			if (! cfg->line_out_pins[0])
3888				if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
3889					       HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
3890					return err;
3891			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
3892					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
3893				return err;
3894		}
3895	}
3896	return 0;
3897}
3898
3899/* identical with ALC880 */
3900#define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls
3901
3902/*
3903 * generic initialization of ADC, input mixers and output mixers
3904 */
3905static struct hda_verb alc262_volume_init_verbs[] = {
3906	/*
3907	 * Unmute ADC0-2 and set the default input to mic-in
3908	 */
3909	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3910	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3911	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3912	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3913	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3914	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3915
3916	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3917	 * mixer widget
3918	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3919	 * mic (mic 2)
3920	 */
3921	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3922	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3923	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3924	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3925	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3926	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3927
3928	/*
3929	 * Set up output mixers (0x0c - 0x0f)
3930	 */
3931	/* set vol=0 to output mixers */
3932	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3933	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3934	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3935
3936	/* set up input amps for analog loopback */
3937	/* Amp Indices: DAC = 0, mixer = 1 */
3938	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3939	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3940	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3941	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3942	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3943	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3944
3945	/* FIXME: use matrix-type input source selection */
3946	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3947	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3948	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3949	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3950	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3951	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3952	/* Input mixer2 */
3953	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3954	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3955	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3956	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3957	/* Input mixer3 */
3958	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3959	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3960	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3961	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3962
3963	{ }
3964};
3965
3966/* pcm configuration: identiacal with ALC880 */
3967#define alc262_pcm_analog_playback	alc880_pcm_analog_playback
3968#define alc262_pcm_analog_capture	alc880_pcm_analog_capture
3969#define alc262_pcm_digital_playback	alc880_pcm_digital_playback
3970#define alc262_pcm_digital_capture	alc880_pcm_digital_capture
3971
3972/*
3973 * BIOS auto configuration
3974 */
3975static int alc262_parse_auto_config(struct hda_codec *codec)
3976{
3977	struct alc_spec *spec = codec->spec;
3978	int err;
3979	static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
3980
3981	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3982						alc262_ignore)) < 0)
3983		return err;
3984	if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
3985	    ! spec->autocfg.hp_pin)
3986		return 0; /* can't find valid BIOS pin config */
3987	if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
3988	    (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
3989		return err;
3990
3991	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3992
3993	if (spec->autocfg.dig_out_pin)
3994		spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
3995	if (spec->autocfg.dig_in_pin)
3996		spec->dig_in_nid = ALC262_DIGIN_NID;
3997
3998	if (spec->kctl_alloc)
3999		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4000
4001	spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
4002	spec->input_mux = &spec->private_imux;
4003
4004	return 1;
4005}
4006
4007#define alc262_auto_init_multi_out	alc882_auto_init_multi_out
4008#define alc262_auto_init_hp_out		alc882_auto_init_hp_out
4009#define alc262_auto_init_analog_input	alc882_auto_init_analog_input
4010
4011
4012/* init callback for auto-configuration model -- overriding the default init */
4013static int alc262_auto_init(struct hda_codec *codec)
4014{
4015	alc_init(codec);
4016	alc262_auto_init_multi_out(codec);
4017	alc262_auto_init_hp_out(codec);
4018	alc262_auto_init_analog_input(codec);
4019	return 0;
4020}
4021
4022/*
4023 * configuration and preset
4024 */
4025static struct hda_board_config alc262_cfg_tbl[] = {
4026	{ .modelname = "basic", .config = ALC262_BASIC },
4027	{ .modelname = "auto", .config = ALC262_AUTO },
4028	{}
4029};
4030
4031static struct alc_config_preset alc262_presets[] = {
4032	[ALC262_BASIC] = {
4033		.mixers = { alc262_base_mixer },
4034		.init_verbs = { alc262_init_verbs },
4035		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
4036		.dac_nids = alc262_dac_nids,
4037		.hp_nid = 0x03,
4038		.num_channel_mode = ARRAY_SIZE(alc262_modes),
4039		.channel_mode = alc262_modes,
4040		.input_mux = &alc262_capture_source,
4041	},
4042};
4043
4044static int patch_alc262(struct hda_codec *codec)
4045{
4046	struct alc_spec *spec;
4047	int board_config;
4048	int err;
4049
4050	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
4051	if (spec == NULL)
4052		return -ENOMEM;
4053
4054	codec->spec = spec;
4055#if 0
4056	/* pshou 07/11/05  set a zero PCM sample to DAC when FIFO is under-run */
4057	{
4058	int tmp;
4059	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4060	tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4061	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4062	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4063	}
4064#endif
4065
4066	board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl);
4067	if (board_config < 0 || board_config >= ALC262_MODEL_LAST) {
4068		printk(KERN_INFO "hda_codec: Unknown model for ALC262, trying auto-probe from BIOS...\n");
4069		board_config = ALC262_AUTO;
4070	}
4071
4072	if (board_config == ALC262_AUTO) {
4073		/* automatic parse from the BIOS config */
4074		err = alc262_parse_auto_config(codec);
4075		if (err < 0) {
4076			alc_free(codec);
4077			return err;
4078		} else if (! err) {
4079			printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS.  Using base mode...\n");
4080			board_config = ALC262_BASIC;
4081		}
4082	}
4083
4084	if (board_config != ALC262_AUTO)
4085		setup_preset(spec, &alc262_presets[board_config]);
4086
4087	spec->stream_name_analog = "ALC262 Analog";
4088	spec->stream_analog_playback = &alc262_pcm_analog_playback;
4089	spec->stream_analog_capture = &alc262_pcm_analog_capture;
4090
4091	spec->stream_name_digital = "ALC262 Digital";
4092	spec->stream_digital_playback = &alc262_pcm_digital_playback;
4093	spec->stream_digital_capture = &alc262_pcm_digital_capture;
4094
4095	if (! spec->adc_nids && spec->input_mux) {
4096		/* check whether NID 0x07 is valid */
4097		unsigned int wcap = get_wcaps(codec, 0x07);
4098
4099		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
4100		if (wcap != AC_WID_AUD_IN) {
4101			spec->adc_nids = alc262_adc_nids_alt;
4102			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
4103			spec->mixers[spec->num_mixers] = alc262_capture_alt_mixer;
4104			spec->num_mixers++;
4105		} else {
4106			spec->adc_nids = alc262_adc_nids;
4107			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
4108			spec->mixers[spec->num_mixers] = alc262_capture_mixer;
4109			spec->num_mixers++;
4110		}
4111	}
4112
4113	codec->patch_ops = alc_patch_ops;
4114	if (board_config == ALC262_AUTO)
4115		codec->patch_ops.init = alc262_auto_init;
4116
4117	return 0;
4118}
4119
4120
4121/*
4122 *  ALC861 channel source setting (2/6 channel selection for 3-stack)
4123 */
4124
4125/*
4126 * set the path ways for 2 channel output
4127 * need to set the codec line out and mic 1 pin widgets to inputs
4128 */
4129static struct hda_verb alc861_threestack_ch2_init[] = {
4130	/* set pin widget 1Ah (line in) for input */
4131	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4132	/* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
4133	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4134
4135        { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
4136        { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, //mic
4137        { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, //line in
4138	{ } /* end */
4139};
4140/*
4141 * 6ch mode
4142 * need to set the codec line out and mic 1 pin widgets to outputs
4143 */
4144static struct hda_verb alc861_threestack_ch6_init[] = {
4145	/* set pin widget 1Ah (line in) for output (Back Surround)*/
4146	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4147	/* set pin widget 18h (mic1) for output (CLFE)*/
4148	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4149
4150	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
4151        { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
4152
4153        { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
4154        { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, //mic
4155        { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, //line in
4156	{ } /* end */
4157};
4158
4159static struct hda_channel_mode alc861_threestack_modes[2] = {
4160	{ 2, alc861_threestack_ch2_init },
4161	{ 6, alc861_threestack_ch6_init },
4162};
4163
4164/* patch-ALC861 */
4165
4166static struct snd_kcontrol_new alc861_base_mixer[] = {
4167        /* output mixer control */
4168	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
4169	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
4170	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
4171	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
4172	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
4173
4174        /*Input mixer control */
4175	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4176	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4177	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
4178	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
4179	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
4180	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
4181	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
4182	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
4183	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
4184	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
4185
4186        /* Capture mixer control */
4187	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4188	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4189	{
4190		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4191		.name = "Capture Source",
4192		.count = 1,
4193		.info = alc_mux_enum_info,
4194		.get = alc_mux_enum_get,
4195		.put = alc_mux_enum_put,
4196	},
4197	{ } /* end */
4198};
4199
4200static struct snd_kcontrol_new alc861_3ST_mixer[] = {
4201        /* output mixer control */
4202	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
4203	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
4204	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
4205	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
4206	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
4207
4208	/* Input mixer control */
4209	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4210	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4211	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
4212	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
4213	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
4214	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
4215	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
4216	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
4217	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
4218	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
4219
4220	/* Capture mixer control */
4221	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4222	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4223	{
4224		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4225		.name = "Capture Source",
4226		.count = 1,
4227		.info = alc_mux_enum_info,
4228		.get = alc_mux_enum_get,
4229		.put = alc_mux_enum_put,
4230	},
4231	{
4232		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4233		.name = "Channel Mode",
4234		.info = alc_ch_mode_info,
4235		.get = alc_ch_mode_get,
4236		.put = alc_ch_mode_put,
4237                .private_value = ARRAY_SIZE(alc861_threestack_modes),
4238	},
4239	{ } /* end */
4240};
4241
4242/*
4243 * generic initialization of ADC, input mixers and output mixers
4244 */
4245static struct hda_verb alc861_base_init_verbs[] = {
4246	/*
4247	 * Unmute ADC0 and set the default input to mic-in
4248	 */
4249	/* port-A for surround (rear panel) */
4250	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4251	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
4252	/* port-B for mic-in (rear panel) with vref */
4253	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4254	/* port-C for line-in (rear panel) */
4255	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4256	/* port-D for Front */
4257	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4258	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
4259	/* port-E for HP out (front panel) */
4260	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
4261	/* route front PCM to HP */
4262	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
4263	/* port-F for mic-in (front panel) with vref */
4264	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4265	/* port-G for CLFE (rear panel) */
4266	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4267	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
4268	/* port-H for side (rear panel) */
4269	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4270	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
4271	/* CD-in */
4272	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4273	/* route front mic to ADC1*/
4274	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4275	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4276
4277	/* Unmute DAC0~3 & spdif out*/
4278	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4279	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4280	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4281	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4282	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4283
4284	/* Unmute Mixer 14 (mic) 1c (Line in)*/
4285	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4286        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4287	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4288        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4289
4290	/* Unmute Stereo Mixer 15 */
4291	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4292	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4293	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4294	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, //Output 0~12 step
4295
4296	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4297	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4298	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4299	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4300	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4301	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4302	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4303	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4304	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4305        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4306
4307	{ }
4308};
4309
4310static struct hda_verb alc861_threestack_init_verbs[] = {
4311	/*
4312	 * Unmute ADC0 and set the default input to mic-in
4313	 */
4314	/* port-A for surround (rear panel) */
4315	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4316	/* port-B for mic-in (rear panel) with vref */
4317	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4318	/* port-C for line-in (rear panel) */
4319	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4320	/* port-D for Front */
4321	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4322	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
4323	/* port-E for HP out (front panel) */
4324	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
4325	/* route front PCM to HP */
4326	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
4327	/* port-F for mic-in (front panel) with vref */
4328	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4329	/* port-G for CLFE (rear panel) */
4330	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4331	/* port-H for side (rear panel) */
4332	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4333	/* CD-in */
4334	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4335	/* route front mic to ADC1*/
4336	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4337	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4338	/* Unmute DAC0~3 & spdif out*/
4339	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4340	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4341	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4342	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4343	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4344
4345	/* Unmute Mixer 14 (mic) 1c (Line in)*/
4346	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4347        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4348	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4349        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4350
4351	/* Unmute Stereo Mixer 15 */
4352	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4353	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4354	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4355	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, //Output 0~12 step
4356
4357	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4358	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4359	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4360	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4361	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4362	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4363	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4364	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4365	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4366        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4367	{ }
4368};
4369/*
4370 * generic initialization of ADC, input mixers and output mixers
4371 */
4372static struct hda_verb alc861_auto_init_verbs[] = {
4373	/*
4374	 * Unmute ADC0 and set the default input to mic-in
4375	 */
4376//	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4377	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4378
4379	/* Unmute DAC0~3 & spdif out*/
4380	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4381	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4382	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4383	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4384	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4385
4386	/* Unmute Mixer 14 (mic) 1c (Line in)*/
4387	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4388	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4389	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4390	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4391
4392	/* Unmute Stereo Mixer 15 */
4393	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4394	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4395	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4396	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
4397
4398	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4399	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4400	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4401	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4402	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4403	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4404	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4405	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4406
4407	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4408	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4409	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4410	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4411	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4412	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4413	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4414	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4415
4416	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},	// set Mic 1
4417
4418	{ }
4419};
4420
4421/* pcm configuration: identiacal with ALC880 */
4422#define alc861_pcm_analog_playback	alc880_pcm_analog_playback
4423#define alc861_pcm_analog_capture	alc880_pcm_analog_capture
4424#define alc861_pcm_digital_playback	alc880_pcm_digital_playback
4425#define alc861_pcm_digital_capture	alc880_pcm_digital_capture
4426
4427
4428#define ALC861_DIGOUT_NID	0x07
4429
4430static struct hda_channel_mode alc861_8ch_modes[1] = {
4431	{ 8, NULL }
4432};
4433
4434static hda_nid_t alc861_dac_nids[4] = {
4435	/* front, surround, clfe, side */
4436	0x03, 0x06, 0x05, 0x04
4437};
4438
4439static hda_nid_t alc861_adc_nids[1] = {
4440	/* ADC0-2 */
4441	0x08,
4442};
4443
4444static struct hda_input_mux alc861_capture_source = {
4445	.num_items = 5,
4446	.items = {
4447		{ "Mic", 0x0 },
4448		{ "Front Mic", 0x3 },
4449		{ "Line", 0x1 },
4450		{ "CD", 0x4 },
4451		{ "Mixer", 0x5 },
4452	},
4453};
4454
4455/* fill in the dac_nids table from the parsed pin configuration */
4456static int alc861_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4457{
4458	int i;
4459	hda_nid_t nid;
4460
4461	spec->multiout.dac_nids = spec->private_dac_nids;
4462	for (i = 0; i < cfg->line_outs; i++) {
4463		nid = cfg->line_out_pins[i];
4464		if (nid) {
4465			if (i >= ARRAY_SIZE(alc861_dac_nids))
4466				continue;
4467			spec->multiout.dac_nids[i] = alc861_dac_nids[i];
4468		}
4469	}
4470	spec->multiout.num_dacs = cfg->line_outs;
4471	return 0;
4472}
4473
4474/* add playback controls from the parsed DAC table */
4475static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
4476					     const struct auto_pin_cfg *cfg)
4477{
4478	char name[32];
4479	static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
4480	hda_nid_t nid;
4481	int i, idx, err;
4482
4483	for (i = 0; i < cfg->line_outs; i++) {
4484		nid = spec->multiout.dac_nids[i];
4485		if (! nid)
4486			continue;
4487		if (nid == 0x05) {
4488			/* Center/LFE */
4489			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
4490					       HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
4491				return err;
4492			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
4493					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4494				return err;
4495		} else {
4496			for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; idx++)
4497				if (nid == alc861_dac_nids[idx])
4498					break;
4499			sprintf(name, "%s Playback Switch", chname[idx]);
4500			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
4501					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4502				return err;
4503		}
4504	}
4505	return 0;
4506}
4507
4508static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
4509{
4510	int err;
4511	hda_nid_t nid;
4512
4513	if (! pin)
4514		return 0;
4515
4516	if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
4517		nid = 0x03;
4518		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4519				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4520			return err;
4521		spec->multiout.hp_nid = nid;
4522	}
4523	return 0;
4524}
4525
4526/* create playback/capture controls for input pins */
4527static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4528{
4529	struct hda_input_mux *imux = &spec->private_imux;
4530	int i, err, idx, idx1;
4531
4532	for (i = 0; i < AUTO_PIN_LAST; i++) {
4533		switch(cfg->input_pins[i]) {
4534		case 0x0c:
4535			idx1 = 1;
4536			idx = 2;	// Line In
4537			break;
4538		case 0x0f:
4539			idx1 = 2;
4540			idx = 2;	// Line In
4541			break;
4542		case 0x0d:
4543			idx1 = 0;
4544			idx = 1;	// Mic In
4545			break;
4546		case 0x10:
4547			idx1 = 3;
4548			idx = 1;	// Mic In
4549			break;
4550		case 0x11:
4551			idx1 = 4;
4552			idx = 0;	// CD
4553			break;
4554		default:
4555			continue;
4556		}
4557
4558		err = new_analog_input(spec, cfg->input_pins[i],
4559				       auto_pin_cfg_labels[i], idx, 0x15);
4560		if (err < 0)
4561			return err;
4562
4563		imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
4564		imux->items[imux->num_items].index = idx1;
4565		imux->num_items++;
4566	}
4567	return 0;
4568}
4569
4570static struct snd_kcontrol_new alc861_capture_mixer[] = {
4571	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4572	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4573
4574	{
4575		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4576		/* The multiple "Capture Source" controls confuse alsamixer
4577		 * So call somewhat different..
4578		 *FIXME: the controls appear in the "playback" view!
4579		 */
4580		/* .name = "Capture Source", */
4581		.name = "Input Source",
4582		.count = 1,
4583		.info = alc_mux_enum_info,
4584		.get = alc_mux_enum_get,
4585		.put = alc_mux_enum_put,
4586	},
4587	{ } /* end */
4588};
4589
4590static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid,
4591					      int pin_type, int dac_idx)
4592{
4593	/* set as output */
4594
4595	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
4596	snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
4597
4598}
4599
4600static void alc861_auto_init_multi_out(struct hda_codec *codec)
4601{
4602	struct alc_spec *spec = codec->spec;
4603	int i;
4604
4605	for (i = 0; i < spec->autocfg.line_outs; i++) {
4606		hda_nid_t nid = spec->autocfg.line_out_pins[i];
4607		if (nid)
4608			alc861_auto_set_output_and_unmute(codec, nid, PIN_OUT, spec->multiout.dac_nids[i]);
4609	}
4610}
4611
4612static void alc861_auto_init_hp_out(struct hda_codec *codec)
4613{
4614	struct alc_spec *spec = codec->spec;
4615	hda_nid_t pin;
4616
4617	pin = spec->autocfg.hp_pin;
4618	if (pin) /* connect to front */
4619		alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]);
4620}
4621
4622static void alc861_auto_init_analog_input(struct hda_codec *codec)
4623{
4624	struct alc_spec *spec = codec->spec;
4625	int i;
4626
4627	for (i = 0; i < AUTO_PIN_LAST; i++) {
4628		hda_nid_t nid = spec->autocfg.input_pins[i];
4629		if ((nid>=0x0c) && (nid <=0x11)) {
4630			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4631					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
4632		}
4633	}
4634}
4635
4636/* parse the BIOS configuration and set up the alc_spec */
4637/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
4638static int alc861_parse_auto_config(struct hda_codec *codec)
4639{
4640	struct alc_spec *spec = codec->spec;
4641	int err;
4642	static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
4643
4644	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4645						alc861_ignore)) < 0)
4646		return err;
4647	if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
4648	    ! spec->autocfg.hp_pin)
4649		return 0; /* can't find valid BIOS pin config */
4650
4651	if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
4652	    (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
4653	    (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
4654	    (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
4655		return err;
4656
4657	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4658
4659	if (spec->autocfg.dig_out_pin)
4660		spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
4661
4662	if (spec->kctl_alloc)
4663		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4664
4665	spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
4666
4667	spec->input_mux = &spec->private_imux;
4668
4669	spec->adc_nids = alc861_adc_nids;
4670	spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
4671	spec->mixers[spec->num_mixers] = alc861_capture_mixer;
4672	spec->num_mixers++;
4673
4674	return 1;
4675}
4676
4677/* init callback for auto-configuration model -- overriding the default init */
4678static int alc861_auto_init(struct hda_codec *codec)
4679{
4680	alc_init(codec);
4681	alc861_auto_init_multi_out(codec);
4682	alc861_auto_init_hp_out(codec);
4683	alc861_auto_init_analog_input(codec);
4684
4685	return 0;
4686}
4687
4688
4689/*
4690 * configuration and preset
4691 */
4692static struct hda_board_config alc861_cfg_tbl[] = {
4693	{ .modelname = "3stack", .config = ALC861_3ST },
4694	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, .config = ALC861_3ST },
4695	{ .modelname = "3stack-dig", .config = ALC861_3ST_DIG },
4696	{ .modelname = "6stack-dig", .config = ALC861_6ST_DIG },
4697	{ .modelname = "auto", .config = ALC861_AUTO },
4698	{}
4699};
4700
4701static struct alc_config_preset alc861_presets[] = {
4702	[ALC861_3ST] = {
4703		.mixers = { alc861_3ST_mixer },
4704		.init_verbs = { alc861_threestack_init_verbs },
4705		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
4706		.dac_nids = alc861_dac_nids,
4707		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
4708		.channel_mode = alc861_threestack_modes,
4709		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4710		.adc_nids = alc861_adc_nids,
4711		.input_mux = &alc861_capture_source,
4712	},
4713	[ALC861_3ST_DIG] = {
4714		.mixers = { alc861_base_mixer },
4715		.init_verbs = { alc861_threestack_init_verbs },
4716		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
4717		.dac_nids = alc861_dac_nids,
4718		.dig_out_nid = ALC861_DIGOUT_NID,
4719		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
4720		.channel_mode = alc861_threestack_modes,
4721		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4722		.adc_nids = alc861_adc_nids,
4723		.input_mux = &alc861_capture_source,
4724	},
4725	[ALC861_6ST_DIG] = {
4726		.mixers = { alc861_base_mixer },
4727		.init_verbs = { alc861_base_init_verbs },
4728		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
4729		.dac_nids = alc861_dac_nids,
4730		.dig_out_nid = ALC861_DIGOUT_NID,
4731		.num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
4732		.channel_mode = alc861_8ch_modes,
4733		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4734		.adc_nids = alc861_adc_nids,
4735		.input_mux = &alc861_capture_source,
4736	},
4737};
4738
4739
4740static int patch_alc861(struct hda_codec *codec)
4741{
4742	struct alc_spec *spec;
4743	int board_config;
4744	int err;
4745
4746	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
4747	if (spec == NULL)
4748		return -ENOMEM;
4749
4750	codec->spec = spec;
4751
4752        board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl);
4753	if (board_config < 0 || board_config >= ALC861_MODEL_LAST) {
4754		printk(KERN_INFO "hda_codec: Unknown model for ALC861, trying auto-probe from BIOS...\n");
4755		board_config = ALC861_AUTO;
4756	}
4757
4758	if (board_config == ALC861_AUTO) {
4759		/* automatic parse from the BIOS config */
4760		err = alc861_parse_auto_config(codec);
4761		if (err < 0) {
4762			alc_free(codec);
4763			return err;
4764		} else if (! err) {
4765			printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS.  Using base mode...\n");
4766		   board_config = ALC861_3ST_DIG;
4767		}
4768	}
4769
4770	if (board_config != ALC861_AUTO)
4771		setup_preset(spec, &alc861_presets[board_config]);
4772
4773	spec->stream_name_analog = "ALC861 Analog";
4774	spec->stream_analog_playback = &alc861_pcm_analog_playback;
4775	spec->stream_analog_capture = &alc861_pcm_analog_capture;
4776
4777	spec->stream_name_digital = "ALC861 Digital";
4778	spec->stream_digital_playback = &alc861_pcm_digital_playback;
4779	spec->stream_digital_capture = &alc861_pcm_digital_capture;
4780
4781	codec->patch_ops = alc_patch_ops;
4782	if (board_config == ALC861_AUTO)
4783		codec->patch_ops.init = alc861_auto_init;
4784
4785	return 0;
4786}
4787
4788/*
4789 * patch entries
4790 */
4791struct hda_codec_preset snd_hda_preset_realtek[] = {
4792	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
4793	{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
4794 	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
4795	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
4796	{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
4797	{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
4798	{ .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
4799	{} /* terminator */
4800};
4801