patch_realtek.c revision 8d88bc3d361bdd81a214eb9c5d06b291d06c603a
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 PeiSen Hou <pshou@realtek.com.tw>
7 *                    Takashi Iwai <tiwai@suse.de>
8 *
9 *  This driver is free software; you can redistribute it and/or modify
10 *  it under the terms of the GNU General Public License as published by
11 *  the Free Software Foundation; either version 2 of the License, or
12 *  (at your option) any later version.
13 *
14 *  This driver is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22 */
23
24#include <sound/driver.h>
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/slab.h>
28#include <linux/pci.h>
29#include <sound/core.h>
30#include "hda_codec.h"
31#include "hda_local.h"
32
33
34/* ALC880 board config type */
35enum {
36	ALC880_3ST,
37	ALC880_3ST_DIG,
38	ALC880_5ST,
39	ALC880_5ST_DIG,
40	ALC880_W810,
41	ALC880_Z71V,
42	ALC880_AUTO,
43	ALC880_6ST,
44	ALC880_6ST_DIG,
45	ALC880_F1734,
46	ALC880_ASUS,
47	ALC880_ASUS_DIG,
48	ALC880_ASUS_W1V,
49	ALC880_UNIWILL_DIG,
50#ifdef CONFIG_SND_DEBUG
51	ALC880_TEST,
52#endif
53	ALC880_MODEL_LAST /* last tag */
54};
55
56/* ALC260 models */
57enum {
58	ALC260_BASIC,
59	ALC260_HP,
60	ALC260_FUJITSU_S702x,
61	ALC260_MODEL_LAST /* last tag */
62};
63
64struct alc_spec {
65	/* codec parameterization */
66	snd_kcontrol_new_t *mixers[3];	/* mixer arrays */
67	unsigned int num_mixers;
68
69	const struct hda_verb *init_verbs[3];	/* initialization verbs
70						 * don't forget NULL termination!
71						 */
72	unsigned int num_init_verbs;
73
74	char *stream_name_analog;	/* analog PCM stream */
75	struct hda_pcm_stream *stream_analog_playback;
76	struct hda_pcm_stream *stream_analog_capture;
77
78	char *stream_name_digital;	/* digital PCM stream */
79	struct hda_pcm_stream *stream_digital_playback;
80	struct hda_pcm_stream *stream_digital_capture;
81
82	/* playback */
83	struct hda_multi_out multiout;	/* playback set-up
84					 * max_channels, dacs must be set
85					 * dig_out_nid and hp_nid are optional
86					 */
87
88	/* capture */
89	unsigned int num_adc_nids;
90	hda_nid_t *adc_nids;
91	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
92
93	/* capture source */
94	const struct hda_input_mux *input_mux;
95	unsigned int cur_mux[3];
96
97	/* channel model */
98	const struct hda_channel_mode *channel_mode;
99	int num_channel_mode;
100
101	/* PCM information */
102	struct hda_pcm pcm_rec[2];	/* used in alc_build_pcms() */
103
104	/* dynamic controls, init_verbs and input_mux */
105	struct auto_pin_cfg autocfg;
106	unsigned int num_kctl_alloc, num_kctl_used;
107	snd_kcontrol_new_t *kctl_alloc;
108	struct hda_input_mux private_imux;
109	hda_nid_t private_dac_nids[4];
110};
111
112
113/*
114 * input MUX handling
115 */
116static int alc_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
117{
118	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
119	struct alc_spec *spec = codec->spec;
120	return snd_hda_input_mux_info(spec->input_mux, uinfo);
121}
122
123static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
124{
125	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
126	struct alc_spec *spec = codec->spec;
127	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
128
129	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
130	return 0;
131}
132
133static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
134{
135	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
136	struct alc_spec *spec = codec->spec;
137	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
138	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
139				     spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
140}
141
142
143/*
144 * channel mode setting
145 */
146static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
147{
148	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
149	struct alc_spec *spec = codec->spec;
150	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
151				    spec->num_channel_mode);
152}
153
154static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
155{
156	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
157	struct alc_spec *spec = codec->spec;
158	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
159				   spec->num_channel_mode, spec->multiout.max_channels);
160}
161
162static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
163{
164	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
165	struct alc_spec *spec = codec->spec;
166	return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
167				   spec->num_channel_mode, &spec->multiout.max_channels);
168}
169
170
171/*
172 * Control of pin widget settings via the mixer.  Only boolean settings are
173 * supported, so VrefEn can't be controlled using these functions as they
174 * stand.
175 */
176static int alc_pinctl_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
177{
178	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
179	uinfo->count = 1;
180	uinfo->value.integer.min = 0;
181	uinfo->value.integer.max = 1;
182	return 0;
183}
184
185static int alc_pinctl_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
186{
187	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
188	hda_nid_t nid = kcontrol->private_value & 0xffff;
189	long mask = (kcontrol->private_value >> 16) & 0xff;
190	long *valp = ucontrol->value.integer.value;
191
192	*valp = 0;
193	if (snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00) & mask)
194		*valp = 1;
195	return 0;
196}
197
198static int alc_pinctl_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
199{
200	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
201	hda_nid_t nid = kcontrol->private_value & 0xffff;
202	long mask = (kcontrol->private_value >> 16) & 0xff;
203	long *valp = ucontrol->value.integer.value;
204	unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00);
205	int change = ((pinctl & mask)!=0) != *valp;
206
207	if (change)
208		snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
209			*valp?(pinctl|mask):(pinctl&~mask));
210	return change;
211}
212
213#define ALC_PINCTL_SWITCH(xname, nid, mask) \
214	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
215	  .info = alc_pinctl_switch_info, \
216	  .get = alc_pinctl_switch_get, \
217	  .put = alc_pinctl_switch_put, \
218	  .private_value = (nid) | (mask<<16) }
219
220/*
221 * ALC880 3-stack model
222 *
223 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
224 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
225 *                 HP = 0x19
226 */
227
228static hda_nid_t alc880_dac_nids[4] = {
229	/* front, rear, clfe, rear_surr */
230	0x02, 0x05, 0x04, 0x03
231};
232
233static hda_nid_t alc880_adc_nids[3] = {
234	/* ADC0-2 */
235	0x07, 0x08, 0x09,
236};
237
238/* The datasheet says the node 0x07 is connected from inputs,
239 * but it shows zero connection in the real implementation on some devices.
240 */
241static hda_nid_t alc880_adc_nids_alt[2] = {
242	/* ADC1-2 */
243	0x08, 0x09,
244};
245
246#define ALC880_DIGOUT_NID	0x06
247#define ALC880_DIGIN_NID	0x0a
248
249static struct hda_input_mux alc880_capture_source = {
250	.num_items = 4,
251	.items = {
252		{ "Mic", 0x0 },
253		{ "Front Mic", 0x3 },
254		{ "Line", 0x2 },
255		{ "CD", 0x4 },
256	},
257};
258
259/* channel source setting (2/6 channel selection for 3-stack) */
260/* 2ch mode */
261static struct hda_verb alc880_threestack_ch2_init[] = {
262	/* set line-in to input, mute it */
263	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
264	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
265	/* set mic-in to input vref 80%, mute it */
266	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
267	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
268	{ } /* end */
269};
270
271/* 6ch mode */
272static struct hda_verb alc880_threestack_ch6_init[] = {
273	/* set line-in to output, unmute it */
274	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
275	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
276	/* set mic-in to output, unmute it */
277	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
278	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
279	{ } /* end */
280};
281
282static struct hda_channel_mode alc880_threestack_modes[2] = {
283	{ 2, alc880_threestack_ch2_init },
284	{ 6, alc880_threestack_ch6_init },
285};
286
287static snd_kcontrol_new_t alc880_three_stack_mixer[] = {
288	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
289	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
290	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
291	HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
292	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
293	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
294	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
295	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
296	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
297	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
298	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
299	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
300	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
301	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
302	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
303	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
304	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
305	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
306	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
307	{
308		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
309		.name = "Channel Mode",
310		.info = alc880_ch_mode_info,
311		.get = alc880_ch_mode_get,
312		.put = alc880_ch_mode_put,
313	},
314	{ } /* end */
315};
316
317/* capture mixer elements */
318static snd_kcontrol_new_t alc880_capture_mixer[] = {
319	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
320	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
321	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
322	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
323	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
324	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
325	{
326		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
327		/* The multiple "Capture Source" controls confuse alsamixer
328		 * So call somewhat different..
329		 * FIXME: the controls appear in the "playback" view!
330		 */
331		/* .name = "Capture Source", */
332		.name = "Input Source",
333		.count = 3,
334		.info = alc_mux_enum_info,
335		.get = alc_mux_enum_get,
336		.put = alc_mux_enum_put,
337	},
338	{ } /* end */
339};
340
341/* capture mixer elements (in case NID 0x07 not available) */
342static snd_kcontrol_new_t alc880_capture_alt_mixer[] = {
343	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
344	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
345	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
346	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
347	{
348		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
349		/* The multiple "Capture Source" controls confuse alsamixer
350		 * So call somewhat different..
351		 * FIXME: the controls appear in the "playback" view!
352		 */
353		/* .name = "Capture Source", */
354		.name = "Input Source",
355		.count = 2,
356		.info = alc_mux_enum_info,
357		.get = alc_mux_enum_get,
358		.put = alc_mux_enum_put,
359	},
360	{ } /* end */
361};
362
363
364
365/*
366 * ALC880 5-stack model
367 *
368 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
369 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
370 *                 Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
371 */
372
373/* additional mixers to alc880_three_stack_mixer */
374static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
375	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
376	HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
377	{ } /* end */
378};
379
380/* channel source setting (6/8 channel selection for 5-stack) */
381/* 6ch mode */
382static struct hda_verb alc880_fivestack_ch6_init[] = {
383	/* set line-in to input, mute it */
384	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
385	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
386	{ } /* end */
387};
388
389/* 8ch mode */
390static struct hda_verb alc880_fivestack_ch8_init[] = {
391	/* set line-in to output, unmute it */
392	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
393	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
394	{ } /* end */
395};
396
397static struct hda_channel_mode alc880_fivestack_modes[2] = {
398	{ 6, alc880_fivestack_ch6_init },
399	{ 8, alc880_fivestack_ch8_init },
400};
401
402
403/*
404 * ALC880 6-stack model
405 *
406 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
407 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
408 *   Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
409 */
410
411static hda_nid_t alc880_6st_dac_nids[4] = {
412	/* front, rear, clfe, rear_surr */
413	0x02, 0x03, 0x04, 0x05
414};
415
416static struct hda_input_mux alc880_6stack_capture_source = {
417	.num_items = 4,
418	.items = {
419		{ "Mic", 0x0 },
420		{ "Front Mic", 0x1 },
421		{ "Line", 0x2 },
422		{ "CD", 0x4 },
423	},
424};
425
426/* fixed 8-channels */
427static struct hda_channel_mode alc880_sixstack_modes[1] = {
428	{ 8, NULL },
429};
430
431static snd_kcontrol_new_t alc880_six_stack_mixer[] = {
432	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
433	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
434	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
435	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
436	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
437	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
438	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
439	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
440	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
441	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
442	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
443	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
444	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
445	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
446	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
447	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
448	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
449	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
450	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
451	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
452	{
453		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
454		.name = "Channel Mode",
455		.info = alc880_ch_mode_info,
456		.get = alc880_ch_mode_get,
457		.put = alc880_ch_mode_put,
458	},
459	{ } /* end */
460};
461
462
463/*
464 * ALC880 W810 model
465 *
466 * W810 has rear IO for:
467 * Front (DAC 02)
468 * Surround (DAC 03)
469 * Center/LFE (DAC 04)
470 * Digital out (06)
471 *
472 * The system also has a pair of internal speakers, and a headphone jack.
473 * These are both connected to Line2 on the codec, hence to DAC 02.
474 *
475 * There is a variable resistor to control the speaker or headphone
476 * volume. This is a hardware-only device without a software API.
477 *
478 * Plugging headphones in will disable the internal speakers. This is
479 * implemented in hardware, not via the driver using jack sense. In
480 * a similar fashion, plugging into the rear socket marked "front" will
481 * disable both the speakers and headphones.
482 *
483 * For input, there's a microphone jack, and an "audio in" jack.
484 * These may not do anything useful with this driver yet, because I
485 * haven't setup any initialization verbs for these yet...
486 */
487
488static hda_nid_t alc880_w810_dac_nids[3] = {
489	/* front, rear/surround, clfe */
490	0x02, 0x03, 0x04
491};
492
493/* fixed 6 channels */
494static struct hda_channel_mode alc880_w810_modes[1] = {
495	{ 6, NULL }
496};
497
498/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
499static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
500	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
501	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
502	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
503	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
504	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
505	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
506	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
507	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
508	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
509	{ } /* end */
510};
511
512
513/*
514 * Z710V model
515 *
516 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
517 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
518 */
519
520static hda_nid_t alc880_z71v_dac_nids[1] = {
521	0x02
522};
523#define ALC880_Z71V_HP_DAC	0x03
524
525/* fixed 2 channels */
526static struct hda_channel_mode alc880_2_jack_modes[1] = {
527	{ 2, NULL }
528};
529
530static snd_kcontrol_new_t alc880_z71v_mixer[] = {
531	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
532	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
533	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
534	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
535	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
536	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
537	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
538	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
539	{ } /* end */
540};
541
542
543/* FIXME! */
544/*
545 * ALC880 F1734 model
546 *
547 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
548 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
549 */
550
551static hda_nid_t alc880_f1734_dac_nids[1] = {
552	0x03
553};
554#define ALC880_F1734_HP_DAC	0x02
555
556static snd_kcontrol_new_t alc880_f1734_mixer[] = {
557	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
558	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
559	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
560	HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
561	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
562	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
563	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
564	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
565	{ } /* end */
566};
567
568
569/* FIXME! */
570/*
571 * ALC880 ASUS model
572 *
573 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
574 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
575 *  Mic = 0x18, Line = 0x1a
576 */
577
578#define alc880_asus_dac_nids	alc880_w810_dac_nids	/* identical with w810 */
579#define alc880_asus_modes	alc880_threestack_modes	/* 2/6 channel mode */
580
581static snd_kcontrol_new_t alc880_asus_mixer[] = {
582	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
583	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
584	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
585	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
586	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
587	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
588	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
589	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
590	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
591	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
592	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
593	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
594	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
595	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
596	{
597		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
598		.name = "Channel Mode",
599		.info = alc880_ch_mode_info,
600		.get = alc880_ch_mode_get,
601		.put = alc880_ch_mode_put,
602	},
603	{ } /* end */
604};
605
606/* FIXME! */
607/*
608 * ALC880 ASUS W1V model
609 *
610 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
611 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
612 *  Mic = 0x18, Line = 0x1a, Line2 = 0x1b
613 */
614
615/* additional mixers to alc880_asus_mixer */
616static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = {
617	HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
618	HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
619	{ } /* end */
620};
621
622/* additional mixers to alc880_asus_mixer */
623static snd_kcontrol_new_t alc880_pcbeep_mixer[] = {
624	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
625	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
626	{ } /* end */
627};
628
629/*
630 * build control elements
631 */
632static int alc_build_controls(struct hda_codec *codec)
633{
634	struct alc_spec *spec = codec->spec;
635	int err;
636	int i;
637
638	for (i = 0; i < spec->num_mixers; i++) {
639		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
640		if (err < 0)
641			return err;
642	}
643
644	if (spec->multiout.dig_out_nid) {
645		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
646		if (err < 0)
647			return err;
648	}
649	if (spec->dig_in_nid) {
650		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
651		if (err < 0)
652			return err;
653	}
654	return 0;
655}
656
657
658/*
659 * initialize the codec volumes, etc
660 */
661
662/*
663 * generic initialization of ADC, input mixers and output mixers
664 */
665static struct hda_verb alc880_volume_init_verbs[] = {
666	/*
667	 * Unmute ADC0-2 and set the default input to mic-in
668	 */
669	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
670	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
671	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
672	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
673	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
674	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
675
676	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
677	 * mixer widget
678	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
679	 * mic (mic 2)
680	 */
681	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
682	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
683	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
684	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
685	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
686	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
687
688	/*
689	 * Set up output mixers (0x0c - 0x0f)
690	 */
691	/* set vol=0 to output mixers */
692	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
693	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
694	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
695	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
696	/* set up input amps for analog loopback */
697	/* Amp Indices: DAC = 0, mixer = 1 */
698	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
699	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
700	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
701	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
702	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
703	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
704	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
705	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
706
707	{ }
708};
709
710/*
711 * 3-stack pin configuration:
712 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
713 */
714static struct hda_verb alc880_pin_3stack_init_verbs[] = {
715	/*
716	 * preset connection lists of input pins
717	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
718	 */
719	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
720	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
721	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
722
723	/*
724	 * Set pin mode and muting
725	 */
726	/* set front pin widgets 0x14 for output */
727	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
728	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
729	/* Mic1 (rear panel) pin widget for input and vref at 80% */
730	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
731	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
732	/* Mic2 (as headphone out) for HP output */
733	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
734	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
735	/* Line In pin widget for input */
736	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
737	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
738	/* Line2 (as front mic) pin widget for input and vref at 80% */
739	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
740	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
741	/* CD pin widget for input */
742	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
743
744	{ }
745};
746
747/*
748 * 5-stack pin configuration:
749 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
750 * line-in/side = 0x1a, f-mic = 0x1b
751 */
752static struct hda_verb alc880_pin_5stack_init_verbs[] = {
753	/*
754	 * preset connection lists of input pins
755	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
756	 */
757	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
758	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
759
760	/*
761	 * Set pin mode and muting
762	 */
763	/* set pin widgets 0x14-0x17 for output */
764	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
765	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
766	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
767	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
768	/* unmute pins for output (no gain on this amp) */
769	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
770	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
771	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
772	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
773
774	/* Mic1 (rear panel) pin widget for input and vref at 80% */
775	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
776	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
777	/* Mic2 (as headphone out) for HP output */
778	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
779	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
780	/* Line In pin widget for input */
781	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
782	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
783	/* Line2 (as front mic) pin widget for input and vref at 80% */
784	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
785	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
786	/* CD pin widget for input */
787	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
788
789	{ }
790};
791
792/*
793 * W810 pin configuration:
794 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
795 */
796static struct hda_verb alc880_pin_w810_init_verbs[] = {
797	/* hphone/speaker input selector: front DAC */
798	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
799
800	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
801	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
802	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
803	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
804	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
805	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
806
807	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
808	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
809
810	{ }
811};
812
813/*
814 * Z71V pin configuration:
815 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
816 */
817static struct hda_verb alc880_pin_z71v_init_verbs[] = {
818	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
819	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
820	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
821	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
822
823	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
824	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
825	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
826	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
827
828	{ }
829};
830
831/*
832 * 6-stack pin configuration:
833 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
834 * line = 0x1a, HP = 0x1b
835 */
836static struct hda_verb alc880_pin_6stack_init_verbs[] = {
837	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
838
839	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
840	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
841	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
842	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
843	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
844	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
845	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
846	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
847
848	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
849	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
850	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
851	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
852	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
853	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
854	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
855	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
856	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
857
858	{ }
859};
860
861/* FIXME! */
862/*
863 * F1734 pin configuration:
864 * HP = 0x14, speaker-out = 0x15, mic = 0x18
865 */
866static struct hda_verb alc880_pin_f1734_init_verbs[] = {
867	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
868	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
869	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
870	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
871
872	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
873	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
874	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
875	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
876
877	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
878	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
879	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
880	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
881	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
882	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
883	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
884	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
885	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
886
887	{ }
888};
889
890/* FIXME! */
891/*
892 * ASUS pin configuration:
893 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
894 */
895static struct hda_verb alc880_pin_asus_init_verbs[] = {
896	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
897	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
898	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
899	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
900
901	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
902	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
903	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
904	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
905	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
906	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
907	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
908	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
909
910	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
911	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
912	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
913	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
914	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
915	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
916	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
917	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
918	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
919
920	{ }
921};
922
923/* Enable GPIO mask and set output */
924static struct hda_verb alc880_gpio1_init_verbs[] = {
925	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
926	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
927	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
928};
929
930/* Enable GPIO mask and set output */
931static struct hda_verb alc880_gpio2_init_verbs[] = {
932	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
933	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
934	{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
935};
936
937
938/*
939 */
940
941static int alc_init(struct hda_codec *codec)
942{
943	struct alc_spec *spec = codec->spec;
944	unsigned int i;
945
946	for (i = 0; i < spec->num_init_verbs; i++)
947		snd_hda_sequence_write(codec, spec->init_verbs[i]);
948	return 0;
949}
950
951#ifdef CONFIG_PM
952/*
953 * resume
954 */
955static int alc_resume(struct hda_codec *codec)
956{
957	struct alc_spec *spec = codec->spec;
958	int i;
959
960	alc_init(codec);
961	for (i = 0; i < spec->num_mixers; i++)
962		snd_hda_resume_ctls(codec, spec->mixers[i]);
963	if (spec->multiout.dig_out_nid)
964		snd_hda_resume_spdif_out(codec);
965	if (spec->dig_in_nid)
966		snd_hda_resume_spdif_in(codec);
967
968	return 0;
969}
970#endif
971
972/*
973 * Analog playback callbacks
974 */
975static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
976				    struct hda_codec *codec,
977				    snd_pcm_substream_t *substream)
978{
979	struct alc_spec *spec = codec->spec;
980	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
981}
982
983static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
984				       struct hda_codec *codec,
985				       unsigned int stream_tag,
986				       unsigned int format,
987				       snd_pcm_substream_t *substream)
988{
989	struct alc_spec *spec = codec->spec;
990	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
991						format, substream);
992}
993
994static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
995				       struct hda_codec *codec,
996				       snd_pcm_substream_t *substream)
997{
998	struct alc_spec *spec = codec->spec;
999	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
1000}
1001
1002/*
1003 * Digital out
1004 */
1005static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
1006					struct hda_codec *codec,
1007					snd_pcm_substream_t *substream)
1008{
1009	struct alc_spec *spec = codec->spec;
1010	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
1011}
1012
1013static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
1014					 struct hda_codec *codec,
1015					 snd_pcm_substream_t *substream)
1016{
1017	struct alc_spec *spec = codec->spec;
1018	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
1019}
1020
1021/*
1022 * Analog capture
1023 */
1024static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
1025				      struct hda_codec *codec,
1026				      unsigned int stream_tag,
1027				      unsigned int format,
1028				      snd_pcm_substream_t *substream)
1029{
1030	struct alc_spec *spec = codec->spec;
1031
1032	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
1033				   stream_tag, 0, format);
1034	return 0;
1035}
1036
1037static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
1038				      struct hda_codec *codec,
1039				      snd_pcm_substream_t *substream)
1040{
1041	struct alc_spec *spec = codec->spec;
1042
1043	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
1044	return 0;
1045}
1046
1047
1048/*
1049 */
1050static struct hda_pcm_stream alc880_pcm_analog_playback = {
1051	.substreams = 1,
1052	.channels_min = 2,
1053	.channels_max = 8,
1054	/* NID is set in alc_build_pcms */
1055	.ops = {
1056		.open = alc880_playback_pcm_open,
1057		.prepare = alc880_playback_pcm_prepare,
1058		.cleanup = alc880_playback_pcm_cleanup
1059	},
1060};
1061
1062static struct hda_pcm_stream alc880_pcm_analog_capture = {
1063	.substreams = 2,
1064	.channels_min = 2,
1065	.channels_max = 2,
1066	/* NID is set in alc_build_pcms */
1067	.ops = {
1068		.prepare = alc880_capture_pcm_prepare,
1069		.cleanup = alc880_capture_pcm_cleanup
1070	},
1071};
1072
1073static struct hda_pcm_stream alc880_pcm_digital_playback = {
1074	.substreams = 1,
1075	.channels_min = 2,
1076	.channels_max = 2,
1077	/* NID is set in alc_build_pcms */
1078	.ops = {
1079		.open = alc880_dig_playback_pcm_open,
1080		.close = alc880_dig_playback_pcm_close
1081	},
1082};
1083
1084static struct hda_pcm_stream alc880_pcm_digital_capture = {
1085	.substreams = 1,
1086	.channels_min = 2,
1087	.channels_max = 2,
1088	/* NID is set in alc_build_pcms */
1089};
1090
1091static int alc_build_pcms(struct hda_codec *codec)
1092{
1093	struct alc_spec *spec = codec->spec;
1094	struct hda_pcm *info = spec->pcm_rec;
1095	int i;
1096
1097	codec->num_pcms = 1;
1098	codec->pcm_info = info;
1099
1100	info->name = spec->stream_name_analog;
1101	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
1102	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
1103	info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
1104	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
1105
1106	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
1107	for (i = 0; i < spec->num_channel_mode; i++) {
1108		if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
1109		    info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
1110		}
1111	}
1112
1113	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
1114		codec->num_pcms++;
1115		info++;
1116		info->name = spec->stream_name_digital;
1117		if (spec->multiout.dig_out_nid) {
1118			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
1119			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
1120		}
1121		if (spec->dig_in_nid) {
1122			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
1123			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
1124		}
1125	}
1126
1127	return 0;
1128}
1129
1130static void alc_free(struct hda_codec *codec)
1131{
1132	struct alc_spec *spec = codec->spec;
1133	unsigned int i;
1134
1135	if (! spec)
1136		return;
1137
1138	if (spec->kctl_alloc) {
1139		for (i = 0; i < spec->num_kctl_used; i++)
1140			kfree(spec->kctl_alloc[i].name);
1141		kfree(spec->kctl_alloc);
1142	}
1143	kfree(spec);
1144}
1145
1146/*
1147 */
1148static struct hda_codec_ops alc_patch_ops = {
1149	.build_controls = alc_build_controls,
1150	.build_pcms = alc_build_pcms,
1151	.init = alc_init,
1152	.free = alc_free,
1153#ifdef CONFIG_PM
1154	.resume = alc_resume,
1155#endif
1156};
1157
1158
1159/*
1160 * Test configuration for debugging
1161 *
1162 * Almost all inputs/outputs are enabled.  I/O pins can be configured via
1163 * enum controls.
1164 */
1165#ifdef CONFIG_SND_DEBUG
1166static hda_nid_t alc880_test_dac_nids[4] = {
1167	0x02, 0x03, 0x04, 0x05
1168};
1169
1170static struct hda_input_mux alc880_test_capture_source = {
1171	.num_items = 5,
1172	.items = {
1173		{ "In-1", 0x0 },
1174		{ "In-2", 0x1 },
1175		{ "In-3", 0x2 },
1176		{ "In-4", 0x3 },
1177		{ "CD", 0x4 },
1178	},
1179};
1180
1181static struct hda_channel_mode alc880_test_modes[4] = {
1182	{ 2, NULL },
1183	{ 4, NULL },
1184	{ 6, NULL },
1185	{ 8, NULL },
1186};
1187
1188static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1189{
1190	static char *texts[] = {
1191		"N/A", "Line Out", "HP Out",
1192		"In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
1193	};
1194	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1195	uinfo->count = 1;
1196	uinfo->value.enumerated.items = 8;
1197	if (uinfo->value.enumerated.item >= 8)
1198		uinfo->value.enumerated.item = 7;
1199	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1200	return 0;
1201}
1202
1203static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1204{
1205	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1206	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1207	unsigned int pin_ctl, item = 0;
1208
1209	pin_ctl = snd_hda_codec_read(codec, nid, 0,
1210				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1211	if (pin_ctl & AC_PINCTL_OUT_EN) {
1212		if (pin_ctl & AC_PINCTL_HP_EN)
1213			item = 2;
1214		else
1215			item = 1;
1216	} else if (pin_ctl & AC_PINCTL_IN_EN) {
1217		switch (pin_ctl & AC_PINCTL_VREFEN) {
1218		case AC_PINCTL_VREF_HIZ: item = 3; break;
1219		case AC_PINCTL_VREF_50:  item = 4; break;
1220		case AC_PINCTL_VREF_GRD: item = 5; break;
1221		case AC_PINCTL_VREF_80:  item = 6; break;
1222		case AC_PINCTL_VREF_100: item = 7; break;
1223		}
1224	}
1225	ucontrol->value.enumerated.item[0] = item;
1226	return 0;
1227}
1228
1229static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1230{
1231	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1232	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1233	static unsigned int ctls[] = {
1234		0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
1235		AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
1236		AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
1237		AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
1238		AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
1239		AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
1240	};
1241	unsigned int old_ctl, new_ctl;
1242
1243	old_ctl = snd_hda_codec_read(codec, nid, 0,
1244				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1245	new_ctl = ctls[ucontrol->value.enumerated.item[0]];
1246	if (old_ctl != new_ctl) {
1247		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
1248		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1249				    ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000);
1250		return 1;
1251	}
1252	return 0;
1253}
1254
1255static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1256{
1257	static char *texts[] = {
1258		"Front", "Surround", "CLFE", "Side"
1259	};
1260	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1261	uinfo->count = 1;
1262	uinfo->value.enumerated.items = 4;
1263	if (uinfo->value.enumerated.item >= 4)
1264		uinfo->value.enumerated.item = 3;
1265	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1266	return 0;
1267}
1268
1269static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1270{
1271	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1272	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1273	unsigned int sel;
1274
1275	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
1276	ucontrol->value.enumerated.item[0] = sel & 3;
1277	return 0;
1278}
1279
1280static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1281{
1282	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1283	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1284	unsigned int sel;
1285
1286	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
1287	if (ucontrol->value.enumerated.item[0] != sel) {
1288		sel = ucontrol->value.enumerated.item[0] & 3;
1289		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
1290		return 1;
1291	}
1292	return 0;
1293}
1294
1295#define PIN_CTL_TEST(xname,nid) {			\
1296		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
1297			.name = xname,		       \
1298			.info = alc_test_pin_ctl_info, \
1299			.get = alc_test_pin_ctl_get,   \
1300			.put = alc_test_pin_ctl_put,   \
1301			.private_value = nid	       \
1302			}
1303
1304#define PIN_SRC_TEST(xname,nid) {			\
1305		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
1306			.name = xname,		       \
1307			.info = alc_test_pin_src_info, \
1308			.get = alc_test_pin_src_get,   \
1309			.put = alc_test_pin_src_put,   \
1310			.private_value = nid	       \
1311			}
1312
1313static snd_kcontrol_new_t alc880_test_mixer[] = {
1314	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1315	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1316	HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
1317	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1318	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1319	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1320	HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
1321	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
1322	PIN_CTL_TEST("Front Pin Mode", 0x14),
1323	PIN_CTL_TEST("Surround Pin Mode", 0x15),
1324	PIN_CTL_TEST("CLFE Pin Mode", 0x16),
1325	PIN_CTL_TEST("Side Pin Mode", 0x17),
1326	PIN_CTL_TEST("In-1 Pin Mode", 0x18),
1327	PIN_CTL_TEST("In-2 Pin Mode", 0x19),
1328	PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
1329	PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
1330	PIN_SRC_TEST("In-1 Pin Source", 0x18),
1331	PIN_SRC_TEST("In-2 Pin Source", 0x19),
1332	PIN_SRC_TEST("In-3 Pin Source", 0x1a),
1333	PIN_SRC_TEST("In-4 Pin Source", 0x1b),
1334	HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
1335	HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
1336	HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
1337	HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
1338	HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
1339	HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
1340	HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
1341	HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
1342	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
1343	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
1344	{
1345		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1346		.name = "Channel Mode",
1347		.info = alc880_ch_mode_info,
1348		.get = alc880_ch_mode_get,
1349		.put = alc880_ch_mode_put,
1350	},
1351	{ } /* end */
1352};
1353
1354static struct hda_verb alc880_test_init_verbs[] = {
1355	/* Unmute inputs of 0x0c - 0x0f */
1356	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1357	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1358	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1359	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1360	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1361	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1362	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1363	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1364	/* Vol output for 0x0c-0x0f */
1365	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1366	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1367	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1368	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1369	/* Set output pins 0x14-0x17 */
1370	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1371	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1372	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1373	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1374	/* Unmute output pins 0x14-0x17 */
1375	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1376	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1377	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1378	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1379	/* Set input pins 0x18-0x1c */
1380	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1381	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1382	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1383	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1384	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1385	/* Mute input pins 0x18-0x1b */
1386	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1387	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1388	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1389	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1390	/* ADC set up */
1391	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1392	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
1393	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1394	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
1395	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1396	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
1397	/* Analog input/passthru */
1398	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1399	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1400	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1401	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1402	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1403	{ }
1404};
1405#endif
1406
1407/*
1408 */
1409
1410static struct hda_board_config alc880_cfg_tbl[] = {
1411	/* Back 3 jack, front 2 jack */
1412	{ .modelname = "3stack", .config = ALC880_3ST },
1413	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST },
1414	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST },
1415	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST },
1416	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST },
1417	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST },
1418	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST },
1419	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST },
1420	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST },
1421	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST },
1422	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST },
1423	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST },
1424	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST },
1425	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST },
1426	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST },
1427	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST },
1428	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST },
1429	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST },
1430	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST },
1431	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
1432	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
1433	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
1434	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
1435	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
1436	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
1437	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
1438	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
1439	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
1440	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
1441	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
1442	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
1443	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
1444	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
1445
1446	/* Back 3 jack, front 2 jack (Internal add Aux-In) */
1447	{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
1448	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST },
1449	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST },
1450
1451	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
1452	{ .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
1453	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
1454	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG },
1455
1456	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
1457	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
1458	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
1459	{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
1460
1461	/* Back 5 jack, front 2 jack */
1462	{ .modelname = "5stack", .config = ALC880_5ST },
1463	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
1464	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
1465	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
1466	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
1467	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
1468
1469	/* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
1470	{ .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
1471	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
1472	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
1473	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
1474	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
1475	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
1476	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
1477	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
1478	{ .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
1479	{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
1480	/* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */
1481	{ .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
1482	/* note subvendor = 0 below */
1483	/* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */
1484
1485	{ .modelname = "w810", .config = ALC880_W810 },
1486	{ .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
1487
1488	{ .modelname = "z71v", .config = ALC880_Z71V },
1489	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
1490
1491	{ .modelname = "6stack", .config = ALC880_6ST },
1492	{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
1493
1494	{ .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
1495	{ .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
1496	{ .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
1497	{ .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
1498	{ .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
1499
1500	{ .modelname = "asus", .config = ALC880_ASUS },
1501	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
1502	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
1503	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
1504	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
1505	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG },
1506	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
1507	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
1508	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
1509	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
1510	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
1511	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
1512
1513	{ .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
1514	{ .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
1515
1516	{ .modelname = "F1734", .config = ALC880_F1734 },
1517	{ .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
1518
1519#ifdef CONFIG_SND_DEBUG
1520	{ .modelname = "test", .config = ALC880_TEST },
1521#endif
1522
1523	{}
1524};
1525
1526/*
1527 * configuration template - to be copied to the spec instance
1528 */
1529struct alc_config_preset {
1530	snd_kcontrol_new_t *mixers[4];
1531	const struct hda_verb *init_verbs[4];
1532	unsigned int num_dacs;
1533	hda_nid_t *dac_nids;
1534	hda_nid_t dig_out_nid;		/* optional */
1535	hda_nid_t hp_nid;		/* optional */
1536	unsigned int num_adc_nids;
1537	hda_nid_t *adc_nids;
1538	unsigned int num_channel_mode;
1539	const struct hda_channel_mode *channel_mode;
1540	const struct hda_input_mux *input_mux;
1541};
1542
1543static struct alc_config_preset alc880_presets[] = {
1544	[ALC880_3ST] = {
1545		.mixers = { alc880_three_stack_mixer },
1546		.init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
1547		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
1548		.dac_nids = alc880_dac_nids,
1549		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1550		.channel_mode = alc880_threestack_modes,
1551		.input_mux = &alc880_capture_source,
1552	},
1553	[ALC880_3ST_DIG] = {
1554		.mixers = { alc880_three_stack_mixer },
1555		.init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
1556		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
1557		.dac_nids = alc880_dac_nids,
1558		.dig_out_nid = ALC880_DIGOUT_NID,
1559		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1560		.channel_mode = alc880_threestack_modes,
1561		.input_mux = &alc880_capture_source,
1562	},
1563	[ALC880_5ST] = {
1564		.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
1565		.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
1566		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
1567		.dac_nids = alc880_dac_nids,
1568		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
1569		.channel_mode = alc880_fivestack_modes,
1570		.input_mux = &alc880_capture_source,
1571	},
1572	[ALC880_5ST_DIG] = {
1573		.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
1574		.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
1575		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
1576		.dac_nids = alc880_dac_nids,
1577		.dig_out_nid = ALC880_DIGOUT_NID,
1578		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
1579		.channel_mode = alc880_fivestack_modes,
1580		.input_mux = &alc880_capture_source,
1581	},
1582	[ALC880_6ST] = {
1583		.mixers = { alc880_six_stack_mixer },
1584		.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
1585		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
1586		.dac_nids = alc880_6st_dac_nids,
1587		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
1588		.channel_mode = alc880_sixstack_modes,
1589		.input_mux = &alc880_6stack_capture_source,
1590	},
1591	[ALC880_6ST_DIG] = {
1592		.mixers = { alc880_six_stack_mixer },
1593		.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
1594		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
1595		.dac_nids = alc880_6st_dac_nids,
1596		.dig_out_nid = ALC880_DIGOUT_NID,
1597		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
1598		.channel_mode = alc880_sixstack_modes,
1599		.input_mux = &alc880_6stack_capture_source,
1600	},
1601	[ALC880_W810] = {
1602		.mixers = { alc880_w810_base_mixer },
1603		.init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs,
1604				alc880_gpio2_init_verbs },
1605		.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
1606		.dac_nids = alc880_w810_dac_nids,
1607		.dig_out_nid = ALC880_DIGOUT_NID,
1608		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
1609		.channel_mode = alc880_w810_modes,
1610		.input_mux = &alc880_capture_source,
1611	},
1612	[ALC880_Z71V] = {
1613		.mixers = { alc880_z71v_mixer },
1614		.init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs },
1615		.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
1616		.dac_nids = alc880_z71v_dac_nids,
1617		.dig_out_nid = ALC880_DIGOUT_NID,
1618		.hp_nid = 0x03,
1619		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1620		.channel_mode = alc880_2_jack_modes,
1621		.input_mux = &alc880_capture_source,
1622	},
1623	[ALC880_F1734] = {
1624		.mixers = { alc880_f1734_mixer },
1625		.init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
1626		.num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
1627		.dac_nids = alc880_f1734_dac_nids,
1628		.hp_nid = 0x02,
1629		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1630		.channel_mode = alc880_2_jack_modes,
1631		.input_mux = &alc880_capture_source,
1632	},
1633	[ALC880_ASUS] = {
1634		.mixers = { alc880_asus_mixer },
1635		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1636				alc880_gpio1_init_verbs },
1637		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1638		.dac_nids = alc880_asus_dac_nids,
1639		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1640		.channel_mode = alc880_asus_modes,
1641		.input_mux = &alc880_capture_source,
1642	},
1643	[ALC880_ASUS_DIG] = {
1644		.mixers = { alc880_asus_mixer },
1645		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1646				alc880_gpio1_init_verbs },
1647		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1648		.dac_nids = alc880_asus_dac_nids,
1649		.dig_out_nid = ALC880_DIGOUT_NID,
1650		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1651		.channel_mode = alc880_asus_modes,
1652		.input_mux = &alc880_capture_source,
1653	},
1654	[ALC880_ASUS_W1V] = {
1655		.mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
1656		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1657				alc880_gpio1_init_verbs },
1658		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1659		.dac_nids = alc880_asus_dac_nids,
1660		.dig_out_nid = ALC880_DIGOUT_NID,
1661		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1662		.channel_mode = alc880_asus_modes,
1663		.input_mux = &alc880_capture_source,
1664	},
1665	[ALC880_UNIWILL_DIG] = {
1666		.mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
1667		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
1668		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1669		.dac_nids = alc880_asus_dac_nids,
1670		.dig_out_nid = ALC880_DIGOUT_NID,
1671		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1672		.channel_mode = alc880_asus_modes,
1673		.input_mux = &alc880_capture_source,
1674	},
1675#ifdef CONFIG_SND_DEBUG
1676	[ALC880_TEST] = {
1677		.mixers = { alc880_test_mixer },
1678		.init_verbs = { alc880_test_init_verbs },
1679		.num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
1680		.dac_nids = alc880_test_dac_nids,
1681		.dig_out_nid = ALC880_DIGOUT_NID,
1682		.num_channel_mode = ARRAY_SIZE(alc880_test_modes),
1683		.channel_mode = alc880_test_modes,
1684		.input_mux = &alc880_test_capture_source,
1685	},
1686#endif
1687};
1688
1689/*
1690 * Automatic parse of I/O pins from the BIOS configuration
1691 */
1692
1693#define NUM_CONTROL_ALLOC	32
1694#define NUM_VERB_ALLOC		32
1695
1696enum {
1697	ALC_CTL_WIDGET_VOL,
1698	ALC_CTL_WIDGET_MUTE,
1699	ALC_CTL_BIND_MUTE,
1700};
1701static snd_kcontrol_new_t alc880_control_templates[] = {
1702	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
1703	HDA_CODEC_MUTE(NULL, 0, 0, 0),
1704	HDA_BIND_MUTE(NULL, 0, 0, 0),
1705};
1706
1707/* add dynamic controls */
1708static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
1709{
1710	snd_kcontrol_new_t *knew;
1711
1712	if (spec->num_kctl_used >= spec->num_kctl_alloc) {
1713		int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
1714
1715		knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
1716		if (! knew)
1717			return -ENOMEM;
1718		if (spec->kctl_alloc) {
1719			memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
1720			kfree(spec->kctl_alloc);
1721		}
1722		spec->kctl_alloc = knew;
1723		spec->num_kctl_alloc = num;
1724	}
1725
1726	knew = &spec->kctl_alloc[spec->num_kctl_used];
1727	*knew = alc880_control_templates[type];
1728	knew->name = kstrdup(name, GFP_KERNEL);
1729	if (! knew->name)
1730		return -ENOMEM;
1731	knew->private_value = val;
1732	spec->num_kctl_used++;
1733	return 0;
1734}
1735
1736#define alc880_is_fixed_pin(nid)	((nid) >= 0x14 && (nid) <= 0x17)
1737#define alc880_fixed_pin_idx(nid)	((nid) - 0x14)
1738#define alc880_is_multi_pin(nid)	((nid) >= 0x18)
1739#define alc880_multi_pin_idx(nid)	((nid) - 0x18)
1740#define alc880_is_input_pin(nid)	((nid) >= 0x18)
1741#define alc880_input_pin_idx(nid)	((nid) - 0x18)
1742#define alc880_idx_to_dac(nid)		((nid) + 0x02)
1743#define alc880_dac_to_idx(nid)		((nid) - 0x02)
1744#define alc880_idx_to_mixer(nid)	((nid) + 0x0c)
1745#define alc880_idx_to_selector(nid)	((nid) + 0x10)
1746#define ALC880_PIN_CD_NID		0x1c
1747
1748/* fill in the dac_nids table from the parsed pin configuration */
1749static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
1750{
1751	hda_nid_t nid;
1752	int assigned[4];
1753	int i, j;
1754
1755	memset(assigned, 0, sizeof(assigned));
1756	spec->multiout.dac_nids = spec->private_dac_nids;
1757
1758	/* check the pins hardwired to audio widget */
1759	for (i = 0; i < cfg->line_outs; i++) {
1760		nid = cfg->line_out_pins[i];
1761		if (alc880_is_fixed_pin(nid)) {
1762			int idx = alc880_fixed_pin_idx(nid);
1763			spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx);
1764			assigned[idx] = 1;
1765		}
1766	}
1767	/* left pins can be connect to any audio widget */
1768	for (i = 0; i < cfg->line_outs; i++) {
1769		nid = cfg->line_out_pins[i];
1770		if (alc880_is_fixed_pin(nid))
1771			continue;
1772		/* search for an empty channel */
1773		for (j = 0; j < cfg->line_outs; j++) {
1774			if (! assigned[j]) {
1775				spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
1776				assigned[j] = 1;
1777				break;
1778			}
1779		}
1780	}
1781	spec->multiout.num_dacs = cfg->line_outs;
1782	return 0;
1783}
1784
1785/* add playback controls from the parsed DAC table */
1786static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
1787{
1788	char name[32];
1789	static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
1790	hda_nid_t nid;
1791	int i, err;
1792
1793	for (i = 0; i < cfg->line_outs; i++) {
1794		if (! spec->multiout.dac_nids[i])
1795			continue;
1796		nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
1797		if (i == 2) {
1798			/* Center/LFE */
1799			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
1800					       HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
1801				return err;
1802			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
1803					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
1804				return err;
1805			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
1806					       HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
1807				return err;
1808			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
1809					       HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
1810				return err;
1811		} else {
1812			sprintf(name, "%s Playback Volume", chname[i]);
1813			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
1814					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
1815				return err;
1816			sprintf(name, "%s Playback Switch", chname[i]);
1817			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
1818					       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
1819				return err;
1820		}
1821	}
1822	return 0;
1823}
1824
1825/* add playback controls for speaker and HP outputs */
1826static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
1827					const char *pfx)
1828{
1829	hda_nid_t nid;
1830	int err;
1831	char name[32];
1832
1833	if (! pin)
1834		return 0;
1835
1836	if (alc880_is_fixed_pin(pin)) {
1837		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
1838		if (! spec->multiout.dac_nids[0]) {
1839			/* use this as the primary output */
1840			spec->multiout.dac_nids[0] = nid;
1841			if (! spec->multiout.num_dacs)
1842				spec->multiout.num_dacs = 1;
1843		} else
1844			/* specify the DAC as the extra output */
1845			spec->multiout.hp_nid = nid;
1846		/* control HP volume/switch on the output mixer amp */
1847		nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
1848		sprintf(name, "%s Playback Volume", pfx);
1849		if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
1850				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
1851			return err;
1852		sprintf(name, "%s Playback Switch", pfx);
1853		if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
1854				       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
1855			return err;
1856	} else if (alc880_is_multi_pin(pin)) {
1857		/* set manual connection */
1858		if (! spec->multiout.dac_nids[0]) {
1859			/* use this as the primary output */
1860			spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin));
1861			if (! spec->multiout.num_dacs)
1862				spec->multiout.num_dacs = 1;
1863		}
1864		/* we have only a switch on HP-out PIN */
1865		sprintf(name, "%s Playback Switch", pfx);
1866		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
1867				       HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
1868			return err;
1869	}
1870	return 0;
1871}
1872
1873/* create input playback/capture controls for the given pin */
1874static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname)
1875{
1876	char name[32];
1877	int err, idx;
1878
1879	sprintf(name, "%s Playback Volume", ctlname);
1880	idx = alc880_input_pin_idx(pin);
1881	if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
1882			       HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
1883		return err;
1884	sprintf(name, "%s Playback Switch", ctlname);
1885	if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
1886			       HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
1887		return err;
1888	return 0;
1889}
1890
1891/* create playback/capture controls for input pins */
1892static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
1893{
1894	static char *labels[AUTO_PIN_LAST] = {
1895		"Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
1896	};
1897	struct hda_input_mux *imux = &spec->private_imux;
1898	int i, err;
1899
1900	for (i = 0; i < AUTO_PIN_LAST; i++) {
1901		if (alc880_is_input_pin(cfg->input_pins[i])) {
1902			err = new_analog_input(spec, cfg->input_pins[i], labels[i]);
1903			if (err < 0)
1904				return err;
1905			imux->items[imux->num_items].label = labels[i];
1906			imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
1907			imux->num_items++;
1908		}
1909	}
1910	return 0;
1911}
1912
1913static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type,
1914					      int dac_idx)
1915{
1916	/* set as output */
1917	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
1918	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
1919	/* need the manual connection? */
1920	if (alc880_is_multi_pin(nid)) {
1921		struct alc_spec *spec = codec->spec;
1922		int idx = alc880_multi_pin_idx(nid);
1923		snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
1924				    AC_VERB_SET_CONNECT_SEL,
1925				    alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
1926	}
1927}
1928
1929static void alc880_auto_init_multi_out(struct hda_codec *codec)
1930{
1931	struct alc_spec *spec = codec->spec;
1932	int i;
1933
1934	for (i = 0; i < spec->autocfg.line_outs; i++) {
1935		hda_nid_t nid = spec->autocfg.line_out_pins[i];
1936		alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
1937	}
1938}
1939
1940static void alc880_auto_init_extra_out(struct hda_codec *codec)
1941{
1942	struct alc_spec *spec = codec->spec;
1943	hda_nid_t pin;
1944
1945	pin = spec->autocfg.speaker_pin;
1946	if (pin) /* connect to front */
1947		alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
1948	pin = spec->autocfg.hp_pin;
1949	if (pin) /* connect to front */
1950		alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
1951}
1952
1953static void alc880_auto_init_analog_input(struct hda_codec *codec)
1954{
1955	struct alc_spec *spec = codec->spec;
1956	int i;
1957
1958	for (i = 0; i < AUTO_PIN_LAST; i++) {
1959		hda_nid_t nid = spec->autocfg.input_pins[i];
1960		if (alc880_is_input_pin(nid)) {
1961			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1962					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
1963			if (nid != ALC880_PIN_CD_NID)
1964				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1965						    AMP_OUT_MUTE);
1966		}
1967	}
1968}
1969
1970/* parse the BIOS configuration and set up the alc_spec */
1971/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
1972static int alc880_parse_auto_config(struct hda_codec *codec)
1973{
1974	struct alc_spec *spec = codec->spec;
1975	int err;
1976
1977	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0)
1978		return err;
1979	if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0)
1980		return err;
1981	if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
1982	    ! spec->autocfg.hp_pin)
1983		return 0; /* can't find valid BIOS pin config */
1984	if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
1985	    (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
1986						"Speaker")) < 0 ||
1987	    (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
1988						"Headphone")) < 0 ||
1989	    (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
1990		return err;
1991
1992	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1993
1994	if (spec->autocfg.dig_out_pin)
1995		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
1996	if (spec->autocfg.dig_in_pin)
1997		spec->dig_in_nid = ALC880_DIGIN_NID;
1998
1999	if (spec->kctl_alloc)
2000		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2001
2002	spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
2003
2004	spec->input_mux = &spec->private_imux;
2005
2006	return 1;
2007}
2008
2009/* init callback for auto-configuration model -- overriding the default init */
2010static int alc880_auto_init(struct hda_codec *codec)
2011{
2012	alc_init(codec);
2013	alc880_auto_init_multi_out(codec);
2014	alc880_auto_init_extra_out(codec);
2015	alc880_auto_init_analog_input(codec);
2016	return 0;
2017}
2018
2019/*
2020 * OK, here we have finally the patch for ALC880
2021 */
2022
2023static int patch_alc880(struct hda_codec *codec)
2024{
2025	struct alc_spec *spec;
2026	int board_config;
2027	int i, err;
2028
2029	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2030	if (spec == NULL)
2031		return -ENOMEM;
2032
2033	codec->spec = spec;
2034
2035	board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
2036	if (board_config < 0 || board_config >= ALC880_MODEL_LAST) {
2037		printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
2038		board_config = ALC880_AUTO;
2039	}
2040
2041	if (board_config == ALC880_AUTO) {
2042		/* automatic parse from the BIOS config */
2043		err = alc880_parse_auto_config(codec);
2044		if (err < 0) {
2045			alc_free(codec);
2046			return err;
2047		} else if (! err) {
2048			printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS.  Using 3-stack mode...\n");
2049			board_config = ALC880_3ST;
2050		}
2051	}
2052
2053	if (board_config != ALC880_AUTO) {
2054		/* set up from the preset table */
2055		const struct alc_config_preset *preset;
2056
2057		preset = &alc880_presets[board_config];
2058
2059		for (i = 0; preset->mixers[i]; i++) {
2060			snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break);
2061			spec->mixers[spec->num_mixers++] = preset->mixers[i];
2062		}
2063		for (i = 0; preset->init_verbs[i]; i++) {
2064			snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break);
2065			spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
2066		}
2067
2068		spec->channel_mode = preset->channel_mode;
2069		spec->num_channel_mode = preset->num_channel_mode;
2070
2071		spec->multiout.max_channels = spec->channel_mode[0].channels;
2072
2073		spec->multiout.num_dacs = preset->num_dacs;
2074		spec->multiout.dac_nids = preset->dac_nids;
2075		spec->multiout.dig_out_nid = preset->dig_out_nid;
2076		spec->multiout.hp_nid = preset->hp_nid;
2077
2078		spec->input_mux = preset->input_mux;
2079
2080		spec->num_adc_nids = preset->num_adc_nids;
2081		spec->adc_nids = preset->adc_nids;
2082	}
2083
2084	spec->stream_name_analog = "ALC880 Analog";
2085	spec->stream_analog_playback = &alc880_pcm_analog_playback;
2086	spec->stream_analog_capture = &alc880_pcm_analog_capture;
2087
2088	spec->stream_name_digital = "ALC880 Digital";
2089	spec->stream_digital_playback = &alc880_pcm_digital_playback;
2090	spec->stream_digital_capture = &alc880_pcm_digital_capture;
2091
2092	if (! spec->adc_nids && spec->input_mux) {
2093		/* check whether NID 0x07 is valid */
2094		unsigned int wcap = snd_hda_param_read(codec, alc880_adc_nids[0],
2095						       AC_PAR_AUDIO_WIDGET_CAP);
2096		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
2097		if (wcap != AC_WID_AUD_IN) {
2098			spec->adc_nids = alc880_adc_nids_alt;
2099			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
2100			spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
2101			spec->num_mixers++;
2102		} else {
2103			spec->adc_nids = alc880_adc_nids;
2104			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
2105			spec->mixers[spec->num_mixers] = alc880_capture_mixer;
2106			spec->num_mixers++;
2107		}
2108	}
2109
2110	codec->patch_ops = alc_patch_ops;
2111	if (board_config == ALC880_AUTO)
2112		codec->patch_ops.init = alc880_auto_init;
2113
2114	return 0;
2115}
2116
2117
2118/*
2119 * ALC260 support
2120 */
2121
2122static hda_nid_t alc260_dac_nids[1] = {
2123	/* front */
2124	0x02,
2125};
2126
2127static hda_nid_t alc260_adc_nids[1] = {
2128	/* ADC0 */
2129	0x04,
2130};
2131
2132static hda_nid_t alc260_hp_adc_nids[1] = {
2133	/* ADC1 */
2134	0x05,
2135};
2136
2137#define ALC260_DIGOUT_NID	0x03
2138#define ALC260_DIGIN_NID	0x06
2139
2140static struct hda_input_mux alc260_capture_source = {
2141	.num_items = 4,
2142	.items = {
2143		{ "Mic", 0x0 },
2144		{ "Front Mic", 0x1 },
2145		{ "Line", 0x2 },
2146		{ "CD", 0x4 },
2147	},
2148};
2149
2150/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack
2151 * and the internal CD lines.
2152 */
2153static struct hda_input_mux alc260_fujitsu_capture_source = {
2154	.num_items = 2,
2155	.items = {
2156		{ "Mic/Line", 0x0 },
2157		{ "CD", 0x4 },
2158	},
2159};
2160
2161/*
2162 * This is just place-holder, so there's something for alc_build_pcms to look
2163 * at when it calculates the maximum number of channels. ALC260 has no mixer
2164 * element which allows changing the channel mode, so the verb list is
2165 * never used.
2166 */
2167static struct hda_channel_mode alc260_modes[1] = {
2168	{ 2, NULL },
2169};
2170
2171static snd_kcontrol_new_t alc260_base_mixer[] = {
2172	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2173	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
2174	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2175	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2176	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
2177	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
2178	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
2179	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
2180	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
2181	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
2182	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
2183	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
2184	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2185	HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
2186	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2187	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2188	HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
2189	HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
2190	{
2191		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2192		.name = "Capture Source",
2193		.info = alc_mux_enum_info,
2194		.get = alc_mux_enum_get,
2195		.put = alc_mux_enum_put,
2196	},
2197	{ } /* end */
2198};
2199
2200static snd_kcontrol_new_t alc260_hp_mixer[] = {
2201	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2202	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
2203	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2204	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2205	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
2206	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
2207	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
2208	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
2209	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
2210	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
2211	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2212	HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
2213	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2214	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2215	HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
2216	HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
2217	{
2218		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2219		.name = "Capture Source",
2220		.info = alc_mux_enum_info,
2221		.get = alc_mux_enum_get,
2222		.put = alc_mux_enum_put,
2223	},
2224	{ } /* end */
2225};
2226
2227static snd_kcontrol_new_t alc260_fujitsu_mixer[] = {
2228	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2229	HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
2230	ALC_PINCTL_SWITCH("Headphone Amp Switch", 0x14, PIN_HP_AMP),
2231	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2232	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2233	HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
2234	HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
2235	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
2236	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
2237	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2238	HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),
2239	HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
2240	HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
2241	{
2242		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2243		.name = "Capture Source",
2244		.info = alc_mux_enum_info,
2245		.get = alc_mux_enum_get,
2246		.put = alc_mux_enum_put,
2247	},
2248	{ } /* end */
2249};
2250
2251static struct hda_verb alc260_init_verbs[] = {
2252	/* Line In pin widget for input */
2253	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2254	/* CD pin widget for input */
2255	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2256	/* Mic1 (rear panel) pin widget for input and vref at 80% */
2257	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2258	/* Mic2 (front panel) pin widget for input and vref at 80% */
2259	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2260	/* LINE-2 is used for line-out in rear */
2261	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2262	/* select line-out */
2263	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2264	/* LINE-OUT pin */
2265	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2266	/* enable HP */
2267	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2268	/* enable Mono */
2269	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2270	/* mute capture amp left and right */
2271	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2272	/* set connection select to line in (default select for this ADC) */
2273	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2274	/* mute capture amp left and right */
2275	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2276	/* set connection select to line in (default select for this ADC) */
2277	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
2278	/* set vol=0 Line-Out mixer amp left and right */
2279	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2280	/* unmute pin widget amp left and right (no gain on this amp) */
2281	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2282	/* set vol=0 HP mixer amp left and right */
2283	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2284	/* unmute pin widget amp left and right (no gain on this amp) */
2285	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2286	/* set vol=0 Mono mixer amp left and right */
2287	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2288	/* unmute pin widget amp left and right (no gain on this amp) */
2289	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2290	/* unmute LINE-2 out pin */
2291	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2292	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2293	/* mute CD */
2294	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
2295	/* mute Line In */
2296	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2297	/* mute Mic */
2298	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2299	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2300	/* mute Front out path */
2301	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2302	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2303	/* mute Headphone out path */
2304	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2305	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2306	/* mute Mono out path */
2307	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2308	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2309	{ }
2310};
2311
2312/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
2313 * laptops.
2314 */
2315static struct hda_verb alc260_fujitsu_init_verbs[] = {
2316	/* Disable all GPIOs */
2317	{0x01, AC_VERB_SET_GPIO_MASK, 0},
2318	/* Internal speaker is connected to headphone pin */
2319	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2320	/* Headphone/Line-out jack connects to Line1 pin; make it an output */
2321	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2322        /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
2323        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2324        /* Ensure all other unused pins are disabled and muted.
2325	 * Note: trying to set widget 0x15 to anything blocks all audio
2326	 * output for some reason, so just leave that at the default.
2327	 */
2328        {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2329        {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2330	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2331        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2332	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2333        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2334        /* Disable digital (SPDIF) pins */
2335        {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
2336        {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
2337
2338        /* Start with mixer outputs muted */
2339        {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2340        {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2341        {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2342
2343        /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
2344        {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2345        /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */
2346        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2347	/* Unmute pin widget used for Line-in (no equiv mixer ctrl) */
2348        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2349
2350        /* Mute capture amp left and right */
2351        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2352        /* Set ADC connection select to line in (on mic1 pin) */
2353        {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
2354
2355        /* Mute all inputs to mixer widget (even unconnected ones) */
2356        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
2357        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
2358        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
2359        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
2360        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
2361        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
2362        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
2363        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
2364};
2365
2366static struct hda_pcm_stream alc260_pcm_analog_playback = {
2367	.substreams = 1,
2368	.channels_min = 2,
2369	.channels_max = 2,
2370};
2371
2372static struct hda_pcm_stream alc260_pcm_analog_capture = {
2373	.substreams = 1,
2374	.channels_min = 2,
2375	.channels_max = 2,
2376};
2377
2378static struct hda_board_config alc260_cfg_tbl[] = {
2379	{ .modelname = "hp", .config = ALC260_HP },
2380	{ .pci_subvendor = 0x103c, .config = ALC260_HP },
2381	{ .modelname = "fujitsu", .config = ALC260_FUJITSU_S702x },
2382	{ .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702x },
2383	{}
2384};
2385
2386static int patch_alc260(struct hda_codec *codec)
2387{
2388	struct alc_spec *spec;
2389	int board_config;
2390
2391	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2392	if (spec == NULL)
2393		return -ENOMEM;
2394
2395	codec->spec = spec;
2396
2397	board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
2398	if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
2399		snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
2400		board_config = ALC260_BASIC;
2401	}
2402
2403	switch (board_config) {
2404	case ALC260_HP:
2405		spec->mixers[spec->num_mixers] = alc260_hp_mixer;
2406		spec->num_mixers++;
2407		break;
2408	case ALC260_FUJITSU_S702x:
2409		spec->mixers[spec->num_mixers] = alc260_fujitsu_mixer;
2410		spec->num_mixers++;
2411		break;
2412	default:
2413		spec->mixers[spec->num_mixers] = alc260_base_mixer;
2414		spec->num_mixers++;
2415		break;
2416	}
2417
2418	if (board_config != ALC260_FUJITSU_S702x) {
2419		spec->init_verbs[0] = alc260_init_verbs;
2420		spec->num_init_verbs = 1;
2421	} else {
2422		spec->init_verbs[0] = alc260_fujitsu_init_verbs;
2423		spec->num_init_verbs = 1;
2424	}
2425
2426	spec->channel_mode = alc260_modes;
2427	spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
2428
2429	spec->stream_name_analog = "ALC260 Analog";
2430	spec->stream_analog_playback = &alc260_pcm_analog_playback;
2431	spec->stream_analog_capture = &alc260_pcm_analog_capture;
2432
2433	spec->multiout.max_channels = spec->channel_mode[0].channels;
2434	spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
2435	spec->multiout.dac_nids = alc260_dac_nids;
2436
2437	if (board_config != ALC260_FUJITSU_S702x) {
2438		spec->input_mux = &alc260_capture_source;
2439	} else {
2440		spec->input_mux = &alc260_fujitsu_capture_source;
2441	}
2442	switch (board_config) {
2443	case ALC260_HP:
2444		spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids);
2445		spec->adc_nids = alc260_hp_adc_nids;
2446		break;
2447	default:
2448		spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
2449		spec->adc_nids = alc260_adc_nids;
2450		break;
2451	}
2452
2453	codec->patch_ops = alc_patch_ops;
2454
2455	return 0;
2456}
2457
2458
2459/*
2460 * ALC882 support
2461 *
2462 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
2463 * configuration.  Each pin widget can choose any input DACs and a mixer.
2464 * Each ADC is connected from a mixer of all inputs.  This makes possible
2465 * 6-channel independent captures.
2466 *
2467 * In addition, an independent DAC for the multi-playback (not used in this
2468 * driver yet).
2469 */
2470
2471static struct hda_channel_mode alc882_ch_modes[1] = {
2472	{ 8, NULL }
2473};
2474
2475static hda_nid_t alc882_dac_nids[4] = {
2476	/* front, rear, clfe, rear_surr */
2477	0x02, 0x03, 0x04, 0x05
2478};
2479
2480static hda_nid_t alc882_adc_nids[3] = {
2481	/* ADC0-2 */
2482	0x07, 0x08, 0x09,
2483};
2484
2485/* input MUX */
2486/* FIXME: should be a matrix-type input source selection */
2487
2488static struct hda_input_mux alc882_capture_source = {
2489	.num_items = 4,
2490	.items = {
2491		{ "Mic", 0x0 },
2492		{ "Front Mic", 0x1 },
2493		{ "Line", 0x2 },
2494		{ "CD", 0x4 },
2495	},
2496};
2497
2498#define alc882_mux_enum_info alc_mux_enum_info
2499#define alc882_mux_enum_get alc_mux_enum_get
2500
2501static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
2502{
2503	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2504	struct alc_spec *spec = codec->spec;
2505	const struct hda_input_mux *imux = spec->input_mux;
2506	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2507	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
2508	hda_nid_t nid = capture_mixers[adc_idx];
2509	unsigned int *cur_val = &spec->cur_mux[adc_idx];
2510	unsigned int i, idx;
2511
2512	idx = ucontrol->value.enumerated.item[0];
2513	if (idx >= imux->num_items)
2514		idx = imux->num_items - 1;
2515	if (*cur_val == idx && ! codec->in_resume)
2516		return 0;
2517	for (i = 0; i < imux->num_items; i++) {
2518		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
2519		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2520				    v | (imux->items[i].index << 8));
2521	}
2522	*cur_val = idx;
2523	return 1;
2524}
2525
2526/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
2527 *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
2528 */
2529static snd_kcontrol_new_t alc882_base_mixer[] = {
2530	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2531	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2532	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2533	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2534	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2535	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2536	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2537	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2538	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2539	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
2540	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
2541	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2542	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2543	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2544	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2545	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2546	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2547	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2548	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
2549	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
2550	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
2551	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
2552	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
2553	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
2554	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
2555	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
2556	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
2557	{
2558		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2559		/* .name = "Capture Source", */
2560		.name = "Input Source",
2561		.count = 3,
2562		.info = alc882_mux_enum_info,
2563		.get = alc882_mux_enum_get,
2564		.put = alc882_mux_enum_put,
2565	},
2566	{ } /* end */
2567};
2568
2569static struct hda_verb alc882_init_verbs[] = {
2570	/* Front mixer: unmute input/output amp left and right (volume = 0) */
2571	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2572	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2573	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2574	/* Rear mixer */
2575	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2576	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2577	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2578	/* CLFE mixer */
2579	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2580	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2581	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2582	/* Side mixer */
2583	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2584	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2585	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2586
2587	/* Front Pin: output 0 (0x0c) */
2588	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2589	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2590	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
2591	/* Rear Pin: output 1 (0x0d) */
2592	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2593	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2594	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
2595	/* CLFE Pin: output 2 (0x0e) */
2596	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2597	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2598	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
2599	/* Side Pin: output 3 (0x0f) */
2600	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2601	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2602	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
2603	/* Mic (rear) pin: input vref at 80% */
2604	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2605	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2606	/* Front Mic pin: input vref at 80% */
2607	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2608	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2609	/* Line In pin: input */
2610	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2611	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2612	/* Line-2 In: Headphone output (output 0 - 0x0c) */
2613	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2614	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2615	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
2616	/* CD pin widget for input */
2617	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2618
2619	/* FIXME: use matrix-type input source selection */
2620	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
2621	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
2622	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2623	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2624	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2625	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2626	/* Input mixer2 */
2627	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2628	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2629	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2630	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2631	/* Input mixer3 */
2632	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2633	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2634	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2635	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2636	/* ADC1: mute amp left and right */
2637	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2638	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
2639	/* ADC2: mute amp left and right */
2640	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2641	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
2642	/* ADC3: mute amp left and right */
2643	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2644	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
2645
2646	{ }
2647};
2648
2649static int patch_alc882(struct hda_codec *codec)
2650{
2651	struct alc_spec *spec;
2652
2653	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2654	if (spec == NULL)
2655		return -ENOMEM;
2656
2657	codec->spec = spec;
2658
2659	spec->mixers[spec->num_mixers] = alc882_base_mixer;
2660	spec->num_mixers++;
2661
2662	spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
2663	spec->dig_in_nid = ALC880_DIGIN_NID;
2664	spec->init_verbs[0] = alc882_init_verbs;
2665	spec->num_init_verbs = 1;
2666
2667	spec->channel_mode = alc882_ch_modes;
2668	spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
2669
2670	spec->stream_name_analog = "ALC882 Analog";
2671	spec->stream_analog_playback = &alc880_pcm_analog_playback;
2672	spec->stream_analog_capture = &alc880_pcm_analog_capture;
2673
2674	spec->stream_name_digital = "ALC882 Digital";
2675	spec->stream_digital_playback = &alc880_pcm_digital_playback;
2676	spec->stream_digital_capture = &alc880_pcm_digital_capture;
2677
2678	spec->multiout.max_channels = spec->channel_mode[0].channels;
2679	spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids);
2680	spec->multiout.dac_nids = alc882_dac_nids;
2681
2682	spec->input_mux = &alc882_capture_source;
2683	spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
2684	spec->adc_nids = alc882_adc_nids;
2685
2686	codec->patch_ops = alc_patch_ops;
2687
2688	return 0;
2689}
2690
2691/*
2692 * patch entries
2693 */
2694struct hda_codec_preset snd_hda_preset_realtek[] = {
2695	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
2696 	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
2697	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
2698	{} /* terminator */
2699};
2700