| changeset 5879: | 6b53fa114faa |
| parent: | d330074658fb |
| child: | 8087414481e8 |
| author: | tiwai |
| date: | Tue Feb 19 15:03:57 2008 +0100 (4 years ago) |
| permissions: | -rw-r--r-- |
| description: | hda-codec - Don't create multiple capture streams for single inputs When the device has only one input source, it makes no sense to have multiple capture streams. |
1/*2 * Universal Interface for Intel High Definition Audio Codec3 *4 * HD audio interface patch for ALC 260/880/882 codecs5 *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>10 *11 * This driver is free software; you can redistribute it and/or modify12 * it under the terms of the GNU General Public License as published by13 * the Free Software Foundation; either version 2 of the License, or14 * (at your option) any later version.15 *16 * This driver is distributed in the hope that it will be useful,17 * but WITHOUT ANY WARRANTY; without even the implied warranty of18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the19 * GNU General Public License for more details.20 *21 * You should have received a copy of the GNU General Public License22 * along with this program; if not, write to the Free Software23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA24 */2526#include <linux/init.h>27#include <linux/delay.h>28#include <linux/slab.h>29#include <linux/pci.h>30#include <sound/core.h>31#include "hda_codec.h"32#include "hda_local.h"3334#define ALC880_FRONT_EVENT 0x0135#define ALC880_DCVOL_EVENT 0x0236#define ALC880_HP_EVENT 0x0437#define ALC880_MIC_EVENT 0x083839/* ALC880 board config type */40enum {41 ALC880_3ST,42 ALC880_3ST_DIG,43 ALC880_5ST,44 ALC880_5ST_DIG,45 ALC880_W810,46 ALC880_Z71V,47 ALC880_6ST,48 ALC880_6ST_DIG,49 ALC880_F1734,50 ALC880_ASUS,51 ALC880_ASUS_DIG,52 ALC880_ASUS_W1V,53 ALC880_ASUS_DIG2,54 ALC880_FUJITSU,55 ALC880_UNIWILL_DIG,56 ALC880_UNIWILL,57 ALC880_UNIWILL_P53,58 ALC880_CLEVO,59 ALC880_TCL_S700,60 ALC880_LG,61 ALC880_LG_LW,62#ifdef CONFIG_SND_DEBUG63 ALC880_TEST,64#endif65 ALC880_AUTO,66 ALC880_MODEL_LAST /* last tag */67};6869/* ALC260 models */70enum {71 ALC260_BASIC,72 ALC260_HP,73 ALC260_HP_3013,74 ALC260_FUJITSU_S702X,75 ALC260_ACER,76 ALC260_WILL,77 ALC260_REPLACER_672V,78#ifdef CONFIG_SND_DEBUG79 ALC260_TEST,80#endif81 ALC260_AUTO,82 ALC260_MODEL_LAST /* last tag */83};8485/* ALC262 models */86enum {87 ALC262_BASIC,88 ALC262_HIPPO,89 ALC262_HIPPO_1,90 ALC262_FUJITSU,91 ALC262_HP_BPC,92 ALC262_HP_BPC_D7000_WL,93 ALC262_HP_BPC_D7000_WF,94 ALC262_HP_TC_T5735,95 ALC262_HP_RP5700,96 ALC262_BENQ_ED8,97 ALC262_SONY_ASSAMD,98 ALC262_BENQ_T31,99 ALC262_ULTRA,100 ALC262_AUTO,101 ALC262_MODEL_LAST /* last tag */102};103104/* ALC268 models */105enum {106 ALC268_3ST,107 ALC268_TOSHIBA,108 ALC268_ACER,109 ALC268_DELL,110 ALC268_ZEPTO,111#ifdef CONFIG_SND_DEBUG112 ALC268_TEST,113#endif114 ALC268_AUTO,115 ALC268_MODEL_LAST /* last tag */116};117118/* ALC269 models */119enum {120 ALC269_BASIC,121 ALC269_AUTO,122 ALC269_MODEL_LAST /* last tag */123};124125/* ALC861 models */126enum {127 ALC861_3ST,128 ALC660_3ST,129 ALC861_3ST_DIG,130 ALC861_6ST_DIG,131 ALC861_UNIWILL_M31,132 ALC861_TOSHIBA,133 ALC861_ASUS,134 ALC861_ASUS_LAPTOP,135 ALC861_AUTO,136 ALC861_MODEL_LAST,137};138139/* ALC861-VD models */140enum {141 ALC660VD_3ST,142 ALC660VD_3ST_DIG,143 ALC861VD_3ST,144 ALC861VD_3ST_DIG,145 ALC861VD_6ST_DIG,146 ALC861VD_LENOVO,147 ALC861VD_DALLAS,148 ALC861VD_HP,149 ALC861VD_AUTO,150 ALC861VD_MODEL_LAST,151};152153/* ALC662 models */154enum {155 ALC662_3ST_2ch_DIG,156 ALC662_3ST_6ch_DIG,157 ALC662_3ST_6ch,158 ALC662_5ST_DIG,159 ALC662_LENOVO_101E,160 ALC662_ASUS_EEEPC_P701,161 ALC662_ASUS_EEEPC_EP20,162 ALC662_AUTO,163 ALC662_MODEL_LAST,164};165166/* ALC882 models */167enum {168 ALC882_3ST_DIG,169 ALC882_6ST_DIG,170 ALC882_ARIMA,171 ALC882_W2JC,172 ALC882_TARGA,173 ALC882_ASUS_A7J,174 ALC882_ASUS_A7M,175 ALC885_MACPRO,176 ALC885_MBP3,177 ALC885_IMAC24,178 ALC882_AUTO,179 ALC882_MODEL_LAST,180};181182/* ALC883 models */183enum {184 ALC883_3ST_2ch_DIG,185 ALC883_3ST_6ch_DIG,186 ALC883_3ST_6ch,187 ALC883_6ST_DIG,188 ALC883_TARGA_DIG,189 ALC883_TARGA_2ch_DIG,190 ALC883_ACER,191 ALC883_ACER_ASPIRE,192 ALC883_MEDION,193 ALC883_MEDION_MD2,194 ALC883_LAPTOP_EAPD,195 ALC883_LENOVO_101E_2ch,196 ALC883_LENOVO_NB0763,197 ALC888_LENOVO_MS7195_DIG,198 ALC883_HAIER_W66,199 ALC888_6ST_HP,200 ALC888_3ST_HP,201 ALC888_6ST_DELL,202 ALC883_MITAC,203 ALC883_AUTO,204 ALC883_MODEL_LAST,205};206207/* for GPIO Poll */208#define GPIO_MASK 0x03209210struct alc_spec {211 /* codec parameterization */212 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */213 unsigned int num_mixers;214215 const struct hda_verb *init_verbs[5]; /* initialization verbs216 * don't forget NULL217 * termination!218 */219 unsigned int num_init_verbs;220221 char *stream_name_analog; /* analog PCM stream */222 struct hda_pcm_stream *stream_analog_playback;223 struct hda_pcm_stream *stream_analog_capture;224 struct hda_pcm_stream *stream_analog_alt_playback;225 struct hda_pcm_stream *stream_analog_alt_capture;226227 char *stream_name_digital; /* digital PCM stream */228 struct hda_pcm_stream *stream_digital_playback;229 struct hda_pcm_stream *stream_digital_capture;230231 /* playback */232 struct hda_multi_out multiout; /* playback set-up233 * max_channels, dacs must be set234 * dig_out_nid and hp_nid are optional235 */236 hda_nid_t alt_dac_nid;237238 /* capture */239 unsigned int num_adc_nids;240 hda_nid_t *adc_nids;241 hda_nid_t *capsrc_nids;242 hda_nid_t dig_in_nid; /* digital-in NID; optional */243244 /* capture source */245 unsigned int num_mux_defs;246 const struct hda_input_mux *input_mux;247 unsigned int cur_mux[3];248249 /* channel model */250 const struct hda_channel_mode *channel_mode;251 int num_channel_mode;252 int need_dac_fix;253254 /* PCM information */255 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */256257 /* dynamic controls, init_verbs and input_mux */258 struct auto_pin_cfg autocfg;259 unsigned int num_kctl_alloc, num_kctl_used;260 struct snd_kcontrol_new *kctl_alloc;261 struct hda_input_mux private_imux;262 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];263264 /* hooks */265 void (*init_hook)(struct hda_codec *codec);266 void (*unsol_event)(struct hda_codec *codec, unsigned int res);267268 /* for pin sensing */269 unsigned int sense_updated: 1;270 unsigned int jack_present: 1;271 unsigned int master_sw: 1;272273 /* for virtual master */274 hda_nid_t vmaster_nid;275#ifdef CONFIG_SND_HDA_POWER_SAVE276 struct hda_loopback_check loopback;277#endif278};279280/*281 * configuration template - to be copied to the spec instance282 */283struct alc_config_preset {284 struct snd_kcontrol_new *mixers[5]; /* should be identical size285 * with spec286 */287 const struct hda_verb *init_verbs[5];288 unsigned int num_dacs;289 hda_nid_t *dac_nids;290 hda_nid_t dig_out_nid; /* optional */291 hda_nid_t hp_nid; /* optional */292 unsigned int num_adc_nids;293 hda_nid_t *adc_nids;294 hda_nid_t *capsrc_nids;295 hda_nid_t dig_in_nid;296 unsigned int num_channel_mode;297 const struct hda_channel_mode *channel_mode;298 int need_dac_fix;299 unsigned int num_mux_defs;300 const struct hda_input_mux *input_mux;301 void (*unsol_event)(struct hda_codec *, unsigned int);302 void (*init_hook)(struct hda_codec *);303#ifdef CONFIG_SND_HDA_POWER_SAVE304 struct hda_amp_list *loopbacks;305#endif306};307308309/*310 * input MUX handling311 */312static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,313 struct snd_ctl_elem_info *uinfo)314{315 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);316 struct alc_spec *spec = codec->spec;317 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);318 if (mux_idx >= spec->num_mux_defs)319 mux_idx = 0;320 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);321}322323static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,324 struct snd_ctl_elem_value *ucontrol)325{326 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);327 struct alc_spec *spec = codec->spec;328 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);329330 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];331 return 0;332}333334static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,335 struct snd_ctl_elem_value *ucontrol)336{337 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);338 struct alc_spec *spec = codec->spec;339 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);340 unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;341 hda_nid_t nid = spec->capsrc_nids ?342 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];343 return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,344 nid, &spec->cur_mux[adc_idx]);345}346347348/*349 * channel mode setting350 */351static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,352 struct snd_ctl_elem_info *uinfo)353{354 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);355 struct alc_spec *spec = codec->spec;356 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,357 spec->num_channel_mode);358}359360static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,361 struct snd_ctl_elem_value *ucontrol)362{363 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);364 struct alc_spec *spec = codec->spec;365 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,366 spec->num_channel_mode,367 spec->multiout.max_channels);368}369370static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,371 struct snd_ctl_elem_value *ucontrol)372{373 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);374 struct alc_spec *spec = codec->spec;375 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,376 spec->num_channel_mode,377 &spec->multiout.max_channels);378 if (err >= 0 && spec->need_dac_fix)379 spec->multiout.num_dacs = spec->multiout.max_channels / 2;380 return err;381}382383/*384 * Control the mode of pin widget settings via the mixer. "pc" is used385 * instead of "%" to avoid consequences of accidently treating the % as386 * being part of a format specifier. Maximum allowed length of a value is387 * 63 characters plus NULL terminator.388 *389 * Note: some retasking pin complexes seem to ignore requests for input390 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these391 * are requested. Therefore order this list so that this behaviour will not392 * cause problems when mixer clients move through the enum sequentially.393 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of394 * March 2006.395 */396static char *alc_pin_mode_names[] = {397 "Mic 50pc bias", "Mic 80pc bias",398 "Line in", "Line out", "Headphone out",399};400static unsigned char alc_pin_mode_values[] = {401 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,402};403/* The control can present all 5 options, or it can limit the options based404 * in the pin being assumed to be exclusively an input or an output pin. In405 * addition, "input" pins may or may not process the mic bias option406 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to407 * accept requests for bias as of chip versions up to March 2006) and/or408 * wiring in the computer.409 */410#define ALC_PIN_DIR_IN 0x00411#define ALC_PIN_DIR_OUT 0x01412#define ALC_PIN_DIR_INOUT 0x02413#define ALC_PIN_DIR_IN_NOMICBIAS 0x03414#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04415416/* Info about the pin modes supported by the different pin direction modes.417 * For each direction the minimum and maximum values are given.418 */419static signed char alc_pin_mode_dir_info[5][2] = {420 { 0, 2 }, /* ALC_PIN_DIR_IN */421 { 3, 4 }, /* ALC_PIN_DIR_OUT */422 { 0, 4 }, /* ALC_PIN_DIR_INOUT */423 { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */424 { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */425};426#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])427#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])428#define alc_pin_mode_n_items(_dir) \429 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)430431static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,432 struct snd_ctl_elem_info *uinfo)433{434 unsigned int item_num = uinfo->value.enumerated.item;435 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;436437 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;438 uinfo->count = 1;439 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);440441 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))442 item_num = alc_pin_mode_min(dir);443 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);444 return 0;445}446447static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,448 struct snd_ctl_elem_value *ucontrol)449{450 unsigned int i;451 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);452 hda_nid_t nid = kcontrol->private_value & 0xffff;453 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;454 long *valp = ucontrol->value.integer.value;455 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,456 AC_VERB_GET_PIN_WIDGET_CONTROL,457 0x00);458459 /* Find enumerated value for current pinctl setting */460 i = alc_pin_mode_min(dir);461 while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir))462 i++;463 *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);464 return 0;465}466467static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,468 struct snd_ctl_elem_value *ucontrol)469{470 signed int change;471 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);472 hda_nid_t nid = kcontrol->private_value & 0xffff;473 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;474 long val = *ucontrol->value.integer.value;475 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,476 AC_VERB_GET_PIN_WIDGET_CONTROL,477 0x00);478479 if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))480 val = alc_pin_mode_min(dir);481482 change = pinctl != alc_pin_mode_values[val];483 if (change) {484 /* Set pin mode to that requested */485 snd_hda_codec_write_cache(codec, nid, 0,486 AC_VERB_SET_PIN_WIDGET_CONTROL,487 alc_pin_mode_values[val]);488489 /* Also enable the retasking pin's input/output as required490 * for the requested pin mode. Enum values of 2 or less are491 * input modes.492 *493 * Dynamically switching the input/output buffers probably494 * reduces noise slightly (particularly on input) so we'll495 * do it. However, having both input and output buffers496 * enabled simultaneously doesn't seem to be problematic if497 * this turns out to be necessary in the future.498 */499 if (val <= 2) {500 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,501 HDA_AMP_MUTE, HDA_AMP_MUTE);502 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,503 HDA_AMP_MUTE, 0);504 } else {505 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,506 HDA_AMP_MUTE, HDA_AMP_MUTE);507 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,508 HDA_AMP_MUTE, 0);509 }510 }511 return change;512}513514#define ALC_PIN_MODE(xname, nid, dir) \515 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \516 .info = alc_pin_mode_info, \517 .get = alc_pin_mode_get, \518 .put = alc_pin_mode_put, \519 .private_value = nid | (dir<<16) }520521/* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged522 * together using a mask with more than one bit set. This control is523 * currently used only by the ALC260 test model. At this stage they are not524 * needed for any "production" models.525 */526#ifdef CONFIG_SND_DEBUG527#define alc_gpio_data_info snd_ctl_boolean_mono_info528529static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,530 struct snd_ctl_elem_value *ucontrol)531{532 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);533 hda_nid_t nid = kcontrol->private_value & 0xffff;534 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;535 long *valp = ucontrol->value.integer.value;536 unsigned int val = snd_hda_codec_read(codec, nid, 0,537 AC_VERB_GET_GPIO_DATA, 0x00);538539 *valp = (val & mask) != 0;540 return 0;541}542static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,543 struct snd_ctl_elem_value *ucontrol)544{545 signed int change;546 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);547 hda_nid_t nid = kcontrol->private_value & 0xffff;548 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;549 long val = *ucontrol->value.integer.value;550 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,551 AC_VERB_GET_GPIO_DATA,552 0x00);553554 /* Set/unset the masked GPIO bit(s) as needed */555 change = (val == 0 ? 0 : mask) != (gpio_data & mask);556 if (val == 0)557 gpio_data &= ~mask;558 else559 gpio_data |= mask;560 snd_hda_codec_write_cache(codec, nid, 0,561 AC_VERB_SET_GPIO_DATA, gpio_data);562563 return change;564}565#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \566 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \567 .info = alc_gpio_data_info, \568 .get = alc_gpio_data_get, \569 .put = alc_gpio_data_put, \570 .private_value = nid | (mask<<16) }571#endif /* CONFIG_SND_DEBUG */572573/* A switch control to allow the enabling of the digital IO pins on the574 * ALC260. This is incredibly simplistic; the intention of this control is575 * to provide something in the test model allowing digital outputs to be576 * identified if present. If models are found which can utilise these577 * outputs a more complete mixer control can be devised for those models if578 * necessary.579 */580#ifdef CONFIG_SND_DEBUG581#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info582583static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,584 struct snd_ctl_elem_value *ucontrol)585{586 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);587 hda_nid_t nid = kcontrol->private_value & 0xffff;588 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;589 long *valp = ucontrol->value.integer.value;590 unsigned int val = snd_hda_codec_read(codec, nid, 0,591 AC_VERB_GET_DIGI_CONVERT_1, 0x00);592593 *valp = (val & mask) != 0;594 return 0;595}596static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,597 struct snd_ctl_elem_value *ucontrol)598{599 signed int change;600 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);601 hda_nid_t nid = kcontrol->private_value & 0xffff;602 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;603 long val = *ucontrol->value.integer.value;604 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,605 AC_VERB_GET_DIGI_CONVERT_1,606 0x00);607608 /* Set/unset the masked control bit(s) as needed */609 change = (val == 0 ? 0 : mask) != (ctrl_data & mask);610 if (val==0)611 ctrl_data &= ~mask;612 else613 ctrl_data |= mask;614 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,615 ctrl_data);616617 return change;618}619#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \620 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \621 .info = alc_spdif_ctrl_info, \622 .get = alc_spdif_ctrl_get, \623 .put = alc_spdif_ctrl_put, \624 .private_value = nid | (mask<<16) }625#endif /* CONFIG_SND_DEBUG */626627/* A switch control to allow the enabling EAPD digital outputs on the ALC26x.628 * Again, this is only used in the ALC26x test models to help identify when629 * the EAPD line must be asserted for features to work.630 */631#ifdef CONFIG_SND_DEBUG632#define alc_eapd_ctrl_info snd_ctl_boolean_mono_info633634static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,635 struct snd_ctl_elem_value *ucontrol)636{637 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);638 hda_nid_t nid = kcontrol->private_value & 0xffff;639 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;640 long *valp = ucontrol->value.integer.value;641 unsigned int val = snd_hda_codec_read(codec, nid, 0,642 AC_VERB_GET_EAPD_BTLENABLE, 0x00);643644 *valp = (val & mask) != 0;645 return 0;646}647648static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,649 struct snd_ctl_elem_value *ucontrol)650{651 int change;652 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);653 hda_nid_t nid = kcontrol->private_value & 0xffff;654 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;655 long val = *ucontrol->value.integer.value;656 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,657 AC_VERB_GET_EAPD_BTLENABLE,658 0x00);659660 /* Set/unset the masked control bit(s) as needed */661 change = (!val ? 0 : mask) != (ctrl_data & mask);662 if (!val)663 ctrl_data &= ~mask;664 else665 ctrl_data |= mask;666 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,667 ctrl_data);668669 return change;670}671672#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \673 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \674 .info = alc_eapd_ctrl_info, \675 .get = alc_eapd_ctrl_get, \676 .put = alc_eapd_ctrl_put, \677 .private_value = nid | (mask<<16) }678#endif /* CONFIG_SND_DEBUG */679680/*681 * set up from the preset table682 */683static void setup_preset(struct alc_spec *spec,684 const struct alc_config_preset *preset)685{686 int i;687688 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)689 spec->mixers[spec->num_mixers++] = preset->mixers[i];690 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];691 i++)692 spec->init_verbs[spec->num_init_verbs++] =693 preset->init_verbs[i];694695 spec->channel_mode = preset->channel_mode;696 spec->num_channel_mode = preset->num_channel_mode;697 spec->need_dac_fix = preset->need_dac_fix;698699 spec->multiout.max_channels = spec->channel_mode[0].channels;700701 spec->multiout.num_dacs = preset->num_dacs;702 spec->multiout.dac_nids = preset->dac_nids;703 spec->multiout.dig_out_nid = preset->dig_out_nid;704 spec->multiout.hp_nid = preset->hp_nid;705706 spec->num_mux_defs = preset->num_mux_defs;707 if (!spec->num_mux_defs)708 spec->num_mux_defs = 1;709 spec->input_mux = preset->input_mux;710711 spec->num_adc_nids = preset->num_adc_nids;712 spec->adc_nids = preset->adc_nids;713 spec->capsrc_nids = preset->capsrc_nids;714 spec->dig_in_nid = preset->dig_in_nid;715716 spec->unsol_event = preset->unsol_event;717 spec->init_hook = preset->init_hook;718#ifdef CONFIG_SND_HDA_POWER_SAVE719 spec->loopback.amplist = preset->loopbacks;720#endif721}722723/* Enable GPIO mask and set output */724static struct hda_verb alc_gpio1_init_verbs[] = {725 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},726 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},727 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},728 { }729};730731static struct hda_verb alc_gpio2_init_verbs[] = {732 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},733 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},734 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},735 { }736};737738static struct hda_verb alc_gpio3_init_verbs[] = {739 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},740 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},741 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},742 { }743};744745static void alc_sku_automute(struct hda_codec *codec)746{747 struct alc_spec *spec = codec->spec;748 unsigned int present;749 unsigned int hp_nid = spec->autocfg.hp_pins[0];750 unsigned int sp_nid = spec->autocfg.speaker_pins[0];751752 /* need to execute and sync at first */753 snd_hda_codec_read(codec, hp_nid, 0, AC_VERB_SET_PIN_SENSE, 0);754 present = snd_hda_codec_read(codec, hp_nid, 0,755 AC_VERB_GET_PIN_SENSE, 0);756 spec->jack_present = (present & 0x80000000) != 0;757 snd_hda_codec_write(codec, sp_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,758 spec->jack_present ? 0 : PIN_OUT);759}760761/* unsolicited event for HP jack sensing */762static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)763{764 if (codec->vendor_id == 0x10ec0880)765 res >>= 28;766 else767 res >>= 26;768 if (res != ALC880_HP_EVENT)769 return;770771 alc_sku_automute(codec);772}773774/* 32-bit subsystem ID for BIOS loading in HD Audio codec.775 * 31 ~ 16 : Manufacture ID776 * 15 ~ 8 : SKU ID777 * 7 ~ 0 : Assembly ID778 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36779 */780static void alc_subsystem_id(struct hda_codec *codec,781 unsigned int porta, unsigned int porte,782 unsigned int portd)783{784 unsigned int ass, tmp, i;785 unsigned nid;786 struct alc_spec *spec = codec->spec;787788 ass = codec->subsystem_id & 0xffff;789 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))790 goto do_sku;791792 /*793 * 31~30 : port conetcivity794 * 29~21 : reserve795 * 20 : PCBEEP input796 * 19~16 : Check sum (15:1)797 * 15~1 : Custom798 * 0 : override799 */800 nid = 0x1d;801 if (codec->vendor_id == 0x10ec0260)802 nid = 0x17;803 ass = snd_hda_codec_read(codec, nid, 0,804 AC_VERB_GET_CONFIG_DEFAULT, 0);805 if (!(ass & 1) && !(ass & 0x100000))806 return;807 if ((ass >> 30) != 1) /* no physical connection */808 return;809810 /* check sum */811 tmp = 0;812 for (i = 1; i < 16; i++) {813 if ((ass >> i) & 1)814 tmp++;815 }816 if (((ass >> 16) & 0xf) != tmp)817 return;818do_sku:819 /*820 * 0 : override821 * 1 : Swap Jack822 * 2 : 0 --> Desktop, 1 --> Laptop823 * 3~5 : External Amplifier control824 * 7~6 : Reserved825 */826 tmp = (ass & 0x38) >> 3; /* external Amp control */827 switch (tmp) {828 case 1:829 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);830 break;831 case 3:832 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);833 break;834 case 7:835 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);836 break;837 case 5: /* set EAPD output high */838 switch (codec->vendor_id) {839 case 0x10ec0260:840 snd_hda_codec_write(codec, 0x0f, 0,841 AC_VERB_SET_EAPD_BTLENABLE, 2);842 snd_hda_codec_write(codec, 0x10, 0,843 AC_VERB_SET_EAPD_BTLENABLE, 2);844 break;845 case 0x10ec0262:846 case 0x10ec0267:847 case 0x10ec0268:848 case 0x10ec0269:849 case 0x10ec0862:850 case 0x10ec0662:851 snd_hda_codec_write(codec, 0x14, 0,852 AC_VERB_SET_EAPD_BTLENABLE, 2);853 snd_hda_codec_write(codec, 0x15, 0,854 AC_VERB_SET_EAPD_BTLENABLE, 2);855 break;856 }857 switch (codec->vendor_id) {858 case 0x10ec0260:859 snd_hda_codec_write(codec, 0x1a, 0,860 AC_VERB_SET_COEF_INDEX, 7);861 tmp = snd_hda_codec_read(codec, 0x1a, 0,862 AC_VERB_GET_PROC_COEF, 0);863 snd_hda_codec_write(codec, 0x1a, 0,864 AC_VERB_SET_COEF_INDEX, 7);865 snd_hda_codec_write(codec, 0x1a, 0,866 AC_VERB_SET_PROC_COEF,867 tmp | 0x2010);868 break;869 case 0x10ec0262:870 case 0x10ec0880:871 case 0x10ec0882:872 case 0x10ec0883:873 case 0x10ec0885:874 case 0x10ec0888:875 snd_hda_codec_write(codec, 0x20, 0,876 AC_VERB_SET_COEF_INDEX, 7);877 tmp = snd_hda_codec_read(codec, 0x20, 0,878 AC_VERB_GET_PROC_COEF, 0);879 snd_hda_codec_write(codec, 0x20, 0,880 AC_VERB_SET_COEF_INDEX, 7);881 snd_hda_codec_write(codec, 0x20, 0,882 AC_VERB_SET_PROC_COEF,883 tmp | 0x2010);884 break;885 case 0x10ec0267:886 case 0x10ec0268:887 snd_hda_codec_write(codec, 0x20, 0,888 AC_VERB_SET_COEF_INDEX, 7);889 tmp = snd_hda_codec_read(codec, 0x20, 0,890 AC_VERB_GET_PROC_COEF, 0);891 snd_hda_codec_write(codec, 0x20, 0,892 AC_VERB_SET_COEF_INDEX, 7);893 snd_hda_codec_write(codec, 0x20, 0,894 AC_VERB_SET_PROC_COEF,895 tmp | 0x3000);896 break;897 }898 default:899 break;900 }901902 /* is laptop or Desktop and enable the function "Mute internal speaker903 * when the external headphone out jack is plugged"904 */905 if (!(ass & 0x8000))906 return;907 /*908 * 10~8 : Jack location909 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered910 * 14~13: Resvered911 * 15 : 1 --> enable the function "Mute internal speaker912 * when the external headphone out jack is plugged"913 */914 if (!spec->autocfg.speaker_pins[0]) {915 if (spec->autocfg.line_out_pins[0])916 spec->autocfg.speaker_pins[0] =917 spec->autocfg.line_out_pins[0];918 else919 return;920 }921922 if (!spec->autocfg.hp_pins[0]) {923 tmp = (ass >> 11) & 0x3; /* HP to chassis */924 if (tmp == 0)925 spec->autocfg.hp_pins[0] = porta;926 else if (tmp == 1)927 spec->autocfg.hp_pins[0] = porte;928 else if (tmp == 2)929 spec->autocfg.hp_pins[0] = portd;930 else931 return;932 }933934 snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,935 AC_VERB_SET_UNSOLICITED_ENABLE,936 AC_USRSP_EN | ALC880_HP_EVENT);937 spec->unsol_event = alc_sku_unsol_event;938 spec->init_hook = alc_sku_automute;939}940941/*942 * Fix-up pin default configurations943 */944945struct alc_pincfg {946 hda_nid_t nid;947 u32 val;948};949950static void alc_fix_pincfg(struct hda_codec *codec,951 const struct snd_pci_quirk *quirk,952 const struct alc_pincfg **pinfix)953{954 const struct alc_pincfg *cfg;955956 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);957 if (!quirk)958 return;959960 cfg = pinfix[quirk->value];961 for (; cfg->nid; cfg++) {962 int i;963 u32 val = cfg->val;964 for (i = 0; i < 4; i++) {965 snd_hda_codec_write(codec, cfg->nid, 0,966 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,967 val & 0xff);968 val >>= 8;969 }970 }971}972973/*974 * ALC880 3-stack model975 *976 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)977 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,978 * F-Mic = 0x1b, HP = 0x19979 */980981static hda_nid_t alc880_dac_nids[4] = {982 /* front, rear, clfe, rear_surr */983 0x02, 0x05, 0x04, 0x03984};985986static hda_nid_t alc880_adc_nids[3] = {987 /* ADC0-2 */988 0x07, 0x08, 0x09,989};990991/* The datasheet says the node 0x07 is connected from inputs,992 * but it shows zero connection in the real implementation on some devices.993 * Note: this is a 915GAV bug, fixed on 915GLV994 */995static hda_nid_t alc880_adc_nids_alt[2] = {996 /* ADC1-2 */997 0x08, 0x09,998};9991000#define ALC880_DIGOUT_NID 0x061001#define ALC880_DIGIN_NID 0x0a10021003static struct hda_input_mux alc880_capture_source = {1004 .num_items = 4,1005 .items = {1006 { "Mic", 0x0 },1007 { "Front Mic", 0x3 },1008 { "Line", 0x2 },1009 { "CD", 0x4 },1010 },1011};10121013/* channel source setting (2/6 channel selection for 3-stack) */1014/* 2ch mode */1015static struct hda_verb alc880_threestack_ch2_init[] = {1016 /* set line-in to input, mute it */1017 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },1018 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },1019 /* set mic-in to input vref 80%, mute it */1020 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },1021 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },1022 { } /* end */1023};10241025/* 6ch mode */1026static struct hda_verb alc880_threestack_ch6_init[] = {1027 /* set line-in to output, unmute it */1028 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },1029 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },1030 /* set mic-in to output, unmute it */1031 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },1032 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },1033 { } /* end */1034};10351036static struct hda_channel_mode alc880_threestack_modes[2] = {1037 { 2, alc880_threestack_ch2_init },1038 { 6, alc880_threestack_ch6_init },1039};10401041static struct snd_kcontrol_new alc880_three_stack_mixer[] = {1042 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),1043 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),1044 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),1045 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),1046 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),1047 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),1048 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),1049 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),1050 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),1051 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),1052 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),1053 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),1054 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),1055 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1056 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),1057 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),1058 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),1059 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),1060 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),1061 {1062 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,1063 .name = "Channel Mode",1064 .info = alc_ch_mode_info,1065 .get = alc_ch_mode_get,1066 .put = alc_ch_mode_put,1067 },1068 { } /* end */1069};10701071/* capture mixer elements */1072static struct snd_kcontrol_new alc880_capture_mixer[] = {1073 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),1074 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),1075 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),1076 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),1077 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),1078 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),1079 {1080 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,1081 /* The multiple "Capture Source" controls confuse alsamixer1082 * So call somewhat different..1083 */1084 /* .name = "Capture Source", */1085 .name = "Input Source",1086 .count = 3,1087 .info = alc_mux_enum_info,1088 .get = alc_mux_enum_get,1089 .put = alc_mux_enum_put,1090 },1091 { } /* end */1092};10931094/* capture mixer elements (in case NID 0x07 not available) */1095static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {1096 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),1097 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),1098 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),1099 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),1100 {1101 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,1102 /* The multiple "Capture Source" controls confuse alsamixer1103 * So call somewhat different..1104 */1105 /* .name = "Capture Source", */1106 .name = "Input Source",1107 .count = 2,1108 .info = alc_mux_enum_info,1109 .get = alc_mux_enum_get,1110 .put = alc_mux_enum_put,1111 },1112 { } /* end */1113};1114111511161117/*1118 * ALC880 5-stack model1119 *1120 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),1121 * Side = 0x02 (0xd)1122 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x161123 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x191124 */11251126/* additional mixers to alc880_three_stack_mixer */1127static struct snd_kcontrol_new alc880_five_stack_mixer[] = {1128 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),1129 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),1130 { } /* end */1131};11321133/* channel source setting (6/8 channel selection for 5-stack) */1134/* 6ch mode */1135static struct hda_verb alc880_fivestack_ch6_init[] = {1136 /* set line-in to input, mute it */1137 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },1138 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },1139 { } /* end */1140};11411142/* 8ch mode */1143static struct hda_verb alc880_fivestack_ch8_init[] = {1144 /* set line-in to output, unmute it */1145 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },1146 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },1147 { } /* end */1148};11491150static struct hda_channel_mode alc880_fivestack_modes[2] = {1151 { 6, alc880_fivestack_ch6_init },1152 { 8, alc880_fivestack_ch8_init },1153};115411551156/*1157 * ALC880 6-stack model1158 *1159 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),1160 * Side = 0x05 (0x0f)1161 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,1162 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b1163 */11641165static hda_nid_t alc880_6st_dac_nids[4] = {1166 /* front, rear, clfe, rear_surr */1167 0x02, 0x03, 0x04, 0x051168};11691170static struct hda_input_mux alc880_6stack_capture_source = {1171 .num_items = 4,1172 .items = {1173 { "Mic", 0x0 },1174 { "Front Mic", 0x1 },1175 { "Line", 0x2 },1176 { "CD", 0x4 },1177 },1178};11791180/* fixed 8-channels */1181static struct hda_channel_mode alc880_sixstack_modes[1] = {1182 { 8, NULL },1183};11841185static struct snd_kcontrol_new alc880_six_stack_mixer[] = {1186 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),1187 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),1188 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),1189 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),1190 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),1191 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),1192 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),1193 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),1194 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),1195 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),1196 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),1197 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),1198 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),1199 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),1200 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),1201 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1202 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),1203 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),1204 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),1205 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),1206 {1207 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,1208 .name = "Channel Mode",1209 .info = alc_ch_mode_info,1210 .get = alc_ch_mode_get,1211 .put = alc_ch_mode_put,1212 },1213 { } /* end */1214};121512161217/*1218 * ALC880 W810 model1219 *1220 * W810 has rear IO for:1221 * Front (DAC 02)1222 * Surround (DAC 03)1223 * Center/LFE (DAC 04)1224 * Digital out (06)1225 *1226 * The system also has a pair of internal speakers, and a headphone jack.1227 * These are both connected to Line2 on the codec, hence to DAC 02.1228 *1229 * There is a variable resistor to control the speaker or headphone1230 * volume. This is a hardware-only device without a software API.1231 *1232 * Plugging headphones in will disable the internal speakers. This is1233 * implemented in hardware, not via the driver using jack sense. In1234 * a similar fashion, plugging into the rear socket marked "front" will1235 * disable both the speakers and headphones.1236 *1237 * For input, there's a microphone jack, and an "audio in" jack.1238 * These may not do anything useful with this driver yet, because I1239 * haven't setup any initialization verbs for these yet...1240 */12411242static hda_nid_t alc880_w810_dac_nids[3] = {1243 /* front, rear/surround, clfe */1244 0x02, 0x03, 0x041245};12461247/* fixed 6 channels */1248static struct hda_channel_mode alc880_w810_modes[1] = {1249 { 6, NULL }1250};12511252/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */1253static struct snd_kcontrol_new alc880_w810_base_mixer[] = {1254 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),1255 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),1256 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),1257 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),1258 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),1259 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),1260 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),1261 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),1262 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),1263 { } /* end */1264};126512661267/*1268 * Z710V model1269 *1270 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)1271 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),1272 * Line = 0x1a1273 */12741275static hda_nid_t alc880_z71v_dac_nids[1] = {1276 0x021277};1278#define ALC880_Z71V_HP_DAC 0x0312791280/* fixed 2 channels */1281static struct hda_channel_mode alc880_2_jack_modes[1] = {1282 { 2, NULL }1283};12841285static struct snd_kcontrol_new alc880_z71v_mixer[] = {1286 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),1287 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),1288 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),1289 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),1290 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),1291 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),1292 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),1293 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1294 { } /* end */1295};129612971298/*1299 * ALC880 F1734 model1300 *1301 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)1302 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x181303 */13041305static hda_nid_t alc880_f1734_dac_nids[1] = {1306 0x031307};1308#define ALC880_F1734_HP_DAC 0x0213091310static struct snd_kcontrol_new alc880_f1734_mixer[] = {1311 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),1312 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),1313 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),1314 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),1315 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),1316 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),1317 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),1318 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),1319 { } /* end */1320};13211322static struct hda_input_mux alc880_f1734_capture_source = {1323 .num_items = 2,1324 .items = {1325 { "Mic", 0x1 },1326 { "CD", 0x4 },1327 },1328};132913301331/*1332 * ALC880 ASUS model1333 *1334 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)1335 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,1336 * Mic = 0x18, Line = 0x1a1337 */13381339#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */1340#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */13411342static struct snd_kcontrol_new alc880_asus_mixer[] = {1343 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),1344 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),1345 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),1346 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),1347 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),1348 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),1349 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),1350 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),1351 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),1352 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),1353 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),1354 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),1355 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),1356 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1357 {1358 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,1359 .name = "Channel Mode",1360 .info = alc_ch_mode_info,1361 .get = alc_ch_mode_get,1362 .put = alc_ch_mode_put,1363 },1364 { } /* end */1365};13661367/*1368 * ALC880 ASUS W1V model1369 *1370 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)1371 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,1372 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b1373 */13741375/* additional mixers to alc880_asus_mixer */1376static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {1377 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),1378 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),1379 { } /* end */1380};13811382/* additional mixers to alc880_asus_mixer */1383static struct snd_kcontrol_new alc880_pcbeep_mixer[] = {1384 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),1385 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),1386 { } /* end */1387};13881389/* TCL S700 */1390static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {1391 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),1392 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),1393 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),1394 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),1395 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),1396 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),1397 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),1398 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),1399 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),1400 {1401 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,1402 /* The multiple "Capture Source" controls confuse alsamixer1403 * So call somewhat different..1404 */1405 /* .name = "Capture Source", */1406 .name = "Input Source",1407 .count = 1,1408 .info = alc_mux_enum_info,1409 .get = alc_mux_enum_get,1410 .put = alc_mux_enum_put,1411 },1412 { } /* end */1413};14141415/* Uniwill */1416static struct snd_kcontrol_new alc880_uniwill_mixer[] = {1417 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),1418 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),1419 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),1420 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),1421 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),1422 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),1423 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),1424 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),1425 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),1426 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),1427 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),1428 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),1429 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),1430 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1431 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),1432 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),1433 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),1434 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),1435 {1436 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,1437 .name = "Channel Mode",1438 .info = alc_ch_mode_info,1439 .get = alc_ch_mode_get,1440 .put = alc_ch_mode_put,1441 },1442 { } /* end */1443};14441445static struct snd_kcontrol_new alc880_fujitsu_mixer[] = {1446 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),1447 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),1448 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),1449 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),1450 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),1451 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),1452 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),1453 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1454 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),1455 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),1456 { } /* end */1457};14581459static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {1460 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),1461 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),1462 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),1463 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),1464 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),1465 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1466 { } /* end */1467};14681469/*1470 * virtual master controls1471 */14721473/*1474 * slave controls for virtual master1475 */1476static const char *alc_slave_vols[] = {1477 "Front Playback Volume",1478 "Surround Playback Volume",1479 "Center Playback Volume",1480 "LFE Playback Volume",1481 "Side Playback Volume",1482 "Headphone Playback Volume",1483 "Speaker Playback Volume",1484 "Mono Playback Volume",1485 "Line-Out Playback Volume",1486 NULL,1487};14881489static const char *alc_slave_sws[] = {1490 "Front Playback Switch",1491 "Surround Playback Switch",1492 "Center Playback Switch",1493 "LFE Playback Switch",1494 "Side Playback Switch",1495 "Headphone Playback Switch",1496 "Speaker Playback Switch",1497 "Mono Playback Switch",1498 "IEC958 Playback Switch",1499 NULL,1500};15011502/*1503 * build control elements1504 */1505static int alc_build_controls(struct hda_codec *codec)1506{1507 struct alc_spec *spec = codec->spec;1508 int err;1509 int i;15101511 for (i = 0; i < spec->num_mixers; i++) {1512 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);1513 if (err < 0)1514 return err;1515 }15161517 if (spec->multiout.dig_out_nid) {1518 err = snd_hda_create_spdif_out_ctls(codec,1519 spec->multiout.dig_out_nid);1520 if (err < 0)1521 return err;1522 err = snd_hda_create_spdif_share_sw(codec,1523 &spec->multiout);1524 if (err < 0)1525 return err;1526 spec->multiout.share_spdif = 1;1527 }1528 if (spec->dig_in_nid) {1529 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);1530 if (err < 0)1531 return err;1532 }15331534 /* if we have no master control, let's create it */1535 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {1536 unsigned int vmaster_tlv[4];1537 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,1538 HDA_OUTPUT, vmaster_tlv);1539 err = snd_hda_add_vmaster(codec, "Master Playback Volume",1540 vmaster_tlv, alc_slave_vols);1541 if (err < 0)1542 return err;1543 }1544 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {1545 err = snd_hda_add_vmaster(codec, "Master Playback Switch",1546 NULL, alc_slave_sws);1547 if (err < 0)1548 return err;1549 }15501551 return 0;1552}155315541555/*1556 * initialize the codec volumes, etc1557 */15581559/*1560 * generic initialization of ADC, input mixers and output mixers1561 */1562static struct hda_verb alc880_volume_init_verbs[] = {1563 /*1564 * Unmute ADC0-2 and set the default input to mic-in1565 */1566 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},1567 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},1568 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},1569 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},1570 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},1571 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},15721573 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback1574 * mixer widget1575 * Note: PASD motherboards uses the Line In 2 as the input for front1576 * panel mic (mic 2)1577 */1578 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */1579 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},1580 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},1581 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},1582 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},1583 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},1584 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},1585 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},15861587 /*1588 * Set up output mixers (0x0c - 0x0f)1589 */1590 /* set vol=0 to output mixers */1591 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},1592 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},1593 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},1594 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},1595 /* set up input amps for analog loopback */1596 /* Amp Indices: DAC = 0, mixer = 1 */1597 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},1598 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},1599 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},1600 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},1601 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},1602 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},1603 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},1604 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},16051606 { }1607};16081609/*1610 * 3-stack pin configuration:1611 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b1612 */1613static struct hda_verb alc880_pin_3stack_init_verbs[] = {1614 /*1615 * preset connection lists of input pins1616 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround1617 */1618 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */1619 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */1620 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */16211622 /*1623 * Set pin mode and muting1624 */1625 /* set front pin widgets 0x14 for output */1626 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1627 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1628 /* Mic1 (rear panel) pin widget for input and vref at 80% */1629 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1630 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1631 /* Mic2 (as headphone out) for HP output */1632 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1633 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1634 /* Line In pin widget for input */1635 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1636 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1637 /* Line2 (as front mic) pin widget for input and vref at 80% */1638 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1639 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1640 /* CD pin widget for input */1641 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},16421643 { }1644};16451646/*1647 * 5-stack pin configuration:1648 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,1649 * line-in/side = 0x1a, f-mic = 0x1b1650 */1651static struct hda_verb alc880_pin_5stack_init_verbs[] = {1652 /*1653 * preset connection lists of input pins1654 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround1655 */1656 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */1657 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */16581659 /*1660 * Set pin mode and muting1661 */1662 /* set pin widgets 0x14-0x17 for output */1663 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1664 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1665 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1666 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1667 /* unmute pins for output (no gain on this amp) */1668 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1669 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1670 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1671 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},16721673 /* Mic1 (rear panel) pin widget for input and vref at 80% */1674 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1675 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1676 /* Mic2 (as headphone out) for HP output */1677 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1678 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1679 /* Line In pin widget for input */1680 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1681 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1682 /* Line2 (as front mic) pin widget for input and vref at 80% */1683 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1684 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1685 /* CD pin widget for input */1686 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},16871688 { }1689};16901691/*1692 * W810 pin configuration:1693 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b1694 */1695static struct hda_verb alc880_pin_w810_init_verbs[] = {1696 /* hphone/speaker input selector: front DAC */1697 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},16981699 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1700 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1701 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1702 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1703 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1704 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},17051706 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1707 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},17081709 { }1710};17111712/*1713 * Z71V pin configuration:1714 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)1715 */1716static struct hda_verb alc880_pin_z71v_init_verbs[] = {1717 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1718 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1719 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1720 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},17211722 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1723 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1724 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1725 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},17261727 { }1728};17291730/*1731 * 6-stack pin configuration:1732 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,1733 * f-mic = 0x19, line = 0x1a, HP = 0x1b1734 */1735static struct hda_verb alc880_pin_6stack_init_verbs[] = {1736 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */17371738 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1739 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1740 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1741 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1742 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1743 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1744 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1745 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},17461747 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1748 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1749 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1750 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1751 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1752 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1753 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1754 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1755 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},17561757 { }1758};17591760/*1761 * Uniwill pin configuration:1762 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,1763 * line = 0x1a1764 */1765static struct hda_verb alc880_uniwill_init_verbs[] = {1766 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */17671768 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1769 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1770 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1771 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1772 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1773 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1774 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1775 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1776 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},1777 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},1778 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},1779 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},1780 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},1781 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},17821783 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1784 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1785 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1786 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1787 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1788 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1789 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */1790 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */1791 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},17921793 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},1794 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},17951796 { }1797};17981799/*1800* Uniwill P531801* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,1802 */1803static struct hda_verb alc880_uniwill_p53_init_verbs[] = {1804 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */18051806 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1807 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1808 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1809 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1810 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1811 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1812 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},1813 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},1814 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},1815 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},1816 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},1817 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},18181819 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1820 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1821 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1822 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1823 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1824 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},18251826 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},1827 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},18281829 { }1830};18311832static struct hda_verb alc880_beep_init_verbs[] = {1833 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },1834 { }1835};18361837/* toggle speaker-output according to the hp-jack state */1838static void alc880_uniwill_hp_automute(struct hda_codec *codec)1839{1840 unsigned int present;1841 unsigned char bits;18421843 present = snd_hda_codec_read(codec, 0x14, 0,1844 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;1845 bits = present ? HDA_AMP_MUTE : 0;1846 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,1847 HDA_AMP_MUTE, bits);1848 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,1849 HDA_AMP_MUTE, bits);1850}18511852/* auto-toggle front mic */1853static void alc880_uniwill_mic_automute(struct hda_codec *codec)1854{1855 unsigned int present;1856 unsigned char bits;18571858 present = snd_hda_codec_read(codec, 0x18, 0,1859 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;1860 bits = present ? HDA_AMP_MUTE : 0;1861 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);1862}18631864static void alc880_uniwill_automute(struct hda_codec *codec)1865{1866 alc880_uniwill_hp_automute(codec);1867 alc880_uniwill_mic_automute(codec);1868}18691870static void alc880_uniwill_unsol_event(struct hda_codec *codec,1871 unsigned int res)1872{1873 /* Looks like the unsol event is incompatible with the standard1874 * definition. 4bit tag is placed at 28 bit!1875 */1876 switch (res >> 28) {1877 case ALC880_HP_EVENT:1878 alc880_uniwill_hp_automute(codec);1879 break;1880 case ALC880_MIC_EVENT:1881 alc880_uniwill_mic_automute(codec);1882 break;1883 }1884}18851886static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)1887{1888 unsigned int present;1889 unsigned char bits;18901891 present = snd_hda_codec_read(codec, 0x14, 0,1892 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;1893 bits = present ? HDA_AMP_MUTE : 0;1894 snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits);1895}18961897static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)1898{1899 unsigned int present;19001901 present = snd_hda_codec_read(codec, 0x21, 0,1902 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);1903 present &= HDA_AMP_VOLMASK;1904 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,1905 HDA_AMP_VOLMASK, present);1906 snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,1907 HDA_AMP_VOLMASK, present);1908}19091910static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,1911 unsigned int res)1912{1913 /* Looks like the unsol event is incompatible with the standard1914 * definition. 4bit tag is placed at 28 bit!1915 */1916 if ((res >> 28) == ALC880_HP_EVENT)1917 alc880_uniwill_p53_hp_automute(codec);1918 if ((res >> 28) == ALC880_DCVOL_EVENT)1919 alc880_uniwill_p53_dcvol_automute(codec);1920}19211922/*1923 * F1734 pin configuration:1924 * HP = 0x14, speaker-out = 0x15, mic = 0x181925 */1926static struct hda_verb alc880_pin_f1734_init_verbs[] = {1927 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},1928 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},1929 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},1930 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},19311932 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1933 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1934 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1935 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},19361937 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1938 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1939 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1940 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1941 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1942 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1943 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1944 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1945 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},19461947 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},1948 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},19491950 { }1951};19521953/*1954 * ASUS pin configuration:1955 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a1956 */1957static struct hda_verb alc880_pin_asus_init_verbs[] = {1958 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},1959 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},1960 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},1961 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},19621963 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},1964 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1965 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1966 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1967 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1968 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1969 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1970 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},19711972 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1973 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1974 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},1975 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1976 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1977 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1978 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1979 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1980 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},19811982 { }1983};19841985/* Enable GPIO mask and set output */1986#define alc880_gpio1_init_verbs alc_gpio1_init_verbs1987#define alc880_gpio2_init_verbs alc_gpio2_init_verbs19881989/* Clevo m520g init */1990static struct hda_verb alc880_pin_clevo_init_verbs[] = {1991 /* headphone output */1992 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},1993 /* line-out */1994 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},1995 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1996 /* Line-in */1997 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1998 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1999 /* CD */2000 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},2001 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2002 /* Mic1 (rear panel) */2003 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},2004 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2005 /* Mic2 (front panel) */2006 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},2007 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2008 /* headphone */2009 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},2010 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2011 /* change to EAPD mode */2012 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},2013 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},20142015 { }2016};20172018static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {2019 /* change to EAPD mode */2020 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},2021 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},20222023 /* Headphone output */2024 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},2025 /* Front output*/2026 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},2027 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},20282029 /* Line In pin widget for input */2030 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},2031 /* CD pin widget for input */2032 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},2033 /* Mic1 (rear panel) pin widget for input and vref at 80% */2034 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},20352036 /* change to EAPD mode */2037 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},2038 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},20392040 { }2041};20422043/*2044 * LG m1 express dual2045 *2046 * Pin assignment:2047 * Rear Line-In/Out (blue): 0x142048 * Build-in Mic-In: 0x152049 * Speaker-out: 0x172050 * HP-Out (green): 0x1b2051 * Mic-In/Out (red): 0x192052 * SPDIF-Out: 0x1e2053 */20542055/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */2056static hda_nid_t alc880_lg_dac_nids[3] = {2057 0x05, 0x02, 0x032058};20592060/* seems analog CD is not working */2061static struct hda_input_mux alc880_lg_capture_source = {2062 .num_items = 3,2063 .items = {2064 { "Mic", 0x1 },2065 { "Line", 0x5 },2066 { "Internal Mic", 0x6 },2067 },2068};20692070/* 2,4,6 channel modes */2071static struct hda_verb alc880_lg_ch2_init[] = {2072 /* set line-in and mic-in to input */2073 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },2074 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },2075 { }2076};20772078static struct hda_verb alc880_lg_ch4_init[] = {2079 /* set line-in to out and mic-in to input */2080 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },2081 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },2082 { }2083};20842085static struct hda_verb alc880_lg_ch6_init[] = {2086 /* set line-in and mic-in to output */2087 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },2088 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },2089 { }2090};20912092static struct hda_channel_mode alc880_lg_ch_modes[3] = {2093 { 2, alc880_lg_ch2_init },2094 { 4, alc880_lg_ch4_init },2095 { 6, alc880_lg_ch6_init },2096};20972098static struct snd_kcontrol_new alc880_lg_mixer[] = {2099 HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),2100 HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),2101 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),2102 HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),2103 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),2104 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),2105 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),2106 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),2107 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),2108 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),2109 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),2110 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),2111 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),2112 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),2113 {2114 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,2115 .name = "Channel Mode",2116 .info = alc_ch_mode_info,2117 .get = alc_ch_mode_get,2118 .put = alc_ch_mode_put,2119 },2120 { } /* end */2121};21222123static struct hda_verb alc880_lg_init_verbs[] = {2124 /* set capture source to mic-in */2125 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},2126 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},2127 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},2128 /* mute all amp mixer inputs */2129 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},2130 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},2131 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},2132 /* line-in to input */2133 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},2134 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2135 /* built-in mic */2136 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},2137 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2138 /* speaker-out */2139 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},2140 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2141 /* mic-in to input */2142 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},2143 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},2144 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2145 /* HP-out */2146 {0x13, AC_VERB_SET_CONNECT_SEL, 0x03},2147 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},2148 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2149 /* jack sense */2150 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},2151 { }2152};21532154/* toggle speaker-output according to the hp-jack state */2155static void alc880_lg_automute(struct hda_codec *codec)2156{2157 unsigned int present;2158 unsigned char bits;21592160 present = snd_hda_codec_read(codec, 0x1b, 0,2161 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;2162 bits = present ? HDA_AMP_MUTE : 0;2163 snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,2164 HDA_AMP_MUTE, bits);2165}21662167static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res)2168{2169 /* Looks like the unsol event is incompatible with the standard2170 * definition. 4bit tag is placed at 28 bit!2171 */2172 if ((res >> 28) == 0x01)2173 alc880_lg_automute(codec);2174}21752176/*2177 * LG LW202178 *2179 * Pin assignment:2180 * Speaker-out: 0x142181 * Mic-In: 0x182182 * Built-in Mic-In: 0x192183 * Line-In: 0x1b2184 * HP-Out: 0x1a2185 * SPDIF-Out: 0x1e2186 */21872188static struct hda_input_mux alc880_lg_lw_capture_source = {2189 .num_items = 3,2190 .items = {2191 { "Mic", 0x0 },2192 { "Internal Mic", 0x1 },2193 { "Line In", 0x2 },2194 },2195};21962197#define alc880_lg_lw_modes alc880_threestack_modes21982199static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {2200 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),2201 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),2202 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),2203 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),2204 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),2205 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),2206 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),2207 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),2208 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),2209 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),2210 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),2211 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),2212 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),2213 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),2214 {2215 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,2216 .name = "Channel Mode",2217 .info = alc_ch_mode_info,2218 .get = alc_ch_mode_get,2219 .put = alc_ch_mode_put,2220 },2221 { } /* end */2222};22232224static struct hda_verb alc880_lg_lw_init_verbs[] = {2225 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */2226 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */2227 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */22282229 /* set capture source to mic-in */2230 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},2231 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},2232 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},2233 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},2234 /* speaker-out */2235 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},2236 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2237 /* HP-out */2238 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},2239 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2240 /* mic-in to input */2241 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},2242 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2243 /* built-in mic */2244 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},2245 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2246 /* jack sense */2247 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},2248 { }2249};22502251/* toggle speaker-output according to the hp-jack state */2252static void alc880_lg_lw_automute(struct hda_codec *codec)2253{2254 unsigned int present;2255 unsigned char bits;22562257 present = snd_hda_codec_read(codec, 0x1b, 0,2258 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;2259 bits = present ? HDA_AMP_MUTE : 0;2260 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,2261 HDA_AMP_MUTE, bits);2262}22632264static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)2265{2266 /* Looks like the unsol event is incompatible with the standard2267 * definition. 4bit tag is placed at 28 bit!2268 */2269 if ((res >> 28) == 0x01)2270 alc880_lg_lw_automute(codec);2271}22722273#ifdef CONFIG_SND_HDA_POWER_SAVE2274static struct hda_amp_list alc880_loopbacks[] = {2275 { 0x0b, HDA_INPUT, 0 },2276 { 0x0b, HDA_INPUT, 1 },2277 { 0x0b, HDA_INPUT, 2 },2278 { 0x0b, HDA_INPUT, 3 },2279 { 0x0b, HDA_INPUT, 4 },2280 { } /* end */2281};22822283static struct hda_amp_list alc880_lg_loopbacks[] = {2284 { 0x0b, HDA_INPUT, 1 },2285 { 0x0b, HDA_INPUT, 6 },2286 { 0x0b, HDA_INPUT, 7 },2287 { } /* end */2288};2289#endif22902291/*2292 * Common callbacks2293 */22942295static int alc_init(struct hda_codec *codec)2296{2297 struct alc_spec *spec = codec->spec;2298 unsigned int i;22992300 for (i = 0; i < spec->num_init_verbs; i++)2301 snd_hda_sequence_write(codec, spec->init_verbs[i]);23022303 if (spec->init_hook)2304 spec->init_hook(codec);23052306 return 0;2307}23082309static void alc_unsol_event(struct hda_codec *codec, unsigned int res)2310{2311 struct alc_spec *spec = codec->spec;23122313 if (spec->unsol_event)2314 spec->unsol_event(codec, res);2315}23162317#ifdef CONFIG_SND_HDA_POWER_SAVE2318static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)2319{2320 struct alc_spec *spec = codec->spec;2321 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);2322}2323#endif23242325/*2326 * Analog playback callbacks2327 */2328static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,2329 struct hda_codec *codec,2330 struct snd_pcm_substream *substream)2331{2332 struct alc_spec *spec = codec->spec;2333 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,2334 hinfo);2335}23362337static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,2338 struct hda_codec *codec,2339 unsigned int stream_tag,2340 unsigned int format,2341 struct snd_pcm_substream *substream)2342{2343 struct alc_spec *spec = codec->spec;2344 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,2345 stream_tag, format, substream);2346}23472348static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,2349 struct hda_codec *codec,2350 struct snd_pcm_substream *substream)2351{2352 struct alc_spec *spec = codec->spec;2353 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);2354}23552356/*2357 * Digital out2358 */2359static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,2360 struct hda_codec *codec,2361 struct snd_pcm_substream *substream)2362{2363 struct alc_spec *spec = codec->spec;2364 return snd_hda_multi_out_dig_open(codec, &spec->multiout);2365}23662367static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,2368 struct hda_codec *codec,2369 unsigned int stream_tag,2370 unsigned int format,2371 struct snd_pcm_substream *substream)2372{2373 struct alc_spec *spec = codec->spec;2374 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,2375 stream_tag, format, substream);2376}23772378static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,2379 struct hda_codec *codec,2380 struct snd_pcm_substream *substream)2381{2382 struct alc_spec *spec = codec->spec;2383 return snd_hda_multi_out_dig_close(codec, &spec->multiout);2384}23852386/*2387 * Analog capture2388 */2389static int alc880_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,2390 struct hda_codec *codec,2391 unsigned int stream_tag,2392 unsigned int format,2393 struct snd_pcm_substream *substream)2394{2395 struct alc_spec *spec = codec->spec;23962397 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],2398 stream_tag, 0, format);2399 return 0;2400}24012402static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,2403 struct hda_codec *codec,2404 struct snd_pcm_substream *substream)2405{2406 struct alc_spec *spec = codec->spec;24072408 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],2409 0, 0, 0);2410 return 0;2411}241224132414/*2415 */2416static struct hda_pcm_stream alc880_pcm_analog_playback = {2417 .substreams = 1,2418 .channels_min = 2,2419 .channels_max = 8,2420 /* NID is set in alc_build_pcms */2421 .ops = {2422 .open = alc880_playback_pcm_open,2423 .prepare = alc880_playback_pcm_prepare,2424 .cleanup = alc880_playback_pcm_cleanup2425 },2426};24272428static struct hda_pcm_stream alc880_pcm_analog_capture = {2429 .substreams = 1,2430 .channels_min = 2,2431 .channels_max = 2,2432 /* NID is set in alc_build_pcms */2433};24342435static struct hda_pcm_stream alc880_pcm_analog_alt_playback = {2436 .substreams = 1,2437 .channels_min = 2,2438 .channels_max = 2,2439 /* NID is set in alc_build_pcms */2440};24412442static struct hda_pcm_stream alc880_pcm_analog_alt_capture = {2443 .substreams = 2, /* can be overridden */2444 .channels_min = 2,2445 .channels_max = 2,2446 /* NID is set in alc_build_pcms */2447 .ops = {2448 .prepare = alc880_alt_capture_pcm_prepare,2449 .cleanup = alc880_alt_capture_pcm_cleanup2450 },2451};24522453static struct hda_pcm_stream alc880_pcm_digital_playback = {2454 .substreams = 1,2455 .channels_min = 2,2456 .channels_max = 2,2457 /* NID is set in alc_build_pcms */2458 .ops = {2459 .open = alc880_dig_playback_pcm_open,2460 .close = alc880_dig_playback_pcm_close,2461 .prepare = alc880_dig_playback_pcm_prepare2462 },2463};24642465static struct hda_pcm_stream alc880_pcm_digital_capture = {2466 .substreams = 1,2467 .channels_min = 2,2468 .channels_max = 2,2469 /* NID is set in alc_build_pcms */2470};24712472/* Used by alc_build_pcms to flag that a PCM has no playback stream */2473static struct hda_pcm_stream alc_pcm_null_stream = {2474 .substreams = 0,2475 .channels_min = 0,2476 .channels_max = 0,2477};24782479static int alc_build_pcms(struct hda_codec *codec)2480{2481 struct alc_spec *spec = codec->spec;2482 struct hda_pcm *info = spec->pcm_rec;2483 int i;24842485 codec->num_pcms = 1;2486 codec->pcm_info = info;24872488 info->name = spec->stream_name_analog;2489 if (spec->stream_analog_playback) {2490 snd_assert(spec->multiout.dac_nids, return -EINVAL);2491 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);2492 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];2493 }2494 if (spec->stream_analog_capture) {2495 snd_assert(spec->adc_nids, return -EINVAL);2496 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);2497 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];2498 }24992500 if (spec->channel_mode) {2501 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;2502 for (i = 0; i < spec->num_channel_mode; i++) {2503 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {2504 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;2505 }2506 }2507 }25082509 /* SPDIF for stream index #1 */2510 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {2511 codec->num_pcms = 2;2512 info = spec->pcm_rec + 1;2513 info->name = spec->stream_name_digital;2514 info->pcm_type = HDA_PCM_TYPE_SPDIF;2515 if (spec->multiout.dig_out_nid &&2516 spec->stream_digital_playback) {2517 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);2518 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;2519 }2520 if (spec->dig_in_nid &&2521 spec->stream_digital_capture) {2522 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);2523 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;2524 }2525 }25262527 /* If the use of more than one ADC is requested for the current2528 * model, configure a second analog capture-only PCM.2529 */2530 /* Additional Analaog capture for index #2 */2531 if ((spec->alt_dac_nid && spec->stream_analog_alt_playback) ||2532 (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture)) {2533 codec->num_pcms = 3;2534 info = spec->pcm_rec + 2;2535 info->name = spec->stream_name_analog;2536 if (spec->alt_dac_nid) {2537 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =2538 *spec->stream_analog_alt_playback;2539 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =2540 spec->alt_dac_nid;2541 } else {2542 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =2543 alc_pcm_null_stream;2544 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;2545 }2546 if (spec->num_adc_nids > 1) {2547 info->stream[SNDRV_PCM_STREAM_CAPTURE] =2548 *spec->stream_analog_alt_capture;2549 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =2550 spec->adc_nids[1];2551 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =2552 spec->num_adc_nids - 1;2553 } else {2554 info->stream[SNDRV_PCM_STREAM_CAPTURE] =2555 alc_pcm_null_stream;2556 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;2557 }2558 }25592560 return 0;2561}25622563static void alc_free(struct hda_codec *codec)2564{2565 struct alc_spec *spec = codec->spec;2566 unsigned int i;25672568 if (!spec)2569 return;25702571 if (spec->kctl_alloc) {2572 for (i = 0; i < spec->num_kctl_used; i++)2573 kfree(spec->kctl_alloc[i].name);2574 kfree(spec->kctl_alloc);2575 }2576 kfree(spec);2577}25782579/*2580 */2581static struct hda_codec_ops alc_patch_ops = {2582 .build_controls = alc_build_controls,2583 .build_pcms = alc_build_pcms,2584 .init = alc_init,2585 .free = alc_free,2586 .unsol_event = alc_unsol_event,2587#ifdef CONFIG_SND_HDA_POWER_SAVE2588 .check_power_status = alc_check_power_status,2589#endif2590};259125922593/*2594 * Test configuration for debugging2595 *2596 * Almost all inputs/outputs are enabled. I/O pins can be configured via2597 * enum controls.2598 */2599#ifdef CONFIG_SND_DEBUG2600static hda_nid_t alc880_test_dac_nids[4] = {2601 0x02, 0x03, 0x04, 0x052602};26032604static struct hda_input_mux alc880_test_capture_source = {2605 .num_items = 7,2606 .items = {2607 { "In-1", 0x0 },2608 { "In-2", 0x1 },2609 { "In-3", 0x2 },2610 { "In-4", 0x3 },2611 { "CD", 0x4 },2612 { "Front", 0x5 },2613 { "Surround", 0x6 },2614 },2615};26162617static struct hda_channel_mode alc880_test_modes[4] = {2618 { 2, NULL },2619 { 4, NULL },2620 { 6, NULL },2621 { 8, NULL },2622};26232624static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,2625 struct snd_ctl_elem_info *uinfo)2626{2627 static char *texts[] = {2628 "N/A", "Line Out", "HP Out",2629 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"2630 };2631 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;2632 uinfo->count = 1;2633 uinfo->value.enumerated.items = 8;2634 if (uinfo->value.enumerated.item >= 8)2635 uinfo->value.enumerated.item = 7;2636 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);2637 return 0;2638}26392640static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,2641 struct snd_ctl_elem_value *ucontrol)2642{2643 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);2644 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;2645 unsigned int pin_ctl, item = 0;26462647 pin_ctl = snd_hda_codec_read(codec, nid, 0,2648 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);2649 if (pin_ctl & AC_PINCTL_OUT_EN) {2650 if (pin_ctl & AC_PINCTL_HP_EN)2651 item = 2;2652 else2653 item = 1;2654 } else if (pin_ctl & AC_PINCTL_IN_EN) {2655 switch (pin_ctl & AC_PINCTL_VREFEN) {2656 case AC_PINCTL_VREF_HIZ: item = 3; break;2657 case AC_PINCTL_VREF_50: item = 4; break;2658 case AC_PINCTL_VREF_GRD: item = 5; break;2659 case AC_PINCTL_VREF_80: item = 6; break;2660 case AC_PINCTL_VREF_100: item = 7; break;2661 }2662 }2663 ucontrol->value.enumerated.item[0] = item;2664 return 0;2665}26662667static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,2668 struct snd_ctl_elem_value *ucontrol)2669{2670 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);2671 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;2672 static unsigned int ctls[] = {2673 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,2674 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,2675 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,2676 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,2677 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,2678 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,2679 };2680 unsigned int old_ctl, new_ctl;26812682 old_ctl = snd_hda_codec_read(codec, nid, 0,2683 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);2684 new_ctl = ctls[ucontrol->value.enumerated.item[0]];2685 if (old_ctl != new_ctl) {2686 int val;2687 snd_hda_codec_write_cache(codec, nid, 0,2688 AC_VERB_SET_PIN_WIDGET_CONTROL,2689 new_ctl);2690 val = ucontrol->value.enumerated.item[0] >= 3 ?2691 HDA_AMP_MUTE : 0;2692 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,2693 HDA_AMP_MUTE, val);2694 return 1;2695 }2696 return 0;2697}26982699static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,2700 struct snd_ctl_elem_info *uinfo)2701{2702 static char *texts[] = {2703 "Front", "Surround", "CLFE", "Side"2704 };2705 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;2706 uinfo->count = 1;2707 uinfo->value.enumerated.items = 4;2708 if (uinfo->value.enumerated.item >= 4)2709 uinfo->value.enumerated.item = 3;2710 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);2711 return 0;2712}27132714static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,2715 struct snd_ctl_elem_value *ucontrol)2716{2717 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);2718 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;2719 unsigned int sel;27202721 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);2722 ucontrol->value.enumerated.item[0] = sel & 3;2723 return 0;2724}27252726static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,2727 struct snd_ctl_elem_value *ucontrol)2728{2729 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);2730 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;2731 unsigned int sel;27322733 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;2734 if (ucontrol->value.enumerated.item[0] != sel) {2735 sel = ucontrol->value.enumerated.item[0] & 3;2736 snd_hda_codec_write_cache(codec, nid, 0,2737 AC_VERB_SET_CONNECT_SEL, sel);2738 return 1;2739 }2740 return 0;2741}27422743#define PIN_CTL_TEST(xname,nid) { \2744 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \2745 .name = xname, \2746 .info = alc_test_pin_ctl_info, \2747 .get = alc_test_pin_ctl_get, \2748 .put = alc_test_pin_ctl_put, \2749 .private_value = nid \2750 }27512752#define PIN_SRC_TEST(xname,nid) { \2753 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \2754 .name = xname, \2755 .info = alc_test_pin_src_info, \2756 .get = alc_test_pin_src_get, \2757 .put = alc_test_pin_src_put, \2758 .private_value = nid \2759 }27602761static struct snd_kcontrol_new alc880_test_mixer[] = {2762 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),2763 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),2764 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),2765 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),2766 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),2767 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),2768 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),2769 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),2770 PIN_CTL_TEST("Front Pin Mode", 0x14),2771 PIN_CTL_TEST("Surround Pin Mode", 0x15),2772 PIN_CTL_TEST("CLFE Pin Mode", 0x16),2773 PIN_CTL_TEST("Side Pin Mode", 0x17),2774 PIN_CTL_TEST("In-1 Pin Mode", 0x18),2775 PIN_CTL_TEST("In-2 Pin Mode", 0x19),2776 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),2777 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),2778 PIN_SRC_TEST("In-1 Pin Source", 0x18),2779 PIN_SRC_TEST("In-2 Pin Source", 0x19),2780 PIN_SRC_TEST("In-3 Pin Source", 0x1a),2781 PIN_SRC_TEST("In-4 Pin Source", 0x1b),2782 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),2783 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),2784 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),2785 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),2786 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),2787 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),2788 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),2789 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),2790 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),2791 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),2792 {2793 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,2794 .name = "Channel Mode",2795 .info = alc_ch_mode_info,2796 .get = alc_ch_mode_get,2797 .put = alc_ch_mode_put,2798 },2799 { } /* end */2800};28012802static struct hda_verb alc880_test_init_verbs[] = {2803 /* Unmute inputs of 0x0c - 0x0f */2804 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},2805 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},2806 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},2807 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},2808 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},2809 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},2810 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},2811 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},2812 /* Vol output for 0x0c-0x0f */2813 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},2814 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},2815 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},2816 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},2817 /* Set output pins 0x14-0x17 */2818 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},2819 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},2820 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},2821 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},2822 /* Unmute output pins 0x14-0x17 */2823 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2824 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2825 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2826 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},2827 /* Set input pins 0x18-0x1c */2828 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},2829 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},2830 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},2831 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},2832 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},2833 /* Mute input pins 0x18-0x1b */2834 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},2835 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},2836 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},2837 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},2838 /* ADC set up */2839 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},2840 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},2841 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},2842 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},2843 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},2844 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},2845 /* Analog input/passthru */2846 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},2847 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},2848 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},2849 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},2850 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},2851 { }2852};2853#endif28542855/*2856 */28572858static const char *alc880_models[ALC880_MODEL_LAST] = {2859 [ALC880_3ST] = "3stack",2860 [ALC880_TCL_S700] = "tcl",2861 [ALC880_3ST_DIG] = "3stack-digout",2862 [ALC880_CLEVO] = "clevo",2863 [ALC880_5ST] = "5stack",2864 [ALC880_5ST_DIG] = "5stack-digout",2865 [ALC880_W810] = "w810",2866 [ALC880_Z71V] = "z71v",2867 [ALC880_6ST] = "6stack",2868 [ALC880_6ST_DIG] = "6stack-digout",2869 [ALC880_ASUS] = "asus",2870 [ALC880_ASUS_W1V] = "asus-w1v",2871 [ALC880_ASUS_DIG] = "asus-dig",2872 [ALC880_ASUS_DIG2] = "asus-dig2",2873 [ALC880_UNIWILL_DIG] = "uniwill",2874 [ALC880_UNIWILL_P53] = "uniwill-p53",2875 [ALC880_FUJITSU] = "fujitsu",2876 [ALC880_F1734] = "F1734",2877 [ALC880_LG] = "lg",2878 [ALC880_LG_LW] = "lg-lw",2879#ifdef CONFIG_SND_DEBUG2880 [ALC880_TEST] = "test",2881#endif2882 [ALC880_AUTO] = "auto",2883};28842885static struct snd_pci_quirk alc880_cfg_tbl[] = {2886 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),2887 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),2888 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),2889 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),2890 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),2891 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),2892 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),2893 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),2894 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),2895 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),2896 SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),2897 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),2898 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),2899 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),2900 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),2901 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),2902 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),2903 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),2904 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */2905 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),2906 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),2907 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS),2908 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),2909 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),2910 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),2911 SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS), /* default ASUS */2912 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),2913 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),2914 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),2915 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),2916 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),2917 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),2918 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),2919 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),2920 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),2921 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),2922 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),2923 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),2924 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),2925 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),2926 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),2927 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),2928 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),2929 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),2930 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),2931 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),2932 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),2933 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),2934 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),2935 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),2936 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),2937 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),2938 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),2939 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),2940 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */2941 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),2942 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),2943 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),2944 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),2945 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),2946 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),2947 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),2948 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),2949 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),2950 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),2951 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),2952 SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST), /* default Intel */2953 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),2954 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),2955 {}2956};29572958/*2959 * ALC880 codec presets2960 */2961static struct alc_config_preset alc880_presets[] = {2962 [ALC880_3ST] = {2963 .mixers = { alc880_three_stack_mixer },2964 .init_verbs = { alc880_volume_init_verbs,2965 alc880_pin_3stack_init_verbs },2966 .num_dacs = ARRAY_SIZE(alc880_dac_nids),2967 .dac_nids = alc880_dac_nids,2968 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),2969 .channel_mode = alc880_threestack_modes,2970 .need_dac_fix = 1,2971 .input_mux = &alc880_capture_source,2972 },2973 [ALC880_3ST_DIG] = {2974 .mixers = { alc880_three_stack_mixer },2975 .init_verbs = { alc880_volume_init_verbs,2976 alc880_pin_3stack_init_verbs },2977 .num_dacs = ARRAY_SIZE(alc880_dac_nids),2978 .dac_nids = alc880_dac_nids,2979 .dig_out_nid = ALC880_DIGOUT_NID,2980 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),2981 .channel_mode = alc880_threestack_modes,2982 .need_dac_fix = 1,2983 .input_mux = &alc880_capture_source,2984 },2985 [ALC880_TCL_S700] = {2986 .mixers = { alc880_tcl_s700_mixer },2987 .init_verbs = { alc880_volume_init_verbs,2988 alc880_pin_tcl_S700_init_verbs,2989 alc880_gpio2_init_verbs },2990 .num_dacs = ARRAY_SIZE(alc880_dac_nids),2991 .dac_nids = alc880_dac_nids,2992 .hp_nid = 0x03,2993 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),2994 .channel_mode = alc880_2_jack_modes,2995 .input_mux = &alc880_capture_source,2996 },2997 [ALC880_5ST] = {2998 .mixers = { alc880_three_stack_mixer,2999 alc880_five_stack_mixer},3000 .init_verbs = { alc880_volume_init_verbs,3001 alc880_pin_5stack_init_verbs },3002 .num_dacs = ARRAY_SIZE(alc880_dac_nids),3003 .dac_nids = alc880_dac_nids,3004 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),3005 .channel_mode = alc880_fivestack_modes,3006 .input_mux = &alc880_capture_source,3007 },3008 [ALC880_5ST_DIG] = {3009 .mixers = { alc880_three_stack_mixer,3010 alc880_five_stack_mixer },3011 .init_verbs = { alc880_volume_init_verbs,3012 alc880_pin_5stack_init_verbs },3013 .num_dacs = ARRAY_SIZE(alc880_dac_nids),3014 .dac_nids = alc880_dac_nids,3015 .dig_out_nid = ALC880_DIGOUT_NID,3016 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),3017 .channel_mode = alc880_fivestack_modes,3018 .input_mux = &alc880_capture_source,3019 },3020 [ALC880_6ST] = {3021 .mixers = { alc880_six_stack_mixer },3022 .init_verbs = { alc880_volume_init_verbs,3023 alc880_pin_6stack_init_verbs },3024 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),3025 .dac_nids = alc880_6st_dac_nids,3026 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),3027 .channel_mode = alc880_sixstack_modes,3028 .input_mux = &alc880_6stack_capture_source,3029 },3030 [ALC880_6ST_DIG] = {3031 .mixers = { alc880_six_stack_mixer },3032 .init_verbs = { alc880_volume_init_verbs,3033 alc880_pin_6stack_init_verbs },3034 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),3035 .dac_nids = alc880_6st_dac_nids,3036 .dig_out_nid = ALC880_DIGOUT_NID,3037 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),3038 .channel_mode = alc880_sixstack_modes,3039 .input_mux = &alc880_6stack_capture_source,3040 },3041 [ALC880_W810] = {3042 .mixers = { alc880_w810_base_mixer },3043 .init_verbs = { alc880_volume_init_verbs,3044 alc880_pin_w810_init_verbs,3045 alc880_gpio2_init_verbs },3046 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),3047 .dac_nids = alc880_w810_dac_nids,3048 .dig_out_nid = ALC880_DIGOUT_NID,3049 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),3050 .channel_mode = alc880_w810_modes,3051 .input_mux = &alc880_capture_source,3052 },3053 [ALC880_Z71V] = {3054 .mixers = { alc880_z71v_mixer },3055 .init_verbs = { alc880_volume_init_verbs,3056 alc880_pin_z71v_init_verbs },3057 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),3058 .dac_nids = alc880_z71v_dac_nids,3059 .dig_out_nid = ALC880_DIGOUT_NID,3060 .hp_nid = 0x03,3061 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),3062 .channel_mode = alc880_2_jack_modes,3063 .input_mux = &alc880_capture_source,3064 },3065 [ALC880_F1734] = {3066 .mixers = { alc880_f1734_mixer },3067 .init_verbs = { alc880_volume_init_verbs,3068 alc880_pin_f1734_init_verbs },3069 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),3070 .dac_nids = alc880_f1734_dac_nids,3071 .hp_nid = 0x02,3072 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),3073 .channel_mode = alc880_2_jack_modes,3074 .input_mux = &alc880_f1734_capture_source,3075 .unsol_event = alc880_uniwill_p53_unsol_event,3076 .init_hook = alc880_uniwill_p53_hp_automute,3077 },3078 [ALC880_ASUS] = {3079 .mixers = { alc880_asus_mixer },3080 .init_verbs = { alc880_volume_init_verbs,3081 alc880_pin_asus_init_verbs,3082 alc880_gpio1_init_verbs },3083 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),3084 .dac_nids = alc880_asus_dac_nids,3085 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),3086 .channel_mode = alc880_asus_modes,3087 .need_dac_fix = 1,3088 .input_mux = &alc880_capture_source,3089 },3090 [ALC880_ASUS_DIG] = {3091 .mixers = { alc880_asus_mixer },3092 .init_verbs = { alc880_volume_init_verbs,3093 alc880_pin_asus_init_verbs,3094 alc880_gpio1_init_verbs },3095 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),3096 .dac_nids = alc880_asus_dac_nids,3097 .dig_out_nid = ALC880_DIGOUT_NID,3098 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),3099 .channel_mode = alc880_asus_modes,3100 .need_dac_fix = 1,3101 .input_mux = &alc880_capture_source,3102 },3103 [ALC880_ASUS_DIG2] = {3104 .mixers = { alc880_asus_mixer },3105 .init_verbs = { alc880_volume_init_verbs,3106 alc880_pin_asus_init_verbs,3107 alc880_gpio2_init_verbs }, /* use GPIO2 */3108 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),3109 .dac_nids = alc880_asus_dac_nids,3110 .dig_out_nid = ALC880_DIGOUT_NID,3111 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),3112 .channel_mode = alc880_asus_modes,3113 .need_dac_fix = 1,3114 .input_mux = &alc880_capture_source,3115 },3116 [ALC880_ASUS_W1V] = {3117 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },3118 .init_verbs = { alc880_volume_init_verbs,3119 alc880_pin_asus_init_verbs,3120 alc880_gpio1_init_verbs },3121 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),3122 .dac_nids = alc880_asus_dac_nids,3123 .dig_out_nid = ALC880_DIGOUT_NID,3124 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),3125 .channel_mode = alc880_asus_modes,3126 .need_dac_fix = 1,3127 .input_mux = &alc880_capture_source,3128 },3129 [ALC880_UNIWILL_DIG] = {3130 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },3131 .init_verbs = { alc880_volume_init_verbs,3132 alc880_pin_asus_init_verbs },3133 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),3134 .dac_nids = alc880_asus_dac_nids,3135 .dig_out_nid = ALC880_DIGOUT_NID,3136 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),3137 .channel_mode = alc880_asus_modes,3138 .need_dac_fix = 1,3139 .input_mux = &alc880_capture_source,3140 },3141 [ALC880_UNIWILL] = {3142 .mixers = { alc880_uniwill_mixer },3143 .init_verbs = { alc880_volume_init_verbs,3144 alc880_uniwill_init_verbs },3145 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),3146 .dac_nids = alc880_asus_dac_nids,3147 .dig_out_nid = ALC880_DIGOUT_NID,3148 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),3149 .channel_mode = alc880_threestack_modes,3150 .need_dac_fix = 1,3151 .input_mux = &alc880_capture_source,3152 .unsol_event = alc880_uniwill_unsol_event,3153 .init_hook = alc880_uniwill_automute,3154 },3155 [ALC880_UNIWILL_P53] = {3156 .mixers = { alc880_uniwill_p53_mixer },3157 .init_verbs = { alc880_volume_init_verbs,3158 alc880_uniwill_p53_init_verbs },3159 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),3160 .dac_nids = alc880_asus_dac_nids,3161 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),3162 .channel_mode = alc880_threestack_modes,3163 .input_mux = &alc880_capture_source,3164 .unsol_event = alc880_uniwill_p53_unsol_event,3165 .init_hook = alc880_uniwill_p53_hp_automute,3166 },3167 [ALC880_FUJITSU] = {3168 .mixers = { alc880_fujitsu_mixer,3169 alc880_pcbeep_mixer, },3170 .init_verbs = { alc880_volume_init_verbs,3171 alc880_uniwill_p53_init_verbs,3172 alc880_beep_init_verbs },3173 .num_dacs = ARRAY_SIZE(alc880_dac_nids),3174 .dac_nids = alc880_dac_nids,3175 .dig_out_nid = ALC880_DIGOUT_NID,3176 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),3177 .channel_mode = alc880_2_jack_modes,3178 .input_mux = &alc880_capture_source,3179 .unsol_event = alc880_uniwill_p53_unsol_event,3180 .init_hook = alc880_uniwill_p53_hp_automute,3181 },3182 [ALC880_CLEVO] = {3183 .mixers = { alc880_three_stack_mixer },3184 .init_verbs = { alc880_volume_init_verbs,3185 alc880_pin_clevo_init_verbs },3186 .num_dacs = ARRAY_SIZE(alc880_dac_nids),3187 .dac_nids = alc880_dac_nids,3188 .hp_nid = 0x03,3189 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),3190 .channel_mode = alc880_threestack_modes,3191 .need_dac_fix = 1,3192 .input_mux = &alc880_capture_source,3193 },3194 [ALC880_LG] = {3195 .mixers = { alc880_lg_mixer },3196 .init_verbs = { alc880_volume_init_verbs,3197 alc880_lg_init_verbs },3198 .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),3199 .dac_nids = alc880_lg_dac_nids,3200 .dig_out_nid = ALC880_DIGOUT_NID,3201 .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),3202 .channel_mode = alc880_lg_ch_modes,3203 .need_dac_fix = 1,3204 .input_mux = &alc880_lg_capture_source,3205 .unsol_event = alc880_lg_unsol_event,3206 .init_hook = alc880_lg_automute,3207#ifdef CONFIG_SND_HDA_POWER_SAVE3208 .loopbacks = alc880_lg_loopbacks,3209#endif3210 },3211 [ALC880_LG_LW] = {3212 .mixers = { alc880_lg_lw_mixer },3213 .init_verbs = { alc880_volume_init_verbs,3214 alc880_lg_lw_init_verbs },3215 .num_dacs = ARRAY_SIZE(alc880_dac_nids),3216 .dac_nids = alc880_dac_nids,3217 .dig_out_nid = ALC880_DIGOUT_NID,3218 .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),3219 .channel_mode = alc880_lg_lw_modes,3220 .input_mux = &alc880_lg_lw_capture_source,3221 .unsol_event = alc880_lg_lw_unsol_event,3222 .init_hook = alc880_lg_lw_automute,3223 },3224#ifdef CONFIG_SND_DEBUG3225 [ALC880_TEST] = {3226 .mixers = { alc880_test_mixer },3227 .init_verbs = { alc880_test_init_verbs },3228 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),3229 .dac_nids = alc880_test_dac_nids,3230 .dig_out_nid = ALC880_DIGOUT_NID,3231 .num_channel_mode = ARRAY_SIZE(alc880_test_modes),3232 .channel_mode = alc880_test_modes,3233 .input_mux = &alc880_test_capture_source,3234 },3235#endif3236};32373238/*3239 * Automatic parse of I/O pins from the BIOS configuration3240 */32413242#define NUM_CONTROL_ALLOC 323243#define NUM_VERB_ALLOC 3232443245enum {3246 ALC_CTL_WIDGET_VOL,3247 ALC_CTL_WIDGET_MUTE,3248 ALC_CTL_BIND_MUTE,3249};3250static struct snd_kcontrol_new alc880_control_templates[] = {3251 HDA_CODEC_VOLUME(NULL, 0, 0, 0),3252 HDA_CODEC_MUTE(NULL, 0, 0, 0),3253 HDA_BIND_MUTE(NULL, 0, 0, 0),3254};32553256/* add dynamic controls */3257static int add_control(struct alc_spec *spec, int type, const char *name,3258 unsigned long val)3259{3260 struct snd_kcontrol_new *knew;32613262 if (spec->num_kctl_used >= spec->num_kctl_alloc) {3263 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;32643265 /* array + terminator */3266 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);3267 if (!knew)3268 return -ENOMEM;3269 if (spec->kctl_alloc) {3270 memcpy(knew, spec->kctl_alloc,3271 sizeof(*knew) * spec->num_kctl_alloc);3272 kfree(spec->kctl_alloc);3273 }3274 spec->kctl_alloc = knew;3275 spec->num_kctl_alloc = num;3276 }32773278 knew = &spec->kctl_alloc[spec->num_kctl_used];3279 *knew = alc880_control_templates[type];3280 knew->name = kstrdup(name, GFP_KERNEL);3281 if (!knew->name)3282 return -ENOMEM;3283 knew->private_value = val;3284 spec->num_kctl_used++;3285 return 0;3286}32873288#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)3289#define alc880_fixed_pin_idx(nid) ((nid) - 0x14)3290#define alc880_is_multi_pin(nid) ((nid) >= 0x18)3291#define alc880_multi_pin_idx(nid) ((nid) - 0x18)3292#define alc880_is_input_pin(nid) ((nid) >= 0x18)3293#define alc880_input_pin_idx(nid) ((nid) - 0x18)3294#define alc880_idx_to_dac(nid) ((nid) + 0x02)3295#define alc880_dac_to_idx(nid) ((nid) - 0x02)3296#define alc880_idx_to_mixer(nid) ((nid) + 0x0c)3297#define alc880_idx_to_selector(nid) ((nid) + 0x10)3298#define ALC880_PIN_CD_NID 0x1c32993300/* fill in the dac_nids table from the parsed pin configuration */3301static int alc880_auto_fill_dac_nids(struct alc_spec *spec,3302 const struct auto_pin_cfg *cfg)3303{3304 hda_nid_t nid;3305 int assigned[4];3306 int i, j;33073308 memset(assigned, 0, sizeof(assigned));3309 spec->multiout.dac_nids = spec->private_dac_nids;33103311 /* check the pins hardwired to audio widget */3312 for (i = 0; i < cfg->line_outs; i++) {3313 nid = cfg->line_out_pins[i];3314 if (alc880_is_fixed_pin(nid)) {3315 int idx = alc880_fixed_pin_idx(nid);3316 spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);3317 assigned[idx] = 1;3318 }3319 }3320 /* left pins can be connect to any audio widget */3321 for (i = 0; i < cfg->line_outs; i++) {3322 nid = cfg->line_out_pins[i];3323 if (alc880_is_fixed_pin(nid))3324 continue;3325 /* search for an empty channel */3326 for (j = 0; j < cfg->line_outs; j++) {3327 if (!assigned[j]) {3328 spec->multiout.dac_nids[i] =3329 alc880_idx_to_dac(j);3330 assigned[j] = 1;3331 break;3332 }3333 }3334 }3335 spec->multiout.num_dacs = cfg->line_outs;3336 return 0;3337}33383339/* add playback controls from the parsed DAC table */3340static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,3341 const struct auto_pin_cfg *cfg)3342{3343 char name[32];3344 static const char *chname[4] = {3345 "Front", "Surround", NULL /*CLFE*/, "Side"3346 };3347 hda_nid_t nid;3348 int i, err;33493350 for (i = 0; i < cfg->line_outs; i++) {3351 if (!spec->multiout.dac_nids[i])3352 continue;3353 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));3354 if (i == 2) {3355 /* Center/LFE */3356 err = add_control(spec, ALC_CTL_WIDGET_VOL,3357 "Center Playback Volume",3358 HDA_COMPOSE_AMP_VAL(nid, 1, 0,3359 HDA_OUTPUT));3360 if (err < 0)3361 return err;3362 err = add_control(spec, ALC_CTL_WIDGET_VOL,3363 "LFE Playback Volume",3364 HDA_COMPOSE_AMP_VAL(nid, 2, 0,3365 HDA_OUTPUT));3366 if (err < 0)3367 return err;3368 err = add_control(spec, ALC_CTL_BIND_MUTE,3369 "Center Playback Switch",3370 HDA_COMPOSE_AMP_VAL(nid, 1, 2,3371 HDA_INPUT));3372 if (err < 0)3373 return err;3374 err = add_control(spec, ALC_CTL_BIND_MUTE,3375 "LFE Playback Switch",3376 HDA_COMPOSE_AMP_VAL(nid, 2, 2,3377 HDA_INPUT));3378 if (err < 0)3379 return err;3380 } else {3381 sprintf(name, "%s Playback Volume", chname[i]);3382 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,3383 HDA_COMPOSE_AMP_VAL(nid, 3, 0,3384 HDA_OUTPUT));3385 if (err < 0)3386 return err;3387 sprintf(name, "%s Playback Switch", chname[i]);3388 err = add_control(spec, ALC_CTL_BIND_MUTE, name,3389 HDA_COMPOSE_AMP_VAL(nid, 3, 2,3390 HDA_INPUT));3391 if (err < 0)3392 return err;3393 }3394 }3395 return 0;3396}33973398/* add playback controls for speaker and HP outputs */3399static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,3400 const char *pfx)3401{3402 hda_nid_t nid;3403 int err;3404 char name[32];34053406 if (!pin)3407 return 0;34083409 if (alc880_is_fixed_pin(pin)) {3410 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));3411 /* specify the DAC as the extra output */3412 if (!spec->multiout.hp_nid)3413 spec->multiout.hp_nid = nid;3414 else3415 spec->multiout.extra_out_nid[0] = nid;3416 /* control HP volume/switch on the output mixer amp */3417 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));3418 sprintf(name, "%s Playback Volume", pfx);3419 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,3420 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));3421 if (err < 0)3422 return err;3423 sprintf(name, "%s Playback Switch", pfx);3424 err = add_control(spec, ALC_CTL_BIND_MUTE, name,3425 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));3426 if (err < 0)3427 return err;3428 } else if (alc880_is_multi_pin(pin)) {3429 /* set manual connection */3430 /* we have only a switch on HP-out PIN */3431 sprintf(name, "%s Playback Switch", pfx);3432 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,3433 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));3434 if (err < 0)3435 return err;3436 }3437 return 0;3438}34393440/* create input playback/capture controls for the given pin */3441static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,3442 const char *ctlname,3443 int idx, hda_nid_t mix_nid)3444{3445 char name[32];3446 int err;34473448 sprintf(name, "%s Playback Volume", ctlname);3449 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,3450 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));3451 if (err < 0)3452 return err;3453 sprintf(name, "%s Playback Switch", ctlname);3454 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,3455 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));3456 if (err < 0)3457 return err;3458 return 0;3459}34603461/* create playback/capture controls for input pins */3462static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,3463 const struct auto_pin_cfg *cfg)3464{3465 struct hda_input_mux *imux = &spec->private_imux;3466 int i, err, idx;34673468 for (i = 0; i < AUTO_PIN_LAST; i++) {3469 if (alc880_is_input_pin(cfg->input_pins[i])) {3470 idx = alc880_input_pin_idx(cfg->input_pins[i]);3471 err = new_analog_input(spec, cfg->input_pins[i],3472 auto_pin_cfg_labels[i],3473 idx, 0x0b);3474 if (err < 0)3475 return err;3476 imux->items[imux->num_items].label =3477 auto_pin_cfg_labels[i];3478 imux->items[imux->num_items].index =3479 alc880_input_pin_idx(cfg->input_pins[i]);3480 imux->num_items++;3481 }3482 }3483 return 0;3484}34853486static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,3487 unsigned int pin_type)3488{3489 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,3490 pin_type);3491 /* unmute pin */3492 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,3493 AMP_OUT_UNMUTE);3494}34953496static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,3497 hda_nid_t nid, int pin_type,3498 int dac_idx)3499{3500 alc_set_pin_output(codec, nid, pin_type);3501 /* need the manual connection? */3502 if (alc880_is_multi_pin(nid)) {3503 struct alc_spec *spec = codec->spec;3504 int idx = alc880_multi_pin_idx(nid);3505 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,3506 AC_VERB_SET_CONNECT_SEL,3507 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));3508 }3509}35103511static int get_pin_type(int line_out_type)3512{3513 if (line_out_type == AUTO_PIN_HP_OUT)3514 return PIN_HP;3515 else3516 return PIN_OUT;3517}35183519static void alc880_auto_init_multi_out(struct hda_codec *codec)3520{3521 struct alc_spec *spec = codec->spec;3522 int i;35233524 alc_subsystem_id(codec, 0x15, 0x1b, 0x14);3525 for (i = 0; i < spec->autocfg.line_outs; i++) {3526 hda_nid_t nid = spec->autocfg.line_out_pins[i];3527 int pin_type = get_pin_type(spec->autocfg.line_out_type);3528 alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);3529 }3530}35313532static void alc880_auto_init_extra_out(struct hda_codec *codec)3533{3534 struct alc_spec *spec = codec->spec;3535 hda_nid_t pin;35363537 pin = spec->autocfg.speaker_pins[0];3538 if (pin) /* connect to front */3539 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);3540 pin = spec->autocfg.hp_pins[0];3541 if (pin) /* connect to front */3542 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);3543}35443545static void alc880_auto_init_analog_input(struct hda_codec *codec)3546{3547 struct alc_spec *spec = codec->spec;3548 int i;35493550 for (i = 0; i < AUTO_PIN_LAST; i++) {3551 hda_nid_t nid = spec->autocfg.input_pins[i];3552 if (alc880_is_input_pin(nid)) {3553 snd_hda_codec_write(codec, nid, 0,3554 AC_VERB_SET_PIN_WIDGET_CONTROL,3555 i <= AUTO_PIN_FRONT_MIC ?3556 PIN_VREF80 : PIN_IN);3557 if (nid != ALC880_PIN_CD_NID)3558 snd_hda_codec_write(codec, nid, 0,3559 AC_VERB_SET_AMP_GAIN_MUTE,3560 AMP_OUT_MUTE);3561 }3562 }3563}35643565/* parse the BIOS configuration and set up the alc_spec */3566/* return 1 if successful, 0 if the proper config is not found,3567 * or a negative error code3568 */3569static int alc880_parse_auto_config(struct hda_codec *codec)3570{3571 struct alc_spec *spec = codec->spec;3572 int err;3573 static hda_nid_t alc880_ignore[] = { 0x1d, 0 };35743575 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,3576 alc880_ignore);3577 if (err < 0)3578 return err;3579 if (!spec->autocfg.line_outs)3580 return 0; /* can't find valid BIOS pin config */35813582 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);3583 if (err < 0)3584 return err;3585 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);3586 if (err < 0)3587 return err;3588 err = alc880_auto_create_extra_out(spec,3589 spec->autocfg.speaker_pins[0],3590 "Speaker");3591 if (err < 0)3592 return err;3593 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],3594 "Headphone");3595 if (err < 0)3596 return err;3597 err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);3598 if (err < 0)3599 return err;36003601 spec->multiout.max_channels = spec->multiout.num_dacs * 2;36023603 if (spec->autocfg.dig_out_pin)3604 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;3605 if (spec->autocfg.dig_in_pin)3606 spec->dig_in_nid = ALC880_DIGIN_NID;36073608 if (spec->kctl_alloc)3609 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;36103611 spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;36123613 spec->num_mux_defs = 1;3614 spec->input_mux = &spec->private_imux;36153616 return 1;3617}36183619/* additional initialization for auto-configuration model */3620static void alc880_auto_init(struct hda_codec *codec)3621{3622 struct alc_spec *spec = codec->spec;3623 alc880_auto_init_multi_out(codec);3624 alc880_auto_init_extra_out(codec);3625 alc880_auto_init_analog_input(codec);3626 if (spec->unsol_event)3627 alc_sku_automute(codec);3628}36293630/*3631 * OK, here we have finally the patch for ALC8803632 */36333634static int patch_alc880(struct hda_codec *codec)3635{3636 struct alc_spec *spec;3637 int board_config;3638 int err;36393640 spec = kzalloc(sizeof(*spec), GFP_KERNEL);3641 if (spec == NULL)3642 return -ENOMEM;36433644 codec->spec = spec;36453646 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,3647 alc880_models,3648 alc880_cfg_tbl);3649 if (board_config < 0) {3650 printk(KERN_INFO "hda_codec: Unknown model for ALC880, "3651 "trying auto-probe from BIOS...\n");3652 board_config = ALC880_AUTO;3653 }36543655 if (board_config == ALC880_AUTO) {3656 /* automatic parse from the BIOS config */3657 err = alc880_parse_auto_config(codec);3658 if (err < 0) {3659 alc_free(codec);3660 return err;3661 } else if (!err) {3662 printk(KERN_INFO3663 "hda_codec: Cannot set up configuration "3664 "from BIOS. Using 3-stack mode...\n");3665 board_config = ALC880_3ST;3666 }3667 }36683669 if (board_config != ALC880_AUTO)3670 setup_preset(spec, &alc880_presets[board_config]);36713672 spec->stream_name_analog = "ALC880 Analog";3673 spec->stream_analog_playback = &alc880_pcm_analog_playback;3674 spec->stream_analog_capture = &alc880_pcm_analog_capture;3675 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;36763677 spec->stream_name_digital = "ALC880 Digital";3678 spec->stream_digital_playback = &alc880_pcm_digital_playback;3679 spec->stream_digital_capture = &alc880_pcm_digital_capture;36803681 if (!spec->adc_nids && spec->input_mux) {3682 /* check whether NID 0x07 is valid */3683 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);3684 /* get type */3685 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;3686 if (wcap != AC_WID_AUD_IN) {3687 spec->adc_nids = alc880_adc_nids_alt;3688 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);3689 spec->mixers[spec->num_mixers] =3690 alc880_capture_alt_mixer;3691 spec->num_mixers++;3692 } else {3693 spec->adc_nids = alc880_adc_nids;3694 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);3695 spec->mixers[spec->num_mixers] = alc880_capture_mixer;3696 spec->num_mixers++;3697 }3698 }36993700 spec->vmaster_nid = 0x0c;37013702 codec->patch_ops = alc_patch_ops;3703 if (board_config == ALC880_AUTO)3704 spec->init_hook = alc880_auto_init;3705#ifdef CONFIG_SND_HDA_POWER_SAVE3706 if (!spec->loopback.amplist)3707 spec->loopback.amplist = alc880_loopbacks;3708#endif37093710 return 0;3711}371237133714/*3715 * ALC260 support3716 */37173718static hda_nid_t alc260_dac_nids[1] = {3719 /* front */3720 0x02,3721};37223723static hda_nid_t alc260_adc_nids[1] = {3724 /* ADC0 */3725 0x04,3726};37273728static hda_nid_t alc260_adc_nids_alt[1] = {3729 /* ADC1 */3730 0x05,3731};37323733static hda_nid_t alc260_hp_adc_nids[2] = {3734 /* ADC1, 0 */3735 0x05, 0x043736};37373738/* NIDs used when simultaneous access to both ADCs makes sense. Note that3739 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.3740 */3741static hda_nid_t alc260_dual_adc_nids[2] = {3742 /* ADC0, ADC1 */3743 0x04, 0x053744};37453746#define ALC260_DIGOUT_NID 0x033747#define ALC260_DIGIN_NID 0x0637483749static struct hda_input_mux alc260_capture_source = {3750 .num_items = 4,3751 .items = {3752 { "Mic", 0x0 },3753 { "Front Mic", 0x1 },3754 { "Line", 0x2 },3755 { "CD", 0x4 },3756 },3757};37583759/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,3760 * headphone jack and the internal CD lines since these are the only pins at3761 * which audio can appear. For flexibility, also allow the option of3762 * recording the mixer output on the second ADC (ADC0 doesn't have a3763 * connection to the mixer output).3764 */3765static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {3766 {3767 .num_items = 3,3768 .items = {3769 { "Mic/Line", 0x0 },3770 { "CD", 0x4 },3771 { "Headphone", 0x2 },3772 },3773 },3774 {3775 .num_items = 4,3776 .items = {3777 { "Mic/Line", 0x0 },3778 { "CD", 0x4 },3779 { "Headphone", 0x2 },3780 { "Mixer", 0x5 },3781 },3782 },37833784};37853786/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to3787 * the Fujitsu S702x, but jacks are marked differently.3788 */3789static struct hda_input_mux alc260_acer_capture_sources[2] = {3790 {3791 .num_items = 4,3792 .items = {3793 { "Mic", 0x0 },3794 { "Line", 0x2 },3795 { "CD", 0x4 },3796 { "Headphone", 0x5 },3797 },3798 },3799 {3800 .num_items = 5,3801 .items = {3802 { "Mic", 0x0 },3803 { "Line", 0x2 },3804 { "CD", 0x4 },3805 { "Headphone", 0x6 },3806 { "Mixer", 0x5 },3807 },3808 },3809};3810/*3811 * This is just place-holder, so there's something for alc_build_pcms to look3812 * at when it calculates the maximum number of channels. ALC260 has no mixer3813 * element which allows changing the channel mode, so the verb list is3814 * never used.3815 */3816static struct hda_channel_mode alc260_modes[1] = {3817 { 2, NULL },3818};381938203821/* Mixer combinations3822 *3823 * basic: base_output + input + pc_beep + capture3824 * HP: base_output + input + capture_alt3825 * HP_3013: hp_3013 + input + capture3826 * fujitsu: fujitsu + capture3827 * acer: acer + capture3828 */38293830static struct snd_kcontrol_new alc260_base_output_mixer[] = {3831 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),3832 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),3833 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),3834 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),3835 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),3836 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),3837 { } /* end */3838};38393840static struct snd_kcontrol_new alc260_input_mixer[] = {3841 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),3842 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),3843 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),3844 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),3845 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),3846 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),3847 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),3848 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),3849 { } /* end */3850};38513852static struct snd_kcontrol_new alc260_pc_beep_mixer[] = {3853 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),3854 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),3855 { } /* end */3856};38573858/* update HP, line and mono out pins according to the master switch */3859static void alc260_hp_master_update(struct hda_codec *codec,3860 hda_nid_t hp, hda_nid_t line,3861 hda_nid_t mono)3862{3863 struct alc_spec *spec = codec->spec;3864 unsigned int val = spec->master_sw ? PIN_HP : 0;3865 /* change HP and line-out pins */3866 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,3867 val);3868 snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,3869 val);3870 /* mono (speaker) depending on the HP jack sense */3871 val = (val && !spec->jack_present) ? PIN_OUT : 0;3872 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,3873 val);3874}38753876static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,3877 struct snd_ctl_elem_value *ucontrol)3878{3879 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);3880 struct alc_spec *spec = codec->spec;3881 *ucontrol->value.integer.value = spec->master_sw;3882 return 0;3883}38843885static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,3886 struct snd_ctl_elem_value *ucontrol)3887{3888 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);3889 struct alc_spec *spec = codec->spec;3890 int val = !!*ucontrol->value.integer.value;3891 hda_nid_t hp, line, mono;38923893 if (val == spec->master_sw)3894 return 0;3895 spec->master_sw = val;3896 hp = (kcontrol->private_value >> 16) & 0xff;3897 line = (kcontrol->private_value >> 8) & 0xff;3898 mono = kcontrol->private_value & 0xff;3899 alc260_hp_master_update(codec, hp, line, mono);3900 return 1;3901}39023903static struct snd_kcontrol_new alc260_hp_output_mixer[] = {3904 {3905 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,3906 .name = "Master Playback Switch",3907 .info = snd_ctl_boolean_mono_info,3908 .get = alc260_hp_master_sw_get,3909 .put = alc260_hp_master_sw_put,3910 .private_value = (0x0f << 16) | (0x10 << 8) | 0x113911 },3912 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),3913 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),3914 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),3915 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),3916 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,3917 HDA_OUTPUT),3918 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT),3919 { } /* end */3920};39213922static struct hda_verb alc260_hp_unsol_verbs[] = {3923 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},3924 {},3925};39263927static void alc260_hp_automute(struct hda_codec *codec)3928{3929 struct alc_spec *spec = codec->spec;3930 unsigned int present;39313932 present = snd_hda_codec_read(codec, 0x10, 0,3933 AC_VERB_GET_PIN_SENSE, 0);3934 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;3935 alc260_hp_master_update(codec, 0x0f, 0x10, 0x11);3936}39373938static void alc260_hp_unsol_event(struct hda_codec *codec, unsigned int res)3939{3940 if ((res >> 26) == ALC880_HP_EVENT)3941 alc260_hp_automute(codec);3942}39433944static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {3945 {3946 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,3947 .name = "Master Playback Switch",3948 .info = snd_ctl_boolean_mono_info,3949 .get = alc260_hp_master_sw_get,3950 .put = alc260_hp_master_sw_put,3951 .private_value = (0x10 << 16) | (0x15 << 8) | 0x113952 },3953 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),3954 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),3955 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),3956 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),3957 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),3958 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),3959 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),3960 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),3961 { } /* end */3962};39633964static struct hda_verb alc260_hp_3013_unsol_verbs[] = {3965 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},3966 {},3967};39683969static void alc260_hp_3013_automute(struct hda_codec *codec)3970{3971 struct alc_spec *spec = codec->spec;3972 unsigned int present;39733974 present = snd_hda_codec_read(codec, 0x15, 0,3975 AC_VERB_GET_PIN_SENSE, 0);3976 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;3977 alc260_hp_master_update(codec, 0x10, 0x15, 0x11);3978}39793980static void alc260_hp_3013_unsol_event(struct hda_codec *codec,3981 unsigned int res)3982{3983 if ((res >> 26) == ALC880_HP_EVENT)3984 alc260_hp_3013_automute(codec);3985}39863987/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,3988 * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.3989 */3990static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {3991 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),3992 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),3993 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),3994 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),3995 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),3996 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),3997 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),3998 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),3999 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),4000 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),4001 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),4002 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),4003 { } /* end */4004};40054006/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current4007 * versions of the ALC260 don't act on requests to enable mic bias from NID4008 * 0x0f (used to drive the headphone jack in these laptops). The ALC2604009 * datasheet doesn't mention this restriction. At this stage it's not clear4010 * whether this behaviour is intentional or is a hardware bug in chip4011 * revisions available in early 2006. Therefore for now allow the4012 * "Headphone Jack Mode" control to span all choices, but if it turns out4013 * that the lack of mic bias for this NID is intentional we could change the4014 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.4015 *4016 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 20064017 * don't appear to make the mic bias available from the "line" jack, even4018 * though the NID used for this jack (0x14) can supply it. The theory is4019 * that perhaps Acer have included blocking capacitors between the ALC2604020 * and the output jack. If this turns out to be the case for all such4021 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT4022 * to ALC_PIN_DIR_INOUT_NOMICBIAS.4023 *4024 * The C20x Tablet series have a mono internal speaker which is controlled4025 * via the chip's Mono sum widget and pin complex, so include the necessary4026 * controls for such models. On models without a "mono speaker" the control4027 * won't do anything.4028 */4029static struct snd_kcontrol_new alc260_acer_mixer[] = {4030 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),4031 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),4032 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),4033 HDA_CODEC_VOLUME_MONO("Mono Speaker Playback Volume", 0x0a, 1, 0x0,4034 HDA_OUTPUT),4035 HDA_BIND_MUTE_MONO("Mono Speaker Playback Switch", 0x0a, 1, 2,4036 HDA_INPUT),4037 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),4038 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),4039 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),4040 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),4041 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),4042 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),4043 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),4044 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),4045 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),4046 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),4047 { } /* end */4048};40494050/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,4051 * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17.4052 */4053static struct snd_kcontrol_new alc260_will_mixer[] = {4054 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),4055 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),4056 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),4057 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),4058 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),4059 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),4060 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),4061 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),4062 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),4063 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),4064 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),4065 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),4066 { } /* end */4067};40684069/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,4070 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.4071 */4072static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {4073 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),4074 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),4075 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),4076 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),4077 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),4078 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),4079 HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),4080 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),4081 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),4082 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),4083 { } /* end */4084};40854086/* capture mixer elements */4087static struct snd_kcontrol_new alc260_capture_mixer[] = {4088 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),4089 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),4090 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),4091 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),4092 {4093 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,4094 /* The multiple "Capture Source" controls confuse alsamixer4095 * So call somewhat different..4096 */4097 /* .name = "Capture Source", */4098 .name = "Input Source",4099 .count = 2,4100 .info = alc_mux_enum_info,4101 .get = alc_mux_enum_get,4102 .put = alc_mux_enum_put,4103 },4104 { } /* end */4105};41064107static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {4108 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),4109 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),4110 {4111 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,4112 /* The multiple "Capture Source" controls confuse alsamixer4113 * So call somewhat different..4114 */4115 /* .name = "Capture Source", */4116 .name = "Input Source",4117 .count = 1,4118 .info = alc_mux_enum_info,4119 .get = alc_mux_enum_get,4120 .put = alc_mux_enum_put,4121 },4122 { } /* end */4123};41244125/*4126 * initialization verbs4127 */4128static struct hda_verb alc260_init_verbs[] = {4129 /* Line In pin widget for input */4130 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},4131 /* CD pin widget for input */4132 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},4133 /* Mic1 (rear panel) pin widget for input and vref at 80% */4134 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},4135 /* Mic2 (front panel) pin widget for input and vref at 80% */4136 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},4137 /* LINE-2 is used for line-out in rear */4138 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},4139 /* select line-out */4140 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},4141 /* LINE-OUT pin */4142 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},4143 /* enable HP */4144 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},4145 /* enable Mono */4146 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},4147 /* mute capture amp left and right */4148 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},4149 /* set connection select to line in (default select for this ADC) */4150 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},4151 /* mute capture amp left and right */4152 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},4153 /* set connection select to line in (default select for this ADC) */4154 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},4155 /* set vol=0 Line-Out mixer amp left and right */4156 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4157 /* unmute pin widget amp left and right (no gain on this amp) */4158 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4159 /* set vol=0 HP mixer amp left and right */4160 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4161 /* unmute pin widget amp left and right (no gain on this amp) */4162 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4163 /* set vol=0 Mono mixer amp left and right */4164 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4165 /* unmute pin widget amp left and right (no gain on this amp) */4166 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4167 /* unmute LINE-2 out pin */4168 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4169 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &4170 * Line In 2 = 0x034171 */4172 /* mute analog inputs */4173 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4174 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4175 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},4176 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},4177 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},4178 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */4179 /* mute Front out path */4180 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4181 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4182 /* mute Headphone out path */4183 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4184 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4185 /* mute Mono out path */4186 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4187 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4188 { }4189};41904191#if 0 /* should be identical with alc260_init_verbs? */4192static struct hda_verb alc260_hp_init_verbs[] = {4193 /* Headphone and output */4194 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},4195 /* mono output */4196 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},4197 /* Mic1 (rear panel) pin widget for input and vref at 80% */4198 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},4199 /* Mic2 (front panel) pin widget for input and vref at 80% */4200 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},4201 /* Line In pin widget for input */4202 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},4203 /* Line-2 pin widget for output */4204 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},4205 /* CD pin widget for input */4206 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},4207 /* unmute amp left and right */4208 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},4209 /* set connection select to line in (default select for this ADC) */4210 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},4211 /* unmute Line-Out mixer amp left and right (volume = 0) */4212 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},4213 /* mute pin widget amp left and right (no gain on this amp) */4214 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},4215 /* unmute HP mixer amp left and right (volume = 0) */4216 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},4217 /* mute pin widget amp left and right (no gain on this amp) */4218 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},4219 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &4220 * Line In 2 = 0x034221 */4222 /* mute analog inputs */4223 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4224 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4225 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},4226 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},4227 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},4228 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */4229 /* Unmute Front out path */4230 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},4231 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},4232 /* Unmute Headphone out path */4233 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},4234 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},4235 /* Unmute Mono out path */4236 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},4237 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},4238 { }4239};4240#endif42414242static struct hda_verb alc260_hp_3013_init_verbs[] = {4243 /* Line out and output */4244 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},4245 /* mono output */4246 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},4247 /* Mic1 (rear panel) pin widget for input and vref at 80% */4248 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},4249 /* Mic2 (front panel) pin widget for input and vref at 80% */4250 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},4251 /* Line In pin widget for input */4252 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},4253 /* Headphone pin widget for output */4254 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},4255 /* CD pin widget for input */4256 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},4257 /* unmute amp left and right */4258 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},4259 /* set connection select to line in (default select for this ADC) */4260 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},4261 /* unmute Line-Out mixer amp left and right (volume = 0) */4262 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},4263 /* mute pin widget amp left and right (no gain on this amp) */4264 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},4265 /* unmute HP mixer amp left and right (volume = 0) */4266 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},4267 /* mute pin widget amp left and right (no gain on this amp) */4268 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},4269 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &4270 * Line In 2 = 0x034271 */4272 /* mute analog inputs */4273 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4274 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4275 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},4276 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},4277 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},4278 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */4279 /* Unmute Front out path */4280 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},4281 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},4282 /* Unmute Headphone out path */4283 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},4284 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},4285 /* Unmute Mono out path */4286 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},4287 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},4288 { }4289};42904291/* Initialisation sequence for ALC260 as configured in Fujitsu S702x4292 * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD4293 * audio = 0x16, internal speaker = 0x10.4294 */4295static struct hda_verb alc260_fujitsu_init_verbs[] = {4296 /* Disable all GPIOs */4297 {0x01, AC_VERB_SET_GPIO_MASK, 0},4298 /* Internal speaker is connected to headphone pin */4299 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},4300 /* Headphone/Line-out jack connects to Line1 pin; make it an output */4301 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},4302 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */4303 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},4304 /* Ensure all other unused pins are disabled and muted. */4305 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},4306 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4307 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},4308 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4309 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},4310 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4311 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},4312 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},43134314 /* Disable digital (SPDIF) pins */4315 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},4316 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},43174318 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus4319 * when acting as an output.4320 */4321 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},43224323 /* Start with output sum widgets muted and their output gains at min */4324 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4325 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4326 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4327 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4328 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4329 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4330 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4331 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4332 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},43334334 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */4335 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4336 /* Unmute Line1 pin widget output buffer since it starts as an output.4337 * If the pin mode is changed by the user the pin mode control will4338 * take care of enabling the pin's input/output buffers as needed.4339 * Therefore there's no need to enable the input buffer at this4340 * stage.4341 */4342 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4343 /* Unmute input buffer of pin widget used for Line-in (no equiv4344 * mixer ctrl)4345 */4346 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},43474348 /* Mute capture amp left and right */4349 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4350 /* Set ADC connection select to match default mixer setting - line4351 * in (on mic1 pin)4352 */4353 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},43544355 /* Do the same for the second ADC: mute capture input amp and4356 * set ADC connection to line in (on mic1 pin)4357 */4358 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4359 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},43604361 /* Mute all inputs to mixer widget (even unconnected ones) */4362 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */4363 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */4364 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */4365 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */4366 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */4367 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */4368 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */4369 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */43704371 { }4372};43734374/* Initialisation sequence for ALC260 as configured in Acer TravelMate and4375 * similar laptops (adapted from Fujitsu init verbs).4376 */4377static struct hda_verb alc260_acer_init_verbs[] = {4378 /* On TravelMate laptops, GPIO 0 enables the internal speaker and4379 * the headphone jack. Turn this on and rely on the standard mute4380 * methods whenever the user wants to turn these outputs off.4381 */4382 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},4383 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},4384 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},4385 /* Internal speaker/Headphone jack is connected to Line-out pin */4386 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},4387 /* Internal microphone/Mic jack is connected to Mic1 pin */4388 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},4389 /* Line In jack is connected to Line1 pin */4390 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},4391 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */4392 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},4393 /* Ensure all other unused pins are disabled and muted. */4394 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},4395 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4396 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},4397 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4398 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},4399 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4400 /* Disable digital (SPDIF) pins */4401 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},4402 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},44034404 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum4405 * bus when acting as outputs.4406 */4407 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},4408 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},44094410 /* Start with output sum widgets muted and their output gains at min */4411 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4412 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4413 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4414 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4415 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4416 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4417 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4418 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4419 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},44204421 /* Unmute Line-out pin widget amp left and right4422 * (no equiv mixer ctrl)4423 */4424 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4425 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */4426 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4427 /* Unmute Mic1 and Line1 pin widget input buffers since they start as4428 * inputs. If the pin mode is changed by the user the pin mode control4429 * will take care of enabling the pin's input/output buffers as needed.4430 * Therefore there's no need to enable the input buffer at this4431 * stage.4432 */4433 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},4434 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},44354436 /* Mute capture amp left and right */4437 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4438 /* Set ADC connection select to match default mixer setting - mic4439 * (on mic1 pin)4440 */4441 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},44424443 /* Do similar with the second ADC: mute capture input amp and4444 * set ADC connection to mic to match ALSA's default state.4445 */4446 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4447 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},44484449 /* Mute all inputs to mixer widget (even unconnected ones) */4450 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */4451 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */4452 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */4453 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */4454 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */4455 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */4456 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */4457 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */44584459 { }4460};44614462static struct hda_verb alc260_will_verbs[] = {4463 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},4464 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},4465 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},4466 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},4467 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},4468 {0x1a, AC_VERB_SET_PROC_COEF, 0x3040},4469 {}4470};44714472static struct hda_verb alc260_replacer_672v_verbs[] = {4473 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},4474 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},4475 {0x1a, AC_VERB_SET_PROC_COEF, 0x3050},44764477 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},4478 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},4479 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},44804481 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},4482 {}4483};44844485/* toggle speaker-output according to the hp-jack state */4486static void alc260_replacer_672v_automute(struct hda_codec *codec)4487{4488 unsigned int present;44894490 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */4491 present = snd_hda_codec_read(codec, 0x0f, 0,4492 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;4493 if (present) {4494 snd_hda_codec_write_cache(codec, 0x01, 0,4495 AC_VERB_SET_GPIO_DATA, 1);4496 snd_hda_codec_write_cache(codec, 0x0f, 0,4497 AC_VERB_SET_PIN_WIDGET_CONTROL,4498 PIN_HP);4499 } else {4500 snd_hda_codec_write_cache(codec, 0x01, 0,4501 AC_VERB_SET_GPIO_DATA, 0);4502 snd_hda_codec_write_cache(codec, 0x0f, 0,4503 AC_VERB_SET_PIN_WIDGET_CONTROL,4504 PIN_OUT);4505 }4506}45074508static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,4509 unsigned int res)4510{4511 if ((res >> 26) == ALC880_HP_EVENT)4512 alc260_replacer_672v_automute(codec);4513}45144515/* Test configuration for debugging, modelled after the ALC880 test4516 * configuration.4517 */4518#ifdef CONFIG_SND_DEBUG4519static hda_nid_t alc260_test_dac_nids[1] = {4520 0x02,4521};4522static hda_nid_t alc260_test_adc_nids[2] = {4523 0x04, 0x05,4524};4525/* For testing the ALC260, each input MUX needs its own definition since4526 * the signal assignments are different. This assumes that the first ADC4527 * is NID 0x04.4528 */4529static struct hda_input_mux alc260_test_capture_sources[2] = {4530 {4531 .num_items = 7,4532 .items = {4533 { "MIC1 pin", 0x0 },4534 { "MIC2 pin", 0x1 },4535 { "LINE1 pin", 0x2 },4536 { "LINE2 pin", 0x3 },4537 { "CD pin", 0x4 },4538 { "LINE-OUT pin", 0x5 },4539 { "HP-OUT pin", 0x6 },4540 },4541 },4542 {4543 .num_items = 8,4544 .items = {4545 { "MIC1 pin", 0x0 },4546 { "MIC2 pin", 0x1 },4547 { "LINE1 pin", 0x2 },4548 { "LINE2 pin", 0x3 },4549 { "CD pin", 0x4 },4550 { "Mixer", 0x5 },4551 { "LINE-OUT pin", 0x6 },4552 { "HP-OUT pin", 0x7 },4553 },4554 },4555};4556static struct snd_kcontrol_new alc260_test_mixer[] = {4557 /* Output driver widgets */4558 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),4559 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),4560 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),4561 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),4562 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),4563 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),45644565 /* Modes for retasking pin widgets4566 * Note: the ALC260 doesn't seem to act on requests to enable mic4567 * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't4568 * mention this restriction. At this stage it's not clear whether4569 * this behaviour is intentional or is a hardware bug in chip4570 * revisions available at least up until early 2006. Therefore for4571 * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all4572 * choices, but if it turns out that the lack of mic bias for these4573 * NIDs is intentional we could change their modes from4574 * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.4575 */4576 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),4577 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),4578 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),4579 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),4580 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),4581 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),45824583 /* Loopback mixer controls */4584 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),4585 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),4586 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),4587 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),4588 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),4589 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),4590 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),4591 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),4592 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),4593 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),4594 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),4595 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),4596 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),4597 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),4598 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),4599 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),46004601 /* Controls for GPIO pins, assuming they are configured as outputs */4602 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),4603 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),4604 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),4605 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),46064607 /* Switches to allow the digital IO pins to be enabled. The datasheet4608 * is ambigious as to which NID is which; testing on laptops which4609 * make this output available should provide clarification.4610 */4611 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),4612 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),46134614 /* A switch allowing EAPD to be enabled. Some laptops seem to use4615 * this output to turn on an external amplifier.4616 */4617 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),4618 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),46194620 { } /* end */4621};4622static struct hda_verb alc260_test_init_verbs[] = {4623 /* Enable all GPIOs as outputs with an initial value of 0 */4624 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},4625 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},4626 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},46274628 /* Enable retasking pins as output, initially without power amp */4629 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},4630 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},4631 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},4632 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},4633 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},4634 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},46354636 /* Disable digital (SPDIF) pins initially, but users can enable4637 * them via a mixer switch. In the case of SPDIF-out, this initverb4638 * payload also sets the generation to 0, output to be in "consumer"4639 * PCM format, copyright asserted, no pre-emphasis and no validity4640 * control.4641 */4642 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},4643 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},46444645 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the4646 * OUT1 sum bus when acting as an output.4647 */4648 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},4649 {0x0c, AC_VERB_SET_CONNECT_SEL, 0},4650 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},4651 {0x0e, AC_VERB_SET_CONNECT_SEL, 0},46524653 /* Start with output sum widgets muted and their output gains at min */4654 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4655 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4656 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4657 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4658 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4659 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4660 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4661 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4662 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},46634664 /* Unmute retasking pin widget output buffers since the default4665 * state appears to be output. As the pin mode is changed by the4666 * user the pin mode control will take care of enabling the pin's4667 * input/output buffers as needed.4668 */4669 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4670 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4671 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4672 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4673 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4674 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},4675 /* Also unmute the mono-out pin widget */4676 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},46774678 /* Mute capture amp left and right */4679 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4680 /* Set ADC connection select to match default mixer setting (mic14681 * pin)4682 */4683 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},46844685 /* Do the same for the second ADC: mute capture input amp and4686 * set ADC connection to mic1 pin4687 */4688 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4689 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},46904691 /* Mute all inputs to mixer widget (even unconnected ones) */4692 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */4693 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */4694 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */4695 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */4696 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */4697 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */4698 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */4699 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */47004701 { }4702};4703#endif47044705#define alc260_pcm_analog_playback alc880_pcm_analog_alt_playback4706#define alc260_pcm_analog_capture alc880_pcm_analog_capture47074708#define alc260_pcm_digital_playback alc880_pcm_digital_playback4709#define alc260_pcm_digital_capture alc880_pcm_digital_capture47104711/*4712 * for BIOS auto-configuration4713 */47144715static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,4716 const char *pfx)4717{4718 hda_nid_t nid_vol;4719 unsigned long vol_val, sw_val;4720 char name[32];4721 int err;47224723 if (nid >= 0x0f && nid < 0x11) {4724 nid_vol = nid - 0x7;4725 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);4726 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);4727 } else if (nid == 0x11) {4728 nid_vol = nid - 0x7;4729 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);4730 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);4731 } else if (nid >= 0x12 && nid <= 0x15) {4732 nid_vol = 0x08;4733 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);4734 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);4735 } else4736 return 0; /* N/A */47374738 snprintf(name, sizeof(name), "%s Playback Volume", pfx);4739 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val);4740 if (err < 0)4741 return err;4742 snprintf(name, sizeof(name), "%s Playback Switch", pfx);4743 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val);4744 if (err < 0)4745 return err;4746 return 1;4747}47484749/* add playback controls from the parsed DAC table */4750static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,4751 const struct auto_pin_cfg *cfg)4752{4753 hda_nid_t nid;4754 int err;47554756 spec->multiout.num_dacs = 1;4757 spec->multiout.dac_nids = spec->private_dac_nids;4758 spec->multiout.dac_nids[0] = 0x02;47594760 nid = cfg->line_out_pins[0];4761 if (nid) {4762 err = alc260_add_playback_controls(spec, nid, "Front");4763 if (err < 0)4764 return err;4765 }47664767 nid = cfg->speaker_pins[0];4768 if (nid) {4769 err = alc260_add_playback_controls(spec, nid, "Speaker");4770 if (err < 0)4771 return err;4772 }47734774 nid = cfg->hp_pins[0];4775 if (nid) {4776 err = alc260_add_playback_controls(spec, nid, "Headphone");4777 if (err < 0)4778 return err;4779 }4780 return 0;4781}47824783/* create playback/capture controls for input pins */4784static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,4785 const struct auto_pin_cfg *cfg)4786{4787 struct hda_input_mux *imux = &spec->private_imux;4788 int i, err, idx;47894790 for (i = 0; i < AUTO_PIN_LAST; i++) {4791 if (cfg->input_pins[i] >= 0x12) {4792 idx = cfg->input_pins[i] - 0x12;4793 err = new_analog_input(spec, cfg->input_pins[i],4794 auto_pin_cfg_labels[i], idx,4795 0x07);4796 if (err < 0)4797 return err;4798 imux->items[imux->num_items].label =4799 auto_pin_cfg_labels[i];4800 imux->items[imux->num_items].index = idx;4801 imux->num_items++;4802 }4803 if (cfg->input_pins[i] >= 0x0f && cfg->input_pins[i] <= 0x10){4804 idx = cfg->input_pins[i] - 0x09;4805 err = new_analog_input(spec, cfg->input_pins[i],4806 auto_pin_cfg_labels[i], idx,4807 0x07);4808 if (err < 0)4809 return err;4810 imux->items[imux->num_items].label =4811 auto_pin_cfg_labels[i];4812 imux->items[imux->num_items].index = idx;4813 imux->num_items++;4814 }4815 }4816 return 0;4817}48184819static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,4820 hda_nid_t nid, int pin_type,4821 int sel_idx)4822{4823 alc_set_pin_output(codec, nid, pin_type);4824 /* need the manual connection? */4825 if (nid >= 0x12) {4826 int idx = nid - 0x12;4827 snd_hda_codec_write(codec, idx + 0x0b, 0,4828 AC_VERB_SET_CONNECT_SEL, sel_idx);4829 }4830}48314832static void alc260_auto_init_multi_out(struct hda_codec *codec)4833{4834 struct alc_spec *spec = codec->spec;4835 hda_nid_t nid;48364837 alc_subsystem_id(codec, 0x10, 0x15, 0x0f);4838 nid = spec->autocfg.line_out_pins[0];4839 if (nid) {4840 int pin_type = get_pin_type(spec->autocfg.line_out_type);4841 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);4842 }48434844 nid = spec->autocfg.speaker_pins[0];4845 if (nid)4846 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);48474848 nid = spec->autocfg.hp_pins[0];4849 if (nid)4850 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);4851}48524853#define ALC260_PIN_CD_NID 0x164854static void alc260_auto_init_analog_input(struct hda_codec *codec)4855{4856 struct alc_spec *spec = codec->spec;4857 int i;48584859 for (i = 0; i < AUTO_PIN_LAST; i++) {4860 hda_nid_t nid = spec->autocfg.input_pins[i];4861 if (nid >= 0x12) {4862 snd_hda_codec_write(codec, nid, 0,4863 AC_VERB_SET_PIN_WIDGET_CONTROL,4864 i <= AUTO_PIN_FRONT_MIC ?4865 PIN_VREF80 : PIN_IN);4866 if (nid != ALC260_PIN_CD_NID)4867 snd_hda_codec_write(codec, nid, 0,4868 AC_VERB_SET_AMP_GAIN_MUTE,4869 AMP_OUT_MUTE);4870 }4871 }4872}48734874/*4875 * generic initialization of ADC, input mixers and output mixers4876 */4877static struct hda_verb alc260_volume_init_verbs[] = {4878 /*4879 * Unmute ADC0-1 and set the default input to mic-in4880 */4881 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},4882 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},4883 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},4884 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},48854886 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback4887 * mixer widget4888 * Note: PASD motherboards uses the Line In 2 as the input for4889 * front panel mic (mic 2)4890 */4891 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */4892 /* mute analog inputs */4893 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},4894 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},4895 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},4896 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},4897 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},48984899 /*4900 * Set up output mixers (0x08 - 0x0a)4901 */4902 /* set vol=0 to output mixers */4903 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4904 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4905 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},4906 /* set up input amps for analog loopback */4907 /* Amp Indices: DAC = 0, mixer = 1 */4908 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},4909 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},4910 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},4911 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},4912 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},4913 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},49144915 { }4916};49174918static int alc260_parse_auto_config(struct hda_codec *codec)4919{4920 struct alc_spec *spec = codec->spec;4921 unsigned int wcap;4922 int err;4923 static hda_nid_t alc260_ignore[] = { 0x17, 0 };49244925 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,4926 alc260_ignore);4927 if (err < 0)4928 return err;4929 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);4930 if (err < 0)4931 return err;4932 if (!spec->kctl_alloc)4933 return 0; /* can't find valid BIOS pin config */4934 err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg);4935 if (err < 0)4936 return err;49374938 spec->multiout.max_channels = 2;49394940 if (spec->autocfg.dig_out_pin)4941 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;4942 if (spec->kctl_alloc)4943 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;49444945 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;49464947 spec->num_mux_defs = 1;4948 spec->input_mux = &spec->private_imux;49494950 /* check whether NID 0x04 is valid */4951 wcap = get_wcaps(codec, 0x04);4952 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */4953 if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {4954 spec->adc_nids = alc260_adc_nids_alt;4955 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);4956 spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;4957 } else {4958 spec->adc_nids = alc260_adc_nids;4959 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);4960 spec->mixers[spec->num_mixers] = alc260_capture_mixer;4961 }4962 spec->num_mixers++;49634964 return 1;4965}49664967/* additional initialization for auto-configuration model */4968static void alc260_auto_init(struct hda_codec *codec)4969{4970 struct alc_spec *spec = codec->spec;4971 alc260_auto_init_multi_out(codec);4972 alc260_auto_init_analog_input(codec);4973 if (spec->unsol_event)4974 alc_sku_automute(codec);4975}49764977#ifdef CONFIG_SND_HDA_POWER_SAVE4978static struct hda_amp_list alc260_loopbacks[] = {4979 { 0x07, HDA_INPUT, 0 },4980 { 0x07, HDA_INPUT, 1 },4981 { 0x07, HDA_INPUT, 2 },4982 { 0x07, HDA_INPUT, 3 },4983 { 0x07, HDA_INPUT, 4 },4984 { } /* end */4985};4986#endif49874988/*4989 * ALC260 configurations4990 */4991static const char *alc260_models[ALC260_MODEL_LAST] = {4992 [ALC260_BASIC] = "basic",4993 [ALC260_HP] = "hp",4994 [ALC260_HP_3013] = "hp-3013",4995 [ALC260_FUJITSU_S702X] = "fujitsu",4996 [ALC260_ACER] = "acer",4997 [ALC260_WILL] = "will",4998 [ALC260_REPLACER_672V] = "replacer",4999#ifdef CONFIG_SND_DEBUG5000 [ALC260_TEST] = "test",5001#endif5002 [ALC260_AUTO] = "auto",5003};50045005static struct snd_pci_quirk alc260_cfg_tbl[] = {5006 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),5007 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),5008 SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),5009 SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013),5010 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),5011 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP),5012 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013),5013 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),5014 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),5015 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),5016 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),5017 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),5018 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),5019 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),5020 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),5021 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),5022 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),5023 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),5024 {}5025};50265027static struct alc_config_preset alc260_presets[] = {5028 [ALC260_BASIC] = {5029 .mixers = { alc260_base_output_mixer,5030 alc260_input_mixer,5031 alc260_pc_beep_mixer,5032 alc260_capture_mixer },5033 .init_verbs = { alc260_init_verbs },5034 .num_dacs = ARRAY_SIZE(alc260_dac_nids),5035 .dac_nids = alc260_dac_nids,5036 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),5037 .adc_nids = alc260_adc_nids,5038 .num_channel_mode = ARRAY_SIZE(alc260_modes),5039 .channel_mode = alc260_modes,5040 .input_mux = &alc260_capture_source,5041 },5042 [ALC260_HP] = {5043 .mixers = { alc260_hp_output_mixer,5044 alc260_input_mixer,5045 alc260_capture_alt_mixer },5046 .init_verbs = { alc260_init_verbs,5047 alc260_hp_unsol_verbs },5048 .num_dacs = ARRAY_SIZE(alc260_dac_nids),5049 .dac_nids = alc260_dac_nids,5050 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),5051 .adc_nids = alc260_hp_adc_nids,5052 .num_channel_mode = ARRAY_SIZE(alc260_modes),5053 .channel_mode = alc260_modes,5054 .input_mux = &alc260_capture_source,5055 .unsol_event = alc260_hp_unsol_event,5056 .init_hook = alc260_hp_automute,5057 },5058 [ALC260_HP_3013] = {5059 .mixers = { alc260_hp_3013_mixer,5060 alc260_input_mixer,5061 alc260_capture_alt_mixer },5062 .init_verbs = { alc260_hp_3013_init_verbs,5063 alc260_hp_3013_unsol_verbs },5064 .num_dacs = ARRAY_SIZE(alc260_dac_nids),5065 .dac_nids = alc260_dac_nids,5066 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),5067 .adc_nids = alc260_hp_adc_nids,5068 .num_channel_mode = ARRAY_SIZE(alc260_modes),5069 .channel_mode = alc260_modes,5070 .input_mux = &alc260_capture_source,5071 .unsol_event = alc260_hp_3013_unsol_event,5072 .init_hook = alc260_hp_3013_automute,5073 },5074 [ALC260_FUJITSU_S702X] = {5075 .mixers = { alc260_fujitsu_mixer,5076 alc260_capture_mixer },5077 .init_verbs = { alc260_fujitsu_init_verbs },5078 .num_dacs = ARRAY_SIZE(alc260_dac_nids),5079 .dac_nids = alc260_dac_nids,5080 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),5081 .adc_nids = alc260_dual_adc_nids,5082 .num_channel_mode = ARRAY_SIZE(alc260_modes),5083 .channel_mode = alc260_modes,5084 .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),5085 .input_mux = alc260_fujitsu_capture_sources,5086 },5087 [ALC260_ACER] = {5088 .mixers = { alc260_acer_mixer,5089 alc260_capture_mixer },5090 .init_verbs = { alc260_acer_init_verbs },5091 .num_dacs = ARRAY_SIZE(alc260_dac_nids),5092 .dac_nids = alc260_dac_nids,5093 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),5094 .adc_nids = alc260_dual_adc_nids,5095 .num_channel_mode = ARRAY_SIZE(alc260_modes),5096 .channel_mode = alc260_modes,5097 .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),5098 .input_mux = alc260_acer_capture_sources,5099 },5100 [ALC260_WILL] = {5101 .mixers = { alc260_will_mixer,5102 alc260_capture_mixer },5103 .init_verbs = { alc260_init_verbs, alc260_will_verbs },5104 .num_dacs = ARRAY_SIZE(alc260_dac_nids),5105 .dac_nids = alc260_dac_nids,5106 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),5107 .adc_nids = alc260_adc_nids,5108 .dig_out_nid = ALC260_DIGOUT_NID,5109 .num_channel_mode = ARRAY_SIZE(alc260_modes),5110 .channel_mode = alc260_modes,5111 .input_mux = &alc260_capture_source,5112 },5113 [ALC260_REPLACER_672V] = {5114 .mixers = { alc260_replacer_672v_mixer,5115 alc260_capture_mixer },5116 .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },5117 .num_dacs = ARRAY_SIZE(alc260_dac_nids),5118 .dac_nids = alc260_dac_nids,5119 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),5120 .adc_nids = alc260_adc_nids,5121 .dig_out_nid = ALC260_DIGOUT_NID,5122 .num_channel_mode = ARRAY_SIZE(alc260_modes),5123 .channel_mode = alc260_modes,5124 .input_mux = &alc260_capture_source,5125 .unsol_event = alc260_replacer_672v_unsol_event,5126 .init_hook = alc260_replacer_672v_automute,5127 },5128#ifdef CONFIG_SND_DEBUG5129 [ALC260_TEST] = {5130 .mixers = { alc260_test_mixer,5131 alc260_capture_mixer },5132 .init_verbs = { alc260_test_init_verbs },5133 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),5134 .dac_nids = alc260_test_dac_nids,5135 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),5136 .adc_nids = alc260_test_adc_nids,5137 .num_channel_mode = ARRAY_SIZE(alc260_modes),5138 .channel_mode = alc260_modes,5139 .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),5140 .input_mux = alc260_test_capture_sources,5141 },5142#endif5143};51445145static int patch_alc260(struct hda_codec *codec)5146{5147 struct alc_spec *spec;5148 int err, board_config;51495150 spec = kzalloc(sizeof(*spec), GFP_KERNEL);5151 if (spec == NULL)5152 return -ENOMEM;51535154 codec->spec = spec;51555156 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,5157 alc260_models,5158 alc260_cfg_tbl);5159 if (board_config < 0) {5160 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, "5161 "trying auto-probe from BIOS...\n");5162 board_config = ALC260_AUTO;5163 }51645165 if (board_config == ALC260_AUTO) {5166 /* automatic parse from the BIOS config */5167 err = alc260_parse_auto_config(codec);5168 if (err < 0) {5169 alc_free(codec);5170 return err;5171 } else if (!err) {5172 printk(KERN_INFO5173 "hda_codec: Cannot set up configuration "5174 "from BIOS. Using base mode...\n");5175 board_config = ALC260_BASIC;5176 }5177 }51785179 if (board_config != ALC260_AUTO)5180 setup_preset(spec, &alc260_presets[board_config]);51815182 spec->stream_name_analog = "ALC260 Analog";5183 spec->stream_analog_playback = &alc260_pcm_analog_playback;5184 spec->stream_analog_capture = &alc260_pcm_analog_capture;51855186 spec->stream_name_digital = "ALC260 Digital";5187 spec->stream_digital_playback = &alc260_pcm_digital_playback;5188 spec->stream_digital_capture = &alc260_pcm_digital_capture;51895190 spec->vmaster_nid = 0x08;51915192 codec->patch_ops = alc_patch_ops;5193 if (board_config == ALC260_AUTO)5194 spec->init_hook = alc260_auto_init;5195#ifdef CONFIG_SND_HDA_POWER_SAVE5196 if (!spec->loopback.amplist)5197 spec->loopback.amplist = alc260_loopbacks;5198#endif51995200 return 0;5201}520252035204/*5205 * ALC882 support5206 *5207 * ALC882 is almost identical with ALC880 but has cleaner and more flexible5208 * configuration. Each pin widget can choose any input DACs and a mixer.5209 * Each ADC is connected from a mixer of all inputs. This makes possible5210 * 6-channel independent captures.5211 *5212 * In addition, an independent DAC for the multi-playback (not used in this5213 * driver yet).5214 */5215#define ALC882_DIGOUT_NID 0x065216#define ALC882_DIGIN_NID 0x0a52175218static struct hda_channel_mode alc882_ch_modes[1] = {5219 { 8, NULL }5220};52215222static hda_nid_t alc882_dac_nids[4] = {5223 /* front, rear, clfe, rear_surr */5224 0x02, 0x03, 0x04, 0x055225};52265227/* identical with ALC880 */5228#define alc882_adc_nids alc880_adc_nids5229#define alc882_adc_nids_alt alc880_adc_nids_alt52305231static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };5232static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };52335234/* input MUX */5235/* FIXME: should be a matrix-type input source selection */52365237static struct hda_input_mux alc882_capture_source = {5238 .num_items = 4,5239 .items = {5240 { "Mic", 0x0 },5241 { "Front Mic", 0x1 },5242 { "Line", 0x2 },5243 { "CD", 0x4 },5244 },5245};5246#define alc882_mux_enum_info alc_mux_enum_info5247#define alc882_mux_enum_get alc_mux_enum_get52485249static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,5250 struct snd_ctl_elem_value *ucontrol)5251{5252 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);5253 struct alc_spec *spec = codec->spec;5254 const struct hda_input_mux *imux = spec->input_mux;5255 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);5256 hda_nid_t nid = spec->capsrc_nids ?5257 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];5258 unsigned int *cur_val = &spec->cur_mux[adc_idx];5259 unsigned int i, idx;52605261 idx = ucontrol->value.enumerated.item[0];5262 if (idx >= imux->num_items)5263 idx = imux->num_items - 1;5264 if (*cur_val == idx)5265 return 0;5266 for (i = 0; i < imux->num_items; i++) {5267 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;5268 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,5269 imux->items[i].index,5270 HDA_AMP_MUTE, v);5271 }5272 *cur_val = idx;5273 return 1;5274}52755276/*5277 * 2ch mode5278 */5279static struct hda_verb alc882_3ST_ch2_init[] = {5280 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },5281 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },5282 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },5283 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },5284 { } /* end */5285};52865287/*5288 * 6ch mode5289 */5290static struct hda_verb alc882_3ST_ch6_init[] = {5291 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },5292 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },5293 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },5294 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },5295 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },5296 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },5297 { } /* end */5298};52995300static struct hda_channel_mode alc882_3ST_6ch_modes[2] = {5301 { 2, alc882_3ST_ch2_init },5302 { 6, alc882_3ST_ch6_init },5303};53045305/*5306 * 6ch mode5307 */5308static struct hda_verb alc882_sixstack_ch6_init[] = {5309 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },5310 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },5311 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },5312 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },5313 { } /* end */5314};53155316/*5317 * 8ch mode5318 */5319static struct hda_verb alc882_sixstack_ch8_init[] = {5320 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },5321 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },5322 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },5323 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },5324 { } /* end */5325};53265327static struct hda_channel_mode alc882_sixstack_modes[2] = {5328 { 6, alc882_sixstack_ch6_init },5329 { 8, alc882_sixstack_ch8_init },5330};53315332/*5333 * macbook pro ALC885 can switch LineIn to LineOut without loosing Mic5334 */53355336/*5337 * 2ch mode5338 */5339static struct hda_verb alc885_mbp_ch2_init[] = {5340 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },5341 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5342 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},5343 { } /* end */5344};53455346/*5347 * 6ch mode5348 */5349static struct hda_verb alc885_mbp_ch6_init[] = {5350 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },5351 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5352 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },5353 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5354 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},5355 { } /* end */5356};53575358static struct hda_channel_mode alc885_mbp_6ch_modes[2] = {5359 { 2, alc885_mbp_ch2_init },5360 { 6, alc885_mbp_ch6_init },5361};536253635364/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x175365 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b5366 */5367static struct snd_kcontrol_new alc882_base_mixer[] = {5368 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),5369 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),5370 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),5371 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),5372 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),5373 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),5374 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),5375 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),5376 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),5377 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),5378 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),5379 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),5380 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),5381 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),5382 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),5383 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),5384 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),5385 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),5386 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),5387 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),5388 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),5389 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),5390 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),5391 { } /* end */5392};53935394static struct snd_kcontrol_new alc885_mbp3_mixer[] = {5395 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),5396 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),5397 HDA_CODEC_MUTE ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT),5398 HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0d, 0x00, HDA_OUTPUT),5399 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),5400 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),5401 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),5402 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),5403 HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT),5404 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),5405 { } /* end */5406};5407static struct snd_kcontrol_new alc882_w2jc_mixer[] = {5408 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),5409 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),5410 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),5411 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),5412 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),5413 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),5414 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),5415 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),5416 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),5417 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),5418 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),5419 { } /* end */5420};54215422static struct snd_kcontrol_new alc882_targa_mixer[] = {5423 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),5424 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),5425 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),5426 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),5427 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),5428 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),5429 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),5430 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),5431 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),5432 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),5433 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),5434 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),5435 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),5436 { } /* end */5437};54385439/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???5440 * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c5441 */5442static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {5443 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),5444 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),5445 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),5446 HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),5447 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),5448 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),5449 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),5450 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),5451 HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),5452 HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),5453 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),5454 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),5455 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),5456 { } /* end */5457};54585459static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {5460 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),5461 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),5462 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),5463 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),5464 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),5465 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),5466 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),5467 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),5468 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),5469 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),5470 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),5471 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),5472 { } /* end */5473};54745475static struct snd_kcontrol_new alc882_chmode_mixer[] = {5476 {5477 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,5478 .name = "Channel Mode",5479 .info = alc_ch_mode_info,5480 .get = alc_ch_mode_get,5481 .put = alc_ch_mode_put,5482 },5483 { } /* end */5484};54855486static struct hda_verb alc882_init_verbs[] = {5487 /* Front mixer: unmute input/output amp left and right (volume = 0) */5488 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5489 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5490 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},5491 /* Rear mixer */5492 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5493 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5494 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},5495 /* CLFE mixer */5496 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5497 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5498 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},5499 /* Side mixer */5500 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5501 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5502 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},55035504 /* Front Pin: output 0 (0x0c) */5505 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5506 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5507 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},5508 /* Rear Pin: output 1 (0x0d) */5509 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5510 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5511 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},5512 /* CLFE Pin: output 2 (0x0e) */5513 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5514 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5515 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},5516 /* Side Pin: output 3 (0x0f) */5517 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5518 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5519 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},5520 /* Mic (rear) pin: input vref at 80% */5521 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},5522 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},5523 /* Front Mic pin: input vref at 80% */5524 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},5525 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},5526 /* Line In pin: input */5527 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},5528 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},5529 /* Line-2 In: Headphone output (output 0 - 0x0c) */5530 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},5531 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5532 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},5533 /* CD pin widget for input */5534 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},55355536 /* FIXME: use matrix-type input source selection */5537 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */5538 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */5539 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5540 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},5541 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},5542 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},5543 /* Input mixer2 */5544 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5545 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},5546 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},5547 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},5548 /* Input mixer3 */5549 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5550 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},5551 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},5552 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},5553 /* ADC1: mute amp left and right */5554 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5555 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},5556 /* ADC2: mute amp left and right */5557 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5558 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},5559 /* ADC3: mute amp left and right */5560 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5561 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},55625563 { }5564};55655566static struct hda_verb alc882_eapd_verbs[] = {5567 /* change to EAPD mode */5568 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},5569 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},5570 { }5571};55725573/* Mac Pro test */5574static struct snd_kcontrol_new alc882_macpro_mixer[] = {5575 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),5576 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),5577 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),5578 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),5579 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),5580 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),5581 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),5582 { } /* end */5583};55845585static struct hda_verb alc882_macpro_init_verbs[] = {5586 /* Front mixer: unmute input/output amp left and right (volume = 0) */5587 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5588 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5589 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},5590 /* Front Pin: output 0 (0x0c) */5591 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5592 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5593 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},5594 /* Front Mic pin: input vref at 80% */5595 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},5596 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},5597 /* Speaker: output */5598 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5599 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5600 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},5601 /* Headphone output (output 0 - 0x0c) */5602 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},5603 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5604 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},56055606 /* FIXME: use matrix-type input source selection */5607 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */5608 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */5609 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5610 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},5611 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},5612 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},5613 /* Input mixer2 */5614 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5615 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},5616 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},5617 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},5618 /* Input mixer3 */5619 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5620 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},5621 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},5622 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},5623 /* ADC1: mute amp left and right */5624 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5625 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},5626 /* ADC2: mute amp left and right */5627 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5628 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},5629 /* ADC3: mute amp left and right */5630 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5631 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},56325633 { }5634};56355636/* Macbook Pro rev3 */5637static struct hda_verb alc885_mbp3_init_verbs[] = {5638 /* Front mixer: unmute input/output amp left and right (volume = 0) */5639 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5640 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5641 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},5642 /* Rear mixer */5643 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5644 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5645 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},5646 /* Front Pin: output 0 (0x0c) */5647 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5648 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5649 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},5650 /* HP Pin: output 0 (0x0d) */5651 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},5652 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},5653 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},5654 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},5655 /* Mic (rear) pin: input vref at 80% */5656 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},5657 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},5658 /* Front Mic pin: input vref at 80% */5659 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},5660 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},5661 /* Line In pin: use output 1 when in LineOut mode */5662 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},5663 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},5664 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},56655666 /* FIXME: use matrix-type input source selection */5667 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */5668 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */5669 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5670 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},5671 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},5672 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},5673 /* Input mixer2 */5674 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5675 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},5676 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},5677 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},5678 /* Input mixer3 */5679 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5680 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},5681 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},5682 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},5683 /* ADC1: mute amp left and right */5684 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5685 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},5686 /* ADC2: mute amp left and right */5687 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5688 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},5689 /* ADC3: mute amp left and right */5690 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5691 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},56925693 { }5694};56955696/* iMac 24 mixer. */5697static struct snd_kcontrol_new alc885_imac24_mixer[] = {5698 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),5699 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),5700 { } /* end */5701};57025703/* iMac 24 init verbs. */5704static struct hda_verb alc885_imac24_init_verbs[] = {5705 /* Internal speakers: output 0 (0x0c) */5706 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5707 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5708 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},5709 /* Internal speakers: output 0 (0x0c) */5710 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5711 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5712 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},5713 /* Headphone: output 0 (0x0c) */5714 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},5715 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},5716 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},5717 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},5718 /* Front Mic: input vref at 80% */5719 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},5720 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},5721 { }5722};57235724/* Toggle speaker-output according to the hp-jack state */5725static void alc885_imac24_automute(struct hda_codec *codec)5726{5727 unsigned int present;57285729 present = snd_hda_codec_read(codec, 0x14, 0,5730 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;5731 snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,5732 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);5733 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,5734 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);5735}57365737/* Processes unsolicited events. */5738static void alc885_imac24_unsol_event(struct hda_codec *codec,5739 unsigned int res)5740{5741 /* Headphone insertion or removal. */5742 if ((res >> 26) == ALC880_HP_EVENT)5743 alc885_imac24_automute(codec);5744}57455746static void alc885_mbp3_automute(struct hda_codec *codec)5747{5748 unsigned int present;57495750 present = snd_hda_codec_read(codec, 0x15, 0,5751 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;5752 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,5753 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);5754 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,5755 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);57565757}5758static void alc885_mbp3_unsol_event(struct hda_codec *codec,5759 unsigned int res)5760{5761 /* Headphone insertion or removal. */5762 if ((res >> 26) == ALC880_HP_EVENT)5763 alc885_mbp3_automute(codec);5764}576557665767static struct hda_verb alc882_targa_verbs[] = {5768 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5769 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},57705771 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},5772 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},57735774 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */5775 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */5776 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */57775778 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},5779 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},5780 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},5781 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},5782 { } /* end */5783};57845785/* toggle speaker-output according to the hp-jack state */5786static void alc882_targa_automute(struct hda_codec *codec)5787{5788 unsigned int present;57895790 present = snd_hda_codec_read(codec, 0x14, 0,5791 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;5792 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,5793 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);5794 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,5795 present ? 1 : 3);5796}57975798static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)5799{5800 /* Looks like the unsol event is incompatible with the standard5801 * definition. 4bit tag is placed at 26 bit!5802 */5803 if (((res >> 26) == ALC880_HP_EVENT)) {5804 alc882_targa_automute(codec);5805 }5806}58075808static struct hda_verb alc882_asus_a7j_verbs[] = {5809 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5810 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},58115812 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},5813 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5814 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},58155816 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */5817 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */5818 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */58195820 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */5821 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */5822 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */5823 { } /* end */5824};58255826static struct hda_verb alc882_asus_a7m_verbs[] = {5827 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5828 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},58295830 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},5831 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},5832 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},58335834 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */5835 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */5836 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */58375838 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */5839 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */5840 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */5841 { } /* end */5842};58435844static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)5845{5846 unsigned int gpiostate, gpiomask, gpiodir;58475848 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,5849 AC_VERB_GET_GPIO_DATA, 0);58505851 if (!muted)5852 gpiostate |= (1 << pin);5853 else5854 gpiostate &= ~(1 << pin);58555856 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,5857 AC_VERB_GET_GPIO_MASK, 0);5858 gpiomask |= (1 << pin);58595860 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,5861 AC_VERB_GET_GPIO_DIRECTION, 0);5862 gpiodir |= (1 << pin);586358645865 snd_hda_codec_write(codec, codec->afg, 0,5866 AC_VERB_SET_GPIO_MASK, gpiomask);5867 snd_hda_codec_write(codec, codec->afg, 0,5868 AC_VERB_SET_GPIO_DIRECTION, gpiodir);58695870 msleep(1);58715872 snd_hda_codec_write(codec, codec->afg, 0,5873 AC_VERB_SET_GPIO_DATA, gpiostate);5874}58755876/* set up GPIO at initialization */5877static void alc885_macpro_init_hook(struct hda_codec *codec)5878{5879 alc882_gpio_mute(codec, 0, 0);5880 alc882_gpio_mute(codec, 1, 0);5881}58825883/* set up GPIO and update auto-muting at initialization */5884static void alc885_imac24_init_hook(struct hda_codec *codec)5885{5886 alc885_macpro_init_hook(codec);5887 alc885_imac24_automute(codec);5888}58895890/*5891 * generic initialization of ADC, input mixers and output mixers5892 */5893static struct hda_verb alc882_auto_init_verbs[] = {5894 /*5895 * Unmute ADC0-2 and set the default input to mic-in5896 */5897 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},5898 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5899 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},5900 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5901 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},5902 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},59035904 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback5905 * mixer widget5906 * Note: PASD motherboards uses the Line In 2 as the input for5907 * front panel mic (mic 2)5908 */5909 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */5910 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},5911 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},5912 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},5913 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},5914 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},59155916 /*5917 * Set up output mixers (0x0c - 0x0f)5918 */5919 /* set vol=0 to output mixers */5920 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5921 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5922 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5923 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},5924 /* set up input amps for analog loopback */5925 /* Amp Indices: DAC = 0, mixer = 1 */5926 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5927 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},5928 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5929 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},5930 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5931 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},5932 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5933 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},5934 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},5935 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},59365937 /* FIXME: use matrix-type input source selection */5938 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */5939 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */5940 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},5941 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},5942 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},5943 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},5944 /* Input mixer2 */5945 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},5946 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},5947 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},5948 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},5949 /* Input mixer3 */5950 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},5951 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},5952 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},5953 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},59545955 { }5956};59575958/* capture mixer elements */5959static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {5960 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),5961 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),5962 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),5963 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),5964 {5965 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,5966 /* The multiple "Capture Source" controls confuse alsamixer5967 * So call somewhat different..5968 */5969 /* .name = "Capture Source", */5970 .name = "Input Source",5971 .count = 2,5972 .info = alc882_mux_enum_info,5973 .get = alc882_mux_enum_get,5974 .put = alc882_mux_enum_put,5975 },5976 { } /* end */5977};59785979static struct snd_kcontrol_new alc882_capture_mixer[] = {5980 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),5981 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),5982 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),5983 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),5984 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),5985 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),5986 {5987 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,5988 /* The multiple "Capture Source" controls confuse alsamixer5989 * So call somewhat different..5990 */5991 /* .name = "Capture Source", */5992 .name = "Input Source",5993 .count = 3,5994 .info = alc882_mux_enum_info,5995 .get = alc882_mux_enum_get,5996 .put = alc882_mux_enum_put,5997 },5998 { } /* end */5999};60006001#ifdef CONFIG_SND_HDA_POWER_SAVE6002#define alc882_loopbacks alc880_loopbacks6003#endif60046005/* pcm configuration: identiacal with ALC880 */6006#define alc882_pcm_analog_playback alc880_pcm_analog_playback6007#define alc882_pcm_analog_capture alc880_pcm_analog_capture6008#define alc882_pcm_digital_playback alc880_pcm_digital_playback6009#define alc882_pcm_digital_capture alc880_pcm_digital_capture60106011/*6012 * configuration and preset6013 */6014static const char *alc882_models[ALC882_MODEL_LAST] = {6015 [ALC882_3ST_DIG] = "3stack-dig",6016 [ALC882_6ST_DIG] = "6stack-dig",6017 [ALC882_ARIMA] = "arima",6018 [ALC882_W2JC] = "w2jc",6019 [ALC882_TARGA] = "targa",6020 [ALC882_ASUS_A7J] = "asus-a7j",6021 [ALC882_ASUS_A7M] = "asus-a7m",6022 [ALC885_MACPRO] = "macpro",6023 [ALC885_MBP3] = "mbp3",6024 [ALC885_IMAC24] = "imac24",6025 [ALC882_AUTO] = "auto",6026};60276028static struct snd_pci_quirk alc882_cfg_tbl[] = {6029 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),6030 SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),6031 SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),6032 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),6033 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),6034 SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),6035 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),6036 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),6037 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),6038 SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */6039 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),6040 SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA),6041 {}6042};60436044static struct alc_config_preset alc882_presets[] = {6045 [ALC882_3ST_DIG] = {6046 .mixers = { alc882_base_mixer },6047 .init_verbs = { alc882_init_verbs },6048 .num_dacs = ARRAY_SIZE(alc882_dac_nids),6049 .dac_nids = alc882_dac_nids,6050 .dig_out_nid = ALC882_DIGOUT_NID,6051 .dig_in_nid = ALC882_DIGIN_NID,6052 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),6053 .channel_mode = alc882_ch_modes,6054 .need_dac_fix = 1,6055 .input_mux = &alc882_capture_source,6056 },6057 [ALC882_6ST_DIG] = {6058 .mixers = { alc882_base_mixer, alc882_chmode_mixer },6059 .init_verbs = { alc882_init_verbs },6060 .num_dacs = ARRAY_SIZE(alc882_dac_nids),6061 .dac_nids = alc882_dac_nids,6062 .dig_out_nid = ALC882_DIGOUT_NID,6063 .dig_in_nid = ALC882_DIGIN_NID,6064 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),6065 .channel_mode = alc882_sixstack_modes,6066 .input_mux = &alc882_capture_source,6067 },6068 [ALC882_ARIMA] = {6069 .mixers = { alc882_base_mixer, alc882_chmode_mixer },6070 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs },6071 .num_dacs = ARRAY_SIZE(alc882_dac_nids),6072 .dac_nids = alc882_dac_nids,6073 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),6074 .channel_mode = alc882_sixstack_modes,6075 .input_mux = &alc882_capture_source,6076 },6077 [ALC882_W2JC] = {6078 .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },6079 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs,6080 alc880_gpio1_init_verbs },6081 .num_dacs = ARRAY_SIZE(alc882_dac_nids),6082 .dac_nids = alc882_dac_nids,6083 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),6084 .channel_mode = alc880_threestack_modes,6085 .need_dac_fix = 1,6086 .input_mux = &alc882_capture_source,6087 .dig_out_nid = ALC882_DIGOUT_NID,6088 },6089 [ALC885_MBP3] = {6090 .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },6091 .init_verbs = { alc885_mbp3_init_verbs,6092 alc880_gpio1_init_verbs },6093 .num_dacs = ARRAY_SIZE(alc882_dac_nids),6094 .dac_nids = alc882_dac_nids,6095 .channel_mode = alc885_mbp_6ch_modes,6096 .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes),6097 .input_mux = &alc882_capture_source,6098 .dig_out_nid = ALC882_DIGOUT_NID,6099 .dig_in_nid = ALC882_DIGIN_NID,6100 .unsol_event = alc885_mbp3_unsol_event,6101 .init_hook = alc885_mbp3_automute,6102 },6103 [ALC885_MACPRO] = {6104 .mixers = { alc882_macpro_mixer },6105 .init_verbs = { alc882_macpro_init_verbs },6106 .num_dacs = ARRAY_SIZE(alc882_dac_nids),6107 .dac_nids = alc882_dac_nids,6108 .dig_out_nid = ALC882_DIGOUT_NID,6109 .dig_in_nid = ALC882_DIGIN_NID,6110 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),6111 .channel_mode = alc882_ch_modes,6112 .input_mux = &alc882_capture_source,6113 .init_hook = alc885_macpro_init_hook,6114 },6115 [ALC885_IMAC24] = {6116 .mixers = { alc885_imac24_mixer },6117 .init_verbs = { alc885_imac24_init_verbs },6118 .num_dacs = ARRAY_SIZE(alc882_dac_nids),6119 .dac_nids = alc882_dac_nids,6120 .dig_out_nid = ALC882_DIGOUT_NID,6121 .dig_in_nid = ALC882_DIGIN_NID,6122 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),6123 .channel_mode = alc882_ch_modes,6124 .input_mux = &alc882_capture_source,6125 .unsol_event = alc885_imac24_unsol_event,6126 .init_hook = alc885_imac24_init_hook,6127 },6128 [ALC882_TARGA] = {6129 .mixers = { alc882_targa_mixer, alc882_chmode_mixer,6130 alc882_capture_mixer },6131 .init_verbs = { alc882_init_verbs, alc882_targa_verbs},6132 .num_dacs = ARRAY_SIZE(alc882_dac_nids),6133 .dac_nids = alc882_dac_nids,6134 .dig_out_nid = ALC882_DIGOUT_NID,6135 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),6136 .adc_nids = alc882_adc_nids,6137 .capsrc_nids = alc882_capsrc_nids,6138 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),6139 .channel_mode = alc882_3ST_6ch_modes,6140 .need_dac_fix = 1,6141 .input_mux = &alc882_capture_source,6142 .unsol_event = alc882_targa_unsol_event,6143 .init_hook = alc882_targa_automute,6144 },6145 [ALC882_ASUS_A7J] = {6146 .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer,6147 alc882_capture_mixer },6148 .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs},6149 .num_dacs = ARRAY_SIZE(alc882_dac_nids),6150 .dac_nids = alc882_dac_nids,6151 .dig_out_nid = ALC882_DIGOUT_NID,6152 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),6153 .adc_nids = alc882_adc_nids,6154 .capsrc_nids = alc882_capsrc_nids,6155 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),6156 .channel_mode = alc882_3ST_6ch_modes,6157 .need_dac_fix = 1,6158 .input_mux = &alc882_capture_source,6159 },6160 [ALC882_ASUS_A7M] = {6161 .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },6162 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs,6163 alc880_gpio1_init_verbs,6164 alc882_asus_a7m_verbs },6165 .num_dacs = ARRAY_SIZE(alc882_dac_nids),6166 .dac_nids = alc882_dac_nids,6167 .dig_out_nid = ALC882_DIGOUT_NID,6168 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),6169 .channel_mode = alc880_threestack_modes,6170 .need_dac_fix = 1,6171 .input_mux = &alc882_capture_source,6172 },6173};617461756176/*6177 * Pin config fixes6178 */6179enum {6180 PINFIX_ABIT_AW9D_MAX6181};61826183static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {6184 { 0x15, 0x01080104 }, /* side */6185 { 0x16, 0x01011012 }, /* rear */6186 { 0x17, 0x01016011 }, /* clfe */6187 { }6188};61896190static const struct alc_pincfg *alc882_pin_fixes[] = {6191 [PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix,6192};61936194static struct snd_pci_quirk alc882_pinfix_tbl[] = {6195 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),6196 {}6197};61986199/*6200 * BIOS auto configuration6201 */6202static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,6203 hda_nid_t nid, int pin_type,6204 int dac_idx)6205{6206 /* set as output */6207 struct alc_spec *spec = codec->spec;6208 int idx;62096210 alc_set_pin_output(codec, nid, pin_type);6211 if (spec->multiout.dac_nids[dac_idx] == 0x25)6212 idx = 4;6213 else6214 idx = spec->multiout.dac_nids[dac_idx] - 2;6215 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);62166217}62186219static void alc882_auto_init_multi_out(struct hda_codec *codec)6220{6221 struct alc_spec *spec = codec->spec;6222 int i;62236224 alc_subsystem_id(codec, 0x15, 0x1b, 0x14);6225 for (i = 0; i <= HDA_SIDE; i++) {6226 hda_nid_t nid = spec->autocfg.line_out_pins[i];6227 int pin_type = get_pin_type(spec->autocfg.line_out_type);6228 if (nid)6229 alc882_auto_set_output_and_unmute(codec, nid, pin_type,6230 i);6231 }6232}62336234static void alc882_auto_init_hp_out(struct hda_codec *codec)6235{6236 struct alc_spec *spec = codec->spec;6237 hda_nid_t pin;62386239 pin = spec->autocfg.hp_pins[0];6240 if (pin) /* connect to front */6241 /* use dac 0 */6242 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);6243 pin = spec->autocfg.speaker_pins[0];6244 if (pin)6245 alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);6246}62476248#define alc882_is_input_pin(nid) alc880_is_input_pin(nid)6249#define ALC882_PIN_CD_NID ALC880_PIN_CD_NID62506251static void alc882_auto_init_analog_input(struct hda_codec *codec)6252{6253 struct alc_spec *spec = codec->spec;6254 int i;62556256 for (i = 0; i < AUTO_PIN_LAST; i++) {6257 hda_nid_t nid = spec->autocfg.input_pins[i];6258 if (alc882_is_input_pin(nid)) {6259 snd_hda_codec_write(codec, nid, 0,6260 AC_VERB_SET_PIN_WIDGET_CONTROL,6261 i <= AUTO_PIN_FRONT_MIC ?6262 PIN_VREF80 : PIN_IN);6263 if (nid != ALC882_PIN_CD_NID)6264 snd_hda_codec_write(codec, nid, 0,6265 AC_VERB_SET_AMP_GAIN_MUTE,6266 AMP_OUT_MUTE);6267 }6268 }6269}62706271/* add mic boosts if needed */6272static int alc_auto_add_mic_boost(struct hda_codec *codec)6273{6274 struct alc_spec *spec = codec->spec;6275 int err;6276 hda_nid_t nid;62776278 nid = spec->autocfg.input_pins[AUTO_PIN_MIC];6279 if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {6280 err = add_control(spec, ALC_CTL_WIDGET_VOL,6281 "Mic Boost",6282 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));6283 if (err < 0)6284 return err;6285 }6286 nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];6287 if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {6288 err = add_control(spec, ALC_CTL_WIDGET_VOL,6289 "Front Mic Boost",6290 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));6291 if (err < 0)6292 return err;6293 }6294 return 0;6295}62966297/* almost identical with ALC880 parser... */6298static int alc882_parse_auto_config(struct hda_codec *codec)6299{6300 struct alc_spec *spec = codec->spec;6301 int err = alc880_parse_auto_config(codec);63026303 if (err < 0)6304 return err;6305 else if (!err)6306 return 0; /* no config found */63076308 err = alc_auto_add_mic_boost(codec);6309 if (err < 0)6310 return err;63116312 /* hack - override the init verbs */6313 spec->init_verbs[0] = alc882_auto_init_verbs;63146315 return 1; /* config found */6316}63176318/* additional initialization for auto-configuration model */6319static void alc882_auto_init(struct hda_codec *codec)6320{6321 struct alc_spec *spec = codec->spec;6322 alc882_auto_init_multi_out(codec);6323 alc882_auto_init_hp_out(codec);6324 alc882_auto_init_analog_input(codec);6325 if (spec->unsol_event)6326 alc_sku_automute(codec);6327}63286329static int patch_alc882(struct hda_codec *codec)6330{6331 struct alc_spec *spec;6332 int err, board_config;63336334 spec = kzalloc(sizeof(*spec), GFP_KERNEL);6335 if (spec == NULL)6336 return -ENOMEM;63376338 codec->spec = spec;63396340 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,6341 alc882_models,6342 alc882_cfg_tbl);63436344 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {6345 /* Pick up systems that don't supply PCI SSID */6346 switch (codec->subsystem_id) {6347 case 0x106b0c00: /* Mac Pro */6348 board_config = ALC885_MACPRO;6349 break;6350 case 0x106b1000: /* iMac 24 */6351 board_config = ALC885_IMAC24;6352 break;6353 case 0x106b00a1: /* Macbook */6354 case 0x106b2c00: /* Macbook Pro rev3 */6355 board_config = ALC885_MBP3;6356 break;6357 default:6358 printk(KERN_INFO "hda_codec: Unknown model for ALC882, "6359 "trying auto-probe from BIOS...\n");6360 board_config = ALC882_AUTO;6361 }6362 }63636364 alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes);63656366 if (board_config == ALC882_AUTO) {6367 /* automatic parse from the BIOS config */6368 err = alc882_parse_auto_config(codec);6369 if (err < 0) {6370 alc_free(codec);6371 return err;6372 } else if (!err) {6373 printk(KERN_INFO6374 "hda_codec: Cannot set up configuration "6375 "from BIOS. Using base mode...\n");6376 board_config = ALC882_3ST_DIG;6377 }6378 }63796380 if (board_config != ALC882_AUTO)6381 setup_preset(spec, &alc882_presets[board_config]);63826383 spec->stream_name_analog = "ALC882 Analog";6384 spec->stream_analog_playback = &alc882_pcm_analog_playback;6385 spec->stream_analog_capture = &alc882_pcm_analog_capture;6386 /* FIXME: setup DAC5 */6387 /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/6388 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;63896390 spec->stream_name_digital = "ALC882 Digital";6391 spec->stream_digital_playback = &alc882_pcm_digital_playback;6392 spec->stream_digital_capture = &alc882_pcm_digital_capture;63936394 if (!spec->adc_nids && spec->input_mux) {6395 /* check whether NID 0x07 is valid */6396 unsigned int wcap = get_wcaps(codec, 0x07);6397 /* get type */6398 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;6399 if (wcap != AC_WID_AUD_IN) {6400 spec->adc_nids = alc882_adc_nids_alt;6401 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);6402 spec->capsrc_nids = alc882_capsrc_nids_alt;6403 spec->mixers[spec->num_mixers] =6404 alc882_capture_alt_mixer;6405 spec->num_mixers++;6406 } else {6407 spec->adc_nids = alc882_adc_nids;6408 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);6409 spec->capsrc_nids = alc882_capsrc_nids;6410 spec->mixers[spec->num_mixers] = alc882_capture_mixer;6411 spec->num_mixers++;6412 }6413 }64146415 spec->vmaster_nid = 0x0c;64166417 codec->patch_ops = alc_patch_ops;6418 if (board_config == ALC882_AUTO)6419 spec->init_hook = alc882_auto_init;6420#ifdef CONFIG_SND_HDA_POWER_SAVE6421 if (!spec->loopback.amplist)6422 spec->loopback.amplist = alc882_loopbacks;6423#endif64246425 return 0;6426}64276428/*6429 * ALC883 support6430 *6431 * ALC883 is almost identical with ALC880 but has cleaner and more flexible6432 * configuration. Each pin widget can choose any input DACs and a mixer.6433 * Each ADC is connected from a mixer of all inputs. This makes possible6434 * 6-channel independent captures.6435 *6436 * In addition, an independent DAC for the multi-playback (not used in this6437 * driver yet).6438 */6439#define ALC883_DIGOUT_NID 0x066440#define ALC883_DIGIN_NID 0x0a64416442static hda_nid_t alc883_dac_nids[4] = {6443 /* front, rear, clfe, rear_surr */6444 0x02, 0x04, 0x03, 0x056445};64466447static hda_nid_t alc883_adc_nids[2] = {6448 /* ADC1-2 */6449 0x08, 0x09,6450};64516452static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };64536454/* input MUX */6455/* FIXME: should be a matrix-type input source selection */64566457static struct hda_input_mux alc883_capture_source = {6458 .num_items = 4,6459 .items = {6460 { "Mic", 0x0 },6461 { "Front Mic", 0x1 },6462 { "Line", 0x2 },6463 { "CD", 0x4 },6464 },6465};64666467static struct hda_input_mux alc883_lenovo_101e_capture_source = {6468 .num_items = 2,6469 .items = {6470 { "Mic", 0x1 },6471 { "Line", 0x2 },6472 },6473};64746475static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {6476 .num_items = 4,6477 .items = {6478 { "Mic", 0x0 },6479 { "iMic", 0x1 },6480 { "Line", 0x2 },6481 { "CD", 0x4 },6482 },6483};64846485#define alc883_mux_enum_info alc_mux_enum_info6486#define alc883_mux_enum_get alc_mux_enum_get6487/* ALC883 has the ALC882-type input selection */6488#define alc883_mux_enum_put alc882_mux_enum_put64896490/*6491 * 2ch mode6492 */6493static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {6494 { 2, NULL }6495};64966497/*6498 * 2ch mode6499 */6500static struct hda_verb alc883_3ST_ch2_init[] = {6501 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },6502 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },6503 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },6504 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },6505 { } /* end */6506};65076508/*6509 * 4ch mode6510 */6511static struct hda_verb alc883_3ST_ch4_init[] = {6512 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },6513 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },6514 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },6515 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },6516 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },6517 { } /* end */6518};65196520/*6521 * 6ch mode6522 */6523static struct hda_verb alc883_3ST_ch6_init[] = {6524 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },6525 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },6526 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },6527 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },6528 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },6529 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },6530 { } /* end */6531};65326533static struct hda_channel_mode alc883_3ST_6ch_modes[3] = {6534 { 2, alc883_3ST_ch2_init },6535 { 4, alc883_3ST_ch4_init },6536 { 6, alc883_3ST_ch6_init },6537};65386539/*6540 * 6ch mode6541 */6542static struct hda_verb alc883_sixstack_ch6_init[] = {6543 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },6544 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },6545 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },6546 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },6547 { } /* end */6548};65496550/*6551 * 8ch mode6552 */6553static struct hda_verb alc883_sixstack_ch8_init[] = {6554 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },6555 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },6556 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },6557 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },6558 { } /* end */6559};65606561static struct hda_channel_mode alc883_sixstack_modes[2] = {6562 { 6, alc883_sixstack_ch6_init },6563 { 8, alc883_sixstack_ch8_init },6564};65656566static struct hda_verb alc883_medion_eapd_verbs[] = {6567 /* eanable EAPD on medion laptop */6568 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},6569 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},6570 { }6571};65726573/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x176574 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b6575 */65766577static struct snd_kcontrol_new alc883_base_mixer[] = {6578 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6579 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),6580 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),6581 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),6582 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),6583 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),6584 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),6585 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),6586 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),6587 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),6588 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),6589 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6590 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6591 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),6592 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),6593 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6594 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6595 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6596 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),6597 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),6598 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),6599 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),6600 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),6601 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6602 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6603 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6604 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6605 {6606 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6607 /* .name = "Capture Source", */6608 .name = "Input Source",6609 .count = 2,6610 .info = alc883_mux_enum_info,6611 .get = alc883_mux_enum_get,6612 .put = alc883_mux_enum_put,6613 },6614 { } /* end */6615};66166617static struct snd_kcontrol_new alc883_mitac_mixer[] = {6618 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6619 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),6620 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),6621 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),6622 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),6623 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),6624 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),6625 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6626 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6627 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6628 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),6629 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),6630 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),6631 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6632 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6633 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6634 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6635 {6636 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6637 /* .name = "Capture Source", */6638 .name = "Input Source",6639 .count = 2,6640 .info = alc883_mux_enum_info,6641 .get = alc883_mux_enum_get,6642 .put = alc883_mux_enum_put,6643 },6644 { } /* end */6645};66466647static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {6648 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6649 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),6650 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),6651 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6652 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6653 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),6654 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),6655 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6656 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6657 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6658 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),6659 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),6660 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),6661 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),6662 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),6663 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6664 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6665 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6666 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6667 {6668 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6669 /* .name = "Capture Source", */6670 .name = "Input Source",6671 .count = 2,6672 .info = alc883_mux_enum_info,6673 .get = alc883_mux_enum_get,6674 .put = alc883_mux_enum_put,6675 },6676 { } /* end */6677};66786679static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {6680 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6681 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),6682 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),6683 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),6684 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),6685 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),6686 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),6687 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),6688 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),6689 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6690 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6691 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),6692 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),6693 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6694 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6695 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6696 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),6697 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),6698 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),6699 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),6700 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),6701 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6702 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6703 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6704 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6705 {6706 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6707 /* .name = "Capture Source", */6708 .name = "Input Source",6709 .count = 2,6710 .info = alc883_mux_enum_info,6711 .get = alc883_mux_enum_get,6712 .put = alc883_mux_enum_put,6713 },6714 { } /* end */6715};67166717static struct snd_kcontrol_new alc883_fivestack_mixer[] = {6718 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6719 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),6720 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),6721 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),6722 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),6723 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),6724 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),6725 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),6726 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),6727 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6728 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6729 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),6730 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),6731 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6732 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6733 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6734 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),6735 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),6736 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),6737 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),6738 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),6739 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6740 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),67416742 {6743 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6744 /* .name = "Capture Source", */6745 .name = "Input Source",6746 .count = 1,6747 .info = alc883_mux_enum_info,6748 .get = alc883_mux_enum_get,6749 .put = alc883_mux_enum_put,6750 },6751 { } /* end */6752};67536754static struct snd_kcontrol_new alc883_tagra_mixer[] = {6755 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6756 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),6757 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),6758 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),6759 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),6760 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),6761 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),6762 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),6763 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),6764 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6765 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6766 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),6767 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),6768 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6769 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6770 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6771 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6772 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6773 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6774 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6775 {6776 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6777 /* .name = "Capture Source", */6778 .name = "Input Source",6779 .count = 2,6780 .info = alc883_mux_enum_info,6781 .get = alc883_mux_enum_get,6782 .put = alc883_mux_enum_put,6783 },6784 { } /* end */6785};67866787static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {6788 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6789 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),6790 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),6791 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6792 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6793 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6794 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6795 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6796 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6797 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6798 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6799 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6800 {6801 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6802 /* .name = "Capture Source", */6803 .name = "Input Source",6804 .count = 2,6805 .info = alc883_mux_enum_info,6806 .get = alc883_mux_enum_get,6807 .put = alc883_mux_enum_put,6808 },6809 { } /* end */6810};68116812static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {6813 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6814 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),6815 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),6816 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),6817 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),6818 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),6819 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6820 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),6821 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6822 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6823 {6824 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6825 /* .name = "Capture Source", */6826 .name = "Input Source",6827 .count = 1,6828 .info = alc883_mux_enum_info,6829 .get = alc883_mux_enum_get,6830 .put = alc883_mux_enum_put,6831 },6832 { } /* end */6833};68346835static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {6836 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6837 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),6838 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),6839 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6840 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6841 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6842 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6843 HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT),6844 HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT),6845 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6846 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6847 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6848 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6849 {6850 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6851 /* .name = "Capture Source", */6852 .name = "Input Source",6853 .count = 2,6854 .info = alc883_mux_enum_info,6855 .get = alc883_mux_enum_get,6856 .put = alc883_mux_enum_put,6857 },6858 { } /* end */6859};68606861static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {6862 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6863 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),6864 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),6865 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6866 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6867 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6868 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6869 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),6870 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),6871 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6872 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6873 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6874 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6875 {6876 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6877 /* .name = "Capture Source", */6878 .name = "Input Source",6879 .count = 2,6880 .info = alc883_mux_enum_info,6881 .get = alc883_mux_enum_get,6882 .put = alc883_mux_enum_put,6883 },6884 { } /* end */6885};68866887static struct snd_kcontrol_new alc888_6st_hp_mixer[] = {6888 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6889 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),6890 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),6891 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),6892 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),6893 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),6894 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),6895 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),6896 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),6897 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),6898 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),6899 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6900 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6901 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),6902 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),6903 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6904 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6905 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6906 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),6907 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),6908 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),6909 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),6910 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),6911 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6912 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6913 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6914 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6915 {6916 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6917 /* .name = "Capture Source", */6918 .name = "Input Source",6919 .count = 2,6920 .info = alc883_mux_enum_info,6921 .get = alc883_mux_enum_get,6922 .put = alc883_mux_enum_put,6923 },6924 { } /* end */6925};69266927static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {6928 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6929 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),6930 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),6931 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),6932 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),6933 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),6934 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),6935 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),6936 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),6937 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6938 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6939 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),6940 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),6941 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6942 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6943 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6944 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),6945 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),6946 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),6947 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),6948 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),6949 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6950 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6951 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6952 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6953 {6954 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6955 /* .name = "Capture Source", */6956 .name = "Input Source",6957 .count = 2,6958 .info = alc883_mux_enum_info,6959 .get = alc883_mux_enum_get,6960 .put = alc883_mux_enum_put,6961 },6962 { } /* end */6963};69646965static struct snd_kcontrol_new alc888_6st_dell_mixer[] = {6966 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),6967 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),6968 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),6969 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),6970 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),6971 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),6972 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),6973 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),6974 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),6975 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),6976 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),6977 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),6978 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),6979 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),6980 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),6981 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),6982 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),6983 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),6984 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),6985 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),6986 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),6987 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),6988 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),6989 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),6990 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),6991 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),6992 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),6993 {6994 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,6995 /* .name = "Capture Source", */6996 .name = "Input Source",6997 .count = 2,6998 .info = alc883_mux_enum_info,6999 .get = alc883_mux_enum_get,7000 .put = alc883_mux_enum_put,7001 },7002 { } /* end */7003};70047005static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {7006 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),7007 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),7008 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),7009 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),7010 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),7011 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),7012 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),7013 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),7014 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),7015 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),7016 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),7017 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),7018 {7019 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,7020 /* .name = "Capture Source", */7021 .name = "Input Source",7022 .count = 2,7023 .info = alc883_mux_enum_info,7024 .get = alc883_mux_enum_get,7025 .put = alc883_mux_enum_put,7026 },7027 { } /* end */7028};70297030static struct snd_kcontrol_new alc883_chmode_mixer[] = {7031 {7032 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,7033 .name = "Channel Mode",7034 .info = alc_ch_mode_info,7035 .get = alc_ch_mode_get,7036 .put = alc_ch_mode_put,7037 },7038 { } /* end */7039};70407041static struct hda_verb alc883_init_verbs[] = {7042 /* ADC1: mute amp left and right */7043 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},7044 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},7045 /* ADC2: mute amp left and right */7046 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},7047 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},7048 /* Front mixer: unmute input/output amp left and right (volume = 0) */7049 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},7050 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},7051 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},7052 /* Rear mixer */7053 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},7054 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},7055 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},7056 /* CLFE mixer */7057 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},7058 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},7059 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},7060 /* Side mixer */7061 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},7062 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},7063 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},70647065 /* mute analog input loopbacks */7066 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},7067 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},7068 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},7069 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},7070 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},70717072 /* Front Pin: output 0 (0x0c) */7073 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},7074 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},7075 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},7076 /* Rear Pin: output 1 (0x0d) */7077 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},7078 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},7079 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},7080 /* CLFE Pin: output 2 (0x0e) */7081 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},7082 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},7083 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},7084 /* Side Pin: output 3 (0x0f) */7085 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},7086 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},7087 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},7088 /* Mic (rear) pin: input vref at 80% */7089 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},7090 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},7091 /* Front Mic pin: input vref at 80% */7092 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},7093 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},7094 /* Line In pin: input */7095 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},7096 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},7097 /* Line-2 In: Headphone output (output 0 - 0x0c) */7098 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},7099 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},7100 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},7101 /* CD pin widget for input */7102 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},71037104 /* FIXME: use matrix-type input source selection */7105 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */7106 /* Input mixer2 */7107 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7108 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},7109 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},7110 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},7111 /* Input mixer3 */7112 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7113 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},7114 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},7115 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},7116 { }7117};71187119/* toggle speaker-output according to the hp-jack state */7120static void alc883_mitac_hp_automute(struct hda_codec *codec)7121{7122 unsigned int present;71237124 present = snd_hda_codec_read(codec, 0x15, 0,7125 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7126 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,7127 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7128 snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,7129 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7130}71317132/* auto-toggle front mic */7133/*7134static void alc883_mitac_mic_automute(struct hda_codec *codec)7135{7136 unsigned int present;7137 unsigned char bits;71387139 present = snd_hda_codec_read(codec, 0x18, 0,7140 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7141 bits = present ? HDA_AMP_MUTE : 0;7142 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);7143}7144*/71457146static void alc883_mitac_automute(struct hda_codec *codec)7147{7148 alc883_mitac_hp_automute(codec);7149 /* alc883_mitac_mic_automute(codec); */7150}71517152static void alc883_mitac_unsol_event(struct hda_codec *codec,7153 unsigned int res)7154{7155 switch (res >> 26) {7156 case ALC880_HP_EVENT:7157 alc883_mitac_hp_automute(codec);7158 break;7159 case ALC880_MIC_EVENT:7160 /* alc883_mitac_mic_automute(codec); */7161 break;7162 }7163}71647165static struct hda_verb alc883_mitac_verbs[] = {7166 /* HP */7167 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},7168 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},7169 /* Subwoofer */7170 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},7171 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},71727173 /* enable unsolicited event */7174 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},7175 /* {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, */71767177 { } /* end */7178};71797180static struct hda_verb alc883_tagra_verbs[] = {7181 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7182 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},71837184 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},7185 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},71867187 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */7188 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */7189 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */71907191 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},7192 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},7193 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},7194 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},71957196 { } /* end */7197};71987199static struct hda_verb alc883_lenovo_101e_verbs[] = {7200 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},7201 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},7202 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},7203 { } /* end */7204};72057206static struct hda_verb alc883_lenovo_nb0763_verbs[] = {7207 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},7208 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},7209 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},7210 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},7211 { } /* end */7212};72137214static struct hda_verb alc888_lenovo_ms7195_verbs[] = {7215 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7216 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},7217 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},7218 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN},7219 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},7220 { } /* end */7221};72227223static struct hda_verb alc883_haier_w66_verbs[] = {7224 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7225 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},72267227 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},72287229 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},7230 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},7231 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},7232 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},7233 { } /* end */7234};72357236static struct hda_verb alc888_6st_hp_verbs[] = {7237 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */7238 {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */7239 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* CLFE : output 1 (0x0d) */7240 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, /* Side : output 3 (0x0f) */7241 { }7242};72437244static struct hda_verb alc888_3st_hp_verbs[] = {7245 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */7246 {0x18, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */7247 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */7248 { }7249};72507251static struct hda_verb alc888_6st_dell_verbs[] = {7252 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */7253 {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 1 (0x0e) */7254 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* CLFE : output 2 (0x0d) */7255 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, /* Side : output 3 (0x0f) */7256 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},7257 { }7258};72597260static struct hda_verb alc888_3st_hp_2ch_init[] = {7261 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },7262 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },7263 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },7264 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },7265 { }7266};72677268static struct hda_verb alc888_3st_hp_6ch_init[] = {7269 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },7270 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },7271 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },7272 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },7273 { }7274};72757276static struct hda_channel_mode alc888_3st_hp_modes[2] = {7277 { 2, alc888_3st_hp_2ch_init },7278 { 6, alc888_3st_hp_6ch_init },7279};72807281/* toggle front-jack and RCA according to the hp-jack state */7282static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)7283{7284 unsigned int present;72857286 present = snd_hda_codec_read(codec, 0x1b, 0,7287 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7288 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,7289 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7290 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,7291 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7292}72937294/* toggle RCA according to the front-jack state */7295static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)7296{7297 unsigned int present;72987299 present = snd_hda_codec_read(codec, 0x14, 0,7300 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7301 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,7302 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7303}73047305static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,7306 unsigned int res)7307{7308 if ((res >> 26) == ALC880_HP_EVENT)7309 alc888_lenovo_ms7195_front_automute(codec);7310 if ((res >> 26) == ALC880_FRONT_EVENT)7311 alc888_lenovo_ms7195_rca_automute(codec);7312}73137314static struct hda_verb alc883_medion_md2_verbs[] = {7315 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7316 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},73177318 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},73197320 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},7321 { } /* end */7322};73237324/* toggle speaker-output according to the hp-jack state */7325static void alc883_medion_md2_automute(struct hda_codec *codec)7326{7327 unsigned int present;73287329 present = snd_hda_codec_read(codec, 0x14, 0,7330 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7331 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,7332 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7333}73347335static void alc883_medion_md2_unsol_event(struct hda_codec *codec,7336 unsigned int res)7337{7338 if ((res >> 26) == ALC880_HP_EVENT)7339 alc883_medion_md2_automute(codec);7340}73417342/* toggle speaker-output according to the hp-jack state */7343static void alc883_tagra_automute(struct hda_codec *codec)7344{7345 unsigned int present;7346 unsigned char bits;73477348 present = snd_hda_codec_read(codec, 0x14, 0,7349 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7350 bits = present ? HDA_AMP_MUTE : 0;7351 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,7352 HDA_AMP_MUTE, bits);7353 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,7354 present ? 1 : 3);7355}73567357static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)7358{7359 if ((res >> 26) == ALC880_HP_EVENT)7360 alc883_tagra_automute(codec);7361}73627363static void alc883_haier_w66_automute(struct hda_codec *codec)7364{7365 unsigned int present;7366 unsigned char bits;73677368 present = snd_hda_codec_read(codec, 0x1b, 0,7369 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7370 bits = present ? 0x80 : 0;7371 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,7372 0x80, bits);7373}73747375static void alc883_haier_w66_unsol_event(struct hda_codec *codec,7376 unsigned int res)7377{7378 if ((res >> 26) == ALC880_HP_EVENT)7379 alc883_haier_w66_automute(codec);7380}73817382static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)7383{7384 unsigned int present;7385 unsigned char bits;73867387 present = snd_hda_codec_read(codec, 0x14, 0,7388 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7389 bits = present ? HDA_AMP_MUTE : 0;7390 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,7391 HDA_AMP_MUTE, bits);7392}73937394static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)7395{7396 unsigned int present;7397 unsigned char bits;73987399 present = snd_hda_codec_read(codec, 0x1b, 0,7400 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7401 bits = present ? HDA_AMP_MUTE : 0;7402 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,7403 HDA_AMP_MUTE, bits);7404 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,7405 HDA_AMP_MUTE, bits);7406}74077408static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,7409 unsigned int res)7410{7411 if ((res >> 26) == ALC880_HP_EVENT)7412 alc883_lenovo_101e_all_automute(codec);7413 if ((res >> 26) == ALC880_FRONT_EVENT)7414 alc883_lenovo_101e_ispeaker_automute(codec);7415}74167417/* toggle speaker-output according to the hp-jack state */7418static void alc883_acer_aspire_automute(struct hda_codec *codec)7419{7420 unsigned int present;74217422 present = snd_hda_codec_read(codec, 0x14, 0,7423 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7424 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,7425 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7426 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,7427 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7428}74297430static void alc883_acer_aspire_unsol_event(struct hda_codec *codec,7431 unsigned int res)7432{7433 if ((res >> 26) == ALC880_HP_EVENT)7434 alc883_acer_aspire_automute(codec);7435}74367437static struct hda_verb alc883_acer_eapd_verbs[] = {7438 /* HP Pin: output 0 (0x0c) */7439 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},7440 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},7441 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},7442 /* Front Pin: output 0 (0x0c) */7443 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},7444 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},7445 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},7446 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},7447 /* eanable EAPD on medion laptop */7448 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},7449 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},7450 /* enable unsolicited event */7451 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},7452 { }7453};74547455static void alc888_6st_dell_front_automute(struct hda_codec *codec)7456{7457 unsigned int present;74587459 present = snd_hda_codec_read(codec, 0x1b, 0,7460 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;7461 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,7462 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7463 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,7464 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7465 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,7466 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7467 snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,7468 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);7469}74707471static void alc888_6st_dell_unsol_event(struct hda_codec *codec,7472 unsigned int res)7473{7474 switch (res >> 26) {7475 case ALC880_HP_EVENT:7476 printk("hp_event\n");7477 alc888_6st_dell_front_automute(codec);7478 break;7479 }7480}74817482/*7483 * generic initialization of ADC, input mixers and output mixers7484 */7485static struct hda_verb alc883_auto_init_verbs[] = {7486 /*7487 * Unmute ADC0-2 and set the default input to mic-in7488 */7489 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},7490 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7491 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},7492 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},74937494 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback7495 * mixer widget7496 * Note: PASD motherboards uses the Line In 2 as the input for7497 * front panel mic (mic 2)7498 */7499 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */7500 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},7501 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},7502 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},7503 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},7504 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},75057506 /*7507 * Set up output mixers (0x0c - 0x0f)7508 */7509 /* set vol=0 to output mixers */7510 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},7511 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},7512 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},7513 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},7514 /* set up input amps for analog loopback */7515 /* Amp Indices: DAC = 0, mixer = 1 */7516 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7517 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},7518 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7519 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},7520 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7521 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},7522 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7523 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},7524 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7525 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},75267527 /* FIXME: use matrix-type input source selection */7528 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */7529 /* Input mixer1 */7530 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7531 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},7532 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},7533 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */7534 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},7535 /* Input mixer2 */7536 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},7537 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},7538 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},7539 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */7540 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},75417542 { }7543};75447545/* capture mixer elements */7546static struct snd_kcontrol_new alc883_capture_mixer[] = {7547 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),7548 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),7549 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),7550 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),7551 {7552 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,7553 /* The multiple "Capture Source" controls confuse alsamixer7554 * So call somewhat different..7555 */7556 /* .name = "Capture Source", */7557 .name = "Input Source",7558 .count = 2,7559 .info = alc882_mux_enum_info,7560 .get = alc882_mux_enum_get,7561 .put = alc882_mux_enum_put,7562 },7563 { } /* end */7564};75657566#ifdef CONFIG_SND_HDA_POWER_SAVE7567#define alc883_loopbacks alc880_loopbacks7568#endif75697570/* pcm configuration: identiacal with ALC880 */7571#define alc883_pcm_analog_playback alc880_pcm_analog_playback7572#define alc883_pcm_analog_capture alc880_pcm_analog_capture7573#define alc883_pcm_analog_alt_capture alc880_pcm_analog_alt_capture7574#define alc883_pcm_digital_playback alc880_pcm_digital_playback7575#define alc883_pcm_digital_capture alc880_pcm_digital_capture75767577/*7578 * configuration and preset7579 */7580static const char *alc883_models[ALC883_MODEL_LAST] = {7581 [ALC883_3ST_2ch_DIG] = "3stack-dig",7582 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig",7583 [ALC883_3ST_6ch] = "3stack-6ch",7584 [ALC883_6ST_DIG] = "6stack-dig",7585 [ALC883_TARGA_DIG] = "targa-dig",7586 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",7587 [ALC883_ACER] = "acer",7588 [ALC883_ACER_ASPIRE] = "acer-aspire",7589 [ALC883_MEDION] = "medion",7590 [ALC883_MEDION_MD2] = "medion-md2",7591 [ALC883_LAPTOP_EAPD] = "laptop-eapd",7592 [ALC883_LENOVO_101E_2ch] = "lenovo-101e",7593 [ALC883_LENOVO_NB0763] = "lenovo-nb0763",7594 [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",7595 [ALC883_HAIER_W66] = "haier-w66",7596 [ALC888_6ST_HP] = "6stack-hp",7597 [ALC888_3ST_HP] = "3stack-hp",7598 [ALC888_6ST_DELL] = "6stack-dell",7599 [ALC883_MITAC] = "mitac",7600 [ALC883_AUTO] = "auto",7601};76027603static struct snd_pci_quirk alc883_cfg_tbl[] = {7604 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),7605 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),7606 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),7607 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),7608 SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */7609 SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),7610 SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),7611 SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),7612 SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),7613 SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_6ST_HP),7614 SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),7615 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),7616 SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),7617 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),7618 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),7619 SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG),7620 SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),7621 SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),7622 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),7623 SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),7624 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),7625 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),7626 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),7627 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),7628 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),7629 SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),7630 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),7631 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),7632 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),7633 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),7634 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),7635 SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),7636 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),7637 SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),7638 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),7639 SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),7640 SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),7641 SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),7642 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),7643 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),7644 SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),7645 SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),7646 SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),7647 SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),7648 SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),7649 SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),7650 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),7651 {}7652};76537654static struct alc_config_preset alc883_presets[] = {7655 [ALC883_3ST_2ch_DIG] = {7656 .mixers = { alc883_3ST_2ch_mixer },7657 .init_verbs = { alc883_init_verbs },7658 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7659 .dac_nids = alc883_dac_nids,7660 .dig_out_nid = ALC883_DIGOUT_NID,7661 .dig_in_nid = ALC883_DIGIN_NID,7662 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),7663 .channel_mode = alc883_3ST_2ch_modes,7664 .input_mux = &alc883_capture_source,7665 },7666 [ALC883_3ST_6ch_DIG] = {7667 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },7668 .init_verbs = { alc883_init_verbs },7669 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7670 .dac_nids = alc883_dac_nids,7671 .dig_out_nid = ALC883_DIGOUT_NID,7672 .dig_in_nid = ALC883_DIGIN_NID,7673 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),7674 .channel_mode = alc883_3ST_6ch_modes,7675 .need_dac_fix = 1,7676 .input_mux = &alc883_capture_source,7677 },7678 [ALC883_3ST_6ch] = {7679 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },7680 .init_verbs = { alc883_init_verbs },7681 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7682 .dac_nids = alc883_dac_nids,7683 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),7684 .channel_mode = alc883_3ST_6ch_modes,7685 .need_dac_fix = 1,7686 .input_mux = &alc883_capture_source,7687 },7688 [ALC883_6ST_DIG] = {7689 .mixers = { alc883_base_mixer, alc883_chmode_mixer },7690 .init_verbs = { alc883_init_verbs },7691 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7692 .dac_nids = alc883_dac_nids,7693 .dig_out_nid = ALC883_DIGOUT_NID,7694 .dig_in_nid = ALC883_DIGIN_NID,7695 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),7696 .channel_mode = alc883_sixstack_modes,7697 .input_mux = &alc883_capture_source,7698 },7699 [ALC883_TARGA_DIG] = {7700 .mixers = { alc883_tagra_mixer, alc883_chmode_mixer },7701 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs},7702 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7703 .dac_nids = alc883_dac_nids,7704 .dig_out_nid = ALC883_DIGOUT_NID,7705 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),7706 .channel_mode = alc883_3ST_6ch_modes,7707 .need_dac_fix = 1,7708 .input_mux = &alc883_capture_source,7709 .unsol_event = alc883_tagra_unsol_event,7710 .init_hook = alc883_tagra_automute,7711 },7712 [ALC883_TARGA_2ch_DIG] = {7713 .mixers = { alc883_tagra_2ch_mixer},7714 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs},7715 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7716 .dac_nids = alc883_dac_nids,7717 .dig_out_nid = ALC883_DIGOUT_NID,7718 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),7719 .channel_mode = alc883_3ST_2ch_modes,7720 .input_mux = &alc883_capture_source,7721 .unsol_event = alc883_tagra_unsol_event,7722 .init_hook = alc883_tagra_automute,7723 },7724 [ALC883_ACER] = {7725 .mixers = { alc883_base_mixer },7726 /* On TravelMate laptops, GPIO 0 enables the internal speaker7727 * and the headphone jack. Turn this on and rely on the7728 * standard mute methods whenever the user wants to turn7729 * these outputs off.7730 */7731 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },7732 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7733 .dac_nids = alc883_dac_nids,7734 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),7735 .channel_mode = alc883_3ST_2ch_modes,7736 .input_mux = &alc883_capture_source,7737 },7738 [ALC883_ACER_ASPIRE] = {7739 .mixers = { alc883_acer_aspire_mixer },7740 .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },7741 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7742 .dac_nids = alc883_dac_nids,7743 .dig_out_nid = ALC883_DIGOUT_NID,7744 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),7745 .channel_mode = alc883_3ST_2ch_modes,7746 .input_mux = &alc883_capture_source,7747 .unsol_event = alc883_acer_aspire_unsol_event,7748 .init_hook = alc883_acer_aspire_automute,7749 },7750 [ALC883_MEDION] = {7751 .mixers = { alc883_fivestack_mixer,7752 alc883_chmode_mixer },7753 .init_verbs = { alc883_init_verbs,7754 alc883_medion_eapd_verbs },7755 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7756 .dac_nids = alc883_dac_nids,7757 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),7758 .channel_mode = alc883_sixstack_modes,7759 .input_mux = &alc883_capture_source,7760 },7761 [ALC883_MEDION_MD2] = {7762 .mixers = { alc883_medion_md2_mixer},7763 .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs},7764 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7765 .dac_nids = alc883_dac_nids,7766 .dig_out_nid = ALC883_DIGOUT_NID,7767 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),7768 .channel_mode = alc883_3ST_2ch_modes,7769 .input_mux = &alc883_capture_source,7770 .unsol_event = alc883_medion_md2_unsol_event,7771 .init_hook = alc883_medion_md2_automute,7772 },7773 [ALC883_LAPTOP_EAPD] = {7774 .mixers = { alc883_base_mixer },7775 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },7776 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7777 .dac_nids = alc883_dac_nids,7778 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),7779 .channel_mode = alc883_3ST_2ch_modes,7780 .input_mux = &alc883_capture_source,7781 },7782 [ALC883_LENOVO_101E_2ch] = {7783 .mixers = { alc883_lenovo_101e_2ch_mixer},7784 .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},7785 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7786 .dac_nids = alc883_dac_nids,7787 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),7788 .channel_mode = alc883_3ST_2ch_modes,7789 .input_mux = &alc883_lenovo_101e_capture_source,7790 .unsol_event = alc883_lenovo_101e_unsol_event,7791 .init_hook = alc883_lenovo_101e_all_automute,7792 },7793 [ALC883_LENOVO_NB0763] = {7794 .mixers = { alc883_lenovo_nb0763_mixer },7795 .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},7796 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7797 .dac_nids = alc883_dac_nids,7798 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),7799 .channel_mode = alc883_3ST_2ch_modes,7800 .need_dac_fix = 1,7801 .input_mux = &alc883_lenovo_nb0763_capture_source,7802 .unsol_event = alc883_medion_md2_unsol_event,7803 .init_hook = alc883_medion_md2_automute,7804 },7805 [ALC888_LENOVO_MS7195_DIG] = {7806 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },7807 .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},7808 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7809 .dac_nids = alc883_dac_nids,7810 .dig_out_nid = ALC883_DIGOUT_NID,7811 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),7812 .channel_mode = alc883_3ST_6ch_modes,7813 .need_dac_fix = 1,7814 .input_mux = &alc883_capture_source,7815 .unsol_event = alc883_lenovo_ms7195_unsol_event,7816 .init_hook = alc888_lenovo_ms7195_front_automute,7817 },7818 [ALC883_HAIER_W66] = {7819 .mixers = { alc883_tagra_2ch_mixer},7820 .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},7821 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7822 .dac_nids = alc883_dac_nids,7823 .dig_out_nid = ALC883_DIGOUT_NID,7824 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),7825 .channel_mode = alc883_3ST_2ch_modes,7826 .input_mux = &alc883_capture_source,7827 .unsol_event = alc883_haier_w66_unsol_event,7828 .init_hook = alc883_haier_w66_automute,7829 },7830 [ALC888_6ST_HP] = {7831 .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer },7832 .init_verbs = { alc883_init_verbs, alc888_6st_hp_verbs },7833 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7834 .dac_nids = alc883_dac_nids,7835 .dig_out_nid = ALC883_DIGOUT_NID,7836 .dig_in_nid = ALC883_DIGIN_NID,7837 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),7838 .channel_mode = alc883_sixstack_modes,7839 .input_mux = &alc883_capture_source,7840 },7841 [ALC888_3ST_HP] = {7842 .mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer },7843 .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },7844 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7845 .dac_nids = alc883_dac_nids,7846 .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),7847 .channel_mode = alc888_3st_hp_modes,7848 .need_dac_fix = 1,7849 .input_mux = &alc883_capture_source,7850 },7851 [ALC888_6ST_DELL] = {7852 .mixers = { alc888_6st_dell_mixer, alc883_chmode_mixer },7853 .init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },7854 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7855 .dac_nids = alc883_dac_nids,7856 .dig_out_nid = ALC883_DIGOUT_NID,7857 .dig_in_nid = ALC883_DIGIN_NID,7858 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),7859 .channel_mode = alc883_sixstack_modes,7860 .input_mux = &alc883_capture_source,7861 .unsol_event = alc888_6st_dell_unsol_event,7862 .init_hook = alc888_6st_dell_front_automute,7863 },7864 [ALC883_MITAC] = {7865 .mixers = { alc883_mitac_mixer },7866 .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },7867 .num_dacs = ARRAY_SIZE(alc883_dac_nids),7868 .dac_nids = alc883_dac_nids,7869 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),7870 .channel_mode = alc883_3ST_2ch_modes,7871 .input_mux = &alc883_capture_source,7872 .unsol_event = alc883_mitac_unsol_event,7873 .init_hook = alc883_mitac_automute,7874 },7875};787678777878/*7879 * BIOS auto configuration7880 */7881static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,7882 hda_nid_t nid, int pin_type,7883 int dac_idx)7884{7885 /* set as output */7886 struct alc_spec *spec = codec->spec;7887 int idx;78887889 alc_set_pin_output(codec, nid, pin_type);7890 if (spec->multiout.dac_nids[dac_idx] == 0x25)7891 idx = 4;7892 else7893 idx = spec->multiout.dac_nids[dac_idx] - 2;7894 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);78957896}78977898static void alc883_auto_init_multi_out(struct hda_codec *codec)7899{7900 struct alc_spec *spec = codec->spec;7901 int i;79027903 alc_subsystem_id(codec, 0x15, 0x1b, 0x14);7904 for (i = 0; i <= HDA_SIDE; i++) {7905 hda_nid_t nid = spec->autocfg.line_out_pins[i];7906 int pin_type = get_pin_type(spec->autocfg.line_out_type);7907 if (nid)7908 alc883_auto_set_output_and_unmute(codec, nid, pin_type,7909 i);7910 }7911}79127913static void alc883_auto_init_hp_out(struct hda_codec *codec)7914{7915 struct alc_spec *spec = codec->spec;7916 hda_nid_t pin;79177918 pin = spec->autocfg.hp_pins[0];7919 if (pin) /* connect to front */7920 /* use dac 0 */7921 alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);7922 pin = spec->autocfg.speaker_pins[0];7923 if (pin)7924 alc883_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);7925}79267927#define alc883_is_input_pin(nid) alc880_is_input_pin(nid)7928#define ALC883_PIN_CD_NID ALC880_PIN_CD_NID79297930static void alc883_auto_init_analog_input(struct hda_codec *codec)7931{7932 struct alc_spec *spec = codec->spec;7933 int i;79347935 for (i = 0; i < AUTO_PIN_LAST; i++) {7936 hda_nid_t nid = spec->autocfg.input_pins[i];7937 if (alc883_is_input_pin(nid)) {7938 snd_hda_codec_write(codec, nid, 0,7939 AC_VERB_SET_PIN_WIDGET_CONTROL,7940 (i <= AUTO_PIN_FRONT_MIC ?7941 PIN_VREF80 : PIN_IN));7942 if (nid != ALC883_PIN_CD_NID)7943 snd_hda_codec_write(codec, nid, 0,7944 AC_VERB_SET_AMP_GAIN_MUTE,7945 AMP_OUT_MUTE);7946 }7947 }7948}79497950/* almost identical with ALC880 parser... */7951static int alc883_parse_auto_config(struct hda_codec *codec)7952{7953 struct alc_spec *spec = codec->spec;7954 int err = alc880_parse_auto_config(codec);79557956 if (err < 0)7957 return err;7958 else if (!err)7959 return 0; /* no config found */79607961 err = alc_auto_add_mic_boost(codec);7962 if (err < 0)7963 return err;79647965 /* hack - override the init verbs */7966 spec->init_verbs[0] = alc883_auto_init_verbs;7967 spec->mixers[spec->num_mixers] = alc883_capture_mixer;7968 spec->num_mixers++;79697970 return 1; /* config found */7971}79727973/* additional initialization for auto-configuration model */7974static void alc883_auto_init(struct hda_codec *codec)7975{7976 struct alc_spec *spec = codec->spec;7977 alc883_auto_init_multi_out(codec);7978 alc883_auto_init_hp_out(codec);7979 alc883_auto_init_analog_input(codec);7980 if (spec->unsol_event)7981 alc_sku_automute(codec);7982}79837984static int patch_alc883(struct hda_codec *codec)7985{7986 struct alc_spec *spec;7987 int err, board_config;79887989 spec = kzalloc(sizeof(*spec), GFP_KERNEL);7990 if (spec == NULL)7991 return -ENOMEM;79927993 codec->spec = spec;79947995 board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,7996 alc883_models,7997 alc883_cfg_tbl);7998 if (board_config < 0) {7999 printk(KERN_INFO "hda_codec: Unknown model for ALC883, "8000 "trying auto-probe from BIOS...\n");8001 board_config = ALC883_AUTO;8002 }80038004 if (board_config == ALC883_AUTO) {8005 /* automatic parse from the BIOS config */8006 err = alc883_parse_auto_config(codec);8007 if (err < 0) {8008 alc_free(codec);8009 return err;8010 } else if (!err) {8011 printk(KERN_INFO8012 "hda_codec: Cannot set up configuration "8013 "from BIOS. Using base mode...\n");8014 board_config = ALC883_3ST_2ch_DIG;8015 }8016 }80178018 if (board_config != ALC883_AUTO)8019 setup_preset(spec, &alc883_presets[board_config]);80208021 spec->stream_name_analog = "ALC883 Analog";8022 spec->stream_analog_playback = &alc883_pcm_analog_playback;8023 spec->stream_analog_capture = &alc883_pcm_analog_capture;8024 spec->stream_analog_alt_capture = &alc883_pcm_analog_alt_capture;80258026 spec->stream_name_digital = "ALC883 Digital";8027 spec->stream_digital_playback = &alc883_pcm_digital_playback;8028 spec->stream_digital_capture = &alc883_pcm_digital_capture;80298030 spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);8031 spec->adc_nids = alc883_adc_nids;8032 spec->capsrc_nids = alc883_capsrc_nids;80338034 spec->vmaster_nid = 0x0c;80358036 codec->patch_ops = alc_patch_ops;8037 if (board_config == ALC883_AUTO)8038 spec->init_hook = alc883_auto_init;8039#ifdef CONFIG_SND_HDA_POWER_SAVE8040 if (!spec->loopback.amplist)8041 spec->loopback.amplist = alc883_loopbacks;8042#endif80438044 return 0;8045}80468047/*8048 * ALC262 support8049 */80508051#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID8052#define ALC262_DIGIN_NID ALC880_DIGIN_NID80538054#define alc262_dac_nids alc260_dac_nids8055#define alc262_adc_nids alc882_adc_nids8056#define alc262_adc_nids_alt alc882_adc_nids_alt8057#define alc262_capsrc_nids alc882_capsrc_nids8058#define alc262_capsrc_nids_alt alc882_capsrc_nids_alt80598060#define alc262_modes alc260_modes8061#define alc262_capture_source alc882_capture_source80628063static struct snd_kcontrol_new alc262_base_mixer[] = {8064 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),8065 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),8066 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),8067 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),8068 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),8069 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),8070 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),8071 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),8072 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),8073 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),8074 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),8075 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),8076 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),8077 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */8078 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),8079 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),8080 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),8081 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),8082 { } /* end */8083};80848085static struct snd_kcontrol_new alc262_hippo1_mixer[] = {8086 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),8087 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),8088 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),8089 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),8090 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),8091 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),8092 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),8093 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),8094 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),8095 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),8096 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),8097 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),8098 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),8099 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */8100 /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/8101 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),8102 { } /* end */8103};81048105/* update HP, line and mono-out pins according to the master switch */8106static void alc262_hp_master_update(struct hda_codec *codec)8107{8108 struct alc_spec *spec = codec->spec;8109 int val = spec->master_sw;81108111 /* HP & line-out */8112 snd_hda_codec_write_cache(codec, 0x1b, 0,8113 AC_VERB_SET_PIN_WIDGET_CONTROL,8114 val ? PIN_HP : 0);8115 snd_hda_codec_write_cache(codec, 0x15, 0,8116 AC_VERB_SET_PIN_WIDGET_CONTROL,8117 val ? PIN_HP : 0);8118 /* mono (speaker) depending on the HP jack sense */8119 val = val && !spec->jack_present;8120 snd_hda_codec_write_cache(codec, 0x16, 0,8121 AC_VERB_SET_PIN_WIDGET_CONTROL,8122 val ? PIN_OUT : 0);8123}81248125static void alc262_hp_bpc_automute(struct hda_codec *codec)8126{8127 struct alc_spec *spec = codec->spec;8128 unsigned int presence;8129 presence = snd_hda_codec_read(codec, 0x1b, 0,8130 AC_VERB_GET_PIN_SENSE, 0);8131 spec->jack_present = !!(presence & AC_PINSENSE_PRESENCE);8132 alc262_hp_master_update(codec);8133}81348135static void alc262_hp_bpc_unsol_event(struct hda_codec *codec, unsigned int res)8136{8137 if ((res >> 26) != ALC880_HP_EVENT)8138 return;8139 alc262_hp_bpc_automute(codec);8140}81418142static void alc262_hp_wildwest_automute(struct hda_codec *codec)8143{8144 struct alc_spec *spec = codec->spec;8145 unsigned int presence;8146 presence = snd_hda_codec_read(codec, 0x15, 0,8147 AC_VERB_GET_PIN_SENSE, 0);8148 spec->jack_present = !!(presence & AC_PINSENSE_PRESENCE);8149 alc262_hp_master_update(codec);8150}81518152static void alc262_hp_wildwest_unsol_event(struct hda_codec *codec,8153 unsigned int res)8154{8155 if ((res >> 26) != ALC880_HP_EVENT)8156 return;8157 alc262_hp_wildwest_automute(codec);8158}81598160static int alc262_hp_master_sw_get(struct snd_kcontrol *kcontrol,8161 struct snd_ctl_elem_value *ucontrol)8162{8163 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);8164 struct alc_spec *spec = codec->spec;8165 *ucontrol->value.integer.value = spec->master_sw;8166 return 0;8167}81688169static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,8170 struct snd_ctl_elem_value *ucontrol)8171{8172 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);8173 struct alc_spec *spec = codec->spec;8174 int val = !!*ucontrol->value.integer.value;81758176 if (val == spec->master_sw)8177 return 0;8178 spec->master_sw = val;8179 alc262_hp_master_update(codec);8180 return 1;8181}81828183static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {8184 {8185 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,8186 .name = "Master Playback Switch",8187 .info = snd_ctl_boolean_mono_info,8188 .get = alc262_hp_master_sw_get,8189 .put = alc262_hp_master_sw_put,8190 },8191 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),8192 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),8193 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),8194 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,8195 HDA_OUTPUT),8196 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,8197 HDA_OUTPUT),8198 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),8199 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),8200 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),8201 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),8202 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),8203 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),8204 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),8205 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),8206 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),8207 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),8208 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),8209 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),8210 HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),8211 HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),8212 { } /* end */8213};82148215static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {8216 {8217 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,8218 .name = "Master Playback Switch",8219 .info = snd_ctl_boolean_mono_info,8220 .get = alc262_hp_master_sw_get,8221 .put = alc262_hp_master_sw_put,8222 },8223 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),8224 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),8225 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),8226 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),8227 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,8228 HDA_OUTPUT),8229 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,8230 HDA_OUTPUT),8231 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),8232 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),8233 HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT),8234 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),8235 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),8236 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),8237 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),8238 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),8239 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),8240 { } /* end */8241};82428243static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {8244 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),8245 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),8246 HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT),8247 { } /* end */8248};82498250/* mute/unmute internal speaker according to the hp jack and mute state */8251static void alc262_hp_t5735_automute(struct hda_codec *codec, int force)8252{8253 struct alc_spec *spec = codec->spec;82548255 if (force || !spec->sense_updated) {8256 unsigned int present;8257 present = snd_hda_codec_read(codec, 0x15, 0,8258 AC_VERB_GET_PIN_SENSE, 0);8259 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;8260 spec->sense_updated = 1;8261 }8262 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0, HDA_AMP_MUTE,8263 spec->jack_present ? HDA_AMP_MUTE : 0);8264}82658266static void alc262_hp_t5735_unsol_event(struct hda_codec *codec,8267 unsigned int res)8268{8269 if ((res >> 26) != ALC880_HP_EVENT)8270 return;8271 alc262_hp_t5735_automute(codec, 1);8272}82738274static void alc262_hp_t5735_init_hook(struct hda_codec *codec)8275{8276 alc262_hp_t5735_automute(codec, 1);8277}82788279static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {8280 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),8281 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),8282 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),8283 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),8284 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),8285 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),8286 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),8287 { } /* end */8288};82898290static struct hda_verb alc262_hp_t5735_verbs[] = {8291 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},8292 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},82938294 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},8295 { }8296};82978298static struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {8299 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),8300 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),8301 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),8302 HDA_CODEC_MUTE("Speaker Playback Switch", 0x16, 0x0, HDA_OUTPUT),8303 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),8304 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),8305 { } /* end */8306};83078308static struct hda_verb alc262_hp_rp5700_verbs[] = {8309 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},8310 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},8311 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},8312 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},8313 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},8314 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},8315 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},8316 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},8317 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},8318 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},8319 {}8320};83218322static struct hda_input_mux alc262_hp_rp5700_capture_source = {8323 .num_items = 1,8324 .items = {8325 { "Line", 0x1 },8326 },8327};83288329/* bind hp and internal speaker mute (with plug check) */8330static int alc262_sony_master_sw_put(struct snd_kcontrol *kcontrol,8331 struct snd_ctl_elem_value *ucontrol)8332{8333 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);8334 long *valp = ucontrol->value.integer.value;8335 int change;83368337 /* change hp mute */8338 change = snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,8339 HDA_AMP_MUTE,8340 valp[0] ? 0 : HDA_AMP_MUTE);8341 change |= snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,8342 HDA_AMP_MUTE,8343 valp[1] ? 0 : HDA_AMP_MUTE);8344 if (change) {8345 /* change speaker according to HP jack state */8346 struct alc_spec *spec = codec->spec;8347 unsigned int mute;8348 if (spec->jack_present)8349 mute = HDA_AMP_MUTE;8350 else8351 mute = snd_hda_codec_amp_read(codec, 0x15, 0,8352 HDA_OUTPUT, 0);8353 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,8354 HDA_AMP_MUTE, mute);8355 }8356 return change;8357}83588359static struct snd_kcontrol_new alc262_sony_mixer[] = {8360 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),8361 {8362 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,8363 .name = "Master Playback Switch",8364 .info = snd_hda_mixer_amp_switch_info,8365 .get = snd_hda_mixer_amp_switch_get,8366 .put = alc262_sony_master_sw_put,8367 .private_value = HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),8368 },8369 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),8370 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),8371 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),8372 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),8373 { } /* end */8374};83758376static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {8377 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),8378 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),8379 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),8380 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),8381 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),8382 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),8383 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),8384 { } /* end */8385};83868387#define alc262_capture_mixer alc882_capture_mixer8388#define alc262_capture_alt_mixer alc882_capture_alt_mixer83898390/*8391 * generic initialization of ADC, input mixers and output mixers8392 */8393static struct hda_verb alc262_init_verbs[] = {8394 /*8395 * Unmute ADC0-2 and set the default input to mic-in8396 */8397 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},8398 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8399 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},8400 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8401 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},8402 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},84038404 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback8405 * mixer widget8406 * Note: PASD motherboards uses the Line In 2 as the input for8407 * front panel mic (mic 2)8408 */8409 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */8410 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},8411 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},8412 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},8413 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},8414 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},84158416 /*8417 * Set up output mixers (0x0c - 0x0e)8418 */8419 /* set vol=0 to output mixers */8420 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},8421 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},8422 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},8423 /* set up input amps for analog loopback */8424 /* Amp Indices: DAC = 0, mixer = 1 */8425 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8426 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},8427 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8428 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},8429 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8430 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},84318432 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},8433 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},8434 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},8435 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},8436 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},8437 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},84388439 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},8440 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},8441 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},8442 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},8443 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},84448445 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},8446 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},84478448 /* FIXME: use matrix-type input source selection */8449 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */8450 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */8451 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},8452 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},8453 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},8454 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},8455 /* Input mixer2 */8456 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},8457 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},8458 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},8459 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},8460 /* Input mixer3 */8461 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},8462 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},8463 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},8464 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},84658466 { }8467};84688469static struct hda_verb alc262_hippo_unsol_verbs[] = {8470 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},8471 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},8472 {}8473};84748475static struct hda_verb alc262_hippo1_unsol_verbs[] = {8476 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},8477 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},8478 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},84798480 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},8481 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},8482 {}8483};84848485static struct hda_verb alc262_sony_unsol_verbs[] = {8486 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},8487 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},8488 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic84898490 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},8491 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},8492};84938494/* mute/unmute internal speaker according to the hp jack and mute state */8495static void alc262_hippo_automute(struct hda_codec *codec)8496{8497 struct alc_spec *spec = codec->spec;8498 unsigned int mute;8499 unsigned int present;85008501 /* need to execute and sync at first */8502 snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);8503 present = snd_hda_codec_read(codec, 0x15, 0,8504 AC_VERB_GET_PIN_SENSE, 0);8505 spec->jack_present = (present & 0x80000000) != 0;8506 if (spec->jack_present) {8507 /* mute internal speaker */8508 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,8509 HDA_AMP_MUTE, HDA_AMP_MUTE);8510 } else {8511 /* unmute internal speaker if necessary */8512 mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);8513 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,8514 HDA_AMP_MUTE, mute);8515 }8516}85178518/* unsolicited event for HP jack sensing */8519static void alc262_hippo_unsol_event(struct hda_codec *codec,8520 unsigned int res)8521{8522 if ((res >> 26) != ALC880_HP_EVENT)8523 return;8524 alc262_hippo_automute(codec);8525}85268527static void alc262_hippo1_automute(struct hda_codec *codec)8528{8529 unsigned int mute;8530 unsigned int present;85318532 snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);8533 present = snd_hda_codec_read(codec, 0x1b, 0,8534 AC_VERB_GET_PIN_SENSE, 0);8535 present = (present & 0x80000000) != 0;8536 if (present) {8537 /* mute internal speaker */8538 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,8539 HDA_AMP_MUTE, HDA_AMP_MUTE);8540 } else {8541 /* unmute internal speaker if necessary */8542 mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);8543 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,8544 HDA_AMP_MUTE, mute);8545 }8546}85478548/* unsolicited event for HP jack sensing */8549static void alc262_hippo1_unsol_event(struct hda_codec *codec,8550 unsigned int res)8551{8552 if ((res >> 26) != ALC880_HP_EVENT)8553 return;8554 alc262_hippo1_automute(codec);8555}85568557/*8558 * fujitsu model8559 * 0x14 = headphone/spdif-out, 0x15 = internal speaker8560 */85618562#define ALC_HP_EVENT 0x3785638564static struct hda_verb alc262_fujitsu_unsol_verbs[] = {8565 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},8566 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},8567 {}8568};85698570static struct hda_input_mux alc262_fujitsu_capture_source = {8571 .num_items = 3,8572 .items = {8573 { "Mic", 0x0 },8574 { "Int Mic", 0x1 },8575 { "CD", 0x4 },8576 },8577};85788579static struct hda_input_mux alc262_HP_capture_source = {8580 .num_items = 5,8581 .items = {8582 { "Mic", 0x0 },8583 { "Front Mic", 0x1 },8584 { "Line", 0x2 },8585 { "CD", 0x4 },8586 { "AUX IN", 0x6 },8587 },8588};85898590static struct hda_input_mux alc262_HP_D7000_capture_source = {8591 .num_items = 4,8592 .items = {8593 { "Mic", 0x0 },8594 { "Front Mic", 0x2 },8595 { "Line", 0x1 },8596 { "CD", 0x4 },8597 },8598};85998600/* mute/unmute internal speaker according to the hp jack and mute state */8601static void alc262_fujitsu_automute(struct hda_codec *codec, int force)8602{8603 struct alc_spec *spec = codec->spec;8604 unsigned int mute;86058606 if (force || !spec->sense_updated) {8607 unsigned int present;8608 /* need to execute and sync at first */8609 snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);8610 present = snd_hda_codec_read(codec, 0x14, 0,8611 AC_VERB_GET_PIN_SENSE, 0);8612 spec->jack_present = (present & 0x80000000) != 0;8613 spec->sense_updated = 1;8614 }8615 if (spec->jack_present) {8616 /* mute internal speaker */8617 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,8618 HDA_AMP_MUTE, HDA_AMP_MUTE);8619 } else {8620 /* unmute internal speaker if necessary */8621 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);8622 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,8623 HDA_AMP_MUTE, mute);8624 }8625}86268627/* unsolicited event for HP jack sensing */8628static void alc262_fujitsu_unsol_event(struct hda_codec *codec,8629 unsigned int res)8630{8631 if ((res >> 26) != ALC_HP_EVENT)8632 return;8633 alc262_fujitsu_automute(codec, 1);8634}86358636/* bind volumes of both NID 0x0c and 0x0d */8637static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {8638 .ops = &snd_hda_bind_vol,8639 .values = {8640 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),8641 HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),8642 08643 },8644};86458646/* bind hp and internal speaker mute (with plug check) */8647static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,8648 struct snd_ctl_elem_value *ucontrol)8649{8650 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);8651 long *valp = ucontrol->value.integer.value;8652 int change;86538654 change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,8655 HDA_AMP_MUTE,8656 valp[0] ? 0 : HDA_AMP_MUTE);8657 change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,8658 HDA_AMP_MUTE,8659 valp[1] ? 0 : HDA_AMP_MUTE);8660 if (change)8661 alc262_fujitsu_automute(codec, 0);8662 return change;8663}86648665static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {8666 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),8667 {8668 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,8669 .name = "Master Playback Switch",8670 .info = snd_hda_mixer_amp_switch_info,8671 .get = snd_hda_mixer_amp_switch_get,8672 .put = alc262_fujitsu_master_sw_put,8673 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),8674 },8675 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),8676 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),8677 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),8678 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),8679 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),8680 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),8681 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),8682 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),8683 { } /* end */8684};86858686/* additional init verbs for Benq laptops */8687static struct hda_verb alc262_EAPD_verbs[] = {8688 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},8689 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},8690 {}8691};86928693static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {8694 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},8695 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},86968697 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},8698 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},8699 {}8700};87018702/* Samsung Q1 Ultra Vista model setup */8703static struct snd_kcontrol_new alc262_ultra_mixer[] = {8704 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),8705 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),8706 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),8707 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),8708 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),8709 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),8710 { } /* end */8711};87128713static struct hda_verb alc262_ultra_verbs[] = {8714 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},8715 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},8716 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},8717 /* Mic is on Node 0x19 */8718 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},8719 {0x22, AC_VERB_SET_CONNECT_SEL, 0x01},8720 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},8721 {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},8722 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},8723 {0x24, AC_VERB_SET_CONNECT_SEL, 0x01},8724 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},8725 {}8726};87278728static struct hda_input_mux alc262_ultra_capture_source = {8729 .num_items = 1,8730 .items = {8731 { "Mic", 0x1 },8732 },8733};87348735/* mute/unmute internal speaker according to the hp jack and mute state */8736static void alc262_ultra_automute(struct hda_codec *codec)8737{8738 struct alc_spec *spec = codec->spec;8739 unsigned int mute;8740 unsigned int present;87418742 /* need to execute and sync at first */8743 snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);8744 present = snd_hda_codec_read(codec, 0x15, 0,8745 AC_VERB_GET_PIN_SENSE, 0);8746 spec->jack_present = (present & 0x80000000) != 0;8747 if (spec->jack_present) {8748 /* mute internal speaker */8749 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,8750 HDA_AMP_MUTE, HDA_AMP_MUTE);8751 } else {8752 /* unmute internal speaker if necessary */8753 mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);8754 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,8755 HDA_AMP_MUTE, mute);8756 }8757}87588759/* unsolicited event for HP jack sensing */8760static void alc262_ultra_unsol_event(struct hda_codec *codec,8761 unsigned int res)8762{8763 if ((res >> 26) != ALC880_HP_EVENT)8764 return;8765 alc262_ultra_automute(codec);8766}87678768/* add playback controls from the parsed DAC table */8769static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,8770 const struct auto_pin_cfg *cfg)8771{8772 hda_nid_t nid;8773 int err;87748775 spec->multiout.num_dacs = 1; /* only use one dac */8776 spec->multiout.dac_nids = spec->private_dac_nids;8777 spec->multiout.dac_nids[0] = 2;87788779 nid = cfg->line_out_pins[0];8780 if (nid) {8781 err = add_control(spec, ALC_CTL_WIDGET_VOL,8782 "Front Playback Volume",8783 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT));8784 if (err < 0)8785 return err;8786 err = add_control(spec, ALC_CTL_WIDGET_MUTE,8787 "Front Playback Switch",8788 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));8789 if (err < 0)8790 return err;8791 }87928793 nid = cfg->speaker_pins[0];8794 if (nid) {8795 if (nid == 0x16) {8796 err = add_control(spec, ALC_CTL_WIDGET_VOL,8797 "Speaker Playback Volume",8798 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,8799 HDA_OUTPUT));8800 if (err < 0)8801 return err;8802 err = add_control(spec, ALC_CTL_WIDGET_MUTE,8803 "Speaker Playback Switch",8804 HDA_COMPOSE_AMP_VAL(nid, 2, 0,8805 HDA_OUTPUT));8806 if (err < 0)8807 return err;8808 } else {8809 err = add_control(spec, ALC_CTL_WIDGET_MUTE,8810 "Speaker Playback Switch",8811 HDA_COMPOSE_AMP_VAL(nid, 3, 0,8812 HDA_OUTPUT));8813 if (err < 0)8814 return err;8815 }8816 }8817 nid = cfg->hp_pins[0];8818 if (nid) {8819 /* spec->multiout.hp_nid = 2; */8820 if (nid == 0x16) {8821 err = add_control(spec, ALC_CTL_WIDGET_VOL,8822 "Headphone Playback Volume",8823 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,8824 HDA_OUTPUT));8825 if (err < 0)8826 return err;8827 err = add_control(spec, ALC_CTL_WIDGET_MUTE,8828 "Headphone Playback Switch",8829 HDA_COMPOSE_AMP_VAL(nid, 2, 0,8830 HDA_OUTPUT));8831 if (err < 0)8832 return err;8833 } else {8834 err = add_control(spec, ALC_CTL_WIDGET_MUTE,8835 "Headphone Playback Switch",8836 HDA_COMPOSE_AMP_VAL(nid, 3, 0,8837 HDA_OUTPUT));8838 if (err < 0)8839 return err;8840 }8841 }8842 return 0;8843}88448845/* identical with ALC880 */8846#define alc262_auto_create_analog_input_ctls \8847 alc880_auto_create_analog_input_ctls88488849/*8850 * generic initialization of ADC, input mixers and output mixers8851 */8852static struct hda_verb alc262_volume_init_verbs[] = {8853 /*8854 * Unmute ADC0-2 and set the default input to mic-in8855 */8856 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},8857 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8858 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},8859 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8860 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},8861 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},88628863 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback8864 * mixer widget8865 * Note: PASD motherboards uses the Line In 2 as the input for8866 * front panel mic (mic 2)8867 */8868 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */8869 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},8870 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},8871 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},8872 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},8873 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},88748875 /*8876 * Set up output mixers (0x0c - 0x0f)8877 */8878 /* set vol=0 to output mixers */8879 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},8880 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},8881 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},88828883 /* set up input amps for analog loopback */8884 /* Amp Indices: DAC = 0, mixer = 1 */8885 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8886 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},8887 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8888 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},8889 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8890 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},88918892 /* FIXME: use matrix-type input source selection */8893 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */8894 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */8895 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},8896 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},8897 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},8898 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},8899 /* Input mixer2 */8900 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},8901 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},8902 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},8903 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},8904 /* Input mixer3 */8905 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},8906 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},8907 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},8908 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},89098910 { }8911};89128913static struct hda_verb alc262_HP_BPC_init_verbs[] = {8914 /*8915 * Unmute ADC0-2 and set the default input to mic-in8916 */8917 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},8918 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8919 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},8920 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8921 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},8922 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},89238924 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback8925 * mixer widget8926 * Note: PASD motherboards uses the Line In 2 as the input for8927 * front panel mic (mic 2)8928 */8929 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */8930 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},8931 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},8932 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},8933 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},8934 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},8935 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},8936 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},89378938 /*8939 * Set up output mixers (0x0c - 0x0e)8940 */8941 /* set vol=0 to output mixers */8942 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},8943 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},8944 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},89458946 /* set up input amps for analog loopback */8947 /* Amp Indices: DAC = 0, mixer = 1 */8948 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8949 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},8950 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8951 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},8952 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},8953 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},89548955 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},8956 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },8957 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },89588959 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },8960 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },89618962 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},8963 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},89648965 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},8966 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},8967 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},8968 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},8969 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},89708971 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },8972 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },8973 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },8974 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },8975 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },8976 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },897789788979 /* FIXME: use matrix-type input source selection */8980 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */8981 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */8982 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},8983 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},8984 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},8985 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},8986 /* Input mixer2 */8987 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},8988 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},8989 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},8990 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},8991 /* Input mixer3 */8992 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},8993 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},8994 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},8995 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},89968997 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},89988999 { }9000};90019002static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {9003 /*9004 * Unmute ADC0-2 and set the default input to mic-in9005 */9006 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},9007 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9008 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},9009 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9010 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},9011 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},90129013 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback9014 * mixer widget9015 * Note: PASD motherboards uses the Line In 2 as the input for front9016 * panel mic (mic 2)9017 */9018 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */9019 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},9020 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},9021 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},9022 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},9023 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},9024 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},9025 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},9026 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},9027 /*9028 * Set up output mixers (0x0c - 0x0e)9029 */9030 /* set vol=0 to output mixers */9031 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},9032 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},9033 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},90349035 /* set up input amps for analog loopback */9036 /* Amp Indices: DAC = 0, mixer = 1 */9037 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9038 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},9039 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9040 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},9041 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9042 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},904390449045 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */9046 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */9047 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */9048 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */9049 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */9050 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */9051 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */90529053 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },9054 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },90559056 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},9057 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},90589059 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */9060 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },9061 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },9062 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },9063 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },9064 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },90659066 /* FIXME: use matrix-type input source selection */9067 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */9068 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */9069 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/9070 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/9071 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/9072 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/9073 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/9074 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */9075 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/9076 /* Input mixer2 */9077 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},9078 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},9079 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},9080 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},9081 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},9082 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */9083 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},9084 /* Input mixer3 */9085 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},9086 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},9087 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},9088 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},9089 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},9090 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */9091 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},90929093 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},90949095 { }9096};90979098#ifdef CONFIG_SND_HDA_POWER_SAVE9099#define alc262_loopbacks alc880_loopbacks9100#endif91019102/* pcm configuration: identiacal with ALC880 */9103#define alc262_pcm_analog_playback alc880_pcm_analog_playback9104#define alc262_pcm_analog_capture alc880_pcm_analog_capture9105#define alc262_pcm_digital_playback alc880_pcm_digital_playback9106#define alc262_pcm_digital_capture alc880_pcm_digital_capture91079108/*9109 * BIOS auto configuration9110 */9111static int alc262_parse_auto_config(struct hda_codec *codec)9112{9113 struct alc_spec *spec = codec->spec;9114 int err;9115 static hda_nid_t alc262_ignore[] = { 0x1d, 0 };91169117 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,9118 alc262_ignore);9119 if (err < 0)9120 return err;9121 if (!spec->autocfg.line_outs)9122 return 0; /* can't find valid BIOS pin config */9123 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);9124 if (err < 0)9125 return err;9126 err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg);9127 if (err < 0)9128 return err;91299130 spec->multiout.max_channels = spec->multiout.num_dacs * 2;91319132 if (spec->autocfg.dig_out_pin)9133 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;9134 if (spec->autocfg.dig_in_pin)9135 spec->dig_in_nid = ALC262_DIGIN_NID;91369137 if (spec->kctl_alloc)9138 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;91399140 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;9141 spec->num_mux_defs = 1;9142 spec->input_mux = &spec->private_imux;91439144 err = alc_auto_add_mic_boost(codec);9145 if (err < 0)9146 return err;91479148 return 1;9149}91509151#define alc262_auto_init_multi_out alc882_auto_init_multi_out9152#define alc262_auto_init_hp_out alc882_auto_init_hp_out9153#define alc262_auto_init_analog_input alc882_auto_init_analog_input915491559156/* init callback for auto-configuration model -- overriding the default init */9157static void alc262_auto_init(struct hda_codec *codec)9158{9159 struct alc_spec *spec = codec->spec;9160 alc262_auto_init_multi_out(codec);9161 alc262_auto_init_hp_out(codec);9162 alc262_auto_init_analog_input(codec);9163 if (spec->unsol_event)9164 alc_sku_automute(codec);9165}91669167/*9168 * configuration and preset9169 */9170static const char *alc262_models[ALC262_MODEL_LAST] = {9171 [ALC262_BASIC] = "basic",9172 [ALC262_HIPPO] = "hippo",9173 [ALC262_HIPPO_1] = "hippo_1",9174 [ALC262_FUJITSU] = "fujitsu",9175 [ALC262_HP_BPC] = "hp-bpc",9176 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",9177 [ALC262_HP_TC_T5735] = "hp-tc-t5735",9178 [ALC262_HP_RP5700] = "hp-rp5700",9179 [ALC262_BENQ_ED8] = "benq",9180 [ALC262_BENQ_T31] = "benq-t31",9181 [ALC262_SONY_ASSAMD] = "sony-assamd",9182 [ALC262_ULTRA] = "ultra",9183 [ALC262_AUTO] = "auto",9184};91859186static struct snd_pci_quirk alc262_cfg_tbl[] = {9187 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),9188 SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC),9189 SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC),9190 SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC),9191 SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC),9192 SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC),9193 SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC),9194 SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC),9195 SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC),9196 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),9197 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),9198 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),9199 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),9200 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),9201 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),9202 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),9203 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),9204 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),9205 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),9206 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),9207 SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735",9208 ALC262_HP_TC_T5735),9209 SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700),9210 SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),9211 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),9212 SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),9213 SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),9214 SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),9215 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),9216 SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),9217 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),9218 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),9219 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),9220 {}9221};92229223static struct alc_config_preset alc262_presets[] = {9224 [ALC262_BASIC] = {9225 .mixers = { alc262_base_mixer },9226 .init_verbs = { alc262_init_verbs },9227 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9228 .dac_nids = alc262_dac_nids,9229 .hp_nid = 0x03,9230 .num_channel_mode = ARRAY_SIZE(alc262_modes),9231 .channel_mode = alc262_modes,9232 .input_mux = &alc262_capture_source,9233 },9234 [ALC262_HIPPO] = {9235 .mixers = { alc262_base_mixer },9236 .init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},9237 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9238 .dac_nids = alc262_dac_nids,9239 .hp_nid = 0x03,9240 .dig_out_nid = ALC262_DIGOUT_NID,9241 .num_channel_mode = ARRAY_SIZE(alc262_modes),9242 .channel_mode = alc262_modes,9243 .input_mux = &alc262_capture_source,9244 .unsol_event = alc262_hippo_unsol_event,9245 .init_hook = alc262_hippo_automute,9246 },9247 [ALC262_HIPPO_1] = {9248 .mixers = { alc262_hippo1_mixer },9249 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},9250 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9251 .dac_nids = alc262_dac_nids,9252 .hp_nid = 0x02,9253 .dig_out_nid = ALC262_DIGOUT_NID,9254 .num_channel_mode = ARRAY_SIZE(alc262_modes),9255 .channel_mode = alc262_modes,9256 .input_mux = &alc262_capture_source,9257 .unsol_event = alc262_hippo1_unsol_event,9258 .init_hook = alc262_hippo1_automute,9259 },9260 [ALC262_FUJITSU] = {9261 .mixers = { alc262_fujitsu_mixer },9262 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,9263 alc262_fujitsu_unsol_verbs },9264 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9265 .dac_nids = alc262_dac_nids,9266 .hp_nid = 0x03,9267 .dig_out_nid = ALC262_DIGOUT_NID,9268 .num_channel_mode = ARRAY_SIZE(alc262_modes),9269 .channel_mode = alc262_modes,9270 .input_mux = &alc262_fujitsu_capture_source,9271 .unsol_event = alc262_fujitsu_unsol_event,9272 },9273 [ALC262_HP_BPC] = {9274 .mixers = { alc262_HP_BPC_mixer },9275 .init_verbs = { alc262_HP_BPC_init_verbs },9276 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9277 .dac_nids = alc262_dac_nids,9278 .hp_nid = 0x03,9279 .num_channel_mode = ARRAY_SIZE(alc262_modes),9280 .channel_mode = alc262_modes,9281 .input_mux = &alc262_HP_capture_source,9282 .unsol_event = alc262_hp_bpc_unsol_event,9283 .init_hook = alc262_hp_bpc_automute,9284 },9285 [ALC262_HP_BPC_D7000_WF] = {9286 .mixers = { alc262_HP_BPC_WildWest_mixer },9287 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },9288 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9289 .dac_nids = alc262_dac_nids,9290 .hp_nid = 0x03,9291 .num_channel_mode = ARRAY_SIZE(alc262_modes),9292 .channel_mode = alc262_modes,9293 .input_mux = &alc262_HP_D7000_capture_source,9294 .unsol_event = alc262_hp_wildwest_unsol_event,9295 .init_hook = alc262_hp_wildwest_automute,9296 },9297 [ALC262_HP_BPC_D7000_WL] = {9298 .mixers = { alc262_HP_BPC_WildWest_mixer,9299 alc262_HP_BPC_WildWest_option_mixer },9300 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },9301 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9302 .dac_nids = alc262_dac_nids,9303 .hp_nid = 0x03,9304 .num_channel_mode = ARRAY_SIZE(alc262_modes),9305 .channel_mode = alc262_modes,9306 .input_mux = &alc262_HP_D7000_capture_source,9307 .unsol_event = alc262_hp_wildwest_unsol_event,9308 .init_hook = alc262_hp_wildwest_automute,9309 },9310 [ALC262_HP_TC_T5735] = {9311 .mixers = { alc262_hp_t5735_mixer },9312 .init_verbs = { alc262_init_verbs, alc262_hp_t5735_verbs },9313 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9314 .dac_nids = alc262_dac_nids,9315 .hp_nid = 0x03,9316 .num_channel_mode = ARRAY_SIZE(alc262_modes),9317 .channel_mode = alc262_modes,9318 .input_mux = &alc262_capture_source,9319 .unsol_event = alc262_hp_t5735_unsol_event,9320 .init_hook = alc262_hp_t5735_init_hook,9321 },9322 [ALC262_HP_RP5700] = {9323 .mixers = { alc262_hp_rp5700_mixer },9324 .init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs },9325 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9326 .dac_nids = alc262_dac_nids,9327 .num_channel_mode = ARRAY_SIZE(alc262_modes),9328 .channel_mode = alc262_modes,9329 .input_mux = &alc262_hp_rp5700_capture_source,9330 },9331 [ALC262_BENQ_ED8] = {9332 .mixers = { alc262_base_mixer },9333 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },9334 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9335 .dac_nids = alc262_dac_nids,9336 .hp_nid = 0x03,9337 .num_channel_mode = ARRAY_SIZE(alc262_modes),9338 .channel_mode = alc262_modes,9339 .input_mux = &alc262_capture_source,9340 },9341 [ALC262_SONY_ASSAMD] = {9342 .mixers = { alc262_sony_mixer },9343 .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},9344 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9345 .dac_nids = alc262_dac_nids,9346 .hp_nid = 0x02,9347 .num_channel_mode = ARRAY_SIZE(alc262_modes),9348 .channel_mode = alc262_modes,9349 .input_mux = &alc262_capture_source,9350 .unsol_event = alc262_hippo_unsol_event,9351 .init_hook = alc262_hippo_automute,9352 },9353 [ALC262_BENQ_T31] = {9354 .mixers = { alc262_benq_t31_mixer },9355 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs, alc262_hippo_unsol_verbs },9356 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9357 .dac_nids = alc262_dac_nids,9358 .hp_nid = 0x03,9359 .num_channel_mode = ARRAY_SIZE(alc262_modes),9360 .channel_mode = alc262_modes,9361 .input_mux = &alc262_capture_source,9362 .unsol_event = alc262_hippo_unsol_event,9363 .init_hook = alc262_hippo_automute,9364 },9365 [ALC262_ULTRA] = {9366 .mixers = { alc262_ultra_mixer },9367 .init_verbs = { alc262_init_verbs, alc262_ultra_verbs },9368 .num_dacs = ARRAY_SIZE(alc262_dac_nids),9369 .dac_nids = alc262_dac_nids,9370 .hp_nid = 0x03,9371 .dig_out_nid = ALC262_DIGOUT_NID,9372 .num_channel_mode = ARRAY_SIZE(alc262_modes),9373 .channel_mode = alc262_modes,9374 .input_mux = &alc262_ultra_capture_source,9375 .unsol_event = alc262_ultra_unsol_event,9376 .init_hook = alc262_ultra_automute,9377 },9378};93799380static int patch_alc262(struct hda_codec *codec)9381{9382 struct alc_spec *spec;9383 int board_config;9384 int err;93859386 spec = kzalloc(sizeof(*spec), GFP_KERNEL);9387 if (spec == NULL)9388 return -ENOMEM;93899390 codec->spec = spec;9391#if 09392 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is9393 * under-run9394 */9395 {9396 int tmp;9397 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);9398 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);9399 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);9400 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);9401 }9402#endif94039404 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,9405 alc262_models,9406 alc262_cfg_tbl);94079408 if (board_config < 0) {9409 printk(KERN_INFO "hda_codec: Unknown model for ALC262, "9410 "trying auto-probe from BIOS...\n");9411 board_config = ALC262_AUTO;9412 }94139414 if (board_config == ALC262_AUTO) {9415 /* automatic parse from the BIOS config */9416 err = alc262_parse_auto_config(codec);9417 if (err < 0) {9418 alc_free(codec);9419 return err;9420 } else if (!err) {9421 printk(KERN_INFO9422 "hda_codec: Cannot set up configuration "9423 "from BIOS. Using base mode...\n");9424 board_config = ALC262_BASIC;9425 }9426 }94279428 if (board_config != ALC262_AUTO)9429 setup_preset(spec, &alc262_presets[board_config]);94309431 spec->stream_name_analog = "ALC262 Analog";9432 spec->stream_analog_playback = &alc262_pcm_analog_playback;9433 spec->stream_analog_capture = &alc262_pcm_analog_capture;94349435 spec->stream_name_digital = "ALC262 Digital";9436 spec->stream_digital_playback = &alc262_pcm_digital_playback;9437 spec->stream_digital_capture = &alc262_pcm_digital_capture;94389439 if (!spec->adc_nids && spec->input_mux) {9440 /* check whether NID 0x07 is valid */9441 unsigned int wcap = get_wcaps(codec, 0x07);94429443 /* get type */9444 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;9445 if (wcap != AC_WID_AUD_IN) {9446 spec->adc_nids = alc262_adc_nids_alt;9447 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);9448 spec->capsrc_nids = alc262_capsrc_nids_alt;9449 spec->mixers[spec->num_mixers] =9450 alc262_capture_alt_mixer;9451 spec->num_mixers++;9452 } else {9453 spec->adc_nids = alc262_adc_nids;9454 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);9455 spec->capsrc_nids = alc262_capsrc_nids;9456 spec->mixers[spec->num_mixers] = alc262_capture_mixer;9457 spec->num_mixers++;9458 }9459 }94609461 spec->vmaster_nid = 0x0c;94629463 codec->patch_ops = alc_patch_ops;9464 if (board_config == ALC262_AUTO)9465 spec->init_hook = alc262_auto_init;9466#ifdef CONFIG_SND_HDA_POWER_SAVE9467 if (!spec->loopback.amplist)9468 spec->loopback.amplist = alc262_loopbacks;9469#endif94709471 return 0;9472}94739474/*9475 * ALC268 channel source setting (2 channel)9476 */9477#define ALC268_DIGOUT_NID ALC880_DIGOUT_NID9478#define alc268_modes alc260_modes94799480static hda_nid_t alc268_dac_nids[2] = {9481 /* front, hp */9482 0x02, 0x039483};94849485static hda_nid_t alc268_adc_nids[2] = {9486 /* ADC0-1 */9487 0x08, 0x079488};94899490static hda_nid_t alc268_adc_nids_alt[1] = {9491 /* ADC0 */9492 0x089493};94949495static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };94969497static struct snd_kcontrol_new alc268_base_mixer[] = {9498 /* output mixer control */9499 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),9500 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),9501 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),9502 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),9503 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),9504 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),9505 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),9506 { }9507};95089509/* bind Beep switches of both NID 0x0f and 0x10 */9510static struct hda_bind_ctls alc268_bind_beep_sw = {9511 .ops = &snd_hda_bind_sw,9512 .values = {9513 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),9514 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),9515 09516 },9517};95189519static struct snd_kcontrol_new alc268_beep_mixer[] = {9520 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),9521 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),9522 { }9523};95249525static struct hda_verb alc268_eapd_verbs[] = {9526 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},9527 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},9528 { }9529};95309531/* Toshiba specific */9532#define alc268_toshiba_automute alc262_hippo_automute95339534static struct hda_verb alc268_toshiba_verbs[] = {9535 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},9536 { } /* end */9537};95389539/* Acer specific */9540/* bind volumes of both NID 0x02 and 0x03 */9541static struct hda_bind_ctls alc268_acer_bind_master_vol = {9542 .ops = &snd_hda_bind_vol,9543 .values = {9544 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),9545 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),9546 09547 },9548};95499550/* mute/unmute internal speaker according to the hp jack and mute state */9551static void alc268_acer_automute(struct hda_codec *codec, int force)9552{9553 struct alc_spec *spec = codec->spec;9554 unsigned int mute;95559556 if (force || !spec->sense_updated) {9557 unsigned int present;9558 present = snd_hda_codec_read(codec, 0x14, 0,9559 AC_VERB_GET_PIN_SENSE, 0);9560 spec->jack_present = (present & 0x80000000) != 0;9561 spec->sense_updated = 1;9562 }9563 if (spec->jack_present)9564 mute = HDA_AMP_MUTE; /* mute internal speaker */9565 else /* unmute internal speaker if necessary */9566 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);9567 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,9568 HDA_AMP_MUTE, mute);9569}957095719572/* bind hp and internal speaker mute (with plug check) */9573static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,9574 struct snd_ctl_elem_value *ucontrol)9575{9576 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);9577 long *valp = ucontrol->value.integer.value;9578 int change;95799580 change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,9581 HDA_AMP_MUTE,9582 valp[0] ? 0 : HDA_AMP_MUTE);9583 change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,9584 HDA_AMP_MUTE,9585 valp[1] ? 0 : HDA_AMP_MUTE);9586 if (change)9587 alc268_acer_automute(codec, 0);9588 return change;9589}95909591static struct snd_kcontrol_new alc268_acer_mixer[] = {9592 /* output mixer control */9593 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),9594 {9595 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,9596 .name = "Master Playback Switch",9597 .info = snd_hda_mixer_amp_switch_info,9598 .get = snd_hda_mixer_amp_switch_get,9599 .put = alc268_acer_master_sw_put,9600 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),9601 },9602 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),9603 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),9604 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),9605 { }9606};96079608static struct hda_verb alc268_acer_verbs[] = {9609 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},9610 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},96119612 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},9613 { }9614};96159616/* unsolicited event for HP jack sensing */9617static void alc268_toshiba_unsol_event(struct hda_codec *codec,9618 unsigned int res)9619{9620 if ((res >> 26) != ALC880_HP_EVENT)9621 return;9622 alc268_toshiba_automute(codec);9623}96249625static void alc268_acer_unsol_event(struct hda_codec *codec,9626 unsigned int res)9627{9628 if ((res >> 26) != ALC880_HP_EVENT)9629 return;9630 alc268_acer_automute(codec, 1);9631}96329633static void alc268_acer_init_hook(struct hda_codec *codec)9634{9635 alc268_acer_automute(codec, 1);9636}96379638static struct snd_kcontrol_new alc268_dell_mixer[] = {9639 /* output mixer control */9640 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),9641 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),9642 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),9643 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),9644 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),9645 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),9646 { }9647};96489649static struct hda_verb alc268_dell_verbs[] = {9650 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},9651 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},9652 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},9653 { }9654};96559656/* mute/unmute internal speaker according to the hp jack and mute state */9657static void alc268_dell_automute(struct hda_codec *codec)9658{9659 unsigned int present;9660 unsigned int mute;96619662 present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0);9663 if (present & 0x80000000)9664 mute = HDA_AMP_MUTE;9665 else9666 mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);9667 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,9668 HDA_AMP_MUTE, mute);9669}96709671static void alc268_dell_unsol_event(struct hda_codec *codec,9672 unsigned int res)9673{9674 if ((res >> 26) != ALC880_HP_EVENT)9675 return;9676 alc268_dell_automute(codec);9677}96789679#define alc268_dell_init_hook alc268_dell_automute96809681/*9682 * generic initialization of ADC, input mixers and output mixers9683 */9684static struct hda_verb alc268_base_init_verbs[] = {9685 /* Unmute DAC0-1 and set vol = 0 */9686 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},9687 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9688 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},9689 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},9690 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9691 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},96929693 /*9694 * Set up output mixers (0x0c - 0x0e)9695 */9696 /* set vol=0 to output mixers */9697 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9698 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},9699 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},9700 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},97019702 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9703 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},97049705 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},9706 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},9707 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},9708 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},9709 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},9710 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},9711 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},9712 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},97139714 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},9715 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},9716 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},9717 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},9718 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},9719 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},9720 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},97219722 /* set PCBEEP vol = 0, mute connections */9723 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9724 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},9725 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},97269727 /* Unmute Selector 23h,24h and set the default input to mic-in */97289729 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},9730 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},9731 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},9732 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},97339734 { }9735};97369737/*9738 * generic initialization of ADC, input mixers and output mixers9739 */9740static struct hda_verb alc268_volume_init_verbs[] = {9741 /* set output DAC */9742 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9743 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},9744 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9745 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},97469747 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},9748 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},9749 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},9750 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},9751 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},97529753 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},9754 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9755 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},9756 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9757 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},97589759 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},9760 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},9761 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},9762 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},97639764 /* set PCBEEP vol = 0, mute connections */9765 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},9766 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},9767 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},97689769 { }9770};97719772#define alc268_mux_enum_info alc_mux_enum_info9773#define alc268_mux_enum_get alc_mux_enum_get9774#define alc268_mux_enum_put alc_mux_enum_put97759776static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {9777 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),9778 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),9779 {9780 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,9781 /* The multiple "Capture Source" controls confuse alsamixer9782 * So call somewhat different..9783 */9784 /* .name = "Capture Source", */9785 .name = "Input Source",9786 .count = 1,9787 .info = alc268_mux_enum_info,9788 .get = alc268_mux_enum_get,9789 .put = alc268_mux_enum_put,9790 },9791 { } /* end */9792};97939794static struct snd_kcontrol_new alc268_capture_mixer[] = {9795 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),9796 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),9797 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),9798 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),9799 {9800 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,9801 /* The multiple "Capture Source" controls confuse alsamixer9802 * So call somewhat different..9803 */9804 /* .name = "Capture Source", */9805 .name = "Input Source",9806 .count = 2,9807 .info = alc268_mux_enum_info,9808 .get = alc268_mux_enum_get,9809 .put = alc268_mux_enum_put,9810 },9811 { } /* end */9812};98139814static struct hda_input_mux alc268_capture_source = {9815 .num_items = 4,9816 .items = {9817 { "Mic", 0x0 },9818 { "Front Mic", 0x1 },9819 { "Line", 0x2 },9820 { "CD", 0x3 },9821 },9822};98239824#ifdef CONFIG_SND_DEBUG9825static struct snd_kcontrol_new alc268_test_mixer[] = {9826 /* Volume widgets */9827 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),9828 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),9829 HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),9830 HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),9831 HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),9832 HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),9833 HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),9834 HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),9835 HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),9836 HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),9837 HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),9838 HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),9839 HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),9840 /* The below appears problematic on some hardwares */9841 /*HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),*/9842 HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),9843 HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),9844 HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),9845 HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),98469847 /* Modes for retasking pin widgets */9848 ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),9849 ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),9850 ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),9851 ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),98529853 /* Controls for GPIO pins, assuming they are configured as outputs */9854 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),9855 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),9856 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),9857 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),98589859 /* Switches to allow the digital SPDIF output pin to be enabled.9860 * The ALC268 does not have an SPDIF input.9861 */9862 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),98639864 /* A switch allowing EAPD to be enabled. Some laptops seem to use9865 * this output to turn on an external amplifier.9866 */9867 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),9868 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),98699870 { } /* end */9871};9872#endif98739874/* create input playback/capture controls for the given pin */9875static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,9876 const char *ctlname, int idx)9877{9878 char name[32];9879 int err;98809881 sprintf(name, "%s Playback Volume", ctlname);9882 if (nid == 0x14) {9883 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,9884 HDA_COMPOSE_AMP_VAL(0x02, 3, idx,9885 HDA_OUTPUT));9886 if (err < 0)9887 return err;9888 } else if (nid == 0x15) {9889 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,9890 HDA_COMPOSE_AMP_VAL(0x03, 3, idx,9891 HDA_OUTPUT));9892 if (err < 0)9893 return err;9894 } else9895 return -1;9896 sprintf(name, "%s Playback Switch", ctlname);9897 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,9898 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));9899 if (err < 0)9900 return err;9901 return 0;9902}99039904/* add playback controls from the parsed DAC table */9905static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,9906 const struct auto_pin_cfg *cfg)9907{9908 hda_nid_t nid;9909 int err;99109911 spec->multiout.num_dacs = 2; /* only use one dac */9912 spec->multiout.dac_nids = spec->private_dac_nids;9913 spec->multiout.dac_nids[0] = 2;9914 spec->multiout.dac_nids[1] = 3;99159916 nid = cfg->line_out_pins[0];9917 if (nid)9918 alc268_new_analog_output(spec, nid, "Front", 0);99199920 nid = cfg->speaker_pins[0];9921 if (nid == 0x1d) {9922 err = add_control(spec, ALC_CTL_WIDGET_VOL,9923 "Speaker Playback Volume",9924 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));9925 if (err < 0)9926 return err;9927 }9928 nid = cfg->hp_pins[0];9929 if (nid)9930 alc268_new_analog_output(spec, nid, "Headphone", 0);99319932 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];9933 if (nid == 0x16) {9934 err = add_control(spec, ALC_CTL_WIDGET_MUTE,9935 "Mono Playback Switch",9936 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_INPUT));9937 if (err < 0)9938 return err;9939 }9940 return 0;9941}99429943/* create playback/capture controls for input pins */9944static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,9945 const struct auto_pin_cfg *cfg)9946{9947 struct hda_input_mux *imux = &spec->private_imux;9948 int i, idx1;99499950 for (i = 0; i < AUTO_PIN_LAST; i++) {9951 switch(cfg->input_pins[i]) {9952 case 0x18:9953 idx1 = 0; /* Mic 1 */9954 break;9955 case 0x19:9956 idx1 = 1; /* Mic 2 */9957 break;9958 case 0x1a:9959 idx1 = 2; /* Line In */9960 break;9961 case 0x1c:9962 idx1 = 3; /* CD */9963 break;9964 default:9965 continue;9966 }9967 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];9968 imux->items[imux->num_items].index = idx1;9969 imux->num_items++;9970 }9971 return 0;9972}99739974static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)9975{9976 struct alc_spec *spec = codec->spec;9977 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];9978 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];9979 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];9980 unsigned int dac_vol1, dac_vol2;99819982 if (speaker_nid) {9983 snd_hda_codec_write(codec, speaker_nid, 0,9984 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);9985 snd_hda_codec_write(codec, 0x0f, 0,9986 AC_VERB_SET_AMP_GAIN_MUTE,9987 AMP_IN_UNMUTE(1));9988 snd_hda_codec_write(codec, 0x10, 0,9989 AC_VERB_SET_AMP_GAIN_MUTE,9990 AMP_IN_UNMUTE(1));9991 } else {9992 snd_hda_codec_write(codec, 0x0f, 0,9993 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));9994 snd_hda_codec_write(codec, 0x10, 0,9995 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));9996 }99979998 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */9999 if (line_nid == 0x14)10000 dac_vol2 = AMP_OUT_ZERO;10001 else if (line_nid == 0x15)10002 dac_vol1 = AMP_OUT_ZERO;10003 if (hp_nid == 0x14)10004 dac_vol2 = AMP_OUT_ZERO;10005 else if (hp_nid == 0x15)10006 dac_vol1 = AMP_OUT_ZERO;10007 if (line_nid != 0x16 || hp_nid != 0x16 ||10008 spec->autocfg.line_out_pins[1] != 0x16 ||10009 spec->autocfg.line_out_pins[2] != 0x16)10010 dac_vol1 = dac_vol2 = AMP_OUT_ZERO;1001110012 snd_hda_codec_write(codec, 0x02, 0,10013 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);10014 snd_hda_codec_write(codec, 0x03, 0,10015 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);10016}1001710018/* pcm configuration: identiacal with ALC880 */10019#define alc268_pcm_analog_playback alc880_pcm_analog_playback10020#define alc268_pcm_analog_capture alc880_pcm_analog_capture10021#define alc268_pcm_analog_alt_capture alc880_pcm_analog_alt_capture10022#define alc268_pcm_digital_playback alc880_pcm_digital_playback1002310024/*10025 * BIOS auto configuration10026 */10027static int alc268_parse_auto_config(struct hda_codec *codec)10028{10029 struct alc_spec *spec = codec->spec;10030 int err;10031 static hda_nid_t alc268_ignore[] = { 0 };1003210033 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,10034 alc268_ignore);10035 if (err < 0)10036 return err;10037 if (!spec->autocfg.line_outs)10038 return 0; /* can't find valid BIOS pin config */1003910040 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);10041 if (err < 0)10042 return err;10043 err = alc268_auto_create_analog_input_ctls(spec, &spec->autocfg);10044 if (err < 0)10045 return err;1004610047 spec->multiout.max_channels = 2;1004810049 /* digital only support output */10050 if (spec->autocfg.dig_out_pin)10051 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;1005210053 if (spec->kctl_alloc)10054 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;1005510056 if (spec->autocfg.speaker_pins[0] != 0x1d)10057 spec->mixers[spec->num_mixers++] = alc268_beep_mixer;1005810059 spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs;10060 spec->num_mux_defs = 1;10061 spec->input_mux = &spec->private_imux;1006210063 err = alc_auto_add_mic_boost(codec);10064 if (err < 0)10065 return err;1006610067 return 1;10068}1006910070#define alc268_auto_init_multi_out alc882_auto_init_multi_out10071#define alc268_auto_init_hp_out alc882_auto_init_hp_out10072#define alc268_auto_init_analog_input alc882_auto_init_analog_input1007310074/* init callback for auto-configuration model -- overriding the default init */10075static void alc268_auto_init(struct hda_codec *codec)10076{10077 struct alc_spec *spec = codec->spec;10078 alc268_auto_init_multi_out(codec);10079 alc268_auto_init_hp_out(codec);10080 alc268_auto_init_mono_speaker_out(codec);10081 alc268_auto_init_analog_input(codec);10082 if (spec->unsol_event)10083 alc_sku_automute(codec);10084}1008510086/*10087 * configuration and preset10088 */10089static const char *alc268_models[ALC268_MODEL_LAST] = {10090 [ALC268_3ST] = "3stack",10091 [ALC268_TOSHIBA] = "toshiba",10092 [ALC268_ACER] = "acer",10093 [ALC268_DELL] = "dell",10094 [ALC268_ZEPTO] = "zepto",10095#ifdef CONFIG_SND_DEBUG10096 [ALC268_TEST] = "test",10097#endif10098 [ALC268_AUTO] = "auto",10099};1010010101static struct snd_pci_quirk alc268_cfg_tbl[] = {10102 SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),10103 SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),10104 SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),10105 SND_PCI_QUIRK(0x1025, 0x0136, "Acer Aspire 5315", ALC268_ACER),10106 SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),10107 SND_PCI_QUIRK(0x103c, 0x30cc, "TOSHIBA", ALC268_TOSHIBA),10108 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),10109 SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),10110 SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA),10111 SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),10112 SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),10113 {}10114};1011510116static struct alc_config_preset alc268_presets[] = {10117 [ALC268_3ST] = {10118 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,10119 alc268_beep_mixer },10120 .init_verbs = { alc268_base_init_verbs },10121 .num_dacs = ARRAY_SIZE(alc268_dac_nids),10122 .dac_nids = alc268_dac_nids,10123 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),10124 .adc_nids = alc268_adc_nids_alt,10125 .capsrc_nids = alc268_capsrc_nids,10126 .hp_nid = 0x03,10127 .dig_out_nid = ALC268_DIGOUT_NID,10128 .num_channel_mode = ARRAY_SIZE(alc268_modes),10129 .channel_mode = alc268_modes,10130 .input_mux = &alc268_capture_source,10131 },10132 [ALC268_TOSHIBA] = {10133 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,10134 alc268_beep_mixer },10135 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,10136 alc268_toshiba_verbs },10137 .num_dacs = ARRAY_SIZE(alc268_dac_nids),10138 .dac_nids = alc268_dac_nids,10139 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),10140 .adc_nids = alc268_adc_nids_alt,10141 .capsrc_nids = alc268_capsrc_nids,10142 .hp_nid = 0x03,10143 .num_channel_mode = ARRAY_SIZE(alc268_modes),10144 .channel_mode = alc268_modes,10145 .input_mux = &alc268_capture_source,10146 .unsol_event = alc268_toshiba_unsol_event,10147 .init_hook = alc268_toshiba_automute,10148 },10149 [ALC268_ACER] = {10150 .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,10151 alc268_beep_mixer },10152 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,10153 alc268_acer_verbs },10154 .num_dacs = ARRAY_SIZE(alc268_dac_nids),10155 .dac_nids = alc268_dac_nids,10156 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),10157 .adc_nids = alc268_adc_nids_alt,10158 .capsrc_nids = alc268_capsrc_nids,10159 .hp_nid = 0x02,10160 .num_channel_mode = ARRAY_SIZE(alc268_modes),10161 .channel_mode = alc268_modes,10162 .input_mux = &alc268_capture_source,10163 .unsol_event = alc268_acer_unsol_event,10164 .init_hook = alc268_acer_init_hook,10165 },10166 [ALC268_DELL] = {10167 .mixers = { alc268_dell_mixer, alc268_beep_mixer },10168 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,10169 alc268_dell_verbs },10170 .num_dacs = ARRAY_SIZE(alc268_dac_nids),10171 .dac_nids = alc268_dac_nids,10172 .hp_nid = 0x02,10173 .num_channel_mode = ARRAY_SIZE(alc268_modes),10174 .channel_mode = alc268_modes,10175 .unsol_event = alc268_dell_unsol_event,10176 .init_hook = alc268_dell_init_hook,10177 .input_mux = &alc268_capture_source,10178 },10179 [ALC268_ZEPTO] = {10180 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,10181 alc268_beep_mixer },10182 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,10183 alc268_toshiba_verbs },10184 .num_dacs = ARRAY_SIZE(alc268_dac_nids),10185 .dac_nids = alc268_dac_nids,10186 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),10187 .adc_nids = alc268_adc_nids_alt,10188 .capsrc_nids = alc268_capsrc_nids,10189 .hp_nid = 0x03,10190 .dig_out_nid = ALC268_DIGOUT_NID,10191 .num_channel_mode = ARRAY_SIZE(alc268_modes),10192 .channel_mode = alc268_modes,10193 .input_mux = &alc268_capture_source,10194 .unsol_event = alc268_toshiba_unsol_event,10195 .init_hook = alc268_toshiba_automute10196 },10197#ifdef CONFIG_SND_DEBUG10198 [ALC268_TEST] = {10199 .mixers = { alc268_test_mixer, alc268_capture_mixer },10200 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,10201 alc268_volume_init_verbs },10202 .num_dacs = ARRAY_SIZE(alc268_dac_nids),10203 .dac_nids = alc268_dac_nids,10204 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),10205 .adc_nids = alc268_adc_nids_alt,10206 .capsrc_nids = alc268_capsrc_nids,10207 .hp_nid = 0x03,10208 .dig_out_nid = ALC268_DIGOUT_NID,10209 .num_channel_mode = ARRAY_SIZE(alc268_modes),10210 .channel_mode = alc268_modes,10211 .input_mux = &alc268_capture_source,10212 },10213#endif10214};1021510216static int patch_alc268(struct hda_codec *codec)10217{10218 struct alc_spec *spec;10219 int board_config;10220 int err;1022110222 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);10223 if (spec == NULL)10224 return -ENOMEM;1022510226 codec->spec = spec;1022710228 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,10229 alc268_models,10230 alc268_cfg_tbl);1023110232 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {10233 printk(KERN_INFO "hda_codec: Unknown model for ALC268, "10234 "trying auto-probe from BIOS...\n");10235 board_config = ALC268_AUTO;10236 }1023710238 if (board_config == ALC268_AUTO) {10239 /* automatic parse from the BIOS config */10240 err = alc268_parse_auto_config(codec);10241 if (err < 0) {10242 alc_free(codec);10243 return err;10244 } else if (!err) {10245 printk(KERN_INFO10246 "hda_codec: Cannot set up configuration "10247 "from BIOS. Using base mode...\n");10248 board_config = ALC268_3ST;10249 }10250 }1025110252 if (board_config != ALC268_AUTO)10253 setup_preset(spec, &alc268_presets[board_config]);1025410255 spec->stream_name_analog = "ALC268 Analog";10256 spec->stream_analog_playback = &alc268_pcm_analog_playback;10257 spec->stream_analog_capture = &alc268_pcm_analog_capture;10258 spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;1025910260 spec->stream_name_digital = "ALC268 Digital";10261 spec->stream_digital_playback = &alc268_pcm_digital_playback;1026210263 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))10264 /* override the amp caps for beep generator */10265 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,10266 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |10267 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |10268 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |10269 (0 << AC_AMPCAP_MUTE_SHIFT));1027010271 if (!spec->adc_nids && spec->input_mux) {10272 /* check whether NID 0x07 is valid */10273 unsigned int wcap = get_wcaps(codec, 0x07);10274 int i;1027510276 /* get type */10277 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;10278 if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {10279 spec->adc_nids = alc268_adc_nids_alt;10280 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);10281 spec->mixers[spec->num_mixers] =10282 alc268_capture_alt_mixer;10283 spec->num_mixers++;10284 } else {10285 spec->adc_nids = alc268_adc_nids;10286 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);10287 spec->mixers[spec->num_mixers] =10288 alc268_capture_mixer;10289 spec->num_mixers++;10290 }10291 spec->capsrc_nids = alc268_capsrc_nids;10292 /* set default input source */10293 for (i = 0; i < spec->num_adc_nids; i++)10294 snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],10295 0, AC_VERB_SET_CONNECT_SEL,10296 spec->input_mux->items[0].index);10297 }1029810299 spec->vmaster_nid = 0x02;1030010301 codec->patch_ops = alc_patch_ops;10302 if (board_config == ALC268_AUTO)10303 spec->init_hook = alc268_auto_init;1030410305 return 0;10306}1030710308/*10309 * ALC269 channel source setting (2 channel)10310 */10311#define ALC269_DIGOUT_NID ALC880_DIGOUT_NID1031210313#define alc269_dac_nids alc260_dac_nids1031410315static hda_nid_t alc269_adc_nids[1] = {10316 /* ADC1 */10317 0x07,10318};1031910320#define alc269_modes alc260_modes10321#define alc269_capture_source alc880_lg_lw_capture_source1032210323static struct snd_kcontrol_new alc269_base_mixer[] = {10324 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),10325 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),10326 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),10327 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),10328 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),10329 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),10330 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),10331 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),10332 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),10333 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),10334 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),10335 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),10336 { } /* end */10337};1033810339/* capture mixer elements */10340static struct snd_kcontrol_new alc269_capture_mixer[] = {10341 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),10342 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),10343 {10344 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,10345 /* The multiple "Capture Source" controls confuse alsamixer10346 * So call somewhat different..10347 */10348 /* .name = "Capture Source", */10349 .name = "Input Source",10350 .count = 1,10351 .info = alc_mux_enum_info,10352 .get = alc_mux_enum_get,10353 .put = alc_mux_enum_put,10354 },10355 { } /* end */10356};1035710358/*10359 * generic initialization of ADC, input mixers and output mixers10360 */10361static struct hda_verb alc269_init_verbs[] = {10362 /*10363 * Unmute ADC0 and set the default input to mic-in10364 */10365 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},1036610367 /* Mute input amps (PCBeep, Line In, Mic 1 & Mic 2) of the10368 * analog-loopback mixer widget10369 * Note: PASD motherboards uses the Line In 2 as the input for10370 * front panel mic (mic 2)10371 */10372 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */10373 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},10374 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},10375 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},10376 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},10377 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},1037810379 /*10380 * Set up output mixers (0x0c - 0x0e)10381 */10382 /* set vol=0 to output mixers */10383 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},10384 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},1038510386 /* set up input amps for analog loopback */10387 /* Amp Indices: DAC = 0, mixer = 1 */10388 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},10389 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},10390 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},10391 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},10392 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},10393 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},1039410395 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},10396 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},10397 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},10398 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},10399 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},10400 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},10401 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1040210403 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},10404 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},10405 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},10406 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},10407 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},10408 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},10409 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},1041010411 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},10412 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},1041310414 /* FIXME: use matrix-type input source selection */10415 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */10416 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */10417 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},10418 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},10419 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},10420 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},1042110422 /* set EAPD */10423 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},10424 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},10425 { }10426};1042710428/* add playback controls from the parsed DAC table */10429static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec,10430 const struct auto_pin_cfg *cfg)10431{10432 hda_nid_t nid;10433 int err;1043410435 spec->multiout.num_dacs = 1; /* only use one dac */10436 spec->multiout.dac_nids = spec->private_dac_nids;10437 spec->multiout.dac_nids[0] = 2;1043810439 nid = cfg->line_out_pins[0];10440 if (nid) {10441 err = add_control(spec, ALC_CTL_WIDGET_VOL,10442 "Front Playback Volume",10443 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT));10444 if (err < 0)10445 return err;10446 err = add_control(spec, ALC_CTL_WIDGET_MUTE,10447 "Front Playback Switch",10448 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));10449 if (err < 0)10450 return err;10451 }1045210453 nid = cfg->speaker_pins[0];10454 if (nid) {10455 if (!cfg->line_out_pins[0]) {10456 err = add_control(spec, ALC_CTL_WIDGET_VOL,10457 "Speaker Playback Volume",10458 HDA_COMPOSE_AMP_VAL(0x02, 3, 0,10459 HDA_OUTPUT));10460 if (err < 0)10461 return err;10462 }10463 if (nid == 0x16) {10464 err = add_control(spec, ALC_CTL_WIDGET_MUTE,10465 "Speaker Playback Switch",10466 HDA_COMPOSE_AMP_VAL(nid, 2, 0,10467 HDA_OUTPUT));10468 if (err < 0)10469 return err;10470 } else {10471 err = add_control(spec, ALC_CTL_WIDGET_MUTE,10472 "Speaker Playback Switch",10473 HDA_COMPOSE_AMP_VAL(nid, 3, 0,10474 HDA_OUTPUT));10475 if (err < 0)10476 return err;10477 }10478 }10479 nid = cfg->hp_pins[0];10480 if (nid) {10481 /* spec->multiout.hp_nid = 2; */10482 if (!cfg->line_out_pins[0] && !cfg->speaker_pins[0]) {10483 err = add_control(spec, ALC_CTL_WIDGET_VOL,10484 "Headphone Playback Volume",10485 HDA_COMPOSE_AMP_VAL(0x02, 3, 0,10486 HDA_OUTPUT));10487 if (err < 0)10488 return err;10489 }10490 if (nid == 0x16) {10491 err = add_control(spec, ALC_CTL_WIDGET_MUTE,10492 "Headphone Playback Switch",10493 HDA_COMPOSE_AMP_VAL(nid, 2, 0,10494 HDA_OUTPUT));10495 if (err < 0)10496 return err;10497 } else {10498 err = add_control(spec, ALC_CTL_WIDGET_MUTE,10499 "Headphone Playback Switch",10500 HDA_COMPOSE_AMP_VAL(nid, 3, 0,10501 HDA_OUTPUT));10502 if (err < 0)10503 return err;10504 }10505 }10506 return 0;10507}1050810509#define alc269_auto_create_analog_input_ctls \10510 alc880_auto_create_analog_input_ctls1051110512#ifdef CONFIG_SND_HDA_POWER_SAVE10513#define alc269_loopbacks alc880_loopbacks10514#endif1051510516/* pcm configuration: identiacal with ALC880 */10517#define alc269_pcm_analog_playback alc880_pcm_analog_playback10518#define alc269_pcm_analog_capture alc880_pcm_analog_capture10519#define alc269_pcm_digital_playback alc880_pcm_digital_playback10520#define alc269_pcm_digital_capture alc880_pcm_digital_capture1052110522/*10523 * BIOS auto configuration10524 */10525static int alc269_parse_auto_config(struct hda_codec *codec)10526{10527 struct alc_spec *spec = codec->spec;10528 int err;10529 static hda_nid_t alc269_ignore[] = { 0x1d, 0 };1053010531 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,10532 alc269_ignore);10533 if (err < 0)10534 return err;1053510536 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);10537 if (err < 0)10538 return err;10539 err = alc269_auto_create_analog_input_ctls(spec, &spec->autocfg);10540 if (err < 0)10541 return err;1054210543 spec->multiout.max_channels = spec->multiout.num_dacs * 2;1054410545 if (spec->autocfg.dig_out_pin)10546 spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;1054710548 if (spec->kctl_alloc)10549 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;1055010551 spec->init_verbs[spec->num_init_verbs++] = alc269_init_verbs;10552 spec->num_mux_defs = 1;10553 spec->input_mux = &spec->private_imux;1055410555 err = alc_auto_add_mic_boost(codec);10556 if (err < 0)10557 return err;1055810559 return 1;10560}1056110562#define alc269_auto_init_multi_out alc882_auto_init_multi_out10563#define alc269_auto_init_hp_out alc882_auto_init_hp_out10564#define alc269_auto_init_analog_input alc882_auto_init_analog_input105651056610567/* init callback for auto-configuration model -- overriding the default init */10568static void alc269_auto_init(struct hda_codec *codec)10569{10570 struct alc_spec *spec = codec->spec;10571 alc269_auto_init_multi_out(codec);10572 alc269_auto_init_hp_out(codec);10573 alc269_auto_init_analog_input(codec);10574 if (spec->unsol_event)10575 alc_sku_automute(codec);10576}1057710578/*10579 * configuration and preset10580 */10581static const char *alc269_models[ALC269_MODEL_LAST] = {10582 [ALC269_BASIC] = "basic",10583};1058410585static struct snd_pci_quirk alc269_cfg_tbl[] = {10586 {}10587};1058810589static struct alc_config_preset alc269_presets[] = {10590 [ALC269_BASIC] = {10591 .mixers = { alc269_base_mixer },10592 .init_verbs = { alc269_init_verbs },10593 .num_dacs = ARRAY_SIZE(alc269_dac_nids),10594 .dac_nids = alc269_dac_nids,10595 .hp_nid = 0x03,10596 .num_channel_mode = ARRAY_SIZE(alc269_modes),10597 .channel_mode = alc269_modes,10598 .input_mux = &alc269_capture_source,10599 },10600};1060110602static int patch_alc269(struct hda_codec *codec)10603{10604 struct alc_spec *spec;10605 int board_config;10606 int err;1060710608 spec = kzalloc(sizeof(*spec), GFP_KERNEL);10609 if (spec == NULL)10610 return -ENOMEM;1061110612 codec->spec = spec;1061310614 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,10615 alc269_models,10616 alc269_cfg_tbl);1061710618 if (board_config < 0) {10619 printk(KERN_INFO "hda_codec: Unknown model for ALC269, "10620 "trying auto-probe from BIOS...\n");10621 board_config = ALC269_AUTO;10622 }1062310624 if (board_config == ALC269_AUTO) {10625 /* automatic parse from the BIOS config */10626 err = alc269_parse_auto_config(codec);10627 if (err < 0) {10628 alc_free(codec);10629 return err;10630 } else if (!err) {10631 printk(KERN_INFO10632 "hda_codec: Cannot set up configuration "10633 "from BIOS. Using base mode...\n");10634 board_config = ALC269_BASIC;10635 }10636 }1063710638 if (board_config != ALC269_AUTO)10639 setup_preset(spec, &alc269_presets[board_config]);1064010641 spec->stream_name_analog = "ALC269 Analog";10642 spec->stream_analog_playback = &alc269_pcm_analog_playback;10643 spec->stream_analog_capture = &alc269_pcm_analog_capture;1064410645 spec->stream_name_digital = "ALC269 Digital";10646 spec->stream_digital_playback = &alc269_pcm_digital_playback;10647 spec->stream_digital_capture = &alc269_pcm_digital_capture;1064810649 spec->adc_nids = alc269_adc_nids;10650 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);10651 spec->mixers[spec->num_mixers] = alc269_capture_mixer;10652 spec->num_mixers++;1065310654 codec->patch_ops = alc_patch_ops;10655 if (board_config == ALC269_AUTO)10656 spec->init_hook = alc269_auto_init;10657#ifdef CONFIG_SND_HDA_POWER_SAVE10658 if (!spec->loopback.amplist)10659 spec->loopback.amplist = alc269_loopbacks;10660#endif1066110662 return 0;10663}1066410665/*10666 * ALC861 channel source setting (2/6 channel selection for 3-stack)10667 */1066810669/*10670 * set the path ways for 2 channel output10671 * need to set the codec line out and mic 1 pin widgets to inputs10672 */10673static struct hda_verb alc861_threestack_ch2_init[] = {10674 /* set pin widget 1Ah (line in) for input */10675 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },10676 /* set pin widget 18h (mic1/2) for input, for mic also enable10677 * the vref10678 */10679 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },1068010681 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },10682#if 010683 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/10684 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/10685#endif10686 { } /* end */10687};10688/*10689 * 6ch mode10690 * need to set the codec line out and mic 1 pin widgets to outputs10691 */10692static struct hda_verb alc861_threestack_ch6_init[] = {10693 /* set pin widget 1Ah (line in) for output (Back Surround)*/10694 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },10695 /* set pin widget 18h (mic1) for output (CLFE)*/10696 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },1069710698 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },10699 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },1070010701 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },10702#if 010703 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/10704 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/10705#endif10706 { } /* end */10707};1070810709static struct hda_channel_mode alc861_threestack_modes[2] = {10710 { 2, alc861_threestack_ch2_init },10711 { 6, alc861_threestack_ch6_init },10712};10713/* Set mic1 as input and unmute the mixer */10714static struct hda_verb alc861_uniwill_m31_ch2_init[] = {10715 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },10716 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/10717 { } /* end */10718};10719/* Set mic1 as output and mute mixer */10720static struct hda_verb alc861_uniwill_m31_ch4_init[] = {10721 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },10722 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/10723 { } /* end */10724};1072510726static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {10727 { 2, alc861_uniwill_m31_ch2_init },10728 { 4, alc861_uniwill_m31_ch4_init },10729};1073010731/* Set mic1 and line-in as input and unmute the mixer */10732static struct hda_verb alc861_asus_ch2_init[] = {10733 /* set pin widget 1Ah (line in) for input */10734 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },10735 /* set pin widget 18h (mic1/2) for input, for mic also enable10736 * the vref10737 */10738 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },1073910740 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },10741#if 010742 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/10743 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/10744#endif10745 { } /* end */10746};10747/* Set mic1 nad line-in as output and mute mixer */10748static struct hda_verb alc861_asus_ch6_init[] = {10749 /* set pin widget 1Ah (line in) for output (Back Surround)*/10750 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },10751 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */10752 /* set pin widget 18h (mic1) for output (CLFE)*/10753 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },10754 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */10755 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },10756 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },1075710758 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },10759#if 010760 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/10761 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/10762#endif10763 { } /* end */10764};1076510766static struct hda_channel_mode alc861_asus_modes[2] = {10767 { 2, alc861_asus_ch2_init },10768 { 6, alc861_asus_ch6_init },10769};1077010771/* patch-ALC861 */1077210773static struct snd_kcontrol_new alc861_base_mixer[] = {10774 /* output mixer control */10775 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),10776 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),10777 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),10778 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),10779 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),1078010781 /*Input mixer control */10782 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),10783 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */10784 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),10785 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),10786 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),10787 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),10788 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),10789 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),10790 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),10791 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),1079210793 /* Capture mixer control */10794 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),10795 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),10796 {10797 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,10798 .name = "Capture Source",10799 .count = 1,10800 .info = alc_mux_enum_info,10801 .get = alc_mux_enum_get,10802 .put = alc_mux_enum_put,10803 },10804 { } /* end */10805};1080610807static struct snd_kcontrol_new alc861_3ST_mixer[] = {10808 /* output mixer control */10809 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),10810 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),10811 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),10812 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),10813 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */1081410815 /* Input mixer control */10816 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),10817 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */10818 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),10819 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),10820 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),10821 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),10822 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),10823 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),10824 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),10825 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),1082610827 /* Capture mixer control */10828 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),10829 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),10830 {10831 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,10832 .name = "Capture Source",10833 .count = 1,10834 .info = alc_mux_enum_info,10835 .get = alc_mux_enum_get,10836 .put = alc_mux_enum_put,10837 },10838 {10839 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,10840 .name = "Channel Mode",10841 .info = alc_ch_mode_info,10842 .get = alc_ch_mode_get,10843 .put = alc_ch_mode_put,10844 .private_value = ARRAY_SIZE(alc861_threestack_modes),10845 },10846 { } /* end */10847};1084810849static struct snd_kcontrol_new alc861_toshiba_mixer[] = {10850 /* output mixer control */10851 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),10852 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),10853 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),1085410855 /*Capture mixer control */10856 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),10857 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),10858 {10859 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,10860 .name = "Capture Source",10861 .count = 1,10862 .info = alc_mux_enum_info,10863 .get = alc_mux_enum_get,10864 .put = alc_mux_enum_put,10865 },1086610867 { } /* end */10868};1086910870static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {10871 /* output mixer control */10872 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),10873 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),10874 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),10875 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),10876 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */1087710878 /* Input mixer control */10879 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),10880 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */10881 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),10882 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),10883 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),10884 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),10885 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),10886 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),10887 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),10888 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),1088910890 /* Capture mixer control */10891 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),10892 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),10893 {10894 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,10895 .name = "Capture Source",10896 .count = 1,10897 .info = alc_mux_enum_info,10898 .get = alc_mux_enum_get,10899 .put = alc_mux_enum_put,10900 },10901 {10902 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,10903 .name = "Channel Mode",10904 .info = alc_ch_mode_info,10905 .get = alc_ch_mode_get,10906 .put = alc_ch_mode_put,10907 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),10908 },10909 { } /* end */10910};1091110912static struct snd_kcontrol_new alc861_asus_mixer[] = {10913 /* output mixer control */10914 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),10915 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),10916 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),10917 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),10918 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),1091910920 /* Input mixer control */10921 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),10922 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),10923 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),10924 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),10925 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),10926 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),10927 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),10928 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),10929 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),10930 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),1093110932 /* Capture mixer control */10933 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),10934 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),10935 {10936 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,10937 .name = "Capture Source",10938 .count = 1,10939 .info = alc_mux_enum_info,10940 .get = alc_mux_enum_get,10941 .put = alc_mux_enum_put,10942 },10943 {10944 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,10945 .name = "Channel Mode",10946 .info = alc_ch_mode_info,10947 .get = alc_ch_mode_get,10948 .put = alc_ch_mode_put,10949 .private_value = ARRAY_SIZE(alc861_asus_modes),10950 },10951 { }10952};1095310954/* additional mixer */10955static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {10956 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),10957 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),10958 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT),10959 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT),10960 { }10961};1096210963/*10964 * generic initialization of ADC, input mixers and output mixers10965 */10966static struct hda_verb alc861_base_init_verbs[] = {10967 /*10968 * Unmute ADC0 and set the default input to mic-in10969 */10970 /* port-A for surround (rear panel) */10971 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },10972 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },10973 /* port-B for mic-in (rear panel) with vref */10974 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },10975 /* port-C for line-in (rear panel) */10976 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },10977 /* port-D for Front */10978 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },10979 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },10980 /* port-E for HP out (front panel) */10981 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },10982 /* route front PCM to HP */10983 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },10984 /* port-F for mic-in (front panel) with vref */10985 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },10986 /* port-G for CLFE (rear panel) */10987 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },10988 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },10989 /* port-H for side (rear panel) */10990 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },10991 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },10992 /* CD-in */10993 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },10994 /* route front mic to ADC1*/10995 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},10996 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},1099710998 /* Unmute DAC0~3 & spdif out*/10999 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11000 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11001 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11002 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11003 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1100411005 /* Unmute Mixer 14 (mic) 1c (Line in)*/11006 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11007 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11008 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11009 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},1101011011 /* Unmute Stereo Mixer 15 */11012 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11013 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11014 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},11015 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */1101611017 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11018 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11019 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11020 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11021 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11022 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11023 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11024 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11025 /* hp used DAC 3 (Front) */11026 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},11027 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},1102811029 { }11030};1103111032static struct hda_verb alc861_threestack_init_verbs[] = {11033 /*11034 * Unmute ADC0 and set the default input to mic-in11035 */11036 /* port-A for surround (rear panel) */11037 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },11038 /* port-B for mic-in (rear panel) with vref */11039 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },11040 /* port-C for line-in (rear panel) */11041 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },11042 /* port-D for Front */11043 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },11044 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },11045 /* port-E for HP out (front panel) */11046 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },11047 /* route front PCM to HP */11048 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },11049 /* port-F for mic-in (front panel) with vref */11050 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },11051 /* port-G for CLFE (rear panel) */11052 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },11053 /* port-H for side (rear panel) */11054 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },11055 /* CD-in */11056 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },11057 /* route front mic to ADC1*/11058 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},11059 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11060 /* Unmute DAC0~3 & spdif out*/11061 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11062 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11063 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11064 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11065 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1106611067 /* Unmute Mixer 14 (mic) 1c (Line in)*/11068 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11069 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11070 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11071 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},1107211073 /* Unmute Stereo Mixer 15 */11074 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11075 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11076 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},11077 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */1107811079 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11080 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11081 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11082 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11083 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11084 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11085 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11086 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11087 /* hp used DAC 3 (Front) */11088 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},11089 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},11090 { }11091};1109211093static struct hda_verb alc861_uniwill_m31_init_verbs[] = {11094 /*11095 * Unmute ADC0 and set the default input to mic-in11096 */11097 /* port-A for surround (rear panel) */11098 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },11099 /* port-B for mic-in (rear panel) with vref */11100 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },11101 /* port-C for line-in (rear panel) */11102 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },11103 /* port-D for Front */11104 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },11105 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },11106 /* port-E for HP out (front panel) */11107 /* this has to be set to VREF80 */11108 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },11109 /* route front PCM to HP */11110 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },11111 /* port-F for mic-in (front panel) with vref */11112 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },11113 /* port-G for CLFE (rear panel) */11114 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },11115 /* port-H for side (rear panel) */11116 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },11117 /* CD-in */11118 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },11119 /* route front mic to ADC1*/11120 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},11121 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11122 /* Unmute DAC0~3 & spdif out*/11123 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11124 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11125 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11126 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11127 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1112811129 /* Unmute Mixer 14 (mic) 1c (Line in)*/11130 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11131 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11132 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11133 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},1113411135 /* Unmute Stereo Mixer 15 */11136 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11137 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11138 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},11139 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */1114011141 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11142 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11143 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11144 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11145 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11146 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11147 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11148 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11149 /* hp used DAC 3 (Front) */11150 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},11151 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},11152 { }11153};1115411155static struct hda_verb alc861_asus_init_verbs[] = {11156 /*11157 * Unmute ADC0 and set the default input to mic-in11158 */11159 /* port-A for surround (rear panel)11160 * according to codec#0 this is the HP jack11161 */11162 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */11163 /* route front PCM to HP */11164 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },11165 /* port-B for mic-in (rear panel) with vref */11166 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },11167 /* port-C for line-in (rear panel) */11168 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },11169 /* port-D for Front */11170 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },11171 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },11172 /* port-E for HP out (front panel) */11173 /* this has to be set to VREF80 */11174 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },11175 /* route front PCM to HP */11176 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },11177 /* port-F for mic-in (front panel) with vref */11178 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },11179 /* port-G for CLFE (rear panel) */11180 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },11181 /* port-H for side (rear panel) */11182 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },11183 /* CD-in */11184 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },11185 /* route front mic to ADC1*/11186 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},11187 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11188 /* Unmute DAC0~3 & spdif out*/11189 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11190 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11191 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11192 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11193 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},11194 /* Unmute Mixer 14 (mic) 1c (Line in)*/11195 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11196 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11197 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11198 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},1119911200 /* Unmute Stereo Mixer 15 */11201 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11202 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11203 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},11204 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */1120511206 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11207 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11208 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11209 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11210 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11211 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11212 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11213 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11214 /* hp used DAC 3 (Front) */11215 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},11216 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},11217 { }11218};1121911220/* additional init verbs for ASUS laptops */11221static struct hda_verb alc861_asus_laptop_init_verbs[] = {11222 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */11223 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */11224 { }11225};1122611227/*11228 * generic initialization of ADC, input mixers and output mixers11229 */11230static struct hda_verb alc861_auto_init_verbs[] = {11231 /*11232 * Unmute ADC0 and set the default input to mic-in11233 */11234 /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */11235 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},1123611237 /* Unmute DAC0~3 & spdif out*/11238 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},11239 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},11240 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},11241 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},11242 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1124311244 /* Unmute Mixer 14 (mic) 1c (Line in)*/11245 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11246 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11247 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11248 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},1124911250 /* Unmute Stereo Mixer 15 */11251 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11252 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11253 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},11254 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},1125511256 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11257 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11258 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11259 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11260 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11261 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},11262 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},11263 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},1126411265 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},11266 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},11267 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},11268 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},11269 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},11270 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},11271 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},11272 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},1127311274 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */1127511276 { }11277};1127811279static struct hda_verb alc861_toshiba_init_verbs[] = {11280 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},1128111282 { }11283};1128411285/* toggle speaker-output according to the hp-jack state */11286static void alc861_toshiba_automute(struct hda_codec *codec)11287{11288 unsigned int present;1128911290 present = snd_hda_codec_read(codec, 0x0f, 0,11291 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;11292 snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,11293 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);11294 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,11295 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);11296}1129711298static void alc861_toshiba_unsol_event(struct hda_codec *codec,11299 unsigned int res)11300{11301 if ((res >> 26) == ALC880_HP_EVENT)11302 alc861_toshiba_automute(codec);11303}1130411305/* pcm configuration: identiacal with ALC880 */11306#define alc861_pcm_analog_playback alc880_pcm_analog_playback11307#define alc861_pcm_analog_capture alc880_pcm_analog_capture11308#define alc861_pcm_digital_playback alc880_pcm_digital_playback11309#define alc861_pcm_digital_capture alc880_pcm_digital_capture113101131111312#define ALC861_DIGOUT_NID 0x071131311314static struct hda_channel_mode alc861_8ch_modes[1] = {11315 { 8, NULL }11316};1131711318static hda_nid_t alc861_dac_nids[4] = {11319 /* front, surround, clfe, side */11320 0x03, 0x06, 0x05, 0x0411321};1132211323static hda_nid_t alc660_dac_nids[3] = {11324 /* front, clfe, surround */11325 0x03, 0x05, 0x0611326};1132711328static hda_nid_t alc861_adc_nids[1] = {11329 /* ADC0-2 */11330 0x08,11331};1133211333static struct hda_input_mux alc861_capture_source = {11334 .num_items = 5,11335 .items = {11336 { "Mic", 0x0 },11337 { "Front Mic", 0x3 },11338 { "Line", 0x1 },11339 { "CD", 0x4 },11340 { "Mixer", 0x5 },11341 },11342};1134311344/* fill in the dac_nids table from the parsed pin configuration */11345static int alc861_auto_fill_dac_nids(struct alc_spec *spec,11346 const struct auto_pin_cfg *cfg)11347{11348 int i;11349 hda_nid_t nid;1135011351 spec->multiout.dac_nids = spec->private_dac_nids;11352 for (i = 0; i < cfg->line_outs; i++) {11353 nid = cfg->line_out_pins[i];11354 if (nid) {11355 if (i >= ARRAY_SIZE(alc861_dac_nids))11356 continue;11357 spec->multiout.dac_nids[i] = alc861_dac_nids[i];11358 }11359 }11360 spec->multiout.num_dacs = cfg->line_outs;11361 return 0;11362}1136311364/* add playback controls from the parsed DAC table */11365static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,11366 const struct auto_pin_cfg *cfg)11367{11368 char name[32];11369 static const char *chname[4] = {11370 "Front", "Surround", NULL /*CLFE*/, "Side"11371 };11372 hda_nid_t nid;11373 int i, idx, err;1137411375 for (i = 0; i < cfg->line_outs; i++) {11376 nid = spec->multiout.dac_nids[i];11377 if (!nid)11378 continue;11379 if (nid == 0x05) {11380 /* Center/LFE */11381 err = add_control(spec, ALC_CTL_BIND_MUTE,11382 "Center Playback Switch",11383 HDA_COMPOSE_AMP_VAL(nid, 1, 0,11384 HDA_OUTPUT));11385 if (err < 0)11386 return err;11387 err = add_control(spec, ALC_CTL_BIND_MUTE,11388 "LFE Playback Switch",11389 HDA_COMPOSE_AMP_VAL(nid, 2, 0,11390 HDA_OUTPUT));11391 if (err < 0)11392 return err;11393 } else {11394 for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1;11395 idx++)11396 if (nid == alc861_dac_nids[idx])11397 break;11398 sprintf(name, "%s Playback Switch", chname[idx]);11399 err = add_control(spec, ALC_CTL_BIND_MUTE, name,11400 HDA_COMPOSE_AMP_VAL(nid, 3, 0,11401 HDA_OUTPUT));11402 if (err < 0)11403 return err;11404 }11405 }11406 return 0;11407}1140811409static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)11410{11411 int err;11412 hda_nid_t nid;1141311414 if (!pin)11415 return 0;1141611417 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {11418 nid = 0x03;11419 err = add_control(spec, ALC_CTL_WIDGET_MUTE,11420 "Headphone Playback Switch",11421 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));11422 if (err < 0)11423 return err;11424 spec->multiout.hp_nid = nid;11425 }11426 return 0;11427}1142811429/* create playback/capture controls for input pins */11430static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,11431 const struct auto_pin_cfg *cfg)11432{11433 struct hda_input_mux *imux = &spec->private_imux;11434 int i, err, idx, idx1;1143511436 for (i = 0; i < AUTO_PIN_LAST; i++) {11437 switch (cfg->input_pins[i]) {11438 case 0x0c:11439 idx1 = 1;11440 idx = 2; /* Line In */11441 break;11442 case 0x0f:11443 idx1 = 2;11444 idx = 2; /* Line In */11445 break;11446 case 0x0d:11447 idx1 = 0;11448 idx = 1; /* Mic In */11449 break;11450 case 0x10:11451 idx1 = 3;11452 idx = 1; /* Mic In */11453 break;11454 case 0x11:11455 idx1 = 4;11456 idx = 0; /* CD */11457 break;11458 default:11459 continue;11460 }1146111462 err = new_analog_input(spec, cfg->input_pins[i],11463 auto_pin_cfg_labels[i], idx, 0x15);11464 if (err < 0)11465 return err;1146611467 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];11468 imux->items[imux->num_items].index = idx1;11469 imux->num_items++;11470 }11471 return 0;11472}1147311474static struct snd_kcontrol_new alc861_capture_mixer[] = {11475 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),11476 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),1147711478 {11479 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,11480 /* The multiple "Capture Source" controls confuse alsamixer11481 * So call somewhat different..11482 */11483 /* .name = "Capture Source", */11484 .name = "Input Source",11485 .count = 1,11486 .info = alc_mux_enum_info,11487 .get = alc_mux_enum_get,11488 .put = alc_mux_enum_put,11489 },11490 { } /* end */11491};1149211493static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,11494 hda_nid_t nid,11495 int pin_type, int dac_idx)11496{11497 alc_set_pin_output(codec, nid, pin_type);11498}1149911500static void alc861_auto_init_multi_out(struct hda_codec *codec)11501{11502 struct alc_spec *spec = codec->spec;11503 int i;1150411505 alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b);11506 for (i = 0; i < spec->autocfg.line_outs; i++) {11507 hda_nid_t nid = spec->autocfg.line_out_pins[i];11508 int pin_type = get_pin_type(spec->autocfg.line_out_type);11509 if (nid)11510 alc861_auto_set_output_and_unmute(codec, nid, pin_type,11511 spec->multiout.dac_nids[i]);11512 }11513}1151411515static void alc861_auto_init_hp_out(struct hda_codec *codec)11516{11517 struct alc_spec *spec = codec->spec;11518 hda_nid_t pin;1151911520 pin = spec->autocfg.hp_pins[0];11521 if (pin) /* connect to front */11522 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP,11523 spec->multiout.dac_nids[0]);11524 pin = spec->autocfg.speaker_pins[0];11525 if (pin)11526 alc861_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);11527}1152811529static void alc861_auto_init_analog_input(struct hda_codec *codec)11530{11531 struct alc_spec *spec = codec->spec;11532 int i;1153311534 for (i = 0; i < AUTO_PIN_LAST; i++) {11535 hda_nid_t nid = spec->autocfg.input_pins[i];11536 if (nid >= 0x0c && nid <= 0x11) {11537 snd_hda_codec_write(codec, nid, 0,11538 AC_VERB_SET_PIN_WIDGET_CONTROL,11539 i <= AUTO_PIN_FRONT_MIC ?11540 PIN_VREF80 : PIN_IN);11541 }11542 }11543}1154411545/* parse the BIOS configuration and set up the alc_spec */11546/* return 1 if successful, 0 if the proper config is not found,11547 * or a negative error code11548 */11549static int alc861_parse_auto_config(struct hda_codec *codec)11550{11551 struct alc_spec *spec = codec->spec;11552 int err;11553 static hda_nid_t alc861_ignore[] = { 0x1d, 0 };1155411555 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,11556 alc861_ignore);11557 if (err < 0)11558 return err;11559 if (!spec->autocfg.line_outs)11560 return 0; /* can't find valid BIOS pin config */1156111562 err = alc861_auto_fill_dac_nids(spec, &spec->autocfg);11563 if (err < 0)11564 return err;11565 err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg);11566 if (err < 0)11567 return err;11568 err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);11569 if (err < 0)11570 return err;11571 err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg);11572 if (err < 0)11573 return err;1157411575 spec->multiout.max_channels = spec->multiout.num_dacs * 2;1157611577 if (spec->autocfg.dig_out_pin)11578 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;1157911580 if (spec->kctl_alloc)11581 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;1158211583 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;1158411585 spec->num_mux_defs = 1;11586 spec->input_mux = &spec->private_imux;1158711588 spec->adc_nids = alc861_adc_nids;11589 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);11590 spec->mixers[spec->num_mixers] = alc861_capture_mixer;11591 spec->num_mixers++;1159211593 return 1;11594}1159511596/* additional initialization for auto-configuration model */11597static void alc861_auto_init(struct hda_codec *codec)11598{11599 struct alc_spec *spec = codec->spec;11600 alc861_auto_init_multi_out(codec);11601 alc861_auto_init_hp_out(codec);11602 alc861_auto_init_analog_input(codec);11603 if (spec->unsol_event)11604 alc_sku_automute(codec);11605}1160611607#ifdef CONFIG_SND_HDA_POWER_SAVE11608static struct hda_amp_list alc861_loopbacks[] = {11609 { 0x15, HDA_INPUT, 0 },11610 { 0x15, HDA_INPUT, 1 },11611 { 0x15, HDA_INPUT, 2 },11612 { 0x15, HDA_INPUT, 3 },11613 { } /* end */11614};11615#endif116161161711618/*11619 * configuration and preset11620 */11621static const char *alc861_models[ALC861_MODEL_LAST] = {11622 [ALC861_3ST] = "3stack",11623 [ALC660_3ST] = "3stack-660",11624 [ALC861_3ST_DIG] = "3stack-dig",11625 [ALC861_6ST_DIG] = "6stack-dig",11626 [ALC861_UNIWILL_M31] = "uniwill-m31",11627 [ALC861_TOSHIBA] = "toshiba",11628 [ALC861_ASUS] = "asus",11629 [ALC861_ASUS_LAPTOP] = "asus-laptop",11630 [ALC861_AUTO] = "auto",11631};1163211633static struct snd_pci_quirk alc861_cfg_tbl[] = {11634 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),11635 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),11636 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),11637 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),11638 SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),11639 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),11640 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),11641 /* FIXME: the entry below breaks Toshiba A100 (model=auto works!)11642 * Any other models that need this preset?11643 */11644 /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */11645 SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),11646 SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),11647 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),11648 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),11649 SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),11650 /* FIXME: the below seems conflict */11651 /* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */11652 SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),11653 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),11654 {}11655};1165611657static struct alc_config_preset alc861_presets[] = {11658 [ALC861_3ST] = {11659 .mixers = { alc861_3ST_mixer },11660 .init_verbs = { alc861_threestack_init_verbs },11661 .num_dacs = ARRAY_SIZE(alc861_dac_nids),11662 .dac_nids = alc861_dac_nids,11663 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),11664 .channel_mode = alc861_threestack_modes,11665 .need_dac_fix = 1,11666 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),11667 .adc_nids = alc861_adc_nids,11668 .input_mux = &alc861_capture_source,11669 },11670 [ALC861_3ST_DIG] = {11671 .mixers = { alc861_base_mixer },11672 .init_verbs = { alc861_threestack_init_verbs },11673 .num_dacs = ARRAY_SIZE(alc861_dac_nids),11674 .dac_nids = alc861_dac_nids,11675 .dig_out_nid = ALC861_DIGOUT_NID,11676 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),11677 .channel_mode = alc861_threestack_modes,11678 .need_dac_fix = 1,11679 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),11680 .adc_nids = alc861_adc_nids,11681 .input_mux = &alc861_capture_source,11682 },11683 [ALC861_6ST_DIG] = {11684 .mixers = { alc861_base_mixer },11685 .init_verbs = { alc861_base_init_verbs },11686 .num_dacs = ARRAY_SIZE(alc861_dac_nids),11687 .dac_nids = alc861_dac_nids,11688 .dig_out_nid = ALC861_DIGOUT_NID,11689 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),11690 .channel_mode = alc861_8ch_modes,11691 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),11692 .adc_nids = alc861_adc_nids,11693 .input_mux = &alc861_capture_source,11694 },11695 [ALC660_3ST] = {11696 .mixers = { alc861_3ST_mixer },11697 .init_verbs = { alc861_threestack_init_verbs },11698 .num_dacs = ARRAY_SIZE(alc660_dac_nids),11699 .dac_nids = alc660_dac_nids,11700 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),11701 .channel_mode = alc861_threestack_modes,11702 .need_dac_fix = 1,11703 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),11704 .adc_nids = alc861_adc_nids,11705 .input_mux = &alc861_capture_source,11706 },11707 [ALC861_UNIWILL_M31] = {11708 .mixers = { alc861_uniwill_m31_mixer },11709 .init_verbs = { alc861_uniwill_m31_init_verbs },11710 .num_dacs = ARRAY_SIZE(alc861_dac_nids),11711 .dac_nids = alc861_dac_nids,11712 .dig_out_nid = ALC861_DIGOUT_NID,11713 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),11714 .channel_mode = alc861_uniwill_m31_modes,11715 .need_dac_fix = 1,11716 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),11717 .adc_nids = alc861_adc_nids,11718 .input_mux = &alc861_capture_source,11719 },11720 [ALC861_TOSHIBA] = {11721 .mixers = { alc861_toshiba_mixer },11722 .init_verbs = { alc861_base_init_verbs,11723 alc861_toshiba_init_verbs },11724 .num_dacs = ARRAY_SIZE(alc861_dac_nids),11725 .dac_nids = alc861_dac_nids,11726 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),11727 .channel_mode = alc883_3ST_2ch_modes,11728 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),11729 .adc_nids = alc861_adc_nids,11730 .input_mux = &alc861_capture_source,11731 .unsol_event = alc861_toshiba_unsol_event,11732 .init_hook = alc861_toshiba_automute,11733 },11734 [ALC861_ASUS] = {11735 .mixers = { alc861_asus_mixer },11736 .init_verbs = { alc861_asus_init_verbs },11737 .num_dacs = ARRAY_SIZE(alc861_dac_nids),11738 .dac_nids = alc861_dac_nids,11739 .dig_out_nid = ALC861_DIGOUT_NID,11740 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes),11741 .channel_mode = alc861_asus_modes,11742 .need_dac_fix = 1,11743 .hp_nid = 0x06,11744 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),11745 .adc_nids = alc861_adc_nids,11746 .input_mux = &alc861_capture_source,11747 },11748 [ALC861_ASUS_LAPTOP] = {11749 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },11750 .init_verbs = { alc861_asus_init_verbs,11751 alc861_asus_laptop_init_verbs },11752 .num_dacs = ARRAY_SIZE(alc861_dac_nids),11753 .dac_nids = alc861_dac_nids,11754 .dig_out_nid = ALC861_DIGOUT_NID,11755 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),11756 .channel_mode = alc883_3ST_2ch_modes,11757 .need_dac_fix = 1,11758 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),11759 .adc_nids = alc861_adc_nids,11760 .input_mux = &alc861_capture_source,11761 },11762};117631176411765static int patch_alc861(struct hda_codec *codec)11766{11767 struct alc_spec *spec;11768 int board_config;11769 int err;1177011771 spec = kzalloc(sizeof(*spec), GFP_KERNEL);11772 if (spec == NULL)11773 return -ENOMEM;1177411775 codec->spec = spec;1177611777 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,11778 alc861_models,11779 alc861_cfg_tbl);1178011781 if (board_config < 0) {11782 printk(KERN_INFO "hda_codec: Unknown model for ALC861, "11783 "trying auto-probe from BIOS...\n");11784 board_config = ALC861_AUTO;11785 }1178611787 if (board_config == ALC861_AUTO) {11788 /* automatic parse from the BIOS config */11789 err = alc861_parse_auto_config(codec);11790 if (err < 0) {11791 alc_free(codec);11792 return err;11793 } else if (!err) {11794 printk(KERN_INFO11795 "hda_codec: Cannot set up configuration "11796 "from BIOS. Using base mode...\n");11797 board_config = ALC861_3ST_DIG;11798 }11799 }1180011801 if (board_config != ALC861_AUTO)11802 setup_preset(spec, &alc861_presets[board_config]);1180311804 spec->stream_name_analog = "ALC861 Analog";11805 spec->stream_analog_playback = &alc861_pcm_analog_playback;11806 spec->stream_analog_capture = &alc861_pcm_analog_capture;1180711808 spec->stream_name_digital = "ALC861 Digital";11809 spec->stream_digital_playback = &alc861_pcm_digital_playback;11810 spec->stream_digital_capture = &alc861_pcm_digital_capture;1181111812 spec->vmaster_nid = 0x03;1181311814 codec->patch_ops = alc_patch_ops;11815 if (board_config == ALC861_AUTO)11816 spec->init_hook = alc861_auto_init;11817#ifdef CONFIG_SND_HDA_POWER_SAVE11818 if (!spec->loopback.amplist)11819 spec->loopback.amplist = alc861_loopbacks;11820#endif1182111822 return 0;11823}1182411825/*11826 * ALC861-VD support11827 *11828 * Based on ALC88211829 *11830 * In addition, an independent DAC11831 */11832#define ALC861VD_DIGOUT_NID 0x061183311834static hda_nid_t alc861vd_dac_nids[4] = {11835 /* front, surr, clfe, side surr */11836 0x02, 0x03, 0x04, 0x0511837};1183811839/* dac_nids for ALC660vd are in a different order - according to11840 * Realtek's driver.11841 * This should probably tesult in a different mixer for 6stack models11842 * of ALC660vd codecs, but for now there is only 3stack mixer11843 * - and it is the same as in 861vd.11844 * adc_nids in ALC660vd are (is) the same as in 861vd11845 */11846static hda_nid_t alc660vd_dac_nids[3] = {11847 /* front, rear, clfe, rear_surr */11848 0x02, 0x04, 0x0311849};1185011851static hda_nid_t alc861vd_adc_nids[1] = {11852 /* ADC0 */11853 0x09,11854};1185511856static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };1185711858/* input MUX */11859/* FIXME: should be a matrix-type input source selection */11860static struct hda_input_mux alc861vd_capture_source = {11861 .num_items = 4,11862 .items = {11863 { "Mic", 0x0 },11864 { "Front Mic", 0x1 },11865 { "Line", 0x2 },11866 { "CD", 0x4 },11867 },11868};1186911870static struct hda_input_mux alc861vd_dallas_capture_source = {11871 .num_items = 3,11872 .items = {11873 { "Front Mic", 0x0 },11874 { "ATAPI Mic", 0x1 },11875 { "Line In", 0x5 },11876 },11877};1187811879static struct hda_input_mux alc861vd_hp_capture_source = {11880 .num_items = 2,11881 .items = {11882 { "Front Mic", 0x0 },11883 { "ATAPI Mic", 0x1 },11884 },11885};1188611887#define alc861vd_mux_enum_info alc_mux_enum_info11888#define alc861vd_mux_enum_get alc_mux_enum_get11889/* ALC861VD has the ALC882-type input selection (but has only one ADC) */11890#define alc861vd_mux_enum_put alc882_mux_enum_put1189111892/*11893 * 2ch mode11894 */11895static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {11896 { 2, NULL }11897};1189811899/*11900 * 6ch mode11901 */11902static struct hda_verb alc861vd_6stack_ch6_init[] = {11903 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },11904 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },11905 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },11906 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },11907 { } /* end */11908};1190911910/*11911 * 8ch mode11912 */11913static struct hda_verb alc861vd_6stack_ch8_init[] = {11914 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },11915 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },11916 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },11917 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },11918 { } /* end */11919};1192011921static struct hda_channel_mode alc861vd_6stack_modes[2] = {11922 { 6, alc861vd_6stack_ch6_init },11923 { 8, alc861vd_6stack_ch8_init },11924};1192511926static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {11927 {11928 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,11929 .name = "Channel Mode",11930 .info = alc_ch_mode_info,11931 .get = alc_ch_mode_get,11932 .put = alc_ch_mode_put,11933 },11934 { } /* end */11935};1193611937static struct snd_kcontrol_new alc861vd_capture_mixer[] = {11938 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),11939 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),1194011941 {11942 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,11943 /* The multiple "Capture Source" controls confuse alsamixer11944 * So call somewhat different..11945 */11946 /* .name = "Capture Source", */11947 .name = "Input Source",11948 .count = 1,11949 .info = alc861vd_mux_enum_info,11950 .get = alc861vd_mux_enum_get,11951 .put = alc861vd_mux_enum_put,11952 },11953 { } /* end */11954};1195511956/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x1711957 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b11958 */11959static struct snd_kcontrol_new alc861vd_6st_mixer[] = {11960 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),11961 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),1196211963 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),11964 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),1196511966 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,11967 HDA_OUTPUT),11968 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,11969 HDA_OUTPUT),11970 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),11971 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),1197211973 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),11974 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),1197511976 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),1197711978 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),11979 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),11980 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1198111982 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),11983 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),11984 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),1198511986 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),11987 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),1198811989 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),11990 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),1199111992 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),11993 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),1199411995 { } /* end */11996};1199711998static struct snd_kcontrol_new alc861vd_3st_mixer[] = {11999 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),12000 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),1200112002 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),1200312004 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),12005 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),12006 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1200712008 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),12009 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),12010 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),1201112012 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),12013 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),1201412015 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),12016 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),1201712018 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),12019 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),1202012021 { } /* end */12022};1202312024static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {12025 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),12026 /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/12027 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),1202812029 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),1203012031 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),12032 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),12033 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1203412035 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),12036 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),12037 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),1203812039 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),12040 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),1204112042 { } /* end */12043};1204412045/* Pin assignment: Front=0x14, HP = 0x15,12046 * Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d12047 */12048static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {12049 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),12050 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),12051 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),12052 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),12053 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),12054 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),12055 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),12056 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),12057 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT),12058 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT),12059 { } /* end */12060};1206112062/* Pin assignment: Speaker=0x14, Line-out = 0x15,12063 * Front Mic=0x18, ATAPI Mic = 0x19,12064 */12065static struct snd_kcontrol_new alc861vd_hp_mixer[] = {12066 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),12067 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),12068 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),12069 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),12070 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),12071 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),12072 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),12073 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),1207412075 { } /* end */12076};1207712078/*12079 * generic initialization of ADC, input mixers and output mixers12080 */12081static struct hda_verb alc861vd_volume_init_verbs[] = {12082 /*12083 * Unmute ADC0 and set the default input to mic-in12084 */12085 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},12086 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},1208712088 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of12089 * the analog-loopback mixer widget12090 */12091 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */12092 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},12093 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},12094 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},12095 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},12096 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},1209712098 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */12099 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},12100 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},12101 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},12102 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},1210312104 /*12105 * Set up output mixers (0x02 - 0x05)12106 */12107 /* set vol=0 to output mixers */12108 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},12109 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},12110 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},12111 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},1211212113 /* set up input amps for analog loopback */12114 /* Amp Indices: DAC = 0, mixer = 1 */12115 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},12116 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},12117 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},12118 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},12119 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},12120 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},12121 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},12122 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},1212312124 { }12125};1212612127/*12128 * 3-stack pin configuration:12129 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b12130 */12131static struct hda_verb alc861vd_3stack_init_verbs[] = {12132 /*12133 * Set pin mode and muting12134 */12135 /* set front pin widgets 0x14 for output */12136 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},12137 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},12138 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},1213912140 /* Mic (rear) pin: input vref at 80% */12141 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},12142 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},12143 /* Front Mic pin: input vref at 80% */12144 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},12145 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},12146 /* Line In pin: input */12147 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},12148 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},12149 /* Line-2 In: Headphone output (output 0 - 0x0c) */12150 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},12151 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},12152 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},12153 /* CD pin widget for input */12154 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1215512156 { }12157};1215812159/*12160 * 6-stack pin configuration:12161 */12162static struct hda_verb alc861vd_6stack_init_verbs[] = {12163 /*12164 * Set pin mode and muting12165 */12166 /* set front pin widgets 0x14 for output */12167 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},12168 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},12169 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},1217012171 /* Rear Pin: output 1 (0x0d) */12172 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},12173 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},12174 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},12175 /* CLFE Pin: output 2 (0x0e) */12176 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},12177 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},12178 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},12179 /* Side Pin: output 3 (0x0f) */12180 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},12181 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},12182 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},1218312184 /* Mic (rear) pin: input vref at 80% */12185 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},12186 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},12187 /* Front Mic pin: input vref at 80% */12188 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},12189 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},12190 /* Line In pin: input */12191 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},12192 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},12193 /* Line-2 In: Headphone output (output 0 - 0x0c) */12194 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},12195 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},12196 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},12197 /* CD pin widget for input */12198 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1219912200 { }12201};1220212203static struct hda_verb alc861vd_eapd_verbs[] = {12204 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},12205 { }12206};1220712208static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {12209 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},12210 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},12211 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},12212 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},12213 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},12214 {}12215};1221612217/* toggle speaker-output according to the hp-jack state */12218static void alc861vd_lenovo_hp_automute(struct hda_codec *codec)12219{12220 unsigned int present;12221 unsigned char bits;1222212223 present = snd_hda_codec_read(codec, 0x1b, 0,12224 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;12225 bits = present ? HDA_AMP_MUTE : 0;12226 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,12227 HDA_AMP_MUTE, bits);12228}1222912230static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)12231{12232 unsigned int present;12233 unsigned char bits;1223412235 present = snd_hda_codec_read(codec, 0x18, 0,12236 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;12237 bits = present ? HDA_AMP_MUTE : 0;12238 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,12239 HDA_AMP_MUTE, bits);12240}1224112242static void alc861vd_lenovo_automute(struct hda_codec *codec)12243{12244 alc861vd_lenovo_hp_automute(codec);12245 alc861vd_lenovo_mic_automute(codec);12246}1224712248static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,12249 unsigned int res)12250{12251 switch (res >> 26) {12252 case ALC880_HP_EVENT:12253 alc861vd_lenovo_hp_automute(codec);12254 break;12255 case ALC880_MIC_EVENT:12256 alc861vd_lenovo_mic_automute(codec);12257 break;12258 }12259}1226012261static struct hda_verb alc861vd_dallas_verbs[] = {12262 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},12263 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},12264 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},12265 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},1226612267 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},12268 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},12269 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},12270 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},12271 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},12272 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},12273 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},12274 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},1227512276 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},12277 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},12278 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},12279 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},12280 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},12281 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},12282 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},12283 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1228412285 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},12286 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},12287 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},12288 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},12289 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},12290 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},12291 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},12292 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1229312294 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},12295 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},12296 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},12297 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},1229812299 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},12300 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},12301 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},1230212303 { } /* end */12304};1230512306/* toggle speaker-output according to the hp-jack state */12307static void alc861vd_dallas_automute(struct hda_codec *codec)12308{12309 unsigned int present;1231012311 present = snd_hda_codec_read(codec, 0x15, 0,12312 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;12313 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,12314 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);12315}1231612317static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res)12318{12319 if ((res >> 26) == ALC880_HP_EVENT)12320 alc861vd_dallas_automute(codec);12321}1232212323#ifdef CONFIG_SND_HDA_POWER_SAVE12324#define alc861vd_loopbacks alc880_loopbacks12325#endif1232612327/* pcm configuration: identiacal with ALC880 */12328#define alc861vd_pcm_analog_playback alc880_pcm_analog_playback12329#define alc861vd_pcm_analog_capture alc880_pcm_analog_capture12330#define alc861vd_pcm_digital_playback alc880_pcm_digital_playback12331#define alc861vd_pcm_digital_capture alc880_pcm_digital_capture1233212333/*12334 * configuration and preset12335 */12336static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {12337 [ALC660VD_3ST] = "3stack-660",12338 [ALC660VD_3ST_DIG] = "3stack-660-digout",12339 [ALC861VD_3ST] = "3stack",12340 [ALC861VD_3ST_DIG] = "3stack-digout",12341 [ALC861VD_6ST_DIG] = "6stack-digout",12342 [ALC861VD_LENOVO] = "lenovo",12343 [ALC861VD_DALLAS] = "dallas",12344 [ALC861VD_HP] = "hp",12345 [ALC861VD_AUTO] = "auto",12346};1234712348static struct snd_pci_quirk alc861vd_cfg_tbl[] = {12349 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),12350 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),12351 SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),12352 SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),12353 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),12354 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),12355 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),12356 /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/12357 SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),12358 SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),12359 SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),12360 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),12361 SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),12362 SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),12363 {}12364};1236512366static struct alc_config_preset alc861vd_presets[] = {12367 [ALC660VD_3ST] = {12368 .mixers = { alc861vd_3st_mixer },12369 .init_verbs = { alc861vd_volume_init_verbs,12370 alc861vd_3stack_init_verbs },12371 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),12372 .dac_nids = alc660vd_dac_nids,12373 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),12374 .channel_mode = alc861vd_3stack_2ch_modes,12375 .input_mux = &alc861vd_capture_source,12376 },12377 [ALC660VD_3ST_DIG] = {12378 .mixers = { alc861vd_3st_mixer },12379 .init_verbs = { alc861vd_volume_init_verbs,12380 alc861vd_3stack_init_verbs },12381 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),12382 .dac_nids = alc660vd_dac_nids,12383 .dig_out_nid = ALC861VD_DIGOUT_NID,12384 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),12385 .channel_mode = alc861vd_3stack_2ch_modes,12386 .input_mux = &alc861vd_capture_source,12387 },12388 [ALC861VD_3ST] = {12389 .mixers = { alc861vd_3st_mixer },12390 .init_verbs = { alc861vd_volume_init_verbs,12391 alc861vd_3stack_init_verbs },12392 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),12393 .dac_nids = alc861vd_dac_nids,12394 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),12395 .channel_mode = alc861vd_3stack_2ch_modes,12396 .input_mux = &alc861vd_capture_source,12397 },12398 [ALC861VD_3ST_DIG] = {12399 .mixers = { alc861vd_3st_mixer },12400 .init_verbs = { alc861vd_volume_init_verbs,12401 alc861vd_3stack_init_verbs },12402 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),12403 .dac_nids = alc861vd_dac_nids,12404 .dig_out_nid = ALC861VD_DIGOUT_NID,12405 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),12406 .channel_mode = alc861vd_3stack_2ch_modes,12407 .input_mux = &alc861vd_capture_source,12408 },12409 [ALC861VD_6ST_DIG] = {12410 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },12411 .init_verbs = { alc861vd_volume_init_verbs,12412 alc861vd_6stack_init_verbs },12413 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),12414 .dac_nids = alc861vd_dac_nids,12415 .dig_out_nid = ALC861VD_DIGOUT_NID,12416 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),12417 .channel_mode = alc861vd_6stack_modes,12418 .input_mux = &alc861vd_capture_source,12419 },12420 [ALC861VD_LENOVO] = {12421 .mixers = { alc861vd_lenovo_mixer },12422 .init_verbs = { alc861vd_volume_init_verbs,12423 alc861vd_3stack_init_verbs,12424 alc861vd_eapd_verbs,12425 alc861vd_lenovo_unsol_verbs },12426 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),12427 .dac_nids = alc660vd_dac_nids,12428 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),12429 .channel_mode = alc861vd_3stack_2ch_modes,12430 .input_mux = &alc861vd_capture_source,12431 .unsol_event = alc861vd_lenovo_unsol_event,12432 .init_hook = alc861vd_lenovo_automute,12433 },12434 [ALC861VD_DALLAS] = {12435 .mixers = { alc861vd_dallas_mixer },12436 .init_verbs = { alc861vd_dallas_verbs },12437 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),12438 .dac_nids = alc861vd_dac_nids,12439 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),12440 .channel_mode = alc861vd_3stack_2ch_modes,12441 .input_mux = &alc861vd_dallas_capture_source,12442 .unsol_event = alc861vd_dallas_unsol_event,12443 .init_hook = alc861vd_dallas_automute,12444 },12445 [ALC861VD_HP] = {12446 .mixers = { alc861vd_hp_mixer },12447 .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },12448 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),12449 .dac_nids = alc861vd_dac_nids,12450 .dig_out_nid = ALC861VD_DIGOUT_NID,12451 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),12452 .channel_mode = alc861vd_3stack_2ch_modes,12453 .input_mux = &alc861vd_hp_capture_source,12454 .unsol_event = alc861vd_dallas_unsol_event,12455 .init_hook = alc861vd_dallas_automute,12456 },12457};1245812459/*12460 * BIOS auto configuration12461 */12462static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,12463 hda_nid_t nid, int pin_type, int dac_idx)12464{12465 alc_set_pin_output(codec, nid, pin_type);12466}1246712468static void alc861vd_auto_init_multi_out(struct hda_codec *codec)12469{12470 struct alc_spec *spec = codec->spec;12471 int i;1247212473 alc_subsystem_id(codec, 0x15, 0x1b, 0x14);12474 for (i = 0; i <= HDA_SIDE; i++) {12475 hda_nid_t nid = spec->autocfg.line_out_pins[i];12476 int pin_type = get_pin_type(spec->autocfg.line_out_type);12477 if (nid)12478 alc861vd_auto_set_output_and_unmute(codec, nid,12479 pin_type, i);12480 }12481}124821248312484static void alc861vd_auto_init_hp_out(struct hda_codec *codec)12485{12486 struct alc_spec *spec = codec->spec;12487 hda_nid_t pin;1248812489 pin = spec->autocfg.hp_pins[0];12490 if (pin) /* connect to front and use dac 0 */12491 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);12492 pin = spec->autocfg.speaker_pins[0];12493 if (pin)12494 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);12495}1249612497#define alc861vd_is_input_pin(nid) alc880_is_input_pin(nid)12498#define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID1249912500static void alc861vd_auto_init_analog_input(struct hda_codec *codec)12501{12502 struct alc_spec *spec = codec->spec;12503 int i;1250412505 for (i = 0; i < AUTO_PIN_LAST; i++) {12506 hda_nid_t nid = spec->autocfg.input_pins[i];12507 if (alc861vd_is_input_pin(nid)) {12508 snd_hda_codec_write(codec, nid, 0,12509 AC_VERB_SET_PIN_WIDGET_CONTROL,12510 i <= AUTO_PIN_FRONT_MIC ?12511 PIN_VREF80 : PIN_IN);12512 if (nid != ALC861VD_PIN_CD_NID)12513 snd_hda_codec_write(codec, nid, 0,12514 AC_VERB_SET_AMP_GAIN_MUTE,12515 AMP_OUT_MUTE);12516 }12517 }12518}1251912520#define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02)12521#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)1252212523/* add playback controls from the parsed DAC table */12524/* Based on ALC880 version. But ALC861VD has separate,12525 * different NIDs for mute/unmute switch and volume control */12526static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,12527 const struct auto_pin_cfg *cfg)12528{12529 char name[32];12530 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};12531 hda_nid_t nid_v, nid_s;12532 int i, err;1253312534 for (i = 0; i < cfg->line_outs; i++) {12535 if (!spec->multiout.dac_nids[i])12536 continue;12537 nid_v = alc861vd_idx_to_mixer_vol(12538 alc880_dac_to_idx(12539 spec->multiout.dac_nids[i]));12540 nid_s = alc861vd_idx_to_mixer_switch(12541 alc880_dac_to_idx(12542 spec->multiout.dac_nids[i]));1254312544 if (i == 2) {12545 /* Center/LFE */12546 err = add_control(spec, ALC_CTL_WIDGET_VOL,12547 "Center Playback Volume",12548 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,12549 HDA_OUTPUT));12550 if (err < 0)12551 return err;12552 err = add_control(spec, ALC_CTL_WIDGET_VOL,12553 "LFE Playback Volume",12554 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,12555 HDA_OUTPUT));12556 if (err < 0)12557 return err;12558 err = add_control(spec, ALC_CTL_BIND_MUTE,12559 "Center Playback Switch",12560 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,12561 HDA_INPUT));12562 if (err < 0)12563 return err;12564 err = add_control(spec, ALC_CTL_BIND_MUTE,12565 "LFE Playback Switch",12566 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,12567 HDA_INPUT));12568 if (err < 0)12569 return err;12570 } else {12571 sprintf(name, "%s Playback Volume", chname[i]);12572 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,12573 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,12574 HDA_OUTPUT));12575 if (err < 0)12576 return err;12577 sprintf(name, "%s Playback Switch", chname[i]);12578 err = add_control(spec, ALC_CTL_BIND_MUTE, name,12579 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,12580 HDA_INPUT));12581 if (err < 0)12582 return err;12583 }12584 }12585 return 0;12586}1258712588/* add playback controls for speaker and HP outputs */12589/* Based on ALC880 version. But ALC861VD has separate,12590 * different NIDs for mute/unmute switch and volume control */12591static int alc861vd_auto_create_extra_out(struct alc_spec *spec,12592 hda_nid_t pin, const char *pfx)12593{12594 hda_nid_t nid_v, nid_s;12595 int err;12596 char name[32];1259712598 if (!pin)12599 return 0;1260012601 if (alc880_is_fixed_pin(pin)) {12602 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));12603 /* specify the DAC as the extra output */12604 if (!spec->multiout.hp_nid)12605 spec->multiout.hp_nid = nid_v;12606 else12607 spec->multiout.extra_out_nid[0] = nid_v;12608 /* control HP volume/switch on the output mixer amp */12609 nid_v = alc861vd_idx_to_mixer_vol(12610 alc880_fixed_pin_idx(pin));12611 nid_s = alc861vd_idx_to_mixer_switch(12612 alc880_fixed_pin_idx(pin));1261312614 sprintf(name, "%s Playback Volume", pfx);12615 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,12616 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));12617 if (err < 0)12618 return err;12619 sprintf(name, "%s Playback Switch", pfx);12620 err = add_control(spec, ALC_CTL_BIND_MUTE, name,12621 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));12622 if (err < 0)12623 return err;12624 } else if (alc880_is_multi_pin(pin)) {12625 /* set manual connection */12626 /* we have only a switch on HP-out PIN */12627 sprintf(name, "%s Playback Switch", pfx);12628 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,12629 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));12630 if (err < 0)12631 return err;12632 }12633 return 0;12634}1263512636/* parse the BIOS configuration and set up the alc_spec12637 * return 1 if successful, 0 if the proper config is not found,12638 * or a negative error code12639 * Based on ALC880 version - had to change it to override12640 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */12641static int alc861vd_parse_auto_config(struct hda_codec *codec)12642{12643 struct alc_spec *spec = codec->spec;12644 int err;12645 static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };1264612647 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,12648 alc861vd_ignore);12649 if (err < 0)12650 return err;12651 if (!spec->autocfg.line_outs)12652 return 0; /* can't find valid BIOS pin config */1265312654 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);12655 if (err < 0)12656 return err;12657 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);12658 if (err < 0)12659 return err;12660 err = alc861vd_auto_create_extra_out(spec,12661 spec->autocfg.speaker_pins[0],12662 "Speaker");12663 if (err < 0)12664 return err;12665 err = alc861vd_auto_create_extra_out(spec,12666 spec->autocfg.hp_pins[0],12667 "Headphone");12668 if (err < 0)12669 return err;12670 err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);12671 if (err < 0)12672 return err;1267312674 spec->multiout.max_channels = spec->multiout.num_dacs * 2;1267512676 if (spec->autocfg.dig_out_pin)12677 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;1267812679 if (spec->kctl_alloc)12680 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;1268112682 spec->init_verbs[spec->num_init_verbs++]12683 = alc861vd_volume_init_verbs;1268412685 spec->num_mux_defs = 1;12686 spec->input_mux = &spec->private_imux;1268712688 err = alc_auto_add_mic_boost(codec);12689 if (err < 0)12690 return err;1269112692 return 1;12693}1269412695/* additional initialization for auto-configuration model */12696static void alc861vd_auto_init(struct hda_codec *codec)12697{12698 struct alc_spec *spec = codec->spec;12699 alc861vd_auto_init_multi_out(codec);12700 alc861vd_auto_init_hp_out(codec);12701 alc861vd_auto_init_analog_input(codec);12702 if (spec->unsol_event)12703 alc_sku_automute(codec);12704}1270512706static int patch_alc861vd(struct hda_codec *codec)12707{12708 struct alc_spec *spec;12709 int err, board_config;1271012711 spec = kzalloc(sizeof(*spec), GFP_KERNEL);12712 if (spec == NULL)12713 return -ENOMEM;1271412715 codec->spec = spec;1271612717 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,12718 alc861vd_models,12719 alc861vd_cfg_tbl);1272012721 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {12722 printk(KERN_INFO "hda_codec: Unknown model for ALC660VD/"12723 "ALC861VD, trying auto-probe from BIOS...\n");12724 board_config = ALC861VD_AUTO;12725 }1272612727 if (board_config == ALC861VD_AUTO) {12728 /* automatic parse from the BIOS config */12729 err = alc861vd_parse_auto_config(codec);12730 if (err < 0) {12731 alc_free(codec);12732 return err;12733 } else if (!err) {12734 printk(KERN_INFO12735 "hda_codec: Cannot set up configuration "12736 "from BIOS. Using base mode...\n");12737 board_config = ALC861VD_3ST;12738 }12739 }1274012741 if (board_config != ALC861VD_AUTO)12742 setup_preset(spec, &alc861vd_presets[board_config]);1274312744 spec->stream_name_analog = "ALC861VD Analog";12745 spec->stream_analog_playback = &alc861vd_pcm_analog_playback;12746 spec->stream_analog_capture = &alc861vd_pcm_analog_capture;1274712748 spec->stream_name_digital = "ALC861VD Digital";12749 spec->stream_digital_playback = &alc861vd_pcm_digital_playback;12750 spec->stream_digital_capture = &alc861vd_pcm_digital_capture;1275112752 spec->adc_nids = alc861vd_adc_nids;12753 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);12754 spec->capsrc_nids = alc861vd_capsrc_nids;1275512756 spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;12757 spec->num_mixers++;1275812759 spec->vmaster_nid = 0x02;1276012761 codec->patch_ops = alc_patch_ops;1276212763 if (board_config == ALC861VD_AUTO)12764 spec->init_hook = alc861vd_auto_init;12765#ifdef CONFIG_SND_HDA_POWER_SAVE12766 if (!spec->loopback.amplist)12767 spec->loopback.amplist = alc861vd_loopbacks;12768#endif1276912770 return 0;12771}1277212773/*12774 * ALC662 support12775 *12776 * ALC662 is almost identical with ALC880 but has cleaner and more flexible12777 * configuration. Each pin widget can choose any input DACs and a mixer.12778 * Each ADC is connected from a mixer of all inputs. This makes possible12779 * 6-channel independent captures.12780 *12781 * In addition, an independent DAC for the multi-playback (not used in this12782 * driver yet).12783 */12784#define ALC662_DIGOUT_NID 0x0612785#define ALC662_DIGIN_NID 0x0a1278612787static hda_nid_t alc662_dac_nids[4] = {12788 /* front, rear, clfe, rear_surr */12789 0x02, 0x03, 0x0412790};1279112792static hda_nid_t alc662_adc_nids[1] = {12793 /* ADC1-2 */12794 0x09,12795};1279612797static hda_nid_t alc662_capsrc_nids[1] = { 0x22 };1279812799/* input MUX */12800/* FIXME: should be a matrix-type input source selection */12801static struct hda_input_mux alc662_capture_source = {12802 .num_items = 4,12803 .items = {12804 { "Mic", 0x0 },12805 { "Front Mic", 0x1 },12806 { "Line", 0x2 },12807 { "CD", 0x4 },12808 },12809};1281012811static struct hda_input_mux alc662_lenovo_101e_capture_source = {12812 .num_items = 2,12813 .items = {12814 { "Mic", 0x1 },12815 { "Line", 0x2 },12816 },12817};1281812819static struct hda_input_mux alc662_eeepc_capture_source = {12820 .num_items = 2,12821 .items = {12822 { "i-Mic", 0x1 },12823 { "e-Mic", 0x0 },12824 },12825};1282612827#define alc662_mux_enum_info alc_mux_enum_info12828#define alc662_mux_enum_get alc_mux_enum_get12829#define alc662_mux_enum_put alc882_mux_enum_put1283012831/*12832 * 2ch mode12833 */12834static struct hda_channel_mode alc662_3ST_2ch_modes[1] = {12835 { 2, NULL }12836};1283712838/*12839 * 2ch mode12840 */12841static struct hda_verb alc662_3ST_ch2_init[] = {12842 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },12843 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },12844 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },12845 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },12846 { } /* end */12847};1284812849/*12850 * 6ch mode12851 */12852static struct hda_verb alc662_3ST_ch6_init[] = {12853 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },12854 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },12855 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },12856 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },12857 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },12858 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },12859 { } /* end */12860};1286112862static struct hda_channel_mode alc662_3ST_6ch_modes[2] = {12863 { 2, alc662_3ST_ch2_init },12864 { 6, alc662_3ST_ch6_init },12865};1286612867/*12868 * 2ch mode12869 */12870static struct hda_verb alc662_sixstack_ch6_init[] = {12871 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },12872 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },12873 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },12874 { } /* end */12875};1287612877/*12878 * 6ch mode12879 */12880static struct hda_verb alc662_sixstack_ch8_init[] = {12881 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },12882 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },12883 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },12884 { } /* end */12885};1288612887static struct hda_channel_mode alc662_5stack_modes[2] = {12888 { 2, alc662_sixstack_ch6_init },12889 { 6, alc662_sixstack_ch8_init },12890};1289112892/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x1712893 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b12894 */1289512896static struct snd_kcontrol_new alc662_base_mixer[] = {12897 /* output mixer control */12898 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),12899 HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT),12900 HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),12901 HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT),12902 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),12903 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),12904 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),12905 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),12906 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),1290712908 /*Input mixer control */12909 HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),12910 HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),12911 HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),12912 HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),12913 HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),12914 HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),12915 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),12916 HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),12917 { } /* end */12918};1291912920static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {12921 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),12922 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),12923 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),12924 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),12925 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),12926 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),12927 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),12928 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),12929 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),12930 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),12931 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),12932 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),12933 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),12934 { } /* end */12935};1293612937static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {12938 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),12939 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),12940 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),12941 HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),12942 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),12943 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),12944 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),12945 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),12946 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),12947 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),12948 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),12949 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),12950 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),12951 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),12952 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),12953 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),12954 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),12955 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),12956 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),12957 { } /* end */12958};1295912960static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {12961 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),12962 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),12963 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),12964 HDA_BIND_MUTE("Speaker Playback Switch", 0x03, 2, HDA_INPUT),12965 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),12966 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),12967 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),12968 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),12969 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),12970 { } /* end */12971};1297212973static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {12974 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),1297512976 HDA_CODEC_VOLUME("LineOut Playback Volume", 0x02, 0x0, HDA_OUTPUT),12977 HDA_CODEC_MUTE("LineOut Playback Switch", 0x1b, 0x0, HDA_OUTPUT),1297812979 HDA_CODEC_VOLUME("e-Mic Boost", 0x18, 0, HDA_INPUT),12980 HDA_CODEC_VOLUME("e-Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),12981 HDA_CODEC_MUTE("e-Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),1298212983 HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT),12984 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),12985 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),12986 { } /* end */12987};1298812989static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {12990 HDA_CODEC_VOLUME("LineOut Playback Volume", 0x02, 0x0, HDA_OUTPUT),12991 HDA_CODEC_MUTE("LineOut Playback Switch", 0x14, 0x0, HDA_OUTPUT),12992 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),12993 HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),12994 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),12995 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),12996 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),12997 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),12998 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),12999 HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),13000 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),13001 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),13002 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),13003 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),13004 { } /* end */13005};1300613007static struct snd_kcontrol_new alc662_chmode_mixer[] = {13008 {13009 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,13010 .name = "Channel Mode",13011 .info = alc_ch_mode_info,13012 .get = alc_ch_mode_get,13013 .put = alc_ch_mode_put,13014 },13015 { } /* end */13016};1301713018static struct hda_verb alc662_init_verbs[] = {13019 /* ADC: mute amp left and right */13020 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},13021 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},13022 /* Front mixer: unmute input/output amp left and right (volume = 0) */1302313024 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},13025 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},13026 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},13027 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},13028 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},1302913030 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},13031 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},13032 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},13033 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},13034 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},13035 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},1303613037 /* Front Pin: output 0 (0x0c) */13038 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},13039 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1304013041 /* Rear Pin: output 1 (0x0d) */13042 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},13043 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1304413045 /* CLFE Pin: output 2 (0x0e) */13046 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},13047 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},1304813049 /* Mic (rear) pin: input vref at 80% */13050 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},13051 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},13052 /* Front Mic pin: input vref at 80% */13053 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},13054 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},13055 /* Line In pin: input */13056 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},13057 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},13058 /* Line-2 In: Headphone output (output 0 - 0x0c) */13059 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},13060 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},13061 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},13062 /* CD pin widget for input */13063 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},1306413065 /* FIXME: use matrix-type input source selection */13066 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */13067 /* Input mixer */13068 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},13069 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},13070 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},13071 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},1307213073 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},13074 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},13075 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},13076 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},13077 { }13078};1307913080static struct hda_verb alc662_sue_init_verbs[] = {13081 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},13082 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},13083 {}13084};1308513086static struct hda_verb alc662_eeepc_sue_init_verbs[] = {13087 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},13088 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},13089 {}13090};1309113092/* Set Unsolicited Event*/13093static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {13094 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},13095 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},13096 {}13097};1309813099/*13100 * generic initialization of ADC, input mixers and output mixers13101 */13102static struct hda_verb alc662_auto_init_verbs[] = {13103 /*13104 * Unmute ADC and set the default input to mic-in13105 */13106 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},13107 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},1310813109 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback13110 * mixer widget13111 * Note: PASD motherboards uses the Line In 2 as the input for front13112 * panel mic (mic 2)13113 */13114 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */13115 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},13116 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},13117 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},13118 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},13119 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},1312013121 /*13122 * Set up output mixers (0x0c - 0x0f)13123 */13124 /* set vol=0 to output mixers */13125 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},13126 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},13127 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},1312813129 /* set up input amps for analog loopback */13130 /* Amp Indices: DAC = 0, mixer = 1 */13131 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},13132 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},13133 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},13134 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},13135 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},13136 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},131371313813139 /* FIXME: use matrix-type input source selection */13140 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */13141 /* Input mixer */13142 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},13143 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},13144 { }13145};1314613147/* capture mixer elements */13148static struct snd_kcontrol_new alc662_capture_mixer[] = {13149 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),13150 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),13151 {13152 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,13153 /* The multiple "Capture Source" controls confuse alsamixer13154 * So call somewhat different..13155 */13156 /* .name = "Capture Source", */13157 .name = "Input Source",13158 .count = 1,13159 .info = alc662_mux_enum_info,13160 .get = alc662_mux_enum_get,13161 .put = alc662_mux_enum_put,13162 },13163 { } /* end */13164};1316513166static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)13167{13168 unsigned int present;13169 unsigned char bits;1317013171 present = snd_hda_codec_read(codec, 0x14, 0,13172 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;13173 bits = present ? HDA_AMP_MUTE : 0;13174 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,13175 HDA_AMP_MUTE, bits);13176}1317713178static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)13179{13180 unsigned int present;13181 unsigned char bits;1318213183 present = snd_hda_codec_read(codec, 0x1b, 0,13184 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;13185 bits = present ? HDA_AMP_MUTE : 0;13186 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,13187 HDA_AMP_MUTE, bits);13188 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,13189 HDA_AMP_MUTE, bits);13190}1319113192static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,13193 unsigned int res)13194{13195 if ((res >> 26) == ALC880_HP_EVENT)13196 alc662_lenovo_101e_all_automute(codec);13197 if ((res >> 26) == ALC880_FRONT_EVENT)13198 alc662_lenovo_101e_ispeaker_automute(codec);13199}1320013201static void alc662_eeepc_mic_automute(struct hda_codec *codec)13202{13203 unsigned int present;1320413205 present = snd_hda_codec_read(codec, 0x18, 0,13206 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;13207 snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,13208 0x7000 | (0x00 << 8) | (present ? 0 : 0x80));13209 snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,13210 0x7000 | (0x00 << 8) | (present ? 0 : 0x80));13211 snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,13212 0x7000 | (0x01 << 8) | (present ? 0x80 : 0));13213 snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,13214 0x7000 | (0x01 << 8) | (present ? 0x80 : 0));13215}1321613217/* unsolicited event for HP jack sensing */13218static void alc662_eeepc_unsol_event(struct hda_codec *codec,13219 unsigned int res)13220{13221 if ((res >> 26) == ALC880_HP_EVENT)13222 alc262_hippo1_automute( codec );1322313224 if ((res >> 26) == ALC880_MIC_EVENT)13225 alc662_eeepc_mic_automute(codec);13226}1322713228static void alc662_eeepc_inithook(struct hda_codec *codec)13229{13230 alc262_hippo1_automute( codec );13231 alc662_eeepc_mic_automute(codec);13232}1323313234static void alc662_eeepc_ep20_automute(struct hda_codec *codec)13235{13236 unsigned int mute;13237 unsigned int present;1323813239 snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);13240 present = snd_hda_codec_read(codec, 0x14, 0,13241 AC_VERB_GET_PIN_SENSE, 0);13242 present = (present & 0x80000000) != 0;13243 if (present) {13244 /* mute internal speaker */13245 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,13246 HDA_AMP_MUTE, HDA_AMP_MUTE);13247 } else {13248 /* unmute internal speaker if necessary */13249 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);13250 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,13251 HDA_AMP_MUTE, mute);13252 }13253}1325413255/* unsolicited event for HP jack sensing */13256static void alc662_eeepc_ep20_unsol_event(struct hda_codec *codec,13257 unsigned int res)13258{13259 if ((res >> 26) == ALC880_HP_EVENT)13260 alc662_eeepc_ep20_automute(codec);13261}1326213263static void alc662_eeepc_ep20_inithook(struct hda_codec *codec)13264{13265 alc662_eeepc_ep20_automute(codec);13266}1326713268#ifdef CONFIG_SND_HDA_POWER_SAVE13269#define alc662_loopbacks alc880_loopbacks13270#endif132711327213273/* pcm configuration: identiacal with ALC880 */13274#define alc662_pcm_analog_playback alc880_pcm_analog_playback13275#define alc662_pcm_analog_capture alc880_pcm_analog_capture13276#define alc662_pcm_digital_playback alc880_pcm_digital_playback13277#define alc662_pcm_digital_capture alc880_pcm_digital_capture1327813279/*13280 * configuration and preset13281 */13282static const char *alc662_models[ALC662_MODEL_LAST] = {13283 [ALC662_3ST_2ch_DIG] = "3stack-dig",13284 [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig",13285 [ALC662_3ST_6ch] = "3stack-6ch",13286 [ALC662_5ST_DIG] = "6stack-dig",13287 [ALC662_LENOVO_101E] = "lenovo-101e",13288 [ALC662_ASUS_EEEPC_P701] = "eeepc-p701",13289 [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",13290 [ALC662_AUTO] = "auto",13291};1329213293static struct snd_pci_quirk alc662_cfg_tbl[] = {13294 SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),13295 SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),13296 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),13297 {}13298};1329913300static struct alc_config_preset alc662_presets[] = {13301 [ALC662_3ST_2ch_DIG] = {13302 .mixers = { alc662_3ST_2ch_mixer, alc662_capture_mixer },13303 .init_verbs = { alc662_init_verbs },13304 .num_dacs = ARRAY_SIZE(alc662_dac_nids),13305 .dac_nids = alc662_dac_nids,13306 .dig_out_nid = ALC662_DIGOUT_NID,13307 .dig_in_nid = ALC662_DIGIN_NID,13308 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),13309 .channel_mode = alc662_3ST_2ch_modes,13310 .input_mux = &alc662_capture_source,13311 },13312 [ALC662_3ST_6ch_DIG] = {13313 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer,13314 alc662_capture_mixer },13315 .init_verbs = { alc662_init_verbs },13316 .num_dacs = ARRAY_SIZE(alc662_dac_nids),13317 .dac_nids = alc662_dac_nids,13318 .dig_out_nid = ALC662_DIGOUT_NID,13319 .dig_in_nid = ALC662_DIGIN_NID,13320 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),13321 .channel_mode = alc662_3ST_6ch_modes,13322 .need_dac_fix = 1,13323 .input_mux = &alc662_capture_source,13324 },13325 [ALC662_3ST_6ch] = {13326 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer,13327 alc662_capture_mixer },13328 .init_verbs = { alc662_init_verbs },13329 .num_dacs = ARRAY_SIZE(alc662_dac_nids),13330 .dac_nids = alc662_dac_nids,13331 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),13332 .channel_mode = alc662_3ST_6ch_modes,13333 .need_dac_fix = 1,13334 .input_mux = &alc662_capture_source,13335 },13336 [ALC662_5ST_DIG] = {13337 .mixers = { alc662_base_mixer, alc662_chmode_mixer,13338 alc662_capture_mixer },13339 .init_verbs = { alc662_init_verbs },13340 .num_dacs = ARRAY_SIZE(alc662_dac_nids),13341 .dac_nids = alc662_dac_nids,13342 .dig_out_nid = ALC662_DIGOUT_NID,13343 .dig_in_nid = ALC662_DIGIN_NID,13344 .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),13345 .channel_mode = alc662_5stack_modes,13346 .input_mux = &alc662_capture_source,13347 },13348 [ALC662_LENOVO_101E] = {13349 .mixers = { alc662_lenovo_101e_mixer, alc662_capture_mixer },13350 .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },13351 .num_dacs = ARRAY_SIZE(alc662_dac_nids),13352 .dac_nids = alc662_dac_nids,13353 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),13354 .channel_mode = alc662_3ST_2ch_modes,13355 .input_mux = &alc662_lenovo_101e_capture_source,13356 .unsol_event = alc662_lenovo_101e_unsol_event,13357 .init_hook = alc662_lenovo_101e_all_automute,13358 },13359 [ALC662_ASUS_EEEPC_P701] = {13360 .mixers = { alc662_eeepc_p701_mixer, alc662_capture_mixer },13361 .init_verbs = { alc662_init_verbs,13362 alc662_eeepc_sue_init_verbs },13363 .num_dacs = ARRAY_SIZE(alc662_dac_nids),13364 .dac_nids = alc662_dac_nids,13365 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),13366 .channel_mode = alc662_3ST_2ch_modes,13367 .input_mux = &alc662_eeepc_capture_source,13368 .unsol_event = alc662_eeepc_unsol_event,13369 .init_hook = alc662_eeepc_inithook,13370 },13371 [ALC662_ASUS_EEEPC_EP20] = {13372 .mixers = { alc662_eeepc_ep20_mixer, alc662_capture_mixer,13373 alc662_chmode_mixer },13374 .init_verbs = { alc662_init_verbs,13375 alc662_eeepc_ep20_sue_init_verbs },13376 .num_dacs = ARRAY_SIZE(alc662_dac_nids),13377 .dac_nids = alc662_dac_nids,13378 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),13379 .channel_mode = alc662_3ST_6ch_modes,13380 .input_mux = &alc662_lenovo_101e_capture_source,13381 .unsol_event = alc662_eeepc_ep20_unsol_event,13382 .init_hook = alc662_eeepc_ep20_inithook,13383 },1338413385};133861338713388/*13389 * BIOS auto configuration13390 */1339113392/* add playback controls from the parsed DAC table */13393static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,13394 const struct auto_pin_cfg *cfg)13395{13396 char name[32];13397 static const char *chname[4] = {13398 "Front", "Surround", NULL /*CLFE*/, "Side"13399 };13400 hda_nid_t nid;13401 int i, err;1340213403 for (i = 0; i < cfg->line_outs; i++) {13404 if (!spec->multiout.dac_nids[i])13405 continue;13406 nid = alc880_idx_to_dac(i);13407 if (i == 2) {13408 /* Center/LFE */13409 err = add_control(spec, ALC_CTL_WIDGET_VOL,13410 "Center Playback Volume",13411 HDA_COMPOSE_AMP_VAL(nid, 1, 0,13412 HDA_OUTPUT));13413 if (err < 0)13414 return err;13415 err = add_control(spec, ALC_CTL_WIDGET_VOL,13416 "LFE Playback Volume",13417 HDA_COMPOSE_AMP_VAL(nid, 2, 0,13418 HDA_OUTPUT));13419 if (err < 0)13420 return err;13421 err = add_control(spec, ALC_CTL_BIND_MUTE,13422 "Center Playback Switch",13423 HDA_COMPOSE_AMP_VAL(nid, 1, 2,13424 HDA_INPUT));13425 if (err < 0)13426 return err;13427 err = add_control(spec, ALC_CTL_BIND_MUTE,13428 "LFE Playback Switch",13429 HDA_COMPOSE_AMP_VAL(nid, 2, 2,13430 HDA_INPUT));13431 if (err < 0)13432 return err;13433 } else {13434 sprintf(name, "%s Playback Volume", chname[i]);13435 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,13436 HDA_COMPOSE_AMP_VAL(nid, 3, 0,13437 HDA_OUTPUT));13438 if (err < 0)13439 return err;13440 sprintf(name, "%s Playback Switch", chname[i]);13441 err = add_control(spec, ALC_CTL_BIND_MUTE, name,13442 HDA_COMPOSE_AMP_VAL(nid, 3, 2,13443 HDA_INPUT));13444 if (err < 0)13445 return err;13446 }13447 }13448 return 0;13449}1345013451/* add playback controls for speaker and HP outputs */13452static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,13453 const char *pfx)13454{13455 hda_nid_t nid;13456 int err;13457 char name[32];1345813459 if (!pin)13460 return 0;1346113462 if (alc880_is_fixed_pin(pin)) {13463 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));13464 /* printk("DAC nid=%x\n",nid); */13465 /* specify the DAC as the extra output */13466 if (!spec->multiout.hp_nid)13467 spec->multiout.hp_nid = nid;13468 else13469 spec->multiout.extra_out_nid[0] = nid;13470 /* control HP volume/switch on the output mixer amp */13471 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));13472 sprintf(name, "%s Playback Volume", pfx);13473 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,13474 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));13475 if (err < 0)13476 return err;13477 sprintf(name, "%s Playback Switch", pfx);13478 err = add_control(spec, ALC_CTL_BIND_MUTE, name,13479 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));13480 if (err < 0)13481 return err;13482 } else if (alc880_is_multi_pin(pin)) {13483 /* set manual connection */13484 /* we have only a switch on HP-out PIN */13485 sprintf(name, "%s Playback Switch", pfx);13486 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,13487 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));13488 if (err < 0)13489 return err;13490 }13491 return 0;13492}1349313494/* create playback/capture controls for input pins */13495static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec,13496 const struct auto_pin_cfg *cfg)13497{13498 struct hda_input_mux *imux = &spec->private_imux;13499 int i, err, idx;1350013501 for (i = 0; i < AUTO_PIN_LAST; i++) {13502 if (alc880_is_input_pin(cfg->input_pins[i])) {13503 idx = alc880_input_pin_idx(cfg->input_pins[i]);13504 err = new_analog_input(spec, cfg->input_pins[i],13505 auto_pin_cfg_labels[i],13506 idx, 0x0b);13507 if (err < 0)13508 return err;13509 imux->items[imux->num_items].label =13510 auto_pin_cfg_labels[i];13511 imux->items[imux->num_items].index =13512 alc880_input_pin_idx(cfg->input_pins[i]);13513 imux->num_items++;13514 }13515 }13516 return 0;13517}1351813519static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,13520 hda_nid_t nid, int pin_type,13521 int dac_idx)13522{13523 alc_set_pin_output(codec, nid, pin_type);13524 /* need the manual connection? */13525 if (alc880_is_multi_pin(nid)) {13526 struct alc_spec *spec = codec->spec;13527 int idx = alc880_multi_pin_idx(nid);13528 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,13529 AC_VERB_SET_CONNECT_SEL,13530 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));13531 }13532}1353313534static void alc662_auto_init_multi_out(struct hda_codec *codec)13535{13536 struct alc_spec *spec = codec->spec;13537 int i;1353813539 alc_subsystem_id(codec, 0x15, 0x1b, 0x14);13540 for (i = 0; i <= HDA_SIDE; i++) {13541 hda_nid_t nid = spec->autocfg.line_out_pins[i];13542 int pin_type = get_pin_type(spec->autocfg.line_out_type);13543 if (nid)13544 alc662_auto_set_output_and_unmute(codec, nid, pin_type,13545 i);13546 }13547}1354813549static void alc662_auto_init_hp_out(struct hda_codec *codec)13550{13551 struct alc_spec *spec = codec->spec;13552 hda_nid_t pin;1355313554 pin = spec->autocfg.hp_pins[0];13555 if (pin) /* connect to front */13556 /* use dac 0 */13557 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);13558 pin = spec->autocfg.speaker_pins[0];13559 if (pin)13560 alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);13561}1356213563#define alc662_is_input_pin(nid) alc880_is_input_pin(nid)13564#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID1356513566static void alc662_auto_init_analog_input(struct hda_codec *codec)13567{13568 struct alc_spec *spec = codec->spec;13569 int i;1357013571 for (i = 0; i < AUTO_PIN_LAST; i++) {13572 hda_nid_t nid = spec->autocfg.input_pins[i];13573 if (alc662_is_input_pin(nid)) {13574 snd_hda_codec_write(codec, nid, 0,13575 AC_VERB_SET_PIN_WIDGET_CONTROL,13576 (i <= AUTO_PIN_FRONT_MIC ?13577 PIN_VREF80 : PIN_IN));13578 if (nid != ALC662_PIN_CD_NID)13579 snd_hda_codec_write(codec, nid, 0,13580 AC_VERB_SET_AMP_GAIN_MUTE,13581 AMP_OUT_MUTE);13582 }13583 }13584}1358513586static int alc662_parse_auto_config(struct hda_codec *codec)13587{13588 struct alc_spec *spec = codec->spec;13589 int err;13590 static hda_nid_t alc662_ignore[] = { 0x1d, 0 };1359113592 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,13593 alc662_ignore);13594 if (err < 0)13595 return err;13596 if (!spec->autocfg.line_outs)13597 return 0; /* can't find valid BIOS pin config */1359813599 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);13600 if (err < 0)13601 return err;13602 err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg);13603 if (err < 0)13604 return err;13605 err = alc662_auto_create_extra_out(spec,13606 spec->autocfg.speaker_pins[0],13607 "Speaker");13608 if (err < 0)13609 return err;13610 err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],13611 "Headphone");13612 if (err < 0)13613 return err;13614 err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg);13615 if (err < 0)13616 return err;1361713618 spec->multiout.max_channels = spec->multiout.num_dacs * 2;1361913620 if (spec->autocfg.dig_out_pin)13621 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;1362213623 if (spec->kctl_alloc)13624 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;1362513626 spec->num_mux_defs = 1;13627 spec->input_mux = &spec->private_imux;1362813629 spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs;13630 spec->mixers[spec->num_mixers] = alc662_capture_mixer;13631 spec->num_mixers++;13632 return 1;13633}1363413635/* additional initialization for auto-configuration model */13636static void alc662_auto_init(struct hda_codec *codec)13637{13638 struct alc_spec *spec = codec->spec;13639 alc662_auto_init_multi_out(codec);13640 alc662_auto_init_hp_out(codec);13641 alc662_auto_init_analog_input(codec);13642 if (spec->unsol_event)13643 alc_sku_automute(codec);13644}1364513646static int patch_alc662(struct hda_codec *codec)13647{13648 struct alc_spec *spec;13649 int err, board_config;1365013651 spec = kzalloc(sizeof(*spec), GFP_KERNEL);13652 if (!spec)13653 return -ENOMEM;1365413655 codec->spec = spec;1365613657 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,13658 alc662_models,13659 alc662_cfg_tbl);13660 if (board_config < 0) {13661 printk(KERN_INFO "hda_codec: Unknown model for ALC662, "13662 "trying auto-probe from BIOS...\n");13663 board_config = ALC662_AUTO;13664 }1366513666 if (board_config == ALC662_AUTO) {13667 /* automatic parse from the BIOS config */13668 err = alc662_parse_auto_config(codec);13669 if (err < 0) {13670 alc_free(codec);13671 return err;13672 } else if (!err) {13673 printk(KERN_INFO13674 "hda_codec: Cannot set up configuration "13675 "from BIOS. Using base mode...\n");13676 board_config = ALC662_3ST_2ch_DIG;13677 }13678 }1367913680 if (board_config != ALC662_AUTO)13681 setup_preset(spec, &alc662_presets[board_config]);1368213683 spec->stream_name_analog = "ALC662 Analog";13684 spec->stream_analog_playback = &alc662_pcm_analog_playback;13685 spec->stream_analog_capture = &alc662_pcm_analog_capture;1368613687 spec->stream_name_digital = "ALC662 Digital";13688 spec->stream_digital_playback = &alc662_pcm_digital_playback;13689 spec->stream_digital_capture = &alc662_pcm_digital_capture;1369013691 spec->adc_nids = alc662_adc_nids;13692 spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);13693 spec->capsrc_nids = alc662_capsrc_nids;1369413695 spec->vmaster_nid = 0x02;1369613697 codec->patch_ops = alc_patch_ops;13698 if (board_config == ALC662_AUTO)13699 spec->init_hook = alc662_auto_init;13700#ifdef CONFIG_SND_HDA_POWER_SAVE13701 if (!spec->loopback.amplist)13702 spec->loopback.amplist = alc662_loopbacks;13703#endif1370413705 return 0;13706}1370713708/*13709 * patch entries13710 */13711struct hda_codec_preset snd_hda_preset_realtek[] = {13712 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },13713 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },13714 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },13715 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },13716 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },13717 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",13718 .patch = patch_alc861 },13719 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },13720 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },13721 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },13722 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",13723 .patch = patch_alc883 },13724 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",13725 .patch = patch_alc662 },13726 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },13727 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },13728 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },13729 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },13730 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },13731 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },13732 {} /* terminator */13733};