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