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