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 */
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
;
62 struct hda_multi_out multiout
;
65 unsigned int num_adc_nids
;
70 const struct hda_input_mux
*input_mux
;
71 unsigned int cur_mux
[3];
74 const struct alc_channel_mode
*channel_mode
;
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 */
93 static hda_nid_t alc880_adc_nids
[3] = {
98 #define ALC880_DIGOUT_NID 0x06
99 #define ALC880_DIGIN_NID 0x0a
101 static hda_nid_t alc260_dac_nids
[1] = {
106 static hda_nid_t alc260_adc_nids
[2] = {
111 #define ALC260_DIGOUT_NID 0x03
112 #define ALC260_DIGIN_NID 0x06
114 static struct hda_input_mux alc880_capture_source
= {
118 { "Front Mic", 0x3 },
124 static struct hda_input_mux alc260_capture_source
= {
128 { "Front Mic", 0x1 },
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
];
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
{
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 },
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 },
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 },
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 },
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:
264 * Center/LFE (DAC 04)
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] = {
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
;
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
);
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;
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
;
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
&&
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
);
341 * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
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",
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
,
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",
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
,
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",
471 .info
= alc_mux_enum_info
,
472 .get
= alc_mux_enum_get
,
473 .put
= alc_mux_enum_put
,
480 static int alc_build_controls(struct hda_codec
*codec
)
482 struct alc_spec
*spec
= codec
->spec
;
486 for (i
= 0; i
< spec
->num_mixers
; i
++) {
487 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
492 if (spec
->multiout
.dig_out_nid
) {
493 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->multiout
.dig_out_nid
);
497 if (spec
->dig_in_nid
) {
498 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
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
552 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
554 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x04 << 8))},
556 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x02 << 8))},
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
564 * the mixers on the output path has 2 inputs, one from the DAC and one
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*/
630 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x04 << 8))},
632 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x02 << 8))},
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
640 * the mixers on the output path has 2 inputs, one from the DAC and
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
);
733 static int alc_resume(struct hda_codec
*codec
)
735 struct alc_spec
*spec
= codec
->spec
;
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
);
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
,
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
,
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
);
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
);
803 static int alc880_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
804 struct hda_codec
*codec
,
805 unsigned int stream_tag
,
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
);
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);
829 static struct hda_pcm_stream alc880_pcm_analog_playback
= {
833 .nid
= 0x02, /* NID to query formats and rates */
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
= {
845 .nid
= 0x07, /* NID to query formats and rates */
847 .prepare
= alc880_capture_pcm_prepare
,
848 .cleanup
= alc880_capture_pcm_cleanup
852 static struct hda_pcm_stream alc880_pcm_digital_playback
= {
856 /* NID is set in alc_build_pcms */
858 .open
= alc880_dig_playback_pcm_open
,
859 .close
= alc880_dig_playback_pcm_close
863 static struct hda_pcm_stream alc880_pcm_digital_capture
= {
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
;
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
) {
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
;
907 static void alc_free(struct hda_codec
*codec
)
914 static struct hda_codec_ops alc_patch_ops
= {
915 .build_controls
= alc_build_controls
,
916 .build_pcms
= alc_build_pcms
,
920 .resume
= alc_resume
,
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
;
1004 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
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
) {
1018 spec
->mixers
[spec
->num_mixers
] = alc880_w810_base_mixer
;
1022 case ALC880_5ST_DIG
:
1023 spec
->mixers
[spec
->num_mixers
] = alc880_five_stack_mixer
;
1027 spec
->mixers
[spec
->num_mixers
] = alc880_base_mixer
;
1032 switch (board_config
) {
1033 case ALC880_3ST_DIG
:
1034 case ALC880_5ST_DIG
:
1036 spec
->multiout
.dig_out_nid
= ALC880_DIGOUT_NID
;
1042 switch (board_config
) {
1044 case ALC880_3ST_DIG
:
1046 case ALC880_5ST_DIG
:
1048 spec
->front_panel
= 1;
1054 switch (board_config
) {
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
);
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
);
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
);
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
) {
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.
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 */
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
;
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
1115 static struct alc_channel_mode alc260_modes
[1] = {
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
,
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},
1164 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1166 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
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 */
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))},
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
= {
1214 static struct hda_pcm_stream alc260_pcm_analog_capture
= {
1221 static int patch_alc260(struct hda_codec
*codec
)
1223 struct alc_spec
*spec
;
1225 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1231 spec
->mixers
[spec
->num_mixers
] = alc260_base_mixer
;
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
;
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
1267 static struct alc_channel_mode alc882_ch_modes
[1] = {
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] = {
1282 /* FIXME: should be a matrix-type input source selection */
1284 static struct hda_input_mux alc882_capture_source
= {
1288 { "Front Mic", 0x1 },
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
)
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));
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",
1358 .info
= alc882_mux_enum_info
,
1359 .get
= alc882_mux_enum_get
,
1360 .put
= alc882_mux_enum_put
,
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))},
1370 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1371 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
1373 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1374 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
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},
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},
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},
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},
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))},
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))},
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
);
1464 spec
->mixers
[spec
->num_mixers
] = alc882_base_mixer
;
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
;
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
},