2 * Universal Interface for Intel High Definition Audio Codec
4 * HD audio interface patch for ALC 260/880/882 codecs
6 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
8 * Takashi Iwai <tiwai@suse.de>
9 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <sound/driver.h>
27 #include <linux/init.h>
28 #include <linux/delay.h>
29 #include <linux/slab.h>
30 #include <linux/pci.h>
31 #include <sound/core.h>
32 #include "hda_codec.h"
33 #include "hda_local.h"
36 /* ALC880 board config type */
54 #ifdef CONFIG_SND_DEBUG
58 ALC880_MODEL_LAST
/* last tag */
68 #ifdef CONFIG_SND_DEBUG
72 ALC260_MODEL_LAST
/* last tag */
80 ALC262_MODEL_LAST
/* last tag */
101 #define GPIO_MASK 0x03
104 /* codec parameterization */
105 struct snd_kcontrol_new
*mixers
[5]; /* mixer arrays */
106 unsigned int num_mixers
;
108 const struct hda_verb
*init_verbs
[5]; /* initialization verbs
109 * don't forget NULL termination!
111 unsigned int num_init_verbs
;
113 char *stream_name_analog
; /* analog PCM stream */
114 struct hda_pcm_stream
*stream_analog_playback
;
115 struct hda_pcm_stream
*stream_analog_capture
;
117 char *stream_name_digital
; /* digital PCM stream */
118 struct hda_pcm_stream
*stream_digital_playback
;
119 struct hda_pcm_stream
*stream_digital_capture
;
122 struct hda_multi_out multiout
; /* playback set-up
123 * max_channels, dacs must be set
124 * dig_out_nid and hp_nid are optional
128 unsigned int num_adc_nids
;
130 hda_nid_t dig_in_nid
; /* digital-in NID; optional */
133 const struct hda_input_mux
*input_mux
;
134 unsigned int cur_mux
[3];
137 const struct hda_channel_mode
*channel_mode
;
138 int num_channel_mode
;
140 /* PCM information */
141 struct hda_pcm pcm_rec
[3]; /* used in alc_build_pcms() */
143 /* dynamic controls, init_verbs and input_mux */
144 struct auto_pin_cfg autocfg
;
145 unsigned int num_kctl_alloc
, num_kctl_used
;
146 struct snd_kcontrol_new
*kctl_alloc
;
147 struct hda_input_mux private_imux
;
148 hda_nid_t private_dac_nids
[5];
150 /* for pin sensing */
151 unsigned int sense_updated
: 1;
152 unsigned int jack_present
: 1;
156 * configuration template - to be copied to the spec instance
158 struct alc_config_preset
{
159 struct snd_kcontrol_new
*mixers
[5]; /* should be identical size with spec */
160 const struct hda_verb
*init_verbs
[5];
161 unsigned int num_dacs
;
163 hda_nid_t dig_out_nid
; /* optional */
164 hda_nid_t hp_nid
; /* optional */
165 unsigned int num_adc_nids
;
167 hda_nid_t dig_in_nid
;
168 unsigned int num_channel_mode
;
169 const struct hda_channel_mode
*channel_mode
;
170 const struct hda_input_mux
*input_mux
;
177 static int alc_mux_enum_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
179 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
180 struct alc_spec
*spec
= codec
->spec
;
181 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
184 static int alc_mux_enum_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
186 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
187 struct alc_spec
*spec
= codec
->spec
;
188 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
190 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
194 static int alc_mux_enum_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
196 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
197 struct alc_spec
*spec
= codec
->spec
;
198 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
199 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
200 spec
->adc_nids
[adc_idx
], &spec
->cur_mux
[adc_idx
]);
205 * channel mode setting
207 static int alc_ch_mode_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
209 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
210 struct alc_spec
*spec
= codec
->spec
;
211 return snd_hda_ch_mode_info(codec
, uinfo
, spec
->channel_mode
,
212 spec
->num_channel_mode
);
215 static int alc_ch_mode_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
217 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
218 struct alc_spec
*spec
= codec
->spec
;
219 return snd_hda_ch_mode_get(codec
, ucontrol
, spec
->channel_mode
,
220 spec
->num_channel_mode
, spec
->multiout
.max_channels
);
223 static int alc_ch_mode_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
225 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
226 struct alc_spec
*spec
= codec
->spec
;
227 return snd_hda_ch_mode_put(codec
, ucontrol
, spec
->channel_mode
,
228 spec
->num_channel_mode
, &spec
->multiout
.max_channels
);
232 * Control the mode of pin widget settings via the mixer. "pc" is used
233 * instead of "%" to avoid consequences of accidently treating the % as
234 * being part of a format specifier. Maximum allowed length of a value is
235 * 63 characters plus NULL terminator.
237 * Note: some retasking pin complexes seem to ignore requests for input
238 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
239 * are requested. Therefore order this list so that this behaviour will not
240 * cause problems when mixer clients move through the enum sequentially.
241 * NIDs 0x0f and 0x10 have been observed to have this behaviour.
243 static char *alc_pin_mode_names
[] = {
244 "Mic 50pc bias", "Mic 80pc bias",
245 "Line in", "Line out", "Headphone out",
247 static unsigned char alc_pin_mode_values
[] = {
248 PIN_VREF50
, PIN_VREF80
, PIN_IN
, PIN_OUT
, PIN_HP
,
250 /* The control can present all 5 options, or it can limit the options based
251 * in the pin being assumed to be exclusively an input or an output pin.
253 #define ALC_PIN_DIR_IN 0x00
254 #define ALC_PIN_DIR_OUT 0x01
255 #define ALC_PIN_DIR_INOUT 0x02
257 /* Info about the pin modes supported by the three different pin directions.
258 * For each direction the minimum and maximum values are given.
260 static signed char alc_pin_mode_dir_info
[3][2] = {
261 { 0, 2 }, /* ALC_PIN_DIR_IN */
262 { 3, 4 }, /* ALC_PIN_DIR_OUT */
263 { 0, 4 }, /* ALC_PIN_DIR_INOUT */
265 #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
266 #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
267 #define alc_pin_mode_n_items(_dir) \
268 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
270 static int alc_pin_mode_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
272 unsigned int item_num
= uinfo
->value
.enumerated
.item
;
273 unsigned char dir
= (kcontrol
->private_value
>> 16) & 0xff;
275 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
277 uinfo
->value
.enumerated
.items
= alc_pin_mode_n_items(dir
);
279 if (item_num
<alc_pin_mode_min(dir
) || item_num
>alc_pin_mode_max(dir
))
280 item_num
= alc_pin_mode_min(dir
);
281 strcpy(uinfo
->value
.enumerated
.name
, alc_pin_mode_names
[item_num
]);
285 static int alc_pin_mode_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
288 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
289 hda_nid_t nid
= kcontrol
->private_value
& 0xffff;
290 unsigned char dir
= (kcontrol
->private_value
>> 16) & 0xff;
291 long *valp
= ucontrol
->value
.integer
.value
;
292 unsigned int pinctl
= snd_hda_codec_read(codec
,nid
,0,AC_VERB_GET_PIN_WIDGET_CONTROL
,0x00);
294 /* Find enumerated value for current pinctl setting */
295 i
= alc_pin_mode_min(dir
);
296 while (alc_pin_mode_values
[i
]!=pinctl
&& i
<=alc_pin_mode_max(dir
))
298 *valp
= i
<=alc_pin_mode_max(dir
)?i
:alc_pin_mode_min(dir
);
302 static int alc_pin_mode_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
305 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
306 hda_nid_t nid
= kcontrol
->private_value
& 0xffff;
307 unsigned char dir
= (kcontrol
->private_value
>> 16) & 0xff;
308 long val
= *ucontrol
->value
.integer
.value
;
309 unsigned int pinctl
= snd_hda_codec_read(codec
,nid
,0,AC_VERB_GET_PIN_WIDGET_CONTROL
,0x00);
311 if (val
<alc_pin_mode_min(dir
) || val
>alc_pin_mode_max(dir
))
312 val
= alc_pin_mode_min(dir
);
314 change
= pinctl
!= alc_pin_mode_values
[val
];
316 /* Set pin mode to that requested */
317 snd_hda_codec_write(codec
,nid
,0,AC_VERB_SET_PIN_WIDGET_CONTROL
,
318 alc_pin_mode_values
[val
]);
320 /* Also enable the retasking pin's input/output as required
321 * for the requested pin mode. Enum values of 2 or less are
324 * Dynamically switching the input/output buffers probably
325 * reduces noise slightly, particularly on input. However,
326 * havingboth input and output buffers enabled
327 * simultaneously doesn't seem to be problematic.
330 snd_hda_codec_write(codec
,nid
,0,AC_VERB_SET_AMP_GAIN_MUTE
,
332 snd_hda_codec_write(codec
,nid
,0,AC_VERB_SET_AMP_GAIN_MUTE
,
335 snd_hda_codec_write(codec
,nid
,0,AC_VERB_SET_AMP_GAIN_MUTE
,
337 snd_hda_codec_write(codec
,nid
,0,AC_VERB_SET_AMP_GAIN_MUTE
,
344 #define ALC_PIN_MODE(xname, nid, dir) \
345 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
346 .info = alc_pin_mode_info, \
347 .get = alc_pin_mode_get, \
348 .put = alc_pin_mode_put, \
349 .private_value = nid | (dir<<16) }
351 /* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged
352 * together using a mask with more than one bit set. This control is
353 * currently used only by the ALC260 test model. At this stage they are not
354 * needed for any "production" models.
356 #ifdef CONFIG_SND_DEBUG
357 static int alc_gpio_data_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
359 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
361 uinfo
->value
.integer
.min
= 0;
362 uinfo
->value
.integer
.max
= 1;
365 static int alc_gpio_data_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
367 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
368 hda_nid_t nid
= kcontrol
->private_value
& 0xffff;
369 unsigned char mask
= (kcontrol
->private_value
>> 16) & 0xff;
370 long *valp
= ucontrol
->value
.integer
.value
;
371 unsigned int val
= snd_hda_codec_read(codec
,nid
,0,AC_VERB_GET_GPIO_DATA
,0x00);
373 *valp
= (val
& mask
) != 0;
376 static int alc_gpio_data_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
379 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
380 hda_nid_t nid
= kcontrol
->private_value
& 0xffff;
381 unsigned char mask
= (kcontrol
->private_value
>> 16) & 0xff;
382 long val
= *ucontrol
->value
.integer
.value
;
383 unsigned int gpio_data
= snd_hda_codec_read(codec
,nid
,0,AC_VERB_GET_GPIO_DATA
,0x00);
385 /* Set/unset the masked GPIO bit(s) as needed */
386 change
= (val
==0?0:mask
) != (gpio_data
& mask
);
391 snd_hda_codec_write(codec
,nid
,0,AC_VERB_SET_GPIO_DATA
,gpio_data
);
395 #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
396 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
397 .info = alc_gpio_data_info, \
398 .get = alc_gpio_data_get, \
399 .put = alc_gpio_data_put, \
400 .private_value = nid | (mask<<16) }
401 #endif /* CONFIG_SND_DEBUG */
403 /* A switch control to allow the enabling of the digital IO pins on the
404 * ALC260. This is incredibly simplistic; the intention of this control is
405 * to provide something in the test model allowing digital outputs to be
406 * identified if present. If models are found which can utilise these
407 * outputs a more complete mixer control can be devised for those models if
410 #ifdef CONFIG_SND_DEBUG
411 static int alc_spdif_ctrl_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
413 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
415 uinfo
->value
.integer
.min
= 0;
416 uinfo
->value
.integer
.max
= 1;
419 static int alc_spdif_ctrl_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
421 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
422 hda_nid_t nid
= kcontrol
->private_value
& 0xffff;
423 unsigned char mask
= (kcontrol
->private_value
>> 16) & 0xff;
424 long *valp
= ucontrol
->value
.integer
.value
;
425 unsigned int val
= snd_hda_codec_read(codec
,nid
,0,AC_VERB_GET_DIGI_CONVERT
,0x00);
427 *valp
= (val
& mask
) != 0;
430 static int alc_spdif_ctrl_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
433 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
434 hda_nid_t nid
= kcontrol
->private_value
& 0xffff;
435 unsigned char mask
= (kcontrol
->private_value
>> 16) & 0xff;
436 long val
= *ucontrol
->value
.integer
.value
;
437 unsigned int ctrl_data
= snd_hda_codec_read(codec
,nid
,0,AC_VERB_GET_DIGI_CONVERT
,0x00);
439 /* Set/unset the masked control bit(s) as needed */
440 change
= (val
==0?0:mask
) != (ctrl_data
& mask
);
445 snd_hda_codec_write(codec
,nid
,0,AC_VERB_SET_DIGI_CONVERT_1
,ctrl_data
);
449 #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
450 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
451 .info = alc_spdif_ctrl_info, \
452 .get = alc_spdif_ctrl_get, \
453 .put = alc_spdif_ctrl_put, \
454 .private_value = nid | (mask<<16) }
455 #endif /* CONFIG_SND_DEBUG */
458 * set up from the preset table
460 static void setup_preset(struct alc_spec
*spec
, const struct alc_config_preset
*preset
)
464 for (i
= 0; i
< ARRAY_SIZE(preset
->mixers
) && preset
->mixers
[i
]; i
++)
465 spec
->mixers
[spec
->num_mixers
++] = preset
->mixers
[i
];
466 for (i
= 0; i
< ARRAY_SIZE(preset
->init_verbs
) && preset
->init_verbs
[i
]; i
++)
467 spec
->init_verbs
[spec
->num_init_verbs
++] = preset
->init_verbs
[i
];
469 spec
->channel_mode
= preset
->channel_mode
;
470 spec
->num_channel_mode
= preset
->num_channel_mode
;
472 spec
->multiout
.max_channels
= spec
->channel_mode
[0].channels
;
474 spec
->multiout
.num_dacs
= preset
->num_dacs
;
475 spec
->multiout
.dac_nids
= preset
->dac_nids
;
476 spec
->multiout
.dig_out_nid
= preset
->dig_out_nid
;
477 spec
->multiout
.hp_nid
= preset
->hp_nid
;
479 spec
->input_mux
= preset
->input_mux
;
481 spec
->num_adc_nids
= preset
->num_adc_nids
;
482 spec
->adc_nids
= preset
->adc_nids
;
483 spec
->dig_in_nid
= preset
->dig_in_nid
;
487 * ALC880 3-stack model
489 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
490 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
494 static hda_nid_t alc880_dac_nids
[4] = {
495 /* front, rear, clfe, rear_surr */
496 0x02, 0x05, 0x04, 0x03
499 static hda_nid_t alc880_adc_nids
[3] = {
504 /* The datasheet says the node 0x07 is connected from inputs,
505 * but it shows zero connection in the real implementation on some devices.
506 * Note: this is a 915GAV bug, fixed on 915GLV
508 static hda_nid_t alc880_adc_nids_alt
[2] = {
513 #define ALC880_DIGOUT_NID 0x06
514 #define ALC880_DIGIN_NID 0x0a
516 static struct hda_input_mux alc880_capture_source
= {
520 { "Front Mic", 0x3 },
526 /* channel source setting (2/6 channel selection for 3-stack) */
528 static struct hda_verb alc880_threestack_ch2_init
[] = {
529 /* set line-in to input, mute it */
530 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
531 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
532 /* set mic-in to input vref 80%, mute it */
533 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
534 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
539 static struct hda_verb alc880_threestack_ch6_init
[] = {
540 /* set line-in to output, unmute it */
541 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
542 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
543 /* set mic-in to output, unmute it */
544 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
545 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
549 static struct hda_channel_mode alc880_threestack_modes
[2] = {
550 { 2, alc880_threestack_ch2_init
},
551 { 6, alc880_threestack_ch6_init
},
554 static struct snd_kcontrol_new alc880_three_stack_mixer
[] = {
555 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
556 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
557 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
558 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT
),
559 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
560 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
561 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
562 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
563 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
564 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
565 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
566 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
567 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
568 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
569 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT
),
570 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT
),
571 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
572 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
573 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT
),
575 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
576 .name
= "Channel Mode",
577 .info
= alc_ch_mode_info
,
578 .get
= alc_ch_mode_get
,
579 .put
= alc_ch_mode_put
,
584 /* capture mixer elements */
585 static struct snd_kcontrol_new alc880_capture_mixer
[] = {
586 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
587 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
588 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
589 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
590 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT
),
591 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT
),
593 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
594 /* The multiple "Capture Source" controls confuse alsamixer
595 * So call somewhat different..
596 * FIXME: the controls appear in the "playback" view!
598 /* .name = "Capture Source", */
599 .name
= "Input Source",
601 .info
= alc_mux_enum_info
,
602 .get
= alc_mux_enum_get
,
603 .put
= alc_mux_enum_put
,
608 /* capture mixer elements (in case NID 0x07 not available) */
609 static struct snd_kcontrol_new alc880_capture_alt_mixer
[] = {
610 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
611 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
612 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT
),
613 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT
),
615 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
616 /* The multiple "Capture Source" controls confuse alsamixer
617 * So call somewhat different..
618 * FIXME: the controls appear in the "playback" view!
620 /* .name = "Capture Source", */
621 .name
= "Input Source",
623 .info
= alc_mux_enum_info
,
624 .get
= alc_mux_enum_get
,
625 .put
= alc_mux_enum_put
,
633 * ALC880 5-stack model
635 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
636 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
637 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
640 /* additional mixers to alc880_three_stack_mixer */
641 static struct snd_kcontrol_new alc880_five_stack_mixer
[] = {
642 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
643 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT
),
647 /* channel source setting (6/8 channel selection for 5-stack) */
649 static struct hda_verb alc880_fivestack_ch6_init
[] = {
650 /* set line-in to input, mute it */
651 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
652 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
657 static struct hda_verb alc880_fivestack_ch8_init
[] = {
658 /* set line-in to output, unmute it */
659 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
660 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
664 static struct hda_channel_mode alc880_fivestack_modes
[2] = {
665 { 6, alc880_fivestack_ch6_init
},
666 { 8, alc880_fivestack_ch8_init
},
671 * ALC880 6-stack model
673 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
674 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
675 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
678 static hda_nid_t alc880_6st_dac_nids
[4] = {
679 /* front, rear, clfe, rear_surr */
680 0x02, 0x03, 0x04, 0x05
683 static struct hda_input_mux alc880_6stack_capture_source
= {
687 { "Front Mic", 0x1 },
693 /* fixed 8-channels */
694 static struct hda_channel_mode alc880_sixstack_modes
[1] = {
698 static struct snd_kcontrol_new alc880_six_stack_mixer
[] = {
699 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
700 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
701 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
702 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
703 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
704 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
705 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
706 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
707 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
708 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT
),
709 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
710 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
711 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
712 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
713 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
714 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
715 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT
),
716 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT
),
717 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
718 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
720 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
721 .name
= "Channel Mode",
722 .info
= alc_ch_mode_info
,
723 .get
= alc_ch_mode_get
,
724 .put
= alc_ch_mode_put
,
733 * W810 has rear IO for:
736 * Center/LFE (DAC 04)
739 * The system also has a pair of internal speakers, and a headphone jack.
740 * These are both connected to Line2 on the codec, hence to DAC 02.
742 * There is a variable resistor to control the speaker or headphone
743 * volume. This is a hardware-only device without a software API.
745 * Plugging headphones in will disable the internal speakers. This is
746 * implemented in hardware, not via the driver using jack sense. In
747 * a similar fashion, plugging into the rear socket marked "front" will
748 * disable both the speakers and headphones.
750 * For input, there's a microphone jack, and an "audio in" jack.
751 * These may not do anything useful with this driver yet, because I
752 * haven't setup any initialization verbs for these yet...
755 static hda_nid_t alc880_w810_dac_nids
[3] = {
756 /* front, rear/surround, clfe */
760 /* fixed 6 channels */
761 static struct hda_channel_mode alc880_w810_modes
[1] = {
765 /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
766 static struct snd_kcontrol_new alc880_w810_base_mixer
[] = {
767 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
768 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
769 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
770 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
771 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
772 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
773 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
774 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
775 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
783 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
784 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
787 static hda_nid_t alc880_z71v_dac_nids
[1] = {
790 #define ALC880_Z71V_HP_DAC 0x03
792 /* fixed 2 channels */
793 static struct hda_channel_mode alc880_2_jack_modes
[1] = {
797 static struct snd_kcontrol_new alc880_z71v_mixer
[] = {
798 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
799 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
800 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
801 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT
),
802 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
803 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
804 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
805 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
814 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
815 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
818 static hda_nid_t alc880_f1734_dac_nids
[1] = {
821 #define ALC880_F1734_HP_DAC 0x02
823 static struct snd_kcontrol_new alc880_f1734_mixer
[] = {
824 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
825 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT
),
826 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
827 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT
),
828 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
829 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
830 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
831 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
840 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
841 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
842 * Mic = 0x18, Line = 0x1a
845 #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
846 #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
848 static struct snd_kcontrol_new alc880_asus_mixer
[] = {
849 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
850 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
851 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
852 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
853 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
854 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
855 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
856 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
857 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
858 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
859 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
860 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
861 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
862 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
864 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
865 .name
= "Channel Mode",
866 .info
= alc_ch_mode_info
,
867 .get
= alc_ch_mode_get
,
868 .put
= alc_ch_mode_put
,
875 * ALC880 ASUS W1V model
877 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
878 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
879 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
882 /* additional mixers to alc880_asus_mixer */
883 static struct snd_kcontrol_new alc880_asus_w1v_mixer
[] = {
884 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT
),
885 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT
),
889 /* additional mixers to alc880_asus_mixer */
890 static struct snd_kcontrol_new alc880_pcbeep_mixer
[] = {
891 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
892 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
897 static struct snd_kcontrol_new alc880_tcl_s700_mixer
[] = {
898 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
899 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
900 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT
),
901 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT
),
902 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT
),
903 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT
),
904 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT
),
905 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
906 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
908 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
909 /* The multiple "Capture Source" controls confuse alsamixer
910 * So call somewhat different..
911 * FIXME: the controls appear in the "playback" view!
913 /* .name = "Capture Source", */
914 .name
= "Input Source",
916 .info
= alc_mux_enum_info
,
917 .get
= alc_mux_enum_get
,
918 .put
= alc_mux_enum_put
,
924 * build control elements
926 static int alc_build_controls(struct hda_codec
*codec
)
928 struct alc_spec
*spec
= codec
->spec
;
932 for (i
= 0; i
< spec
->num_mixers
; i
++) {
933 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
938 if (spec
->multiout
.dig_out_nid
) {
939 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->multiout
.dig_out_nid
);
943 if (spec
->dig_in_nid
) {
944 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
953 * initialize the codec volumes, etc
957 * generic initialization of ADC, input mixers and output mixers
959 static struct hda_verb alc880_volume_init_verbs
[] = {
961 * Unmute ADC0-2 and set the default input to mic-in
963 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
964 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
965 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
966 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
967 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
968 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
970 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
972 * Note: PASD motherboards uses the Line In 2 as the input for front panel
975 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
976 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
977 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
978 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
979 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
980 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
983 * Set up output mixers (0x0c - 0x0f)
985 /* set vol=0 to output mixers */
986 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
987 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
988 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
989 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
990 /* set up input amps for analog loopback */
991 /* Amp Indices: DAC = 0, mixer = 1 */
992 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
993 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
994 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
995 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
996 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
997 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
998 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
999 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1005 * 3-stack pin configuration:
1006 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
1008 static struct hda_verb alc880_pin_3stack_init_verbs
[] = {
1010 * preset connection lists of input pins
1011 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
1013 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x02}, /* mic/clfe */
1014 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* HP */
1015 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x03}, /* line/surround */
1018 * Set pin mode and muting
1020 /* set front pin widgets 0x14 for output */
1021 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1022 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1023 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1024 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1025 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1026 /* Mic2 (as headphone out) for HP output */
1027 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1028 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1029 /* Line In pin widget for input */
1030 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1031 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1032 /* Line2 (as front mic) pin widget for input and vref at 80% */
1033 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1034 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1035 /* CD pin widget for input */
1036 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1042 * 5-stack pin configuration:
1043 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
1044 * line-in/side = 0x1a, f-mic = 0x1b
1046 static struct hda_verb alc880_pin_5stack_init_verbs
[] = {
1048 * preset connection lists of input pins
1049 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
1051 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* HP */
1052 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* line/side */
1055 * Set pin mode and muting
1057 /* set pin widgets 0x14-0x17 for output */
1058 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1059 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1060 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1061 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1062 /* unmute pins for output (no gain on this amp) */
1063 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1064 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1065 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1066 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1068 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1069 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1070 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1071 /* Mic2 (as headphone out) for HP output */
1072 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1073 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1074 /* Line In pin widget for input */
1075 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1076 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1077 /* Line2 (as front mic) pin widget for input and vref at 80% */
1078 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1079 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1080 /* CD pin widget for input */
1081 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1087 * W810 pin configuration:
1088 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
1090 static struct hda_verb alc880_pin_w810_init_verbs
[] = {
1091 /* hphone/speaker input selector: front DAC */
1092 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x0},
1094 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1095 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1096 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1097 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1098 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1099 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1101 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1102 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1108 * Z71V pin configuration:
1109 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
1111 static struct hda_verb alc880_pin_z71v_init_verbs
[] = {
1112 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1113 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1114 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1115 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1117 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1118 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1119 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1120 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1126 * 6-stack pin configuration:
1127 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
1128 * line = 0x1a, HP = 0x1b
1130 static struct hda_verb alc880_pin_6stack_init_verbs
[] = {
1131 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* HP */
1133 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1134 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1135 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1136 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1137 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1138 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1139 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1140 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1142 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1143 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1144 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1145 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1146 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1147 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1148 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1149 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1150 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1157 * F1734 pin configuration:
1158 * HP = 0x14, speaker-out = 0x15, mic = 0x18
1160 static struct hda_verb alc880_pin_f1734_init_verbs
[] = {
1161 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x02},
1162 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00},
1163 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x01},
1164 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x00},
1166 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1167 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1168 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1169 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1171 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1172 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1173 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1174 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1175 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1176 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1177 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1178 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1179 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1186 * ASUS pin configuration:
1187 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
1189 static struct hda_verb alc880_pin_asus_init_verbs
[] = {
1190 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x02},
1191 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00},
1192 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x01},
1193 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x00},
1195 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1196 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1197 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1198 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1199 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1200 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1201 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1202 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1204 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1205 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1206 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1207 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1208 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1209 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1210 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1211 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1212 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1217 /* Enable GPIO mask and set output */
1218 static struct hda_verb alc880_gpio1_init_verbs
[] = {
1219 {0x01, AC_VERB_SET_GPIO_MASK
, 0x01},
1220 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x01},
1221 {0x01, AC_VERB_SET_GPIO_DATA
, 0x01},
1226 /* Enable GPIO mask and set output */
1227 static struct hda_verb alc880_gpio2_init_verbs
[] = {
1228 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
1229 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
1230 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02},
1235 /* Clevo m520g init */
1236 static struct hda_verb alc880_pin_clevo_init_verbs
[] = {
1237 /* headphone output */
1238 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x01},
1240 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1241 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1243 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1244 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1246 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1247 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1248 /* Mic1 (rear panel) */
1249 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1250 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1251 /* Mic2 (front panel) */
1252 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1253 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1255 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1256 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1257 /* change to EAPD mode */
1258 {0x20, AC_VERB_SET_COEF_INDEX
, 0x07},
1259 {0x20, AC_VERB_SET_PROC_COEF
, 0x3060},
1264 static struct hda_verb alc880_pin_tcl_S700_init_verbs
[] = {
1265 /* Headphone output */
1266 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1268 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1269 {0x1b, AC_VERB_SET_CONNECT_SEL
, 0x00},
1271 /* Line In pin widget for input */
1272 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1273 /* CD pin widget for input */
1274 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1275 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1276 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1278 /* change to EAPD mode */
1279 {0x20, AC_VERB_SET_COEF_INDEX
, 0x07},
1280 {0x20, AC_VERB_SET_PROC_COEF
, 0x3070},
1288 static int alc_init(struct hda_codec
*codec
)
1290 struct alc_spec
*spec
= codec
->spec
;
1293 for (i
= 0; i
< spec
->num_init_verbs
; i
++)
1294 snd_hda_sequence_write(codec
, spec
->init_verbs
[i
]);
1302 static int alc_resume(struct hda_codec
*codec
)
1304 struct alc_spec
*spec
= codec
->spec
;
1308 for (i
= 0; i
< spec
->num_mixers
; i
++)
1309 snd_hda_resume_ctls(codec
, spec
->mixers
[i
]);
1310 if (spec
->multiout
.dig_out_nid
)
1311 snd_hda_resume_spdif_out(codec
);
1312 if (spec
->dig_in_nid
)
1313 snd_hda_resume_spdif_in(codec
);
1320 * Analog playback callbacks
1322 static int alc880_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
1323 struct hda_codec
*codec
,
1324 struct snd_pcm_substream
*substream
)
1326 struct alc_spec
*spec
= codec
->spec
;
1327 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
);
1330 static int alc880_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
1331 struct hda_codec
*codec
,
1332 unsigned int stream_tag
,
1333 unsigned int format
,
1334 struct snd_pcm_substream
*substream
)
1336 struct alc_spec
*spec
= codec
->spec
;
1337 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
, stream_tag
,
1341 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
1342 struct hda_codec
*codec
,
1343 struct snd_pcm_substream
*substream
)
1345 struct alc_spec
*spec
= codec
->spec
;
1346 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
1352 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
1353 struct hda_codec
*codec
,
1354 struct snd_pcm_substream
*substream
)
1356 struct alc_spec
*spec
= codec
->spec
;
1357 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
1360 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
1361 struct hda_codec
*codec
,
1362 struct snd_pcm_substream
*substream
)
1364 struct alc_spec
*spec
= codec
->spec
;
1365 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
1371 static int alc880_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
1372 struct hda_codec
*codec
,
1373 unsigned int stream_tag
,
1374 unsigned int format
,
1375 struct snd_pcm_substream
*substream
)
1377 struct alc_spec
*spec
= codec
->spec
;
1379 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
1380 stream_tag
, 0, format
);
1384 static int alc880_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
1385 struct hda_codec
*codec
,
1386 struct snd_pcm_substream
*substream
)
1388 struct alc_spec
*spec
= codec
->spec
;
1390 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
], 0, 0, 0);
1397 static struct hda_pcm_stream alc880_pcm_analog_playback
= {
1401 /* NID is set in alc_build_pcms */
1403 .open
= alc880_playback_pcm_open
,
1404 .prepare
= alc880_playback_pcm_prepare
,
1405 .cleanup
= alc880_playback_pcm_cleanup
1409 static struct hda_pcm_stream alc880_pcm_analog_capture
= {
1413 /* NID is set in alc_build_pcms */
1415 .prepare
= alc880_capture_pcm_prepare
,
1416 .cleanup
= alc880_capture_pcm_cleanup
1420 static struct hda_pcm_stream alc880_pcm_digital_playback
= {
1424 /* NID is set in alc_build_pcms */
1426 .open
= alc880_dig_playback_pcm_open
,
1427 .close
= alc880_dig_playback_pcm_close
1431 static struct hda_pcm_stream alc880_pcm_digital_capture
= {
1435 /* NID is set in alc_build_pcms */
1438 /* Used by alc_build_pcms to flag that a PCM has no playback stream */
1439 static struct hda_pcm_stream alc_pcm_null_playback
= {
1445 static int alc_build_pcms(struct hda_codec
*codec
)
1447 struct alc_spec
*spec
= codec
->spec
;
1448 struct hda_pcm
*info
= spec
->pcm_rec
;
1451 codec
->num_pcms
= 1;
1452 codec
->pcm_info
= info
;
1454 info
->name
= spec
->stream_name_analog
;
1455 if (spec
->stream_analog_playback
) {
1456 snd_assert(spec
->multiout
.dac_nids
, return -EINVAL
);
1457 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_analog_playback
);
1458 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
1460 if (spec
->stream_analog_capture
) {
1461 snd_assert(spec
->adc_nids
, return -EINVAL
);
1462 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_analog_capture
);
1463 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
1466 if (spec
->channel_mode
) {
1467 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
= 0;
1468 for (i
= 0; i
< spec
->num_channel_mode
; i
++) {
1469 if (spec
->channel_mode
[i
].channels
> info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
) {
1470 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
= spec
->channel_mode
[i
].channels
;
1475 /* If the use of more than one ADC is requested for the current
1476 * model, configure a second analog capture-only PCM.
1478 if (spec
->num_adc_nids
> 1) {
1481 info
->name
= spec
->stream_name_analog
;
1482 /* No playback stream for second PCM */
1483 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = alc_pcm_null_playback
;
1484 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= 0;
1485 if (spec
->stream_analog_capture
) {
1486 snd_assert(spec
->adc_nids
, return -EINVAL
);
1487 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_analog_capture
);
1488 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[1];
1492 if (spec
->multiout
.dig_out_nid
|| spec
->dig_in_nid
) {
1495 info
->name
= spec
->stream_name_digital
;
1496 if (spec
->multiout
.dig_out_nid
&&
1497 spec
->stream_digital_playback
) {
1498 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_digital_playback
);
1499 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dig_out_nid
;
1501 if (spec
->dig_in_nid
&&
1502 spec
->stream_digital_capture
) {
1503 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_digital_capture
);
1504 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in_nid
;
1511 static void alc_free(struct hda_codec
*codec
)
1513 struct alc_spec
*spec
= codec
->spec
;
1519 if (spec
->kctl_alloc
) {
1520 for (i
= 0; i
< spec
->num_kctl_used
; i
++)
1521 kfree(spec
->kctl_alloc
[i
].name
);
1522 kfree(spec
->kctl_alloc
);
1529 static struct hda_codec_ops alc_patch_ops
= {
1530 .build_controls
= alc_build_controls
,
1531 .build_pcms
= alc_build_pcms
,
1535 .resume
= alc_resume
,
1541 * Test configuration for debugging
1543 * Almost all inputs/outputs are enabled. I/O pins can be configured via
1546 #ifdef CONFIG_SND_DEBUG
1547 static hda_nid_t alc880_test_dac_nids
[4] = {
1548 0x02, 0x03, 0x04, 0x05
1551 static struct hda_input_mux alc880_test_capture_source
= {
1562 static struct hda_channel_mode alc880_test_modes
[4] = {
1569 static int alc_test_pin_ctl_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
1571 static char *texts
[] = {
1572 "N/A", "Line Out", "HP Out",
1573 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
1575 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
1577 uinfo
->value
.enumerated
.items
= 8;
1578 if (uinfo
->value
.enumerated
.item
>= 8)
1579 uinfo
->value
.enumerated
.item
= 7;
1580 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
1584 static int alc_test_pin_ctl_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1586 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1587 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1588 unsigned int pin_ctl
, item
= 0;
1590 pin_ctl
= snd_hda_codec_read(codec
, nid
, 0,
1591 AC_VERB_GET_PIN_WIDGET_CONTROL
, 0);
1592 if (pin_ctl
& AC_PINCTL_OUT_EN
) {
1593 if (pin_ctl
& AC_PINCTL_HP_EN
)
1597 } else if (pin_ctl
& AC_PINCTL_IN_EN
) {
1598 switch (pin_ctl
& AC_PINCTL_VREFEN
) {
1599 case AC_PINCTL_VREF_HIZ
: item
= 3; break;
1600 case AC_PINCTL_VREF_50
: item
= 4; break;
1601 case AC_PINCTL_VREF_GRD
: item
= 5; break;
1602 case AC_PINCTL_VREF_80
: item
= 6; break;
1603 case AC_PINCTL_VREF_100
: item
= 7; break;
1606 ucontrol
->value
.enumerated
.item
[0] = item
;
1610 static int alc_test_pin_ctl_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1612 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1613 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1614 static unsigned int ctls
[] = {
1615 0, AC_PINCTL_OUT_EN
, AC_PINCTL_OUT_EN
| AC_PINCTL_HP_EN
,
1616 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_HIZ
,
1617 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_50
,
1618 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_GRD
,
1619 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_80
,
1620 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_100
,
1622 unsigned int old_ctl
, new_ctl
;
1624 old_ctl
= snd_hda_codec_read(codec
, nid
, 0,
1625 AC_VERB_GET_PIN_WIDGET_CONTROL
, 0);
1626 new_ctl
= ctls
[ucontrol
->value
.enumerated
.item
[0]];
1627 if (old_ctl
!= new_ctl
) {
1628 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, new_ctl
);
1629 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
1630 ucontrol
->value
.enumerated
.item
[0] >= 3 ? 0xb080 : 0xb000);
1636 static int alc_test_pin_src_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
1638 static char *texts
[] = {
1639 "Front", "Surround", "CLFE", "Side"
1641 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
1643 uinfo
->value
.enumerated
.items
= 4;
1644 if (uinfo
->value
.enumerated
.item
>= 4)
1645 uinfo
->value
.enumerated
.item
= 3;
1646 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
1650 static int alc_test_pin_src_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1652 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1653 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1656 sel
= snd_hda_codec_read(codec
, nid
, 0, AC_VERB_GET_CONNECT_SEL
, 0);
1657 ucontrol
->value
.enumerated
.item
[0] = sel
& 3;
1661 static int alc_test_pin_src_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1663 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1664 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1667 sel
= snd_hda_codec_read(codec
, nid
, 0, AC_VERB_GET_CONNECT_SEL
, 0) & 3;
1668 if (ucontrol
->value
.enumerated
.item
[0] != sel
) {
1669 sel
= ucontrol
->value
.enumerated
.item
[0] & 3;
1670 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_CONNECT_SEL
, sel
);
1676 #define PIN_CTL_TEST(xname,nid) { \
1677 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1679 .info = alc_test_pin_ctl_info, \
1680 .get = alc_test_pin_ctl_get, \
1681 .put = alc_test_pin_ctl_put, \
1682 .private_value = nid \
1685 #define PIN_SRC_TEST(xname,nid) { \
1686 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1688 .info = alc_test_pin_src_info, \
1689 .get = alc_test_pin_src_get, \
1690 .put = alc_test_pin_src_put, \
1691 .private_value = nid \
1694 static struct snd_kcontrol_new alc880_test_mixer
[] = {
1695 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
1696 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
1697 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT
),
1698 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
1699 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
1700 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
1701 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT
),
1702 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT
),
1703 PIN_CTL_TEST("Front Pin Mode", 0x14),
1704 PIN_CTL_TEST("Surround Pin Mode", 0x15),
1705 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
1706 PIN_CTL_TEST("Side Pin Mode", 0x17),
1707 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
1708 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
1709 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
1710 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
1711 PIN_SRC_TEST("In-1 Pin Source", 0x18),
1712 PIN_SRC_TEST("In-2 Pin Source", 0x19),
1713 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
1714 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
1715 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT
),
1716 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT
),
1717 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT
),
1718 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT
),
1719 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT
),
1720 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT
),
1721 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT
),
1722 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT
),
1723 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT
),
1724 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT
),
1726 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1727 .name
= "Channel Mode",
1728 .info
= alc_ch_mode_info
,
1729 .get
= alc_ch_mode_get
,
1730 .put
= alc_ch_mode_put
,
1735 static struct hda_verb alc880_test_init_verbs
[] = {
1736 /* Unmute inputs of 0x0c - 0x0f */
1737 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1738 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1739 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1740 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1741 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1742 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1743 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1744 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1745 /* Vol output for 0x0c-0x0f */
1746 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1747 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1748 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1749 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1750 /* Set output pins 0x14-0x17 */
1751 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1752 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1753 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1754 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1755 /* Unmute output pins 0x14-0x17 */
1756 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1757 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1758 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1759 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1760 /* Set input pins 0x18-0x1c */
1761 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1762 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1763 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1764 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1765 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1766 /* Mute input pins 0x18-0x1b */
1767 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1768 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1769 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1770 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1772 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1773 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
1774 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1775 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
1776 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1777 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
1778 /* Analog input/passthru */
1779 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1780 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1781 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
1782 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
1783 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
1791 static struct hda_board_config alc880_cfg_tbl
[] = {
1792 /* Back 3 jack, front 2 jack */
1793 { .modelname
= "3stack", .config
= ALC880_3ST
},
1794 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe200, .config
= ALC880_3ST
},
1795 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe201, .config
= ALC880_3ST
},
1796 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe202, .config
= ALC880_3ST
},
1797 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe203, .config
= ALC880_3ST
},
1798 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe204, .config
= ALC880_3ST
},
1799 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe205, .config
= ALC880_3ST
},
1800 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe206, .config
= ALC880_3ST
},
1801 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe207, .config
= ALC880_3ST
},
1802 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe208, .config
= ALC880_3ST
},
1803 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe209, .config
= ALC880_3ST
},
1804 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20a, .config
= ALC880_3ST
},
1805 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20b, .config
= ALC880_3ST
},
1806 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20c, .config
= ALC880_3ST
},
1807 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20d, .config
= ALC880_3ST
},
1808 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20e, .config
= ALC880_3ST
},
1809 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20f, .config
= ALC880_3ST
},
1810 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe210, .config
= ALC880_3ST
},
1811 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe211, .config
= ALC880_3ST
},
1812 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe214, .config
= ALC880_3ST
},
1813 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe302, .config
= ALC880_3ST
},
1814 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe303, .config
= ALC880_3ST
},
1815 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe304, .config
= ALC880_3ST
},
1816 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe306, .config
= ALC880_3ST
},
1817 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe307, .config
= ALC880_3ST
},
1818 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe404, .config
= ALC880_3ST
},
1819 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xa101, .config
= ALC880_3ST
},
1820 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x3031, .config
= ALC880_3ST
},
1821 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4036, .config
= ALC880_3ST
},
1822 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4037, .config
= ALC880_3ST
},
1823 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4038, .config
= ALC880_3ST
},
1824 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4040, .config
= ALC880_3ST
},
1825 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4041, .config
= ALC880_3ST
},
1827 { .pci_subvendor
= 0x19db, .pci_subdevice
= 0x4188, .config
= ALC880_TCL_S700
},
1829 /* Back 3 jack, front 2 jack (Internal add Aux-In) */
1830 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0xe310, .config
= ALC880_3ST
},
1831 { .pci_subvendor
= 0x104d, .pci_subdevice
= 0x81d6, .config
= ALC880_3ST
},
1832 { .pci_subvendor
= 0x104d, .pci_subdevice
= 0x81a0, .config
= ALC880_3ST
},
1834 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
1835 { .modelname
= "3stack-digout", .config
= ALC880_3ST_DIG
},
1836 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe308, .config
= ALC880_3ST_DIG
},
1837 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0x0070, .config
= ALC880_3ST_DIG
},
1838 /* Clevo m520G NB */
1839 { .pci_subvendor
= 0x1558, .pci_subdevice
= 0x0520, .config
= ALC880_CLEVO
},
1841 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
1842 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe305, .config
= ALC880_3ST_DIG
},
1843 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd402, .config
= ALC880_3ST_DIG
},
1844 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0xe309, .config
= ALC880_3ST_DIG
},
1846 /* Back 5 jack, front 2 jack */
1847 { .modelname
= "5stack", .config
= ALC880_5ST
},
1848 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x3033, .config
= ALC880_5ST
},
1849 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4039, .config
= ALC880_5ST
},
1850 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x3032, .config
= ALC880_5ST
},
1851 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x2a09, .config
= ALC880_5ST
},
1852 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x814e, .config
= ALC880_5ST
},
1854 /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
1855 { .modelname
= "5stack-digout", .config
= ALC880_5ST_DIG
},
1856 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe224, .config
= ALC880_5ST_DIG
},
1857 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe400, .config
= ALC880_5ST_DIG
},
1858 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe401, .config
= ALC880_5ST_DIG
},
1859 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe402, .config
= ALC880_5ST_DIG
},
1860 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd400, .config
= ALC880_5ST_DIG
},
1861 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd401, .config
= ALC880_5ST_DIG
},
1862 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xa100, .config
= ALC880_5ST_DIG
},
1863 { .pci_subvendor
= 0x1565, .pci_subdevice
= 0x8202, .config
= ALC880_5ST_DIG
},
1864 { .pci_subvendor
= 0x1019, .pci_subdevice
= 0xa880, .config
= ALC880_5ST_DIG
},
1865 /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */
1866 { .pci_subvendor
= 0x1695, .pci_subdevice
= 0x400d, .config
= ALC880_5ST_DIG
},
1867 /* note subvendor = 0 below */
1868 /* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */
1870 { .modelname
= "w810", .config
= ALC880_W810
},
1871 { .pci_subvendor
= 0x161f, .pci_subdevice
= 0x203d, .config
= ALC880_W810
},
1873 { .modelname
= "z71v", .config
= ALC880_Z71V
},
1874 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1964, .config
= ALC880_Z71V
},
1876 { .modelname
= "6stack", .config
= ALC880_6ST
},
1877 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x8196, .config
= ALC880_6ST
}, /* ASUS P5GD1-HVM */
1878 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x81b4, .config
= ALC880_6ST
},
1879 { .pci_subvendor
= 0x1019, .pci_subdevice
= 0xa884, .config
= ALC880_6ST
}, /* Acer APFV */
1880 { .pci_subvendor
= 0x1458, .pci_subdevice
= 0xa102, .config
= ALC880_6ST
}, /* Gigabyte K8N51 */
1882 { .modelname
= "6stack-digout", .config
= ALC880_6ST_DIG
},
1883 { .pci_subvendor
= 0x2668, .pci_subdevice
= 0x8086, .config
= ALC880_6ST_DIG
},
1884 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0x2668, .config
= ALC880_6ST_DIG
},
1885 { .pci_subvendor
= 0x1462, .pci_subdevice
= 0x1150, .config
= ALC880_6ST_DIG
},
1886 { .pci_subvendor
= 0xe803, .pci_subdevice
= 0x1019, .config
= ALC880_6ST_DIG
},
1887 { .pci_subvendor
= 0x1039, .pci_subdevice
= 0x1234, .config
= ALC880_6ST_DIG
},
1888 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0x0077, .config
= ALC880_6ST_DIG
},
1889 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0x0078, .config
= ALC880_6ST_DIG
},
1890 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0x0087, .config
= ALC880_6ST_DIG
},
1891 { .pci_subvendor
= 0x1297, .pci_subdevice
= 0xc790, .config
= ALC880_6ST_DIG
}, /* Shuttle ST20G5 */
1893 { .modelname
= "asus", .config
= ALC880_ASUS
},
1894 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1964, .config
= ALC880_ASUS_DIG
},
1895 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1973, .config
= ALC880_ASUS_DIG
},
1896 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x19b3, .config
= ALC880_ASUS_DIG
},
1897 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1113, .config
= ALC880_ASUS_DIG
},
1898 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1173, .config
= ALC880_ASUS_DIG
},
1899 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1993, .config
= ALC880_ASUS
},
1900 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x10c3, .config
= ALC880_ASUS_DIG
},
1901 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1133, .config
= ALC880_ASUS
},
1902 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1123, .config
= ALC880_ASUS_DIG
},
1903 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1143, .config
= ALC880_ASUS
},
1904 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x10b3, .config
= ALC880_ASUS_W1V
},
1905 { .pci_subvendor
= 0x1558, .pci_subdevice
= 0x5401, .config
= ALC880_ASUS_DIG2
},
1907 { .modelname
= "uniwill", .config
= ALC880_UNIWILL_DIG
},
1908 { .pci_subvendor
= 0x1584, .pci_subdevice
= 0x9050, .config
= ALC880_UNIWILL_DIG
},
1910 { .modelname
= "F1734", .config
= ALC880_F1734
},
1911 { .pci_subvendor
= 0x1734, .pci_subdevice
= 0x107c, .config
= ALC880_F1734
},
1912 { .pci_subvendor
= 0x1584, .pci_subdevice
= 0x9054, .config
= ALC880_F1734
},
1914 #ifdef CONFIG_SND_DEBUG
1915 { .modelname
= "test", .config
= ALC880_TEST
},
1917 { .modelname
= "auto", .config
= ALC880_AUTO
},
1923 * ALC880 codec presets
1925 static struct alc_config_preset alc880_presets
[] = {
1927 .mixers
= { alc880_three_stack_mixer
},
1928 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_3stack_init_verbs
},
1929 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1930 .dac_nids
= alc880_dac_nids
,
1931 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
1932 .channel_mode
= alc880_threestack_modes
,
1933 .input_mux
= &alc880_capture_source
,
1935 [ALC880_3ST_DIG
] = {
1936 .mixers
= { alc880_three_stack_mixer
},
1937 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_3stack_init_verbs
},
1938 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1939 .dac_nids
= alc880_dac_nids
,
1940 .dig_out_nid
= ALC880_DIGOUT_NID
,
1941 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
1942 .channel_mode
= alc880_threestack_modes
,
1943 .input_mux
= &alc880_capture_source
,
1945 [ALC880_TCL_S700
] = {
1946 .mixers
= { alc880_tcl_s700_mixer
},
1947 .init_verbs
= { alc880_volume_init_verbs
,
1948 alc880_pin_tcl_S700_init_verbs
,
1949 alc880_gpio2_init_verbs
},
1950 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1951 .dac_nids
= alc880_dac_nids
,
1953 .num_channel_mode
= ARRAY_SIZE(alc880_2_jack_modes
),
1954 .channel_mode
= alc880_2_jack_modes
,
1955 .input_mux
= &alc880_capture_source
,
1958 .mixers
= { alc880_three_stack_mixer
, alc880_five_stack_mixer
},
1959 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_5stack_init_verbs
},
1960 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1961 .dac_nids
= alc880_dac_nids
,
1962 .num_channel_mode
= ARRAY_SIZE(alc880_fivestack_modes
),
1963 .channel_mode
= alc880_fivestack_modes
,
1964 .input_mux
= &alc880_capture_source
,
1966 [ALC880_5ST_DIG
] = {
1967 .mixers
= { alc880_three_stack_mixer
, alc880_five_stack_mixer
},
1968 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_5stack_init_verbs
},
1969 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1970 .dac_nids
= alc880_dac_nids
,
1971 .dig_out_nid
= ALC880_DIGOUT_NID
,
1972 .num_channel_mode
= ARRAY_SIZE(alc880_fivestack_modes
),
1973 .channel_mode
= alc880_fivestack_modes
,
1974 .input_mux
= &alc880_capture_source
,
1977 .mixers
= { alc880_six_stack_mixer
},
1978 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_6stack_init_verbs
},
1979 .num_dacs
= ARRAY_SIZE(alc880_6st_dac_nids
),
1980 .dac_nids
= alc880_6st_dac_nids
,
1981 .num_channel_mode
= ARRAY_SIZE(alc880_sixstack_modes
),
1982 .channel_mode
= alc880_sixstack_modes
,
1983 .input_mux
= &alc880_6stack_capture_source
,
1985 [ALC880_6ST_DIG
] = {
1986 .mixers
= { alc880_six_stack_mixer
},
1987 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_6stack_init_verbs
},
1988 .num_dacs
= ARRAY_SIZE(alc880_6st_dac_nids
),
1989 .dac_nids
= alc880_6st_dac_nids
,
1990 .dig_out_nid
= ALC880_DIGOUT_NID
,
1991 .num_channel_mode
= ARRAY_SIZE(alc880_sixstack_modes
),
1992 .channel_mode
= alc880_sixstack_modes
,
1993 .input_mux
= &alc880_6stack_capture_source
,
1996 .mixers
= { alc880_w810_base_mixer
},
1997 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_w810_init_verbs
,
1998 alc880_gpio2_init_verbs
},
1999 .num_dacs
= ARRAY_SIZE(alc880_w810_dac_nids
),
2000 .dac_nids
= alc880_w810_dac_nids
,
2001 .dig_out_nid
= ALC880_DIGOUT_NID
,
2002 .num_channel_mode
= ARRAY_SIZE(alc880_w810_modes
),
2003 .channel_mode
= alc880_w810_modes
,
2004 .input_mux
= &alc880_capture_source
,
2007 .mixers
= { alc880_z71v_mixer
},
2008 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_z71v_init_verbs
},
2009 .num_dacs
= ARRAY_SIZE(alc880_z71v_dac_nids
),
2010 .dac_nids
= alc880_z71v_dac_nids
,
2011 .dig_out_nid
= ALC880_DIGOUT_NID
,
2013 .num_channel_mode
= ARRAY_SIZE(alc880_2_jack_modes
),
2014 .channel_mode
= alc880_2_jack_modes
,
2015 .input_mux
= &alc880_capture_source
,
2018 .mixers
= { alc880_f1734_mixer
},
2019 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_f1734_init_verbs
},
2020 .num_dacs
= ARRAY_SIZE(alc880_f1734_dac_nids
),
2021 .dac_nids
= alc880_f1734_dac_nids
,
2023 .num_channel_mode
= ARRAY_SIZE(alc880_2_jack_modes
),
2024 .channel_mode
= alc880_2_jack_modes
,
2025 .input_mux
= &alc880_capture_source
,
2028 .mixers
= { alc880_asus_mixer
},
2029 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_asus_init_verbs
,
2030 alc880_gpio1_init_verbs
},
2031 .num_dacs
= ARRAY_SIZE(alc880_asus_dac_nids
),
2032 .dac_nids
= alc880_asus_dac_nids
,
2033 .num_channel_mode
= ARRAY_SIZE(alc880_asus_modes
),
2034 .channel_mode
= alc880_asus_modes
,
2035 .input_mux
= &alc880_capture_source
,
2037 [ALC880_ASUS_DIG
] = {
2038 .mixers
= { alc880_asus_mixer
},
2039 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_asus_init_verbs
,
2040 alc880_gpio1_init_verbs
},
2041 .num_dacs
= ARRAY_SIZE(alc880_asus_dac_nids
),
2042 .dac_nids
= alc880_asus_dac_nids
,
2043 .dig_out_nid
= ALC880_DIGOUT_NID
,
2044 .num_channel_mode
= ARRAY_SIZE(alc880_asus_modes
),
2045 .channel_mode
= alc880_asus_modes
,
2046 .input_mux
= &alc880_capture_source
,
2048 [ALC880_ASUS_DIG2
] = {
2049 .mixers
= { alc880_asus_mixer
},
2050 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_asus_init_verbs
,
2051 alc880_gpio2_init_verbs
}, /* use GPIO2 */
2052 .num_dacs
= ARRAY_SIZE(alc880_asus_dac_nids
),
2053 .dac_nids
= alc880_asus_dac_nids
,
2054 .dig_out_nid
= ALC880_DIGOUT_NID
,
2055 .num_channel_mode
= ARRAY_SIZE(alc880_asus_modes
),
2056 .channel_mode
= alc880_asus_modes
,
2057 .input_mux
= &alc880_capture_source
,
2059 [ALC880_ASUS_W1V
] = {
2060 .mixers
= { alc880_asus_mixer
, alc880_asus_w1v_mixer
},
2061 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_asus_init_verbs
,
2062 alc880_gpio1_init_verbs
},
2063 .num_dacs
= ARRAY_SIZE(alc880_asus_dac_nids
),
2064 .dac_nids
= alc880_asus_dac_nids
,
2065 .dig_out_nid
= ALC880_DIGOUT_NID
,
2066 .num_channel_mode
= ARRAY_SIZE(alc880_asus_modes
),
2067 .channel_mode
= alc880_asus_modes
,
2068 .input_mux
= &alc880_capture_source
,
2070 [ALC880_UNIWILL_DIG
] = {
2071 .mixers
= { alc880_asus_mixer
, alc880_pcbeep_mixer
},
2072 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_asus_init_verbs
},
2073 .num_dacs
= ARRAY_SIZE(alc880_asus_dac_nids
),
2074 .dac_nids
= alc880_asus_dac_nids
,
2075 .dig_out_nid
= ALC880_DIGOUT_NID
,
2076 .num_channel_mode
= ARRAY_SIZE(alc880_asus_modes
),
2077 .channel_mode
= alc880_asus_modes
,
2078 .input_mux
= &alc880_capture_source
,
2081 .mixers
= { alc880_three_stack_mixer
},
2082 .init_verbs
= { alc880_volume_init_verbs
,
2083 alc880_pin_clevo_init_verbs
},
2084 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
2085 .dac_nids
= alc880_dac_nids
,
2087 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
2088 .channel_mode
= alc880_threestack_modes
,
2089 .input_mux
= &alc880_capture_source
,
2091 #ifdef CONFIG_SND_DEBUG
2093 .mixers
= { alc880_test_mixer
},
2094 .init_verbs
= { alc880_test_init_verbs
},
2095 .num_dacs
= ARRAY_SIZE(alc880_test_dac_nids
),
2096 .dac_nids
= alc880_test_dac_nids
,
2097 .dig_out_nid
= ALC880_DIGOUT_NID
,
2098 .num_channel_mode
= ARRAY_SIZE(alc880_test_modes
),
2099 .channel_mode
= alc880_test_modes
,
2100 .input_mux
= &alc880_test_capture_source
,
2106 * Automatic parse of I/O pins from the BIOS configuration
2109 #define NUM_CONTROL_ALLOC 32
2110 #define NUM_VERB_ALLOC 32
2114 ALC_CTL_WIDGET_MUTE
,
2117 static struct snd_kcontrol_new alc880_control_templates
[] = {
2118 HDA_CODEC_VOLUME(NULL
, 0, 0, 0),
2119 HDA_CODEC_MUTE(NULL
, 0, 0, 0),
2120 HDA_BIND_MUTE(NULL
, 0, 0, 0),
2123 /* add dynamic controls */
2124 static int add_control(struct alc_spec
*spec
, int type
, const char *name
, unsigned long val
)
2126 struct snd_kcontrol_new
*knew
;
2128 if (spec
->num_kctl_used
>= spec
->num_kctl_alloc
) {
2129 int num
= spec
->num_kctl_alloc
+ NUM_CONTROL_ALLOC
;
2131 knew
= kcalloc(num
+ 1, sizeof(*knew
), GFP_KERNEL
); /* array + terminator */
2134 if (spec
->kctl_alloc
) {
2135 memcpy(knew
, spec
->kctl_alloc
, sizeof(*knew
) * spec
->num_kctl_alloc
);
2136 kfree(spec
->kctl_alloc
);
2138 spec
->kctl_alloc
= knew
;
2139 spec
->num_kctl_alloc
= num
;
2142 knew
= &spec
->kctl_alloc
[spec
->num_kctl_used
];
2143 *knew
= alc880_control_templates
[type
];
2144 knew
->name
= kstrdup(name
, GFP_KERNEL
);
2147 knew
->private_value
= val
;
2148 spec
->num_kctl_used
++;
2152 #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
2153 #define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
2154 #define alc880_is_multi_pin(nid) ((nid) >= 0x18)
2155 #define alc880_multi_pin_idx(nid) ((nid) - 0x18)
2156 #define alc880_is_input_pin(nid) ((nid) >= 0x18)
2157 #define alc880_input_pin_idx(nid) ((nid) - 0x18)
2158 #define alc880_idx_to_dac(nid) ((nid) + 0x02)
2159 #define alc880_dac_to_idx(nid) ((nid) - 0x02)
2160 #define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
2161 #define alc880_idx_to_selector(nid) ((nid) + 0x10)
2162 #define ALC880_PIN_CD_NID 0x1c
2164 /* fill in the dac_nids table from the parsed pin configuration */
2165 static int alc880_auto_fill_dac_nids(struct alc_spec
*spec
, const struct auto_pin_cfg
*cfg
)
2171 memset(assigned
, 0, sizeof(assigned
));
2172 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
2174 /* check the pins hardwired to audio widget */
2175 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2176 nid
= cfg
->line_out_pins
[i
];
2177 if (alc880_is_fixed_pin(nid
)) {
2178 int idx
= alc880_fixed_pin_idx(nid
);
2179 spec
->multiout
.dac_nids
[i
] = alc880_idx_to_dac(idx
);
2183 /* left pins can be connect to any audio widget */
2184 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2185 nid
= cfg
->line_out_pins
[i
];
2186 if (alc880_is_fixed_pin(nid
))
2188 /* search for an empty channel */
2189 for (j
= 0; j
< cfg
->line_outs
; j
++) {
2190 if (! assigned
[j
]) {
2191 spec
->multiout
.dac_nids
[i
] = alc880_idx_to_dac(j
);
2197 spec
->multiout
.num_dacs
= cfg
->line_outs
;
2201 /* add playback controls from the parsed DAC table */
2202 static int alc880_auto_create_multi_out_ctls(struct alc_spec
*spec
,
2203 const struct auto_pin_cfg
*cfg
)
2206 static const char *chname
[4] = { "Front", "Surround", NULL
/*CLFE*/, "Side" };
2210 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2211 if (! spec
->multiout
.dac_nids
[i
])
2213 nid
= alc880_idx_to_mixer(alc880_dac_to_idx(spec
->multiout
.dac_nids
[i
]));
2216 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Center Playback Volume",
2217 HDA_COMPOSE_AMP_VAL(nid
, 1, 0, HDA_OUTPUT
))) < 0)
2219 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "LFE Playback Volume",
2220 HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
))) < 0)
2222 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, "Center Playback Switch",
2223 HDA_COMPOSE_AMP_VAL(nid
, 1, 2, HDA_INPUT
))) < 0)
2225 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, "LFE Playback Switch",
2226 HDA_COMPOSE_AMP_VAL(nid
, 2, 2, HDA_INPUT
))) < 0)
2229 sprintf(name
, "%s Playback Volume", chname
[i
]);
2230 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, name
,
2231 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
2233 sprintf(name
, "%s Playback Switch", chname
[i
]);
2234 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, name
,
2235 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
))) < 0)
2242 /* add playback controls for speaker and HP outputs */
2243 static int alc880_auto_create_extra_out(struct alc_spec
*spec
, hda_nid_t pin
,
2253 if (alc880_is_fixed_pin(pin
)) {
2254 nid
= alc880_idx_to_dac(alc880_fixed_pin_idx(pin
));
2255 if (! spec
->multiout
.dac_nids
[0]) {
2256 /* use this as the primary output */
2257 spec
->multiout
.dac_nids
[0] = nid
;
2258 if (! spec
->multiout
.num_dacs
)
2259 spec
->multiout
.num_dacs
= 1;
2261 /* specify the DAC as the extra output */
2262 spec
->multiout
.hp_nid
= nid
;
2263 /* control HP volume/switch on the output mixer amp */
2264 nid
= alc880_idx_to_mixer(alc880_fixed_pin_idx(pin
));
2265 sprintf(name
, "%s Playback Volume", pfx
);
2266 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, name
,
2267 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
2269 sprintf(name
, "%s Playback Switch", pfx
);
2270 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, name
,
2271 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
))) < 0)
2273 } else if (alc880_is_multi_pin(pin
)) {
2274 /* set manual connection */
2275 if (! spec
->multiout
.dac_nids
[0]) {
2276 /* use this as the primary output */
2277 spec
->multiout
.dac_nids
[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin
));
2278 if (! spec
->multiout
.num_dacs
)
2279 spec
->multiout
.num_dacs
= 1;
2281 /* we have only a switch on HP-out PIN */
2282 sprintf(name
, "%s Playback Switch", pfx
);
2283 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, name
,
2284 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
))) < 0)
2290 /* create input playback/capture controls for the given pin */
2291 static int new_analog_input(struct alc_spec
*spec
, hda_nid_t pin
, const char *ctlname
,
2292 int idx
, hda_nid_t mix_nid
)
2297 sprintf(name
, "%s Playback Volume", ctlname
);
2298 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, name
,
2299 HDA_COMPOSE_AMP_VAL(mix_nid
, 3, idx
, HDA_INPUT
))) < 0)
2301 sprintf(name
, "%s Playback Switch", ctlname
);
2302 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, name
,
2303 HDA_COMPOSE_AMP_VAL(mix_nid
, 3, idx
, HDA_INPUT
))) < 0)
2308 /* create playback/capture controls for input pins */
2309 static int alc880_auto_create_analog_input_ctls(struct alc_spec
*spec
,
2310 const struct auto_pin_cfg
*cfg
)
2312 struct hda_input_mux
*imux
= &spec
->private_imux
;
2315 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
2316 if (alc880_is_input_pin(cfg
->input_pins
[i
])) {
2317 idx
= alc880_input_pin_idx(cfg
->input_pins
[i
]);
2318 err
= new_analog_input(spec
, cfg
->input_pins
[i
],
2319 auto_pin_cfg_labels
[i
],
2323 imux
->items
[imux
->num_items
].label
= auto_pin_cfg_labels
[i
];
2324 imux
->items
[imux
->num_items
].index
= alc880_input_pin_idx(cfg
->input_pins
[i
]);
2331 static void alc880_auto_set_output_and_unmute(struct hda_codec
*codec
,
2332 hda_nid_t nid
, int pin_type
,
2336 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
2337 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
2338 /* need the manual connection? */
2339 if (alc880_is_multi_pin(nid
)) {
2340 struct alc_spec
*spec
= codec
->spec
;
2341 int idx
= alc880_multi_pin_idx(nid
);
2342 snd_hda_codec_write(codec
, alc880_idx_to_selector(idx
), 0,
2343 AC_VERB_SET_CONNECT_SEL
,
2344 alc880_dac_to_idx(spec
->multiout
.dac_nids
[dac_idx
]));
2348 static void alc880_auto_init_multi_out(struct hda_codec
*codec
)
2350 struct alc_spec
*spec
= codec
->spec
;
2353 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
2354 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
2355 alc880_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
2359 static void alc880_auto_init_extra_out(struct hda_codec
*codec
)
2361 struct alc_spec
*spec
= codec
->spec
;
2364 pin
= spec
->autocfg
.speaker_pin
;
2365 if (pin
) /* connect to front */
2366 alc880_auto_set_output_and_unmute(codec
, pin
, PIN_OUT
, 0);
2367 pin
= spec
->autocfg
.hp_pin
;
2368 if (pin
) /* connect to front */
2369 alc880_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0);
2372 static void alc880_auto_init_analog_input(struct hda_codec
*codec
)
2374 struct alc_spec
*spec
= codec
->spec
;
2377 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
2378 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
2379 if (alc880_is_input_pin(nid
)) {
2380 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
2381 i
<= AUTO_PIN_FRONT_MIC
? PIN_VREF80
: PIN_IN
);
2382 if (nid
!= ALC880_PIN_CD_NID
)
2383 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
2389 /* parse the BIOS configuration and set up the alc_spec */
2390 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2391 static int alc880_parse_auto_config(struct hda_codec
*codec
)
2393 struct alc_spec
*spec
= codec
->spec
;
2395 static hda_nid_t alc880_ignore
[] = { 0x1d, 0 };
2397 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
,
2398 alc880_ignore
)) < 0)
2400 if (! spec
->autocfg
.line_outs
&& ! spec
->autocfg
.speaker_pin
&&
2401 ! spec
->autocfg
.hp_pin
)
2402 return 0; /* can't find valid BIOS pin config */
2404 if ((err
= alc880_auto_fill_dac_nids(spec
, &spec
->autocfg
)) < 0 ||
2405 (err
= alc880_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
2406 (err
= alc880_auto_create_extra_out(spec
, spec
->autocfg
.speaker_pin
,
2408 (err
= alc880_auto_create_extra_out(spec
, spec
->autocfg
.speaker_pin
,
2409 "Headphone")) < 0 ||
2410 (err
= alc880_auto_create_analog_input_ctls(spec
, &spec
->autocfg
)) < 0)
2413 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
2415 if (spec
->autocfg
.dig_out_pin
)
2416 spec
->multiout
.dig_out_nid
= ALC880_DIGOUT_NID
;
2417 if (spec
->autocfg
.dig_in_pin
)
2418 spec
->dig_in_nid
= ALC880_DIGIN_NID
;
2420 if (spec
->kctl_alloc
)
2421 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
2423 spec
->init_verbs
[spec
->num_init_verbs
++] = alc880_volume_init_verbs
;
2425 spec
->input_mux
= &spec
->private_imux
;
2430 /* init callback for auto-configuration model -- overriding the default init */
2431 static int alc880_auto_init(struct hda_codec
*codec
)
2434 alc880_auto_init_multi_out(codec
);
2435 alc880_auto_init_extra_out(codec
);
2436 alc880_auto_init_analog_input(codec
);
2441 * OK, here we have finally the patch for ALC880
2444 static int patch_alc880(struct hda_codec
*codec
)
2446 struct alc_spec
*spec
;
2450 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
2456 board_config
= snd_hda_check_board_config(codec
, alc880_cfg_tbl
);
2457 if (board_config
< 0 || board_config
>= ALC880_MODEL_LAST
) {
2458 printk(KERN_INFO
"hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
2459 board_config
= ALC880_AUTO
;
2462 if (board_config
== ALC880_AUTO
) {
2463 /* automatic parse from the BIOS config */
2464 err
= alc880_parse_auto_config(codec
);
2469 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n");
2470 board_config
= ALC880_3ST
;
2474 if (board_config
!= ALC880_AUTO
)
2475 setup_preset(spec
, &alc880_presets
[board_config
]);
2477 spec
->stream_name_analog
= "ALC880 Analog";
2478 spec
->stream_analog_playback
= &alc880_pcm_analog_playback
;
2479 spec
->stream_analog_capture
= &alc880_pcm_analog_capture
;
2481 spec
->stream_name_digital
= "ALC880 Digital";
2482 spec
->stream_digital_playback
= &alc880_pcm_digital_playback
;
2483 spec
->stream_digital_capture
= &alc880_pcm_digital_capture
;
2485 if (! spec
->adc_nids
&& spec
->input_mux
) {
2486 /* check whether NID 0x07 is valid */
2487 unsigned int wcap
= get_wcaps(codec
, alc880_adc_nids
[0]);
2488 wcap
= (wcap
& AC_WCAP_TYPE
) >> AC_WCAP_TYPE_SHIFT
; /* get type */
2489 if (wcap
!= AC_WID_AUD_IN
) {
2490 spec
->adc_nids
= alc880_adc_nids_alt
;
2491 spec
->num_adc_nids
= ARRAY_SIZE(alc880_adc_nids_alt
);
2492 spec
->mixers
[spec
->num_mixers
] = alc880_capture_alt_mixer
;
2495 spec
->adc_nids
= alc880_adc_nids
;
2496 spec
->num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
);
2497 spec
->mixers
[spec
->num_mixers
] = alc880_capture_mixer
;
2502 codec
->patch_ops
= alc_patch_ops
;
2503 if (board_config
== ALC880_AUTO
)
2504 codec
->patch_ops
.init
= alc880_auto_init
;
2514 static hda_nid_t alc260_dac_nids
[1] = {
2519 static hda_nid_t alc260_adc_nids
[1] = {
2524 static hda_nid_t alc260_adc_nids_alt
[1] = {
2529 static hda_nid_t alc260_hp_adc_nids
[2] = {
2534 /* NIDs used when simultaneous access to both ADCs makes sense. Note that
2535 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
2537 static hda_nid_t alc260_dual_adc_nids
[2] = {
2542 #define ALC260_DIGOUT_NID 0x03
2543 #define ALC260_DIGIN_NID 0x06
2545 static struct hda_input_mux alc260_capture_source
= {
2549 { "Front Mic", 0x1 },
2555 /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
2556 * headphone jack and the internal CD lines.
2558 static struct hda_input_mux alc260_fujitsu_capture_source
= {
2561 { "Mic/Line", 0x0 },
2563 { "Headphone", 0x2 },
2567 /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configutation to
2568 * the Fujitsu S702x, but jacks are marked differently. We won't allow
2569 * retasking the Headphone jack, so it won't be available here.
2571 static struct hda_input_mux alc260_acer_capture_source
= {
2581 * This is just place-holder, so there's something for alc_build_pcms to look
2582 * at when it calculates the maximum number of channels. ALC260 has no mixer
2583 * element which allows changing the channel mode, so the verb list is
2586 static struct hda_channel_mode alc260_modes
[1] = {
2591 /* Mixer combinations
2593 * basic: base_output + input + pc_beep + capture
2594 * HP: base_output + input + capture_alt
2595 * HP_3013: hp_3013 + input + capture
2596 * fujitsu: fujitsu + capture
2597 * acer: acer + capture
2600 static struct snd_kcontrol_new alc260_base_output_mixer
[] = {
2601 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT
),
2602 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT
),
2603 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT
),
2604 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT
),
2605 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
2606 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT
),
2610 static struct snd_kcontrol_new alc260_input_mixer
[] = {
2611 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT
),
2612 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT
),
2613 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT
),
2614 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT
),
2615 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT
),
2616 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT
),
2617 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT
),
2618 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT
),
2622 static struct snd_kcontrol_new alc260_pc_beep_mixer
[] = {
2623 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT
),
2624 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT
),
2628 static struct snd_kcontrol_new alc260_hp_3013_mixer
[] = {
2629 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT
),
2630 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT
),
2631 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT
),
2632 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT
),
2633 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT
),
2634 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
2635 HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
2636 HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT
),
2640 static struct snd_kcontrol_new alc260_fujitsu_mixer
[] = {
2641 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT
),
2642 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT
),
2643 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT
),
2644 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT
),
2645 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT
),
2646 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT
),
2647 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT
),
2648 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN
),
2649 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT
),
2650 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT
),
2651 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT
),
2652 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT
),
2656 static struct snd_kcontrol_new alc260_acer_mixer
[] = {
2657 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT
),
2658 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT
),
2659 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT
),
2660 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT
),
2661 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT
),
2662 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT
),
2663 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN
),
2664 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT
),
2665 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT
),
2666 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT
),
2667 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT
),
2668 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT
),
2672 /* capture mixer elements */
2673 static struct snd_kcontrol_new alc260_capture_mixer
[] = {
2674 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT
),
2675 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT
),
2676 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT
),
2677 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT
),
2679 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2680 /* The multiple "Capture Source" controls confuse alsamixer
2681 * So call somewhat different..
2682 * FIXME: the controls appear in the "playback" view!
2684 /* .name = "Capture Source", */
2685 .name
= "Input Source",
2687 .info
= alc_mux_enum_info
,
2688 .get
= alc_mux_enum_get
,
2689 .put
= alc_mux_enum_put
,
2694 static struct snd_kcontrol_new alc260_capture_alt_mixer
[] = {
2695 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT
),
2696 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT
),
2698 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2699 /* The multiple "Capture Source" controls confuse alsamixer
2700 * So call somewhat different..
2701 * FIXME: the controls appear in the "playback" view!
2703 /* .name = "Capture Source", */
2704 .name
= "Input Source",
2706 .info
= alc_mux_enum_info
,
2707 .get
= alc_mux_enum_get
,
2708 .put
= alc_mux_enum_put
,
2714 * initialization verbs
2716 static struct hda_verb alc260_init_verbs
[] = {
2717 /* Line In pin widget for input */
2718 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2719 /* CD pin widget for input */
2720 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2721 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2722 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2723 /* Mic2 (front panel) pin widget for input and vref at 80% */
2724 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2725 /* LINE-2 is used for line-out in rear */
2726 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2727 /* select line-out */
2728 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x00},
2730 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2732 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2734 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2735 /* mute capture amp left and right */
2736 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2737 /* set connection select to line in (default select for this ADC) */
2738 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x02},
2739 /* mute capture amp left and right */
2740 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2741 /* set connection select to line in (default select for this ADC) */
2742 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x02},
2743 /* set vol=0 Line-Out mixer amp left and right */
2744 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2745 /* unmute pin widget amp left and right (no gain on this amp) */
2746 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2747 /* set vol=0 HP mixer amp left and right */
2748 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2749 /* unmute pin widget amp left and right (no gain on this amp) */
2750 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2751 /* set vol=0 Mono mixer amp left and right */
2752 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2753 /* unmute pin widget amp left and right (no gain on this amp) */
2754 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2755 /* unmute LINE-2 out pin */
2756 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2757 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2759 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
2761 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
2763 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2764 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2765 /* mute Front out path */
2766 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2767 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2768 /* mute Headphone out path */
2769 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2770 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2771 /* mute Mono out path */
2772 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2773 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2777 static struct hda_verb alc260_hp_init_verbs
[] = {
2778 /* Headphone and output */
2779 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0},
2781 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
2782 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2783 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24},
2784 /* Mic2 (front panel) pin widget for input and vref at 80% */
2785 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24},
2786 /* Line In pin widget for input */
2787 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
2788 /* Line-2 pin widget for output */
2789 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
2790 /* CD pin widget for input */
2791 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
2792 /* unmute amp left and right */
2793 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7000},
2794 /* set connection select to line in (default select for this ADC) */
2795 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x02},
2796 /* unmute Line-Out mixer amp left and right (volume = 0) */
2797 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
2798 /* mute pin widget amp left and right (no gain on this amp) */
2799 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
2800 /* unmute HP mixer amp left and right (volume = 0) */
2801 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
2802 /* mute pin widget amp left and right (no gain on this amp) */
2803 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
2804 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2806 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x04 << 8))},
2807 /* unmute Line In */
2808 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x02 << 8))},
2810 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2811 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2812 /* Unmute Front out path */
2813 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2814 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2815 /* Unmute Headphone out path */
2816 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2817 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2818 /* Unmute Mono out path */
2819 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2820 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2824 static struct hda_verb alc260_hp_3013_init_verbs
[] = {
2825 /* Line out and output */
2826 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
2828 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
2829 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2830 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24},
2831 /* Mic2 (front panel) pin widget for input and vref at 80% */
2832 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24},
2833 /* Line In pin widget for input */
2834 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
2835 /* Headphone pin widget for output */
2836 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0},
2837 /* CD pin widget for input */
2838 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
2839 /* unmute amp left and right */
2840 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7000},
2841 /* set connection select to line in (default select for this ADC) */
2842 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x02},
2843 /* unmute Line-Out mixer amp left and right (volume = 0) */
2844 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
2845 /* mute pin widget amp left and right (no gain on this amp) */
2846 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
2847 /* unmute HP mixer amp left and right (volume = 0) */
2848 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
2849 /* mute pin widget amp left and right (no gain on this amp) */
2850 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
2851 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2853 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x04 << 8))},
2854 /* unmute Line In */
2855 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x02 << 8))},
2857 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2858 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2859 /* Unmute Front out path */
2860 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2861 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2862 /* Unmute Headphone out path */
2863 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2864 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2865 /* Unmute Mono out path */
2866 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2867 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2871 /* Initialisation sequence for ALC260 as configured in Fujitsu S702x
2874 static struct hda_verb alc260_fujitsu_init_verbs
[] = {
2875 /* Disable all GPIOs */
2876 {0x01, AC_VERB_SET_GPIO_MASK
, 0},
2877 /* Internal speaker is connected to headphone pin */
2878 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2879 /* Headphone/Line-out jack connects to Line1 pin; make it an output */
2880 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2881 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
2882 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2883 /* Ensure all other unused pins are disabled and muted. */
2884 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2885 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2886 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2887 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2888 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2889 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2890 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2891 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2893 /* Disable digital (SPDIF) pins */
2894 {0x03, AC_VERB_SET_DIGI_CONVERT_1
, 0},
2895 {0x06, AC_VERB_SET_DIGI_CONVERT_1
, 0},
2897 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
2898 * when acting as an output.
2900 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0},
2902 /* Start with output sum widgets muted and their output gains at min */
2903 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2904 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2905 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2906 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2907 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2908 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2909 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2910 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2911 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2913 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
2914 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2915 /* Unmute Line1 pin widget output buffer since it starts as an output.
2916 * If the pin mode is changed by the user the pin mode control will
2917 * take care of enabling the pin's input/output buffers as needed.
2918 * Therefore there's no need to enable the input buffer at this
2921 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2922 /* Unmute input buffer of pin widget used for Line-in (no equiv
2925 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2927 /* Mute capture amp left and right */
2928 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2929 /* Set ADC connection select to match default mixer setting - line
2932 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x00},
2934 /* Do the same for the second ADC: mute capture input amp and
2935 * set ADC connection to line in (on mic1 pin)
2937 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2938 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x00},
2940 /* Mute all inputs to mixer widget (even unconnected ones) */
2941 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)}, /* mic1 pin */
2942 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)}, /* mic2 pin */
2943 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)}, /* line1 pin */
2944 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)}, /* line2 pin */
2945 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)}, /* CD pin */
2946 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)}, /* Beep-gen pin */
2947 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)}, /* Line-out pin */
2948 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)}, /* HP-pin pin */
2953 /* Initialisation sequence for ALC260 as configured in Acer TravelMate and
2954 * similar laptops (adapted from Fujitsu init verbs).
2956 static struct hda_verb alc260_acer_init_verbs
[] = {
2957 /* On TravelMate laptops, GPIO 0 enables the internal speaker and
2958 * the headphone jack. Turn this on and rely on the standard mute
2959 * methods whenever the user wants to turn these outputs off.
2961 {0x01, AC_VERB_SET_GPIO_MASK
, 0x01},
2962 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x01},
2963 {0x01, AC_VERB_SET_GPIO_DATA
, 0x01},
2964 /* Internal speaker/Headphone jack is connected to Line-out pin */
2965 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2966 /* Internal microphone/Mic jack is connected to Mic1 pin */
2967 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF50
},
2968 /* Line In jack is connected to Line1 pin */
2969 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2970 /* Ensure all other unused pins are disabled and muted. */
2971 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2972 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2973 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2974 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2975 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2976 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2977 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2978 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2979 /* Disable digital (SPDIF) pins */
2980 {0x03, AC_VERB_SET_DIGI_CONVERT_1
, 0},
2981 {0x06, AC_VERB_SET_DIGI_CONVERT_1
, 0},
2983 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
2984 * bus when acting as outputs.
2986 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0},
2987 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0},
2989 /* Start with output sum widgets muted and their output gains at min */
2990 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2991 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2992 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2993 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2994 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2995 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2996 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2997 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2998 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3000 /* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */
3001 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3002 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
3003 * inputs. If the pin mode is changed by the user the pin mode control
3004 * will take care of enabling the pin's input/output buffers as needed.
3005 * Therefore there's no need to enable the input buffer at this
3008 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3009 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3011 /* Mute capture amp left and right */
3012 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3013 /* Set ADC connection select to match default mixer setting - mic
3016 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x00},
3018 /* Do similar with the second ADC: mute capture input amp and
3019 * set ADC connection to line (on line1 pin)
3021 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3022 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x02},
3024 /* Mute all inputs to mixer widget (even unconnected ones) */
3025 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)}, /* mic1 pin */
3026 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)}, /* mic2 pin */
3027 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)}, /* line1 pin */
3028 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)}, /* line2 pin */
3029 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)}, /* CD pin */
3030 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)}, /* Beep-gen pin */
3031 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)}, /* Line-out pin */
3032 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)}, /* HP-pin pin */
3037 /* Test configuration for debugging, modelled after the ALC880 test
3040 #ifdef CONFIG_SND_DEBUG
3041 static hda_nid_t alc260_test_dac_nids
[1] = {
3044 static hda_nid_t alc260_test_adc_nids
[2] = {
3047 /* This is a bit messy since the two input muxes in the ALC260 have slight
3048 * variations in their signal assignments. The ideal way to deal with this
3049 * is to extend alc_spec.input_mux to allow a different input MUX for each
3050 * ADC. For the purposes of the test model it's sufficient to just list
3051 * both options for affected signal indices. The separate input mux
3052 * functionality only needs to be considered if a model comes along which
3053 * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to
3056 static struct hda_input_mux alc260_test_capture_source
= {
3059 { "MIC1 pin", 0x0 },
3060 { "MIC2 pin", 0x1 },
3061 { "LINE1 pin", 0x2 },
3062 { "LINE2 pin", 0x3 },
3064 { "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 },
3065 { "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 },
3066 { "HP-OUT pin (cap2 only)", 0x7 },
3069 static struct snd_kcontrol_new alc260_test_mixer
[] = {
3070 /* Output driver widgets */
3071 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
3072 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT
),
3073 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT
),
3074 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT
),
3075 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT
),
3076 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT
),
3078 /* Modes for retasking pin widgets */
3079 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT
),
3080 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT
),
3081 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT
),
3082 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT
),
3083 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT
),
3084 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT
),
3086 /* Loopback mixer controls */
3087 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT
),
3088 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT
),
3089 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT
),
3090 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT
),
3091 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT
),
3092 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT
),
3093 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT
),
3094 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT
),
3095 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT
),
3096 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT
),
3097 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT
),
3098 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT
),
3099 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT
),
3100 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT
),
3101 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT
),
3102 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT
),
3104 /* Controls for GPIO pins, assuming they are configured as outputs */
3105 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
3106 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
3107 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
3108 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
3110 /* Switches to allow the digital IO pins to be enabled. The datasheet
3111 * is ambigious as to which NID is which; testing on laptops which
3112 * make this output available should provide clarification.
3114 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
3115 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
3119 static struct hda_verb alc260_test_init_verbs
[] = {
3120 /* Enable all GPIOs as outputs with an initial value of 0 */
3121 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x0f},
3122 {0x01, AC_VERB_SET_GPIO_DATA
, 0x00},
3123 {0x01, AC_VERB_SET_GPIO_MASK
, 0x0f},
3125 /* Enable retasking pins as output, initially without power amp */
3126 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3127 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3128 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3129 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3130 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3131 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3133 /* Disable digital (SPDIF) pins initially, but users can enable
3134 * them via a mixer switch. In the case of SPDIF-out, this initverb
3135 * payload also sets the generation to 0, output to be in "consumer"
3136 * PCM format, copyright asserted, no pre-emphasis and no validity
3139 {0x03, AC_VERB_SET_DIGI_CONVERT_1
, 0},
3140 {0x06, AC_VERB_SET_DIGI_CONVERT_1
, 0},
3142 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
3143 * OUT1 sum bus when acting as an output.
3145 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0},
3146 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0},
3147 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0},
3148 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0},
3150 /* Start with output sum widgets muted and their output gains at min */
3151 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3152 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3153 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3154 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3155 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3156 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3157 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3158 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3159 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3161 /* Unmute retasking pin widget output buffers since the default
3162 * state appears to be output. As the pin mode is changed by the
3163 * user the pin mode control will take care of enabling the pin's
3164 * input/output buffers as needed.
3166 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3167 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3168 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3169 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3170 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3171 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3172 /* Also unmute the mono-out pin widget */
3173 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3175 /* Mute capture amp left and right */
3176 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3177 /* Set ADC connection select to match default mixer setting (mic1
3180 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x00},
3182 /* Do the same for the second ADC: mute capture input amp and
3183 * set ADC connection to mic1 pin
3185 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3186 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x00},
3188 /* Mute all inputs to mixer widget (even unconnected ones) */
3189 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)}, /* mic1 pin */
3190 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)}, /* mic2 pin */
3191 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)}, /* line1 pin */
3192 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)}, /* line2 pin */
3193 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)}, /* CD pin */
3194 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)}, /* Beep-gen pin */
3195 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)}, /* Line-out pin */
3196 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)}, /* HP-pin pin */
3202 static struct hda_pcm_stream alc260_pcm_analog_playback
= {
3208 static struct hda_pcm_stream alc260_pcm_analog_capture
= {
3214 #define alc260_pcm_digital_playback alc880_pcm_digital_playback
3215 #define alc260_pcm_digital_capture alc880_pcm_digital_capture
3218 * for BIOS auto-configuration
3221 static int alc260_add_playback_controls(struct alc_spec
*spec
, hda_nid_t nid
,
3225 unsigned long vol_val
, sw_val
;
3229 if (nid
>= 0x0f && nid
< 0x11) {
3230 nid_vol
= nid
- 0x7;
3231 vol_val
= HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0, HDA_OUTPUT
);
3232 sw_val
= HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
);
3233 } else if (nid
== 0x11) {
3234 nid_vol
= nid
- 0x7;
3235 vol_val
= HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0, HDA_OUTPUT
);
3236 sw_val
= HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
);
3237 } else if (nid
>= 0x12 && nid
<= 0x15) {
3239 vol_val
= HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0, HDA_OUTPUT
);
3240 sw_val
= HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
);
3244 snprintf(name
, sizeof(name
), "%s Playback Volume", pfx
);
3245 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, name
, vol_val
)) < 0)
3247 snprintf(name
, sizeof(name
), "%s Playback Switch", pfx
);
3248 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, name
, sw_val
)) < 0)
3253 /* add playback controls from the parsed DAC table */
3254 static int alc260_auto_create_multi_out_ctls(struct alc_spec
*spec
,
3255 const struct auto_pin_cfg
*cfg
)
3260 spec
->multiout
.num_dacs
= 1;
3261 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
3262 spec
->multiout
.dac_nids
[0] = 0x02;
3264 nid
= cfg
->line_out_pins
[0];
3266 err
= alc260_add_playback_controls(spec
, nid
, "Front");
3271 nid
= cfg
->speaker_pin
;
3273 err
= alc260_add_playback_controls(spec
, nid
, "Speaker");
3280 err
= alc260_add_playback_controls(spec
, nid
, "Headphone");
3287 /* create playback/capture controls for input pins */
3288 static int alc260_auto_create_analog_input_ctls(struct alc_spec
*spec
,
3289 const struct auto_pin_cfg
*cfg
)
3291 struct hda_input_mux
*imux
= &spec
->private_imux
;
3294 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
3295 if (cfg
->input_pins
[i
] >= 0x12) {
3296 idx
= cfg
->input_pins
[i
] - 0x12;
3297 err
= new_analog_input(spec
, cfg
->input_pins
[i
],
3298 auto_pin_cfg_labels
[i
], idx
, 0x07);
3301 imux
->items
[imux
->num_items
].label
= auto_pin_cfg_labels
[i
];
3302 imux
->items
[imux
->num_items
].index
= idx
;
3305 if ((cfg
->input_pins
[i
] >= 0x0f) && (cfg
->input_pins
[i
] <= 0x10)){
3306 idx
= cfg
->input_pins
[i
] - 0x09;
3307 err
= new_analog_input(spec
, cfg
->input_pins
[i
],
3308 auto_pin_cfg_labels
[i
], idx
, 0x07);
3311 imux
->items
[imux
->num_items
].label
= auto_pin_cfg_labels
[i
];
3312 imux
->items
[imux
->num_items
].index
= idx
;
3319 static void alc260_auto_set_output_and_unmute(struct hda_codec
*codec
,
3320 hda_nid_t nid
, int pin_type
,
3324 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
3325 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
3326 /* need the manual connection? */
3328 int idx
= nid
- 0x12;
3329 snd_hda_codec_write(codec
, idx
+ 0x0b, 0,
3330 AC_VERB_SET_CONNECT_SEL
, sel_idx
);
3335 static void alc260_auto_init_multi_out(struct hda_codec
*codec
)
3337 struct alc_spec
*spec
= codec
->spec
;
3340 nid
= spec
->autocfg
.line_out_pins
[0];
3342 alc260_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, 0);
3344 nid
= spec
->autocfg
.speaker_pin
;
3346 alc260_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, 0);
3348 nid
= spec
->autocfg
.hp_pin
;
3350 alc260_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, 0);
3353 #define ALC260_PIN_CD_NID 0x16
3354 static void alc260_auto_init_analog_input(struct hda_codec
*codec
)
3356 struct alc_spec
*spec
= codec
->spec
;
3359 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
3360 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
3362 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
3363 i
<= AUTO_PIN_FRONT_MIC
? PIN_VREF80
: PIN_IN
);
3364 if (nid
!= ALC260_PIN_CD_NID
)
3365 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
3372 * generic initialization of ADC, input mixers and output mixers
3374 static struct hda_verb alc260_volume_init_verbs
[] = {
3376 * Unmute ADC0-1 and set the default input to mic-in
3378 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x00},
3379 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3380 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x00},
3381 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3383 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3385 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3388 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3389 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3390 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3391 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
3392 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
3393 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
3396 * Set up output mixers (0x08 - 0x0a)
3398 /* set vol=0 to output mixers */
3399 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3400 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3401 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3402 /* set up input amps for analog loopback */
3403 /* Amp Indices: DAC = 0, mixer = 1 */
3404 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3405 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3406 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3407 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3408 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3409 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3414 static int alc260_parse_auto_config(struct hda_codec
*codec
)
3416 struct alc_spec
*spec
= codec
->spec
;
3419 static hda_nid_t alc260_ignore
[] = { 0x17, 0 };
3421 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
,
3422 alc260_ignore
)) < 0)
3424 if ((err
= alc260_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0)
3426 if (! spec
->kctl_alloc
)
3427 return 0; /* can't find valid BIOS pin config */
3428 if ((err
= alc260_auto_create_analog_input_ctls(spec
, &spec
->autocfg
)) < 0)
3431 spec
->multiout
.max_channels
= 2;
3433 if (spec
->autocfg
.dig_out_pin
)
3434 spec
->multiout
.dig_out_nid
= ALC260_DIGOUT_NID
;
3435 if (spec
->kctl_alloc
)
3436 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
3438 spec
->init_verbs
[spec
->num_init_verbs
++] = alc260_volume_init_verbs
;
3440 spec
->input_mux
= &spec
->private_imux
;
3442 /* check whether NID 0x04 is valid */
3443 wcap
= get_wcaps(codec
, 0x04);
3444 wcap
= (wcap
& AC_WCAP_TYPE
) >> AC_WCAP_TYPE_SHIFT
; /* get type */
3445 if (wcap
!= AC_WID_AUD_IN
) {
3446 spec
->adc_nids
= alc260_adc_nids_alt
;
3447 spec
->num_adc_nids
= ARRAY_SIZE(alc260_adc_nids_alt
);
3448 spec
->mixers
[spec
->num_mixers
] = alc260_capture_alt_mixer
;
3450 spec
->adc_nids
= alc260_adc_nids
;
3451 spec
->num_adc_nids
= ARRAY_SIZE(alc260_adc_nids
);
3452 spec
->mixers
[spec
->num_mixers
] = alc260_capture_mixer
;
3459 /* init callback for auto-configuration model -- overriding the default init */
3460 static int alc260_auto_init(struct hda_codec
*codec
)
3463 alc260_auto_init_multi_out(codec
);
3464 alc260_auto_init_analog_input(codec
);
3469 * ALC260 configurations
3471 static struct hda_board_config alc260_cfg_tbl
[] = {
3472 { .modelname
= "basic", .config
= ALC260_BASIC
},
3473 { .pci_subvendor
= 0x104d, .pci_subdevice
= 0x81bb,
3474 .config
= ALC260_BASIC
}, /* Sony VAIO */
3475 { .modelname
= "hp", .config
= ALC260_HP
},
3476 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3010, .config
= ALC260_HP
},
3477 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3011, .config
= ALC260_HP
},
3478 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3012, .config
= ALC260_HP
},
3479 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3013, .config
= ALC260_HP_3013
},
3480 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3014, .config
= ALC260_HP
},
3481 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3015, .config
= ALC260_HP
},
3482 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3016, .config
= ALC260_HP
},
3483 { .modelname
= "fujitsu", .config
= ALC260_FUJITSU_S702X
},
3484 { .pci_subvendor
= 0x10cf, .pci_subdevice
= 0x1326, .config
= ALC260_FUJITSU_S702X
},
3485 { .modelname
= "acer", .config
= ALC260_ACER
},
3486 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0x008f, .config
= ALC260_ACER
},
3487 #ifdef CONFIG_SND_DEBUG
3488 { .modelname
= "test", .config
= ALC260_TEST
},
3490 { .modelname
= "auto", .config
= ALC260_AUTO
},
3494 static struct alc_config_preset alc260_presets
[] = {
3496 .mixers
= { alc260_base_output_mixer
,
3498 alc260_pc_beep_mixer
,
3499 alc260_capture_mixer
},
3500 .init_verbs
= { alc260_init_verbs
},
3501 .num_dacs
= ARRAY_SIZE(alc260_dac_nids
),
3502 .dac_nids
= alc260_dac_nids
,
3503 .num_adc_nids
= ARRAY_SIZE(alc260_adc_nids
),
3504 .adc_nids
= alc260_adc_nids
,
3505 .num_channel_mode
= ARRAY_SIZE(alc260_modes
),
3506 .channel_mode
= alc260_modes
,
3507 .input_mux
= &alc260_capture_source
,
3510 .mixers
= { alc260_base_output_mixer
,
3512 alc260_capture_alt_mixer
},
3513 .init_verbs
= { alc260_hp_init_verbs
},
3514 .num_dacs
= ARRAY_SIZE(alc260_dac_nids
),
3515 .dac_nids
= alc260_dac_nids
,
3516 .num_adc_nids
= ARRAY_SIZE(alc260_hp_adc_nids
),
3517 .adc_nids
= alc260_hp_adc_nids
,
3518 .num_channel_mode
= ARRAY_SIZE(alc260_modes
),
3519 .channel_mode
= alc260_modes
,
3520 .input_mux
= &alc260_capture_source
,
3522 [ALC260_HP_3013
] = {
3523 .mixers
= { alc260_hp_3013_mixer
,
3525 alc260_capture_alt_mixer
},
3526 .init_verbs
= { alc260_hp_3013_init_verbs
},
3527 .num_dacs
= ARRAY_SIZE(alc260_dac_nids
),
3528 .dac_nids
= alc260_dac_nids
,
3529 .num_adc_nids
= ARRAY_SIZE(alc260_hp_adc_nids
),
3530 .adc_nids
= alc260_hp_adc_nids
,
3531 .num_channel_mode
= ARRAY_SIZE(alc260_modes
),
3532 .channel_mode
= alc260_modes
,
3533 .input_mux
= &alc260_capture_source
,
3535 [ALC260_FUJITSU_S702X
] = {
3536 .mixers
= { alc260_fujitsu_mixer
,
3537 alc260_capture_mixer
},
3538 .init_verbs
= { alc260_fujitsu_init_verbs
},
3539 .num_dacs
= ARRAY_SIZE(alc260_dac_nids
),
3540 .dac_nids
= alc260_dac_nids
,
3541 .num_adc_nids
= ARRAY_SIZE(alc260_dual_adc_nids
),
3542 .adc_nids
= alc260_dual_adc_nids
,
3543 .num_channel_mode
= ARRAY_SIZE(alc260_modes
),
3544 .channel_mode
= alc260_modes
,
3545 .input_mux
= &alc260_fujitsu_capture_source
,
3548 .mixers
= { alc260_acer_mixer
,
3549 alc260_capture_mixer
},
3550 .init_verbs
= { alc260_acer_init_verbs
},
3551 .num_dacs
= ARRAY_SIZE(alc260_dac_nids
),
3552 .dac_nids
= alc260_dac_nids
,
3553 .num_adc_nids
= ARRAY_SIZE(alc260_dual_adc_nids
),
3554 .adc_nids
= alc260_dual_adc_nids
,
3555 .num_channel_mode
= ARRAY_SIZE(alc260_modes
),
3556 .channel_mode
= alc260_modes
,
3557 .input_mux
= &alc260_acer_capture_source
,
3559 #ifdef CONFIG_SND_DEBUG
3561 .mixers
= { alc260_test_mixer
,
3562 alc260_capture_mixer
},
3563 .init_verbs
= { alc260_test_init_verbs
},
3564 .num_dacs
= ARRAY_SIZE(alc260_test_dac_nids
),
3565 .dac_nids
= alc260_test_dac_nids
,
3566 .num_adc_nids
= ARRAY_SIZE(alc260_test_adc_nids
),
3567 .adc_nids
= alc260_test_adc_nids
,
3568 .num_channel_mode
= ARRAY_SIZE(alc260_modes
),
3569 .channel_mode
= alc260_modes
,
3570 .input_mux
= &alc260_test_capture_source
,
3575 static int patch_alc260(struct hda_codec
*codec
)
3577 struct alc_spec
*spec
;
3578 int err
, board_config
;
3580 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
3586 board_config
= snd_hda_check_board_config(codec
, alc260_cfg_tbl
);
3587 if (board_config
< 0 || board_config
>= ALC260_MODEL_LAST
) {
3588 snd_printd(KERN_INFO
"hda_codec: Unknown model for ALC260\n");
3589 board_config
= ALC260_AUTO
;
3592 if (board_config
== ALC260_AUTO
) {
3593 /* automatic parse from the BIOS config */
3594 err
= alc260_parse_auto_config(codec
);
3599 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3600 board_config
= ALC260_BASIC
;
3604 if (board_config
!= ALC260_AUTO
)
3605 setup_preset(spec
, &alc260_presets
[board_config
]);
3607 spec
->stream_name_analog
= "ALC260 Analog";
3608 spec
->stream_analog_playback
= &alc260_pcm_analog_playback
;
3609 spec
->stream_analog_capture
= &alc260_pcm_analog_capture
;
3611 spec
->stream_name_digital
= "ALC260 Digital";
3612 spec
->stream_digital_playback
= &alc260_pcm_digital_playback
;
3613 spec
->stream_digital_capture
= &alc260_pcm_digital_capture
;
3615 codec
->patch_ops
= alc_patch_ops
;
3616 if (board_config
== ALC260_AUTO
)
3617 codec
->patch_ops
.init
= alc260_auto_init
;
3626 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3627 * configuration. Each pin widget can choose any input DACs and a mixer.
3628 * Each ADC is connected from a mixer of all inputs. This makes possible
3629 * 6-channel independent captures.
3631 * In addition, an independent DAC for the multi-playback (not used in this
3634 #define ALC882_DIGOUT_NID 0x06
3635 #define ALC882_DIGIN_NID 0x0a
3637 static struct hda_channel_mode alc882_ch_modes
[1] = {
3641 static hda_nid_t alc882_dac_nids
[4] = {
3642 /* front, rear, clfe, rear_surr */
3643 0x02, 0x03, 0x04, 0x05
3646 /* identical with ALC880 */
3647 #define alc882_adc_nids alc880_adc_nids
3648 #define alc882_adc_nids_alt alc880_adc_nids_alt
3651 /* FIXME: should be a matrix-type input source selection */
3653 static struct hda_input_mux alc882_capture_source
= {
3657 { "Front Mic", 0x1 },
3663 #define alc882_mux_enum_info alc_mux_enum_info
3664 #define alc882_mux_enum_get alc_mux_enum_get
3666 static int alc882_mux_enum_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
3668 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
3669 struct alc_spec
*spec
= codec
->spec
;
3670 const struct hda_input_mux
*imux
= spec
->input_mux
;
3671 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
3672 static hda_nid_t capture_mixers
[3] = { 0x24, 0x23, 0x22 };
3673 hda_nid_t nid
= capture_mixers
[adc_idx
];
3674 unsigned int *cur_val
= &spec
->cur_mux
[adc_idx
];
3675 unsigned int i
, idx
;
3677 idx
= ucontrol
->value
.enumerated
.item
[0];
3678 if (idx
>= imux
->num_items
)
3679 idx
= imux
->num_items
- 1;
3680 if (*cur_val
== idx
&& ! codec
->in_resume
)
3682 for (i
= 0; i
< imux
->num_items
; i
++) {
3683 unsigned int v
= (i
== idx
) ? 0x7000 : 0x7080;
3684 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
3685 v
| (imux
->items
[i
].index
<< 8));
3694 static struct hda_verb alc882_sixstack_ch6_init
[] = {
3695 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x00 },
3696 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3697 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3698 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3705 static struct hda_verb alc882_sixstack_ch8_init
[] = {
3706 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3707 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3708 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3709 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3713 static struct hda_channel_mode alc882_sixstack_modes
[2] = {
3714 { 6, alc882_sixstack_ch6_init
},
3715 { 8, alc882_sixstack_ch8_init
},
3718 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
3719 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
3721 static struct snd_kcontrol_new alc882_base_mixer
[] = {
3722 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
3723 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
3724 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
3725 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
3726 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
3727 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
3728 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
3729 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
3730 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
3731 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT
),
3732 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
3733 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
3734 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
3735 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
3736 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
3737 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
3738 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
3739 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT
),
3740 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT
),
3741 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
3742 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
3743 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
3744 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
3745 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
3746 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
3747 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT
),
3748 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT
),
3750 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3751 /* .name = "Capture Source", */
3752 .name
= "Input Source",
3754 .info
= alc882_mux_enum_info
,
3755 .get
= alc882_mux_enum_get
,
3756 .put
= alc882_mux_enum_put
,
3761 static struct snd_kcontrol_new alc882_chmode_mixer
[] = {
3763 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3764 .name
= "Channel Mode",
3765 .info
= alc_ch_mode_info
,
3766 .get
= alc_ch_mode_get
,
3767 .put
= alc_ch_mode_put
,
3772 static struct hda_verb alc882_init_verbs
[] = {
3773 /* Front mixer: unmute input/output amp left and right (volume = 0) */
3774 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3775 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3776 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3778 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3779 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3780 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3782 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3783 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3784 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3786 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3787 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3788 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3790 /* Front Pin: output 0 (0x0c) */
3791 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3792 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3793 {0x14, AC_VERB_SET_CONNECT_SEL
, 0x00},
3794 /* Rear Pin: output 1 (0x0d) */
3795 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3796 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3797 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x01},
3798 /* CLFE Pin: output 2 (0x0e) */
3799 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3800 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3801 {0x16, AC_VERB_SET_CONNECT_SEL
, 0x02},
3802 /* Side Pin: output 3 (0x0f) */
3803 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3804 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3805 {0x17, AC_VERB_SET_CONNECT_SEL
, 0x03},
3806 /* Mic (rear) pin: input vref at 80% */
3807 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3808 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3809 /* Front Mic pin: input vref at 80% */
3810 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3811 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3812 /* Line In pin: input */
3813 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
3814 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3815 /* Line-2 In: Headphone output (output 0 - 0x0c) */
3816 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3817 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3818 {0x1b, AC_VERB_SET_CONNECT_SEL
, 0x00},
3819 /* CD pin widget for input */
3820 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
3822 /* FIXME: use matrix-type input source selection */
3823 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3824 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3825 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3826 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3827 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3828 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3830 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3831 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3832 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3833 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3835 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3836 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3837 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3838 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3839 /* ADC1: mute amp left and right */
3840 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3841 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
3842 /* ADC2: mute amp left and right */
3843 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3844 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
3845 /* ADC3: mute amp left and right */
3846 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3847 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
3853 * generic initialization of ADC, input mixers and output mixers
3855 static struct hda_verb alc882_auto_init_verbs
[] = {
3857 * Unmute ADC0-2 and set the default input to mic-in
3859 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
3860 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3861 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
3862 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3863 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
3864 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3866 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3868 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3871 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3872 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3873 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3874 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
3875 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
3876 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
3879 * Set up output mixers (0x0c - 0x0f)
3881 /* set vol=0 to output mixers */
3882 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3883 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3884 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3885 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3886 /* set up input amps for analog loopback */
3887 /* Amp Indices: DAC = 0, mixer = 1 */
3888 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3889 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3890 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3891 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3892 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3893 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3894 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3895 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3896 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3897 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3899 /* FIXME: use matrix-type input source selection */
3900 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3901 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3902 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3903 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3904 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3905 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3907 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3908 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3909 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3910 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3912 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3913 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3914 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3915 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3920 /* capture mixer elements */
3921 static struct snd_kcontrol_new alc882_capture_alt_mixer
[] = {
3922 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
3923 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
3924 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT
),
3925 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT
),
3927 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3928 /* The multiple "Capture Source" controls confuse alsamixer
3929 * So call somewhat different..
3930 * FIXME: the controls appear in the "playback" view!
3932 /* .name = "Capture Source", */
3933 .name
= "Input Source",
3935 .info
= alc882_mux_enum_info
,
3936 .get
= alc882_mux_enum_get
,
3937 .put
= alc882_mux_enum_put
,
3942 static struct snd_kcontrol_new alc882_capture_mixer
[] = {
3943 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
3944 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
3945 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
3946 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
3947 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT
),
3948 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT
),
3950 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3951 /* The multiple "Capture Source" controls confuse alsamixer
3952 * So call somewhat different..
3953 * FIXME: the controls appear in the "playback" view!
3955 /* .name = "Capture Source", */
3956 .name
= "Input Source",
3958 .info
= alc882_mux_enum_info
,
3959 .get
= alc882_mux_enum_get
,
3960 .put
= alc882_mux_enum_put
,
3965 /* pcm configuration: identiacal with ALC880 */
3966 #define alc882_pcm_analog_playback alc880_pcm_analog_playback
3967 #define alc882_pcm_analog_capture alc880_pcm_analog_capture
3968 #define alc882_pcm_digital_playback alc880_pcm_digital_playback
3969 #define alc882_pcm_digital_capture alc880_pcm_digital_capture
3972 * configuration and preset
3974 static struct hda_board_config alc882_cfg_tbl
[] = {
3975 { .modelname
= "3stack-dig", .config
= ALC882_3ST_DIG
},
3976 { .modelname
= "6stack-dig", .config
= ALC882_6ST_DIG
},
3977 { .pci_subvendor
= 0x1462, .pci_subdevice
= 0x6668, .config
= ALC882_6ST_DIG
}, /* MSI */
3978 { .pci_subvendor
= 0x105b, .pci_subdevice
= 0x6668, .config
= ALC882_6ST_DIG
}, /* Foxconn */
3979 { .pci_subvendor
= 0x1019, .pci_subdevice
= 0x6668, .config
= ALC882_6ST_DIG
}, /* ECS */
3980 { .modelname
= "auto", .config
= ALC882_AUTO
},
3984 static struct alc_config_preset alc882_presets
[] = {
3985 [ALC882_3ST_DIG
] = {
3986 .mixers
= { alc882_base_mixer
},
3987 .init_verbs
= { alc882_init_verbs
},
3988 .num_dacs
= ARRAY_SIZE(alc882_dac_nids
),
3989 .dac_nids
= alc882_dac_nids
,
3990 .dig_out_nid
= ALC882_DIGOUT_NID
,
3991 .num_adc_nids
= ARRAY_SIZE(alc882_adc_nids
),
3992 .adc_nids
= alc882_adc_nids
,
3993 .dig_in_nid
= ALC882_DIGIN_NID
,
3994 .num_channel_mode
= ARRAY_SIZE(alc882_ch_modes
),
3995 .channel_mode
= alc882_ch_modes
,
3996 .input_mux
= &alc882_capture_source
,
3998 [ALC882_6ST_DIG
] = {
3999 .mixers
= { alc882_base_mixer
, alc882_chmode_mixer
},
4000 .init_verbs
= { alc882_init_verbs
},
4001 .num_dacs
= ARRAY_SIZE(alc882_dac_nids
),
4002 .dac_nids
= alc882_dac_nids
,
4003 .dig_out_nid
= ALC882_DIGOUT_NID
,
4004 .num_adc_nids
= ARRAY_SIZE(alc882_adc_nids
),
4005 .adc_nids
= alc882_adc_nids
,
4006 .dig_in_nid
= ALC882_DIGIN_NID
,
4007 .num_channel_mode
= ARRAY_SIZE(alc882_sixstack_modes
),
4008 .channel_mode
= alc882_sixstack_modes
,
4009 .input_mux
= &alc882_capture_source
,
4015 * BIOS auto configuration
4017 static void alc882_auto_set_output_and_unmute(struct hda_codec
*codec
,
4018 hda_nid_t nid
, int pin_type
,
4022 struct alc_spec
*spec
= codec
->spec
;
4025 if (spec
->multiout
.dac_nids
[dac_idx
] == 0x25)
4028 idx
= spec
->multiout
.dac_nids
[dac_idx
] - 2;
4030 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
4031 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
4032 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_CONNECT_SEL
, idx
);
4036 static void alc882_auto_init_multi_out(struct hda_codec
*codec
)
4038 struct alc_spec
*spec
= codec
->spec
;
4041 for (i
= 0; i
<= HDA_SIDE
; i
++) {
4042 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
4044 alc882_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
4048 static void alc882_auto_init_hp_out(struct hda_codec
*codec
)
4050 struct alc_spec
*spec
= codec
->spec
;
4053 pin
= spec
->autocfg
.hp_pin
;
4054 if (pin
) /* connect to front */
4055 alc882_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0); /* use dac 0 */
4058 #define alc882_is_input_pin(nid) alc880_is_input_pin(nid)
4059 #define ALC882_PIN_CD_NID ALC880_PIN_CD_NID
4061 static void alc882_auto_init_analog_input(struct hda_codec
*codec
)
4063 struct alc_spec
*spec
= codec
->spec
;
4066 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
4067 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
4068 if (alc882_is_input_pin(nid
)) {
4069 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
4070 i
<= AUTO_PIN_FRONT_MIC
? PIN_VREF80
: PIN_IN
);
4071 if (nid
!= ALC882_PIN_CD_NID
)
4072 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
4078 /* almost identical with ALC880 parser... */
4079 static int alc882_parse_auto_config(struct hda_codec
*codec
)
4081 struct alc_spec
*spec
= codec
->spec
;
4082 int err
= alc880_parse_auto_config(codec
);
4087 /* hack - override the init verbs */
4088 spec
->init_verbs
[0] = alc882_auto_init_verbs
;
4092 /* init callback for auto-configuration model -- overriding the default init */
4093 static int alc882_auto_init(struct hda_codec
*codec
)
4096 alc882_auto_init_multi_out(codec
);
4097 alc882_auto_init_hp_out(codec
);
4098 alc882_auto_init_analog_input(codec
);
4103 * ALC882 Headphone poll in 3.5.1a or 3.5.2
4106 static int patch_alc882(struct hda_codec
*codec
)
4108 struct alc_spec
*spec
;
4109 int err
, board_config
;
4111 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
4117 board_config
= snd_hda_check_board_config(codec
, alc882_cfg_tbl
);
4119 if (board_config
< 0 || board_config
>= ALC882_MODEL_LAST
) {
4120 printk(KERN_INFO
"hda_codec: Unknown model for ALC882, trying auto-probe from BIOS...\n");
4121 board_config
= ALC882_AUTO
;
4124 if (board_config
== ALC882_AUTO
) {
4125 /* automatic parse from the BIOS config */
4126 err
= alc882_parse_auto_config(codec
);
4131 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
4132 board_config
= ALC882_3ST_DIG
;
4136 if (board_config
!= ALC882_AUTO
)
4137 setup_preset(spec
, &alc882_presets
[board_config
]);
4139 spec
->stream_name_analog
= "ALC882 Analog";
4140 spec
->stream_analog_playback
= &alc882_pcm_analog_playback
;
4141 spec
->stream_analog_capture
= &alc882_pcm_analog_capture
;
4143 spec
->stream_name_digital
= "ALC882 Digital";
4144 spec
->stream_digital_playback
= &alc882_pcm_digital_playback
;
4145 spec
->stream_digital_capture
= &alc882_pcm_digital_capture
;
4147 if (! spec
->adc_nids
&& spec
->input_mux
) {
4148 /* check whether NID 0x07 is valid */
4149 unsigned int wcap
= get_wcaps(codec
, 0x07);
4150 wcap
= (wcap
& AC_WCAP_TYPE
) >> AC_WCAP_TYPE_SHIFT
; /* get type */
4151 if (wcap
!= AC_WID_AUD_IN
) {
4152 spec
->adc_nids
= alc882_adc_nids_alt
;
4153 spec
->num_adc_nids
= ARRAY_SIZE(alc882_adc_nids_alt
);
4154 spec
->mixers
[spec
->num_mixers
] = alc882_capture_alt_mixer
;
4157 spec
->adc_nids
= alc882_adc_nids
;
4158 spec
->num_adc_nids
= ARRAY_SIZE(alc882_adc_nids
);
4159 spec
->mixers
[spec
->num_mixers
] = alc882_capture_mixer
;
4164 codec
->patch_ops
= alc_patch_ops
;
4165 if (board_config
== ALC882_AUTO
)
4166 codec
->patch_ops
.init
= alc882_auto_init
;
4175 #define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
4176 #define ALC262_DIGIN_NID ALC880_DIGIN_NID
4178 #define alc262_dac_nids alc260_dac_nids
4179 #define alc262_adc_nids alc882_adc_nids
4180 #define alc262_adc_nids_alt alc882_adc_nids_alt
4182 #define alc262_modes alc260_modes
4183 #define alc262_capture_source alc882_capture_source
4185 static struct snd_kcontrol_new alc262_base_mixer
[] = {
4186 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
4187 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT
),
4188 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
4189 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
4190 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
4191 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
4192 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
4193 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
4194 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT
),
4195 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT
),
4196 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
4197 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
4198 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT
),
4199 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
4200 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
4201 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT
),
4205 #define alc262_capture_mixer alc882_capture_mixer
4206 #define alc262_capture_alt_mixer alc882_capture_alt_mixer
4209 * generic initialization of ADC, input mixers and output mixers
4211 static struct hda_verb alc262_init_verbs
[] = {
4213 * Unmute ADC0-2 and set the default input to mic-in
4215 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
4216 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4217 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
4218 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4219 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
4220 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4222 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4224 * Note: PASD motherboards uses the Line In 2 as the input for front panel
4227 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
4228 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4229 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4230 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4231 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
4232 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
4235 * Set up output mixers (0x0c - 0x0e)
4237 /* set vol=0 to output mixers */
4238 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4239 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4240 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4241 /* set up input amps for analog loopback */
4242 /* Amp Indices: DAC = 0, mixer = 1 */
4243 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4244 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4245 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4246 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4247 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4248 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4250 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
4251 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0},
4252 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
4253 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24},
4254 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
4255 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
4257 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
4258 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
4259 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
4260 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
4261 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
4263 {0x14, AC_VERB_SET_CONNECT_SEL
, 0x00},
4264 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x01},
4266 /* FIXME: use matrix-type input source selection */
4267 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4268 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4269 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
4270 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
4271 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
4272 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
4274 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
4275 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
4276 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
4277 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
4279 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
4280 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
4281 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
4282 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
4289 * 0x14 = headphone/spdif-out, 0x15 = internal speaker
4292 #define ALC_HP_EVENT 0x37
4294 static struct hda_verb alc262_fujitsu_unsol_verbs
[] = {
4295 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| ALC_HP_EVENT
},
4296 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4300 static struct hda_input_mux alc262_fujitsu_capture_source
= {
4308 /* mute/unmute internal speaker according to the hp jack and mute state */
4309 static void alc262_fujitsu_automute(struct hda_codec
*codec
, int force
)
4311 struct alc_spec
*spec
= codec
->spec
;
4314 if (force
|| ! spec
->sense_updated
) {
4315 unsigned int present
;
4316 /* need to execute and sync at first */
4317 snd_hda_codec_read(codec
, 0x14, 0, AC_VERB_SET_PIN_SENSE
, 0);
4318 present
= snd_hda_codec_read(codec
, 0x14, 0,
4319 AC_VERB_GET_PIN_SENSE
, 0);
4320 spec
->jack_present
= (present
& 0x80000000) != 0;
4321 spec
->sense_updated
= 1;
4323 if (spec
->jack_present
) {
4324 /* mute internal speaker */
4325 snd_hda_codec_amp_update(codec
, 0x15, 0, HDA_OUTPUT
, 0,
4327 snd_hda_codec_amp_update(codec
, 0x15, 1, HDA_OUTPUT
, 0,
4330 /* unmute internal speaker if necessary */
4331 mute
= snd_hda_codec_amp_read(codec
, 0x14, 0, HDA_OUTPUT
, 0);
4332 snd_hda_codec_amp_update(codec
, 0x15, 0, HDA_OUTPUT
, 0,
4334 mute
= snd_hda_codec_amp_read(codec
, 0x14, 1, HDA_OUTPUT
, 0);
4335 snd_hda_codec_amp_update(codec
, 0x15, 1, HDA_OUTPUT
, 0,
4340 /* unsolicited event for HP jack sensing */
4341 static void alc262_fujitsu_unsol_event(struct hda_codec
*codec
,
4344 if ((res
>> 26) != ALC_HP_EVENT
)
4346 alc262_fujitsu_automute(codec
, 1);
4349 /* bind volumes of both NID 0x0c and 0x0d */
4350 static int alc262_fujitsu_master_vol_put(struct snd_kcontrol
*kcontrol
,
4351 struct snd_ctl_elem_value
*ucontrol
)
4353 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
4354 long *valp
= ucontrol
->value
.integer
.value
;
4357 change
= snd_hda_codec_amp_update(codec
, 0x0c, 0, HDA_OUTPUT
, 0,
4358 0x7f, valp
[0] & 0x7f);
4359 change
|= snd_hda_codec_amp_update(codec
, 0x0c, 1, HDA_OUTPUT
, 0,
4360 0x7f, valp
[1] & 0x7f);
4361 snd_hda_codec_amp_update(codec
, 0x0d, 0, HDA_OUTPUT
, 0,
4362 0x7f, valp
[0] & 0x7f);
4363 snd_hda_codec_amp_update(codec
, 0x0d, 1, HDA_OUTPUT
, 0,
4364 0x7f, valp
[1] & 0x7f);
4368 /* bind hp and internal speaker mute (with plug check) */
4369 static int alc262_fujitsu_master_sw_put(struct snd_kcontrol
*kcontrol
,
4370 struct snd_ctl_elem_value
*ucontrol
)
4372 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
4373 long *valp
= ucontrol
->value
.integer
.value
;
4376 change
= snd_hda_codec_amp_update(codec
, 0x14, 0, HDA_OUTPUT
, 0,
4377 0x80, valp
[0] ? 0 : 0x80);
4378 change
|= snd_hda_codec_amp_update(codec
, 0x14, 1, HDA_OUTPUT
, 0,
4379 0x80, valp
[1] ? 0 : 0x80);
4380 if (change
|| codec
->in_resume
)
4381 alc262_fujitsu_automute(codec
, codec
->in_resume
);
4385 static struct snd_kcontrol_new alc262_fujitsu_mixer
[] = {
4387 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4388 .name
= "Master Playback Volume",
4389 .info
= snd_hda_mixer_amp_volume_info
,
4390 .get
= snd_hda_mixer_amp_volume_get
,
4391 .put
= alc262_fujitsu_master_vol_put
,
4392 .private_value
= HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT
),
4395 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4396 .name
= "Master Playback Switch",
4397 .info
= snd_hda_mixer_amp_switch_info
,
4398 .get
= snd_hda_mixer_amp_switch_get
,
4399 .put
= alc262_fujitsu_master_sw_put
,
4400 .private_value
= HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT
),
4402 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
4403 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
4404 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT
),
4405 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
4406 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
4410 /* add playback controls from the parsed DAC table */
4411 static int alc262_auto_create_multi_out_ctls(struct alc_spec
*spec
, const struct auto_pin_cfg
*cfg
)
4416 spec
->multiout
.num_dacs
= 1; /* only use one dac */
4417 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
4418 spec
->multiout
.dac_nids
[0] = 2;
4420 nid
= cfg
->line_out_pins
[0];
4422 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Front Playback Volume",
4423 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT
))) < 0)
4425 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Front Playback Switch",
4426 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
4430 nid
= cfg
->speaker_pin
;
4433 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Speaker Playback Volume",
4434 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT
))) < 0)
4436 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Speaker Playback Switch",
4437 HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
))) < 0)
4440 if (! cfg
->line_out_pins
[0])
4441 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Speaker Playback Volume",
4442 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT
))) < 0)
4444 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Speaker Playback Switch",
4445 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
4451 /* spec->multiout.hp_nid = 2; */
4453 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Headphone Playback Volume",
4454 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT
))) < 0)
4456 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Headphone Playback Switch",
4457 HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
))) < 0)
4460 if (! cfg
->line_out_pins
[0])
4461 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Headphone Playback Volume",
4462 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT
))) < 0)
4464 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Headphone Playback Switch",
4465 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
4472 /* identical with ALC880 */
4473 #define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls
4476 * generic initialization of ADC, input mixers and output mixers
4478 static struct hda_verb alc262_volume_init_verbs
[] = {
4480 * Unmute ADC0-2 and set the default input to mic-in
4482 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
4483 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4484 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
4485 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4486 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
4487 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4489 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4491 * Note: PASD motherboards uses the Line In 2 as the input for front panel
4494 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
4495 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4496 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4497 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4498 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
4499 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
4502 * Set up output mixers (0x0c - 0x0f)
4504 /* set vol=0 to output mixers */
4505 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4506 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4507 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4509 /* set up input amps for analog loopback */
4510 /* Amp Indices: DAC = 0, mixer = 1 */
4511 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4512 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4513 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4514 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4515 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4516 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4518 /* FIXME: use matrix-type input source selection */
4519 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4520 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4521 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
4522 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
4523 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
4524 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
4526 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
4527 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
4528 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
4529 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
4531 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
4532 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
4533 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
4534 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
4539 /* pcm configuration: identiacal with ALC880 */
4540 #define alc262_pcm_analog_playback alc880_pcm_analog_playback
4541 #define alc262_pcm_analog_capture alc880_pcm_analog_capture
4542 #define alc262_pcm_digital_playback alc880_pcm_digital_playback
4543 #define alc262_pcm_digital_capture alc880_pcm_digital_capture
4546 * BIOS auto configuration
4548 static int alc262_parse_auto_config(struct hda_codec
*codec
)
4550 struct alc_spec
*spec
= codec
->spec
;
4552 static hda_nid_t alc262_ignore
[] = { 0x1d, 0 };
4554 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
,
4555 alc262_ignore
)) < 0)
4557 if (! spec
->autocfg
.line_outs
&& ! spec
->autocfg
.speaker_pin
&&
4558 ! spec
->autocfg
.hp_pin
)
4559 return 0; /* can't find valid BIOS pin config */
4560 if ((err
= alc262_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
4561 (err
= alc262_auto_create_analog_input_ctls(spec
, &spec
->autocfg
)) < 0)
4564 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
4566 if (spec
->autocfg
.dig_out_pin
)
4567 spec
->multiout
.dig_out_nid
= ALC262_DIGOUT_NID
;
4568 if (spec
->autocfg
.dig_in_pin
)
4569 spec
->dig_in_nid
= ALC262_DIGIN_NID
;
4571 if (spec
->kctl_alloc
)
4572 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
4574 spec
->init_verbs
[spec
->num_init_verbs
++] = alc262_volume_init_verbs
;
4575 spec
->input_mux
= &spec
->private_imux
;
4580 #define alc262_auto_init_multi_out alc882_auto_init_multi_out
4581 #define alc262_auto_init_hp_out alc882_auto_init_hp_out
4582 #define alc262_auto_init_analog_input alc882_auto_init_analog_input
4585 /* init callback for auto-configuration model -- overriding the default init */
4586 static int alc262_auto_init(struct hda_codec
*codec
)
4589 alc262_auto_init_multi_out(codec
);
4590 alc262_auto_init_hp_out(codec
);
4591 alc262_auto_init_analog_input(codec
);
4596 * configuration and preset
4598 static struct hda_board_config alc262_cfg_tbl
[] = {
4599 { .modelname
= "basic", .config
= ALC262_BASIC
},
4600 { .modelname
= "fujitsu", .config
= ALC262_FUJITSU
},
4601 { .pci_subvendor
= 0x10cf, .pci_subdevice
= 0x1397, .config
= ALC262_FUJITSU
},
4602 { .modelname
= "auto", .config
= ALC262_AUTO
},
4606 static struct alc_config_preset alc262_presets
[] = {
4608 .mixers
= { alc262_base_mixer
},
4609 .init_verbs
= { alc262_init_verbs
},
4610 .num_dacs
= ARRAY_SIZE(alc262_dac_nids
),
4611 .dac_nids
= alc262_dac_nids
,
4613 .num_channel_mode
= ARRAY_SIZE(alc262_modes
),
4614 .channel_mode
= alc262_modes
,
4615 .input_mux
= &alc262_capture_source
,
4617 [ALC262_FUJITSU
] = {
4618 .mixers
= { alc262_fujitsu_mixer
},
4619 .init_verbs
= { alc262_init_verbs
, alc262_fujitsu_unsol_verbs
},
4620 .num_dacs
= ARRAY_SIZE(alc262_dac_nids
),
4621 .dac_nids
= alc262_dac_nids
,
4623 .dig_out_nid
= ALC262_DIGOUT_NID
,
4624 .num_channel_mode
= ARRAY_SIZE(alc262_modes
),
4625 .channel_mode
= alc262_modes
,
4626 .input_mux
= &alc262_fujitsu_capture_source
,
4630 static int patch_alc262(struct hda_codec
*codec
)
4632 struct alc_spec
*spec
;
4636 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
4642 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is under-run */
4645 snd_hda_codec_write(codec
, 0x1a, 0, AC_VERB_SET_COEF_INDEX
, 7);
4646 tmp
= snd_hda_codec_read(codec
, 0x20, 0, AC_VERB_GET_PROC_COEF
, 0);
4647 snd_hda_codec_write(codec
, 0x1a, 0, AC_VERB_SET_COEF_INDEX
, 7);
4648 snd_hda_codec_write(codec
, 0x1a, 0, AC_VERB_SET_PROC_COEF
, tmp
| 0x80);
4652 board_config
= snd_hda_check_board_config(codec
, alc262_cfg_tbl
);
4653 if (board_config
< 0 || board_config
>= ALC262_MODEL_LAST
) {
4654 printk(KERN_INFO
"hda_codec: Unknown model for ALC262, trying auto-probe from BIOS...\n");
4655 board_config
= ALC262_AUTO
;
4658 if (board_config
== ALC262_AUTO
) {
4659 /* automatic parse from the BIOS config */
4660 err
= alc262_parse_auto_config(codec
);
4665 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
4666 board_config
= ALC262_BASIC
;
4670 if (board_config
!= ALC262_AUTO
)
4671 setup_preset(spec
, &alc262_presets
[board_config
]);
4673 spec
->stream_name_analog
= "ALC262 Analog";
4674 spec
->stream_analog_playback
= &alc262_pcm_analog_playback
;
4675 spec
->stream_analog_capture
= &alc262_pcm_analog_capture
;
4677 spec
->stream_name_digital
= "ALC262 Digital";
4678 spec
->stream_digital_playback
= &alc262_pcm_digital_playback
;
4679 spec
->stream_digital_capture
= &alc262_pcm_digital_capture
;
4681 if (! spec
->adc_nids
&& spec
->input_mux
) {
4682 /* check whether NID 0x07 is valid */
4683 unsigned int wcap
= get_wcaps(codec
, 0x07);
4685 wcap
= (wcap
& AC_WCAP_TYPE
) >> AC_WCAP_TYPE_SHIFT
; /* get type */
4686 if (wcap
!= AC_WID_AUD_IN
) {
4687 spec
->adc_nids
= alc262_adc_nids_alt
;
4688 spec
->num_adc_nids
= ARRAY_SIZE(alc262_adc_nids_alt
);
4689 spec
->mixers
[spec
->num_mixers
] = alc262_capture_alt_mixer
;
4692 spec
->adc_nids
= alc262_adc_nids
;
4693 spec
->num_adc_nids
= ARRAY_SIZE(alc262_adc_nids
);
4694 spec
->mixers
[spec
->num_mixers
] = alc262_capture_mixer
;
4699 codec
->patch_ops
= alc_patch_ops
;
4700 if (board_config
== ALC262_AUTO
)
4701 codec
->patch_ops
.init
= alc262_auto_init
;
4702 if (board_config
== ALC262_FUJITSU
)
4703 codec
->patch_ops
.unsol_event
= alc262_fujitsu_unsol_event
;
4710 * ALC861 channel source setting (2/6 channel selection for 3-stack)
4714 * set the path ways for 2 channel output
4715 * need to set the codec line out and mic 1 pin widgets to inputs
4717 static struct hda_verb alc861_threestack_ch2_init
[] = {
4718 /* set pin widget 1Ah (line in) for input */
4719 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
4720 /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
4721 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
4723 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb00c },
4724 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8)) }, //mic
4725 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x02 << 8)) }, //line in
4730 * need to set the codec line out and mic 1 pin widgets to outputs
4732 static struct hda_verb alc861_threestack_ch6_init
[] = {
4733 /* set pin widget 1Ah (line in) for output (Back Surround)*/
4734 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4735 /* set pin widget 18h (mic1) for output (CLFE)*/
4736 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4738 { 0x0c, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4739 { 0x0d, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4741 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080 },
4742 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x01 << 8)) }, //mic
4743 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8)) }, //line in
4747 static struct hda_channel_mode alc861_threestack_modes
[2] = {
4748 { 2, alc861_threestack_ch2_init
},
4749 { 6, alc861_threestack_ch6_init
},
4754 static struct snd_kcontrol_new alc861_base_mixer
[] = {
4755 /* output mixer control */
4756 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT
),
4757 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
4758 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT
),
4759 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT
),
4760 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT
),
4762 /*Input mixer control */
4763 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4764 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4765 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT
),
4766 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT
),
4767 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT
),
4768 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT
),
4769 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT
),
4770 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT
),
4771 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT
),
4772 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT
),
4774 /* Capture mixer control */
4775 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
4776 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
4778 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4779 .name
= "Capture Source",
4781 .info
= alc_mux_enum_info
,
4782 .get
= alc_mux_enum_get
,
4783 .put
= alc_mux_enum_put
,
4788 static struct snd_kcontrol_new alc861_3ST_mixer
[] = {
4789 /* output mixer control */
4790 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT
),
4791 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
4792 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT
),
4793 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT
),
4794 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
4796 /* Input mixer control */
4797 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4798 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4799 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT
),
4800 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT
),
4801 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT
),
4802 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT
),
4803 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT
),
4804 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT
),
4805 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT
),
4806 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT
),
4808 /* Capture mixer control */
4809 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
4810 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
4812 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4813 .name
= "Capture Source",
4815 .info
= alc_mux_enum_info
,
4816 .get
= alc_mux_enum_get
,
4817 .put
= alc_mux_enum_put
,
4820 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4821 .name
= "Channel Mode",
4822 .info
= alc_ch_mode_info
,
4823 .get
= alc_ch_mode_get
,
4824 .put
= alc_ch_mode_put
,
4825 .private_value
= ARRAY_SIZE(alc861_threestack_modes
),
4831 * generic initialization of ADC, input mixers and output mixers
4833 static struct hda_verb alc861_base_init_verbs
[] = {
4835 * Unmute ADC0 and set the default input to mic-in
4837 /* port-A for surround (rear panel) */
4838 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4839 { 0x0e, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4840 /* port-B for mic-in (rear panel) with vref */
4841 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
4842 /* port-C for line-in (rear panel) */
4843 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
4844 /* port-D for Front */
4845 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4846 { 0x0b, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4847 /* port-E for HP out (front panel) */
4848 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
4849 /* route front PCM to HP */
4850 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x01 },
4851 /* port-F for mic-in (front panel) with vref */
4852 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
4853 /* port-G for CLFE (rear panel) */
4854 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4855 { 0x1f, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4856 /* port-H for side (rear panel) */
4857 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4858 { 0x20, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4860 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
4861 /* route front mic to ADC1*/
4862 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
4863 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4865 /* Unmute DAC0~3 & spdif out*/
4866 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4867 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4868 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4869 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4870 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4872 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4873 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4874 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4875 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4876 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4878 /* Unmute Stereo Mixer 15 */
4879 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4880 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4881 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4882 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb00c }, //Output 0~12 step
4884 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4885 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4886 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4887 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4888 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4889 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4890 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4891 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4892 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4893 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4898 static struct hda_verb alc861_threestack_init_verbs
[] = {
4900 * Unmute ADC0 and set the default input to mic-in
4902 /* port-A for surround (rear panel) */
4903 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x00 },
4904 /* port-B for mic-in (rear panel) with vref */
4905 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
4906 /* port-C for line-in (rear panel) */
4907 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
4908 /* port-D for Front */
4909 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4910 { 0x0b, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4911 /* port-E for HP out (front panel) */
4912 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
4913 /* route front PCM to HP */
4914 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x01 },
4915 /* port-F for mic-in (front panel) with vref */
4916 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
4917 /* port-G for CLFE (rear panel) */
4918 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x00 },
4919 /* port-H for side (rear panel) */
4920 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x00 },
4922 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
4923 /* route front mic to ADC1*/
4924 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
4925 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4926 /* Unmute DAC0~3 & spdif out*/
4927 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4928 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4929 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4930 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4931 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4933 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4934 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4935 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4936 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4937 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4939 /* Unmute Stereo Mixer 15 */
4940 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4941 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4942 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4943 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb00c }, //Output 0~12 step
4945 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4946 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4947 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4948 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4949 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4950 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4951 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4952 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4953 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4954 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4958 * generic initialization of ADC, input mixers and output mixers
4960 static struct hda_verb alc861_auto_init_verbs
[] = {
4962 * Unmute ADC0 and set the default input to mic-in
4964 // {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4965 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4967 /* Unmute DAC0~3 & spdif out*/
4968 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4969 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4970 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4971 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4972 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4974 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4975 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4976 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4977 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4978 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4980 /* Unmute Stereo Mixer 15 */
4981 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4982 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4983 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4984 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb00c},
4986 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4987 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4988 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4989 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4990 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4991 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4992 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4993 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4995 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4996 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4997 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4998 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
4999 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
5000 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
5001 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
5002 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
5004 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00}, // set Mic 1
5009 /* pcm configuration: identiacal with ALC880 */
5010 #define alc861_pcm_analog_playback alc880_pcm_analog_playback
5011 #define alc861_pcm_analog_capture alc880_pcm_analog_capture
5012 #define alc861_pcm_digital_playback alc880_pcm_digital_playback
5013 #define alc861_pcm_digital_capture alc880_pcm_digital_capture
5016 #define ALC861_DIGOUT_NID 0x07
5018 static struct hda_channel_mode alc861_8ch_modes
[1] = {
5022 static hda_nid_t alc861_dac_nids
[4] = {
5023 /* front, surround, clfe, side */
5024 0x03, 0x06, 0x05, 0x04
5027 static hda_nid_t alc861_adc_nids
[1] = {
5032 static struct hda_input_mux alc861_capture_source
= {
5036 { "Front Mic", 0x3 },
5043 /* fill in the dac_nids table from the parsed pin configuration */
5044 static int alc861_auto_fill_dac_nids(struct alc_spec
*spec
, const struct auto_pin_cfg
*cfg
)
5049 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
5050 for (i
= 0; i
< cfg
->line_outs
; i
++) {
5051 nid
= cfg
->line_out_pins
[i
];
5053 if (i
>= ARRAY_SIZE(alc861_dac_nids
))
5055 spec
->multiout
.dac_nids
[i
] = alc861_dac_nids
[i
];
5058 spec
->multiout
.num_dacs
= cfg
->line_outs
;
5062 /* add playback controls from the parsed DAC table */
5063 static int alc861_auto_create_multi_out_ctls(struct alc_spec
*spec
,
5064 const struct auto_pin_cfg
*cfg
)
5067 static const char *chname
[4] = { "Front", "Surround", NULL
/*CLFE*/, "Side" };
5071 for (i
= 0; i
< cfg
->line_outs
; i
++) {
5072 nid
= spec
->multiout
.dac_nids
[i
];
5077 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, "Center Playback Switch",
5078 HDA_COMPOSE_AMP_VAL(nid
, 1, 0, HDA_OUTPUT
))) < 0)
5080 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, "LFE Playback Switch",
5081 HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
))) < 0)
5084 for (idx
= 0; idx
< ARRAY_SIZE(alc861_dac_nids
) - 1; idx
++)
5085 if (nid
== alc861_dac_nids
[idx
])
5087 sprintf(name
, "%s Playback Switch", chname
[idx
]);
5088 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, name
,
5089 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
5096 static int alc861_auto_create_hp_ctls(struct alc_spec
*spec
, hda_nid_t pin
)
5104 if ((pin
>= 0x0b && pin
<= 0x10) || pin
== 0x1f || pin
== 0x20) {
5106 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Headphone Playback Switch",
5107 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
5109 spec
->multiout
.hp_nid
= nid
;
5114 /* create playback/capture controls for input pins */
5115 static int alc861_auto_create_analog_input_ctls(struct alc_spec
*spec
, const struct auto_pin_cfg
*cfg
)
5117 struct hda_input_mux
*imux
= &spec
->private_imux
;
5118 int i
, err
, idx
, idx1
;
5120 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
5121 switch(cfg
->input_pins
[i
]) {
5146 err
= new_analog_input(spec
, cfg
->input_pins
[i
],
5147 auto_pin_cfg_labels
[i
], idx
, 0x15);
5151 imux
->items
[imux
->num_items
].label
= auto_pin_cfg_labels
[i
];
5152 imux
->items
[imux
->num_items
].index
= idx1
;
5158 static struct snd_kcontrol_new alc861_capture_mixer
[] = {
5159 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
5160 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
5163 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
5164 /* The multiple "Capture Source" controls confuse alsamixer
5165 * So call somewhat different..
5166 *FIXME: the controls appear in the "playback" view!
5168 /* .name = "Capture Source", */
5169 .name
= "Input Source",
5171 .info
= alc_mux_enum_info
,
5172 .get
= alc_mux_enum_get
,
5173 .put
= alc_mux_enum_put
,
5178 static void alc861_auto_set_output_and_unmute(struct hda_codec
*codec
, hda_nid_t nid
,
5179 int pin_type
, int dac_idx
)
5183 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
5184 snd_hda_codec_write(codec
, dac_idx
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
5188 static void alc861_auto_init_multi_out(struct hda_codec
*codec
)
5190 struct alc_spec
*spec
= codec
->spec
;
5193 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
5194 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
5196 alc861_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, spec
->multiout
.dac_nids
[i
]);
5200 static void alc861_auto_init_hp_out(struct hda_codec
*codec
)
5202 struct alc_spec
*spec
= codec
->spec
;
5205 pin
= spec
->autocfg
.hp_pin
;
5206 if (pin
) /* connect to front */
5207 alc861_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, spec
->multiout
.dac_nids
[0]);
5210 static void alc861_auto_init_analog_input(struct hda_codec
*codec
)
5212 struct alc_spec
*spec
= codec
->spec
;
5215 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
5216 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
5217 if ((nid
>=0x0c) && (nid
<=0x11)) {
5218 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
5219 i
<= AUTO_PIN_FRONT_MIC
? PIN_VREF80
: PIN_IN
);
5224 /* parse the BIOS configuration and set up the alc_spec */
5225 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
5226 static int alc861_parse_auto_config(struct hda_codec
*codec
)
5228 struct alc_spec
*spec
= codec
->spec
;
5230 static hda_nid_t alc861_ignore
[] = { 0x1d, 0 };
5232 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
,
5233 alc861_ignore
)) < 0)
5235 if (! spec
->autocfg
.line_outs
&& ! spec
->autocfg
.speaker_pin
&&
5236 ! spec
->autocfg
.hp_pin
)
5237 return 0; /* can't find valid BIOS pin config */
5239 if ((err
= alc861_auto_fill_dac_nids(spec
, &spec
->autocfg
)) < 0 ||
5240 (err
= alc861_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
5241 (err
= alc861_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pin
)) < 0 ||
5242 (err
= alc861_auto_create_analog_input_ctls(spec
, &spec
->autocfg
)) < 0)
5245 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
5247 if (spec
->autocfg
.dig_out_pin
)
5248 spec
->multiout
.dig_out_nid
= ALC861_DIGOUT_NID
;
5250 if (spec
->kctl_alloc
)
5251 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
5253 spec
->init_verbs
[spec
->num_init_verbs
++] = alc861_auto_init_verbs
;
5255 spec
->input_mux
= &spec
->private_imux
;
5257 spec
->adc_nids
= alc861_adc_nids
;
5258 spec
->num_adc_nids
= ARRAY_SIZE(alc861_adc_nids
);
5259 spec
->mixers
[spec
->num_mixers
] = alc861_capture_mixer
;
5265 /* init callback for auto-configuration model -- overriding the default init */
5266 static int alc861_auto_init(struct hda_codec
*codec
)
5269 alc861_auto_init_multi_out(codec
);
5270 alc861_auto_init_hp_out(codec
);
5271 alc861_auto_init_analog_input(codec
);
5278 * configuration and preset
5280 static struct hda_board_config alc861_cfg_tbl
[] = {
5281 { .modelname
= "3stack", .config
= ALC861_3ST
},
5282 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd600, .config
= ALC861_3ST
},
5283 { .modelname
= "3stack-dig", .config
= ALC861_3ST_DIG
},
5284 { .modelname
= "6stack-dig", .config
= ALC861_6ST_DIG
},
5285 { .modelname
= "auto", .config
= ALC861_AUTO
},
5289 static struct alc_config_preset alc861_presets
[] = {
5291 .mixers
= { alc861_3ST_mixer
},
5292 .init_verbs
= { alc861_threestack_init_verbs
},
5293 .num_dacs
= ARRAY_SIZE(alc861_dac_nids
),
5294 .dac_nids
= alc861_dac_nids
,
5295 .num_channel_mode
= ARRAY_SIZE(alc861_threestack_modes
),
5296 .channel_mode
= alc861_threestack_modes
,
5297 .num_adc_nids
= ARRAY_SIZE(alc861_adc_nids
),
5298 .adc_nids
= alc861_adc_nids
,
5299 .input_mux
= &alc861_capture_source
,
5301 [ALC861_3ST_DIG
] = {
5302 .mixers
= { alc861_base_mixer
},
5303 .init_verbs
= { alc861_threestack_init_verbs
},
5304 .num_dacs
= ARRAY_SIZE(alc861_dac_nids
),
5305 .dac_nids
= alc861_dac_nids
,
5306 .dig_out_nid
= ALC861_DIGOUT_NID
,
5307 .num_channel_mode
= ARRAY_SIZE(alc861_threestack_modes
),
5308 .channel_mode
= alc861_threestack_modes
,
5309 .num_adc_nids
= ARRAY_SIZE(alc861_adc_nids
),
5310 .adc_nids
= alc861_adc_nids
,
5311 .input_mux
= &alc861_capture_source
,
5313 [ALC861_6ST_DIG
] = {
5314 .mixers
= { alc861_base_mixer
},
5315 .init_verbs
= { alc861_base_init_verbs
},
5316 .num_dacs
= ARRAY_SIZE(alc861_dac_nids
),
5317 .dac_nids
= alc861_dac_nids
,
5318 .dig_out_nid
= ALC861_DIGOUT_NID
,
5319 .num_channel_mode
= ARRAY_SIZE(alc861_8ch_modes
),
5320 .channel_mode
= alc861_8ch_modes
,
5321 .num_adc_nids
= ARRAY_SIZE(alc861_adc_nids
),
5322 .adc_nids
= alc861_adc_nids
,
5323 .input_mux
= &alc861_capture_source
,
5328 static int patch_alc861(struct hda_codec
*codec
)
5330 struct alc_spec
*spec
;
5334 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
5340 board_config
= snd_hda_check_board_config(codec
, alc861_cfg_tbl
);
5341 if (board_config
< 0 || board_config
>= ALC861_MODEL_LAST
) {
5342 printk(KERN_INFO
"hda_codec: Unknown model for ALC861, trying auto-probe from BIOS...\n");
5343 board_config
= ALC861_AUTO
;
5346 if (board_config
== ALC861_AUTO
) {
5347 /* automatic parse from the BIOS config */
5348 err
= alc861_parse_auto_config(codec
);
5353 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
5354 board_config
= ALC861_3ST_DIG
;
5358 if (board_config
!= ALC861_AUTO
)
5359 setup_preset(spec
, &alc861_presets
[board_config
]);
5361 spec
->stream_name_analog
= "ALC861 Analog";
5362 spec
->stream_analog_playback
= &alc861_pcm_analog_playback
;
5363 spec
->stream_analog_capture
= &alc861_pcm_analog_capture
;
5365 spec
->stream_name_digital
= "ALC861 Digital";
5366 spec
->stream_digital_playback
= &alc861_pcm_digital_playback
;
5367 spec
->stream_digital_capture
= &alc861_pcm_digital_capture
;
5369 codec
->patch_ops
= alc_patch_ops
;
5370 if (board_config
== ALC861_AUTO
)
5371 codec
->patch_ops
.init
= alc861_auto_init
;
5379 struct hda_codec_preset snd_hda_preset_realtek
[] = {
5380 { .id
= 0x10ec0260, .name
= "ALC260", .patch
= patch_alc260
},
5381 { .id
= 0x10ec0262, .name
= "ALC262", .patch
= patch_alc262
},
5382 { .id
= 0x10ec0880, .name
= "ALC880", .patch
= patch_alc880
},
5383 { .id
= 0x10ec0882, .name
= "ALC882", .patch
= patch_alc882
},
5384 { .id
= 0x10ec0883, .name
= "ALC883", .patch
= patch_alc882
},
5385 { .id
= 0x10ec0885, .name
= "ALC885", .patch
= patch_alc882
},
5386 { .id
= 0x10ec0861, .name
= "ALC861", .patch
= patch_alc861
},