]> git.ipfire.org Git - thirdparty/kernel/stable.git/blame - sound/pci/hda/patch_realtek.c
[ALSA] Add ASUS Z71V support
[thirdparty/kernel/stable.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 *
6 * Copyright (c) 2004 PeiSen Hou <pshou@realtek.com.tw>
7 * Takashi Iwai <tiwai@suse.de>
8 *
9 * This driver is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This driver is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <sound/driver.h>
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/slab.h>
28#include <linux/pci.h>
29#include <sound/core.h>
30#include "hda_codec.h"
31#include "hda_local.h"
32
33
34/* ALC880 board config type */
35enum {
36 ALC880_MINIMAL,
37 ALC880_3ST,
38 ALC880_3ST_DIG,
39 ALC880_5ST,
40 ALC880_5ST_DIG,
41 ALC880_W810,
dfc0ff62 42 ALC880_Z71V,
1da177e4
LT
43};
44
45struct alc_spec {
46 /* codec parameterization */
47 unsigned int front_panel: 1;
48
49 snd_kcontrol_new_t* mixers[2];
50 unsigned int num_mixers;
51
52 struct hda_verb *init_verbs;
53
54 char* stream_name_analog;
55 struct hda_pcm_stream *stream_analog_playback;
56 struct hda_pcm_stream *stream_analog_capture;
57
58 char* stream_name_digital;
59 struct hda_pcm_stream *stream_digital_playback;
60 struct hda_pcm_stream *stream_digital_capture;
61
62 /* playback */
63 struct hda_multi_out multiout;
64
65 /* capture */
66 unsigned int num_adc_nids;
67 hda_nid_t *adc_nids;
68 hda_nid_t dig_in_nid;
69
70 /* capture source */
71 const struct hda_input_mux *input_mux;
72 unsigned int cur_mux[3];
73
74 /* channel model */
75 const struct alc_channel_mode *channel_mode;
76 int num_channel_mode;
77
78 /* PCM information */
79 struct hda_pcm pcm_rec[2];
80};
81
82/* DAC/ADC assignment */
83
84static hda_nid_t alc880_dac_nids[4] = {
85 /* front, rear, clfe, rear_surr */
86 0x02, 0x05, 0x04, 0x03
87};
88
89static hda_nid_t alc880_w810_dac_nids[3] = {
90 /* front, rear/surround, clfe */
91 0x02, 0x03, 0x04
92};
93
dfc0ff62
TI
94static hda_nid_t alc880_z71v_dac_nids[1] = {
95 /* front only? */
96 0x02
97};
98
1da177e4
LT
99static hda_nid_t alc880_adc_nids[3] = {
100 /* ADC0-2 */
101 0x07, 0x08, 0x09,
102};
103
104#define ALC880_DIGOUT_NID 0x06
105#define ALC880_DIGIN_NID 0x0a
106
107static hda_nid_t alc260_dac_nids[1] = {
108 /* front */
109 0x02,
110};
111
112static hda_nid_t alc260_adc_nids[2] = {
113 /* ADC0-1 */
114 0x04, 0x05,
115};
116
117#define ALC260_DIGOUT_NID 0x03
118#define ALC260_DIGIN_NID 0x06
119
120static struct hda_input_mux alc880_capture_source = {
121 .num_items = 4,
122 .items = {
123 { "Mic", 0x0 },
124 { "Front Mic", 0x3 },
125 { "Line", 0x2 },
126 { "CD", 0x4 },
127 },
128};
129
130static struct hda_input_mux alc260_capture_source = {
131 .num_items = 4,
132 .items = {
133 { "Mic", 0x0 },
134 { "Front Mic", 0x1 },
135 { "Line", 0x2 },
136 { "CD", 0x4 },
137 },
138};
139
140/*
141 * input MUX handling
142 */
143static int alc_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
144{
145 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
146 struct alc_spec *spec = codec->spec;
147 return snd_hda_input_mux_info(spec->input_mux, uinfo);
148}
149
150static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
151{
152 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
153 struct alc_spec *spec = codec->spec;
154 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
155
156 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
157 return 0;
158}
159
160static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
161{
162 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
163 struct alc_spec *spec = codec->spec;
164 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
165 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
166 spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
167}
168
169/*
170 * channel mode setting
171 */
172struct alc_channel_mode {
173 int channels;
174 const struct hda_verb *sequence;
175};
176
177
178/*
179 * channel source setting (2/6 channel selection for 3-stack)
180 */
181
182/*
183 * set the path ways for 2 channel output
184 * need to set the codec line out and mic 1 pin widgets to inputs
185 */
186static struct hda_verb alc880_threestack_ch2_init[] = {
187 /* set pin widget 1Ah (line in) for input */
188 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
189 /* set pin widget 18h (mic1) for input, for mic also enable the vref */
190 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
191 /* mute the output for Line In PW */
192 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
193 /* mute for Mic1 PW */
194 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
195 { } /* end */
196};
197
198/*
199 * 6ch mode
200 * need to set the codec line out and mic 1 pin widgets to outputs
201 */
202static struct hda_verb alc880_threestack_ch6_init[] = {
203 /* set pin widget 1Ah (line in) for output */
204 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
205 /* set pin widget 18h (mic1) for output */
206 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
207 /* unmute the output for Line In PW */
208 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
209 /* unmute for Mic1 PW */
210 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
211 /* for rear channel output using Line In 1
212 * set select widget connection (nid = 0x12) - to summer node
213 * for rear NID = 0x0f...offset 3 in connection list
214 */
215 { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 },
216 /* for Mic1 - retask for center/lfe */
217 /* set select widget connection (nid = 0x10) - to summer node for
218 * front CLFE NID = 0x0e...offset 2 in connection list
219 */
220 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 },
221 { } /* end */
222};
223
224static struct alc_channel_mode alc880_threestack_modes[2] = {
225 { 2, alc880_threestack_ch2_init },
226 { 6, alc880_threestack_ch6_init },
227};
228
229
230/*
231 * channel source setting (6/8 channel selection for 5-stack)
232 */
233
234/* set the path ways for 6 channel output
235 * need to set the codec line out and mic 1 pin widgets to inputs
236 */
237static struct hda_verb alc880_fivestack_ch6_init[] = {
238 /* set pin widget 1Ah (line in) for input */
239 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
240 /* mute the output for Line In PW */
241 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
242 { } /* end */
243};
244
245/* need to set the codec line out and mic 1 pin widgets to outputs */
246static struct hda_verb alc880_fivestack_ch8_init[] = {
247 /* set pin widget 1Ah (line in) for output */
248 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
249 /* unmute the output for Line In PW */
250 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
251 /* output for surround channel output using Line In 1 */
252 /* set select widget connection (nid = 0x12) - to summer node
253 * for surr_rear NID = 0x0d...offset 1 in connection list
254 */
255 { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 },
256 { } /* end */
257};
258
259static struct alc_channel_mode alc880_fivestack_modes[2] = {
260 { 6, alc880_fivestack_ch6_init },
261 { 8, alc880_fivestack_ch8_init },
262};
263
264/*
265 * channel source setting for W810 system
266 *
267 * W810 has rear IO for:
268 * Front (DAC 02)
269 * Surround (DAC 03)
270 * Center/LFE (DAC 04)
271 * Digital out (06)
272 *
273 * The system also has a pair of internal speakers, and a headphone jack.
274 * These are both connected to Line2 on the codec, hence to DAC 02.
275 *
276 * There is a variable resistor to control the speaker or headphone
277 * volume. This is a hardware-only device without a software API.
278 *
279 * Plugging headphones in will disable the internal speakers. This is
280 * implemented in hardware, not via the driver using jack sense. In
281 * a similar fashion, plugging into the rear socket marked "front" will
282 * disable both the speakers and headphones.
283 *
284 * For input, there's a microphone jack, and an "audio in" jack.
285 * These may not do anything useful with this driver yet, because I
286 * haven't setup any initialization verbs for these yet...
287 */
288
289static struct alc_channel_mode alc880_w810_modes[1] = {
290 { 6, NULL }
291};
292
dfc0ff62
TI
293static struct alc_channel_mode alc880_z71v_modes[1] = {
294 { 2, NULL }
295};
296
1da177e4
LT
297/*
298 */
299static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
300{
301 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
302 struct alc_spec *spec = codec->spec;
303
304 snd_assert(spec->channel_mode, return -ENXIO);
305 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
306 uinfo->count = 1;
307 uinfo->value.enumerated.items = 2;
308 if (uinfo->value.enumerated.item >= 2)
309 uinfo->value.enumerated.item = 1;
310 sprintf(uinfo->value.enumerated.name, "%dch",
311 spec->channel_mode[uinfo->value.enumerated.item].channels);
312 return 0;
313}
314
315static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
316{
317 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
318 struct alc_spec *spec = codec->spec;
319
320 snd_assert(spec->channel_mode, return -ENXIO);
321 ucontrol->value.enumerated.item[0] =
322 (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1;
323 return 0;
324}
325
326static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
327{
328 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
329 struct alc_spec *spec = codec->spec;
330 int mode;
331
332 snd_assert(spec->channel_mode, return -ENXIO);
333 mode = ucontrol->value.enumerated.item[0] ? 1 : 0;
334 if (spec->multiout.max_channels == spec->channel_mode[mode].channels &&
335 ! codec->in_resume)
336 return 0;
337
338 /* change the current channel setting */
339 spec->multiout.max_channels = spec->channel_mode[mode].channels;
340 if (spec->channel_mode[mode].sequence)
341 snd_hda_sequence_write(codec, spec->channel_mode[mode].sequence);
342
343 return 1;
344}
345
346
347/*
348 */
349
350/* 3-stack mode
351 * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
352 * HP=0x19
353 */
354static snd_kcontrol_new_t alc880_base_mixer[] = {
355 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
356 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
357 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
358 HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
359 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
360 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
361 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT),
362 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT),
363 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
364 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
365 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
366 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
367 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
368 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
369 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
370 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
371 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
372 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
373 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
374 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
375 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
376 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
377 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
378 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
379 {
380 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
381 /* The multiple "Capture Source" controls confuse alsamixer
382 * So call somewhat different..
383 * FIXME: the controls appear in the "playback" view!
384 */
385 /* .name = "Capture Source", */
386 .name = "Input Source",
387 .count = 2,
388 .info = alc_mux_enum_info,
389 .get = alc_mux_enum_get,
390 .put = alc_mux_enum_put,
391 },
392 {
393 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
394 .name = "Channel Mode",
395 .info = alc880_ch_mode_info,
396 .get = alc880_ch_mode_get,
397 .put = alc880_ch_mode_put,
398 },
399 { } /* end */
400};
401
402/* 5-stack mode
403 * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
404 * Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
405 */
406static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
407 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
408 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
409 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
410 HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT),
411 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
412 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
413 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
414 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
415 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
416 HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
417 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
418 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
419 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
420 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
421 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
422 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
423 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
424 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
425 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
426 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
427 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
428 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
429 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
430 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
431 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
432 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
433 {
434 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
435 /* The multiple "Capture Source" controls confuse alsamixer
436 * So call somewhat different..
437 * FIXME: the controls appear in the "playback" view!
438 */
439 /* .name = "Capture Source", */
440 .name = "Input Source",
441 .count = 2,
442 .info = alc_mux_enum_info,
443 .get = alc_mux_enum_get,
444 .put = alc_mux_enum_put,
445 },
446 {
447 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
448 .name = "Channel Mode",
449 .info = alc880_ch_mode_info,
450 .get = alc880_ch_mode_get,
451 .put = alc880_ch_mode_put,
452 },
453 { } /* end */
454};
455
456static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
457 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
458 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
459 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
460 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
461 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
462 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
463 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
464 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
465 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
466 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
467 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
468 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
469 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
470 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
471 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
472 {
473 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
474 /* The multiple "Capture Source" controls confuse alsamixer
475 * So call somewhat different..
476 * FIXME: the controls appear in the "playback" view!
477 */
478 /* .name = "Capture Source", */
479 .name = "Input Source",
480 .count = 3,
481 .info = alc_mux_enum_info,
482 .get = alc_mux_enum_get,
483 .put = alc_mux_enum_put,
484 },
485 { } /* end */
486};
487
dfc0ff62
TI
488static snd_kcontrol_new_t alc880_z71v_mixer[] = {
489 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
490 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
491 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
492 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
493 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
494 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
495 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
496 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
497 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
498 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
499 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
500 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
501 {
502 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
503 /* The multiple "Capture Source" controls confuse alsamixer
504 * So call somewhat different..
505 * FIXME: the controls appear in the "playback" view!
506 */
507 /* .name = "Capture Source", */
508 .name = "Input Source",
509 .count = 2,
510 .info = alc_mux_enum_info,
511 .get = alc_mux_enum_get,
512 .put = alc_mux_enum_put,
513 },
514 { } /* end */
515};
516
1da177e4
LT
517/*
518 */
519static int alc_build_controls(struct hda_codec *codec)
520{
521 struct alc_spec *spec = codec->spec;
522 int err;
523 int i;
524
525 for (i = 0; i < spec->num_mixers; i++) {
526 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
527 if (err < 0)
528 return err;
529 }
530
531 if (spec->multiout.dig_out_nid) {
532 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
533 if (err < 0)
534 return err;
535 }
536 if (spec->dig_in_nid) {
537 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
538 if (err < 0)
539 return err;
540 }
541 return 0;
542}
543
544/*
545 * initialize the codec volumes, etc
546 */
547
548static struct hda_verb alc880_init_verbs_three_stack[] = {
549 /* Line In pin widget for input */
550 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
551 /* CD pin widget for input */
552 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
553 /* Mic1 (rear panel) pin widget for input and vref at 80% */
554 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
555 /* Mic2 (front panel) pin widget for input and vref at 80% */
556 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
557 /* unmute amp left and right */
558 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
559 /* set connection select to line in (default select for this ADC) */
560 {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
561 /* unmute front mixer amp left (volume = 0) */
562 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
563 /* mute pin widget amp left and right (no gain on this amp) */
564 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
565 /* unmute rear mixer amp left and right (volume = 0) */
566 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
567 /* mute pin widget amp left and right (no gain on this amp) */
568 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
569 /* unmute rear mixer amp left and right (volume = 0) */
570 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
571 /* mute pin widget amp left and right (no gain on this amp) */
572 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
573
574 /* using rear surround as the path for headphone output */
575 /* unmute rear surround mixer amp left and right (volume = 0) */
576 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
577 /* PASD 3 stack boards use the Mic 2 as the headphone output */
578 /* need to program the selector associated with the Mic 2 pin widget to
579 * surround path (index 0x01) for headphone output */
580 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
581 /* mute pin widget amp left and right (no gain on this amp) */
582 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
583 /* need to retask the Mic 2 pin widget to output */
584 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
585
586 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
587 * to support the input path of analog loopback
588 * Note: PASD motherboards uses the Line In 2 as the input for front panel
589 * mic (mic 2)
590 */
591 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
592 /* unmute CD */
593 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
594 /* unmute Line In */
595 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
596 /* unmute Mic 1 */
597 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
598 /* unmute Line In 2 (for PASD boards Mic 2) */
599 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
600
601 /* Unmute input amps for the line out paths to support the output path of
602 * analog loopback
603 * the mixers on the output path has 2 inputs, one from the DAC and one
604 * from the mixer
605 */
606 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
607 /* Unmute Front out path */
608 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
609 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
610 /* Unmute Surround (used as HP) out path */
611 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
612 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
613 /* Unmute C/LFE out path */
614 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
615 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
616 /* Unmute rear Surround out path */
617 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
618 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
619
620 { }
621};
622
623static struct hda_verb alc880_init_verbs_five_stack[] = {
624 /* Line In pin widget for input */
625 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
626 /* CD pin widget for input */
627 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
628 /* Mic1 (rear panel) pin widget for input and vref at 80% */
629 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
630 /* Mic2 (front panel) pin widget for input and vref at 80% */
631 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
632 /* unmute amp left and right */
633 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
634 /* set connection select to line in (default select for this ADC) */
635 {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
636 /* unmute front mixer amp left and right (volume = 0) */
637 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
638 /* mute pin widget amp left and right (no gain on this amp) */
639 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
640 /* five rear and clfe */
641 /* unmute rear mixer amp left and right (volume = 0) */
642 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
643 /* mute pin widget amp left and right (no gain on this amp) */
644 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
645 /* unmute clfe mixer amp left and right (volume = 0) */
646 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
647 /* mute pin widget amp left and right (no gain on this amp) */
648 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
649
650 /* using rear surround as the path for headphone output */
651 /* unmute rear surround mixer amp left and right (volume = 0) */
652 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
653 /* PASD 3 stack boards use the Mic 2 as the headphone output */
654 /* need to program the selector associated with the Mic 2 pin widget to
655 * surround path (index 0x01) for headphone output
656 */
657 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
658 /* mute pin widget amp left and right (no gain on this amp) */
659 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
660 /* need to retask the Mic 2 pin widget to output */
661 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
662
663 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
664 * widget(nid=0x0B) to support the input path of analog loopback
665 */
666 /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
667 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
668 /* unmute CD */
669 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
670 /* unmute Line In */
671 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
672 /* unmute Mic 1 */
673 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
674 /* unmute Line In 2 (for PASD boards Mic 2) */
675 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
676
677 /* Unmute input amps for the line out paths to support the output path of
678 * analog loopback
679 * the mixers on the output path has 2 inputs, one from the DAC and
680 * one from the mixer
681 */
682 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
683 /* Unmute Front out path */
684 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
685 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
686 /* Unmute Surround (used as HP) out path */
687 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
688 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
689 /* Unmute C/LFE out path */
690 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
691 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
692 /* Unmute rear Surround out path */
693 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
694 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
695
696 { }
697};
698
699static struct hda_verb alc880_w810_init_verbs[] = {
700 /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
701 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
702
703 /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
704 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
705
706 /* front channel selector/amp: output 0: unmuted, max volume */
707 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
708
709 /* front out pin: muted, (no volume selection) */
710 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
711
712 /* front out pin: NOT headphone enable, out enable, vref disabled */
713 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
714
715
716 /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
717 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
718
719 /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
720 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
721
722 /* surround channel selector/amp: output 0: unmuted, max volume */
723 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
724
725 /* surround out pin: muted, (no volume selection) */
726 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
727
728 /* surround out pin: NOT headphone enable, out enable, vref disabled */
729 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
730
731
732 /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
733 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
734
735 /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
736 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
737
738 /* c/lfe channel selector/amp: output 0: unmuted, max volume */
739 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
740
741 /* c/lfe out pin: muted, (no volume selection) */
742 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
743
744 /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
745 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
746
747
748 /* hphone/speaker input selector: front DAC */
749 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
750
751 /* hphone/speaker out pin: muted, (no volume selection) */
752 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
753
754 /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
755 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
756
757
758 { }
759};
760
dfc0ff62
TI
761static struct hda_verb alc880_z71v_init_verbs[] = {
762 /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
763 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
764 /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
765 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
766 /* front channel selector/amp: output 0: unmuted, max volume */
767 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
768 /* front out pin: muted, (no volume selection) */
769 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
770 /* front out pin: NOT headphone enable, out enable, vref disabled */
771 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
772 /* headphone channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
773 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
774 /* headphone channel selector/amp: input 1: capture mix: muted, (no volume selection) */
775 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
776 /* headphone channel selector/amp: output 0: unmuted, max volume */
777 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
778 /* headphone out pin: muted, (no volume selection) */
779 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
780 /* headpohne out pin: headphone enable, out enable, vref disabled */
781 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
782
783 /* Line In pin widget for input */
784 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
785 /* CD pin widget for input */
786 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
787 /* Mic1 (rear panel) pin widget for input and vref at 80% */
788 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
789 /* Mic2 (front panel) pin widget for input and vref at 80% */
790 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
791 /* unmute amp left and right */
792 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
793 /* set connection select to line in (default select for this ADC) */
794 {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
795
796 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
797 * widget(nid=0x0B) to support the input path of analog loopback
798 */
799 /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
800 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
801 /* unmute CD */
802 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
803 /* unmute Line In */
804 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
805 /* unmute Mic 1 */
806 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
807 /* unmute Line In 2 (for PASD boards Mic 2) */
808 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
809
810 { }
811};
812
1da177e4
LT
813static int alc_init(struct hda_codec *codec)
814{
815 struct alc_spec *spec = codec->spec;
816 snd_hda_sequence_write(codec, spec->init_verbs);
817 return 0;
818}
819
820#ifdef CONFIG_PM
821/*
822 * resume
823 */
824static int alc_resume(struct hda_codec *codec)
825{
826 struct alc_spec *spec = codec->spec;
827 int i;
828
829 alc_init(codec);
830 for (i = 0; i < spec->num_mixers; i++) {
831 snd_hda_resume_ctls(codec, spec->mixers[i]);
832 }
833 if (spec->multiout.dig_out_nid)
834 snd_hda_resume_spdif_out(codec);
835 if (spec->dig_in_nid)
836 snd_hda_resume_spdif_in(codec);
837
838 return 0;
839}
840#endif
841
842/*
843 * Analog playback callbacks
844 */
845static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
846 struct hda_codec *codec,
847 snd_pcm_substream_t *substream)
848{
849 struct alc_spec *spec = codec->spec;
850 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
851}
852
853static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
854 struct hda_codec *codec,
855 unsigned int stream_tag,
856 unsigned int format,
857 snd_pcm_substream_t *substream)
858{
859 struct alc_spec *spec = codec->spec;
860 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
861 format, substream);
862}
863
864static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
865 struct hda_codec *codec,
866 snd_pcm_substream_t *substream)
867{
868 struct alc_spec *spec = codec->spec;
869 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
870}
871
872/*
873 * Digital out
874 */
875static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
876 struct hda_codec *codec,
877 snd_pcm_substream_t *substream)
878{
879 struct alc_spec *spec = codec->spec;
880 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
881}
882
883static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
884 struct hda_codec *codec,
885 snd_pcm_substream_t *substream)
886{
887 struct alc_spec *spec = codec->spec;
888 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
889}
890
891/*
892 * Analog capture
893 */
894static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
895 struct hda_codec *codec,
896 unsigned int stream_tag,
897 unsigned int format,
898 snd_pcm_substream_t *substream)
899{
900 struct alc_spec *spec = codec->spec;
901
902 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
903 stream_tag, 0, format);
904 return 0;
905}
906
907static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
908 struct hda_codec *codec,
909 snd_pcm_substream_t *substream)
910{
911 struct alc_spec *spec = codec->spec;
912
913 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
914 return 0;
915}
916
917
918/*
919 */
920static struct hda_pcm_stream alc880_pcm_analog_playback = {
921 .substreams = 1,
922 .channels_min = 2,
923 .channels_max = 8,
924 .nid = 0x02, /* NID to query formats and rates */
925 .ops = {
926 .open = alc880_playback_pcm_open,
927 .prepare = alc880_playback_pcm_prepare,
928 .cleanup = alc880_playback_pcm_cleanup
929 },
930};
931
932static struct hda_pcm_stream alc880_pcm_analog_capture = {
933 .substreams = 2,
934 .channels_min = 2,
935 .channels_max = 2,
936 .nid = 0x07, /* NID to query formats and rates */
937 .ops = {
938 .prepare = alc880_capture_pcm_prepare,
939 .cleanup = alc880_capture_pcm_cleanup
940 },
941};
942
943static struct hda_pcm_stream alc880_pcm_digital_playback = {
944 .substreams = 1,
945 .channels_min = 2,
946 .channels_max = 2,
947 /* NID is set in alc_build_pcms */
948 .ops = {
949 .open = alc880_dig_playback_pcm_open,
950 .close = alc880_dig_playback_pcm_close
951 },
952};
953
954static struct hda_pcm_stream alc880_pcm_digital_capture = {
955 .substreams = 1,
956 .channels_min = 2,
957 .channels_max = 2,
958 /* NID is set in alc_build_pcms */
959};
960
961static int alc_build_pcms(struct hda_codec *codec)
962{
963 struct alc_spec *spec = codec->spec;
964 struct hda_pcm *info = spec->pcm_rec;
965 int i;
966
967 codec->num_pcms = 1;
968 codec->pcm_info = info;
969
970 info->name = spec->stream_name_analog;
971 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
972 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
973
974 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
975 for (i = 0; i < spec->num_channel_mode; i++) {
976 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
977 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
978 }
979 }
980
981 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
982 codec->num_pcms++;
983 info++;
984 info->name = spec->stream_name_digital;
985 if (spec->multiout.dig_out_nid) {
986 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
987 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
988 }
989 if (spec->dig_in_nid) {
990 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
991 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
992 }
993 }
994
995 return 0;
996}
997
998static void alc_free(struct hda_codec *codec)
999{
1000 kfree(codec->spec);
1001}
1002
1003/*
1004 */
1005static struct hda_codec_ops alc_patch_ops = {
1006 .build_controls = alc_build_controls,
1007 .build_pcms = alc_build_pcms,
1008 .init = alc_init,
1009 .free = alc_free,
1010#ifdef CONFIG_PM
1011 .resume = alc_resume,
1012#endif
1013};
1014
1015/*
1016 */
1017
1018static struct hda_board_config alc880_cfg_tbl[] = {
1019 /* Back 3 jack, front 2 jack */
1020 { .modelname = "3stack", .config = ALC880_3ST },
1021 { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
1022 { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
1023 { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
1024 { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
1025 { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
1026 { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
1027 { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
1028 { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
1029 { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
1030 { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
1031 { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
1032 { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
1033 { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
1034 { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
1035 { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
1036 { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
1037 { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
1038 { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
1039 { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
1040 { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST },
1041 { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST },
1042 { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST },
1043 { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST },
1044 { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST },
1045 { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
1046 { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
1047 { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
1048 { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
1049 { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
1050 { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
1051 { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
1052 { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
1053
1054 /* Back 3 jack, front 2 jack (Internal add Aux-In) */
1055 { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
1056
1057 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
1058 { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
1059 { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG },
1060
1061 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
1062 { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG },
1063 { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG },
1064 { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG },
1065
1066 /* Back 5 jack, front 2 jack */
1067 { .modelname = "5stack", .config = ALC880_5ST },
1068 { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST },
1069 { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST },
1070 { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST },
1071 { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST },
1072
1073 /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
1074 { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
1075 { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG },
1076 { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG },
1077 { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG },
1078 { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG },
1079 { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG },
1080 { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG },
1081 { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
1082 { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
1083
1084 { .modelname = "w810", .config = ALC880_W810 },
1085 { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
1086
dfc0ff62
TI
1087 { .modelname = "z71v", .config = ALC880_Z71V },
1088 { .pci_vendor = 0x1043, .pci_device = 0x1964, .config = ALC880_Z71V },
1089
1da177e4
LT
1090 {}
1091};
1092
1093static int patch_alc880(struct hda_codec *codec)
1094{
1095 struct alc_spec *spec;
1096 int board_config;
1097
1098 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1099 if (spec == NULL)
1100 return -ENOMEM;
1101
1102 codec->spec = spec;
1103
1104 board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
1105 if (board_config < 0) {
1106 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
1107 board_config = ALC880_MINIMAL;
1108 }
1109
1110 switch (board_config) {
1111 case ALC880_W810:
1112 spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
1113 spec->num_mixers++;
1114 break;
1115 case ALC880_5ST:
1116 case ALC880_5ST_DIG:
1117 spec->mixers[spec->num_mixers] = alc880_five_stack_mixer;
1118 spec->num_mixers++;
1119 break;
dfc0ff62
TI
1120 case ALC880_Z71V:
1121 spec->mixers[spec->num_mixers] = alc880_z71v_mixer;
1122 spec->num_mixers++;
1123 break;
1da177e4
LT
1124 default:
1125 spec->mixers[spec->num_mixers] = alc880_base_mixer;
1126 spec->num_mixers++;
1127 break;
1128 }
1129
1130 switch (board_config) {
1131 case ALC880_3ST_DIG:
1132 case ALC880_5ST_DIG:
1133 case ALC880_W810:
dfc0ff62 1134 case ALC880_Z71V:
1da177e4
LT
1135 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
1136 break;
1137 default:
1138 break;
1139 }
1140
1141 switch (board_config) {
1142 case ALC880_3ST:
1143 case ALC880_3ST_DIG:
1144 case ALC880_5ST:
1145 case ALC880_5ST_DIG:
1146 case ALC880_W810:
1147 spec->front_panel = 1;
1148 break;
1149 default:
1150 break;
1151 }
1152
1153 switch (board_config) {
1154 case ALC880_5ST:
1155 case ALC880_5ST_DIG:
1156 spec->init_verbs = alc880_init_verbs_five_stack;
1157 spec->channel_mode = alc880_fivestack_modes;
1158 spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
1159 break;
1160 case ALC880_W810:
1161 spec->init_verbs = alc880_w810_init_verbs;
1162 spec->channel_mode = alc880_w810_modes;
1163 spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
1164 break;
dfc0ff62
TI
1165 case ALC880_Z71V:
1166 spec->init_verbs = alc880_z71v_init_verbs;
1167 spec->channel_mode = alc880_z71v_modes;
1168 spec->num_channel_mode = ARRAY_SIZE(alc880_z71v_modes);
1169 break;
1da177e4
LT
1170 default:
1171 spec->init_verbs = alc880_init_verbs_three_stack;
1172 spec->channel_mode = alc880_threestack_modes;
1173 spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
1174 break;
1175 }
1176
1177 spec->stream_name_analog = "ALC880 Analog";
1178 spec->stream_analog_playback = &alc880_pcm_analog_playback;
1179 spec->stream_analog_capture = &alc880_pcm_analog_capture;
1180
1181 spec->stream_name_digital = "ALC880 Digital";
1182 spec->stream_digital_playback = &alc880_pcm_digital_playback;
1183 spec->stream_digital_capture = &alc880_pcm_digital_capture;
1184
1185 spec->multiout.max_channels = spec->channel_mode[0].channels;
1186
1187 switch (board_config) {
1188 case ALC880_W810:
1189 spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
1190 spec->multiout.dac_nids = alc880_w810_dac_nids;
1191 // No dedicated headphone socket - it's shared with built-in speakers.
1192 break;
dfc0ff62
TI
1193 case ALC880_Z71V:
1194 spec->multiout.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids);
1195 spec->multiout.dac_nids = alc880_z71v_dac_nids;
1196 spec->multiout.hp_nid = 0x03;
1197 break;
1da177e4
LT
1198 default:
1199 spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
1200 spec->multiout.dac_nids = alc880_dac_nids;
1201 spec->multiout.hp_nid = 0x03; /* rear-surround NID */
1202 break;
1203 }
1204
1205 spec->input_mux = &alc880_capture_source;
1206 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
1207 spec->adc_nids = alc880_adc_nids;
1208
1209 codec->patch_ops = alc_patch_ops;
1210
1211 return 0;
1212}
1213
1214/*
1215 * ALC260 support
1216 */
1217
1218/*
1219 * This is just place-holder, so there's something for alc_build_pcms to look
1220 * at when it calculates the maximum number of channels. ALC260 has no mixer
1221 * element which allows changing the channel mode, so the verb list is
1222 * never used.
1223 */
1224static struct alc_channel_mode alc260_modes[1] = {
1225 { 2, NULL },
1226};
1227
1228snd_kcontrol_new_t alc260_base_mixer[] = {
1229 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
1230 /* use LINE2 for the output */
1231 /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */
1232 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
1233 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
1234 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
1235 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
1236 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
1237 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
1238 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
1239 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
1240 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
1241 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
1242 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
1243 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
1244 HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1245 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
1246 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
1247 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
1248 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
1249 {
1250 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1251 .name = "Capture Source",
1252 .info = alc_mux_enum_info,
1253 .get = alc_mux_enum_get,
1254 .put = alc_mux_enum_put,
1255 },
1256 { } /* end */
1257};
1258
1259static struct hda_verb alc260_init_verbs[] = {
1260 /* Line In pin widget for input */
1261 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1262 /* CD pin widget for input */
1263 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1264 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1265 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1266 /* Mic2 (front panel) pin widget for input and vref at 80% */
1267 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1268 /* LINE-2 is used for line-out in rear */
1269 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1270 /* select line-out */
1271 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1272 /* LINE-OUT pin */
1273 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1274 /* enable HP */
1275 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1276 /* enable Mono */
1277 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1278 /* unmute amp left and right */
1279 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1280 /* set connection select to line in (default select for this ADC) */
1281 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
1282 /* unmute Line-Out mixer amp left and right (volume = 0) */
1283 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1284 /* mute pin widget amp left and right (no gain on this amp) */
1285 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1286 /* unmute HP mixer amp left and right (volume = 0) */
1287 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1288 /* mute pin widget amp left and right (no gain on this amp) */
1289 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1290 /* unmute Mono mixer amp left and right (volume = 0) */
1291 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1292 /* mute pin widget amp left and right (no gain on this amp) */
1293 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1294 /* mute LINE-2 out */
1295 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1296 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
1297 /* unmute CD */
1298 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
1299 /* unmute Line In */
1300 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
1301 /* unmute Mic */
1302 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1303 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
1304 /* Unmute Front out path */
1305 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1306 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1307 /* Unmute Headphone out path */
1308 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1309 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1310 /* Unmute Mono out path */
1311 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1312 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1313 { }
1314};
1315
1316static struct hda_pcm_stream alc260_pcm_analog_playback = {
1317 .substreams = 1,
1318 .channels_min = 2,
1319 .channels_max = 2,
1320 .nid = 0x2,
1321};
1322
1323static struct hda_pcm_stream alc260_pcm_analog_capture = {
1324 .substreams = 1,
1325 .channels_min = 2,
1326 .channels_max = 2,
1327 .nid = 0x4,
1328};
1329
1330static int patch_alc260(struct hda_codec *codec)
1331{
1332 struct alc_spec *spec;
1333
1334 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1335 if (spec == NULL)
1336 return -ENOMEM;
1337
1338 codec->spec = spec;
1339
1340 spec->mixers[spec->num_mixers] = alc260_base_mixer;
1341 spec->num_mixers++;
1342
1343 spec->init_verbs = alc260_init_verbs;
1344 spec->channel_mode = alc260_modes;
1345 spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
1346
1347 spec->stream_name_analog = "ALC260 Analog";
1348 spec->stream_analog_playback = &alc260_pcm_analog_playback;
1349 spec->stream_analog_capture = &alc260_pcm_analog_capture;
1350
1351 spec->multiout.max_channels = spec->channel_mode[0].channels;
1352 spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
1353 spec->multiout.dac_nids = alc260_dac_nids;
1354
1355 spec->input_mux = &alc260_capture_source;
1356 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
1357 spec->adc_nids = alc260_adc_nids;
1358
1359 codec->patch_ops = alc_patch_ops;
1360
1361 return 0;
1362}
1363
1364/*
1365 * ALC882 support
1366 *
1367 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
1368 * configuration. Each pin widget can choose any input DACs and a mixer.
1369 * Each ADC is connected from a mixer of all inputs. This makes possible
1370 * 6-channel independent captures.
1371 *
1372 * In addition, an independent DAC for the multi-playback (not used in this
1373 * driver yet).
1374 */
1375
1376static struct alc_channel_mode alc882_ch_modes[1] = {
1377 { 8, NULL }
1378};
1379
1380static hda_nid_t alc882_dac_nids[4] = {
1381 /* front, rear, clfe, rear_surr */
1382 0x02, 0x03, 0x04, 0x05
1383};
1384
1385static hda_nid_t alc882_adc_nids[3] = {
1386 /* ADC0-2 */
1387 0x07, 0x08, 0x09,
1388};
1389
1390/* input MUX */
1391/* FIXME: should be a matrix-type input source selection */
1392
1393static struct hda_input_mux alc882_capture_source = {
1394 .num_items = 4,
1395 .items = {
1396 { "Mic", 0x0 },
1397 { "Front Mic", 0x1 },
1398 { "Line", 0x2 },
1399 { "CD", 0x4 },
1400 },
1401};
1402
1403#define alc882_mux_enum_info alc_mux_enum_info
1404#define alc882_mux_enum_get alc_mux_enum_get
1405
1406static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1407{
1408 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1409 struct alc_spec *spec = codec->spec;
1410 const struct hda_input_mux *imux = spec->input_mux;
1411 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1412 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
1413 hda_nid_t nid = capture_mixers[adc_idx];
1414 unsigned int *cur_val = &spec->cur_mux[adc_idx];
1415 unsigned int i, idx;
1416
1417 idx = ucontrol->value.enumerated.item[0];
1418 if (idx >= imux->num_items)
1419 idx = imux->num_items - 1;
1420 if (*cur_val == idx && ! codec->in_resume)
1421 return 0;
1422 for (i = 0; i < imux->num_items; i++) {
1423 unsigned int v = (i == idx) ? 0x7000 : 0x7080;
1424 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1425 v | (imux->items[i].index << 8));
1426 }
1427 *cur_val = idx;
1428 return 1;
1429}
1430
1431/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
1432 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
1433 */
1434static snd_kcontrol_new_t alc882_base_mixer[] = {
1435 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1436 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
1437 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1438 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
1439 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1440 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1441 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
1442 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
1443 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1444 HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT),
1445 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1446 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1447 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1448 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1449 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1450 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1451 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1452 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1453 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1454 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1455 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1456 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
1457 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
1458 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
1459 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
1460 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
1461 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
1462 {
1463 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1464 /* .name = "Capture Source", */
1465 .name = "Input Source",
1466 .count = 3,
1467 .info = alc882_mux_enum_info,
1468 .get = alc882_mux_enum_get,
1469 .put = alc882_mux_enum_put,
1470 },
1471 { } /* end */
1472};
1473
1474static struct hda_verb alc882_init_verbs[] = {
1475 /* Front mixer: unmute input/output amp left and right (volume = 0) */
1476 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1477 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1478 /* Rear mixer */
1479 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1480 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1481 /* CLFE mixer */
1482 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1483 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1484 /* Side mixer */
1485 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1486 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1487
1488 /* Front Pin: to output mode */
1489 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1490 /* Front Pin: mute amp left and right (no volume) */
1491 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1492 /* select Front mixer (0x0c, index 0) */
1493 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1494 /* Rear Pin */
1495 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1496 /* Rear Pin: mute amp left and right (no volume) */
1497 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1498 /* select Rear mixer (0x0d, index 1) */
1499 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
1500 /* CLFE Pin */
1501 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1502 /* CLFE Pin: mute amp left and right (no volume) */
1503 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1504 /* select CLFE mixer (0x0e, index 2) */
1505 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
1506 /* Side Pin */
1507 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1508 /* Side Pin: mute amp left and right (no volume) */
1509 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1510 /* select Side mixer (0x0f, index 3) */
1511 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1512 /* Headphone Pin */
1513 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1514 /* Headphone Pin: mute amp left and right (no volume) */
1515 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1516 /* select Front mixer (0x0c, index 0) */
1517 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1518 /* Mic (rear) pin widget for input and vref at 80% */
1519 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1520 /* Front Mic pin widget for input and vref at 80% */
1521 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1522 /* Line In pin widget for input */
1523 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1524 /* CD pin widget for input */
1525 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1526
1527 /* FIXME: use matrix-type input source selection */
1528 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
1529 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
1530 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1531 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
1532 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
1533 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
1534 /* Input mixer2 */
1535 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1536 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
1537 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
1538 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
1539 /* Input mixer3 */
1540 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1541 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
1542 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
1543 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
1544 /* ADC1: unmute amp left and right */
1545 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1546 /* ADC2: unmute amp left and right */
1547 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1548 /* ADC3: unmute amp left and right */
1549 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1550
1551 /* Unmute front loopback */
1552 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1553 /* Unmute rear loopback */
1554 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1555 /* Mute CLFE loopback */
1556 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
1557 /* Unmute side loopback */
1558 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1559
1560 { }
1561};
1562
1563static int patch_alc882(struct hda_codec *codec)
1564{
1565 struct alc_spec *spec;
1566
1567 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1568 if (spec == NULL)
1569 return -ENOMEM;
1570
1571 codec->spec = spec;
1572
1573 spec->mixers[spec->num_mixers] = alc882_base_mixer;
1574 spec->num_mixers++;
1575
1576 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
1577 spec->dig_in_nid = ALC880_DIGIN_NID;
1578 spec->front_panel = 1;
1579 spec->init_verbs = alc882_init_verbs;
1580 spec->channel_mode = alc882_ch_modes;
1581 spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
1582
1583 spec->stream_name_analog = "ALC882 Analog";
1584 spec->stream_analog_playback = &alc880_pcm_analog_playback;
1585 spec->stream_analog_capture = &alc880_pcm_analog_capture;
1586
1587 spec->stream_name_digital = "ALC882 Digital";
1588 spec->stream_digital_playback = &alc880_pcm_digital_playback;
1589 spec->stream_digital_capture = &alc880_pcm_digital_capture;
1590
1591 spec->multiout.max_channels = spec->channel_mode[0].channels;
1592 spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids);
1593 spec->multiout.dac_nids = alc882_dac_nids;
1594
1595 spec->input_mux = &alc882_capture_source;
1596 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
1597 spec->adc_nids = alc882_adc_nids;
1598
1599 codec->patch_ops = alc_patch_ops;
1600
1601 return 0;
1602}
1603
1604/*
1605 * patch entries
1606 */
1607struct hda_codec_preset snd_hda_preset_realtek[] = {
1608 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
1609 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
1610 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
1611 {} /* terminator */
1612};