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