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