[PATCH] aic7xxx_osm build fix
[cris-mirror.git] / sound / pci / hda / patch_realtek.c
blob17c5062423aee236922d940bb697ffd5822b1ea5
1 /*
2 * Universal Interface for Intel High Definition Audio Codec
4 * HD audio interface patch for ALC 260/880/882 codecs
6 * Copyright (c) 2004 PeiSen Hou <pshou@realtek.com.tw>
7 * Takashi Iwai <tiwai@suse.de>
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.
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.
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
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"
34 /* ALC880 board config type */
35 enum {
36 ALC880_MINIMAL,
37 ALC880_3ST,
38 ALC880_3ST_DIG,
39 ALC880_5ST,
40 ALC880_5ST_DIG,
41 ALC880_W810,
44 struct alc_spec {
45 /* codec parameterization */
46 unsigned int front_panel: 1;
48 snd_kcontrol_new_t* mixers[2];
49 unsigned int num_mixers;
51 struct hda_verb *init_verbs;
53 char* stream_name_analog;
54 struct hda_pcm_stream *stream_analog_playback;
55 struct hda_pcm_stream *stream_analog_capture;
57 char* stream_name_digital;
58 struct hda_pcm_stream *stream_digital_playback;
59 struct hda_pcm_stream *stream_digital_capture;
61 /* playback */
62 struct hda_multi_out multiout;
64 /* capture */
65 unsigned int num_adc_nids;
66 hda_nid_t *adc_nids;
67 hda_nid_t dig_in_nid;
69 /* capture source */
70 const struct hda_input_mux *input_mux;
71 unsigned int cur_mux[3];
73 /* channel model */
74 const struct alc_channel_mode *channel_mode;
75 int num_channel_mode;
77 /* PCM information */
78 struct hda_pcm pcm_rec[2];
81 /* DAC/ADC assignment */
83 static hda_nid_t alc880_dac_nids[4] = {
84 /* front, rear, clfe, rear_surr */
85 0x02, 0x05, 0x04, 0x03
88 static hda_nid_t alc880_w810_dac_nids[3] = {
89 /* front, rear/surround, clfe */
90 0x02, 0x03, 0x04
93 static hda_nid_t alc880_adc_nids[3] = {
94 /* ADC0-2 */
95 0x07, 0x08, 0x09,
98 #define ALC880_DIGOUT_NID 0x06
99 #define ALC880_DIGIN_NID 0x0a
101 static hda_nid_t alc260_dac_nids[1] = {
102 /* front */
103 0x02,
106 static hda_nid_t alc260_adc_nids[2] = {
107 /* ADC0-1 */
108 0x04, 0x05,
111 #define ALC260_DIGOUT_NID 0x03
112 #define ALC260_DIGIN_NID 0x06
114 static struct hda_input_mux alc880_capture_source = {
115 .num_items = 4,
116 .items = {
117 { "Mic", 0x0 },
118 { "Front Mic", 0x3 },
119 { "Line", 0x2 },
120 { "CD", 0x4 },
124 static struct hda_input_mux alc260_capture_source = {
125 .num_items = 4,
126 .items = {
127 { "Mic", 0x0 },
128 { "Front Mic", 0x1 },
129 { "Line", 0x2 },
130 { "CD", 0x4 },
135 * input MUX handling
137 static int alc_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
139 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
140 struct alc_spec *spec = codec->spec;
141 return snd_hda_input_mux_info(spec->input_mux, uinfo);
144 static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
146 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
147 struct alc_spec *spec = codec->spec;
148 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
150 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
151 return 0;
154 static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
156 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
157 struct alc_spec *spec = codec->spec;
158 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
159 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
160 spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
164 * channel mode setting
166 struct alc_channel_mode {
167 int channels;
168 const struct hda_verb *sequence;
173 * channel source setting (2/6 channel selection for 3-stack)
177 * set the path ways for 2 channel output
178 * need to set the codec line out and mic 1 pin widgets to inputs
180 static struct hda_verb alc880_threestack_ch2_init[] = {
181 /* set pin widget 1Ah (line in) for input */
182 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
183 /* set pin widget 18h (mic1) for input, for mic also enable the vref */
184 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
185 /* mute the output for Line In PW */
186 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
187 /* mute for Mic1 PW */
188 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
189 { } /* end */
193 * 6ch mode
194 * need to set the codec line out and mic 1 pin widgets to outputs
196 static struct hda_verb alc880_threestack_ch6_init[] = {
197 /* set pin widget 1Ah (line in) for output */
198 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
199 /* set pin widget 18h (mic1) for output */
200 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
201 /* unmute the output for Line In PW */
202 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
203 /* unmute for Mic1 PW */
204 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
205 /* for rear channel output using Line In 1
206 * set select widget connection (nid = 0x12) - to summer node
207 * for rear NID = 0x0f...offset 3 in connection list
209 { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 },
210 /* for Mic1 - retask for center/lfe */
211 /* set select widget connection (nid = 0x10) - to summer node for
212 * front CLFE NID = 0x0e...offset 2 in connection list
214 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 },
215 { } /* end */
218 static struct alc_channel_mode alc880_threestack_modes[2] = {
219 { 2, alc880_threestack_ch2_init },
220 { 6, alc880_threestack_ch6_init },
225 * channel source setting (6/8 channel selection for 5-stack)
228 /* set the path ways for 6 channel output
229 * need to set the codec line out and mic 1 pin widgets to inputs
231 static struct hda_verb alc880_fivestack_ch6_init[] = {
232 /* set pin widget 1Ah (line in) for input */
233 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
234 /* mute the output for Line In PW */
235 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
236 { } /* end */
239 /* need to set the codec line out and mic 1 pin widgets to outputs */
240 static struct hda_verb alc880_fivestack_ch8_init[] = {
241 /* set pin widget 1Ah (line in) for output */
242 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
243 /* unmute the output for Line In PW */
244 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
245 /* output for surround channel output using Line In 1 */
246 /* set select widget connection (nid = 0x12) - to summer node
247 * for surr_rear NID = 0x0d...offset 1 in connection list
249 { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 },
250 { } /* end */
253 static struct alc_channel_mode alc880_fivestack_modes[2] = {
254 { 6, alc880_fivestack_ch6_init },
255 { 8, alc880_fivestack_ch8_init },
259 * channel source setting for W810 system
261 * W810 has rear IO for:
262 * Front (DAC 02)
263 * Surround (DAC 03)
264 * Center/LFE (DAC 04)
265 * Digital out (06)
267 * The system also has a pair of internal speakers, and a headphone jack.
268 * These are both connected to Line2 on the codec, hence to DAC 02.
270 * There is a variable resistor to control the speaker or headphone
271 * volume. This is a hardware-only device without a software API.
273 * Plugging headphones in will disable the internal speakers. This is
274 * implemented in hardware, not via the driver using jack sense. In
275 * a similar fashion, plugging into the rear socket marked "front" will
276 * disable both the speakers and headphones.
278 * For input, there's a microphone jack, and an "audio in" jack.
279 * These may not do anything useful with this driver yet, because I
280 * haven't setup any initialization verbs for these yet...
283 static struct alc_channel_mode alc880_w810_modes[1] = {
284 { 6, NULL }
289 static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
291 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
292 struct alc_spec *spec = codec->spec;
294 snd_assert(spec->channel_mode, return -ENXIO);
295 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
296 uinfo->count = 1;
297 uinfo->value.enumerated.items = 2;
298 if (uinfo->value.enumerated.item >= 2)
299 uinfo->value.enumerated.item = 1;
300 sprintf(uinfo->value.enumerated.name, "%dch",
301 spec->channel_mode[uinfo->value.enumerated.item].channels);
302 return 0;
305 static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
307 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
308 struct alc_spec *spec = codec->spec;
310 snd_assert(spec->channel_mode, return -ENXIO);
311 ucontrol->value.enumerated.item[0] =
312 (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1;
313 return 0;
316 static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
318 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
319 struct alc_spec *spec = codec->spec;
320 int mode;
322 snd_assert(spec->channel_mode, return -ENXIO);
323 mode = ucontrol->value.enumerated.item[0] ? 1 : 0;
324 if (spec->multiout.max_channels == spec->channel_mode[mode].channels &&
325 ! codec->in_resume)
326 return 0;
328 /* change the current channel setting */
329 spec->multiout.max_channels = spec->channel_mode[mode].channels;
330 if (spec->channel_mode[mode].sequence)
331 snd_hda_sequence_write(codec, spec->channel_mode[mode].sequence);
333 return 1;
340 /* 3-stack mode
341 * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
342 * HP=0x19
344 static snd_kcontrol_new_t alc880_base_mixer[] = {
345 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
346 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
347 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
348 HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
349 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
350 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
351 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT),
352 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT),
353 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
354 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
355 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
356 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
357 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
358 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
359 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
360 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
361 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
362 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
363 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
364 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
365 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
366 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
367 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
368 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
370 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
371 /* The multiple "Capture Source" controls confuse alsamixer
372 * So call somewhat different..
373 * FIXME: the controls appear in the "playback" view!
375 /* .name = "Capture Source", */
376 .name = "Input Source",
377 .count = 2,
378 .info = alc_mux_enum_info,
379 .get = alc_mux_enum_get,
380 .put = alc_mux_enum_put,
383 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
384 .name = "Channel Mode",
385 .info = alc880_ch_mode_info,
386 .get = alc880_ch_mode_get,
387 .put = alc880_ch_mode_put,
389 { } /* end */
392 /* 5-stack mode
393 * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
394 * Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
396 static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
397 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
398 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
399 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
400 HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT),
401 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
402 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
403 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
404 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
405 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
406 HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
407 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
408 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
409 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
410 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
411 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
412 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
413 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
414 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
415 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
416 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
417 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
418 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
419 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
420 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
421 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
422 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
424 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
425 /* The multiple "Capture Source" controls confuse alsamixer
426 * So call somewhat different..
427 * FIXME: the controls appear in the "playback" view!
429 /* .name = "Capture Source", */
430 .name = "Input Source",
431 .count = 2,
432 .info = alc_mux_enum_info,
433 .get = alc_mux_enum_get,
434 .put = alc_mux_enum_put,
437 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
438 .name = "Channel Mode",
439 .info = alc880_ch_mode_info,
440 .get = alc880_ch_mode_get,
441 .put = alc880_ch_mode_put,
443 { } /* end */
446 static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
447 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
448 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
449 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
450 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
451 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
452 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
453 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
454 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
455 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
456 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
457 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
458 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
459 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
460 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
461 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
463 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
464 /* The multiple "Capture Source" controls confuse alsamixer
465 * So call somewhat different..
466 * FIXME: the controls appear in the "playback" view!
468 /* .name = "Capture Source", */
469 .name = "Input Source",
470 .count = 3,
471 .info = alc_mux_enum_info,
472 .get = alc_mux_enum_get,
473 .put = alc_mux_enum_put,
475 { } /* end */
480 static int alc_build_controls(struct hda_codec *codec)
482 struct alc_spec *spec = codec->spec;
483 int err;
484 int i;
486 for (i = 0; i < spec->num_mixers; i++) {
487 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
488 if (err < 0)
489 return err;
492 if (spec->multiout.dig_out_nid) {
493 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
494 if (err < 0)
495 return err;
497 if (spec->dig_in_nid) {
498 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
499 if (err < 0)
500 return err;
502 return 0;
506 * initialize the codec volumes, etc
509 static struct hda_verb alc880_init_verbs_three_stack[] = {
510 /* Line In pin widget for input */
511 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
512 /* CD pin widget for input */
513 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
514 /* Mic1 (rear panel) pin widget for input and vref at 80% */
515 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
516 /* Mic2 (front panel) pin widget for input and vref at 80% */
517 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
518 /* unmute amp left and right */
519 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
520 /* set connection select to line in (default select for this ADC) */
521 {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
522 /* unmute front mixer amp left (volume = 0) */
523 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
524 /* mute pin widget amp left and right (no gain on this amp) */
525 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
526 /* unmute rear mixer amp left and right (volume = 0) */
527 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
528 /* mute pin widget amp left and right (no gain on this amp) */
529 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
530 /* unmute rear mixer amp left and right (volume = 0) */
531 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
532 /* mute pin widget amp left and right (no gain on this amp) */
533 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
535 /* using rear surround as the path for headphone output */
536 /* unmute rear surround mixer amp left and right (volume = 0) */
537 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
538 /* PASD 3 stack boards use the Mic 2 as the headphone output */
539 /* need to program the selector associated with the Mic 2 pin widget to
540 * surround path (index 0x01) for headphone output */
541 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
542 /* mute pin widget amp left and right (no gain on this amp) */
543 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
544 /* need to retask the Mic 2 pin widget to output */
545 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
547 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
548 * to support the input path of analog loopback
549 * Note: PASD motherboards uses the Line In 2 as the input for front panel
550 * mic (mic 2)
552 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
553 /* unmute CD */
554 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
555 /* unmute Line In */
556 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
557 /* unmute Mic 1 */
558 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
559 /* unmute Line In 2 (for PASD boards Mic 2) */
560 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
562 /* Unmute input amps for the line out paths to support the output path of
563 * analog loopback
564 * the mixers on the output path has 2 inputs, one from the DAC and one
565 * from the mixer
567 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
568 /* Unmute Front out path */
569 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
570 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
571 /* Unmute Surround (used as HP) out path */
572 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
573 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
574 /* Unmute C/LFE out path */
575 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
576 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
577 /* Unmute rear Surround out path */
578 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
579 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
584 static struct hda_verb alc880_init_verbs_five_stack[] = {
585 /* Line In pin widget for input */
586 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
587 /* CD pin widget for input */
588 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
589 /* Mic1 (rear panel) pin widget for input and vref at 80% */
590 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
591 /* Mic2 (front panel) pin widget for input and vref at 80% */
592 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
593 /* unmute amp left and right */
594 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
595 /* set connection select to line in (default select for this ADC) */
596 {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
597 /* unmute front mixer amp left and right (volume = 0) */
598 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
599 /* mute pin widget amp left and right (no gain on this amp) */
600 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
601 /* five rear and clfe */
602 /* unmute rear mixer amp left and right (volume = 0) */
603 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
604 /* mute pin widget amp left and right (no gain on this amp) */
605 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
606 /* unmute clfe mixer amp left and right (volume = 0) */
607 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
608 /* mute pin widget amp left and right (no gain on this amp) */
609 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
611 /* using rear surround as the path for headphone output */
612 /* unmute rear surround mixer amp left and right (volume = 0) */
613 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
614 /* PASD 3 stack boards use the Mic 2 as the headphone output */
615 /* need to program the selector associated with the Mic 2 pin widget to
616 * surround path (index 0x01) for headphone output
618 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
619 /* mute pin widget amp left and right (no gain on this amp) */
620 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
621 /* need to retask the Mic 2 pin widget to output */
622 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
624 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
625 * widget(nid=0x0B) to support the input path of analog loopback
627 /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
628 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
629 /* unmute CD */
630 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
631 /* unmute Line In */
632 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
633 /* unmute Mic 1 */
634 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
635 /* unmute Line In 2 (for PASD boards Mic 2) */
636 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
638 /* Unmute input amps for the line out paths to support the output path of
639 * analog loopback
640 * the mixers on the output path has 2 inputs, one from the DAC and
641 * one from the mixer
643 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
644 /* Unmute Front out path */
645 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
646 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
647 /* Unmute Surround (used as HP) out path */
648 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
649 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
650 /* Unmute C/LFE out path */
651 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
652 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
653 /* Unmute rear Surround out path */
654 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
655 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
660 static struct hda_verb alc880_w810_init_verbs[] = {
661 /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
662 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
664 /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
665 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
667 /* front channel selector/amp: output 0: unmuted, max volume */
668 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
670 /* front out pin: muted, (no volume selection) */
671 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
673 /* front out pin: NOT headphone enable, out enable, vref disabled */
674 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
677 /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
678 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
680 /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
681 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
683 /* surround channel selector/amp: output 0: unmuted, max volume */
684 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
686 /* surround out pin: muted, (no volume selection) */
687 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
689 /* surround out pin: NOT headphone enable, out enable, vref disabled */
690 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
693 /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
694 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
696 /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
697 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
699 /* c/lfe channel selector/amp: output 0: unmuted, max volume */
700 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
702 /* c/lfe out pin: muted, (no volume selection) */
703 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
705 /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
706 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
709 /* hphone/speaker input selector: front DAC */
710 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
712 /* hphone/speaker out pin: muted, (no volume selection) */
713 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
715 /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
716 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
722 static int alc_init(struct hda_codec *codec)
724 struct alc_spec *spec = codec->spec;
725 snd_hda_sequence_write(codec, spec->init_verbs);
726 return 0;
729 #ifdef CONFIG_PM
731 * resume
733 static int alc_resume(struct hda_codec *codec)
735 struct alc_spec *spec = codec->spec;
736 int i;
738 alc_init(codec);
739 for (i = 0; i < spec->num_mixers; i++) {
740 snd_hda_resume_ctls(codec, spec->mixers[i]);
742 if (spec->multiout.dig_out_nid)
743 snd_hda_resume_spdif_out(codec);
744 if (spec->dig_in_nid)
745 snd_hda_resume_spdif_in(codec);
747 return 0;
749 #endif
752 * Analog playback callbacks
754 static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
755 struct hda_codec *codec,
756 snd_pcm_substream_t *substream)
758 struct alc_spec *spec = codec->spec;
759 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
762 static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
763 struct hda_codec *codec,
764 unsigned int stream_tag,
765 unsigned int format,
766 snd_pcm_substream_t *substream)
768 struct alc_spec *spec = codec->spec;
769 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
770 format, substream);
773 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
774 struct hda_codec *codec,
775 snd_pcm_substream_t *substream)
777 struct alc_spec *spec = codec->spec;
778 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
782 * Digital out
784 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
785 struct hda_codec *codec,
786 snd_pcm_substream_t *substream)
788 struct alc_spec *spec = codec->spec;
789 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
792 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
793 struct hda_codec *codec,
794 snd_pcm_substream_t *substream)
796 struct alc_spec *spec = codec->spec;
797 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
801 * Analog capture
803 static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
804 struct hda_codec *codec,
805 unsigned int stream_tag,
806 unsigned int format,
807 snd_pcm_substream_t *substream)
809 struct alc_spec *spec = codec->spec;
811 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
812 stream_tag, 0, format);
813 return 0;
816 static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
817 struct hda_codec *codec,
818 snd_pcm_substream_t *substream)
820 struct alc_spec *spec = codec->spec;
822 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
823 return 0;
829 static struct hda_pcm_stream alc880_pcm_analog_playback = {
830 .substreams = 1,
831 .channels_min = 2,
832 .channels_max = 8,
833 .nid = 0x02, /* NID to query formats and rates */
834 .ops = {
835 .open = alc880_playback_pcm_open,
836 .prepare = alc880_playback_pcm_prepare,
837 .cleanup = alc880_playback_pcm_cleanup
841 static struct hda_pcm_stream alc880_pcm_analog_capture = {
842 .substreams = 2,
843 .channels_min = 2,
844 .channels_max = 2,
845 .nid = 0x07, /* NID to query formats and rates */
846 .ops = {
847 .prepare = alc880_capture_pcm_prepare,
848 .cleanup = alc880_capture_pcm_cleanup
852 static struct hda_pcm_stream alc880_pcm_digital_playback = {
853 .substreams = 1,
854 .channels_min = 2,
855 .channels_max = 2,
856 /* NID is set in alc_build_pcms */
857 .ops = {
858 .open = alc880_dig_playback_pcm_open,
859 .close = alc880_dig_playback_pcm_close
863 static struct hda_pcm_stream alc880_pcm_digital_capture = {
864 .substreams = 1,
865 .channels_min = 2,
866 .channels_max = 2,
867 /* NID is set in alc_build_pcms */
870 static int alc_build_pcms(struct hda_codec *codec)
872 struct alc_spec *spec = codec->spec;
873 struct hda_pcm *info = spec->pcm_rec;
874 int i;
876 codec->num_pcms = 1;
877 codec->pcm_info = info;
879 info->name = spec->stream_name_analog;
880 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
881 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
883 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
884 for (i = 0; i < spec->num_channel_mode; i++) {
885 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
886 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
890 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
891 codec->num_pcms++;
892 info++;
893 info->name = spec->stream_name_digital;
894 if (spec->multiout.dig_out_nid) {
895 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
896 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
898 if (spec->dig_in_nid) {
899 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
900 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
904 return 0;
907 static void alc_free(struct hda_codec *codec)
909 kfree(codec->spec);
914 static struct hda_codec_ops alc_patch_ops = {
915 .build_controls = alc_build_controls,
916 .build_pcms = alc_build_pcms,
917 .init = alc_init,
918 .free = alc_free,
919 #ifdef CONFIG_PM
920 .resume = alc_resume,
921 #endif
927 static struct hda_board_config alc880_cfg_tbl[] = {
928 /* Back 3 jack, front 2 jack */
929 { .modelname = "3stack", .config = ALC880_3ST },
930 { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
931 { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
932 { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
933 { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
934 { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
935 { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
936 { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
937 { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
938 { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
939 { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
940 { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
941 { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
942 { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
943 { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
944 { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
945 { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
946 { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
947 { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
948 { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
949 { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST },
950 { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST },
951 { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST },
952 { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST },
953 { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST },
954 { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
955 { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
956 { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
957 { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
958 { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
959 { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
960 { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
961 { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
963 /* Back 3 jack, front 2 jack (Internal add Aux-In) */
964 { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
966 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
967 { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
968 { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG },
970 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
971 { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG },
972 { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG },
973 { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG },
975 /* Back 5 jack, front 2 jack */
976 { .modelname = "5stack", .config = ALC880_5ST },
977 { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST },
978 { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST },
979 { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST },
980 { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST },
982 /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
983 { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
984 { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG },
985 { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG },
986 { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG },
987 { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG },
988 { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG },
989 { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG },
990 { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
991 { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
993 { .modelname = "w810", .config = ALC880_W810 },
994 { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
999 static int patch_alc880(struct hda_codec *codec)
1001 struct alc_spec *spec;
1002 int board_config;
1004 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1005 if (spec == NULL)
1006 return -ENOMEM;
1008 codec->spec = spec;
1010 board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
1011 if (board_config < 0) {
1012 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
1013 board_config = ALC880_MINIMAL;
1016 switch (board_config) {
1017 case ALC880_W810:
1018 spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
1019 spec->num_mixers++;
1020 break;
1021 case ALC880_5ST:
1022 case ALC880_5ST_DIG:
1023 spec->mixers[spec->num_mixers] = alc880_five_stack_mixer;
1024 spec->num_mixers++;
1025 break;
1026 default:
1027 spec->mixers[spec->num_mixers] = alc880_base_mixer;
1028 spec->num_mixers++;
1029 break;
1032 switch (board_config) {
1033 case ALC880_3ST_DIG:
1034 case ALC880_5ST_DIG:
1035 case ALC880_W810:
1036 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
1037 break;
1038 default:
1039 break;
1042 switch (board_config) {
1043 case ALC880_3ST:
1044 case ALC880_3ST_DIG:
1045 case ALC880_5ST:
1046 case ALC880_5ST_DIG:
1047 case ALC880_W810:
1048 spec->front_panel = 1;
1049 break;
1050 default:
1051 break;
1054 switch (board_config) {
1055 case ALC880_5ST:
1056 case ALC880_5ST_DIG:
1057 spec->init_verbs = alc880_init_verbs_five_stack;
1058 spec->channel_mode = alc880_fivestack_modes;
1059 spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
1060 break;
1061 case ALC880_W810:
1062 spec->init_verbs = alc880_w810_init_verbs;
1063 spec->channel_mode = alc880_w810_modes;
1064 spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
1065 break;
1066 default:
1067 spec->init_verbs = alc880_init_verbs_three_stack;
1068 spec->channel_mode = alc880_threestack_modes;
1069 spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
1070 break;
1073 spec->stream_name_analog = "ALC880 Analog";
1074 spec->stream_analog_playback = &alc880_pcm_analog_playback;
1075 spec->stream_analog_capture = &alc880_pcm_analog_capture;
1077 spec->stream_name_digital = "ALC880 Digital";
1078 spec->stream_digital_playback = &alc880_pcm_digital_playback;
1079 spec->stream_digital_capture = &alc880_pcm_digital_capture;
1081 spec->multiout.max_channels = spec->channel_mode[0].channels;
1083 switch (board_config) {
1084 case ALC880_W810:
1085 spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
1086 spec->multiout.dac_nids = alc880_w810_dac_nids;
1087 // No dedicated headphone socket - it's shared with built-in speakers.
1088 break;
1089 default:
1090 spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
1091 spec->multiout.dac_nids = alc880_dac_nids;
1092 spec->multiout.hp_nid = 0x03; /* rear-surround NID */
1093 break;
1096 spec->input_mux = &alc880_capture_source;
1097 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
1098 spec->adc_nids = alc880_adc_nids;
1100 codec->patch_ops = alc_patch_ops;
1102 return 0;
1106 * ALC260 support
1110 * This is just place-holder, so there's something for alc_build_pcms to look
1111 * at when it calculates the maximum number of channels. ALC260 has no mixer
1112 * element which allows changing the channel mode, so the verb list is
1113 * never used.
1115 static struct alc_channel_mode alc260_modes[1] = {
1116 { 2, NULL },
1119 snd_kcontrol_new_t alc260_base_mixer[] = {
1120 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
1121 /* use LINE2 for the output */
1122 /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */
1123 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
1124 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
1125 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
1126 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
1127 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
1128 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
1129 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
1130 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
1131 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
1132 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
1133 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
1134 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
1135 HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1136 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
1137 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
1138 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
1139 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
1141 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1142 .name = "Capture Source",
1143 .info = alc_mux_enum_info,
1144 .get = alc_mux_enum_get,
1145 .put = alc_mux_enum_put,
1147 { } /* end */
1150 static struct hda_verb alc260_init_verbs[] = {
1151 /* Line In pin widget for input */
1152 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1153 /* CD pin widget for input */
1154 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1155 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1156 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1157 /* Mic2 (front panel) pin widget for input and vref at 80% */
1158 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1159 /* LINE-2 is used for line-out in rear */
1160 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1161 /* select line-out */
1162 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1163 /* LINE-OUT pin */
1164 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1165 /* enable HP */
1166 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1167 /* enable Mono */
1168 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1169 /* unmute amp left and right */
1170 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1171 /* set connection select to line in (default select for this ADC) */
1172 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
1173 /* unmute Line-Out mixer amp left and right (volume = 0) */
1174 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1175 /* mute pin widget amp left and right (no gain on this amp) */
1176 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1177 /* unmute HP mixer amp left and right (volume = 0) */
1178 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1179 /* mute pin widget amp left and right (no gain on this amp) */
1180 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1181 /* unmute Mono mixer amp left and right (volume = 0) */
1182 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1183 /* mute pin widget amp left and right (no gain on this amp) */
1184 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1185 /* mute LINE-2 out */
1186 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1187 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
1188 /* unmute CD */
1189 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
1190 /* unmute Line In */
1191 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
1192 /* unmute Mic */
1193 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1194 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
1195 /* Unmute Front out path */
1196 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1197 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1198 /* Unmute Headphone out path */
1199 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1200 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1201 /* Unmute Mono out path */
1202 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1203 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1207 static struct hda_pcm_stream alc260_pcm_analog_playback = {
1208 .substreams = 1,
1209 .channels_min = 2,
1210 .channels_max = 2,
1211 .nid = 0x2,
1214 static struct hda_pcm_stream alc260_pcm_analog_capture = {
1215 .substreams = 1,
1216 .channels_min = 2,
1217 .channels_max = 2,
1218 .nid = 0x4,
1221 static int patch_alc260(struct hda_codec *codec)
1223 struct alc_spec *spec;
1225 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1226 if (spec == NULL)
1227 return -ENOMEM;
1229 codec->spec = spec;
1231 spec->mixers[spec->num_mixers] = alc260_base_mixer;
1232 spec->num_mixers++;
1234 spec->init_verbs = alc260_init_verbs;
1235 spec->channel_mode = alc260_modes;
1236 spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
1238 spec->stream_name_analog = "ALC260 Analog";
1239 spec->stream_analog_playback = &alc260_pcm_analog_playback;
1240 spec->stream_analog_capture = &alc260_pcm_analog_capture;
1242 spec->multiout.max_channels = spec->channel_mode[0].channels;
1243 spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
1244 spec->multiout.dac_nids = alc260_dac_nids;
1246 spec->input_mux = &alc260_capture_source;
1247 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
1248 spec->adc_nids = alc260_adc_nids;
1250 codec->patch_ops = alc_patch_ops;
1252 return 0;
1256 * ALC882 support
1258 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
1259 * configuration. Each pin widget can choose any input DACs and a mixer.
1260 * Each ADC is connected from a mixer of all inputs. This makes possible
1261 * 6-channel independent captures.
1263 * In addition, an independent DAC for the multi-playback (not used in this
1264 * driver yet).
1267 static struct alc_channel_mode alc882_ch_modes[1] = {
1268 { 8, NULL }
1271 static hda_nid_t alc882_dac_nids[4] = {
1272 /* front, rear, clfe, rear_surr */
1273 0x02, 0x03, 0x04, 0x05
1276 static hda_nid_t alc882_adc_nids[3] = {
1277 /* ADC0-2 */
1278 0x07, 0x08, 0x09,
1281 /* input MUX */
1282 /* FIXME: should be a matrix-type input source selection */
1284 static struct hda_input_mux alc882_capture_source = {
1285 .num_items = 4,
1286 .items = {
1287 { "Mic", 0x0 },
1288 { "Front Mic", 0x1 },
1289 { "Line", 0x2 },
1290 { "CD", 0x4 },
1294 #define alc882_mux_enum_info alc_mux_enum_info
1295 #define alc882_mux_enum_get alc_mux_enum_get
1297 static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1299 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1300 struct alc_spec *spec = codec->spec;
1301 const struct hda_input_mux *imux = spec->input_mux;
1302 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1303 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
1304 hda_nid_t nid = capture_mixers[adc_idx];
1305 unsigned int *cur_val = &spec->cur_mux[adc_idx];
1306 unsigned int i, idx;
1308 idx = ucontrol->value.enumerated.item[0];
1309 if (idx >= imux->num_items)
1310 idx = imux->num_items - 1;
1311 if (*cur_val == idx && ! codec->in_resume)
1312 return 0;
1313 for (i = 0; i < imux->num_items; i++) {
1314 unsigned int v = (i == idx) ? 0x7000 : 0x7080;
1315 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1316 v | (imux->items[i].index << 8));
1318 *cur_val = idx;
1319 return 1;
1322 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
1323 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
1325 static snd_kcontrol_new_t alc882_base_mixer[] = {
1326 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1327 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
1328 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1329 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
1330 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1331 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1332 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
1333 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
1334 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1335 HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT),
1336 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1337 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1338 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1339 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1340 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1341 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1342 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1343 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1344 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1345 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1346 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1347 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
1348 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
1349 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
1350 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
1351 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
1352 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
1354 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1355 /* .name = "Capture Source", */
1356 .name = "Input Source",
1357 .count = 3,
1358 .info = alc882_mux_enum_info,
1359 .get = alc882_mux_enum_get,
1360 .put = alc882_mux_enum_put,
1362 { } /* end */
1365 static struct hda_verb alc882_init_verbs[] = {
1366 /* Front mixer: unmute input/output amp left and right (volume = 0) */
1367 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1368 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1369 /* Rear mixer */
1370 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1371 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1372 /* CLFE mixer */
1373 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1374 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1375 /* Side mixer */
1376 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1377 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1379 /* Front Pin: to output mode */
1380 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1381 /* Front Pin: mute amp left and right (no volume) */
1382 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1383 /* select Front mixer (0x0c, index 0) */
1384 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1385 /* Rear Pin */
1386 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1387 /* Rear Pin: mute amp left and right (no volume) */
1388 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1389 /* select Rear mixer (0x0d, index 1) */
1390 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
1391 /* CLFE Pin */
1392 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1393 /* CLFE Pin: mute amp left and right (no volume) */
1394 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1395 /* select CLFE mixer (0x0e, index 2) */
1396 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
1397 /* Side Pin */
1398 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1399 /* Side Pin: mute amp left and right (no volume) */
1400 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1401 /* select Side mixer (0x0f, index 3) */
1402 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1403 /* Headphone Pin */
1404 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1405 /* Headphone Pin: mute amp left and right (no volume) */
1406 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1407 /* select Front mixer (0x0c, index 0) */
1408 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1409 /* Mic (rear) pin widget for input and vref at 80% */
1410 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1411 /* Front Mic pin widget for input and vref at 80% */
1412 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1413 /* Line In pin widget for input */
1414 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1415 /* CD pin widget for input */
1416 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1418 /* FIXME: use matrix-type input source selection */
1419 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
1420 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
1421 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1422 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
1423 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
1424 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
1425 /* Input mixer2 */
1426 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1427 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
1428 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
1429 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
1430 /* Input mixer3 */
1431 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1432 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
1433 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
1434 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
1435 /* ADC1: unmute amp left and right */
1436 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1437 /* ADC2: unmute amp left and right */
1438 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1439 /* ADC3: unmute amp left and right */
1440 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1442 /* Unmute front loopback */
1443 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1444 /* Unmute rear loopback */
1445 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1446 /* Mute CLFE loopback */
1447 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
1448 /* Unmute side loopback */
1449 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1454 static int patch_alc882(struct hda_codec *codec)
1456 struct alc_spec *spec;
1458 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1459 if (spec == NULL)
1460 return -ENOMEM;
1462 codec->spec = spec;
1464 spec->mixers[spec->num_mixers] = alc882_base_mixer;
1465 spec->num_mixers++;
1467 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
1468 spec->dig_in_nid = ALC880_DIGIN_NID;
1469 spec->front_panel = 1;
1470 spec->init_verbs = alc882_init_verbs;
1471 spec->channel_mode = alc882_ch_modes;
1472 spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
1474 spec->stream_name_analog = "ALC882 Analog";
1475 spec->stream_analog_playback = &alc880_pcm_analog_playback;
1476 spec->stream_analog_capture = &alc880_pcm_analog_capture;
1478 spec->stream_name_digital = "ALC882 Digital";
1479 spec->stream_digital_playback = &alc880_pcm_digital_playback;
1480 spec->stream_digital_capture = &alc880_pcm_digital_capture;
1482 spec->multiout.max_channels = spec->channel_mode[0].channels;
1483 spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids);
1484 spec->multiout.dac_nids = alc882_dac_nids;
1486 spec->input_mux = &alc882_capture_source;
1487 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
1488 spec->adc_nids = alc882_adc_nids;
1490 codec->patch_ops = alc_patch_ops;
1492 return 0;
1496 * patch entries
1498 struct hda_codec_preset snd_hda_preset_realtek[] = {
1499 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
1500 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
1501 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
1502 {} /* terminator */