patch_realtek.c revision 38baf5ad8b7d24be16a2cf0e4c1d7429aeb4aa45
1/* 2 * Universal Interface for Intel High Definition Audio Codec 3 * 4 * HD audio interface patch for ALC 260/880/882 codecs 5 * 6 * Copyright (c) 2004 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 modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This driver is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26#include <sound/driver.h> 27#include <linux/init.h> 28#include <linux/delay.h> 29#include <linux/slab.h> 30#include <linux/pci.h> 31#include <sound/core.h> 32#include "hda_codec.h" 33#include "hda_local.h" 34 35#define ALC880_FRONT_EVENT 0x01 36#define ALC880_DCVOL_EVENT 0x02 37#define ALC880_HP_EVENT 0x04 38#define ALC880_MIC_EVENT 0x08 39 40/* ALC880 board config type */ 41enum { 42 ALC880_3ST, 43 ALC880_3ST_DIG, 44 ALC880_5ST, 45 ALC880_5ST_DIG, 46 ALC880_W810, 47 ALC880_Z71V, 48 ALC880_6ST, 49 ALC880_6ST_DIG, 50 ALC880_F1734, 51 ALC880_ASUS, 52 ALC880_ASUS_DIG, 53 ALC880_ASUS_W1V, 54 ALC880_ASUS_DIG2, 55 ALC880_FUJITSU, 56 ALC880_UNIWILL_DIG, 57 ALC880_UNIWILL, 58 ALC880_UNIWILL_P53, 59 ALC880_CLEVO, 60 ALC880_TCL_S700, 61 ALC880_LG, 62 ALC880_LG_LW, 63#ifdef CONFIG_SND_DEBUG 64 ALC880_TEST, 65#endif 66 ALC880_AUTO, 67 ALC880_MODEL_LAST /* last tag */ 68}; 69 70/* ALC260 models */ 71enum { 72 ALC260_BASIC, 73 ALC260_HP, 74 ALC260_HP_3013, 75 ALC260_FUJITSU_S702X, 76 ALC260_ACER, 77 ALC260_WILL, 78 ALC260_REPLACER_672V, 79#ifdef CONFIG_SND_DEBUG 80 ALC260_TEST, 81#endif 82 ALC260_AUTO, 83 ALC260_MODEL_LAST /* last tag */ 84}; 85 86/* ALC262 models */ 87enum { 88 ALC262_BASIC, 89 ALC262_HIPPO, 90 ALC262_HIPPO_1, 91 ALC262_FUJITSU, 92 ALC262_HP_BPC, 93 ALC262_HP_BPC_D7000_WL, 94 ALC262_HP_BPC_D7000_WF, 95 ALC262_BENQ_ED8, 96 ALC262_SONY_ASSAMD, 97 ALC262_BENQ_T31, 98 ALC262_AUTO, 99 ALC262_MODEL_LAST /* last tag */ 100}; 101 102/* ALC268 models */ 103enum { 104 ALC268_3ST, 105 ALC268_TOSHIBA, 106 ALC268_ACER, 107 ALC268_AUTO, 108 ALC268_MODEL_LAST /* last tag */ 109}; 110 111/* ALC861 models */ 112enum { 113 ALC861_3ST, 114 ALC660_3ST, 115 ALC861_3ST_DIG, 116 ALC861_6ST_DIG, 117 ALC861_UNIWILL_M31, 118 ALC861_TOSHIBA, 119 ALC861_ASUS, 120 ALC861_ASUS_LAPTOP, 121 ALC861_AUTO, 122 ALC861_MODEL_LAST, 123}; 124 125/* ALC861-VD models */ 126enum { 127 ALC660VD_3ST, 128 ALC660VD_3ST_DIG, 129 ALC861VD_3ST, 130 ALC861VD_3ST_DIG, 131 ALC861VD_6ST_DIG, 132 ALC861VD_LENOVO, 133 ALC861VD_DALLAS, 134 ALC861VD_HP, 135 ALC861VD_AUTO, 136 ALC861VD_MODEL_LAST, 137}; 138 139/* ALC662 models */ 140enum { 141 ALC662_3ST_2ch_DIG, 142 ALC662_3ST_6ch_DIG, 143 ALC662_3ST_6ch, 144 ALC662_5ST_DIG, 145 ALC662_LENOVO_101E, 146 ALC662_AUTO, 147 ALC662_MODEL_LAST, 148}; 149 150/* ALC882 models */ 151enum { 152 ALC882_3ST_DIG, 153 ALC882_6ST_DIG, 154 ALC882_ARIMA, 155 ALC882_W2JC, 156 ALC882_TARGA, 157 ALC882_ASUS_A7J, 158 ALC885_MACPRO, 159 ALC885_IMAC24, 160 ALC882_AUTO, 161 ALC882_MODEL_LAST, 162}; 163 164/* ALC883 models */ 165enum { 166 ALC883_3ST_2ch_DIG, 167 ALC883_3ST_6ch_DIG, 168 ALC883_3ST_6ch, 169 ALC883_6ST_DIG, 170 ALC883_TARGA_DIG, 171 ALC883_TARGA_2ch_DIG, 172 ALC883_ACER, 173 ALC883_ACER_ASPIRE, 174 ALC883_MEDION, 175 ALC883_MEDION_MD2, 176 ALC883_LAPTOP_EAPD, 177 ALC883_LENOVO_101E_2ch, 178 ALC883_LENOVO_NB0763, 179 ALC888_LENOVO_MS7195_DIG, 180 ALC888_6ST_HP, 181 ALC888_3ST_HP, 182 ALC883_AUTO, 183 ALC883_MODEL_LAST, 184}; 185 186/* for GPIO Poll */ 187#define GPIO_MASK 0x03 188 189struct alc_spec { 190 /* codec parameterization */ 191 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ 192 unsigned int num_mixers; 193 194 const struct hda_verb *init_verbs[5]; /* initialization verbs 195 * don't forget NULL 196 * termination! 197 */ 198 unsigned int num_init_verbs; 199 200 char *stream_name_analog; /* analog PCM stream */ 201 struct hda_pcm_stream *stream_analog_playback; 202 struct hda_pcm_stream *stream_analog_capture; 203 204 char *stream_name_digital; /* digital PCM stream */ 205 struct hda_pcm_stream *stream_digital_playback; 206 struct hda_pcm_stream *stream_digital_capture; 207 208 /* playback */ 209 struct hda_multi_out multiout; /* playback set-up 210 * max_channels, dacs must be set 211 * dig_out_nid and hp_nid are optional 212 */ 213 214 /* capture */ 215 unsigned int num_adc_nids; 216 hda_nid_t *adc_nids; 217 hda_nid_t dig_in_nid; /* digital-in NID; optional */ 218 219 /* capture source */ 220 unsigned int num_mux_defs; 221 const struct hda_input_mux *input_mux; 222 unsigned int cur_mux[3]; 223 224 /* channel model */ 225 const struct hda_channel_mode *channel_mode; 226 int num_channel_mode; 227 int need_dac_fix; 228 229 /* PCM information */ 230 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ 231 232 /* dynamic controls, init_verbs and input_mux */ 233 struct auto_pin_cfg autocfg; 234 unsigned int num_kctl_alloc, num_kctl_used; 235 struct snd_kcontrol_new *kctl_alloc; 236 struct hda_input_mux private_imux; 237 hda_nid_t private_dac_nids[5]; 238 239 /* hooks */ 240 void (*init_hook)(struct hda_codec *codec); 241 void (*unsol_event)(struct hda_codec *codec, unsigned int res); 242 243 /* for pin sensing */ 244 unsigned int sense_updated: 1; 245 unsigned int jack_present: 1; 246 247#ifdef CONFIG_SND_HDA_POWER_SAVE 248 struct hda_loopback_check loopback; 249#endif 250}; 251 252/* 253 * configuration template - to be copied to the spec instance 254 */ 255struct alc_config_preset { 256 struct snd_kcontrol_new *mixers[5]; /* should be identical size 257 * with spec 258 */ 259 const struct hda_verb *init_verbs[5]; 260 unsigned int num_dacs; 261 hda_nid_t *dac_nids; 262 hda_nid_t dig_out_nid; /* optional */ 263 hda_nid_t hp_nid; /* optional */ 264 unsigned int num_adc_nids; 265 hda_nid_t *adc_nids; 266 hda_nid_t dig_in_nid; 267 unsigned int num_channel_mode; 268 const struct hda_channel_mode *channel_mode; 269 int need_dac_fix; 270 unsigned int num_mux_defs; 271 const struct hda_input_mux *input_mux; 272 void (*unsol_event)(struct hda_codec *, unsigned int); 273 void (*init_hook)(struct hda_codec *); 274#ifdef CONFIG_SND_HDA_POWER_SAVE 275 struct hda_amp_list *loopbacks; 276#endif 277}; 278 279 280/* 281 * input MUX handling 282 */ 283static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, 284 struct snd_ctl_elem_info *uinfo) 285{ 286 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 287 struct alc_spec *spec = codec->spec; 288 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id); 289 if (mux_idx >= spec->num_mux_defs) 290 mux_idx = 0; 291 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); 292} 293 294static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, 295 struct snd_ctl_elem_value *ucontrol) 296{ 297 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 298 struct alc_spec *spec = codec->spec; 299 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 300 301 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; 302 return 0; 303} 304 305static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, 306 struct snd_ctl_elem_value *ucontrol) 307{ 308 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 309 struct alc_spec *spec = codec->spec; 310 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 311 unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; 312 return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol, 313 spec->adc_nids[adc_idx], 314 &spec->cur_mux[adc_idx]); 315} 316 317 318/* 319 * channel mode setting 320 */ 321static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, 322 struct snd_ctl_elem_info *uinfo) 323{ 324 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 325 struct alc_spec *spec = codec->spec; 326 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, 327 spec->num_channel_mode); 328} 329 330static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, 331 struct snd_ctl_elem_value *ucontrol) 332{ 333 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 334 struct alc_spec *spec = codec->spec; 335 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, 336 spec->num_channel_mode, 337 spec->multiout.max_channels); 338} 339 340static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, 341 struct snd_ctl_elem_value *ucontrol) 342{ 343 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 344 struct alc_spec *spec = codec->spec; 345 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, 346 spec->num_channel_mode, 347 &spec->multiout.max_channels); 348 if (err >= 0 && spec->need_dac_fix) 349 spec->multiout.num_dacs = spec->multiout.max_channels / 2; 350 return err; 351} 352 353/* 354 * Control the mode of pin widget settings via the mixer. "pc" is used 355 * instead of "%" to avoid consequences of accidently treating the % as 356 * being part of a format specifier. Maximum allowed length of a value is 357 * 63 characters plus NULL terminator. 358 * 359 * Note: some retasking pin complexes seem to ignore requests for input 360 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these 361 * are requested. Therefore order this list so that this behaviour will not 362 * cause problems when mixer clients move through the enum sequentially. 363 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of 364 * March 2006. 365 */ 366static char *alc_pin_mode_names[] = { 367 "Mic 50pc bias", "Mic 80pc bias", 368 "Line in", "Line out", "Headphone out", 369}; 370static unsigned char alc_pin_mode_values[] = { 371 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, 372}; 373/* The control can present all 5 options, or it can limit the options based 374 * in the pin being assumed to be exclusively an input or an output pin. In 375 * addition, "input" pins may or may not process the mic bias option 376 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to 377 * accept requests for bias as of chip versions up to March 2006) and/or 378 * wiring in the computer. 379 */ 380#define ALC_PIN_DIR_IN 0x00 381#define ALC_PIN_DIR_OUT 0x01 382#define ALC_PIN_DIR_INOUT 0x02 383#define ALC_PIN_DIR_IN_NOMICBIAS 0x03 384#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04 385 386/* Info about the pin modes supported by the different pin direction modes. 387 * For each direction the minimum and maximum values are given. 388 */ 389static signed char alc_pin_mode_dir_info[5][2] = { 390 { 0, 2 }, /* ALC_PIN_DIR_IN */ 391 { 3, 4 }, /* ALC_PIN_DIR_OUT */ 392 { 0, 4 }, /* ALC_PIN_DIR_INOUT */ 393 { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */ 394 { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */ 395}; 396#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) 397#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) 398#define alc_pin_mode_n_items(_dir) \ 399 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1) 400 401static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, 402 struct snd_ctl_elem_info *uinfo) 403{ 404 unsigned int item_num = uinfo->value.enumerated.item; 405 unsigned char dir = (kcontrol->private_value >> 16) & 0xff; 406 407 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 408 uinfo->count = 1; 409 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir); 410 411 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir)) 412 item_num = alc_pin_mode_min(dir); 413 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]); 414 return 0; 415} 416 417static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, 418 struct snd_ctl_elem_value *ucontrol) 419{ 420 unsigned int i; 421 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 422 hda_nid_t nid = kcontrol->private_value & 0xffff; 423 unsigned char dir = (kcontrol->private_value >> 16) & 0xff; 424 long *valp = ucontrol->value.integer.value; 425 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, 426 AC_VERB_GET_PIN_WIDGET_CONTROL, 427 0x00); 428 429 /* Find enumerated value for current pinctl setting */ 430 i = alc_pin_mode_min(dir); 431 while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir)) 432 i++; 433 *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir); 434 return 0; 435} 436 437static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, 438 struct snd_ctl_elem_value *ucontrol) 439{ 440 signed int change; 441 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 442 hda_nid_t nid = kcontrol->private_value & 0xffff; 443 unsigned char dir = (kcontrol->private_value >> 16) & 0xff; 444 long val = *ucontrol->value.integer.value; 445 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, 446 AC_VERB_GET_PIN_WIDGET_CONTROL, 447 0x00); 448 449 if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) 450 val = alc_pin_mode_min(dir); 451 452 change = pinctl != alc_pin_mode_values[val]; 453 if (change) { 454 /* Set pin mode to that requested */ 455 snd_hda_codec_write_cache(codec, nid, 0, 456 AC_VERB_SET_PIN_WIDGET_CONTROL, 457 alc_pin_mode_values[val]); 458 459 /* Also enable the retasking pin's input/output as required 460 * for the requested pin mode. Enum values of 2 or less are 461 * input modes. 462 * 463 * Dynamically switching the input/output buffers probably 464 * reduces noise slightly (particularly on input) so we'll 465 * do it. However, having both input and output buffers 466 * enabled simultaneously doesn't seem to be problematic if 467 * this turns out to be necessary in the future. 468 */ 469 if (val <= 2) { 470 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, 471 HDA_AMP_MUTE, HDA_AMP_MUTE); 472 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, 473 HDA_AMP_MUTE, 0); 474 } else { 475 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, 476 HDA_AMP_MUTE, HDA_AMP_MUTE); 477 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, 478 HDA_AMP_MUTE, 0); 479 } 480 } 481 return change; 482} 483 484#define ALC_PIN_MODE(xname, nid, dir) \ 485 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 486 .info = alc_pin_mode_info, \ 487 .get = alc_pin_mode_get, \ 488 .put = alc_pin_mode_put, \ 489 .private_value = nid | (dir<<16) } 490 491/* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged 492 * together using a mask with more than one bit set. This control is 493 * currently used only by the ALC260 test model. At this stage they are not 494 * needed for any "production" models. 495 */ 496#ifdef CONFIG_SND_DEBUG 497#define alc_gpio_data_info snd_ctl_boolean_mono_info 498 499static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, 500 struct snd_ctl_elem_value *ucontrol) 501{ 502 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 503 hda_nid_t nid = kcontrol->private_value & 0xffff; 504 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 505 long *valp = ucontrol->value.integer.value; 506 unsigned int val = snd_hda_codec_read(codec, nid, 0, 507 AC_VERB_GET_GPIO_DATA, 0x00); 508 509 *valp = (val & mask) != 0; 510 return 0; 511} 512static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, 513 struct snd_ctl_elem_value *ucontrol) 514{ 515 signed int change; 516 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 517 hda_nid_t nid = kcontrol->private_value & 0xffff; 518 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 519 long val = *ucontrol->value.integer.value; 520 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, 521 AC_VERB_GET_GPIO_DATA, 522 0x00); 523 524 /* Set/unset the masked GPIO bit(s) as needed */ 525 change = (val == 0 ? 0 : mask) != (gpio_data & mask); 526 if (val == 0) 527 gpio_data &= ~mask; 528 else 529 gpio_data |= mask; 530 snd_hda_codec_write_cache(codec, nid, 0, 531 AC_VERB_SET_GPIO_DATA, gpio_data); 532 533 return change; 534} 535#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ 536 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 537 .info = alc_gpio_data_info, \ 538 .get = alc_gpio_data_get, \ 539 .put = alc_gpio_data_put, \ 540 .private_value = nid | (mask<<16) } 541#endif /* CONFIG_SND_DEBUG */ 542 543/* A switch control to allow the enabling of the digital IO pins on the 544 * ALC260. This is incredibly simplistic; the intention of this control is 545 * to provide something in the test model allowing digital outputs to be 546 * identified if present. If models are found which can utilise these 547 * outputs a more complete mixer control can be devised for those models if 548 * necessary. 549 */ 550#ifdef CONFIG_SND_DEBUG 551#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info 552 553static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, 554 struct snd_ctl_elem_value *ucontrol) 555{ 556 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 557 hda_nid_t nid = kcontrol->private_value & 0xffff; 558 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 559 long *valp = ucontrol->value.integer.value; 560 unsigned int val = snd_hda_codec_read(codec, nid, 0, 561 AC_VERB_GET_DIGI_CONVERT, 0x00); 562 563 *valp = (val & mask) != 0; 564 return 0; 565} 566static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, 567 struct snd_ctl_elem_value *ucontrol) 568{ 569 signed int change; 570 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 571 hda_nid_t nid = kcontrol->private_value & 0xffff; 572 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 573 long val = *ucontrol->value.integer.value; 574 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, 575 AC_VERB_GET_DIGI_CONVERT, 576 0x00); 577 578 /* Set/unset the masked control bit(s) as needed */ 579 change = (val == 0 ? 0 : mask) != (ctrl_data & mask); 580 if (val==0) 581 ctrl_data &= ~mask; 582 else 583 ctrl_data |= mask; 584 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, 585 ctrl_data); 586 587 return change; 588} 589#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ 590 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 591 .info = alc_spdif_ctrl_info, \ 592 .get = alc_spdif_ctrl_get, \ 593 .put = alc_spdif_ctrl_put, \ 594 .private_value = nid | (mask<<16) } 595#endif /* CONFIG_SND_DEBUG */ 596 597/* 598 * set up from the preset table 599 */ 600static void setup_preset(struct alc_spec *spec, 601 const struct alc_config_preset *preset) 602{ 603 int i; 604 605 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) 606 spec->mixers[spec->num_mixers++] = preset->mixers[i]; 607 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; 608 i++) 609 spec->init_verbs[spec->num_init_verbs++] = 610 preset->init_verbs[i]; 611 612 spec->channel_mode = preset->channel_mode; 613 spec->num_channel_mode = preset->num_channel_mode; 614 spec->need_dac_fix = preset->need_dac_fix; 615 616 spec->multiout.max_channels = spec->channel_mode[0].channels; 617 618 spec->multiout.num_dacs = preset->num_dacs; 619 spec->multiout.dac_nids = preset->dac_nids; 620 spec->multiout.dig_out_nid = preset->dig_out_nid; 621 spec->multiout.hp_nid = preset->hp_nid; 622 623 spec->num_mux_defs = preset->num_mux_defs; 624 if (!spec->num_mux_defs) 625 spec->num_mux_defs = 1; 626 spec->input_mux = preset->input_mux; 627 628 spec->num_adc_nids = preset->num_adc_nids; 629 spec->adc_nids = preset->adc_nids; 630 spec->dig_in_nid = preset->dig_in_nid; 631 632 spec->unsol_event = preset->unsol_event; 633 spec->init_hook = preset->init_hook; 634#ifdef CONFIG_SND_HDA_POWER_SAVE 635 spec->loopback.amplist = preset->loopbacks; 636#endif 637} 638 639/* Enable GPIO mask and set output */ 640static struct hda_verb alc_gpio1_init_verbs[] = { 641 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 642 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 643 {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, 644 { } 645}; 646 647static struct hda_verb alc_gpio2_init_verbs[] = { 648 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 649 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 650 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, 651 { } 652}; 653 654static struct hda_verb alc_gpio3_init_verbs[] = { 655 {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 656 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 657 {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 658 { } 659}; 660 661/* 32-bit subsystem ID for BIOS loading in HD Audio codec. 662 * 31 ~ 16 : Manufacture ID 663 * 15 ~ 8 : SKU ID 664 * 7 ~ 0 : Assembly ID 665 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36 666 */ 667static void alc_subsystem_id(struct hda_codec *codec, 668 unsigned int porta, unsigned int porte, 669 unsigned int portd) 670{ 671 unsigned int ass, tmp; 672 673 ass = codec->subsystem_id; 674 if (!(ass & 1)) 675 return; 676 677 /* Override */ 678 tmp = (ass & 0x38) >> 3; /* external Amp control */ 679 switch (tmp) { 680 case 1: 681 snd_hda_sequence_write(codec, alc_gpio1_init_verbs); 682 break; 683 case 3: 684 snd_hda_sequence_write(codec, alc_gpio2_init_verbs); 685 break; 686 case 7: 687 snd_hda_sequence_write(codec, alc_gpio3_init_verbs); 688 break; 689 case 5: 690 switch (codec->vendor_id) { 691 case 0x10ec0862: 692 case 0x10ec0660: 693 case 0x10ec0662: 694 case 0x10ec0267: 695 case 0x10ec0268: 696 snd_hda_codec_write(codec, 0x14, 0, 697 AC_VERB_SET_EAPD_BTLENABLE, 2); 698 snd_hda_codec_write(codec, 0x15, 0, 699 AC_VERB_SET_EAPD_BTLENABLE, 2); 700 return; 701 } 702 case 6: 703 if (ass & 4) { /* bit 2 : 0 = Desktop, 1 = Laptop */ 704 hda_nid_t port = 0; 705 tmp = (ass & 0x1800) >> 11; 706 switch (tmp) { 707 case 0: port = porta; break; 708 case 1: port = porte; break; 709 case 2: port = portd; break; 710 } 711 if (port) 712 snd_hda_codec_write(codec, port, 0, 713 AC_VERB_SET_EAPD_BTLENABLE, 714 2); 715 } 716 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); 717 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, 718 (tmp == 5 ? 0x3040 : 0x3050)); 719 break; 720 } 721} 722 723/* 724 * Fix-up pin default configurations 725 */ 726 727struct alc_pincfg { 728 hda_nid_t nid; 729 u32 val; 730}; 731 732static void alc_fix_pincfg(struct hda_codec *codec, 733 const struct snd_pci_quirk *quirk, 734 const struct alc_pincfg **pinfix) 735{ 736 const struct alc_pincfg *cfg; 737 738 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); 739 if (!quirk) 740 return; 741 742 cfg = pinfix[quirk->value]; 743 for (; cfg->nid; cfg++) { 744 int i; 745 u32 val = cfg->val; 746 for (i = 0; i < 4; i++) { 747 snd_hda_codec_write(codec, cfg->nid, 0, 748 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i, 749 val & 0xff); 750 val >>= 8; 751 } 752 } 753} 754 755/* 756 * ALC880 3-stack model 757 * 758 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) 759 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, 760 * F-Mic = 0x1b, HP = 0x19 761 */ 762 763static hda_nid_t alc880_dac_nids[4] = { 764 /* front, rear, clfe, rear_surr */ 765 0x02, 0x05, 0x04, 0x03 766}; 767 768static hda_nid_t alc880_adc_nids[3] = { 769 /* ADC0-2 */ 770 0x07, 0x08, 0x09, 771}; 772 773/* The datasheet says the node 0x07 is connected from inputs, 774 * but it shows zero connection in the real implementation on some devices. 775 * Note: this is a 915GAV bug, fixed on 915GLV 776 */ 777static hda_nid_t alc880_adc_nids_alt[2] = { 778 /* ADC1-2 */ 779 0x08, 0x09, 780}; 781 782#define ALC880_DIGOUT_NID 0x06 783#define ALC880_DIGIN_NID 0x0a 784 785static struct hda_input_mux alc880_capture_source = { 786 .num_items = 4, 787 .items = { 788 { "Mic", 0x0 }, 789 { "Front Mic", 0x3 }, 790 { "Line", 0x2 }, 791 { "CD", 0x4 }, 792 }, 793}; 794 795/* channel source setting (2/6 channel selection for 3-stack) */ 796/* 2ch mode */ 797static struct hda_verb alc880_threestack_ch2_init[] = { 798 /* set line-in to input, mute it */ 799 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 800 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 801 /* set mic-in to input vref 80%, mute it */ 802 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 803 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 804 { } /* end */ 805}; 806 807/* 6ch mode */ 808static struct hda_verb alc880_threestack_ch6_init[] = { 809 /* set line-in to output, unmute it */ 810 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 811 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 812 /* set mic-in to output, unmute it */ 813 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 814 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 815 { } /* end */ 816}; 817 818static struct hda_channel_mode alc880_threestack_modes[2] = { 819 { 2, alc880_threestack_ch2_init }, 820 { 6, alc880_threestack_ch6_init }, 821}; 822 823static struct snd_kcontrol_new alc880_three_stack_mixer[] = { 824 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 825 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 826 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 827 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), 828 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 829 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 830 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 831 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 832 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 833 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 834 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 835 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 836 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 837 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 838 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), 839 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), 840 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 841 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 842 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), 843 { 844 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 845 .name = "Channel Mode", 846 .info = alc_ch_mode_info, 847 .get = alc_ch_mode_get, 848 .put = alc_ch_mode_put, 849 }, 850 { } /* end */ 851}; 852 853/* capture mixer elements */ 854static struct snd_kcontrol_new alc880_capture_mixer[] = { 855 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), 856 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), 857 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), 858 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), 859 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), 860 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), 861 { 862 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 863 /* The multiple "Capture Source" controls confuse alsamixer 864 * So call somewhat different.. 865 * FIXME: the controls appear in the "playback" view! 866 */ 867 /* .name = "Capture Source", */ 868 .name = "Input Source", 869 .count = 3, 870 .info = alc_mux_enum_info, 871 .get = alc_mux_enum_get, 872 .put = alc_mux_enum_put, 873 }, 874 { } /* end */ 875}; 876 877/* capture mixer elements (in case NID 0x07 not available) */ 878static struct snd_kcontrol_new alc880_capture_alt_mixer[] = { 879 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 880 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 881 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 882 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 883 { 884 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 885 /* The multiple "Capture Source" controls confuse alsamixer 886 * So call somewhat different.. 887 * FIXME: the controls appear in the "playback" view! 888 */ 889 /* .name = "Capture Source", */ 890 .name = "Input Source", 891 .count = 2, 892 .info = alc_mux_enum_info, 893 .get = alc_mux_enum_get, 894 .put = alc_mux_enum_put, 895 }, 896 { } /* end */ 897}; 898 899 900 901/* 902 * ALC880 5-stack model 903 * 904 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), 905 * Side = 0x02 (0xd) 906 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 907 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 908 */ 909 910/* additional mixers to alc880_three_stack_mixer */ 911static struct snd_kcontrol_new alc880_five_stack_mixer[] = { 912 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 913 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), 914 { } /* end */ 915}; 916 917/* channel source setting (6/8 channel selection for 5-stack) */ 918/* 6ch mode */ 919static struct hda_verb alc880_fivestack_ch6_init[] = { 920 /* set line-in to input, mute it */ 921 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 922 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 923 { } /* end */ 924}; 925 926/* 8ch mode */ 927static struct hda_verb alc880_fivestack_ch8_init[] = { 928 /* set line-in to output, unmute it */ 929 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 930 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 931 { } /* end */ 932}; 933 934static struct hda_channel_mode alc880_fivestack_modes[2] = { 935 { 6, alc880_fivestack_ch6_init }, 936 { 8, alc880_fivestack_ch8_init }, 937}; 938 939 940/* 941 * ALC880 6-stack model 942 * 943 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), 944 * Side = 0x05 (0x0f) 945 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, 946 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b 947 */ 948 949static hda_nid_t alc880_6st_dac_nids[4] = { 950 /* front, rear, clfe, rear_surr */ 951 0x02, 0x03, 0x04, 0x05 952}; 953 954static struct hda_input_mux alc880_6stack_capture_source = { 955 .num_items = 4, 956 .items = { 957 { "Mic", 0x0 }, 958 { "Front Mic", 0x1 }, 959 { "Line", 0x2 }, 960 { "CD", 0x4 }, 961 }, 962}; 963 964/* fixed 8-channels */ 965static struct hda_channel_mode alc880_sixstack_modes[1] = { 966 { 8, NULL }, 967}; 968 969static struct snd_kcontrol_new alc880_six_stack_mixer[] = { 970 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 971 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 972 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 973 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 974 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 975 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 976 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 977 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 978 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 979 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 980 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 981 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 982 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 983 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 984 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 985 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 986 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 987 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 988 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 989 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 990 { 991 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 992 .name = "Channel Mode", 993 .info = alc_ch_mode_info, 994 .get = alc_ch_mode_get, 995 .put = alc_ch_mode_put, 996 }, 997 { } /* end */ 998}; 999 1000 1001/* 1002 * ALC880 W810 model 1003 * 1004 * W810 has rear IO for: 1005 * Front (DAC 02) 1006 * Surround (DAC 03) 1007 * Center/LFE (DAC 04) 1008 * Digital out (06) 1009 * 1010 * The system also has a pair of internal speakers, and a headphone jack. 1011 * These are both connected to Line2 on the codec, hence to DAC 02. 1012 * 1013 * There is a variable resistor to control the speaker or headphone 1014 * volume. This is a hardware-only device without a software API. 1015 * 1016 * Plugging headphones in will disable the internal speakers. This is 1017 * implemented in hardware, not via the driver using jack sense. In 1018 * a similar fashion, plugging into the rear socket marked "front" will 1019 * disable both the speakers and headphones. 1020 * 1021 * For input, there's a microphone jack, and an "audio in" jack. 1022 * These may not do anything useful with this driver yet, because I 1023 * haven't setup any initialization verbs for these yet... 1024 */ 1025 1026static hda_nid_t alc880_w810_dac_nids[3] = { 1027 /* front, rear/surround, clfe */ 1028 0x02, 0x03, 0x04 1029}; 1030 1031/* fixed 6 channels */ 1032static struct hda_channel_mode alc880_w810_modes[1] = { 1033 { 6, NULL } 1034}; 1035 1036/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ 1037static struct snd_kcontrol_new alc880_w810_base_mixer[] = { 1038 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1039 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1040 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1041 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 1042 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1043 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1044 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1045 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1046 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 1047 { } /* end */ 1048}; 1049 1050 1051/* 1052 * Z710V model 1053 * 1054 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) 1055 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), 1056 * Line = 0x1a 1057 */ 1058 1059static hda_nid_t alc880_z71v_dac_nids[1] = { 1060 0x02 1061}; 1062#define ALC880_Z71V_HP_DAC 0x03 1063 1064/* fixed 2 channels */ 1065static struct hda_channel_mode alc880_2_jack_modes[1] = { 1066 { 2, NULL } 1067}; 1068 1069static struct snd_kcontrol_new alc880_z71v_mixer[] = { 1070 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1071 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1072 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1073 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), 1074 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1075 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1076 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1077 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1078 { } /* end */ 1079}; 1080 1081 1082/* FIXME! */ 1083/* 1084 * ALC880 F1734 model 1085 * 1086 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d) 1087 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18 1088 */ 1089 1090static hda_nid_t alc880_f1734_dac_nids[1] = { 1091 0x03 1092}; 1093#define ALC880_F1734_HP_DAC 0x02 1094 1095static struct snd_kcontrol_new alc880_f1734_mixer[] = { 1096 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1097 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), 1098 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1099 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT), 1100 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1101 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1102 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1103 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1104 { } /* end */ 1105}; 1106 1107 1108/* FIXME! */ 1109/* 1110 * ALC880 ASUS model 1111 * 1112 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) 1113 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, 1114 * Mic = 0x18, Line = 0x1a 1115 */ 1116 1117#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */ 1118#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */ 1119 1120static struct snd_kcontrol_new alc880_asus_mixer[] = { 1121 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1122 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1123 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1124 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 1125 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1126 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1127 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1128 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1129 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1130 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1131 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 1132 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 1133 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1134 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1135 { 1136 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1137 .name = "Channel Mode", 1138 .info = alc_ch_mode_info, 1139 .get = alc_ch_mode_get, 1140 .put = alc_ch_mode_put, 1141 }, 1142 { } /* end */ 1143}; 1144 1145/* FIXME! */ 1146/* 1147 * ALC880 ASUS W1V model 1148 * 1149 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) 1150 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, 1151 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b 1152 */ 1153 1154/* additional mixers to alc880_asus_mixer */ 1155static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { 1156 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT), 1157 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT), 1158 { } /* end */ 1159}; 1160 1161/* additional mixers to alc880_asus_mixer */ 1162static struct snd_kcontrol_new alc880_pcbeep_mixer[] = { 1163 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 1164 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 1165 { } /* end */ 1166}; 1167 1168/* TCL S700 */ 1169static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { 1170 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1171 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 1172 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 1173 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT), 1174 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT), 1175 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT), 1176 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT), 1177 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 1178 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 1179 { 1180 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1181 /* The multiple "Capture Source" controls confuse alsamixer 1182 * So call somewhat different.. 1183 * FIXME: the controls appear in the "playback" view! 1184 */ 1185 /* .name = "Capture Source", */ 1186 .name = "Input Source", 1187 .count = 1, 1188 .info = alc_mux_enum_info, 1189 .get = alc_mux_enum_get, 1190 .put = alc_mux_enum_put, 1191 }, 1192 { } /* end */ 1193}; 1194 1195/* Uniwill */ 1196static struct snd_kcontrol_new alc880_uniwill_mixer[] = { 1197 HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1198 HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT), 1199 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1200 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), 1201 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1202 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1203 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1204 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1205 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1206 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1207 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 1208 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 1209 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1210 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1211 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 1212 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 1213 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 1214 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 1215 { 1216 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1217 .name = "Channel Mode", 1218 .info = alc_ch_mode_info, 1219 .get = alc_ch_mode_get, 1220 .put = alc_ch_mode_put, 1221 }, 1222 { } /* end */ 1223}; 1224 1225static struct snd_kcontrol_new alc880_fujitsu_mixer[] = { 1226 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1227 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), 1228 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1229 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), 1230 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1231 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1232 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1233 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1234 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 1235 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 1236 { } /* end */ 1237}; 1238 1239static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = { 1240 HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1241 HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT), 1242 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1243 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), 1244 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1245 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1246 { } /* end */ 1247}; 1248 1249/* 1250 * build control elements 1251 */ 1252static int alc_build_controls(struct hda_codec *codec) 1253{ 1254 struct alc_spec *spec = codec->spec; 1255 int err; 1256 int i; 1257 1258 for (i = 0; i < spec->num_mixers; i++) { 1259 err = snd_hda_add_new_ctls(codec, spec->mixers[i]); 1260 if (err < 0) 1261 return err; 1262 } 1263 1264 if (spec->multiout.dig_out_nid) { 1265 err = snd_hda_create_spdif_out_ctls(codec, 1266 spec->multiout.dig_out_nid); 1267 if (err < 0) 1268 return err; 1269 } 1270 if (spec->dig_in_nid) { 1271 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 1272 if (err < 0) 1273 return err; 1274 } 1275 return 0; 1276} 1277 1278 1279/* 1280 * initialize the codec volumes, etc 1281 */ 1282 1283/* 1284 * generic initialization of ADC, input mixers and output mixers 1285 */ 1286static struct hda_verb alc880_volume_init_verbs[] = { 1287 /* 1288 * Unmute ADC0-2 and set the default input to mic-in 1289 */ 1290 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 1291 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1292 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 1293 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1294 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 1295 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1296 1297 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 1298 * mixer widget 1299 * Note: PASD motherboards uses the Line In 2 as the input for front 1300 * panel mic (mic 2) 1301 */ 1302 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 1303 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1304 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1305 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 1306 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 1307 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 1308 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 1309 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 1310 1311 /* 1312 * Set up output mixers (0x0c - 0x0f) 1313 */ 1314 /* set vol=0 to output mixers */ 1315 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1316 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1317 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1318 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1319 /* set up input amps for analog loopback */ 1320 /* Amp Indices: DAC = 0, mixer = 1 */ 1321 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1322 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1323 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1324 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1325 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1326 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1327 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1328 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1329 1330 { } 1331}; 1332 1333/* 1334 * 3-stack pin configuration: 1335 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b 1336 */ 1337static struct hda_verb alc880_pin_3stack_init_verbs[] = { 1338 /* 1339 * preset connection lists of input pins 1340 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround 1341 */ 1342 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 1343 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1344 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ 1345 1346 /* 1347 * Set pin mode and muting 1348 */ 1349 /* set front pin widgets 0x14 for output */ 1350 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1351 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1352 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 1353 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1354 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1355 /* Mic2 (as headphone out) for HP output */ 1356 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1357 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1358 /* Line In pin widget for input */ 1359 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1360 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1361 /* Line2 (as front mic) pin widget for input and vref at 80% */ 1362 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1363 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1364 /* CD pin widget for input */ 1365 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1366 1367 { } 1368}; 1369 1370/* 1371 * 5-stack pin configuration: 1372 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19, 1373 * line-in/side = 0x1a, f-mic = 0x1b 1374 */ 1375static struct hda_verb alc880_pin_5stack_init_verbs[] = { 1376 /* 1377 * preset connection lists of input pins 1378 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround 1379 */ 1380 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1381 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */ 1382 1383 /* 1384 * Set pin mode and muting 1385 */ 1386 /* set pin widgets 0x14-0x17 for output */ 1387 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1388 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1389 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1390 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1391 /* unmute pins for output (no gain on this amp) */ 1392 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1393 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1394 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1395 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1396 1397 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 1398 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1399 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1400 /* Mic2 (as headphone out) for HP output */ 1401 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1402 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1403 /* Line In pin widget for input */ 1404 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1405 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1406 /* Line2 (as front mic) pin widget for input and vref at 80% */ 1407 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1408 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1409 /* CD pin widget for input */ 1410 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1411 1412 { } 1413}; 1414 1415/* 1416 * W810 pin configuration: 1417 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b 1418 */ 1419static struct hda_verb alc880_pin_w810_init_verbs[] = { 1420 /* hphone/speaker input selector: front DAC */ 1421 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, 1422 1423 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1424 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1425 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1426 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1427 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1428 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1429 1430 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1431 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1432 1433 { } 1434}; 1435 1436/* 1437 * Z71V pin configuration: 1438 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) 1439 */ 1440static struct hda_verb alc880_pin_z71v_init_verbs[] = { 1441 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1442 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1443 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1444 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1445 1446 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1447 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1448 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1449 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1450 1451 { } 1452}; 1453 1454/* 1455 * 6-stack pin configuration: 1456 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, 1457 * f-mic = 0x19, line = 0x1a, HP = 0x1b 1458 */ 1459static struct hda_verb alc880_pin_6stack_init_verbs[] = { 1460 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1461 1462 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1463 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1464 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1465 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1466 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1467 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1468 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1469 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1470 1471 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1472 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1473 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1474 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1475 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1476 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1477 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1478 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1479 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1480 1481 { } 1482}; 1483 1484/* 1485 * Uniwill pin configuration: 1486 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19, 1487 * line = 0x1a 1488 */ 1489static struct hda_verb alc880_uniwill_init_verbs[] = { 1490 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1491 1492 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1493 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1494 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1495 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1496 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1497 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1498 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1499 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1500 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1501 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1502 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1503 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1504 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1505 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1506 1507 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1508 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1509 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1510 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1511 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1512 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1513 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */ 1514 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */ 1515 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1516 1517 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 1518 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, 1519 1520 { } 1521}; 1522 1523/* 1524* Uniwill P53 1525* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19, 1526 */ 1527static struct hda_verb alc880_uniwill_p53_init_verbs[] = { 1528 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1529 1530 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1531 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1532 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1533 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1534 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1535 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1536 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1537 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1538 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1539 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1540 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1541 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1542 1543 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1544 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1545 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1546 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1547 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1548 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1549 1550 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 1551 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT}, 1552 1553 { } 1554}; 1555 1556static struct hda_verb alc880_beep_init_verbs[] = { 1557 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) }, 1558 { } 1559}; 1560 1561/* toggle speaker-output according to the hp-jack state */ 1562static void alc880_uniwill_hp_automute(struct hda_codec *codec) 1563{ 1564 unsigned int present; 1565 unsigned char bits; 1566 1567 present = snd_hda_codec_read(codec, 0x14, 0, 1568 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1569 bits = present ? HDA_AMP_MUTE : 0; 1570 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 1571 HDA_AMP_MUTE, bits); 1572 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 1573 HDA_AMP_MUTE, bits); 1574} 1575 1576/* auto-toggle front mic */ 1577static void alc880_uniwill_mic_automute(struct hda_codec *codec) 1578{ 1579 unsigned int present; 1580 unsigned char bits; 1581 1582 present = snd_hda_codec_read(codec, 0x18, 0, 1583 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1584 bits = present ? HDA_AMP_MUTE : 0; 1585 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits); 1586} 1587 1588static void alc880_uniwill_automute(struct hda_codec *codec) 1589{ 1590 alc880_uniwill_hp_automute(codec); 1591 alc880_uniwill_mic_automute(codec); 1592} 1593 1594static void alc880_uniwill_unsol_event(struct hda_codec *codec, 1595 unsigned int res) 1596{ 1597 /* Looks like the unsol event is incompatible with the standard 1598 * definition. 4bit tag is placed at 28 bit! 1599 */ 1600 switch (res >> 28) { 1601 case ALC880_HP_EVENT: 1602 alc880_uniwill_hp_automute(codec); 1603 break; 1604 case ALC880_MIC_EVENT: 1605 alc880_uniwill_mic_automute(codec); 1606 break; 1607 } 1608} 1609 1610static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec) 1611{ 1612 unsigned int present; 1613 unsigned char bits; 1614 1615 present = snd_hda_codec_read(codec, 0x14, 0, 1616 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1617 bits = present ? HDA_AMP_MUTE : 0; 1618 snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits); 1619} 1620 1621static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) 1622{ 1623 unsigned int present; 1624 1625 present = snd_hda_codec_read(codec, 0x21, 0, 1626 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); 1627 present &= HDA_AMP_VOLMASK; 1628 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0, 1629 HDA_AMP_VOLMASK, present); 1630 snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0, 1631 HDA_AMP_VOLMASK, present); 1632} 1633 1634static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, 1635 unsigned int res) 1636{ 1637 /* Looks like the unsol event is incompatible with the standard 1638 * definition. 4bit tag is placed at 28 bit! 1639 */ 1640 if ((res >> 28) == ALC880_HP_EVENT) 1641 alc880_uniwill_p53_hp_automute(codec); 1642 if ((res >> 28) == ALC880_DCVOL_EVENT) 1643 alc880_uniwill_p53_dcvol_automute(codec); 1644} 1645 1646/* FIXME! */ 1647/* 1648 * F1734 pin configuration: 1649 * HP = 0x14, speaker-out = 0x15, mic = 0x18 1650 */ 1651static struct hda_verb alc880_pin_f1734_init_verbs[] = { 1652 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, 1653 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, 1654 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, 1655 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, 1656 1657 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1658 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1659 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1660 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1661 1662 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1663 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1664 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1665 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1666 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1667 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1668 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1669 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1670 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1671 1672 { } 1673}; 1674 1675/* FIXME! */ 1676/* 1677 * ASUS pin configuration: 1678 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a 1679 */ 1680static struct hda_verb alc880_pin_asus_init_verbs[] = { 1681 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, 1682 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, 1683 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, 1684 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, 1685 1686 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1687 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1688 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1689 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1690 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1691 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1692 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1693 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1694 1695 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1696 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1697 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1698 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1699 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1700 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1701 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1702 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1703 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1704 1705 { } 1706}; 1707 1708/* Enable GPIO mask and set output */ 1709#define alc880_gpio1_init_verbs alc_gpio1_init_verbs 1710#define alc880_gpio2_init_verbs alc_gpio2_init_verbs 1711 1712/* Clevo m520g init */ 1713static struct hda_verb alc880_pin_clevo_init_verbs[] = { 1714 /* headphone output */ 1715 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, 1716 /* line-out */ 1717 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1718 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1719 /* Line-in */ 1720 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1721 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1722 /* CD */ 1723 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1724 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1725 /* Mic1 (rear panel) */ 1726 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1727 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1728 /* Mic2 (front panel) */ 1729 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1730 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1731 /* headphone */ 1732 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1733 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1734 /* change to EAPD mode */ 1735 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 1736 {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, 1737 1738 { } 1739}; 1740 1741static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { 1742 /* change to EAPD mode */ 1743 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 1744 {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, 1745 1746 /* Headphone output */ 1747 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1748 /* Front output*/ 1749 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1750 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 1751 1752 /* Line In pin widget for input */ 1753 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1754 /* CD pin widget for input */ 1755 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1756 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 1757 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1758 1759 /* change to EAPD mode */ 1760 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 1761 {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, 1762 1763 { } 1764}; 1765 1766/* 1767 * LG m1 express dual 1768 * 1769 * Pin assignment: 1770 * Rear Line-In/Out (blue): 0x14 1771 * Build-in Mic-In: 0x15 1772 * Speaker-out: 0x17 1773 * HP-Out (green): 0x1b 1774 * Mic-In/Out (red): 0x19 1775 * SPDIF-Out: 0x1e 1776 */ 1777 1778/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */ 1779static hda_nid_t alc880_lg_dac_nids[3] = { 1780 0x05, 0x02, 0x03 1781}; 1782 1783/* seems analog CD is not working */ 1784static struct hda_input_mux alc880_lg_capture_source = { 1785 .num_items = 3, 1786 .items = { 1787 { "Mic", 0x1 }, 1788 { "Line", 0x5 }, 1789 { "Internal Mic", 0x6 }, 1790 }, 1791}; 1792 1793/* 2,4,6 channel modes */ 1794static struct hda_verb alc880_lg_ch2_init[] = { 1795 /* set line-in and mic-in to input */ 1796 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 1797 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 1798 { } 1799}; 1800 1801static struct hda_verb alc880_lg_ch4_init[] = { 1802 /* set line-in to out and mic-in to input */ 1803 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, 1804 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 1805 { } 1806}; 1807 1808static struct hda_verb alc880_lg_ch6_init[] = { 1809 /* set line-in and mic-in to output */ 1810 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, 1811 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, 1812 { } 1813}; 1814 1815static struct hda_channel_mode alc880_lg_ch_modes[3] = { 1816 { 2, alc880_lg_ch2_init }, 1817 { 4, alc880_lg_ch4_init }, 1818 { 6, alc880_lg_ch6_init }, 1819}; 1820 1821static struct snd_kcontrol_new alc880_lg_mixer[] = { 1822 /* FIXME: it's not really "master" but front channels */ 1823 HDA_CODEC_VOLUME("Master Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 1824 HDA_BIND_MUTE("Master Playback Switch", 0x0f, 2, HDA_INPUT), 1825 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1826 HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT), 1827 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), 1828 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), 1829 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), 1830 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), 1831 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 1832 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 1833 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT), 1834 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT), 1835 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT), 1836 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT), 1837 { 1838 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1839 .name = "Channel Mode", 1840 .info = alc_ch_mode_info, 1841 .get = alc_ch_mode_get, 1842 .put = alc_ch_mode_put, 1843 }, 1844 { } /* end */ 1845}; 1846 1847static struct hda_verb alc880_lg_init_verbs[] = { 1848 /* set capture source to mic-in */ 1849 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1850 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1851 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1852 /* mute all amp mixer inputs */ 1853 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, 1854 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 1855 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 1856 /* line-in to input */ 1857 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1858 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1859 /* built-in mic */ 1860 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1861 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1862 /* speaker-out */ 1863 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1864 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1865 /* mic-in to input */ 1866 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, 1867 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1868 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1869 /* HP-out */ 1870 {0x13, AC_VERB_SET_CONNECT_SEL, 0x03}, 1871 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1872 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1873 /* jack sense */ 1874 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1}, 1875 { } 1876}; 1877 1878/* toggle speaker-output according to the hp-jack state */ 1879static void alc880_lg_automute(struct hda_codec *codec) 1880{ 1881 unsigned int present; 1882 unsigned char bits; 1883 1884 present = snd_hda_codec_read(codec, 0x1b, 0, 1885 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1886 bits = present ? HDA_AMP_MUTE : 0; 1887 snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0, 1888 HDA_AMP_MUTE, bits); 1889} 1890 1891static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) 1892{ 1893 /* Looks like the unsol event is incompatible with the standard 1894 * definition. 4bit tag is placed at 28 bit! 1895 */ 1896 if ((res >> 28) == 0x01) 1897 alc880_lg_automute(codec); 1898} 1899 1900/* 1901 * LG LW20 1902 * 1903 * Pin assignment: 1904 * Speaker-out: 0x14 1905 * Mic-In: 0x18 1906 * Built-in Mic-In: 0x19 1907 * Line-In: 0x1b 1908 * HP-Out: 0x1a 1909 * SPDIF-Out: 0x1e 1910 */ 1911 1912static struct hda_input_mux alc880_lg_lw_capture_source = { 1913 .num_items = 3, 1914 .items = { 1915 { "Mic", 0x0 }, 1916 { "Internal Mic", 0x1 }, 1917 { "Line In", 0x2 }, 1918 }, 1919}; 1920 1921#define alc880_lg_lw_modes alc880_threestack_modes 1922 1923static struct snd_kcontrol_new alc880_lg_lw_mixer[] = { 1924 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1925 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1926 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 1927 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), 1928 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1929 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1930 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1931 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1932 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 1933 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 1934 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1935 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1936 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 1937 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 1938 { 1939 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1940 .name = "Channel Mode", 1941 .info = alc_ch_mode_info, 1942 .get = alc_ch_mode_get, 1943 .put = alc_ch_mode_put, 1944 }, 1945 { } /* end */ 1946}; 1947 1948static struct hda_verb alc880_lg_lw_init_verbs[] = { 1949 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1950 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 1951 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ 1952 1953 /* set capture source to mic-in */ 1954 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1955 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1956 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1957 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 1958 /* speaker-out */ 1959 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1960 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1961 /* HP-out */ 1962 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1963 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1964 /* mic-in to input */ 1965 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1966 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1967 /* built-in mic */ 1968 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1969 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1970 /* jack sense */ 1971 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1}, 1972 { } 1973}; 1974 1975/* toggle speaker-output according to the hp-jack state */ 1976static void alc880_lg_lw_automute(struct hda_codec *codec) 1977{ 1978 unsigned int present; 1979 unsigned char bits; 1980 1981 present = snd_hda_codec_read(codec, 0x1b, 0, 1982 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1983 bits = present ? HDA_AMP_MUTE : 0; 1984 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 1985 HDA_AMP_MUTE, bits); 1986} 1987 1988static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) 1989{ 1990 /* Looks like the unsol event is incompatible with the standard 1991 * definition. 4bit tag is placed at 28 bit! 1992 */ 1993 if ((res >> 28) == 0x01) 1994 alc880_lg_lw_automute(codec); 1995} 1996 1997#ifdef CONFIG_SND_HDA_POWER_SAVE 1998static struct hda_amp_list alc880_loopbacks[] = { 1999 { 0x0b, HDA_INPUT, 0 }, 2000 { 0x0b, HDA_INPUT, 1 }, 2001 { 0x0b, HDA_INPUT, 2 }, 2002 { 0x0b, HDA_INPUT, 3 }, 2003 { 0x0b, HDA_INPUT, 4 }, 2004 { } /* end */ 2005}; 2006 2007static struct hda_amp_list alc880_lg_loopbacks[] = { 2008 { 0x0b, HDA_INPUT, 1 }, 2009 { 0x0b, HDA_INPUT, 6 }, 2010 { 0x0b, HDA_INPUT, 7 }, 2011 { } /* end */ 2012}; 2013#endif 2014 2015/* 2016 * Common callbacks 2017 */ 2018 2019static int alc_init(struct hda_codec *codec) 2020{ 2021 struct alc_spec *spec = codec->spec; 2022 unsigned int i; 2023 2024 for (i = 0; i < spec->num_init_verbs; i++) 2025 snd_hda_sequence_write(codec, spec->init_verbs[i]); 2026 2027 if (spec->init_hook) 2028 spec->init_hook(codec); 2029 2030 return 0; 2031} 2032 2033static void alc_unsol_event(struct hda_codec *codec, unsigned int res) 2034{ 2035 struct alc_spec *spec = codec->spec; 2036 2037 if (spec->unsol_event) 2038 spec->unsol_event(codec, res); 2039} 2040 2041#ifdef CONFIG_SND_HDA_POWER_SAVE 2042static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) 2043{ 2044 struct alc_spec *spec = codec->spec; 2045 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); 2046} 2047#endif 2048 2049/* 2050 * Analog playback callbacks 2051 */ 2052static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo, 2053 struct hda_codec *codec, 2054 struct snd_pcm_substream *substream) 2055{ 2056 struct alc_spec *spec = codec->spec; 2057 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); 2058} 2059 2060static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 2061 struct hda_codec *codec, 2062 unsigned int stream_tag, 2063 unsigned int format, 2064 struct snd_pcm_substream *substream) 2065{ 2066 struct alc_spec *spec = codec->spec; 2067 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, 2068 stream_tag, format, substream); 2069} 2070 2071static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, 2072 struct hda_codec *codec, 2073 struct snd_pcm_substream *substream) 2074{ 2075 struct alc_spec *spec = codec->spec; 2076 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); 2077} 2078 2079/* 2080 * Digital out 2081 */ 2082static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, 2083 struct hda_codec *codec, 2084 struct snd_pcm_substream *substream) 2085{ 2086 struct alc_spec *spec = codec->spec; 2087 return snd_hda_multi_out_dig_open(codec, &spec->multiout); 2088} 2089 2090static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 2091 struct hda_codec *codec, 2092 unsigned int stream_tag, 2093 unsigned int format, 2094 struct snd_pcm_substream *substream) 2095{ 2096 struct alc_spec *spec = codec->spec; 2097 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, 2098 stream_tag, format, substream); 2099} 2100 2101static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, 2102 struct hda_codec *codec, 2103 struct snd_pcm_substream *substream) 2104{ 2105 struct alc_spec *spec = codec->spec; 2106 return snd_hda_multi_out_dig_close(codec, &spec->multiout); 2107} 2108 2109/* 2110 * Analog capture 2111 */ 2112static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, 2113 struct hda_codec *codec, 2114 unsigned int stream_tag, 2115 unsigned int format, 2116 struct snd_pcm_substream *substream) 2117{ 2118 struct alc_spec *spec = codec->spec; 2119 2120 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 2121 stream_tag, 0, format); 2122 return 0; 2123} 2124 2125static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, 2126 struct hda_codec *codec, 2127 struct snd_pcm_substream *substream) 2128{ 2129 struct alc_spec *spec = codec->spec; 2130 2131 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 2132 0, 0, 0); 2133 return 0; 2134} 2135 2136 2137/* 2138 */ 2139static struct hda_pcm_stream alc880_pcm_analog_playback = { 2140 .substreams = 1, 2141 .channels_min = 2, 2142 .channels_max = 8, 2143 /* NID is set in alc_build_pcms */ 2144 .ops = { 2145 .open = alc880_playback_pcm_open, 2146 .prepare = alc880_playback_pcm_prepare, 2147 .cleanup = alc880_playback_pcm_cleanup 2148 }, 2149}; 2150 2151static struct hda_pcm_stream alc880_pcm_analog_capture = { 2152 .substreams = 2, 2153 .channels_min = 2, 2154 .channels_max = 2, 2155 /* NID is set in alc_build_pcms */ 2156 .ops = { 2157 .prepare = alc880_capture_pcm_prepare, 2158 .cleanup = alc880_capture_pcm_cleanup 2159 }, 2160}; 2161 2162static struct hda_pcm_stream alc880_pcm_digital_playback = { 2163 .substreams = 1, 2164 .channels_min = 2, 2165 .channels_max = 2, 2166 /* NID is set in alc_build_pcms */ 2167 .ops = { 2168 .open = alc880_dig_playback_pcm_open, 2169 .close = alc880_dig_playback_pcm_close, 2170 .prepare = alc880_dig_playback_pcm_prepare 2171 }, 2172}; 2173 2174static struct hda_pcm_stream alc880_pcm_digital_capture = { 2175 .substreams = 1, 2176 .channels_min = 2, 2177 .channels_max = 2, 2178 /* NID is set in alc_build_pcms */ 2179}; 2180 2181/* Used by alc_build_pcms to flag that a PCM has no playback stream */ 2182static struct hda_pcm_stream alc_pcm_null_playback = { 2183 .substreams = 0, 2184 .channels_min = 0, 2185 .channels_max = 0, 2186}; 2187 2188static int alc_build_pcms(struct hda_codec *codec) 2189{ 2190 struct alc_spec *spec = codec->spec; 2191 struct hda_pcm *info = spec->pcm_rec; 2192 int i; 2193 2194 codec->num_pcms = 1; 2195 codec->pcm_info = info; 2196 2197 info->name = spec->stream_name_analog; 2198 if (spec->stream_analog_playback) { 2199 snd_assert(spec->multiout.dac_nids, return -EINVAL); 2200 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); 2201 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; 2202 } 2203 if (spec->stream_analog_capture) { 2204 snd_assert(spec->adc_nids, return -EINVAL); 2205 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); 2206 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; 2207 } 2208 2209 if (spec->channel_mode) { 2210 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0; 2211 for (i = 0; i < spec->num_channel_mode; i++) { 2212 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) { 2213 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels; 2214 } 2215 } 2216 } 2217 2218 /* SPDIF for stream index #1 */ 2219 if (spec->multiout.dig_out_nid || spec->dig_in_nid) { 2220 codec->num_pcms = 2; 2221 info = spec->pcm_rec + 1; 2222 info->name = spec->stream_name_digital; 2223 if (spec->multiout.dig_out_nid && 2224 spec->stream_digital_playback) { 2225 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); 2226 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; 2227 } 2228 if (spec->dig_in_nid && 2229 spec->stream_digital_capture) { 2230 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture); 2231 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; 2232 } 2233 } 2234 2235 /* If the use of more than one ADC is requested for the current 2236 * model, configure a second analog capture-only PCM. 2237 */ 2238 /* Additional Analaog capture for index #2 */ 2239 if (spec->num_adc_nids > 1 && spec->stream_analog_capture && 2240 spec->adc_nids) { 2241 codec->num_pcms = 3; 2242 info = spec->pcm_rec + 2; 2243 info->name = spec->stream_name_analog; 2244 /* No playback stream for second PCM */ 2245 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; 2246 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; 2247 if (spec->stream_analog_capture) { 2248 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); 2249 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1]; 2250 } 2251 } 2252 2253 return 0; 2254} 2255 2256static void alc_free(struct hda_codec *codec) 2257{ 2258 struct alc_spec *spec = codec->spec; 2259 unsigned int i; 2260 2261 if (!spec) 2262 return; 2263 2264 if (spec->kctl_alloc) { 2265 for (i = 0; i < spec->num_kctl_used; i++) 2266 kfree(spec->kctl_alloc[i].name); 2267 kfree(spec->kctl_alloc); 2268 } 2269 kfree(spec); 2270} 2271 2272/* 2273 */ 2274static struct hda_codec_ops alc_patch_ops = { 2275 .build_controls = alc_build_controls, 2276 .build_pcms = alc_build_pcms, 2277 .init = alc_init, 2278 .free = alc_free, 2279 .unsol_event = alc_unsol_event, 2280#ifdef CONFIG_SND_HDA_POWER_SAVE 2281 .check_power_status = alc_check_power_status, 2282#endif 2283}; 2284 2285 2286/* 2287 * Test configuration for debugging 2288 * 2289 * Almost all inputs/outputs are enabled. I/O pins can be configured via 2290 * enum controls. 2291 */ 2292#ifdef CONFIG_SND_DEBUG 2293static hda_nid_t alc880_test_dac_nids[4] = { 2294 0x02, 0x03, 0x04, 0x05 2295}; 2296 2297static struct hda_input_mux alc880_test_capture_source = { 2298 .num_items = 7, 2299 .items = { 2300 { "In-1", 0x0 }, 2301 { "In-2", 0x1 }, 2302 { "In-3", 0x2 }, 2303 { "In-4", 0x3 }, 2304 { "CD", 0x4 }, 2305 { "Front", 0x5 }, 2306 { "Surround", 0x6 }, 2307 }, 2308}; 2309 2310static struct hda_channel_mode alc880_test_modes[4] = { 2311 { 2, NULL }, 2312 { 4, NULL }, 2313 { 6, NULL }, 2314 { 8, NULL }, 2315}; 2316 2317static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, 2318 struct snd_ctl_elem_info *uinfo) 2319{ 2320 static char *texts[] = { 2321 "N/A", "Line Out", "HP Out", 2322 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" 2323 }; 2324 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2325 uinfo->count = 1; 2326 uinfo->value.enumerated.items = 8; 2327 if (uinfo->value.enumerated.item >= 8) 2328 uinfo->value.enumerated.item = 7; 2329 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2330 return 0; 2331} 2332 2333static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, 2334 struct snd_ctl_elem_value *ucontrol) 2335{ 2336 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2337 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 2338 unsigned int pin_ctl, item = 0; 2339 2340 pin_ctl = snd_hda_codec_read(codec, nid, 0, 2341 AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 2342 if (pin_ctl & AC_PINCTL_OUT_EN) { 2343 if (pin_ctl & AC_PINCTL_HP_EN) 2344 item = 2; 2345 else 2346 item = 1; 2347 } else if (pin_ctl & AC_PINCTL_IN_EN) { 2348 switch (pin_ctl & AC_PINCTL_VREFEN) { 2349 case AC_PINCTL_VREF_HIZ: item = 3; break; 2350 case AC_PINCTL_VREF_50: item = 4; break; 2351 case AC_PINCTL_VREF_GRD: item = 5; break; 2352 case AC_PINCTL_VREF_80: item = 6; break; 2353 case AC_PINCTL_VREF_100: item = 7; break; 2354 } 2355 } 2356 ucontrol->value.enumerated.item[0] = item; 2357 return 0; 2358} 2359 2360static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, 2361 struct snd_ctl_elem_value *ucontrol) 2362{ 2363 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2364 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 2365 static unsigned int ctls[] = { 2366 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, 2367 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, 2368 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, 2369 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, 2370 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, 2371 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, 2372 }; 2373 unsigned int old_ctl, new_ctl; 2374 2375 old_ctl = snd_hda_codec_read(codec, nid, 0, 2376 AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 2377 new_ctl = ctls[ucontrol->value.enumerated.item[0]]; 2378 if (old_ctl != new_ctl) { 2379 int val; 2380 snd_hda_codec_write_cache(codec, nid, 0, 2381 AC_VERB_SET_PIN_WIDGET_CONTROL, 2382 new_ctl); 2383 val = ucontrol->value.enumerated.item[0] >= 3 ? 2384 HDA_AMP_MUTE : 0; 2385 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, 2386 HDA_AMP_MUTE, val); 2387 return 1; 2388 } 2389 return 0; 2390} 2391 2392static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, 2393 struct snd_ctl_elem_info *uinfo) 2394{ 2395 static char *texts[] = { 2396 "Front", "Surround", "CLFE", "Side" 2397 }; 2398 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2399 uinfo->count = 1; 2400 uinfo->value.enumerated.items = 4; 2401 if (uinfo->value.enumerated.item >= 4) 2402 uinfo->value.enumerated.item = 3; 2403 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2404 return 0; 2405} 2406 2407static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, 2408 struct snd_ctl_elem_value *ucontrol) 2409{ 2410 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2411 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 2412 unsigned int sel; 2413 2414 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); 2415 ucontrol->value.enumerated.item[0] = sel & 3; 2416 return 0; 2417} 2418 2419static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, 2420 struct snd_ctl_elem_value *ucontrol) 2421{ 2422 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2423 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 2424 unsigned int sel; 2425 2426 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; 2427 if (ucontrol->value.enumerated.item[0] != sel) { 2428 sel = ucontrol->value.enumerated.item[0] & 3; 2429 snd_hda_codec_write_cache(codec, nid, 0, 2430 AC_VERB_SET_CONNECT_SEL, sel); 2431 return 1; 2432 } 2433 return 0; 2434} 2435 2436#define PIN_CTL_TEST(xname,nid) { \ 2437 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 2438 .name = xname, \ 2439 .info = alc_test_pin_ctl_info, \ 2440 .get = alc_test_pin_ctl_get, \ 2441 .put = alc_test_pin_ctl_put, \ 2442 .private_value = nid \ 2443 } 2444 2445#define PIN_SRC_TEST(xname,nid) { \ 2446 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 2447 .name = xname, \ 2448 .info = alc_test_pin_src_info, \ 2449 .get = alc_test_pin_src_get, \ 2450 .put = alc_test_pin_src_put, \ 2451 .private_value = nid \ 2452 } 2453 2454static struct snd_kcontrol_new alc880_test_mixer[] = { 2455 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 2456 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 2457 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), 2458 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 2459 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 2460 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 2461 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), 2462 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 2463 PIN_CTL_TEST("Front Pin Mode", 0x14), 2464 PIN_CTL_TEST("Surround Pin Mode", 0x15), 2465 PIN_CTL_TEST("CLFE Pin Mode", 0x16), 2466 PIN_CTL_TEST("Side Pin Mode", 0x17), 2467 PIN_CTL_TEST("In-1 Pin Mode", 0x18), 2468 PIN_CTL_TEST("In-2 Pin Mode", 0x19), 2469 PIN_CTL_TEST("In-3 Pin Mode", 0x1a), 2470 PIN_CTL_TEST("In-4 Pin Mode", 0x1b), 2471 PIN_SRC_TEST("In-1 Pin Source", 0x18), 2472 PIN_SRC_TEST("In-2 Pin Source", 0x19), 2473 PIN_SRC_TEST("In-3 Pin Source", 0x1a), 2474 PIN_SRC_TEST("In-4 Pin Source", 0x1b), 2475 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), 2476 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), 2477 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), 2478 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), 2479 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), 2480 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), 2481 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), 2482 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), 2483 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), 2484 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), 2485 { 2486 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2487 .name = "Channel Mode", 2488 .info = alc_ch_mode_info, 2489 .get = alc_ch_mode_get, 2490 .put = alc_ch_mode_put, 2491 }, 2492 { } /* end */ 2493}; 2494 2495static struct hda_verb alc880_test_init_verbs[] = { 2496 /* Unmute inputs of 0x0c - 0x0f */ 2497 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2498 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2499 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2500 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2501 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2502 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2503 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2504 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2505 /* Vol output for 0x0c-0x0f */ 2506 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2507 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2508 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2509 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2510 /* Set output pins 0x14-0x17 */ 2511 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2512 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2513 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2514 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2515 /* Unmute output pins 0x14-0x17 */ 2516 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2517 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2518 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2519 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2520 /* Set input pins 0x18-0x1c */ 2521 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2522 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2523 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2524 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2525 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2526 /* Mute input pins 0x18-0x1b */ 2527 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2528 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2529 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2530 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2531 /* ADC set up */ 2532 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2533 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 2534 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2535 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 2536 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2537 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 2538 /* Analog input/passthru */ 2539 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2540 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2541 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2542 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2543 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2544 { } 2545}; 2546#endif 2547 2548/* 2549 */ 2550 2551static const char *alc880_models[ALC880_MODEL_LAST] = { 2552 [ALC880_3ST] = "3stack", 2553 [ALC880_TCL_S700] = "tcl", 2554 [ALC880_3ST_DIG] = "3stack-digout", 2555 [ALC880_CLEVO] = "clevo", 2556 [ALC880_5ST] = "5stack", 2557 [ALC880_5ST_DIG] = "5stack-digout", 2558 [ALC880_W810] = "w810", 2559 [ALC880_Z71V] = "z71v", 2560 [ALC880_6ST] = "6stack", 2561 [ALC880_6ST_DIG] = "6stack-digout", 2562 [ALC880_ASUS] = "asus", 2563 [ALC880_ASUS_W1V] = "asus-w1v", 2564 [ALC880_ASUS_DIG] = "asus-dig", 2565 [ALC880_ASUS_DIG2] = "asus-dig2", 2566 [ALC880_UNIWILL_DIG] = "uniwill", 2567 [ALC880_UNIWILL_P53] = "uniwill-p53", 2568 [ALC880_FUJITSU] = "fujitsu", 2569 [ALC880_F1734] = "F1734", 2570 [ALC880_LG] = "lg", 2571 [ALC880_LG_LW] = "lg-lw", 2572#ifdef CONFIG_SND_DEBUG 2573 [ALC880_TEST] = "test", 2574#endif 2575 [ALC880_AUTO] = "auto", 2576}; 2577 2578static struct snd_pci_quirk alc880_cfg_tbl[] = { 2579 /* Broken BIOS configuration */ 2580 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), 2581 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG), 2582 2583 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG), 2584 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST), 2585 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810), 2586 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG), 2587 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG), 2588 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG), 2589 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG), 2590 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG), 2591 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST), 2592 2593 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG), 2594 SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST), 2595 2596 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V), 2597 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG), 2598 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG), 2599 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG), 2600 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG), 2601 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG), 2602 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V), 2603 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ 2604 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), 2605 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), 2606 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS), 2607 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), 2608 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), 2609 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), 2610 SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS), 2611 2612 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), 2613 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), 2614 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST), 2615 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST), 2616 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), 2617 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO), 2618 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO), 2619 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), 2620 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810), 2621 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), 2622 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700), 2623 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), 2624 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), 2625 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG), 2626 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG), 2627 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG), 2628 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG), 2629 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), 2630 2631 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), 2632 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), 2633 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53), 2634 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734), 2635 2636 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), 2637 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL), 2638 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), 2639 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), 2640 2641 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), 2642 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG), 2643 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW), 2644 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW), 2645 2646 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG), 2647 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG), 2648 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG), 2649 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG), 2650 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG), 2651 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG), 2652 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), 2653 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), 2654 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), 2655 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG), 2656 SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST), 2657 2658 {} 2659}; 2660 2661/* 2662 * ALC880 codec presets 2663 */ 2664static struct alc_config_preset alc880_presets[] = { 2665 [ALC880_3ST] = { 2666 .mixers = { alc880_three_stack_mixer }, 2667 .init_verbs = { alc880_volume_init_verbs, 2668 alc880_pin_3stack_init_verbs }, 2669 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2670 .dac_nids = alc880_dac_nids, 2671 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2672 .channel_mode = alc880_threestack_modes, 2673 .need_dac_fix = 1, 2674 .input_mux = &alc880_capture_source, 2675 }, 2676 [ALC880_3ST_DIG] = { 2677 .mixers = { alc880_three_stack_mixer }, 2678 .init_verbs = { alc880_volume_init_verbs, 2679 alc880_pin_3stack_init_verbs }, 2680 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2681 .dac_nids = alc880_dac_nids, 2682 .dig_out_nid = ALC880_DIGOUT_NID, 2683 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2684 .channel_mode = alc880_threestack_modes, 2685 .need_dac_fix = 1, 2686 .input_mux = &alc880_capture_source, 2687 }, 2688 [ALC880_TCL_S700] = { 2689 .mixers = { alc880_tcl_s700_mixer }, 2690 .init_verbs = { alc880_volume_init_verbs, 2691 alc880_pin_tcl_S700_init_verbs, 2692 alc880_gpio2_init_verbs }, 2693 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2694 .dac_nids = alc880_dac_nids, 2695 .hp_nid = 0x03, 2696 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2697 .channel_mode = alc880_2_jack_modes, 2698 .input_mux = &alc880_capture_source, 2699 }, 2700 [ALC880_5ST] = { 2701 .mixers = { alc880_three_stack_mixer, 2702 alc880_five_stack_mixer}, 2703 .init_verbs = { alc880_volume_init_verbs, 2704 alc880_pin_5stack_init_verbs }, 2705 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2706 .dac_nids = alc880_dac_nids, 2707 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), 2708 .channel_mode = alc880_fivestack_modes, 2709 .input_mux = &alc880_capture_source, 2710 }, 2711 [ALC880_5ST_DIG] = { 2712 .mixers = { alc880_three_stack_mixer, 2713 alc880_five_stack_mixer }, 2714 .init_verbs = { alc880_volume_init_verbs, 2715 alc880_pin_5stack_init_verbs }, 2716 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2717 .dac_nids = alc880_dac_nids, 2718 .dig_out_nid = ALC880_DIGOUT_NID, 2719 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), 2720 .channel_mode = alc880_fivestack_modes, 2721 .input_mux = &alc880_capture_source, 2722 }, 2723 [ALC880_6ST] = { 2724 .mixers = { alc880_six_stack_mixer }, 2725 .init_verbs = { alc880_volume_init_verbs, 2726 alc880_pin_6stack_init_verbs }, 2727 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), 2728 .dac_nids = alc880_6st_dac_nids, 2729 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), 2730 .channel_mode = alc880_sixstack_modes, 2731 .input_mux = &alc880_6stack_capture_source, 2732 }, 2733 [ALC880_6ST_DIG] = { 2734 .mixers = { alc880_six_stack_mixer }, 2735 .init_verbs = { alc880_volume_init_verbs, 2736 alc880_pin_6stack_init_verbs }, 2737 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), 2738 .dac_nids = alc880_6st_dac_nids, 2739 .dig_out_nid = ALC880_DIGOUT_NID, 2740 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), 2741 .channel_mode = alc880_sixstack_modes, 2742 .input_mux = &alc880_6stack_capture_source, 2743 }, 2744 [ALC880_W810] = { 2745 .mixers = { alc880_w810_base_mixer }, 2746 .init_verbs = { alc880_volume_init_verbs, 2747 alc880_pin_w810_init_verbs, 2748 alc880_gpio2_init_verbs }, 2749 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), 2750 .dac_nids = alc880_w810_dac_nids, 2751 .dig_out_nid = ALC880_DIGOUT_NID, 2752 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), 2753 .channel_mode = alc880_w810_modes, 2754 .input_mux = &alc880_capture_source, 2755 }, 2756 [ALC880_Z71V] = { 2757 .mixers = { alc880_z71v_mixer }, 2758 .init_verbs = { alc880_volume_init_verbs, 2759 alc880_pin_z71v_init_verbs }, 2760 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), 2761 .dac_nids = alc880_z71v_dac_nids, 2762 .dig_out_nid = ALC880_DIGOUT_NID, 2763 .hp_nid = 0x03, 2764 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2765 .channel_mode = alc880_2_jack_modes, 2766 .input_mux = &alc880_capture_source, 2767 }, 2768 [ALC880_F1734] = { 2769 .mixers = { alc880_f1734_mixer }, 2770 .init_verbs = { alc880_volume_init_verbs, 2771 alc880_pin_f1734_init_verbs }, 2772 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), 2773 .dac_nids = alc880_f1734_dac_nids, 2774 .hp_nid = 0x02, 2775 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2776 .channel_mode = alc880_2_jack_modes, 2777 .input_mux = &alc880_capture_source, 2778 }, 2779 [ALC880_ASUS] = { 2780 .mixers = { alc880_asus_mixer }, 2781 .init_verbs = { alc880_volume_init_verbs, 2782 alc880_pin_asus_init_verbs, 2783 alc880_gpio1_init_verbs }, 2784 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2785 .dac_nids = alc880_asus_dac_nids, 2786 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2787 .channel_mode = alc880_asus_modes, 2788 .need_dac_fix = 1, 2789 .input_mux = &alc880_capture_source, 2790 }, 2791 [ALC880_ASUS_DIG] = { 2792 .mixers = { alc880_asus_mixer }, 2793 .init_verbs = { alc880_volume_init_verbs, 2794 alc880_pin_asus_init_verbs, 2795 alc880_gpio1_init_verbs }, 2796 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2797 .dac_nids = alc880_asus_dac_nids, 2798 .dig_out_nid = ALC880_DIGOUT_NID, 2799 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2800 .channel_mode = alc880_asus_modes, 2801 .need_dac_fix = 1, 2802 .input_mux = &alc880_capture_source, 2803 }, 2804 [ALC880_ASUS_DIG2] = { 2805 .mixers = { alc880_asus_mixer }, 2806 .init_verbs = { alc880_volume_init_verbs, 2807 alc880_pin_asus_init_verbs, 2808 alc880_gpio2_init_verbs }, /* use GPIO2 */ 2809 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2810 .dac_nids = alc880_asus_dac_nids, 2811 .dig_out_nid = ALC880_DIGOUT_NID, 2812 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2813 .channel_mode = alc880_asus_modes, 2814 .need_dac_fix = 1, 2815 .input_mux = &alc880_capture_source, 2816 }, 2817 [ALC880_ASUS_W1V] = { 2818 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, 2819 .init_verbs = { alc880_volume_init_verbs, 2820 alc880_pin_asus_init_verbs, 2821 alc880_gpio1_init_verbs }, 2822 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2823 .dac_nids = alc880_asus_dac_nids, 2824 .dig_out_nid = ALC880_DIGOUT_NID, 2825 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2826 .channel_mode = alc880_asus_modes, 2827 .need_dac_fix = 1, 2828 .input_mux = &alc880_capture_source, 2829 }, 2830 [ALC880_UNIWILL_DIG] = { 2831 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer }, 2832 .init_verbs = { alc880_volume_init_verbs, 2833 alc880_pin_asus_init_verbs }, 2834 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2835 .dac_nids = alc880_asus_dac_nids, 2836 .dig_out_nid = ALC880_DIGOUT_NID, 2837 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2838 .channel_mode = alc880_asus_modes, 2839 .need_dac_fix = 1, 2840 .input_mux = &alc880_capture_source, 2841 }, 2842 [ALC880_UNIWILL] = { 2843 .mixers = { alc880_uniwill_mixer }, 2844 .init_verbs = { alc880_volume_init_verbs, 2845 alc880_uniwill_init_verbs }, 2846 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2847 .dac_nids = alc880_asus_dac_nids, 2848 .dig_out_nid = ALC880_DIGOUT_NID, 2849 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2850 .channel_mode = alc880_threestack_modes, 2851 .need_dac_fix = 1, 2852 .input_mux = &alc880_capture_source, 2853 .unsol_event = alc880_uniwill_unsol_event, 2854 .init_hook = alc880_uniwill_automute, 2855 }, 2856 [ALC880_UNIWILL_P53] = { 2857 .mixers = { alc880_uniwill_p53_mixer }, 2858 .init_verbs = { alc880_volume_init_verbs, 2859 alc880_uniwill_p53_init_verbs }, 2860 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2861 .dac_nids = alc880_asus_dac_nids, 2862 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), 2863 .channel_mode = alc880_threestack_modes, 2864 .input_mux = &alc880_capture_source, 2865 .unsol_event = alc880_uniwill_p53_unsol_event, 2866 .init_hook = alc880_uniwill_p53_hp_automute, 2867 }, 2868 [ALC880_FUJITSU] = { 2869 .mixers = { alc880_fujitsu_mixer, 2870 alc880_pcbeep_mixer, }, 2871 .init_verbs = { alc880_volume_init_verbs, 2872 alc880_uniwill_p53_init_verbs, 2873 alc880_beep_init_verbs }, 2874 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2875 .dac_nids = alc880_dac_nids, 2876 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2877 .channel_mode = alc880_2_jack_modes, 2878 .input_mux = &alc880_capture_source, 2879 .unsol_event = alc880_uniwill_p53_unsol_event, 2880 .init_hook = alc880_uniwill_p53_hp_automute, 2881 }, 2882 [ALC880_CLEVO] = { 2883 .mixers = { alc880_three_stack_mixer }, 2884 .init_verbs = { alc880_volume_init_verbs, 2885 alc880_pin_clevo_init_verbs }, 2886 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2887 .dac_nids = alc880_dac_nids, 2888 .hp_nid = 0x03, 2889 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2890 .channel_mode = alc880_threestack_modes, 2891 .need_dac_fix = 1, 2892 .input_mux = &alc880_capture_source, 2893 }, 2894 [ALC880_LG] = { 2895 .mixers = { alc880_lg_mixer }, 2896 .init_verbs = { alc880_volume_init_verbs, 2897 alc880_lg_init_verbs }, 2898 .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids), 2899 .dac_nids = alc880_lg_dac_nids, 2900 .dig_out_nid = ALC880_DIGOUT_NID, 2901 .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), 2902 .channel_mode = alc880_lg_ch_modes, 2903 .need_dac_fix = 1, 2904 .input_mux = &alc880_lg_capture_source, 2905 .unsol_event = alc880_lg_unsol_event, 2906 .init_hook = alc880_lg_automute, 2907#ifdef CONFIG_SND_HDA_POWER_SAVE 2908 .loopbacks = alc880_lg_loopbacks, 2909#endif 2910 }, 2911 [ALC880_LG_LW] = { 2912 .mixers = { alc880_lg_lw_mixer }, 2913 .init_verbs = { alc880_volume_init_verbs, 2914 alc880_lg_lw_init_verbs }, 2915 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2916 .dac_nids = alc880_dac_nids, 2917 .dig_out_nid = ALC880_DIGOUT_NID, 2918 .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes), 2919 .channel_mode = alc880_lg_lw_modes, 2920 .input_mux = &alc880_lg_lw_capture_source, 2921 .unsol_event = alc880_lg_lw_unsol_event, 2922 .init_hook = alc880_lg_lw_automute, 2923 }, 2924#ifdef CONFIG_SND_DEBUG 2925 [ALC880_TEST] = { 2926 .mixers = { alc880_test_mixer }, 2927 .init_verbs = { alc880_test_init_verbs }, 2928 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids), 2929 .dac_nids = alc880_test_dac_nids, 2930 .dig_out_nid = ALC880_DIGOUT_NID, 2931 .num_channel_mode = ARRAY_SIZE(alc880_test_modes), 2932 .channel_mode = alc880_test_modes, 2933 .input_mux = &alc880_test_capture_source, 2934 }, 2935#endif 2936}; 2937 2938/* 2939 * Automatic parse of I/O pins from the BIOS configuration 2940 */ 2941 2942#define NUM_CONTROL_ALLOC 32 2943#define NUM_VERB_ALLOC 32 2944 2945enum { 2946 ALC_CTL_WIDGET_VOL, 2947 ALC_CTL_WIDGET_MUTE, 2948 ALC_CTL_BIND_MUTE, 2949}; 2950static struct snd_kcontrol_new alc880_control_templates[] = { 2951 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 2952 HDA_CODEC_MUTE(NULL, 0, 0, 0), 2953 HDA_BIND_MUTE(NULL, 0, 0, 0), 2954}; 2955 2956/* add dynamic controls */ 2957static int add_control(struct alc_spec *spec, int type, const char *name, 2958 unsigned long val) 2959{ 2960 struct snd_kcontrol_new *knew; 2961 2962 if (spec->num_kctl_used >= spec->num_kctl_alloc) { 2963 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; 2964 2965 /* array + terminator */ 2966 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); 2967 if (!knew) 2968 return -ENOMEM; 2969 if (spec->kctl_alloc) { 2970 memcpy(knew, spec->kctl_alloc, 2971 sizeof(*knew) * spec->num_kctl_alloc); 2972 kfree(spec->kctl_alloc); 2973 } 2974 spec->kctl_alloc = knew; 2975 spec->num_kctl_alloc = num; 2976 } 2977 2978 knew = &spec->kctl_alloc[spec->num_kctl_used]; 2979 *knew = alc880_control_templates[type]; 2980 knew->name = kstrdup(name, GFP_KERNEL); 2981 if (!knew->name) 2982 return -ENOMEM; 2983 knew->private_value = val; 2984 spec->num_kctl_used++; 2985 return 0; 2986} 2987 2988#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) 2989#define alc880_fixed_pin_idx(nid) ((nid) - 0x14) 2990#define alc880_is_multi_pin(nid) ((nid) >= 0x18) 2991#define alc880_multi_pin_idx(nid) ((nid) - 0x18) 2992#define alc880_is_input_pin(nid) ((nid) >= 0x18) 2993#define alc880_input_pin_idx(nid) ((nid) - 0x18) 2994#define alc880_idx_to_dac(nid) ((nid) + 0x02) 2995#define alc880_dac_to_idx(nid) ((nid) - 0x02) 2996#define alc880_idx_to_mixer(nid) ((nid) + 0x0c) 2997#define alc880_idx_to_selector(nid) ((nid) + 0x10) 2998#define ALC880_PIN_CD_NID 0x1c 2999 3000/* fill in the dac_nids table from the parsed pin configuration */ 3001static int alc880_auto_fill_dac_nids(struct alc_spec *spec, 3002 const struct auto_pin_cfg *cfg) 3003{ 3004 hda_nid_t nid; 3005 int assigned[4]; 3006 int i, j; 3007 3008 memset(assigned, 0, sizeof(assigned)); 3009 spec->multiout.dac_nids = spec->private_dac_nids; 3010 3011 /* check the pins hardwired to audio widget */ 3012 for (i = 0; i < cfg->line_outs; i++) { 3013 nid = cfg->line_out_pins[i]; 3014 if (alc880_is_fixed_pin(nid)) { 3015 int idx = alc880_fixed_pin_idx(nid); 3016 spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx); 3017 assigned[idx] = 1; 3018 } 3019 } 3020 /* left pins can be connect to any audio widget */ 3021 for (i = 0; i < cfg->line_outs; i++) { 3022 nid = cfg->line_out_pins[i]; 3023 if (alc880_is_fixed_pin(nid)) 3024 continue; 3025 /* search for an empty channel */ 3026 for (j = 0; j < cfg->line_outs; j++) { 3027 if (!assigned[j]) { 3028 spec->multiout.dac_nids[i] = 3029 alc880_idx_to_dac(j); 3030 assigned[j] = 1; 3031 break; 3032 } 3033 } 3034 } 3035 spec->multiout.num_dacs = cfg->line_outs; 3036 return 0; 3037} 3038 3039/* add playback controls from the parsed DAC table */ 3040static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, 3041 const struct auto_pin_cfg *cfg) 3042{ 3043 char name[32]; 3044 static const char *chname[4] = { 3045 "Front", "Surround", NULL /*CLFE*/, "Side" 3046 }; 3047 hda_nid_t nid; 3048 int i, err; 3049 3050 for (i = 0; i < cfg->line_outs; i++) { 3051 if (!spec->multiout.dac_nids[i]) 3052 continue; 3053 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); 3054 if (i == 2) { 3055 /* Center/LFE */ 3056 err = add_control(spec, ALC_CTL_WIDGET_VOL, 3057 "Center Playback Volume", 3058 HDA_COMPOSE_AMP_VAL(nid, 1, 0, 3059 HDA_OUTPUT)); 3060 if (err < 0) 3061 return err; 3062 err = add_control(spec, ALC_CTL_WIDGET_VOL, 3063 "LFE Playback Volume", 3064 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 3065 HDA_OUTPUT)); 3066 if (err < 0) 3067 return err; 3068 err = add_control(spec, ALC_CTL_BIND_MUTE, 3069 "Center Playback Switch", 3070 HDA_COMPOSE_AMP_VAL(nid, 1, 2, 3071 HDA_INPUT)); 3072 if (err < 0) 3073 return err; 3074 err = add_control(spec, ALC_CTL_BIND_MUTE, 3075 "LFE Playback Switch", 3076 HDA_COMPOSE_AMP_VAL(nid, 2, 2, 3077 HDA_INPUT)); 3078 if (err < 0) 3079 return err; 3080 } else { 3081 sprintf(name, "%s Playback Volume", chname[i]); 3082 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 3083 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 3084 HDA_OUTPUT)); 3085 if (err < 0) 3086 return err; 3087 sprintf(name, "%s Playback Switch", chname[i]); 3088 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 3089 HDA_COMPOSE_AMP_VAL(nid, 3, 2, 3090 HDA_INPUT)); 3091 if (err < 0) 3092 return err; 3093 } 3094 } 3095 return 0; 3096} 3097 3098/* add playback controls for speaker and HP outputs */ 3099static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, 3100 const char *pfx) 3101{ 3102 hda_nid_t nid; 3103 int err; 3104 char name[32]; 3105 3106 if (!pin) 3107 return 0; 3108 3109 if (alc880_is_fixed_pin(pin)) { 3110 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 3111 /* specify the DAC as the extra output */ 3112 if (!spec->multiout.hp_nid) 3113 spec->multiout.hp_nid = nid; 3114 else 3115 spec->multiout.extra_out_nid[0] = nid; 3116 /* control HP volume/switch on the output mixer amp */ 3117 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); 3118 sprintf(name, "%s Playback Volume", pfx); 3119 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 3120 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 3121 if (err < 0) 3122 return err; 3123 sprintf(name, "%s Playback Switch", pfx); 3124 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 3125 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); 3126 if (err < 0) 3127 return err; 3128 } else if (alc880_is_multi_pin(pin)) { 3129 /* set manual connection */ 3130 /* we have only a switch on HP-out PIN */ 3131 sprintf(name, "%s Playback Switch", pfx); 3132 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 3133 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 3134 if (err < 0) 3135 return err; 3136 } 3137 return 0; 3138} 3139 3140/* create input playback/capture controls for the given pin */ 3141static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, 3142 const char *ctlname, 3143 int idx, hda_nid_t mix_nid) 3144{ 3145 char name[32]; 3146 int err; 3147 3148 sprintf(name, "%s Playback Volume", ctlname); 3149 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 3150 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 3151 if (err < 0) 3152 return err; 3153 sprintf(name, "%s Playback Switch", ctlname); 3154 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 3155 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 3156 if (err < 0) 3157 return err; 3158 return 0; 3159} 3160 3161/* create playback/capture controls for input pins */ 3162static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, 3163 const struct auto_pin_cfg *cfg) 3164{ 3165 struct hda_input_mux *imux = &spec->private_imux; 3166 int i, err, idx; 3167 3168 for (i = 0; i < AUTO_PIN_LAST; i++) { 3169 if (alc880_is_input_pin(cfg->input_pins[i])) { 3170 idx = alc880_input_pin_idx(cfg->input_pins[i]); 3171 err = new_analog_input(spec, cfg->input_pins[i], 3172 auto_pin_cfg_labels[i], 3173 idx, 0x0b); 3174 if (err < 0) 3175 return err; 3176 imux->items[imux->num_items].label = 3177 auto_pin_cfg_labels[i]; 3178 imux->items[imux->num_items].index = 3179 alc880_input_pin_idx(cfg->input_pins[i]); 3180 imux->num_items++; 3181 } 3182 } 3183 return 0; 3184} 3185 3186static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, 3187 hda_nid_t nid, int pin_type, 3188 int dac_idx) 3189{ 3190 /* set as output */ 3191 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 3192 pin_type); 3193 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 3194 AMP_OUT_UNMUTE); 3195 /* need the manual connection? */ 3196 if (alc880_is_multi_pin(nid)) { 3197 struct alc_spec *spec = codec->spec; 3198 int idx = alc880_multi_pin_idx(nid); 3199 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, 3200 AC_VERB_SET_CONNECT_SEL, 3201 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); 3202 } 3203} 3204 3205static int get_pin_type(int line_out_type) 3206{ 3207 if (line_out_type == AUTO_PIN_HP_OUT) 3208 return PIN_HP; 3209 else 3210 return PIN_OUT; 3211} 3212 3213static void alc880_auto_init_multi_out(struct hda_codec *codec) 3214{ 3215 struct alc_spec *spec = codec->spec; 3216 int i; 3217 3218 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 3219 for (i = 0; i < spec->autocfg.line_outs; i++) { 3220 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 3221 int pin_type = get_pin_type(spec->autocfg.line_out_type); 3222 alc880_auto_set_output_and_unmute(codec, nid, pin_type, i); 3223 } 3224} 3225 3226static void alc880_auto_init_extra_out(struct hda_codec *codec) 3227{ 3228 struct alc_spec *spec = codec->spec; 3229 hda_nid_t pin; 3230 3231 pin = spec->autocfg.speaker_pins[0]; 3232 if (pin) /* connect to front */ 3233 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); 3234 pin = spec->autocfg.hp_pins[0]; 3235 if (pin) /* connect to front */ 3236 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 3237} 3238 3239static void alc880_auto_init_analog_input(struct hda_codec *codec) 3240{ 3241 struct alc_spec *spec = codec->spec; 3242 int i; 3243 3244 for (i = 0; i < AUTO_PIN_LAST; i++) { 3245 hda_nid_t nid = spec->autocfg.input_pins[i]; 3246 if (alc880_is_input_pin(nid)) { 3247 snd_hda_codec_write(codec, nid, 0, 3248 AC_VERB_SET_PIN_WIDGET_CONTROL, 3249 i <= AUTO_PIN_FRONT_MIC ? 3250 PIN_VREF80 : PIN_IN); 3251 if (nid != ALC880_PIN_CD_NID) 3252 snd_hda_codec_write(codec, nid, 0, 3253 AC_VERB_SET_AMP_GAIN_MUTE, 3254 AMP_OUT_MUTE); 3255 } 3256 } 3257} 3258 3259/* parse the BIOS configuration and set up the alc_spec */ 3260/* return 1 if successful, 0 if the proper config is not found, 3261 * or a negative error code 3262 */ 3263static int alc880_parse_auto_config(struct hda_codec *codec) 3264{ 3265 struct alc_spec *spec = codec->spec; 3266 int err; 3267 static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; 3268 3269 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 3270 alc880_ignore); 3271 if (err < 0) 3272 return err; 3273 if (!spec->autocfg.line_outs) 3274 return 0; /* can't find valid BIOS pin config */ 3275 3276 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 3277 if (err < 0) 3278 return err; 3279 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); 3280 if (err < 0) 3281 return err; 3282 err = alc880_auto_create_extra_out(spec, 3283 spec->autocfg.speaker_pins[0], 3284 "Speaker"); 3285 if (err < 0) 3286 return err; 3287 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], 3288 "Headphone"); 3289 if (err < 0) 3290 return err; 3291 err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg); 3292 if (err < 0) 3293 return err; 3294 3295 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 3296 3297 if (spec->autocfg.dig_out_pin) 3298 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; 3299 if (spec->autocfg.dig_in_pin) 3300 spec->dig_in_nid = ALC880_DIGIN_NID; 3301 3302 if (spec->kctl_alloc) 3303 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 3304 3305 spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; 3306 3307 spec->num_mux_defs = 1; 3308 spec->input_mux = &spec->private_imux; 3309 3310 return 1; 3311} 3312 3313/* additional initialization for auto-configuration model */ 3314static void alc880_auto_init(struct hda_codec *codec) 3315{ 3316 alc880_auto_init_multi_out(codec); 3317 alc880_auto_init_extra_out(codec); 3318 alc880_auto_init_analog_input(codec); 3319} 3320 3321/* 3322 * OK, here we have finally the patch for ALC880 3323 */ 3324 3325static int patch_alc880(struct hda_codec *codec) 3326{ 3327 struct alc_spec *spec; 3328 int board_config; 3329 int err; 3330 3331 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3332 if (spec == NULL) 3333 return -ENOMEM; 3334 3335 codec->spec = spec; 3336 3337 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST, 3338 alc880_models, 3339 alc880_cfg_tbl); 3340 if (board_config < 0) { 3341 printk(KERN_INFO "hda_codec: Unknown model for ALC880, " 3342 "trying auto-probe from BIOS...\n"); 3343 board_config = ALC880_AUTO; 3344 } 3345 3346 if (board_config == ALC880_AUTO) { 3347 /* automatic parse from the BIOS config */ 3348 err = alc880_parse_auto_config(codec); 3349 if (err < 0) { 3350 alc_free(codec); 3351 return err; 3352 } else if (!err) { 3353 printk(KERN_INFO 3354 "hda_codec: Cannot set up configuration " 3355 "from BIOS. Using 3-stack mode...\n"); 3356 board_config = ALC880_3ST; 3357 } 3358 } 3359 3360 if (board_config != ALC880_AUTO) 3361 setup_preset(spec, &alc880_presets[board_config]); 3362 3363 spec->stream_name_analog = "ALC880 Analog"; 3364 spec->stream_analog_playback = &alc880_pcm_analog_playback; 3365 spec->stream_analog_capture = &alc880_pcm_analog_capture; 3366 3367 spec->stream_name_digital = "ALC880 Digital"; 3368 spec->stream_digital_playback = &alc880_pcm_digital_playback; 3369 spec->stream_digital_capture = &alc880_pcm_digital_capture; 3370 3371 if (!spec->adc_nids && spec->input_mux) { 3372 /* check whether NID 0x07 is valid */ 3373 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]); 3374 /* get type */ 3375 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 3376 if (wcap != AC_WID_AUD_IN) { 3377 spec->adc_nids = alc880_adc_nids_alt; 3378 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); 3379 spec->mixers[spec->num_mixers] = 3380 alc880_capture_alt_mixer; 3381 spec->num_mixers++; 3382 } else { 3383 spec->adc_nids = alc880_adc_nids; 3384 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); 3385 spec->mixers[spec->num_mixers] = alc880_capture_mixer; 3386 spec->num_mixers++; 3387 } 3388 } 3389 3390 codec->patch_ops = alc_patch_ops; 3391 if (board_config == ALC880_AUTO) 3392 spec->init_hook = alc880_auto_init; 3393#ifdef CONFIG_SND_HDA_POWER_SAVE 3394 if (!spec->loopback.amplist) 3395 spec->loopback.amplist = alc880_loopbacks; 3396#endif 3397 3398 return 0; 3399} 3400 3401 3402/* 3403 * ALC260 support 3404 */ 3405 3406static hda_nid_t alc260_dac_nids[1] = { 3407 /* front */ 3408 0x02, 3409}; 3410 3411static hda_nid_t alc260_adc_nids[1] = { 3412 /* ADC0 */ 3413 0x04, 3414}; 3415 3416static hda_nid_t alc260_adc_nids_alt[1] = { 3417 /* ADC1 */ 3418 0x05, 3419}; 3420 3421static hda_nid_t alc260_hp_adc_nids[2] = { 3422 /* ADC1, 0 */ 3423 0x05, 0x04 3424}; 3425 3426/* NIDs used when simultaneous access to both ADCs makes sense. Note that 3427 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. 3428 */ 3429static hda_nid_t alc260_dual_adc_nids[2] = { 3430 /* ADC0, ADC1 */ 3431 0x04, 0x05 3432}; 3433 3434#define ALC260_DIGOUT_NID 0x03 3435#define ALC260_DIGIN_NID 0x06 3436 3437static struct hda_input_mux alc260_capture_source = { 3438 .num_items = 4, 3439 .items = { 3440 { "Mic", 0x0 }, 3441 { "Front Mic", 0x1 }, 3442 { "Line", 0x2 }, 3443 { "CD", 0x4 }, 3444 }, 3445}; 3446 3447/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, 3448 * headphone jack and the internal CD lines since these are the only pins at 3449 * which audio can appear. For flexibility, also allow the option of 3450 * recording the mixer output on the second ADC (ADC0 doesn't have a 3451 * connection to the mixer output). 3452 */ 3453static struct hda_input_mux alc260_fujitsu_capture_sources[2] = { 3454 { 3455 .num_items = 3, 3456 .items = { 3457 { "Mic/Line", 0x0 }, 3458 { "CD", 0x4 }, 3459 { "Headphone", 0x2 }, 3460 }, 3461 }, 3462 { 3463 .num_items = 4, 3464 .items = { 3465 { "Mic/Line", 0x0 }, 3466 { "CD", 0x4 }, 3467 { "Headphone", 0x2 }, 3468 { "Mixer", 0x5 }, 3469 }, 3470 }, 3471 3472}; 3473 3474/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to 3475 * the Fujitsu S702x, but jacks are marked differently. 3476 */ 3477static struct hda_input_mux alc260_acer_capture_sources[2] = { 3478 { 3479 .num_items = 4, 3480 .items = { 3481 { "Mic", 0x0 }, 3482 { "Line", 0x2 }, 3483 { "CD", 0x4 }, 3484 { "Headphone", 0x5 }, 3485 }, 3486 }, 3487 { 3488 .num_items = 5, 3489 .items = { 3490 { "Mic", 0x0 }, 3491 { "Line", 0x2 }, 3492 { "CD", 0x4 }, 3493 { "Headphone", 0x6 }, 3494 { "Mixer", 0x5 }, 3495 }, 3496 }, 3497}; 3498/* 3499 * This is just place-holder, so there's something for alc_build_pcms to look 3500 * at when it calculates the maximum number of channels. ALC260 has no mixer 3501 * element which allows changing the channel mode, so the verb list is 3502 * never used. 3503 */ 3504static struct hda_channel_mode alc260_modes[1] = { 3505 { 2, NULL }, 3506}; 3507 3508 3509/* Mixer combinations 3510 * 3511 * basic: base_output + input + pc_beep + capture 3512 * HP: base_output + input + capture_alt 3513 * HP_3013: hp_3013 + input + capture 3514 * fujitsu: fujitsu + capture 3515 * acer: acer + capture 3516 */ 3517 3518static struct snd_kcontrol_new alc260_base_output_mixer[] = { 3519 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3520 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), 3521 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), 3522 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), 3523 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 3524 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), 3525 { } /* end */ 3526}; 3527 3528static struct snd_kcontrol_new alc260_input_mixer[] = { 3529 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3530 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3531 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3532 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3533 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3534 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3535 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), 3536 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), 3537 { } /* end */ 3538}; 3539 3540static struct snd_kcontrol_new alc260_pc_beep_mixer[] = { 3541 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), 3542 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), 3543 { } /* end */ 3544}; 3545 3546static struct snd_kcontrol_new alc260_hp_3013_mixer[] = { 3547 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT), 3548 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT), 3549 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT), 3550 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT), 3551 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3552 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 3553 HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 3554 HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT), 3555 { } /* end */ 3556}; 3557 3558/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12, 3559 * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10. 3560 */ 3561static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { 3562 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3563 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), 3564 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3565 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3566 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3567 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), 3568 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), 3569 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), 3570 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 3571 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 3572 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), 3573 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT), 3574 { } /* end */ 3575}; 3576 3577/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current 3578 * versions of the ALC260 don't act on requests to enable mic bias from NID 3579 * 0x0f (used to drive the headphone jack in these laptops). The ALC260 3580 * datasheet doesn't mention this restriction. At this stage it's not clear 3581 * whether this behaviour is intentional or is a hardware bug in chip 3582 * revisions available in early 2006. Therefore for now allow the 3583 * "Headphone Jack Mode" control to span all choices, but if it turns out 3584 * that the lack of mic bias for this NID is intentional we could change the 3585 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. 3586 * 3587 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006 3588 * don't appear to make the mic bias available from the "line" jack, even 3589 * though the NID used for this jack (0x14) can supply it. The theory is 3590 * that perhaps Acer have included blocking capacitors between the ALC260 3591 * and the output jack. If this turns out to be the case for all such 3592 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT 3593 * to ALC_PIN_DIR_INOUT_NOMICBIAS. 3594 * 3595 * The C20x Tablet series have a mono internal speaker which is controlled 3596 * via the chip's Mono sum widget and pin complex, so include the necessary 3597 * controls for such models. On models without a "mono speaker" the control 3598 * won't do anything. 3599 */ 3600static struct snd_kcontrol_new alc260_acer_mixer[] = { 3601 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3602 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), 3603 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), 3604 HDA_CODEC_VOLUME_MONO("Mono Speaker Playback Volume", 0x0a, 1, 0x0, 3605 HDA_OUTPUT), 3606 HDA_BIND_MUTE_MONO("Mono Speaker Playback Switch", 0x0a, 1, 2, 3607 HDA_INPUT), 3608 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3609 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3610 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3611 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3612 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), 3613 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3614 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3615 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3616 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 3617 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 3618 { } /* end */ 3619}; 3620 3621/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12, 3622 * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17. 3623 */ 3624static struct snd_kcontrol_new alc260_will_mixer[] = { 3625 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3626 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), 3627 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3628 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3629 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), 3630 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3631 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3632 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3633 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3634 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3635 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 3636 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 3637 { } /* end */ 3638}; 3639 3640/* Replacer 672V ALC260 pin usage: Mic jack = 0x12, 3641 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f. 3642 */ 3643static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = { 3644 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3645 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), 3646 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3647 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3648 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), 3649 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT), 3650 HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT), 3651 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3652 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3653 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3654 { } /* end */ 3655}; 3656 3657/* capture mixer elements */ 3658static struct snd_kcontrol_new alc260_capture_mixer[] = { 3659 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), 3660 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), 3661 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT), 3662 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT), 3663 { 3664 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3665 /* The multiple "Capture Source" controls confuse alsamixer 3666 * So call somewhat different.. 3667 * FIXME: the controls appear in the "playback" view! 3668 */ 3669 /* .name = "Capture Source", */ 3670 .name = "Input Source", 3671 .count = 2, 3672 .info = alc_mux_enum_info, 3673 .get = alc_mux_enum_get, 3674 .put = alc_mux_enum_put, 3675 }, 3676 { } /* end */ 3677}; 3678 3679static struct snd_kcontrol_new alc260_capture_alt_mixer[] = { 3680 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), 3681 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT), 3682 { 3683 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3684 /* The multiple "Capture Source" controls confuse alsamixer 3685 * So call somewhat different.. 3686 * FIXME: the controls appear in the "playback" view! 3687 */ 3688 /* .name = "Capture Source", */ 3689 .name = "Input Source", 3690 .count = 1, 3691 .info = alc_mux_enum_info, 3692 .get = alc_mux_enum_get, 3693 .put = alc_mux_enum_put, 3694 }, 3695 { } /* end */ 3696}; 3697 3698/* 3699 * initialization verbs 3700 */ 3701static struct hda_verb alc260_init_verbs[] = { 3702 /* Line In pin widget for input */ 3703 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3704 /* CD pin widget for input */ 3705 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3706 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 3707 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3708 /* Mic2 (front panel) pin widget for input and vref at 80% */ 3709 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3710 /* LINE-2 is used for line-out in rear */ 3711 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3712 /* select line-out */ 3713 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, 3714 /* LINE-OUT pin */ 3715 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3716 /* enable HP */ 3717 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3718 /* enable Mono */ 3719 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3720 /* mute capture amp left and right */ 3721 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3722 /* set connection select to line in (default select for this ADC) */ 3723 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, 3724 /* mute capture amp left and right */ 3725 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3726 /* set connection select to line in (default select for this ADC) */ 3727 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, 3728 /* set vol=0 Line-Out mixer amp left and right */ 3729 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3730 /* unmute pin widget amp left and right (no gain on this amp) */ 3731 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3732 /* set vol=0 HP mixer amp left and right */ 3733 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3734 /* unmute pin widget amp left and right (no gain on this amp) */ 3735 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3736 /* set vol=0 Mono mixer amp left and right */ 3737 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3738 /* unmute pin widget amp left and right (no gain on this amp) */ 3739 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3740 /* unmute LINE-2 out pin */ 3741 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3742 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & 3743 * Line In 2 = 0x03 3744 */ 3745 /* mute analog inputs */ 3746 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3747 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3748 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 3749 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 3750 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3751 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ 3752 /* mute Front out path */ 3753 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3754 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3755 /* mute Headphone out path */ 3756 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3757 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3758 /* mute Mono out path */ 3759 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3760 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3761 { } 3762}; 3763 3764#if 0 /* should be identical with alc260_init_verbs? */ 3765static struct hda_verb alc260_hp_init_verbs[] = { 3766 /* Headphone and output */ 3767 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 3768 /* mono output */ 3769 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3770 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 3771 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3772 /* Mic2 (front panel) pin widget for input and vref at 80% */ 3773 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3774 /* Line In pin widget for input */ 3775 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3776 /* Line-2 pin widget for output */ 3777 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3778 /* CD pin widget for input */ 3779 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3780 /* unmute amp left and right */ 3781 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, 3782 /* set connection select to line in (default select for this ADC) */ 3783 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, 3784 /* unmute Line-Out mixer amp left and right (volume = 0) */ 3785 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3786 /* mute pin widget amp left and right (no gain on this amp) */ 3787 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3788 /* unmute HP mixer amp left and right (volume = 0) */ 3789 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3790 /* mute pin widget amp left and right (no gain on this amp) */ 3791 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3792 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & 3793 * Line In 2 = 0x03 3794 */ 3795 /* mute analog inputs */ 3796 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3797 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3798 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 3799 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 3800 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3801 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ 3802 /* Unmute Front out path */ 3803 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3804 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3805 /* Unmute Headphone out path */ 3806 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3807 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3808 /* Unmute Mono out path */ 3809 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3810 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3811 { } 3812}; 3813#endif 3814 3815static struct hda_verb alc260_hp_3013_init_verbs[] = { 3816 /* Line out and output */ 3817 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3818 /* mono output */ 3819 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3820 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 3821 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3822 /* Mic2 (front panel) pin widget for input and vref at 80% */ 3823 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3824 /* Line In pin widget for input */ 3825 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3826 /* Headphone pin widget for output */ 3827 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 3828 /* CD pin widget for input */ 3829 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3830 /* unmute amp left and right */ 3831 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, 3832 /* set connection select to line in (default select for this ADC) */ 3833 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, 3834 /* unmute Line-Out mixer amp left and right (volume = 0) */ 3835 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3836 /* mute pin widget amp left and right (no gain on this amp) */ 3837 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3838 /* unmute HP mixer amp left and right (volume = 0) */ 3839 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3840 /* mute pin widget amp left and right (no gain on this amp) */ 3841 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3842 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & 3843 * Line In 2 = 0x03 3844 */ 3845 /* mute analog inputs */ 3846 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3847 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3848 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 3849 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 3850 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3851 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ 3852 /* Unmute Front out path */ 3853 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3854 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3855 /* Unmute Headphone out path */ 3856 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3857 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3858 /* Unmute Mono out path */ 3859 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3860 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3861 { } 3862}; 3863 3864/* Initialisation sequence for ALC260 as configured in Fujitsu S702x 3865 * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD 3866 * audio = 0x16, internal speaker = 0x10. 3867 */ 3868static struct hda_verb alc260_fujitsu_init_verbs[] = { 3869 /* Disable all GPIOs */ 3870 {0x01, AC_VERB_SET_GPIO_MASK, 0}, 3871 /* Internal speaker is connected to headphone pin */ 3872 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3873 /* Headphone/Line-out jack connects to Line1 pin; make it an output */ 3874 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3875 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */ 3876 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3877 /* Ensure all other unused pins are disabled and muted. */ 3878 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3879 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3880 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3881 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3882 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3883 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3884 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3885 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3886 3887 /* Disable digital (SPDIF) pins */ 3888 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3889 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3890 3891 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus 3892 * when acting as an output. 3893 */ 3894 {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, 3895 3896 /* Start with output sum widgets muted and their output gains at min */ 3897 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3898 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3899 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3900 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3901 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3902 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3903 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3904 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3905 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3906 3907 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */ 3908 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3909 /* Unmute Line1 pin widget output buffer since it starts as an output. 3910 * If the pin mode is changed by the user the pin mode control will 3911 * take care of enabling the pin's input/output buffers as needed. 3912 * Therefore there's no need to enable the input buffer at this 3913 * stage. 3914 */ 3915 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3916 /* Unmute input buffer of pin widget used for Line-in (no equiv 3917 * mixer ctrl) 3918 */ 3919 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3920 3921 /* Mute capture amp left and right */ 3922 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3923 /* Set ADC connection select to match default mixer setting - line 3924 * in (on mic1 pin) 3925 */ 3926 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 3927 3928 /* Do the same for the second ADC: mute capture input amp and 3929 * set ADC connection to line in (on mic1 pin) 3930 */ 3931 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3932 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 3933 3934 /* Mute all inputs to mixer widget (even unconnected ones) */ 3935 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 3936 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 3937 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 3938 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 3939 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 3940 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 3941 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 3942 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 3943 3944 { } 3945}; 3946 3947/* Initialisation sequence for ALC260 as configured in Acer TravelMate and 3948 * similar laptops (adapted from Fujitsu init verbs). 3949 */ 3950static struct hda_verb alc260_acer_init_verbs[] = { 3951 /* On TravelMate laptops, GPIO 0 enables the internal speaker and 3952 * the headphone jack. Turn this on and rely on the standard mute 3953 * methods whenever the user wants to turn these outputs off. 3954 */ 3955 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 3956 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 3957 {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, 3958 /* Internal speaker/Headphone jack is connected to Line-out pin */ 3959 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3960 /* Internal microphone/Mic jack is connected to Mic1 pin */ 3961 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, 3962 /* Line In jack is connected to Line1 pin */ 3963 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3964 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */ 3965 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3966 /* Ensure all other unused pins are disabled and muted. */ 3967 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3968 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3969 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3970 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3971 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3972 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3973 /* Disable digital (SPDIF) pins */ 3974 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3975 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3976 3977 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum 3978 * bus when acting as outputs. 3979 */ 3980 {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, 3981 {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, 3982 3983 /* Start with output sum widgets muted and their output gains at min */ 3984 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3985 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3986 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3987 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3988 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3989 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3990 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3991 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3992 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3993 3994 /* Unmute Line-out pin widget amp left and right 3995 * (no equiv mixer ctrl) 3996 */ 3997 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3998 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */ 3999 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4000 /* Unmute Mic1 and Line1 pin widget input buffers since they start as 4001 * inputs. If the pin mode is changed by the user the pin mode control 4002 * will take care of enabling the pin's input/output buffers as needed. 4003 * Therefore there's no need to enable the input buffer at this 4004 * stage. 4005 */ 4006 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4007 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4008 4009 /* Mute capture amp left and right */ 4010 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4011 /* Set ADC connection select to match default mixer setting - mic 4012 * (on mic1 pin) 4013 */ 4014 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 4015 4016 /* Do similar with the second ADC: mute capture input amp and 4017 * set ADC connection to mic to match ALSA's default state. 4018 */ 4019 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4020 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 4021 4022 /* Mute all inputs to mixer widget (even unconnected ones) */ 4023 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 4024 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 4025 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 4026 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 4027 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 4028 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 4029 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 4030 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 4031 4032 { } 4033}; 4034 4035static struct hda_verb alc260_will_verbs[] = { 4036 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4037 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, 4038 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, 4039 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4040 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, 4041 {0x1a, AC_VERB_SET_PROC_COEF, 0x3040}, 4042 {} 4043}; 4044 4045static struct hda_verb alc260_replacer_672v_verbs[] = { 4046 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4047 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, 4048 {0x1a, AC_VERB_SET_PROC_COEF, 0x3050}, 4049 4050 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 4051 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 4052 {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, 4053 4054 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 4055 {} 4056}; 4057 4058/* toggle speaker-output according to the hp-jack state */ 4059static void alc260_replacer_672v_automute(struct hda_codec *codec) 4060{ 4061 unsigned int present; 4062 4063 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */ 4064 present = snd_hda_codec_read(codec, 0x0f, 0, 4065 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 4066 if (present) { 4067 snd_hda_codec_write_cache(codec, 0x01, 0, 4068 AC_VERB_SET_GPIO_DATA, 1); 4069 snd_hda_codec_write_cache(codec, 0x0f, 0, 4070 AC_VERB_SET_PIN_WIDGET_CONTROL, 4071 PIN_HP); 4072 } else { 4073 snd_hda_codec_write_cache(codec, 0x01, 0, 4074 AC_VERB_SET_GPIO_DATA, 0); 4075 snd_hda_codec_write_cache(codec, 0x0f, 0, 4076 AC_VERB_SET_PIN_WIDGET_CONTROL, 4077 PIN_OUT); 4078 } 4079} 4080 4081static void alc260_replacer_672v_unsol_event(struct hda_codec *codec, 4082 unsigned int res) 4083{ 4084 if ((res >> 26) == ALC880_HP_EVENT) 4085 alc260_replacer_672v_automute(codec); 4086} 4087 4088/* Test configuration for debugging, modelled after the ALC880 test 4089 * configuration. 4090 */ 4091#ifdef CONFIG_SND_DEBUG 4092static hda_nid_t alc260_test_dac_nids[1] = { 4093 0x02, 4094}; 4095static hda_nid_t alc260_test_adc_nids[2] = { 4096 0x04, 0x05, 4097}; 4098/* For testing the ALC260, each input MUX needs its own definition since 4099 * the signal assignments are different. This assumes that the first ADC 4100 * is NID 0x04. 4101 */ 4102static struct hda_input_mux alc260_test_capture_sources[2] = { 4103 { 4104 .num_items = 7, 4105 .items = { 4106 { "MIC1 pin", 0x0 }, 4107 { "MIC2 pin", 0x1 }, 4108 { "LINE1 pin", 0x2 }, 4109 { "LINE2 pin", 0x3 }, 4110 { "CD pin", 0x4 }, 4111 { "LINE-OUT pin", 0x5 }, 4112 { "HP-OUT pin", 0x6 }, 4113 }, 4114 }, 4115 { 4116 .num_items = 8, 4117 .items = { 4118 { "MIC1 pin", 0x0 }, 4119 { "MIC2 pin", 0x1 }, 4120 { "LINE1 pin", 0x2 }, 4121 { "LINE2 pin", 0x3 }, 4122 { "CD pin", 0x4 }, 4123 { "Mixer", 0x5 }, 4124 { "LINE-OUT pin", 0x6 }, 4125 { "HP-OUT pin", 0x7 }, 4126 }, 4127 }, 4128}; 4129static struct snd_kcontrol_new alc260_test_mixer[] = { 4130 /* Output driver widgets */ 4131 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 4132 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), 4133 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT), 4134 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT), 4135 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), 4136 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), 4137 4138 /* Modes for retasking pin widgets 4139 * Note: the ALC260 doesn't seem to act on requests to enable mic 4140 * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't 4141 * mention this restriction. At this stage it's not clear whether 4142 * this behaviour is intentional or is a hardware bug in chip 4143 * revisions available at least up until early 2006. Therefore for 4144 * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all 4145 * choices, but if it turns out that the lack of mic bias for these 4146 * NIDs is intentional we could change their modes from 4147 * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. 4148 */ 4149 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), 4150 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), 4151 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), 4152 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT), 4153 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT), 4154 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT), 4155 4156 /* Loopback mixer controls */ 4157 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT), 4158 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT), 4159 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT), 4160 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT), 4161 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT), 4162 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT), 4163 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT), 4164 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), 4165 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 4166 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 4167 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 4168 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 4169 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), 4170 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), 4171 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), 4172 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT), 4173 4174 /* Controls for GPIO pins, assuming they are configured as outputs */ 4175 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), 4176 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), 4177 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), 4178 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), 4179 4180 /* Switches to allow the digital IO pins to be enabled. The datasheet 4181 * is ambigious as to which NID is which; testing on laptops which 4182 * make this output available should provide clarification. 4183 */ 4184 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01), 4185 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01), 4186 4187 { } /* end */ 4188}; 4189static struct hda_verb alc260_test_init_verbs[] = { 4190 /* Enable all GPIOs as outputs with an initial value of 0 */ 4191 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f}, 4192 {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, 4193 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f}, 4194 4195 /* Enable retasking pins as output, initially without power amp */ 4196 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4197 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4198 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4199 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4200 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4201 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4202 4203 /* Disable digital (SPDIF) pins initially, but users can enable 4204 * them via a mixer switch. In the case of SPDIF-out, this initverb 4205 * payload also sets the generation to 0, output to be in "consumer" 4206 * PCM format, copyright asserted, no pre-emphasis and no validity 4207 * control. 4208 */ 4209 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, 4210 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, 4211 4212 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the 4213 * OUT1 sum bus when acting as an output. 4214 */ 4215 {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, 4216 {0x0c, AC_VERB_SET_CONNECT_SEL, 0}, 4217 {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, 4218 {0x0e, AC_VERB_SET_CONNECT_SEL, 0}, 4219 4220 /* Start with output sum widgets muted and their output gains at min */ 4221 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4222 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4223 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4224 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4225 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4226 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4227 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4228 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4229 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4230 4231 /* Unmute retasking pin widget output buffers since the default 4232 * state appears to be output. As the pin mode is changed by the 4233 * user the pin mode control will take care of enabling the pin's 4234 * input/output buffers as needed. 4235 */ 4236 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4237 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4238 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4239 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4240 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4241 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4242 /* Also unmute the mono-out pin widget */ 4243 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4244 4245 /* Mute capture amp left and right */ 4246 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4247 /* Set ADC connection select to match default mixer setting (mic1 4248 * pin) 4249 */ 4250 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 4251 4252 /* Do the same for the second ADC: mute capture input amp and 4253 * set ADC connection to mic1 pin 4254 */ 4255 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4256 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 4257 4258 /* Mute all inputs to mixer widget (even unconnected ones) */ 4259 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 4260 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 4261 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 4262 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 4263 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 4264 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 4265 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 4266 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 4267 4268 { } 4269}; 4270#endif 4271 4272static struct hda_pcm_stream alc260_pcm_analog_playback = { 4273 .substreams = 1, 4274 .channels_min = 2, 4275 .channels_max = 2, 4276}; 4277 4278static struct hda_pcm_stream alc260_pcm_analog_capture = { 4279 .substreams = 1, 4280 .channels_min = 2, 4281 .channels_max = 2, 4282}; 4283 4284#define alc260_pcm_digital_playback alc880_pcm_digital_playback 4285#define alc260_pcm_digital_capture alc880_pcm_digital_capture 4286 4287/* 4288 * for BIOS auto-configuration 4289 */ 4290 4291static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid, 4292 const char *pfx) 4293{ 4294 hda_nid_t nid_vol; 4295 unsigned long vol_val, sw_val; 4296 char name[32]; 4297 int err; 4298 4299 if (nid >= 0x0f && nid < 0x11) { 4300 nid_vol = nid - 0x7; 4301 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT); 4302 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); 4303 } else if (nid == 0x11) { 4304 nid_vol = nid - 0x7; 4305 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT); 4306 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); 4307 } else if (nid >= 0x12 && nid <= 0x15) { 4308 nid_vol = 0x08; 4309 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT); 4310 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); 4311 } else 4312 return 0; /* N/A */ 4313 4314 snprintf(name, sizeof(name), "%s Playback Volume", pfx); 4315 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val); 4316 if (err < 0) 4317 return err; 4318 snprintf(name, sizeof(name), "%s Playback Switch", pfx); 4319 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val); 4320 if (err < 0) 4321 return err; 4322 return 1; 4323} 4324 4325/* add playback controls from the parsed DAC table */ 4326static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, 4327 const struct auto_pin_cfg *cfg) 4328{ 4329 hda_nid_t nid; 4330 int err; 4331 4332 spec->multiout.num_dacs = 1; 4333 spec->multiout.dac_nids = spec->private_dac_nids; 4334 spec->multiout.dac_nids[0] = 0x02; 4335 4336 nid = cfg->line_out_pins[0]; 4337 if (nid) { 4338 err = alc260_add_playback_controls(spec, nid, "Front"); 4339 if (err < 0) 4340 return err; 4341 } 4342 4343 nid = cfg->speaker_pins[0]; 4344 if (nid) { 4345 err = alc260_add_playback_controls(spec, nid, "Speaker"); 4346 if (err < 0) 4347 return err; 4348 } 4349 4350 nid = cfg->hp_pins[0]; 4351 if (nid) { 4352 err = alc260_add_playback_controls(spec, nid, "Headphone"); 4353 if (err < 0) 4354 return err; 4355 } 4356 return 0; 4357} 4358 4359/* create playback/capture controls for input pins */ 4360static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec, 4361 const struct auto_pin_cfg *cfg) 4362{ 4363 struct hda_input_mux *imux = &spec->private_imux; 4364 int i, err, idx; 4365 4366 for (i = 0; i < AUTO_PIN_LAST; i++) { 4367 if (cfg->input_pins[i] >= 0x12) { 4368 idx = cfg->input_pins[i] - 0x12; 4369 err = new_analog_input(spec, cfg->input_pins[i], 4370 auto_pin_cfg_labels[i], idx, 4371 0x07); 4372 if (err < 0) 4373 return err; 4374 imux->items[imux->num_items].label = 4375 auto_pin_cfg_labels[i]; 4376 imux->items[imux->num_items].index = idx; 4377 imux->num_items++; 4378 } 4379 if (cfg->input_pins[i] >= 0x0f && cfg->input_pins[i] <= 0x10){ 4380 idx = cfg->input_pins[i] - 0x09; 4381 err = new_analog_input(spec, cfg->input_pins[i], 4382 auto_pin_cfg_labels[i], idx, 4383 0x07); 4384 if (err < 0) 4385 return err; 4386 imux->items[imux->num_items].label = 4387 auto_pin_cfg_labels[i]; 4388 imux->items[imux->num_items].index = idx; 4389 imux->num_items++; 4390 } 4391 } 4392 return 0; 4393} 4394 4395static void alc260_auto_set_output_and_unmute(struct hda_codec *codec, 4396 hda_nid_t nid, int pin_type, 4397 int sel_idx) 4398{ 4399 /* set as output */ 4400 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 4401 pin_type); 4402 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 4403 AMP_OUT_UNMUTE); 4404 /* need the manual connection? */ 4405 if (nid >= 0x12) { 4406 int idx = nid - 0x12; 4407 snd_hda_codec_write(codec, idx + 0x0b, 0, 4408 AC_VERB_SET_CONNECT_SEL, sel_idx); 4409 } 4410} 4411 4412static void alc260_auto_init_multi_out(struct hda_codec *codec) 4413{ 4414 struct alc_spec *spec = codec->spec; 4415 hda_nid_t nid; 4416 4417 alc_subsystem_id(codec, 0x10, 0x15, 0x0f); 4418 nid = spec->autocfg.line_out_pins[0]; 4419 if (nid) { 4420 int pin_type = get_pin_type(spec->autocfg.line_out_type); 4421 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0); 4422 } 4423 4424 nid = spec->autocfg.speaker_pins[0]; 4425 if (nid) 4426 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); 4427 4428 nid = spec->autocfg.hp_pins[0]; 4429 if (nid) 4430 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0); 4431} 4432 4433#define ALC260_PIN_CD_NID 0x16 4434static void alc260_auto_init_analog_input(struct hda_codec *codec) 4435{ 4436 struct alc_spec *spec = codec->spec; 4437 int i; 4438 4439 for (i = 0; i < AUTO_PIN_LAST; i++) { 4440 hda_nid_t nid = spec->autocfg.input_pins[i]; 4441 if (nid >= 0x12) { 4442 snd_hda_codec_write(codec, nid, 0, 4443 AC_VERB_SET_PIN_WIDGET_CONTROL, 4444 i <= AUTO_PIN_FRONT_MIC ? 4445 PIN_VREF80 : PIN_IN); 4446 if (nid != ALC260_PIN_CD_NID) 4447 snd_hda_codec_write(codec, nid, 0, 4448 AC_VERB_SET_AMP_GAIN_MUTE, 4449 AMP_OUT_MUTE); 4450 } 4451 } 4452} 4453 4454/* 4455 * generic initialization of ADC, input mixers and output mixers 4456 */ 4457static struct hda_verb alc260_volume_init_verbs[] = { 4458 /* 4459 * Unmute ADC0-1 and set the default input to mic-in 4460 */ 4461 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 4462 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4463 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 4464 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4465 4466 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 4467 * mixer widget 4468 * Note: PASD motherboards uses the Line In 2 as the input for 4469 * front panel mic (mic 2) 4470 */ 4471 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 4472 /* mute analog inputs */ 4473 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4474 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4475 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4476 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4477 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4478 4479 /* 4480 * Set up output mixers (0x08 - 0x0a) 4481 */ 4482 /* set vol=0 to output mixers */ 4483 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4484 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4485 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4486 /* set up input amps for analog loopback */ 4487 /* Amp Indices: DAC = 0, mixer = 1 */ 4488 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4489 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4490 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4491 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4492 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4493 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4494 4495 { } 4496}; 4497 4498static int alc260_parse_auto_config(struct hda_codec *codec) 4499{ 4500 struct alc_spec *spec = codec->spec; 4501 unsigned int wcap; 4502 int err; 4503 static hda_nid_t alc260_ignore[] = { 0x17, 0 }; 4504 4505 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 4506 alc260_ignore); 4507 if (err < 0) 4508 return err; 4509 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); 4510 if (err < 0) 4511 return err; 4512 if (!spec->kctl_alloc) 4513 return 0; /* can't find valid BIOS pin config */ 4514 err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); 4515 if (err < 0) 4516 return err; 4517 4518 spec->multiout.max_channels = 2; 4519 4520 if (spec->autocfg.dig_out_pin) 4521 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; 4522 if (spec->kctl_alloc) 4523 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 4524 4525 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; 4526 4527 spec->num_mux_defs = 1; 4528 spec->input_mux = &spec->private_imux; 4529 4530 /* check whether NID 0x04 is valid */ 4531 wcap = get_wcaps(codec, 0x04); 4532 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ 4533 if (wcap != AC_WID_AUD_IN) { 4534 spec->adc_nids = alc260_adc_nids_alt; 4535 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt); 4536 spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer; 4537 } else { 4538 spec->adc_nids = alc260_adc_nids; 4539 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); 4540 spec->mixers[spec->num_mixers] = alc260_capture_mixer; 4541 } 4542 spec->num_mixers++; 4543 4544 return 1; 4545} 4546 4547/* additional initialization for auto-configuration model */ 4548static void alc260_auto_init(struct hda_codec *codec) 4549{ 4550 alc260_auto_init_multi_out(codec); 4551 alc260_auto_init_analog_input(codec); 4552} 4553 4554#ifdef CONFIG_SND_HDA_POWER_SAVE 4555static struct hda_amp_list alc260_loopbacks[] = { 4556 { 0x07, HDA_INPUT, 0 }, 4557 { 0x07, HDA_INPUT, 1 }, 4558 { 0x07, HDA_INPUT, 2 }, 4559 { 0x07, HDA_INPUT, 3 }, 4560 { 0x07, HDA_INPUT, 4 }, 4561 { } /* end */ 4562}; 4563#endif 4564 4565/* 4566 * ALC260 configurations 4567 */ 4568static const char *alc260_models[ALC260_MODEL_LAST] = { 4569 [ALC260_BASIC] = "basic", 4570 [ALC260_HP] = "hp", 4571 [ALC260_HP_3013] = "hp-3013", 4572 [ALC260_FUJITSU_S702X] = "fujitsu", 4573 [ALC260_ACER] = "acer", 4574 [ALC260_WILL] = "will", 4575 [ALC260_REPLACER_672V] = "replacer", 4576#ifdef CONFIG_SND_DEBUG 4577 [ALC260_TEST] = "test", 4578#endif 4579 [ALC260_AUTO] = "auto", 4580}; 4581 4582static struct snd_pci_quirk alc260_cfg_tbl[] = { 4583 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), 4584 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), 4585 SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013), 4586 SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013), 4587 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013), 4588 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP), 4589 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013), 4590 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013), 4591 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP), 4592 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP), 4593 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP), 4594 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC), 4595 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC), 4596 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), 4597 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), 4598 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), 4599 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL), 4600 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V), 4601 {} 4602}; 4603 4604static struct alc_config_preset alc260_presets[] = { 4605 [ALC260_BASIC] = { 4606 .mixers = { alc260_base_output_mixer, 4607 alc260_input_mixer, 4608 alc260_pc_beep_mixer, 4609 alc260_capture_mixer }, 4610 .init_verbs = { alc260_init_verbs }, 4611 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4612 .dac_nids = alc260_dac_nids, 4613 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), 4614 .adc_nids = alc260_adc_nids, 4615 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4616 .channel_mode = alc260_modes, 4617 .input_mux = &alc260_capture_source, 4618 }, 4619 [ALC260_HP] = { 4620 .mixers = { alc260_base_output_mixer, 4621 alc260_input_mixer, 4622 alc260_capture_alt_mixer }, 4623 .init_verbs = { alc260_init_verbs }, 4624 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4625 .dac_nids = alc260_dac_nids, 4626 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), 4627 .adc_nids = alc260_hp_adc_nids, 4628 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4629 .channel_mode = alc260_modes, 4630 .input_mux = &alc260_capture_source, 4631 }, 4632 [ALC260_HP_3013] = { 4633 .mixers = { alc260_hp_3013_mixer, 4634 alc260_input_mixer, 4635 alc260_capture_alt_mixer }, 4636 .init_verbs = { alc260_hp_3013_init_verbs }, 4637 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4638 .dac_nids = alc260_dac_nids, 4639 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), 4640 .adc_nids = alc260_hp_adc_nids, 4641 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4642 .channel_mode = alc260_modes, 4643 .input_mux = &alc260_capture_source, 4644 }, 4645 [ALC260_FUJITSU_S702X] = { 4646 .mixers = { alc260_fujitsu_mixer, 4647 alc260_capture_mixer }, 4648 .init_verbs = { alc260_fujitsu_init_verbs }, 4649 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4650 .dac_nids = alc260_dac_nids, 4651 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), 4652 .adc_nids = alc260_dual_adc_nids, 4653 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4654 .channel_mode = alc260_modes, 4655 .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources), 4656 .input_mux = alc260_fujitsu_capture_sources, 4657 }, 4658 [ALC260_ACER] = { 4659 .mixers = { alc260_acer_mixer, 4660 alc260_capture_mixer }, 4661 .init_verbs = { alc260_acer_init_verbs }, 4662 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4663 .dac_nids = alc260_dac_nids, 4664 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), 4665 .adc_nids = alc260_dual_adc_nids, 4666 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4667 .channel_mode = alc260_modes, 4668 .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), 4669 .input_mux = alc260_acer_capture_sources, 4670 }, 4671 [ALC260_WILL] = { 4672 .mixers = { alc260_will_mixer, 4673 alc260_capture_mixer }, 4674 .init_verbs = { alc260_init_verbs, alc260_will_verbs }, 4675 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4676 .dac_nids = alc260_dac_nids, 4677 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), 4678 .adc_nids = alc260_adc_nids, 4679 .dig_out_nid = ALC260_DIGOUT_NID, 4680 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4681 .channel_mode = alc260_modes, 4682 .input_mux = &alc260_capture_source, 4683 }, 4684 [ALC260_REPLACER_672V] = { 4685 .mixers = { alc260_replacer_672v_mixer, 4686 alc260_capture_mixer }, 4687 .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, 4688 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4689 .dac_nids = alc260_dac_nids, 4690 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), 4691 .adc_nids = alc260_adc_nids, 4692 .dig_out_nid = ALC260_DIGOUT_NID, 4693 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4694 .channel_mode = alc260_modes, 4695 .input_mux = &alc260_capture_source, 4696 .unsol_event = alc260_replacer_672v_unsol_event, 4697 .init_hook = alc260_replacer_672v_automute, 4698 }, 4699#ifdef CONFIG_SND_DEBUG 4700 [ALC260_TEST] = { 4701 .mixers = { alc260_test_mixer, 4702 alc260_capture_mixer }, 4703 .init_verbs = { alc260_test_init_verbs }, 4704 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), 4705 .dac_nids = alc260_test_dac_nids, 4706 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids), 4707 .adc_nids = alc260_test_adc_nids, 4708 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4709 .channel_mode = alc260_modes, 4710 .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources), 4711 .input_mux = alc260_test_capture_sources, 4712 }, 4713#endif 4714}; 4715 4716static int patch_alc260(struct hda_codec *codec) 4717{ 4718 struct alc_spec *spec; 4719 int err, board_config; 4720 4721 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 4722 if (spec == NULL) 4723 return -ENOMEM; 4724 4725 codec->spec = spec; 4726 4727 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST, 4728 alc260_models, 4729 alc260_cfg_tbl); 4730 if (board_config < 0) { 4731 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, " 4732 "trying auto-probe from BIOS...\n"); 4733 board_config = ALC260_AUTO; 4734 } 4735 4736 if (board_config == ALC260_AUTO) { 4737 /* automatic parse from the BIOS config */ 4738 err = alc260_parse_auto_config(codec); 4739 if (err < 0) { 4740 alc_free(codec); 4741 return err; 4742 } else if (!err) { 4743 printk(KERN_INFO 4744 "hda_codec: Cannot set up configuration " 4745 "from BIOS. Using base mode...\n"); 4746 board_config = ALC260_BASIC; 4747 } 4748 } 4749 4750 if (board_config != ALC260_AUTO) 4751 setup_preset(spec, &alc260_presets[board_config]); 4752 4753 spec->stream_name_analog = "ALC260 Analog"; 4754 spec->stream_analog_playback = &alc260_pcm_analog_playback; 4755 spec->stream_analog_capture = &alc260_pcm_analog_capture; 4756 4757 spec->stream_name_digital = "ALC260 Digital"; 4758 spec->stream_digital_playback = &alc260_pcm_digital_playback; 4759 spec->stream_digital_capture = &alc260_pcm_digital_capture; 4760 4761 codec->patch_ops = alc_patch_ops; 4762 if (board_config == ALC260_AUTO) 4763 spec->init_hook = alc260_auto_init; 4764#ifdef CONFIG_SND_HDA_POWER_SAVE 4765 if (!spec->loopback.amplist) 4766 spec->loopback.amplist = alc260_loopbacks; 4767#endif 4768 4769 return 0; 4770} 4771 4772 4773/* 4774 * ALC882 support 4775 * 4776 * ALC882 is almost identical with ALC880 but has cleaner and more flexible 4777 * configuration. Each pin widget can choose any input DACs and a mixer. 4778 * Each ADC is connected from a mixer of all inputs. This makes possible 4779 * 6-channel independent captures. 4780 * 4781 * In addition, an independent DAC for the multi-playback (not used in this 4782 * driver yet). 4783 */ 4784#define ALC882_DIGOUT_NID 0x06 4785#define ALC882_DIGIN_NID 0x0a 4786 4787static struct hda_channel_mode alc882_ch_modes[1] = { 4788 { 8, NULL } 4789}; 4790 4791static hda_nid_t alc882_dac_nids[4] = { 4792 /* front, rear, clfe, rear_surr */ 4793 0x02, 0x03, 0x04, 0x05 4794}; 4795 4796/* identical with ALC880 */ 4797#define alc882_adc_nids alc880_adc_nids 4798#define alc882_adc_nids_alt alc880_adc_nids_alt 4799 4800/* input MUX */ 4801/* FIXME: should be a matrix-type input source selection */ 4802 4803static struct hda_input_mux alc882_capture_source = { 4804 .num_items = 4, 4805 .items = { 4806 { "Mic", 0x0 }, 4807 { "Front Mic", 0x1 }, 4808 { "Line", 0x2 }, 4809 { "CD", 0x4 }, 4810 }, 4811}; 4812#define alc882_mux_enum_info alc_mux_enum_info 4813#define alc882_mux_enum_get alc_mux_enum_get 4814 4815static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, 4816 struct snd_ctl_elem_value *ucontrol) 4817{ 4818 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 4819 struct alc_spec *spec = codec->spec; 4820 const struct hda_input_mux *imux = spec->input_mux; 4821 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 4822 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; 4823 hda_nid_t nid = capture_mixers[adc_idx]; 4824 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 4825 unsigned int i, idx; 4826 4827 idx = ucontrol->value.enumerated.item[0]; 4828 if (idx >= imux->num_items) 4829 idx = imux->num_items - 1; 4830 if (*cur_val == idx) 4831 return 0; 4832 for (i = 0; i < imux->num_items; i++) { 4833 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; 4834 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 4835 imux->items[i].index, 4836 HDA_AMP_MUTE, v); 4837 } 4838 *cur_val = idx; 4839 return 1; 4840} 4841 4842/* 4843 * 2ch mode 4844 */ 4845static struct hda_verb alc882_3ST_ch2_init[] = { 4846 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 4847 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 4848 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 4849 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 4850 { } /* end */ 4851}; 4852 4853/* 4854 * 6ch mode 4855 */ 4856static struct hda_verb alc882_3ST_ch6_init[] = { 4857 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4858 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 4859 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, 4860 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4861 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 4862 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, 4863 { } /* end */ 4864}; 4865 4866static struct hda_channel_mode alc882_3ST_6ch_modes[2] = { 4867 { 2, alc882_3ST_ch2_init }, 4868 { 6, alc882_3ST_ch6_init }, 4869}; 4870 4871/* 4872 * 6ch mode 4873 */ 4874static struct hda_verb alc882_sixstack_ch6_init[] = { 4875 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 4876 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4877 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4878 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4879 { } /* end */ 4880}; 4881 4882/* 4883 * 8ch mode 4884 */ 4885static struct hda_verb alc882_sixstack_ch8_init[] = { 4886 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4887 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4888 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4889 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4890 { } /* end */ 4891}; 4892 4893static struct hda_channel_mode alc882_sixstack_modes[2] = { 4894 { 6, alc882_sixstack_ch6_init }, 4895 { 8, alc882_sixstack_ch8_init }, 4896}; 4897 4898/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 4899 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 4900 */ 4901static struct snd_kcontrol_new alc882_base_mixer[] = { 4902 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4903 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 4904 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 4905 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 4906 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 4907 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 4908 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 4909 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 4910 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 4911 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 4912 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 4913 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4914 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4915 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4916 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4917 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4918 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 4919 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4920 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 4921 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 4922 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 4923 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 4924 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 4925 { } /* end */ 4926}; 4927 4928static struct snd_kcontrol_new alc882_w2jc_mixer[] = { 4929 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4930 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 4931 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4932 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4933 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4934 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4935 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4936 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 4937 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4938 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 4939 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 4940 { } /* end */ 4941}; 4942 4943static struct snd_kcontrol_new alc882_targa_mixer[] = { 4944 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4945 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 4946 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 4947 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4948 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4949 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4950 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4951 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4952 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4953 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 4954 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 4955 { } /* end */ 4956}; 4957 4958/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ??? 4959 * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c 4960 */ 4961static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = { 4962 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4963 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 4964 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 4965 HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT), 4966 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4967 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4968 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4969 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4970 HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT), 4971 HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT), 4972 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4973 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4974 { } /* end */ 4975}; 4976 4977static struct snd_kcontrol_new alc882_chmode_mixer[] = { 4978 { 4979 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4980 .name = "Channel Mode", 4981 .info = alc_ch_mode_info, 4982 .get = alc_ch_mode_get, 4983 .put = alc_ch_mode_put, 4984 }, 4985 { } /* end */ 4986}; 4987 4988static struct hda_verb alc882_init_verbs[] = { 4989 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 4990 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4991 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4992 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4993 /* Rear mixer */ 4994 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4995 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4996 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4997 /* CLFE mixer */ 4998 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4999 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5000 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5001 /* Side mixer */ 5002 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5003 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5004 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5005 5006 /* Front Pin: output 0 (0x0c) */ 5007 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5008 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5009 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 5010 /* Rear Pin: output 1 (0x0d) */ 5011 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5012 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5013 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 5014 /* CLFE Pin: output 2 (0x0e) */ 5015 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5016 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5017 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, 5018 /* Side Pin: output 3 (0x0f) */ 5019 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5020 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5021 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, 5022 /* Mic (rear) pin: input vref at 80% */ 5023 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5024 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5025 /* Front Mic pin: input vref at 80% */ 5026 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5027 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5028 /* Line In pin: input */ 5029 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 5030 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5031 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 5032 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5033 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5034 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 5035 /* CD pin widget for input */ 5036 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 5037 5038 /* FIXME: use matrix-type input source selection */ 5039 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 5040 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 5041 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5042 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5043 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5044 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5045 /* Input mixer2 */ 5046 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5047 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5048 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5049 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5050 /* Input mixer3 */ 5051 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5052 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5053 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5054 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5055 /* ADC1: mute amp left and right */ 5056 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5057 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 5058 /* ADC2: mute amp left and right */ 5059 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5060 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 5061 /* ADC3: mute amp left and right */ 5062 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5063 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 5064 5065 { } 5066}; 5067 5068static struct hda_verb alc882_eapd_verbs[] = { 5069 /* change to EAPD mode */ 5070 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 5071 {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, 5072 { } 5073}; 5074 5075/* Mac Pro test */ 5076static struct snd_kcontrol_new alc882_macpro_mixer[] = { 5077 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5078 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5079 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT), 5080 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), 5081 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), 5082 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT), 5083 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT), 5084 { } /* end */ 5085}; 5086 5087static struct hda_verb alc882_macpro_init_verbs[] = { 5088 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 5089 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5090 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5091 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5092 /* Front Pin: output 0 (0x0c) */ 5093 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5094 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5095 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 5096 /* Front Mic pin: input vref at 80% */ 5097 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5098 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5099 /* Speaker: output */ 5100 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5101 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5102 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04}, 5103 /* Headphone output (output 0 - 0x0c) */ 5104 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5105 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5106 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, 5107 5108 /* FIXME: use matrix-type input source selection */ 5109 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 5110 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 5111 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5112 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5113 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5114 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5115 /* Input mixer2 */ 5116 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5117 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5118 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5119 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5120 /* Input mixer3 */ 5121 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5122 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5123 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5124 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5125 /* ADC1: mute amp left and right */ 5126 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5127 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 5128 /* ADC2: mute amp left and right */ 5129 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5130 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 5131 /* ADC3: mute amp left and right */ 5132 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5133 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 5134 5135 { } 5136}; 5137 5138/* iMac 24 mixer. */ 5139static struct snd_kcontrol_new alc885_imac24_mixer[] = { 5140 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT), 5141 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT), 5142 { } /* end */ 5143}; 5144 5145/* iMac 24 init verbs. */ 5146static struct hda_verb alc885_imac24_init_verbs[] = { 5147 /* Internal speakers: output 0 (0x0c) */ 5148 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5149 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5150 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, 5151 /* Internal speakers: output 0 (0x0c) */ 5152 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5153 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5154 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, 5155 /* Headphone: output 0 (0x0c) */ 5156 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5157 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5158 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 5159 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 5160 /* Front Mic: input vref at 80% */ 5161 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5162 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5163 { } 5164}; 5165 5166/* Toggle speaker-output according to the hp-jack state */ 5167static void alc885_imac24_automute(struct hda_codec *codec) 5168{ 5169 unsigned int present; 5170 5171 present = snd_hda_codec_read(codec, 0x14, 0, 5172 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 5173 snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0, 5174 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 5175 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0, 5176 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 5177} 5178 5179/* Processes unsolicited events. */ 5180static void alc885_imac24_unsol_event(struct hda_codec *codec, 5181 unsigned int res) 5182{ 5183 /* Headphone insertion or removal. */ 5184 if ((res >> 26) == ALC880_HP_EVENT) 5185 alc885_imac24_automute(codec); 5186} 5187 5188static struct hda_verb alc882_targa_verbs[] = { 5189 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5190 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5191 5192 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5193 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5194 5195 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 5196 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ 5197 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 5198 5199 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 5200 {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 5201 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 5202 {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 5203 { } /* end */ 5204}; 5205 5206/* toggle speaker-output according to the hp-jack state */ 5207static void alc882_targa_automute(struct hda_codec *codec) 5208{ 5209 unsigned int present; 5210 5211 present = snd_hda_codec_read(codec, 0x14, 0, 5212 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 5213 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, 5214 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 5215 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA, 5216 present ? 1 : 3); 5217} 5218 5219static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res) 5220{ 5221 /* Looks like the unsol event is incompatible with the standard 5222 * definition. 4bit tag is placed at 26 bit! 5223 */ 5224 if (((res >> 26) == ALC880_HP_EVENT)) { 5225 alc882_targa_automute(codec); 5226 } 5227} 5228 5229static struct hda_verb alc882_asus_a7j_verbs[] = { 5230 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5231 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5232 5233 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5234 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5235 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5236 5237 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ 5238 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 5239 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ 5240 5241 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 5242 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ 5243 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 5244 { } /* end */ 5245}; 5246 5247static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) 5248{ 5249 unsigned int gpiostate, gpiomask, gpiodir; 5250 5251 gpiostate = snd_hda_codec_read(codec, codec->afg, 0, 5252 AC_VERB_GET_GPIO_DATA, 0); 5253 5254 if (!muted) 5255 gpiostate |= (1 << pin); 5256 else 5257 gpiostate &= ~(1 << pin); 5258 5259 gpiomask = snd_hda_codec_read(codec, codec->afg, 0, 5260 AC_VERB_GET_GPIO_MASK, 0); 5261 gpiomask |= (1 << pin); 5262 5263 gpiodir = snd_hda_codec_read(codec, codec->afg, 0, 5264 AC_VERB_GET_GPIO_DIRECTION, 0); 5265 gpiodir |= (1 << pin); 5266 5267 5268 snd_hda_codec_write(codec, codec->afg, 0, 5269 AC_VERB_SET_GPIO_MASK, gpiomask); 5270 snd_hda_codec_write(codec, codec->afg, 0, 5271 AC_VERB_SET_GPIO_DIRECTION, gpiodir); 5272 5273 msleep(1); 5274 5275 snd_hda_codec_write(codec, codec->afg, 0, 5276 AC_VERB_SET_GPIO_DATA, gpiostate); 5277} 5278 5279/* set up GPIO at initialization */ 5280static void alc885_macpro_init_hook(struct hda_codec *codec) 5281{ 5282 alc882_gpio_mute(codec, 0, 0); 5283 alc882_gpio_mute(codec, 1, 0); 5284} 5285 5286/* set up GPIO and update auto-muting at initialization */ 5287static void alc885_imac24_init_hook(struct hda_codec *codec) 5288{ 5289 alc885_macpro_init_hook(codec); 5290 alc885_imac24_automute(codec); 5291} 5292 5293/* 5294 * generic initialization of ADC, input mixers and output mixers 5295 */ 5296static struct hda_verb alc882_auto_init_verbs[] = { 5297 /* 5298 * Unmute ADC0-2 and set the default input to mic-in 5299 */ 5300 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 5301 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5302 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 5303 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5304 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 5305 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5306 5307 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 5308 * mixer widget 5309 * Note: PASD motherboards uses the Line In 2 as the input for 5310 * front panel mic (mic 2) 5311 */ 5312 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 5313 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5314 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5315 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5316 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5317 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5318 5319 /* 5320 * Set up output mixers (0x0c - 0x0f) 5321 */ 5322 /* set vol=0 to output mixers */ 5323 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5324 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5325 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5326 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5327 /* set up input amps for analog loopback */ 5328 /* Amp Indices: DAC = 0, mixer = 1 */ 5329 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5330 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5331 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5332 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5333 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5334 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5335 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5336 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5337 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5338 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5339 5340 /* FIXME: use matrix-type input source selection */ 5341 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 5342 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 5343 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 5344 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 5345 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 5346 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 5347 /* Input mixer2 */ 5348 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 5349 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 5350 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 5351 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 5352 /* Input mixer3 */ 5353 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 5354 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 5355 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 5356 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 5357 5358 { } 5359}; 5360 5361/* capture mixer elements */ 5362static struct snd_kcontrol_new alc882_capture_alt_mixer[] = { 5363 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5364 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5365 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5366 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5367 { 5368 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5369 /* The multiple "Capture Source" controls confuse alsamixer 5370 * So call somewhat different.. 5371 * FIXME: the controls appear in the "playback" view! 5372 */ 5373 /* .name = "Capture Source", */ 5374 .name = "Input Source", 5375 .count = 2, 5376 .info = alc882_mux_enum_info, 5377 .get = alc882_mux_enum_get, 5378 .put = alc882_mux_enum_put, 5379 }, 5380 { } /* end */ 5381}; 5382 5383static struct snd_kcontrol_new alc882_capture_mixer[] = { 5384 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), 5385 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), 5386 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), 5387 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), 5388 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), 5389 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), 5390 { 5391 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5392 /* The multiple "Capture Source" controls confuse alsamixer 5393 * So call somewhat different.. 5394 * FIXME: the controls appear in the "playback" view! 5395 */ 5396 /* .name = "Capture Source", */ 5397 .name = "Input Source", 5398 .count = 3, 5399 .info = alc882_mux_enum_info, 5400 .get = alc882_mux_enum_get, 5401 .put = alc882_mux_enum_put, 5402 }, 5403 { } /* end */ 5404}; 5405 5406#ifdef CONFIG_SND_HDA_POWER_SAVE 5407#define alc882_loopbacks alc880_loopbacks 5408#endif 5409 5410/* pcm configuration: identiacal with ALC880 */ 5411#define alc882_pcm_analog_playback alc880_pcm_analog_playback 5412#define alc882_pcm_analog_capture alc880_pcm_analog_capture 5413#define alc882_pcm_digital_playback alc880_pcm_digital_playback 5414#define alc882_pcm_digital_capture alc880_pcm_digital_capture 5415 5416/* 5417 * configuration and preset 5418 */ 5419static const char *alc882_models[ALC882_MODEL_LAST] = { 5420 [ALC882_3ST_DIG] = "3stack-dig", 5421 [ALC882_6ST_DIG] = "6stack-dig", 5422 [ALC882_ARIMA] = "arima", 5423 [ALC882_W2JC] = "w2jc", 5424 [ALC885_MACPRO] = "macpro", 5425 [ALC885_IMAC24] = "imac24", 5426 [ALC882_AUTO] = "auto", 5427}; 5428 5429static struct snd_pci_quirk alc882_cfg_tbl[] = { 5430 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG), 5431 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG), 5432 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), 5433 SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ 5434 SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), 5435 SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), 5436 SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG), 5437 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), 5438 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), 5439 {} 5440}; 5441 5442static struct alc_config_preset alc882_presets[] = { 5443 [ALC882_3ST_DIG] = { 5444 .mixers = { alc882_base_mixer }, 5445 .init_verbs = { alc882_init_verbs }, 5446 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5447 .dac_nids = alc882_dac_nids, 5448 .dig_out_nid = ALC882_DIGOUT_NID, 5449 .dig_in_nid = ALC882_DIGIN_NID, 5450 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), 5451 .channel_mode = alc882_ch_modes, 5452 .need_dac_fix = 1, 5453 .input_mux = &alc882_capture_source, 5454 }, 5455 [ALC882_6ST_DIG] = { 5456 .mixers = { alc882_base_mixer, alc882_chmode_mixer }, 5457 .init_verbs = { alc882_init_verbs }, 5458 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5459 .dac_nids = alc882_dac_nids, 5460 .dig_out_nid = ALC882_DIGOUT_NID, 5461 .dig_in_nid = ALC882_DIGIN_NID, 5462 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), 5463 .channel_mode = alc882_sixstack_modes, 5464 .input_mux = &alc882_capture_source, 5465 }, 5466 [ALC882_ARIMA] = { 5467 .mixers = { alc882_base_mixer, alc882_chmode_mixer }, 5468 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs }, 5469 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5470 .dac_nids = alc882_dac_nids, 5471 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), 5472 .channel_mode = alc882_sixstack_modes, 5473 .input_mux = &alc882_capture_source, 5474 }, 5475 [ALC882_W2JC] = { 5476 .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer }, 5477 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, 5478 alc880_gpio1_init_verbs }, 5479 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5480 .dac_nids = alc882_dac_nids, 5481 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 5482 .channel_mode = alc880_threestack_modes, 5483 .need_dac_fix = 1, 5484 .input_mux = &alc882_capture_source, 5485 .dig_out_nid = ALC882_DIGOUT_NID, 5486 }, 5487 [ALC885_MACPRO] = { 5488 .mixers = { alc882_macpro_mixer }, 5489 .init_verbs = { alc882_macpro_init_verbs }, 5490 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5491 .dac_nids = alc882_dac_nids, 5492 .dig_out_nid = ALC882_DIGOUT_NID, 5493 .dig_in_nid = ALC882_DIGIN_NID, 5494 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), 5495 .channel_mode = alc882_ch_modes, 5496 .input_mux = &alc882_capture_source, 5497 .init_hook = alc885_macpro_init_hook, 5498 }, 5499 [ALC885_IMAC24] = { 5500 .mixers = { alc885_imac24_mixer }, 5501 .init_verbs = { alc885_imac24_init_verbs }, 5502 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5503 .dac_nids = alc882_dac_nids, 5504 .dig_out_nid = ALC882_DIGOUT_NID, 5505 .dig_in_nid = ALC882_DIGIN_NID, 5506 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), 5507 .channel_mode = alc882_ch_modes, 5508 .input_mux = &alc882_capture_source, 5509 .unsol_event = alc885_imac24_unsol_event, 5510 .init_hook = alc885_imac24_init_hook, 5511 }, 5512 [ALC882_TARGA] = { 5513 .mixers = { alc882_targa_mixer, alc882_chmode_mixer, 5514 alc882_capture_mixer }, 5515 .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, 5516 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5517 .dac_nids = alc882_dac_nids, 5518 .dig_out_nid = ALC882_DIGOUT_NID, 5519 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), 5520 .adc_nids = alc882_adc_nids, 5521 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), 5522 .channel_mode = alc882_3ST_6ch_modes, 5523 .need_dac_fix = 1, 5524 .input_mux = &alc882_capture_source, 5525 .unsol_event = alc882_targa_unsol_event, 5526 .init_hook = alc882_targa_automute, 5527 }, 5528 [ALC882_ASUS_A7J] = { 5529 .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer, 5530 alc882_capture_mixer }, 5531 .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs}, 5532 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5533 .dac_nids = alc882_dac_nids, 5534 .dig_out_nid = ALC882_DIGOUT_NID, 5535 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), 5536 .adc_nids = alc882_adc_nids, 5537 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), 5538 .channel_mode = alc882_3ST_6ch_modes, 5539 .need_dac_fix = 1, 5540 .input_mux = &alc882_capture_source, 5541 }, 5542}; 5543 5544 5545/* 5546 * Pin config fixes 5547 */ 5548enum { 5549 PINFIX_ABIT_AW9D_MAX 5550}; 5551 5552static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { 5553 { 0x15, 0x01080104 }, /* side */ 5554 { 0x16, 0x01011012 }, /* rear */ 5555 { 0x17, 0x01016011 }, /* clfe */ 5556 { } 5557}; 5558 5559static const struct alc_pincfg *alc882_pin_fixes[] = { 5560 [PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix, 5561}; 5562 5563static struct snd_pci_quirk alc882_pinfix_tbl[] = { 5564 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), 5565 {} 5566}; 5567 5568/* 5569 * BIOS auto configuration 5570 */ 5571static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, 5572 hda_nid_t nid, int pin_type, 5573 int dac_idx) 5574{ 5575 /* set as output */ 5576 struct alc_spec *spec = codec->spec; 5577 int idx; 5578 5579 if (spec->multiout.dac_nids[dac_idx] == 0x25) 5580 idx = 4; 5581 else 5582 idx = spec->multiout.dac_nids[dac_idx] - 2; 5583 5584 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 5585 pin_type); 5586 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 5587 AMP_OUT_UNMUTE); 5588 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); 5589 5590} 5591 5592static void alc882_auto_init_multi_out(struct hda_codec *codec) 5593{ 5594 struct alc_spec *spec = codec->spec; 5595 int i; 5596 5597 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 5598 for (i = 0; i <= HDA_SIDE; i++) { 5599 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 5600 int pin_type = get_pin_type(spec->autocfg.line_out_type); 5601 if (nid) 5602 alc882_auto_set_output_and_unmute(codec, nid, pin_type, 5603 i); 5604 } 5605} 5606 5607static void alc882_auto_init_hp_out(struct hda_codec *codec) 5608{ 5609 struct alc_spec *spec = codec->spec; 5610 hda_nid_t pin; 5611 5612 pin = spec->autocfg.hp_pins[0]; 5613 if (pin) /* connect to front */ 5614 /* use dac 0 */ 5615 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 5616} 5617 5618#define alc882_is_input_pin(nid) alc880_is_input_pin(nid) 5619#define ALC882_PIN_CD_NID ALC880_PIN_CD_NID 5620 5621static void alc882_auto_init_analog_input(struct hda_codec *codec) 5622{ 5623 struct alc_spec *spec = codec->spec; 5624 int i; 5625 5626 for (i = 0; i < AUTO_PIN_LAST; i++) { 5627 hda_nid_t nid = spec->autocfg.input_pins[i]; 5628 if (alc882_is_input_pin(nid)) { 5629 snd_hda_codec_write(codec, nid, 0, 5630 AC_VERB_SET_PIN_WIDGET_CONTROL, 5631 i <= AUTO_PIN_FRONT_MIC ? 5632 PIN_VREF80 : PIN_IN); 5633 if (nid != ALC882_PIN_CD_NID) 5634 snd_hda_codec_write(codec, nid, 0, 5635 AC_VERB_SET_AMP_GAIN_MUTE, 5636 AMP_OUT_MUTE); 5637 } 5638 } 5639} 5640 5641/* almost identical with ALC880 parser... */ 5642static int alc882_parse_auto_config(struct hda_codec *codec) 5643{ 5644 struct alc_spec *spec = codec->spec; 5645 int err = alc880_parse_auto_config(codec); 5646 5647 if (err < 0) 5648 return err; 5649 else if (err > 0) 5650 /* hack - override the init verbs */ 5651 spec->init_verbs[0] = alc882_auto_init_verbs; 5652 return err; 5653} 5654 5655/* additional initialization for auto-configuration model */ 5656static void alc882_auto_init(struct hda_codec *codec) 5657{ 5658 alc882_auto_init_multi_out(codec); 5659 alc882_auto_init_hp_out(codec); 5660 alc882_auto_init_analog_input(codec); 5661} 5662 5663static int patch_alc882(struct hda_codec *codec) 5664{ 5665 struct alc_spec *spec; 5666 int err, board_config; 5667 5668 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 5669 if (spec == NULL) 5670 return -ENOMEM; 5671 5672 codec->spec = spec; 5673 5674 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST, 5675 alc882_models, 5676 alc882_cfg_tbl); 5677 5678 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) { 5679 /* Pick up systems that don't supply PCI SSID */ 5680 switch (codec->subsystem_id) { 5681 case 0x106b0c00: /* Mac Pro */ 5682 board_config = ALC885_MACPRO; 5683 break; 5684 case 0x106b1000: /* iMac 24 */ 5685 board_config = ALC885_IMAC24; 5686 break; 5687 default: 5688 printk(KERN_INFO "hda_codec: Unknown model for ALC882, " 5689 "trying auto-probe from BIOS...\n"); 5690 board_config = ALC882_AUTO; 5691 } 5692 } 5693 5694 alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes); 5695 5696 if (board_config == ALC882_AUTO) { 5697 /* automatic parse from the BIOS config */ 5698 err = alc882_parse_auto_config(codec); 5699 if (err < 0) { 5700 alc_free(codec); 5701 return err; 5702 } else if (!err) { 5703 printk(KERN_INFO 5704 "hda_codec: Cannot set up configuration " 5705 "from BIOS. Using base mode...\n"); 5706 board_config = ALC882_3ST_DIG; 5707 } 5708 } 5709 5710 if (board_config != ALC882_AUTO) 5711 setup_preset(spec, &alc882_presets[board_config]); 5712 5713 spec->stream_name_analog = "ALC882 Analog"; 5714 spec->stream_analog_playback = &alc882_pcm_analog_playback; 5715 spec->stream_analog_capture = &alc882_pcm_analog_capture; 5716 5717 spec->stream_name_digital = "ALC882 Digital"; 5718 spec->stream_digital_playback = &alc882_pcm_digital_playback; 5719 spec->stream_digital_capture = &alc882_pcm_digital_capture; 5720 5721 if (!spec->adc_nids && spec->input_mux) { 5722 /* check whether NID 0x07 is valid */ 5723 unsigned int wcap = get_wcaps(codec, 0x07); 5724 /* get type */ 5725 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 5726 if (wcap != AC_WID_AUD_IN) { 5727 spec->adc_nids = alc882_adc_nids_alt; 5728 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); 5729 spec->mixers[spec->num_mixers] = 5730 alc882_capture_alt_mixer; 5731 spec->num_mixers++; 5732 } else { 5733 spec->adc_nids = alc882_adc_nids; 5734 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); 5735 spec->mixers[spec->num_mixers] = alc882_capture_mixer; 5736 spec->num_mixers++; 5737 } 5738 } 5739 5740 codec->patch_ops = alc_patch_ops; 5741 if (board_config == ALC882_AUTO) 5742 spec->init_hook = alc882_auto_init; 5743#ifdef CONFIG_SND_HDA_POWER_SAVE 5744 if (!spec->loopback.amplist) 5745 spec->loopback.amplist = alc882_loopbacks; 5746#endif 5747 5748 return 0; 5749} 5750 5751/* 5752 * ALC883 support 5753 * 5754 * ALC883 is almost identical with ALC880 but has cleaner and more flexible 5755 * configuration. Each pin widget can choose any input DACs and a mixer. 5756 * Each ADC is connected from a mixer of all inputs. This makes possible 5757 * 6-channel independent captures. 5758 * 5759 * In addition, an independent DAC for the multi-playback (not used in this 5760 * driver yet). 5761 */ 5762#define ALC883_DIGOUT_NID 0x06 5763#define ALC883_DIGIN_NID 0x0a 5764 5765static hda_nid_t alc883_dac_nids[4] = { 5766 /* front, rear, clfe, rear_surr */ 5767 0x02, 0x04, 0x03, 0x05 5768}; 5769 5770static hda_nid_t alc883_adc_nids[2] = { 5771 /* ADC1-2 */ 5772 0x08, 0x09, 5773}; 5774 5775/* input MUX */ 5776/* FIXME: should be a matrix-type input source selection */ 5777 5778static struct hda_input_mux alc883_capture_source = { 5779 .num_items = 4, 5780 .items = { 5781 { "Mic", 0x0 }, 5782 { "Front Mic", 0x1 }, 5783 { "Line", 0x2 }, 5784 { "CD", 0x4 }, 5785 }, 5786}; 5787 5788static struct hda_input_mux alc883_lenovo_101e_capture_source = { 5789 .num_items = 2, 5790 .items = { 5791 { "Mic", 0x1 }, 5792 { "Line", 0x2 }, 5793 }, 5794}; 5795 5796static struct hda_input_mux alc883_lenovo_nb0763_capture_source = { 5797 .num_items = 4, 5798 .items = { 5799 { "Mic", 0x0 }, 5800 { "iMic", 0x1 }, 5801 { "Line", 0x2 }, 5802 { "CD", 0x4 }, 5803 }, 5804}; 5805 5806#define alc883_mux_enum_info alc_mux_enum_info 5807#define alc883_mux_enum_get alc_mux_enum_get 5808 5809static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, 5810 struct snd_ctl_elem_value *ucontrol) 5811{ 5812 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 5813 struct alc_spec *spec = codec->spec; 5814 const struct hda_input_mux *imux = spec->input_mux; 5815 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 5816 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; 5817 hda_nid_t nid = capture_mixers[adc_idx]; 5818 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 5819 unsigned int i, idx; 5820 5821 idx = ucontrol->value.enumerated.item[0]; 5822 if (idx >= imux->num_items) 5823 idx = imux->num_items - 1; 5824 if (*cur_val == idx) 5825 return 0; 5826 for (i = 0; i < imux->num_items; i++) { 5827 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; 5828 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 5829 imux->items[i].index, 5830 HDA_AMP_MUTE, v); 5831 } 5832 *cur_val = idx; 5833 return 1; 5834} 5835 5836/* 5837 * 2ch mode 5838 */ 5839static struct hda_channel_mode alc883_3ST_2ch_modes[1] = { 5840 { 2, NULL } 5841}; 5842 5843/* 5844 * 2ch mode 5845 */ 5846static struct hda_verb alc883_3ST_ch2_init[] = { 5847 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 5848 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 5849 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 5850 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 5851 { } /* end */ 5852}; 5853 5854/* 5855 * 6ch mode 5856 */ 5857static struct hda_verb alc883_3ST_ch6_init[] = { 5858 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5859 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 5860 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, 5861 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5862 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 5863 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, 5864 { } /* end */ 5865}; 5866 5867static struct hda_channel_mode alc883_3ST_6ch_modes[2] = { 5868 { 2, alc883_3ST_ch2_init }, 5869 { 6, alc883_3ST_ch6_init }, 5870}; 5871 5872/* 5873 * 6ch mode 5874 */ 5875static struct hda_verb alc883_sixstack_ch6_init[] = { 5876 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 5877 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5878 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5879 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5880 { } /* end */ 5881}; 5882 5883/* 5884 * 8ch mode 5885 */ 5886static struct hda_verb alc883_sixstack_ch8_init[] = { 5887 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5888 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5889 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5890 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5891 { } /* end */ 5892}; 5893 5894static struct hda_channel_mode alc883_sixstack_modes[2] = { 5895 { 6, alc883_sixstack_ch6_init }, 5896 { 8, alc883_sixstack_ch8_init }, 5897}; 5898 5899static struct hda_verb alc883_medion_eapd_verbs[] = { 5900 /* eanable EAPD on medion laptop */ 5901 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 5902 {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, 5903 { } 5904}; 5905 5906/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 5907 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 5908 */ 5909 5910static struct snd_kcontrol_new alc883_base_mixer[] = { 5911 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5912 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5913 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 5914 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 5915 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 5916 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 5917 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 5918 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 5919 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 5920 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 5921 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5922 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5923 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5924 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5925 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5926 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5927 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5928 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5929 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5930 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 5931 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5932 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5933 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5934 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5935 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5936 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5937 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5938 { 5939 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5940 /* .name = "Capture Source", */ 5941 .name = "Input Source", 5942 .count = 2, 5943 .info = alc883_mux_enum_info, 5944 .get = alc883_mux_enum_get, 5945 .put = alc883_mux_enum_put, 5946 }, 5947 { } /* end */ 5948}; 5949 5950static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { 5951 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5952 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5953 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5954 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5955 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5956 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5957 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5958 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5959 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5960 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5961 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5962 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 5963 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5964 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5965 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5966 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5967 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5968 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5969 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5970 { 5971 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5972 /* .name = "Capture Source", */ 5973 .name = "Input Source", 5974 .count = 2, 5975 .info = alc883_mux_enum_info, 5976 .get = alc883_mux_enum_get, 5977 .put = alc883_mux_enum_put, 5978 }, 5979 { } /* end */ 5980}; 5981 5982static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { 5983 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5984 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5985 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 5986 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 5987 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 5988 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 5989 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 5990 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 5991 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5992 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5993 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5994 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5995 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5996 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5997 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5998 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5999 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6000 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 6001 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6002 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 6003 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 6004 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6005 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6006 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6007 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6008 { 6009 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6010 /* .name = "Capture Source", */ 6011 .name = "Input Source", 6012 .count = 2, 6013 .info = alc883_mux_enum_info, 6014 .get = alc883_mux_enum_get, 6015 .put = alc883_mux_enum_put, 6016 }, 6017 { } /* end */ 6018}; 6019 6020static struct snd_kcontrol_new alc883_fivestack_mixer[] = { 6021 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6022 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6023 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 6024 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), 6025 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 6026 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 6027 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), 6028 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 6029 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6030 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6031 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6032 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6033 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6034 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6035 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6036 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6037 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6038 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 6039 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6040 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 6041 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 6042 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6043 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6044 6045 { 6046 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6047 /* .name = "Capture Source", */ 6048 .name = "Input Source", 6049 .count = 1, 6050 .info = alc883_mux_enum_info, 6051 .get = alc883_mux_enum_get, 6052 .put = alc883_mux_enum_put, 6053 }, 6054 { } /* end */ 6055}; 6056 6057static struct snd_kcontrol_new alc883_tagra_mixer[] = { 6058 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6059 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6060 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6061 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 6062 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 6063 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 6064 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 6065 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 6066 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 6067 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6068 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6069 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6070 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6071 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6072 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6073 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6074 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6075 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6076 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6077 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6078 { 6079 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6080 /* .name = "Capture Source", */ 6081 .name = "Input Source", 6082 .count = 2, 6083 .info = alc883_mux_enum_info, 6084 .get = alc883_mux_enum_get, 6085 .put = alc883_mux_enum_put, 6086 }, 6087 { } /* end */ 6088}; 6089 6090static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { 6091 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6092 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6093 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6094 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6095 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6096 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6097 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6098 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6099 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6100 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6101 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6102 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6103 { 6104 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6105 /* .name = "Capture Source", */ 6106 .name = "Input Source", 6107 .count = 2, 6108 .info = alc883_mux_enum_info, 6109 .get = alc883_mux_enum_get, 6110 .put = alc883_mux_enum_put, 6111 }, 6112 { } /* end */ 6113}; 6114 6115static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = { 6116 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6117 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 6118 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 6119 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), 6120 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6121 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6122 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6123 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6124 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6125 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6126 { 6127 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6128 /* .name = "Capture Source", */ 6129 .name = "Input Source", 6130 .count = 1, 6131 .info = alc883_mux_enum_info, 6132 .get = alc883_mux_enum_get, 6133 .put = alc883_mux_enum_put, 6134 }, 6135 { } /* end */ 6136}; 6137 6138static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = { 6139 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6140 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT), 6141 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6142 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6143 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6144 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6145 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6146 HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6147 HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6148 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6149 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6150 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6151 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6152 { 6153 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6154 /* .name = "Capture Source", */ 6155 .name = "Input Source", 6156 .count = 2, 6157 .info = alc883_mux_enum_info, 6158 .get = alc883_mux_enum_get, 6159 .put = alc883_mux_enum_put, 6160 }, 6161 { } /* end */ 6162}; 6163 6164static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { 6165 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6166 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6167 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), 6168 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6169 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6170 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6171 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6172 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6173 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6174 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6175 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6176 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6177 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6178 { 6179 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6180 /* .name = "Capture Source", */ 6181 .name = "Input Source", 6182 .count = 2, 6183 .info = alc883_mux_enum_info, 6184 .get = alc883_mux_enum_get, 6185 .put = alc883_mux_enum_put, 6186 }, 6187 { } /* end */ 6188}; 6189 6190static struct snd_kcontrol_new alc888_6st_hp_mixer[] = { 6191 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6192 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 6193 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT), 6194 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT), 6195 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), 6196 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), 6197 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), 6198 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), 6199 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 6200 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 6201 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6202 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6203 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6204 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6205 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6206 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6207 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6208 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6209 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6210 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 6211 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6212 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 6213 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 6214 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6215 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6216 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6217 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6218 { 6219 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6220 /* .name = "Capture Source", */ 6221 .name = "Input Source", 6222 .count = 2, 6223 .info = alc883_mux_enum_info, 6224 .get = alc883_mux_enum_get, 6225 .put = alc883_mux_enum_put, 6226 }, 6227 { } /* end */ 6228}; 6229 6230static struct snd_kcontrol_new alc888_3st_hp_mixer[] = { 6231 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6232 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 6233 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT), 6234 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT), 6235 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), 6236 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), 6237 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), 6238 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), 6239 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6240 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6241 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6242 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6243 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6244 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6245 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6246 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6247 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6248 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 6249 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6250 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 6251 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 6252 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6253 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6254 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6255 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6256 { 6257 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6258 /* .name = "Capture Source", */ 6259 .name = "Input Source", 6260 .count = 2, 6261 .info = alc883_mux_enum_info, 6262 .get = alc883_mux_enum_get, 6263 .put = alc883_mux_enum_put, 6264 }, 6265 { } /* end */ 6266}; 6267 6268static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { 6269 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6270 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 6271 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6272 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6273 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6274 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6275 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6276 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6277 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6278 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6279 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6280 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6281 { 6282 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6283 /* .name = "Capture Source", */ 6284 .name = "Input Source", 6285 .count = 2, 6286 .info = alc883_mux_enum_info, 6287 .get = alc883_mux_enum_get, 6288 .put = alc883_mux_enum_put, 6289 }, 6290 { } /* end */ 6291}; 6292 6293static struct snd_kcontrol_new alc883_chmode_mixer[] = { 6294 { 6295 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6296 .name = "Channel Mode", 6297 .info = alc_ch_mode_info, 6298 .get = alc_ch_mode_get, 6299 .put = alc_ch_mode_put, 6300 }, 6301 { } /* end */ 6302}; 6303 6304static struct hda_verb alc883_init_verbs[] = { 6305 /* ADC1: mute amp left and right */ 6306 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6307 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 6308 /* ADC2: mute amp left and right */ 6309 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6310 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 6311 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 6312 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6313 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6314 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6315 /* Rear mixer */ 6316 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6317 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6318 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6319 /* CLFE mixer */ 6320 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6321 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6322 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6323 /* Side mixer */ 6324 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6325 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6326 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6327 6328 /* mute analog input loopbacks */ 6329 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6330 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6331 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 6332 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 6333 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 6334 6335 /* Front Pin: output 0 (0x0c) */ 6336 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6337 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6338 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 6339 /* Rear Pin: output 1 (0x0d) */ 6340 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6341 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6342 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 6343 /* CLFE Pin: output 2 (0x0e) */ 6344 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6345 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6346 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, 6347 /* Side Pin: output 3 (0x0f) */ 6348 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6349 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6350 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, 6351 /* Mic (rear) pin: input vref at 80% */ 6352 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 6353 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 6354 /* Front Mic pin: input vref at 80% */ 6355 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 6356 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 6357 /* Line In pin: input */ 6358 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 6359 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 6360 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 6361 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6362 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6363 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 6364 /* CD pin widget for input */ 6365 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 6366 6367 /* FIXME: use matrix-type input source selection */ 6368 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 6369 /* Input mixer2 */ 6370 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6371 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6372 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6373 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6374 /* Input mixer3 */ 6375 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6376 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6377 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6378 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6379 { } 6380}; 6381 6382static struct hda_verb alc883_tagra_verbs[] = { 6383 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6384 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6385 6386 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6387 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6388 6389 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 6390 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ 6391 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 6392 6393 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6394 {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 6395 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 6396 {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 6397 6398 { } /* end */ 6399}; 6400 6401static struct hda_verb alc883_lenovo_101e_verbs[] = { 6402 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 6403 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN}, 6404 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN}, 6405 { } /* end */ 6406}; 6407 6408static struct hda_verb alc883_lenovo_nb0763_verbs[] = { 6409 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 6410 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6411 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6412 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6413 { } /* end */ 6414}; 6415 6416static struct hda_verb alc888_lenovo_ms7195_verbs[] = { 6417 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6418 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6419 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 6420 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN}, 6421 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6422 { } /* end */ 6423}; 6424 6425static struct hda_verb alc888_6st_hp_verbs[] = { 6426 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ 6427 {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */ 6428 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* CLFE : output 1 (0x0d) */ 6429 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, /* Side : output 3 (0x0f) */ 6430 { } 6431}; 6432 6433static struct hda_verb alc888_3st_hp_verbs[] = { 6434 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ 6435 {0x18, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */ 6436 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */ 6437 { } 6438}; 6439 6440static struct hda_verb alc888_3st_hp_2ch_init[] = { 6441 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 6442 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 6443 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 6444 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 6445 { } 6446}; 6447 6448static struct hda_verb alc888_3st_hp_6ch_init[] = { 6449 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 6450 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 6451 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 6452 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 6453 { } 6454}; 6455 6456static struct hda_channel_mode alc888_3st_hp_modes[2] = { 6457 { 2, alc888_3st_hp_2ch_init }, 6458 { 6, alc888_3st_hp_6ch_init }, 6459}; 6460 6461/* toggle front-jack and RCA according to the hp-jack state */ 6462static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec) 6463{ 6464 unsigned int present; 6465 6466 present = snd_hda_codec_read(codec, 0x1b, 0, 6467 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6468 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 6469 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 6470 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 6471 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 6472} 6473 6474/* toggle RCA according to the front-jack state */ 6475static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec) 6476{ 6477 unsigned int present; 6478 6479 present = snd_hda_codec_read(codec, 0x14, 0, 6480 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6481 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 6482 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 6483} 6484 6485static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec, 6486 unsigned int res) 6487{ 6488 if ((res >> 26) == ALC880_HP_EVENT) 6489 alc888_lenovo_ms7195_front_automute(codec); 6490 if ((res >> 26) == ALC880_FRONT_EVENT) 6491 alc888_lenovo_ms7195_rca_automute(codec); 6492} 6493 6494static struct hda_verb alc883_medion_md2_verbs[] = { 6495 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6496 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6497 6498 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6499 6500 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6501 { } /* end */ 6502}; 6503 6504/* toggle speaker-output according to the hp-jack state */ 6505static void alc883_medion_md2_automute(struct hda_codec *codec) 6506{ 6507 unsigned int present; 6508 6509 present = snd_hda_codec_read(codec, 0x14, 0, 6510 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6511 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 6512 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 6513} 6514 6515static void alc883_medion_md2_unsol_event(struct hda_codec *codec, 6516 unsigned int res) 6517{ 6518 if ((res >> 26) == ALC880_HP_EVENT) 6519 alc883_medion_md2_automute(codec); 6520} 6521 6522/* toggle speaker-output according to the hp-jack state */ 6523static void alc883_tagra_automute(struct hda_codec *codec) 6524{ 6525 unsigned int present; 6526 unsigned char bits; 6527 6528 present = snd_hda_codec_read(codec, 0x14, 0, 6529 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6530 bits = present ? HDA_AMP_MUTE : 0; 6531 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, 6532 HDA_AMP_MUTE, bits); 6533 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA, 6534 present ? 1 : 3); 6535} 6536 6537static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) 6538{ 6539 if ((res >> 26) == ALC880_HP_EVENT) 6540 alc883_tagra_automute(codec); 6541} 6542 6543static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) 6544{ 6545 unsigned int present; 6546 unsigned char bits; 6547 6548 present = snd_hda_codec_read(codec, 0x14, 0, 6549 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6550 bits = present ? HDA_AMP_MUTE : 0; 6551 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 6552 HDA_AMP_MUTE, bits); 6553} 6554 6555static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) 6556{ 6557 unsigned int present; 6558 unsigned char bits; 6559 6560 present = snd_hda_codec_read(codec, 0x1b, 0, 6561 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6562 bits = present ? HDA_AMP_MUTE : 0; 6563 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 6564 HDA_AMP_MUTE, bits); 6565 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 6566 HDA_AMP_MUTE, bits); 6567} 6568 6569static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, 6570 unsigned int res) 6571{ 6572 if ((res >> 26) == ALC880_HP_EVENT) 6573 alc883_lenovo_101e_all_automute(codec); 6574 if ((res >> 26) == ALC880_FRONT_EVENT) 6575 alc883_lenovo_101e_ispeaker_automute(codec); 6576} 6577 6578/* toggle speaker-output according to the hp-jack state */ 6579static void alc883_acer_aspire_automute(struct hda_codec *codec) 6580{ 6581 unsigned int present; 6582 6583 present = snd_hda_codec_read(codec, 0x14, 0, 6584 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6585 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 6586 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 6587 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 6588 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 6589} 6590 6591static void alc883_acer_aspire_unsol_event(struct hda_codec *codec, 6592 unsigned int res) 6593{ 6594 if ((res >> 26) == ALC880_HP_EVENT) 6595 alc883_acer_aspire_automute(codec); 6596} 6597 6598static struct hda_verb alc883_acer_eapd_verbs[] = { 6599 /* HP Pin: output 0 (0x0c) */ 6600 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6601 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6602 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 6603 /* Front Pin: output 0 (0x0c) */ 6604 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6605 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 6606 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6607 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, 6608 /* eanable EAPD on medion laptop */ 6609 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 6610 {0x20, AC_VERB_SET_PROC_COEF, 0x3050}, 6611 /* enable unsolicited event */ 6612 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6613 { } 6614}; 6615 6616/* 6617 * generic initialization of ADC, input mixers and output mixers 6618 */ 6619static struct hda_verb alc883_auto_init_verbs[] = { 6620 /* 6621 * Unmute ADC0-2 and set the default input to mic-in 6622 */ 6623 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 6624 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6625 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 6626 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6627 6628 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 6629 * mixer widget 6630 * Note: PASD motherboards uses the Line In 2 as the input for 6631 * front panel mic (mic 2) 6632 */ 6633 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 6634 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6635 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6636 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 6637 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 6638 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 6639 6640 /* 6641 * Set up output mixers (0x0c - 0x0f) 6642 */ 6643 /* set vol=0 to output mixers */ 6644 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6645 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6646 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6647 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6648 /* set up input amps for analog loopback */ 6649 /* Amp Indices: DAC = 0, mixer = 1 */ 6650 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6651 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6652 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6653 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6654 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6655 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6656 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6657 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6658 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6659 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6660 6661 /* FIXME: use matrix-type input source selection */ 6662 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 6663 /* Input mixer1 */ 6664 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6665 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6666 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6667 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ 6668 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6669 /* Input mixer2 */ 6670 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6671 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6672 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6673 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ 6674 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6675 6676 { } 6677}; 6678 6679/* capture mixer elements */ 6680static struct snd_kcontrol_new alc883_capture_mixer[] = { 6681 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6682 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6683 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6684 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6685 { 6686 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6687 /* The multiple "Capture Source" controls confuse alsamixer 6688 * So call somewhat different.. 6689 * FIXME: the controls appear in the "playback" view! 6690 */ 6691 /* .name = "Capture Source", */ 6692 .name = "Input Source", 6693 .count = 2, 6694 .info = alc882_mux_enum_info, 6695 .get = alc882_mux_enum_get, 6696 .put = alc882_mux_enum_put, 6697 }, 6698 { } /* end */ 6699}; 6700 6701#ifdef CONFIG_SND_HDA_POWER_SAVE 6702#define alc883_loopbacks alc880_loopbacks 6703#endif 6704 6705/* pcm configuration: identiacal with ALC880 */ 6706#define alc883_pcm_analog_playback alc880_pcm_analog_playback 6707#define alc883_pcm_analog_capture alc880_pcm_analog_capture 6708#define alc883_pcm_digital_playback alc880_pcm_digital_playback 6709#define alc883_pcm_digital_capture alc880_pcm_digital_capture 6710 6711/* 6712 * configuration and preset 6713 */ 6714static const char *alc883_models[ALC883_MODEL_LAST] = { 6715 [ALC883_3ST_2ch_DIG] = "3stack-dig", 6716 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig", 6717 [ALC883_3ST_6ch] = "3stack-6ch", 6718 [ALC883_6ST_DIG] = "6stack-dig", 6719 [ALC883_TARGA_DIG] = "targa-dig", 6720 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", 6721 [ALC883_ACER] = "acer", 6722 [ALC883_ACER_ASPIRE] = "acer-aspire", 6723 [ALC883_MEDION] = "medion", 6724 [ALC883_MEDION_MD2] = "medion-md2", 6725 [ALC883_LAPTOP_EAPD] = "laptop-eapd", 6726 [ALC883_LENOVO_101E_2ch] = "lenovo-101e", 6727 [ALC883_LENOVO_NB0763] = "lenovo-nb0763", 6728 [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", 6729 [ALC888_6ST_HP] = "6stack-hp", 6730 [ALC888_3ST_HP] = "3stack-hp", 6731 [ALC883_AUTO] = "auto", 6732}; 6733 6734static struct snd_pci_quirk alc883_cfg_tbl[] = { 6735 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), 6736 SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), 6737 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), 6738 SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), 6739 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), 6740 SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG), 6741 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG), 6742 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), 6743 SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG), 6744 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), 6745 SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), 6746 SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG), 6747 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG), 6748 SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG), 6749 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG), 6750 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG), 6751 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG), 6752 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG), 6753 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG), 6754 SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG), 6755 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG), 6756 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG), 6757 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG), 6758 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), 6759 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), 6760 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), 6761 SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), 6762 SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), 6763 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), 6764 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), 6765 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), 6766 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch), 6767 SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763), 6768 SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763), 6769 SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_6ST_HP), 6770 SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), 6771 SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), 6772 SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), 6773 {} 6774}; 6775 6776static struct alc_config_preset alc883_presets[] = { 6777 [ALC883_3ST_2ch_DIG] = { 6778 .mixers = { alc883_3ST_2ch_mixer }, 6779 .init_verbs = { alc883_init_verbs }, 6780 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6781 .dac_nids = alc883_dac_nids, 6782 .dig_out_nid = ALC883_DIGOUT_NID, 6783 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6784 .adc_nids = alc883_adc_nids, 6785 .dig_in_nid = ALC883_DIGIN_NID, 6786 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6787 .channel_mode = alc883_3ST_2ch_modes, 6788 .input_mux = &alc883_capture_source, 6789 }, 6790 [ALC883_3ST_6ch_DIG] = { 6791 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, 6792 .init_verbs = { alc883_init_verbs }, 6793 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6794 .dac_nids = alc883_dac_nids, 6795 .dig_out_nid = ALC883_DIGOUT_NID, 6796 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6797 .adc_nids = alc883_adc_nids, 6798 .dig_in_nid = ALC883_DIGIN_NID, 6799 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6800 .channel_mode = alc883_3ST_6ch_modes, 6801 .need_dac_fix = 1, 6802 .input_mux = &alc883_capture_source, 6803 }, 6804 [ALC883_3ST_6ch] = { 6805 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, 6806 .init_verbs = { alc883_init_verbs }, 6807 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6808 .dac_nids = alc883_dac_nids, 6809 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6810 .adc_nids = alc883_adc_nids, 6811 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6812 .channel_mode = alc883_3ST_6ch_modes, 6813 .need_dac_fix = 1, 6814 .input_mux = &alc883_capture_source, 6815 }, 6816 [ALC883_6ST_DIG] = { 6817 .mixers = { alc883_base_mixer, alc883_chmode_mixer }, 6818 .init_verbs = { alc883_init_verbs }, 6819 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6820 .dac_nids = alc883_dac_nids, 6821 .dig_out_nid = ALC883_DIGOUT_NID, 6822 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6823 .adc_nids = alc883_adc_nids, 6824 .dig_in_nid = ALC883_DIGIN_NID, 6825 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), 6826 .channel_mode = alc883_sixstack_modes, 6827 .input_mux = &alc883_capture_source, 6828 }, 6829 [ALC883_TARGA_DIG] = { 6830 .mixers = { alc883_tagra_mixer, alc883_chmode_mixer }, 6831 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, 6832 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6833 .dac_nids = alc883_dac_nids, 6834 .dig_out_nid = ALC883_DIGOUT_NID, 6835 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6836 .adc_nids = alc883_adc_nids, 6837 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6838 .channel_mode = alc883_3ST_6ch_modes, 6839 .need_dac_fix = 1, 6840 .input_mux = &alc883_capture_source, 6841 .unsol_event = alc883_tagra_unsol_event, 6842 .init_hook = alc883_tagra_automute, 6843 }, 6844 [ALC883_TARGA_2ch_DIG] = { 6845 .mixers = { alc883_tagra_2ch_mixer}, 6846 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, 6847 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6848 .dac_nids = alc883_dac_nids, 6849 .dig_out_nid = ALC883_DIGOUT_NID, 6850 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6851 .adc_nids = alc883_adc_nids, 6852 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6853 .channel_mode = alc883_3ST_2ch_modes, 6854 .input_mux = &alc883_capture_source, 6855 .unsol_event = alc883_tagra_unsol_event, 6856 .init_hook = alc883_tagra_automute, 6857 }, 6858 [ALC883_ACER] = { 6859 .mixers = { alc883_base_mixer }, 6860 /* On TravelMate laptops, GPIO 0 enables the internal speaker 6861 * and the headphone jack. Turn this on and rely on the 6862 * standard mute methods whenever the user wants to turn 6863 * these outputs off. 6864 */ 6865 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs }, 6866 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6867 .dac_nids = alc883_dac_nids, 6868 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6869 .adc_nids = alc883_adc_nids, 6870 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6871 .channel_mode = alc883_3ST_2ch_modes, 6872 .input_mux = &alc883_capture_source, 6873 }, 6874 [ALC883_ACER_ASPIRE] = { 6875 .mixers = { alc883_acer_aspire_mixer }, 6876 .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs }, 6877 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6878 .dac_nids = alc883_dac_nids, 6879 .dig_out_nid = ALC883_DIGOUT_NID, 6880 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6881 .adc_nids = alc883_adc_nids, 6882 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6883 .channel_mode = alc883_3ST_2ch_modes, 6884 .input_mux = &alc883_capture_source, 6885 .unsol_event = alc883_acer_aspire_unsol_event, 6886 .init_hook = alc883_acer_aspire_automute, 6887 }, 6888 [ALC883_MEDION] = { 6889 .mixers = { alc883_fivestack_mixer, 6890 alc883_chmode_mixer }, 6891 .init_verbs = { alc883_init_verbs, 6892 alc883_medion_eapd_verbs }, 6893 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6894 .dac_nids = alc883_dac_nids, 6895 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6896 .adc_nids = alc883_adc_nids, 6897 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), 6898 .channel_mode = alc883_sixstack_modes, 6899 .input_mux = &alc883_capture_source, 6900 }, 6901 [ALC883_MEDION_MD2] = { 6902 .mixers = { alc883_medion_md2_mixer}, 6903 .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs}, 6904 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6905 .dac_nids = alc883_dac_nids, 6906 .dig_out_nid = ALC883_DIGOUT_NID, 6907 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6908 .adc_nids = alc883_adc_nids, 6909 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6910 .channel_mode = alc883_3ST_2ch_modes, 6911 .input_mux = &alc883_capture_source, 6912 .unsol_event = alc883_medion_md2_unsol_event, 6913 .init_hook = alc883_medion_md2_automute, 6914 }, 6915 [ALC883_LAPTOP_EAPD] = { 6916 .mixers = { alc883_base_mixer }, 6917 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, 6918 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6919 .dac_nids = alc883_dac_nids, 6920 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6921 .adc_nids = alc883_adc_nids, 6922 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6923 .channel_mode = alc883_3ST_2ch_modes, 6924 .input_mux = &alc883_capture_source, 6925 }, 6926 [ALC883_LENOVO_101E_2ch] = { 6927 .mixers = { alc883_lenovo_101e_2ch_mixer}, 6928 .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs}, 6929 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6930 .dac_nids = alc883_dac_nids, 6931 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6932 .adc_nids = alc883_adc_nids, 6933 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6934 .channel_mode = alc883_3ST_2ch_modes, 6935 .input_mux = &alc883_lenovo_101e_capture_source, 6936 .unsol_event = alc883_lenovo_101e_unsol_event, 6937 .init_hook = alc883_lenovo_101e_all_automute, 6938 }, 6939 [ALC883_LENOVO_NB0763] = { 6940 .mixers = { alc883_lenovo_nb0763_mixer }, 6941 .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs}, 6942 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6943 .dac_nids = alc883_dac_nids, 6944 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6945 .adc_nids = alc883_adc_nids, 6946 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6947 .channel_mode = alc883_3ST_2ch_modes, 6948 .need_dac_fix = 1, 6949 .input_mux = &alc883_lenovo_nb0763_capture_source, 6950 .unsol_event = alc883_medion_md2_unsol_event, 6951 .init_hook = alc883_medion_md2_automute, 6952 }, 6953 [ALC888_LENOVO_MS7195_DIG] = { 6954 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, 6955 .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs}, 6956 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6957 .dac_nids = alc883_dac_nids, 6958 .dig_out_nid = ALC883_DIGOUT_NID, 6959 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6960 .adc_nids = alc883_adc_nids, 6961 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6962 .channel_mode = alc883_3ST_6ch_modes, 6963 .need_dac_fix = 1, 6964 .input_mux = &alc883_capture_source, 6965 .unsol_event = alc883_lenovo_ms7195_unsol_event, 6966 .init_hook = alc888_lenovo_ms7195_front_automute, 6967 }, 6968 [ALC888_6ST_HP] = { 6969 .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer }, 6970 .init_verbs = { alc883_init_verbs, alc888_6st_hp_verbs }, 6971 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6972 .dac_nids = alc883_dac_nids, 6973 .dig_out_nid = ALC883_DIGOUT_NID, 6974 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6975 .adc_nids = alc883_adc_nids, 6976 .dig_in_nid = ALC883_DIGIN_NID, 6977 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), 6978 .channel_mode = alc883_sixstack_modes, 6979 .input_mux = &alc883_capture_source, 6980 }, 6981 [ALC888_3ST_HP] = { 6982 .mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer }, 6983 .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs }, 6984 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6985 .dac_nids = alc883_dac_nids, 6986 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6987 .adc_nids = alc883_adc_nids, 6988 .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes), 6989 .channel_mode = alc888_3st_hp_modes, 6990 .need_dac_fix = 1, 6991 .input_mux = &alc883_capture_source, 6992 }, 6993}; 6994 6995 6996/* 6997 * BIOS auto configuration 6998 */ 6999static void alc883_auto_set_output_and_unmute(struct hda_codec *codec, 7000 hda_nid_t nid, int pin_type, 7001 int dac_idx) 7002{ 7003 /* set as output */ 7004 struct alc_spec *spec = codec->spec; 7005 int idx; 7006 7007 if (spec->multiout.dac_nids[dac_idx] == 0x25) 7008 idx = 4; 7009 else 7010 idx = spec->multiout.dac_nids[dac_idx] - 2; 7011 7012 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 7013 pin_type); 7014 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 7015 AMP_OUT_UNMUTE); 7016 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); 7017 7018} 7019 7020static void alc883_auto_init_multi_out(struct hda_codec *codec) 7021{ 7022 struct alc_spec *spec = codec->spec; 7023 int i; 7024 7025 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 7026 for (i = 0; i <= HDA_SIDE; i++) { 7027 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 7028 int pin_type = get_pin_type(spec->autocfg.line_out_type); 7029 if (nid) 7030 alc883_auto_set_output_and_unmute(codec, nid, pin_type, 7031 i); 7032 } 7033} 7034 7035static void alc883_auto_init_hp_out(struct hda_codec *codec) 7036{ 7037 struct alc_spec *spec = codec->spec; 7038 hda_nid_t pin; 7039 7040 pin = spec->autocfg.hp_pins[0]; 7041 if (pin) /* connect to front */ 7042 /* use dac 0 */ 7043 alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 7044} 7045 7046#define alc883_is_input_pin(nid) alc880_is_input_pin(nid) 7047#define ALC883_PIN_CD_NID ALC880_PIN_CD_NID 7048 7049static void alc883_auto_init_analog_input(struct hda_codec *codec) 7050{ 7051 struct alc_spec *spec = codec->spec; 7052 int i; 7053 7054 for (i = 0; i < AUTO_PIN_LAST; i++) { 7055 hda_nid_t nid = spec->autocfg.input_pins[i]; 7056 if (alc883_is_input_pin(nid)) { 7057 snd_hda_codec_write(codec, nid, 0, 7058 AC_VERB_SET_PIN_WIDGET_CONTROL, 7059 (i <= AUTO_PIN_FRONT_MIC ? 7060 PIN_VREF80 : PIN_IN)); 7061 if (nid != ALC883_PIN_CD_NID) 7062 snd_hda_codec_write(codec, nid, 0, 7063 AC_VERB_SET_AMP_GAIN_MUTE, 7064 AMP_OUT_MUTE); 7065 } 7066 } 7067} 7068 7069/* almost identical with ALC880 parser... */ 7070static int alc883_parse_auto_config(struct hda_codec *codec) 7071{ 7072 struct alc_spec *spec = codec->spec; 7073 int err = alc880_parse_auto_config(codec); 7074 7075 if (err < 0) 7076 return err; 7077 else if (err > 0) 7078 /* hack - override the init verbs */ 7079 spec->init_verbs[0] = alc883_auto_init_verbs; 7080 spec->mixers[spec->num_mixers] = alc883_capture_mixer; 7081 spec->num_mixers++; 7082 return err; 7083} 7084 7085/* additional initialization for auto-configuration model */ 7086static void alc883_auto_init(struct hda_codec *codec) 7087{ 7088 alc883_auto_init_multi_out(codec); 7089 alc883_auto_init_hp_out(codec); 7090 alc883_auto_init_analog_input(codec); 7091} 7092 7093static int patch_alc883(struct hda_codec *codec) 7094{ 7095 struct alc_spec *spec; 7096 int err, board_config; 7097 7098 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 7099 if (spec == NULL) 7100 return -ENOMEM; 7101 7102 codec->spec = spec; 7103 7104 board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST, 7105 alc883_models, 7106 alc883_cfg_tbl); 7107 if (board_config < 0) { 7108 printk(KERN_INFO "hda_codec: Unknown model for ALC883, " 7109 "trying auto-probe from BIOS...\n"); 7110 board_config = ALC883_AUTO; 7111 } 7112 7113 if (board_config == ALC883_AUTO) { 7114 /* automatic parse from the BIOS config */ 7115 err = alc883_parse_auto_config(codec); 7116 if (err < 0) { 7117 alc_free(codec); 7118 return err; 7119 } else if (!err) { 7120 printk(KERN_INFO 7121 "hda_codec: Cannot set up configuration " 7122 "from BIOS. Using base mode...\n"); 7123 board_config = ALC883_3ST_2ch_DIG; 7124 } 7125 } 7126 7127 if (board_config != ALC883_AUTO) 7128 setup_preset(spec, &alc883_presets[board_config]); 7129 7130 spec->stream_name_analog = "ALC883 Analog"; 7131 spec->stream_analog_playback = &alc883_pcm_analog_playback; 7132 spec->stream_analog_capture = &alc883_pcm_analog_capture; 7133 7134 spec->stream_name_digital = "ALC883 Digital"; 7135 spec->stream_digital_playback = &alc883_pcm_digital_playback; 7136 spec->stream_digital_capture = &alc883_pcm_digital_capture; 7137 7138 if (!spec->adc_nids && spec->input_mux) { 7139 spec->adc_nids = alc883_adc_nids; 7140 spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); 7141 } 7142 7143 codec->patch_ops = alc_patch_ops; 7144 if (board_config == ALC883_AUTO) 7145 spec->init_hook = alc883_auto_init; 7146#ifdef CONFIG_SND_HDA_POWER_SAVE 7147 if (!spec->loopback.amplist) 7148 spec->loopback.amplist = alc883_loopbacks; 7149#endif 7150 7151 return 0; 7152} 7153 7154/* 7155 * ALC262 support 7156 */ 7157 7158#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID 7159#define ALC262_DIGIN_NID ALC880_DIGIN_NID 7160 7161#define alc262_dac_nids alc260_dac_nids 7162#define alc262_adc_nids alc882_adc_nids 7163#define alc262_adc_nids_alt alc882_adc_nids_alt 7164 7165#define alc262_modes alc260_modes 7166#define alc262_capture_source alc882_capture_source 7167 7168static struct snd_kcontrol_new alc262_base_mixer[] = { 7169 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7170 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 7171 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7172 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7173 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 7174 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 7175 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7176 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7177 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7178 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7179 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7180 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 7181 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7182 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */ 7183 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), 7184 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7185 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 7186 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 7187 { } /* end */ 7188}; 7189 7190static struct snd_kcontrol_new alc262_hippo1_mixer[] = { 7191 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7192 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 7193 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7194 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7195 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 7196 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 7197 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7198 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7199 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7200 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7201 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7202 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 7203 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7204 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */ 7205 /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/ 7206 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 7207 { } /* end */ 7208}; 7209 7210static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { 7211 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7212 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7213 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 7214 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 7215 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 7216 7217 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7218 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7219 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7220 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7221 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7222 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 7223 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 7224 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 7225 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7226 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7227 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7228 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), 7229 HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT), 7230 HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT), 7231 { } /* end */ 7232}; 7233 7234static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = { 7235 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7236 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 7237 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 7238 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7239 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 7240 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 7241 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT), 7242 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT), 7243 HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT), 7244 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), 7245 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), 7246 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7247 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7248 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7249 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), 7250 { } /* end */ 7251}; 7252 7253static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = { 7254 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7255 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7256 HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT), 7257 { } /* end */ 7258}; 7259 7260static struct hda_bind_ctls alc262_sony_bind_sw = { 7261 .ops = &snd_hda_bind_sw, 7262 .values = { 7263 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT), 7264 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), 7265 0, 7266 }, 7267}; 7268 7269static struct snd_kcontrol_new alc262_sony_mixer[] = { 7270 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7271 HDA_BIND_SW("Front Playback Switch", &alc262_sony_bind_sw), 7272 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7273 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7274 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7275 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7276 { } /* end */ 7277}; 7278 7279static struct snd_kcontrol_new alc262_benq_t31_mixer[] = { 7280 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7281 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 7282 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7283 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7284 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7285 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7286 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7287 { } /* end */ 7288}; 7289 7290#define alc262_capture_mixer alc882_capture_mixer 7291#define alc262_capture_alt_mixer alc882_capture_alt_mixer 7292 7293/* 7294 * generic initialization of ADC, input mixers and output mixers 7295 */ 7296static struct hda_verb alc262_init_verbs[] = { 7297 /* 7298 * Unmute ADC0-2 and set the default input to mic-in 7299 */ 7300 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7301 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7302 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7303 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7304 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7305 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7306 7307 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7308 * mixer widget 7309 * Note: PASD motherboards uses the Line In 2 as the input for 7310 * front panel mic (mic 2) 7311 */ 7312 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7313 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 7314 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 7315 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 7316 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 7317 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 7318 7319 /* 7320 * Set up output mixers (0x0c - 0x0e) 7321 */ 7322 /* set vol=0 to output mixers */ 7323 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7324 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7325 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7326 /* set up input amps for analog loopback */ 7327 /* Amp Indices: DAC = 0, mixer = 1 */ 7328 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7329 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7330 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7331 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7332 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7333 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7334 7335 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 7336 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7337 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 7338 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7339 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7340 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7341 7342 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7343 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7344 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7345 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7346 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7347 7348 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 7349 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 7350 7351 /* FIXME: use matrix-type input source selection */ 7352 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7353 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7354 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7355 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7356 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7357 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7358 /* Input mixer2 */ 7359 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7360 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7361 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7362 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7363 /* Input mixer3 */ 7364 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7365 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7366 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7367 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7368 7369 { } 7370}; 7371 7372static struct hda_verb alc262_hippo_unsol_verbs[] = { 7373 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 7374 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7375 {} 7376}; 7377 7378static struct hda_verb alc262_hippo1_unsol_verbs[] = { 7379 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7380 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 7381 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7382 7383 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 7384 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7385 {} 7386}; 7387 7388static struct hda_verb alc262_sony_unsol_verbs[] = { 7389 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7390 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 7391 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic 7392 7393 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 7394 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7395}; 7396 7397/* mute/unmute internal speaker according to the hp jack and mute state */ 7398static void alc262_hippo_automute(struct hda_codec *codec) 7399{ 7400 struct alc_spec *spec = codec->spec; 7401 unsigned int mute; 7402 unsigned int present; 7403 7404 /* need to execute and sync at first */ 7405 snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); 7406 present = snd_hda_codec_read(codec, 0x15, 0, 7407 AC_VERB_GET_PIN_SENSE, 0); 7408 spec->jack_present = (present & 0x80000000) != 0; 7409 if (spec->jack_present) { 7410 /* mute internal speaker */ 7411 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 7412 HDA_AMP_MUTE, HDA_AMP_MUTE); 7413 } else { 7414 /* unmute internal speaker if necessary */ 7415 mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0); 7416 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 7417 HDA_AMP_MUTE, mute); 7418 } 7419} 7420 7421/* unsolicited event for HP jack sensing */ 7422static void alc262_hippo_unsol_event(struct hda_codec *codec, 7423 unsigned int res) 7424{ 7425 if ((res >> 26) != ALC880_HP_EVENT) 7426 return; 7427 alc262_hippo_automute(codec); 7428} 7429 7430static void alc262_hippo1_automute(struct hda_codec *codec) 7431{ 7432 unsigned int mute; 7433 unsigned int present; 7434 7435 snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); 7436 present = snd_hda_codec_read(codec, 0x1b, 0, 7437 AC_VERB_GET_PIN_SENSE, 0); 7438 present = (present & 0x80000000) != 0; 7439 if (present) { 7440 /* mute internal speaker */ 7441 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 7442 HDA_AMP_MUTE, HDA_AMP_MUTE); 7443 } else { 7444 /* unmute internal speaker if necessary */ 7445 mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); 7446 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 7447 HDA_AMP_MUTE, mute); 7448 } 7449} 7450 7451/* unsolicited event for HP jack sensing */ 7452static void alc262_hippo1_unsol_event(struct hda_codec *codec, 7453 unsigned int res) 7454{ 7455 if ((res >> 26) != ALC880_HP_EVENT) 7456 return; 7457 alc262_hippo1_automute(codec); 7458} 7459 7460/* 7461 * fujitsu model 7462 * 0x14 = headphone/spdif-out, 0x15 = internal speaker 7463 */ 7464 7465#define ALC_HP_EVENT 0x37 7466 7467static struct hda_verb alc262_fujitsu_unsol_verbs[] = { 7468 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, 7469 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7470 {} 7471}; 7472 7473static struct hda_input_mux alc262_fujitsu_capture_source = { 7474 .num_items = 2, 7475 .items = { 7476 { "Mic", 0x0 }, 7477 { "CD", 0x4 }, 7478 }, 7479}; 7480 7481static struct hda_input_mux alc262_HP_capture_source = { 7482 .num_items = 5, 7483 .items = { 7484 { "Mic", 0x0 }, 7485 { "Front Mic", 0x3 }, 7486 { "Line", 0x2 }, 7487 { "CD", 0x4 }, 7488 { "AUX IN", 0x6 }, 7489 }, 7490}; 7491 7492/* mute/unmute internal speaker according to the hp jack and mute state */ 7493static void alc262_fujitsu_automute(struct hda_codec *codec, int force) 7494{ 7495 struct alc_spec *spec = codec->spec; 7496 unsigned int mute; 7497 7498 if (force || !spec->sense_updated) { 7499 unsigned int present; 7500 /* need to execute and sync at first */ 7501 snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); 7502 present = snd_hda_codec_read(codec, 0x14, 0, 7503 AC_VERB_GET_PIN_SENSE, 0); 7504 spec->jack_present = (present & 0x80000000) != 0; 7505 spec->sense_updated = 1; 7506 } 7507 if (spec->jack_present) { 7508 /* mute internal speaker */ 7509 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 7510 HDA_AMP_MUTE, HDA_AMP_MUTE); 7511 } else { 7512 /* unmute internal speaker if necessary */ 7513 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); 7514 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 7515 HDA_AMP_MUTE, mute); 7516 } 7517} 7518 7519/* unsolicited event for HP jack sensing */ 7520static void alc262_fujitsu_unsol_event(struct hda_codec *codec, 7521 unsigned int res) 7522{ 7523 if ((res >> 26) != ALC_HP_EVENT) 7524 return; 7525 alc262_fujitsu_automute(codec, 1); 7526} 7527 7528/* bind volumes of both NID 0x0c and 0x0d */ 7529static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = { 7530 .ops = &snd_hda_bind_vol, 7531 .values = { 7532 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), 7533 HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT), 7534 0 7535 }, 7536}; 7537 7538/* bind hp and internal speaker mute (with plug check) */ 7539static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, 7540 struct snd_ctl_elem_value *ucontrol) 7541{ 7542 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 7543 long *valp = ucontrol->value.integer.value; 7544 int change; 7545 7546 change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7547 HDA_AMP_MUTE, 7548 valp[0] ? 0 : HDA_AMP_MUTE); 7549 change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7550 HDA_AMP_MUTE, 7551 valp[1] ? 0 : HDA_AMP_MUTE); 7552 if (change) 7553 alc262_fujitsu_automute(codec, 0); 7554 return change; 7555} 7556 7557static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { 7558 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol), 7559 { 7560 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 7561 .name = "Master Playback Switch", 7562 .info = snd_hda_mixer_amp_switch_info, 7563 .get = snd_hda_mixer_amp_switch_get, 7564 .put = alc262_fujitsu_master_sw_put, 7565 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), 7566 }, 7567 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7568 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7569 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7570 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7571 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7572 { } /* end */ 7573}; 7574 7575/* additional init verbs for Benq laptops */ 7576static struct hda_verb alc262_EAPD_verbs[] = { 7577 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 7578 {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, 7579 {} 7580}; 7581 7582static struct hda_verb alc262_benq_t31_EAPD_verbs[] = { 7583 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 7584 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7585 7586 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 7587 {0x20, AC_VERB_SET_PROC_COEF, 0x3050}, 7588 {} 7589}; 7590 7591/* add playback controls from the parsed DAC table */ 7592static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, 7593 const struct auto_pin_cfg *cfg) 7594{ 7595 hda_nid_t nid; 7596 int err; 7597 7598 spec->multiout.num_dacs = 1; /* only use one dac */ 7599 spec->multiout.dac_nids = spec->private_dac_nids; 7600 spec->multiout.dac_nids[0] = 2; 7601 7602 nid = cfg->line_out_pins[0]; 7603 if (nid) { 7604 err = add_control(spec, ALC_CTL_WIDGET_VOL, 7605 "Front Playback Volume", 7606 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT)); 7607 if (err < 0) 7608 return err; 7609 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7610 "Front Playback Switch", 7611 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 7612 if (err < 0) 7613 return err; 7614 } 7615 7616 nid = cfg->speaker_pins[0]; 7617 if (nid) { 7618 if (nid == 0x16) { 7619 err = add_control(spec, ALC_CTL_WIDGET_VOL, 7620 "Speaker Playback Volume", 7621 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, 7622 HDA_OUTPUT)); 7623 if (err < 0) 7624 return err; 7625 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7626 "Speaker Playback Switch", 7627 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 7628 HDA_OUTPUT)); 7629 if (err < 0) 7630 return err; 7631 } else { 7632 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7633 "Speaker Playback Switch", 7634 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 7635 HDA_OUTPUT)); 7636 if (err < 0) 7637 return err; 7638 } 7639 } 7640 nid = cfg->hp_pins[0]; 7641 if (nid) { 7642 /* spec->multiout.hp_nid = 2; */ 7643 if (nid == 0x16) { 7644 err = add_control(spec, ALC_CTL_WIDGET_VOL, 7645 "Headphone Playback Volume", 7646 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, 7647 HDA_OUTPUT)); 7648 if (err < 0) 7649 return err; 7650 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7651 "Headphone Playback Switch", 7652 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 7653 HDA_OUTPUT)); 7654 if (err < 0) 7655 return err; 7656 } else { 7657 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7658 "Headphone Playback Switch", 7659 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 7660 HDA_OUTPUT)); 7661 if (err < 0) 7662 return err; 7663 } 7664 } 7665 return 0; 7666} 7667 7668/* identical with ALC880 */ 7669#define alc262_auto_create_analog_input_ctls \ 7670 alc880_auto_create_analog_input_ctls 7671 7672/* 7673 * generic initialization of ADC, input mixers and output mixers 7674 */ 7675static struct hda_verb alc262_volume_init_verbs[] = { 7676 /* 7677 * Unmute ADC0-2 and set the default input to mic-in 7678 */ 7679 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7680 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7681 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7682 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7683 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7684 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7685 7686 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7687 * mixer widget 7688 * Note: PASD motherboards uses the Line In 2 as the input for 7689 * front panel mic (mic 2) 7690 */ 7691 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7692 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 7693 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 7694 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 7695 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 7696 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 7697 7698 /* 7699 * Set up output mixers (0x0c - 0x0f) 7700 */ 7701 /* set vol=0 to output mixers */ 7702 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7703 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7704 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7705 7706 /* set up input amps for analog loopback */ 7707 /* Amp Indices: DAC = 0, mixer = 1 */ 7708 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7709 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7710 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7711 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7712 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7713 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7714 7715 /* FIXME: use matrix-type input source selection */ 7716 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7717 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7718 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7719 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7720 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7721 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7722 /* Input mixer2 */ 7723 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7724 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7725 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7726 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7727 /* Input mixer3 */ 7728 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7729 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7730 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7731 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7732 7733 { } 7734}; 7735 7736static struct hda_verb alc262_HP_BPC_init_verbs[] = { 7737 /* 7738 * Unmute ADC0-2 and set the default input to mic-in 7739 */ 7740 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7741 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7742 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7743 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7744 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7745 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7746 7747 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7748 * mixer widget 7749 * Note: PASD motherboards uses the Line In 2 as the input for 7750 * front panel mic (mic 2) 7751 */ 7752 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7753 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 7754 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 7755 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 7756 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 7757 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 7758 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 7759 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 7760 7761 /* 7762 * Set up output mixers (0x0c - 0x0e) 7763 */ 7764 /* set vol=0 to output mixers */ 7765 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7766 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7767 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7768 7769 /* set up input amps for analog loopback */ 7770 /* Amp Indices: DAC = 0, mixer = 1 */ 7771 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7772 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7773 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7774 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7775 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7776 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7777 7778 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7779 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 7780 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 7781 7782 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7783 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7784 7785 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 7786 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 7787 7788 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7789 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7790 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7791 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7792 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7793 7794 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, 7795 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7796 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7797 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, 7798 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7799 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7800 7801 7802 /* FIXME: use matrix-type input source selection */ 7803 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7804 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7805 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7806 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7807 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7808 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7809 /* Input mixer2 */ 7810 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7811 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7812 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7813 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7814 /* Input mixer3 */ 7815 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7816 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7817 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7818 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7819 7820 { } 7821}; 7822 7823static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = { 7824 /* 7825 * Unmute ADC0-2 and set the default input to mic-in 7826 */ 7827 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7828 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7829 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7830 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7831 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7832 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7833 7834 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7835 * mixer widget 7836 * Note: PASD motherboards uses the Line In 2 as the input for front 7837 * panel mic (mic 2) 7838 */ 7839 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7840 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 7841 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 7842 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 7843 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 7844 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 7845 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 7846 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 7847 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 7848 /* 7849 * Set up output mixers (0x0c - 0x0e) 7850 */ 7851 /* set vol=0 to output mixers */ 7852 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7853 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7854 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7855 7856 /* set up input amps for analog loopback */ 7857 /* Amp Indices: DAC = 0, mixer = 1 */ 7858 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7859 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7860 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7861 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7862 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7863 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7864 7865 7866 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */ 7867 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */ 7868 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */ 7869 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */ 7870 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */ 7871 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */ 7872 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */ 7873 7874 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7875 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7876 7877 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 7878 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 7879 7880 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */ 7881 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7882 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7883 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, 7884 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7885 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7886 7887 /* FIXME: use matrix-type input source selection */ 7888 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7889 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7890 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/ 7891 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/ 7892 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/ 7893 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/ 7894 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/ 7895 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */ 7896 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/ 7897 /* Input mixer2 */ 7898 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7899 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 7900 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7901 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7902 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7903 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */ 7904 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, 7905 /* Input mixer3 */ 7906 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7907 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 7908 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7909 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7910 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7911 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */ 7912 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, 7913 7914 { } 7915}; 7916 7917#ifdef CONFIG_SND_HDA_POWER_SAVE 7918#define alc262_loopbacks alc880_loopbacks 7919#endif 7920 7921/* pcm configuration: identiacal with ALC880 */ 7922#define alc262_pcm_analog_playback alc880_pcm_analog_playback 7923#define alc262_pcm_analog_capture alc880_pcm_analog_capture 7924#define alc262_pcm_digital_playback alc880_pcm_digital_playback 7925#define alc262_pcm_digital_capture alc880_pcm_digital_capture 7926 7927/* 7928 * BIOS auto configuration 7929 */ 7930static int alc262_parse_auto_config(struct hda_codec *codec) 7931{ 7932 struct alc_spec *spec = codec->spec; 7933 int err; 7934 static hda_nid_t alc262_ignore[] = { 0x1d, 0 }; 7935 7936 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 7937 alc262_ignore); 7938 if (err < 0) 7939 return err; 7940 if (!spec->autocfg.line_outs) 7941 return 0; /* can't find valid BIOS pin config */ 7942 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); 7943 if (err < 0) 7944 return err; 7945 err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg); 7946 if (err < 0) 7947 return err; 7948 7949 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 7950 7951 if (spec->autocfg.dig_out_pin) 7952 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; 7953 if (spec->autocfg.dig_in_pin) 7954 spec->dig_in_nid = ALC262_DIGIN_NID; 7955 7956 if (spec->kctl_alloc) 7957 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 7958 7959 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; 7960 spec->num_mux_defs = 1; 7961 spec->input_mux = &spec->private_imux; 7962 7963 return 1; 7964} 7965 7966#define alc262_auto_init_multi_out alc882_auto_init_multi_out 7967#define alc262_auto_init_hp_out alc882_auto_init_hp_out 7968#define alc262_auto_init_analog_input alc882_auto_init_analog_input 7969 7970 7971/* init callback for auto-configuration model -- overriding the default init */ 7972static void alc262_auto_init(struct hda_codec *codec) 7973{ 7974 alc262_auto_init_multi_out(codec); 7975 alc262_auto_init_hp_out(codec); 7976 alc262_auto_init_analog_input(codec); 7977} 7978 7979/* 7980 * configuration and preset 7981 */ 7982static const char *alc262_models[ALC262_MODEL_LAST] = { 7983 [ALC262_BASIC] = "basic", 7984 [ALC262_HIPPO] = "hippo", 7985 [ALC262_HIPPO_1] = "hippo_1", 7986 [ALC262_FUJITSU] = "fujitsu", 7987 [ALC262_HP_BPC] = "hp-bpc", 7988 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000", 7989 [ALC262_BENQ_ED8] = "benq", 7990 [ALC262_BENQ_T31] = "benq-t31", 7991 [ALC262_SONY_ASSAMD] = "sony-assamd", 7992 [ALC262_AUTO] = "auto", 7993}; 7994 7995static struct snd_pci_quirk alc262_cfg_tbl[] = { 7996 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), 7997 SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC), 7998 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC), 7999 SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC), 8000 SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC), 8001 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC), 8002 SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC), 8003 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC), 8004 SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC), 8005 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), 8006 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), 8007 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL), 8008 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL), 8009 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), 8010 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF), 8011 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF), 8012 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF), 8013 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO), 8014 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), 8015 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), 8016 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), 8017 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), 8018 SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), 8019 SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), 8020 SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), 8021 SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), 8022 {} 8023}; 8024 8025static struct alc_config_preset alc262_presets[] = { 8026 [ALC262_BASIC] = { 8027 .mixers = { alc262_base_mixer }, 8028 .init_verbs = { alc262_init_verbs }, 8029 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8030 .dac_nids = alc262_dac_nids, 8031 .hp_nid = 0x03, 8032 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8033 .channel_mode = alc262_modes, 8034 .input_mux = &alc262_capture_source, 8035 }, 8036 [ALC262_HIPPO] = { 8037 .mixers = { alc262_base_mixer }, 8038 .init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs}, 8039 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8040 .dac_nids = alc262_dac_nids, 8041 .hp_nid = 0x03, 8042 .dig_out_nid = ALC262_DIGOUT_NID, 8043 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8044 .channel_mode = alc262_modes, 8045 .input_mux = &alc262_capture_source, 8046 .unsol_event = alc262_hippo_unsol_event, 8047 .init_hook = alc262_hippo_automute, 8048 }, 8049 [ALC262_HIPPO_1] = { 8050 .mixers = { alc262_hippo1_mixer }, 8051 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs}, 8052 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8053 .dac_nids = alc262_dac_nids, 8054 .hp_nid = 0x02, 8055 .dig_out_nid = ALC262_DIGOUT_NID, 8056 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8057 .channel_mode = alc262_modes, 8058 .input_mux = &alc262_capture_source, 8059 .unsol_event = alc262_hippo1_unsol_event, 8060 .init_hook = alc262_hippo1_automute, 8061 }, 8062 [ALC262_FUJITSU] = { 8063 .mixers = { alc262_fujitsu_mixer }, 8064 .init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs }, 8065 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8066 .dac_nids = alc262_dac_nids, 8067 .hp_nid = 0x03, 8068 .dig_out_nid = ALC262_DIGOUT_NID, 8069 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8070 .channel_mode = alc262_modes, 8071 .input_mux = &alc262_fujitsu_capture_source, 8072 .unsol_event = alc262_fujitsu_unsol_event, 8073 }, 8074 [ALC262_HP_BPC] = { 8075 .mixers = { alc262_HP_BPC_mixer }, 8076 .init_verbs = { alc262_HP_BPC_init_verbs }, 8077 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8078 .dac_nids = alc262_dac_nids, 8079 .hp_nid = 0x03, 8080 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8081 .channel_mode = alc262_modes, 8082 .input_mux = &alc262_HP_capture_source, 8083 }, 8084 [ALC262_HP_BPC_D7000_WF] = { 8085 .mixers = { alc262_HP_BPC_WildWest_mixer }, 8086 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs }, 8087 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8088 .dac_nids = alc262_dac_nids, 8089 .hp_nid = 0x03, 8090 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8091 .channel_mode = alc262_modes, 8092 .input_mux = &alc262_HP_capture_source, 8093 }, 8094 [ALC262_HP_BPC_D7000_WL] = { 8095 .mixers = { alc262_HP_BPC_WildWest_mixer, 8096 alc262_HP_BPC_WildWest_option_mixer }, 8097 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs }, 8098 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8099 .dac_nids = alc262_dac_nids, 8100 .hp_nid = 0x03, 8101 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8102 .channel_mode = alc262_modes, 8103 .input_mux = &alc262_HP_capture_source, 8104 }, 8105 [ALC262_BENQ_ED8] = { 8106 .mixers = { alc262_base_mixer }, 8107 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs }, 8108 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8109 .dac_nids = alc262_dac_nids, 8110 .hp_nid = 0x03, 8111 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8112 .channel_mode = alc262_modes, 8113 .input_mux = &alc262_capture_source, 8114 }, 8115 [ALC262_SONY_ASSAMD] = { 8116 .mixers = { alc262_sony_mixer }, 8117 .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs}, 8118 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8119 .dac_nids = alc262_dac_nids, 8120 .hp_nid = 0x02, 8121 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8122 .channel_mode = alc262_modes, 8123 .input_mux = &alc262_capture_source, 8124 .unsol_event = alc262_hippo_unsol_event, 8125 .init_hook = alc262_hippo_automute, 8126 }, 8127 [ALC262_BENQ_T31] = { 8128 .mixers = { alc262_benq_t31_mixer }, 8129 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs, alc262_hippo_unsol_verbs }, 8130 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8131 .dac_nids = alc262_dac_nids, 8132 .hp_nid = 0x03, 8133 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8134 .channel_mode = alc262_modes, 8135 .input_mux = &alc262_capture_source, 8136 .unsol_event = alc262_hippo_unsol_event, 8137 .init_hook = alc262_hippo_automute, 8138 }, 8139}; 8140 8141static int patch_alc262(struct hda_codec *codec) 8142{ 8143 struct alc_spec *spec; 8144 int board_config; 8145 int err; 8146 8147 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 8148 if (spec == NULL) 8149 return -ENOMEM; 8150 8151 codec->spec = spec; 8152#if 0 8153 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is 8154 * under-run 8155 */ 8156 { 8157 int tmp; 8158 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); 8159 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); 8160 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); 8161 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80); 8162 } 8163#endif 8164 8165 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST, 8166 alc262_models, 8167 alc262_cfg_tbl); 8168 8169 if (board_config < 0) { 8170 printk(KERN_INFO "hda_codec: Unknown model for ALC262, " 8171 "trying auto-probe from BIOS...\n"); 8172 board_config = ALC262_AUTO; 8173 } 8174 8175 if (board_config == ALC262_AUTO) { 8176 /* automatic parse from the BIOS config */ 8177 err = alc262_parse_auto_config(codec); 8178 if (err < 0) { 8179 alc_free(codec); 8180 return err; 8181 } else if (!err) { 8182 printk(KERN_INFO 8183 "hda_codec: Cannot set up configuration " 8184 "from BIOS. Using base mode...\n"); 8185 board_config = ALC262_BASIC; 8186 } 8187 } 8188 8189 if (board_config != ALC262_AUTO) 8190 setup_preset(spec, &alc262_presets[board_config]); 8191 8192 spec->stream_name_analog = "ALC262 Analog"; 8193 spec->stream_analog_playback = &alc262_pcm_analog_playback; 8194 spec->stream_analog_capture = &alc262_pcm_analog_capture; 8195 8196 spec->stream_name_digital = "ALC262 Digital"; 8197 spec->stream_digital_playback = &alc262_pcm_digital_playback; 8198 spec->stream_digital_capture = &alc262_pcm_digital_capture; 8199 8200 if (!spec->adc_nids && spec->input_mux) { 8201 /* check whether NID 0x07 is valid */ 8202 unsigned int wcap = get_wcaps(codec, 0x07); 8203 8204 /* get type */ 8205 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 8206 if (wcap != AC_WID_AUD_IN) { 8207 spec->adc_nids = alc262_adc_nids_alt; 8208 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); 8209 spec->mixers[spec->num_mixers] = 8210 alc262_capture_alt_mixer; 8211 spec->num_mixers++; 8212 } else { 8213 spec->adc_nids = alc262_adc_nids; 8214 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids); 8215 spec->mixers[spec->num_mixers] = alc262_capture_mixer; 8216 spec->num_mixers++; 8217 } 8218 } 8219 8220 codec->patch_ops = alc_patch_ops; 8221 if (board_config == ALC262_AUTO) 8222 spec->init_hook = alc262_auto_init; 8223#ifdef CONFIG_SND_HDA_POWER_SAVE 8224 if (!spec->loopback.amplist) 8225 spec->loopback.amplist = alc262_loopbacks; 8226#endif 8227 8228 return 0; 8229} 8230 8231/* 8232 * ALC268 channel source setting (2 channel) 8233 */ 8234#define ALC268_DIGOUT_NID ALC880_DIGOUT_NID 8235#define alc268_modes alc260_modes 8236 8237static hda_nid_t alc268_dac_nids[2] = { 8238 /* front, hp */ 8239 0x02, 0x03 8240}; 8241 8242static hda_nid_t alc268_adc_nids[2] = { 8243 /* ADC0-1 */ 8244 0x08, 0x07 8245}; 8246 8247static hda_nid_t alc268_adc_nids_alt[1] = { 8248 /* ADC0 */ 8249 0x08 8250}; 8251 8252static struct snd_kcontrol_new alc268_base_mixer[] = { 8253 /* output mixer control */ 8254 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), 8255 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 8256 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), 8257 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 8258 { } 8259}; 8260 8261static struct hda_verb alc268_eapd_verbs[] = { 8262 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, 8263 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, 8264 { } 8265}; 8266 8267/* Toshiba specific */ 8268#define alc268_toshiba_automute alc262_hippo_automute 8269 8270static struct hda_verb alc268_toshiba_verbs[] = { 8271 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 8272 { } /* end */ 8273}; 8274 8275/* Acer specific */ 8276#define alc268_acer_bind_master_vol alc262_fujitsu_bind_master_vol 8277#define alc268_acer_master_sw_put alc262_fujitsu_master_sw_put 8278#define alc268_acer_automute alc262_fujitsu_automute 8279 8280static struct snd_kcontrol_new alc268_acer_mixer[] = { 8281 /* output mixer control */ 8282 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol), 8283 { 8284 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8285 .name = "Master Playback Switch", 8286 .info = snd_hda_mixer_amp_switch_info, 8287 .get = snd_hda_mixer_amp_switch_get, 8288 .put = alc268_acer_master_sw_put, 8289 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), 8290 }, 8291 { } 8292}; 8293 8294static struct hda_verb alc268_acer_verbs[] = { 8295 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 8296 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 8297 8298 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 8299 { } 8300}; 8301 8302/* unsolicited event for HP jack sensing */ 8303static void alc268_toshiba_unsol_event(struct hda_codec *codec, 8304 unsigned int res) 8305{ 8306 if ((res >> 28) != ALC880_HP_EVENT) 8307 return; 8308 alc268_toshiba_automute(codec); 8309} 8310 8311static void alc268_acer_unsol_event(struct hda_codec *codec, 8312 unsigned int res) 8313{ 8314 if ((res >> 28) != ALC880_HP_EVENT) 8315 return; 8316 alc268_acer_automute(codec, 1); 8317} 8318 8319/* 8320 * generic initialization of ADC, input mixers and output mixers 8321 */ 8322static struct hda_verb alc268_base_init_verbs[] = { 8323 /* Unmute DAC0-1 and set vol = 0 */ 8324 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8325 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8326 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8327 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8328 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8329 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8330 8331 /* 8332 * Set up output mixers (0x0c - 0x0e) 8333 */ 8334 /* set vol=0 to output mixers */ 8335 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8336 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8337 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8338 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, 8339 8340 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8341 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8342 8343 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 8344 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 8345 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 8346 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8347 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8348 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8349 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8350 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8351 8352 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8353 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8354 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8355 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8356 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8357 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8358 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8359 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 8360 8361 /* FIXME: use matrix-type input source selection */ 8362 /* Mixer elements: 0x18, 19, 1a, 1c, 14, 15, 0b */ 8363 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 8364 /* Input mixer2 */ 8365 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 8366 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 8367 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 8368 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 8369 8370 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 8371 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 8372 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 8373 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 8374 { } 8375}; 8376 8377/* 8378 * generic initialization of ADC, input mixers and output mixers 8379 */ 8380static struct hda_verb alc268_volume_init_verbs[] = { 8381 /* set output DAC */ 8382 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8383 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8384 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8385 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8386 8387 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8388 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8389 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8390 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8391 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8392 8393 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8394 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8395 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8396 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8397 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8398 8399 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8400 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8401 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8402 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8403 8404 /* set PCBEEP vol = 0 */ 8405 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0xb000 | (0x00 << 8))}, 8406 8407 { } 8408}; 8409 8410#define alc268_mux_enum_info alc_mux_enum_info 8411#define alc268_mux_enum_get alc_mux_enum_get 8412 8413static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol, 8414 struct snd_ctl_elem_value *ucontrol) 8415{ 8416 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 8417 struct alc_spec *spec = codec->spec; 8418 const struct hda_input_mux *imux = spec->input_mux; 8419 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 8420 static hda_nid_t capture_mixers[3] = { 0x23, 0x24 }; 8421 hda_nid_t nid = capture_mixers[adc_idx]; 8422 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 8423 unsigned int i, idx; 8424 8425 idx = ucontrol->value.enumerated.item[0]; 8426 if (idx >= imux->num_items) 8427 idx = imux->num_items - 1; 8428 if (*cur_val == idx) 8429 return 0; 8430 for (i = 0; i < imux->num_items; i++) { 8431 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; 8432 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 8433 imux->items[i].index, 8434 HDA_AMP_MUTE, v); 8435 snd_hda_codec_write_cache(codec, nid, 0, 8436 AC_VERB_SET_CONNECT_SEL, 8437 idx ); 8438 } 8439 *cur_val = idx; 8440 return 1; 8441} 8442 8443static struct snd_kcontrol_new alc268_capture_alt_mixer[] = { 8444 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), 8445 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), 8446 { 8447 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8448 /* The multiple "Capture Source" controls confuse alsamixer 8449 * So call somewhat different.. 8450 * FIXME: the controls appear in the "playback" view! 8451 */ 8452 /* .name = "Capture Source", */ 8453 .name = "Input Source", 8454 .count = 1, 8455 .info = alc268_mux_enum_info, 8456 .get = alc268_mux_enum_get, 8457 .put = alc268_mux_enum_put, 8458 }, 8459 { } /* end */ 8460}; 8461 8462static struct snd_kcontrol_new alc268_capture_mixer[] = { 8463 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), 8464 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), 8465 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT), 8466 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT), 8467 { 8468 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8469 /* The multiple "Capture Source" controls confuse alsamixer 8470 * So call somewhat different.. 8471 * FIXME: the controls appear in the "playback" view! 8472 */ 8473 /* .name = "Capture Source", */ 8474 .name = "Input Source", 8475 .count = 2, 8476 .info = alc268_mux_enum_info, 8477 .get = alc268_mux_enum_get, 8478 .put = alc268_mux_enum_put, 8479 }, 8480 { } /* end */ 8481}; 8482 8483static struct hda_input_mux alc268_capture_source = { 8484 .num_items = 4, 8485 .items = { 8486 { "Mic", 0x0 }, 8487 { "Front Mic", 0x1 }, 8488 { "Line", 0x2 }, 8489 { "CD", 0x3 }, 8490 }, 8491}; 8492 8493/* create input playback/capture controls for the given pin */ 8494static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, 8495 const char *ctlname, int idx) 8496{ 8497 char name[32]; 8498 int err; 8499 8500 sprintf(name, "%s Playback Volume", ctlname); 8501 if (nid == 0x14) { 8502 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 8503 HDA_COMPOSE_AMP_VAL(0x02, 3, idx, 8504 HDA_OUTPUT)); 8505 if (err < 0) 8506 return err; 8507 } else if (nid == 0x15) { 8508 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 8509 HDA_COMPOSE_AMP_VAL(0x03, 3, idx, 8510 HDA_OUTPUT)); 8511 if (err < 0) 8512 return err; 8513 } else 8514 return -1; 8515 sprintf(name, "%s Playback Switch", ctlname); 8516 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 8517 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT)); 8518 if (err < 0) 8519 return err; 8520 return 0; 8521} 8522 8523/* add playback controls from the parsed DAC table */ 8524static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec, 8525 const struct auto_pin_cfg *cfg) 8526{ 8527 hda_nid_t nid; 8528 int err; 8529 8530 spec->multiout.num_dacs = 2; /* only use one dac */ 8531 spec->multiout.dac_nids = spec->private_dac_nids; 8532 spec->multiout.dac_nids[0] = 2; 8533 spec->multiout.dac_nids[1] = 3; 8534 8535 nid = cfg->line_out_pins[0]; 8536 if (nid) 8537 alc268_new_analog_output(spec, nid, "Front", 0); 8538 8539 nid = cfg->speaker_pins[0]; 8540 if (nid == 0x1d) { 8541 err = add_control(spec, ALC_CTL_WIDGET_VOL, 8542 "Speaker Playback Volume", 8543 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); 8544 if (err < 0) 8545 return err; 8546 } 8547 nid = cfg->hp_pins[0]; 8548 if (nid) 8549 alc268_new_analog_output(spec, nid, "Headphone", 0); 8550 8551 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2]; 8552 if (nid == 0x16) { 8553 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 8554 "Mono Playback Switch", 8555 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_INPUT)); 8556 if (err < 0) 8557 return err; 8558 } 8559 return 0; 8560} 8561 8562/* create playback/capture controls for input pins */ 8563static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec, 8564 const struct auto_pin_cfg *cfg) 8565{ 8566 struct hda_input_mux *imux = &spec->private_imux; 8567 int i, idx1; 8568 8569 for (i = 0; i < AUTO_PIN_LAST; i++) { 8570 switch(cfg->input_pins[i]) { 8571 case 0x18: 8572 idx1 = 0; /* Mic 1 */ 8573 break; 8574 case 0x19: 8575 idx1 = 1; /* Mic 2 */ 8576 break; 8577 case 0x1a: 8578 idx1 = 2; /* Line In */ 8579 break; 8580 case 0x1c: 8581 idx1 = 3; /* CD */ 8582 break; 8583 default: 8584 continue; 8585 } 8586 imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; 8587 imux->items[imux->num_items].index = idx1; 8588 imux->num_items++; 8589 } 8590 return 0; 8591} 8592 8593static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) 8594{ 8595 struct alc_spec *spec = codec->spec; 8596 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0]; 8597 hda_nid_t hp_nid = spec->autocfg.hp_pins[0]; 8598 hda_nid_t line_nid = spec->autocfg.line_out_pins[0]; 8599 unsigned int dac_vol1, dac_vol2; 8600 8601 if (speaker_nid) { 8602 snd_hda_codec_write(codec, speaker_nid, 0, 8603 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 8604 snd_hda_codec_write(codec, 0x0f, 0, 8605 AC_VERB_SET_AMP_GAIN_MUTE, 8606 AMP_IN_UNMUTE(1)); 8607 snd_hda_codec_write(codec, 0x10, 0, 8608 AC_VERB_SET_AMP_GAIN_MUTE, 8609 AMP_IN_UNMUTE(1)); 8610 } else { 8611 snd_hda_codec_write(codec, 0x0f, 0, 8612 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)); 8613 snd_hda_codec_write(codec, 0x10, 0, 8614 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)); 8615 } 8616 8617 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */ 8618 if (line_nid == 0x14) 8619 dac_vol2 = AMP_OUT_ZERO; 8620 else if (line_nid == 0x15) 8621 dac_vol1 = AMP_OUT_ZERO; 8622 if (hp_nid == 0x14) 8623 dac_vol2 = AMP_OUT_ZERO; 8624 else if (hp_nid == 0x15) 8625 dac_vol1 = AMP_OUT_ZERO; 8626 if (line_nid != 0x16 || hp_nid != 0x16 || 8627 spec->autocfg.line_out_pins[1] != 0x16 || 8628 spec->autocfg.line_out_pins[2] != 0x16) 8629 dac_vol1 = dac_vol2 = AMP_OUT_ZERO; 8630 8631 snd_hda_codec_write(codec, 0x02, 0, 8632 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1); 8633 snd_hda_codec_write(codec, 0x03, 0, 8634 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2); 8635} 8636 8637/* pcm configuration: identiacal with ALC880 */ 8638#define alc268_pcm_analog_playback alc880_pcm_analog_playback 8639#define alc268_pcm_analog_capture alc880_pcm_analog_capture 8640#define alc268_pcm_digital_playback alc880_pcm_digital_playback 8641 8642/* 8643 * BIOS auto configuration 8644 */ 8645static int alc268_parse_auto_config(struct hda_codec *codec) 8646{ 8647 struct alc_spec *spec = codec->spec; 8648 int err; 8649 static hda_nid_t alc268_ignore[] = { 0 }; 8650 8651 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 8652 alc268_ignore); 8653 if (err < 0) 8654 return err; 8655 if (!spec->autocfg.line_outs) 8656 return 0; /* can't find valid BIOS pin config */ 8657 8658 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg); 8659 if (err < 0) 8660 return err; 8661 err = alc268_auto_create_analog_input_ctls(spec, &spec->autocfg); 8662 if (err < 0) 8663 return err; 8664 8665 spec->multiout.max_channels = 2; 8666 8667 /* digital only support output */ 8668 if (spec->autocfg.dig_out_pin) 8669 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; 8670 8671 if (spec->kctl_alloc) 8672 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 8673 8674 spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs; 8675 spec->num_mux_defs = 1; 8676 spec->input_mux = &spec->private_imux; 8677 8678 return 1; 8679} 8680 8681#define alc268_auto_init_multi_out alc882_auto_init_multi_out 8682#define alc268_auto_init_hp_out alc882_auto_init_hp_out 8683#define alc268_auto_init_analog_input alc882_auto_init_analog_input 8684 8685/* init callback for auto-configuration model -- overriding the default init */ 8686static void alc268_auto_init(struct hda_codec *codec) 8687{ 8688 alc268_auto_init_multi_out(codec); 8689 alc268_auto_init_hp_out(codec); 8690 alc268_auto_init_mono_speaker_out(codec); 8691 alc268_auto_init_analog_input(codec); 8692} 8693 8694/* 8695 * configuration and preset 8696 */ 8697static const char *alc268_models[ALC268_MODEL_LAST] = { 8698 [ALC268_3ST] = "3stack", 8699 [ALC268_TOSHIBA] = "toshiba", 8700 [ALC268_ACER] = "acer", 8701 [ALC268_AUTO] = "auto", 8702}; 8703 8704static struct snd_pci_quirk alc268_cfg_tbl[] = { 8705 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), 8706 SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA), 8707 SND_PCI_QUIRK(0x103c, 0x30cc, "TOSHIBA", ALC268_TOSHIBA), 8708 SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER), 8709 {} 8710}; 8711 8712static struct alc_config_preset alc268_presets[] = { 8713 [ALC268_3ST] = { 8714 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer }, 8715 .init_verbs = { alc268_base_init_verbs }, 8716 .num_dacs = ARRAY_SIZE(alc268_dac_nids), 8717 .dac_nids = alc268_dac_nids, 8718 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), 8719 .adc_nids = alc268_adc_nids_alt, 8720 .hp_nid = 0x03, 8721 .dig_out_nid = ALC268_DIGOUT_NID, 8722 .num_channel_mode = ARRAY_SIZE(alc268_modes), 8723 .channel_mode = alc268_modes, 8724 .input_mux = &alc268_capture_source, 8725 }, 8726 [ALC268_TOSHIBA] = { 8727 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer }, 8728 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, 8729 alc268_toshiba_verbs }, 8730 .num_dacs = ARRAY_SIZE(alc268_dac_nids), 8731 .dac_nids = alc268_dac_nids, 8732 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), 8733 .adc_nids = alc268_adc_nids_alt, 8734 .hp_nid = 0x03, 8735 .num_channel_mode = ARRAY_SIZE(alc268_modes), 8736 .channel_mode = alc268_modes, 8737 .input_mux = &alc268_capture_source, 8738 .input_mux = &alc268_capture_source, 8739 .unsol_event = alc268_toshiba_unsol_event, 8740 .init_hook = alc268_toshiba_automute, 8741 }, 8742 [ALC268_ACER] = { 8743 .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer }, 8744 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, 8745 alc268_acer_verbs }, 8746 .num_dacs = ARRAY_SIZE(alc268_dac_nids), 8747 .dac_nids = alc268_dac_nids, 8748 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), 8749 .adc_nids = alc268_adc_nids_alt, 8750 .hp_nid = 0x02, 8751 .num_channel_mode = ARRAY_SIZE(alc268_modes), 8752 .channel_mode = alc268_modes, 8753 .input_mux = &alc268_capture_source, 8754 .unsol_event = alc268_acer_unsol_event, 8755 }, 8756}; 8757 8758static int patch_alc268(struct hda_codec *codec) 8759{ 8760 struct alc_spec *spec; 8761 int board_config; 8762 int err; 8763 8764 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); 8765 if (spec == NULL) 8766 return -ENOMEM; 8767 8768 codec->spec = spec; 8769 8770 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST, 8771 alc268_models, 8772 alc268_cfg_tbl); 8773 8774 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) { 8775 printk(KERN_INFO "hda_codec: Unknown model for ALC268, " 8776 "trying auto-probe from BIOS...\n"); 8777 board_config = ALC268_AUTO; 8778 } 8779 8780 if (board_config == ALC268_AUTO) { 8781 /* automatic parse from the BIOS config */ 8782 err = alc268_parse_auto_config(codec); 8783 if (err < 0) { 8784 alc_free(codec); 8785 return err; 8786 } else if (!err) { 8787 printk(KERN_INFO 8788 "hda_codec: Cannot set up configuration " 8789 "from BIOS. Using base mode...\n"); 8790 board_config = ALC268_3ST; 8791 } 8792 } 8793 8794 if (board_config != ALC268_AUTO) 8795 setup_preset(spec, &alc268_presets[board_config]); 8796 8797 spec->stream_name_analog = "ALC268 Analog"; 8798 spec->stream_analog_playback = &alc268_pcm_analog_playback; 8799 spec->stream_analog_capture = &alc268_pcm_analog_capture; 8800 8801 spec->stream_name_digital = "ALC268 Digital"; 8802 spec->stream_digital_playback = &alc268_pcm_digital_playback; 8803 8804 if (board_config == ALC268_AUTO) { 8805 if (!spec->adc_nids && spec->input_mux) { 8806 /* check whether NID 0x07 is valid */ 8807 unsigned int wcap = get_wcaps(codec, 0x07); 8808 8809 /* get type */ 8810 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 8811 if (wcap != AC_WID_AUD_IN) { 8812 spec->adc_nids = alc268_adc_nids_alt; 8813 spec->num_adc_nids = 8814 ARRAY_SIZE(alc268_adc_nids_alt); 8815 spec->mixers[spec->num_mixers] = 8816 alc268_capture_alt_mixer; 8817 spec->num_mixers++; 8818 } else { 8819 spec->adc_nids = alc268_adc_nids; 8820 spec->num_adc_nids = 8821 ARRAY_SIZE(alc268_adc_nids); 8822 spec->mixers[spec->num_mixers] = 8823 alc268_capture_mixer; 8824 spec->num_mixers++; 8825 } 8826 } 8827 } 8828 codec->patch_ops = alc_patch_ops; 8829 if (board_config == ALC268_AUTO) 8830 spec->init_hook = alc268_auto_init; 8831 8832 return 0; 8833} 8834 8835/* 8836 * ALC861 channel source setting (2/6 channel selection for 3-stack) 8837 */ 8838 8839/* 8840 * set the path ways for 2 channel output 8841 * need to set the codec line out and mic 1 pin widgets to inputs 8842 */ 8843static struct hda_verb alc861_threestack_ch2_init[] = { 8844 /* set pin widget 1Ah (line in) for input */ 8845 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8846 /* set pin widget 18h (mic1/2) for input, for mic also enable 8847 * the vref 8848 */ 8849 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8850 8851 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, 8852#if 0 8853 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ 8854 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/ 8855#endif 8856 { } /* end */ 8857}; 8858/* 8859 * 6ch mode 8860 * need to set the codec line out and mic 1 pin widgets to outputs 8861 */ 8862static struct hda_verb alc861_threestack_ch6_init[] = { 8863 /* set pin widget 1Ah (line in) for output (Back Surround)*/ 8864 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8865 /* set pin widget 18h (mic1) for output (CLFE)*/ 8866 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8867 8868 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8869 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8870 8871 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, 8872#if 0 8873 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ 8874 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/ 8875#endif 8876 { } /* end */ 8877}; 8878 8879static struct hda_channel_mode alc861_threestack_modes[2] = { 8880 { 2, alc861_threestack_ch2_init }, 8881 { 6, alc861_threestack_ch6_init }, 8882}; 8883/* Set mic1 as input and unmute the mixer */ 8884static struct hda_verb alc861_uniwill_m31_ch2_init[] = { 8885 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8886 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ 8887 { } /* end */ 8888}; 8889/* Set mic1 as output and mute mixer */ 8890static struct hda_verb alc861_uniwill_m31_ch4_init[] = { 8891 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8892 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ 8893 { } /* end */ 8894}; 8895 8896static struct hda_channel_mode alc861_uniwill_m31_modes[2] = { 8897 { 2, alc861_uniwill_m31_ch2_init }, 8898 { 4, alc861_uniwill_m31_ch4_init }, 8899}; 8900 8901/* Set mic1 and line-in as input and unmute the mixer */ 8902static struct hda_verb alc861_asus_ch2_init[] = { 8903 /* set pin widget 1Ah (line in) for input */ 8904 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8905 /* set pin widget 18h (mic1/2) for input, for mic also enable 8906 * the vref 8907 */ 8908 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8909 8910 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, 8911#if 0 8912 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ 8913 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/ 8914#endif 8915 { } /* end */ 8916}; 8917/* Set mic1 nad line-in as output and mute mixer */ 8918static struct hda_verb alc861_asus_ch6_init[] = { 8919 /* set pin widget 1Ah (line in) for output (Back Surround)*/ 8920 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8921 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */ 8922 /* set pin widget 18h (mic1) for output (CLFE)*/ 8923 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8924 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */ 8925 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8926 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8927 8928 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, 8929#if 0 8930 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ 8931 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/ 8932#endif 8933 { } /* end */ 8934}; 8935 8936static struct hda_channel_mode alc861_asus_modes[2] = { 8937 { 2, alc861_asus_ch2_init }, 8938 { 6, alc861_asus_ch6_init }, 8939}; 8940 8941/* patch-ALC861 */ 8942 8943static struct snd_kcontrol_new alc861_base_mixer[] = { 8944 /* output mixer control */ 8945 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8946 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 8947 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 8948 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 8949 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), 8950 8951 /*Input mixer control */ 8952 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 8953 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ 8954 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8955 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8956 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 8957 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 8958 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8959 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8960 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 8961 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), 8962 8963 /* Capture mixer control */ 8964 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8965 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8966 { 8967 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8968 .name = "Capture Source", 8969 .count = 1, 8970 .info = alc_mux_enum_info, 8971 .get = alc_mux_enum_get, 8972 .put = alc_mux_enum_put, 8973 }, 8974 { } /* end */ 8975}; 8976 8977static struct snd_kcontrol_new alc861_3ST_mixer[] = { 8978 /* output mixer control */ 8979 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8980 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 8981 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 8982 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 8983 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */ 8984 8985 /* Input mixer control */ 8986 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 8987 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ 8988 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8989 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8990 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 8991 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 8992 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8993 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8994 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 8995 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), 8996 8997 /* Capture mixer control */ 8998 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8999 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 9000 { 9001 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9002 .name = "Capture Source", 9003 .count = 1, 9004 .info = alc_mux_enum_info, 9005 .get = alc_mux_enum_get, 9006 .put = alc_mux_enum_put, 9007 }, 9008 { 9009 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9010 .name = "Channel Mode", 9011 .info = alc_ch_mode_info, 9012 .get = alc_ch_mode_get, 9013 .put = alc_ch_mode_put, 9014 .private_value = ARRAY_SIZE(alc861_threestack_modes), 9015 }, 9016 { } /* end */ 9017}; 9018 9019static struct snd_kcontrol_new alc861_toshiba_mixer[] = { 9020 /* output mixer control */ 9021 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT), 9022 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 9023 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 9024 9025 /*Capture mixer control */ 9026 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 9027 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 9028 { 9029 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9030 .name = "Capture Source", 9031 .count = 1, 9032 .info = alc_mux_enum_info, 9033 .get = alc_mux_enum_get, 9034 .put = alc_mux_enum_put, 9035 }, 9036 9037 { } /* end */ 9038}; 9039 9040static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { 9041 /* output mixer control */ 9042 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 9043 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 9044 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 9045 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 9046 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */ 9047 9048 /* Input mixer control */ 9049 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 9050 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ 9051 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 9052 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 9053 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 9054 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 9055 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 9056 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 9057 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 9058 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), 9059 9060 /* Capture mixer control */ 9061 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 9062 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 9063 { 9064 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9065 .name = "Capture Source", 9066 .count = 1, 9067 .info = alc_mux_enum_info, 9068 .get = alc_mux_enum_get, 9069 .put = alc_mux_enum_put, 9070 }, 9071 { 9072 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9073 .name = "Channel Mode", 9074 .info = alc_ch_mode_info, 9075 .get = alc_ch_mode_get, 9076 .put = alc_ch_mode_put, 9077 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes), 9078 }, 9079 { } /* end */ 9080}; 9081 9082static struct snd_kcontrol_new alc861_asus_mixer[] = { 9083 /* output mixer control */ 9084 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 9085 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 9086 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 9087 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 9088 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), 9089 9090 /* Input mixer control */ 9091 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 9092 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), 9093 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 9094 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 9095 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 9096 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 9097 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 9098 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 9099 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 9100 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), 9101 9102 /* Capture mixer control */ 9103 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 9104 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 9105 { 9106 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9107 .name = "Capture Source", 9108 .count = 1, 9109 .info = alc_mux_enum_info, 9110 .get = alc_mux_enum_get, 9111 .put = alc_mux_enum_put, 9112 }, 9113 { 9114 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9115 .name = "Channel Mode", 9116 .info = alc_ch_mode_info, 9117 .get = alc_ch_mode_get, 9118 .put = alc_ch_mode_put, 9119 .private_value = ARRAY_SIZE(alc861_asus_modes), 9120 }, 9121 { } 9122}; 9123 9124/* additional mixer */ 9125static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = { 9126 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 9127 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 9128 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT), 9129 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT), 9130 { } 9131}; 9132 9133/* 9134 * generic initialization of ADC, input mixers and output mixers 9135 */ 9136static struct hda_verb alc861_base_init_verbs[] = { 9137 /* 9138 * Unmute ADC0 and set the default input to mic-in 9139 */ 9140 /* port-A for surround (rear panel) */ 9141 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9142 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9143 /* port-B for mic-in (rear panel) with vref */ 9144 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9145 /* port-C for line-in (rear panel) */ 9146 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9147 /* port-D for Front */ 9148 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9149 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9150 /* port-E for HP out (front panel) */ 9151 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 9152 /* route front PCM to HP */ 9153 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9154 /* port-F for mic-in (front panel) with vref */ 9155 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9156 /* port-G for CLFE (rear panel) */ 9157 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9158 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9159 /* port-H for side (rear panel) */ 9160 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9161 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9162 /* CD-in */ 9163 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9164 /* route front mic to ADC1*/ 9165 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 9166 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9167 9168 /* Unmute DAC0~3 & spdif out*/ 9169 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9170 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9171 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9172 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9173 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9174 9175 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9176 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9177 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9178 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9179 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9180 9181 /* Unmute Stereo Mixer 15 */ 9182 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9183 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9184 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9185 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 9186 9187 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9188 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9189 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9190 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9191 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9192 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9193 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9194 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9195 /* hp used DAC 3 (Front) */ 9196 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9197 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9198 9199 { } 9200}; 9201 9202static struct hda_verb alc861_threestack_init_verbs[] = { 9203 /* 9204 * Unmute ADC0 and set the default input to mic-in 9205 */ 9206 /* port-A for surround (rear panel) */ 9207 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9208 /* port-B for mic-in (rear panel) with vref */ 9209 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9210 /* port-C for line-in (rear panel) */ 9211 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9212 /* port-D for Front */ 9213 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9214 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9215 /* port-E for HP out (front panel) */ 9216 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 9217 /* route front PCM to HP */ 9218 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9219 /* port-F for mic-in (front panel) with vref */ 9220 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9221 /* port-G for CLFE (rear panel) */ 9222 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9223 /* port-H for side (rear panel) */ 9224 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9225 /* CD-in */ 9226 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9227 /* route front mic to ADC1*/ 9228 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 9229 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9230 /* Unmute DAC0~3 & spdif out*/ 9231 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9232 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9233 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9234 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9235 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9236 9237 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9238 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9239 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9240 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9241 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9242 9243 /* Unmute Stereo Mixer 15 */ 9244 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9245 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9246 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9247 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 9248 9249 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9250 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9251 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9252 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9253 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9254 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9255 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9256 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9257 /* hp used DAC 3 (Front) */ 9258 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9259 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9260 { } 9261}; 9262 9263static struct hda_verb alc861_uniwill_m31_init_verbs[] = { 9264 /* 9265 * Unmute ADC0 and set the default input to mic-in 9266 */ 9267 /* port-A for surround (rear panel) */ 9268 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9269 /* port-B for mic-in (rear panel) with vref */ 9270 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9271 /* port-C for line-in (rear panel) */ 9272 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9273 /* port-D for Front */ 9274 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9275 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9276 /* port-E for HP out (front panel) */ 9277 /* this has to be set to VREF80 */ 9278 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9279 /* route front PCM to HP */ 9280 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9281 /* port-F for mic-in (front panel) with vref */ 9282 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9283 /* port-G for CLFE (rear panel) */ 9284 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9285 /* port-H for side (rear panel) */ 9286 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9287 /* CD-in */ 9288 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9289 /* route front mic to ADC1*/ 9290 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 9291 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9292 /* Unmute DAC0~3 & spdif out*/ 9293 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9294 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9295 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9296 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9297 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9298 9299 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9300 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9301 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9302 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9303 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9304 9305 /* Unmute Stereo Mixer 15 */ 9306 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9307 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9308 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9309 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 9310 9311 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9312 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9313 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9314 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9315 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9316 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9317 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9318 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9319 /* hp used DAC 3 (Front) */ 9320 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9321 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9322 { } 9323}; 9324 9325static struct hda_verb alc861_asus_init_verbs[] = { 9326 /* 9327 * Unmute ADC0 and set the default input to mic-in 9328 */ 9329 /* port-A for surround (rear panel) 9330 * according to codec#0 this is the HP jack 9331 */ 9332 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */ 9333 /* route front PCM to HP */ 9334 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 }, 9335 /* port-B for mic-in (rear panel) with vref */ 9336 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9337 /* port-C for line-in (rear panel) */ 9338 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9339 /* port-D for Front */ 9340 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9341 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9342 /* port-E for HP out (front panel) */ 9343 /* this has to be set to VREF80 */ 9344 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9345 /* route front PCM to HP */ 9346 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9347 /* port-F for mic-in (front panel) with vref */ 9348 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9349 /* port-G for CLFE (rear panel) */ 9350 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9351 /* port-H for side (rear panel) */ 9352 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9353 /* CD-in */ 9354 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9355 /* route front mic to ADC1*/ 9356 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 9357 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9358 /* Unmute DAC0~3 & spdif out*/ 9359 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9360 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9361 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9362 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9363 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9364 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9365 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9366 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9367 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9368 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9369 9370 /* Unmute Stereo Mixer 15 */ 9371 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9372 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9373 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9374 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 9375 9376 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9377 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9378 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9379 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9380 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9381 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9382 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9383 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9384 /* hp used DAC 3 (Front) */ 9385 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9386 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9387 { } 9388}; 9389 9390/* additional init verbs for ASUS laptops */ 9391static struct hda_verb alc861_asus_laptop_init_verbs[] = { 9392 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */ 9393 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */ 9394 { } 9395}; 9396 9397/* 9398 * generic initialization of ADC, input mixers and output mixers 9399 */ 9400static struct hda_verb alc861_auto_init_verbs[] = { 9401 /* 9402 * Unmute ADC0 and set the default input to mic-in 9403 */ 9404 /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */ 9405 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9406 9407 /* Unmute DAC0~3 & spdif out*/ 9408 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9409 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9410 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9411 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9412 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9413 9414 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9415 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9416 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9417 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9418 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9419 9420 /* Unmute Stereo Mixer 15 */ 9421 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9422 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9423 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9424 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, 9425 9426 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9427 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9428 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9429 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9430 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9431 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9432 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9433 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9434 9435 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 9436 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 9437 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9438 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9439 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 9440 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 9441 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9442 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9443 9444 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */ 9445 9446 { } 9447}; 9448 9449static struct hda_verb alc861_toshiba_init_verbs[] = { 9450 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 9451 9452 { } 9453}; 9454 9455/* toggle speaker-output according to the hp-jack state */ 9456static void alc861_toshiba_automute(struct hda_codec *codec) 9457{ 9458 unsigned int present; 9459 9460 present = snd_hda_codec_read(codec, 0x0f, 0, 9461 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 9462 snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0, 9463 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 9464 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3, 9465 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE); 9466} 9467 9468static void alc861_toshiba_unsol_event(struct hda_codec *codec, 9469 unsigned int res) 9470{ 9471 if ((res >> 26) == ALC880_HP_EVENT) 9472 alc861_toshiba_automute(codec); 9473} 9474 9475/* pcm configuration: identiacal with ALC880 */ 9476#define alc861_pcm_analog_playback alc880_pcm_analog_playback 9477#define alc861_pcm_analog_capture alc880_pcm_analog_capture 9478#define alc861_pcm_digital_playback alc880_pcm_digital_playback 9479#define alc861_pcm_digital_capture alc880_pcm_digital_capture 9480 9481 9482#define ALC861_DIGOUT_NID 0x07 9483 9484static struct hda_channel_mode alc861_8ch_modes[1] = { 9485 { 8, NULL } 9486}; 9487 9488static hda_nid_t alc861_dac_nids[4] = { 9489 /* front, surround, clfe, side */ 9490 0x03, 0x06, 0x05, 0x04 9491}; 9492 9493static hda_nid_t alc660_dac_nids[3] = { 9494 /* front, clfe, surround */ 9495 0x03, 0x05, 0x06 9496}; 9497 9498static hda_nid_t alc861_adc_nids[1] = { 9499 /* ADC0-2 */ 9500 0x08, 9501}; 9502 9503static struct hda_input_mux alc861_capture_source = { 9504 .num_items = 5, 9505 .items = { 9506 { "Mic", 0x0 }, 9507 { "Front Mic", 0x3 }, 9508 { "Line", 0x1 }, 9509 { "CD", 0x4 }, 9510 { "Mixer", 0x5 }, 9511 }, 9512}; 9513 9514/* fill in the dac_nids table from the parsed pin configuration */ 9515static int alc861_auto_fill_dac_nids(struct alc_spec *spec, 9516 const struct auto_pin_cfg *cfg) 9517{ 9518 int i; 9519 hda_nid_t nid; 9520 9521 spec->multiout.dac_nids = spec->private_dac_nids; 9522 for (i = 0; i < cfg->line_outs; i++) { 9523 nid = cfg->line_out_pins[i]; 9524 if (nid) { 9525 if (i >= ARRAY_SIZE(alc861_dac_nids)) 9526 continue; 9527 spec->multiout.dac_nids[i] = alc861_dac_nids[i]; 9528 } 9529 } 9530 spec->multiout.num_dacs = cfg->line_outs; 9531 return 0; 9532} 9533 9534/* add playback controls from the parsed DAC table */ 9535static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec, 9536 const struct auto_pin_cfg *cfg) 9537{ 9538 char name[32]; 9539 static const char *chname[4] = { 9540 "Front", "Surround", NULL /*CLFE*/, "Side" 9541 }; 9542 hda_nid_t nid; 9543 int i, idx, err; 9544 9545 for (i = 0; i < cfg->line_outs; i++) { 9546 nid = spec->multiout.dac_nids[i]; 9547 if (!nid) 9548 continue; 9549 if (nid == 0x05) { 9550 /* Center/LFE */ 9551 err = add_control(spec, ALC_CTL_BIND_MUTE, 9552 "Center Playback Switch", 9553 HDA_COMPOSE_AMP_VAL(nid, 1, 0, 9554 HDA_OUTPUT)); 9555 if (err < 0) 9556 return err; 9557 err = add_control(spec, ALC_CTL_BIND_MUTE, 9558 "LFE Playback Switch", 9559 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 9560 HDA_OUTPUT)); 9561 if (err < 0) 9562 return err; 9563 } else { 9564 for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; 9565 idx++) 9566 if (nid == alc861_dac_nids[idx]) 9567 break; 9568 sprintf(name, "%s Playback Switch", chname[idx]); 9569 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 9570 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 9571 HDA_OUTPUT)); 9572 if (err < 0) 9573 return err; 9574 } 9575 } 9576 return 0; 9577} 9578 9579static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) 9580{ 9581 int err; 9582 hda_nid_t nid; 9583 9584 if (!pin) 9585 return 0; 9586 9587 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) { 9588 nid = 0x03; 9589 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 9590 "Headphone Playback Switch", 9591 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 9592 if (err < 0) 9593 return err; 9594 spec->multiout.hp_nid = nid; 9595 } 9596 return 0; 9597} 9598 9599/* create playback/capture controls for input pins */ 9600static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, 9601 const struct auto_pin_cfg *cfg) 9602{ 9603 struct hda_input_mux *imux = &spec->private_imux; 9604 int i, err, idx, idx1; 9605 9606 for (i = 0; i < AUTO_PIN_LAST; i++) { 9607 switch (cfg->input_pins[i]) { 9608 case 0x0c: 9609 idx1 = 1; 9610 idx = 2; /* Line In */ 9611 break; 9612 case 0x0f: 9613 idx1 = 2; 9614 idx = 2; /* Line In */ 9615 break; 9616 case 0x0d: 9617 idx1 = 0; 9618 idx = 1; /* Mic In */ 9619 break; 9620 case 0x10: 9621 idx1 = 3; 9622 idx = 1; /* Mic In */ 9623 break; 9624 case 0x11: 9625 idx1 = 4; 9626 idx = 0; /* CD */ 9627 break; 9628 default: 9629 continue; 9630 } 9631 9632 err = new_analog_input(spec, cfg->input_pins[i], 9633 auto_pin_cfg_labels[i], idx, 0x15); 9634 if (err < 0) 9635 return err; 9636 9637 imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; 9638 imux->items[imux->num_items].index = idx1; 9639 imux->num_items++; 9640 } 9641 return 0; 9642} 9643 9644static struct snd_kcontrol_new alc861_capture_mixer[] = { 9645 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 9646 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 9647 9648 { 9649 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9650 /* The multiple "Capture Source" controls confuse alsamixer 9651 * So call somewhat different.. 9652 *FIXME: the controls appear in the "playback" view! 9653 */ 9654 /* .name = "Capture Source", */ 9655 .name = "Input Source", 9656 .count = 1, 9657 .info = alc_mux_enum_info, 9658 .get = alc_mux_enum_get, 9659 .put = alc_mux_enum_put, 9660 }, 9661 { } /* end */ 9662}; 9663 9664static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, 9665 hda_nid_t nid, 9666 int pin_type, int dac_idx) 9667{ 9668 /* set as output */ 9669 9670 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 9671 pin_type); 9672 snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, 9673 AMP_OUT_UNMUTE); 9674 9675} 9676 9677static void alc861_auto_init_multi_out(struct hda_codec *codec) 9678{ 9679 struct alc_spec *spec = codec->spec; 9680 int i; 9681 9682 alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b); 9683 for (i = 0; i < spec->autocfg.line_outs; i++) { 9684 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 9685 int pin_type = get_pin_type(spec->autocfg.line_out_type); 9686 if (nid) 9687 alc861_auto_set_output_and_unmute(codec, nid, pin_type, 9688 spec->multiout.dac_nids[i]); 9689 } 9690} 9691 9692static void alc861_auto_init_hp_out(struct hda_codec *codec) 9693{ 9694 struct alc_spec *spec = codec->spec; 9695 hda_nid_t pin; 9696 9697 pin = spec->autocfg.hp_pins[0]; 9698 if (pin) /* connect to front */ 9699 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, 9700 spec->multiout.dac_nids[0]); 9701} 9702 9703static void alc861_auto_init_analog_input(struct hda_codec *codec) 9704{ 9705 struct alc_spec *spec = codec->spec; 9706 int i; 9707 9708 for (i = 0; i < AUTO_PIN_LAST; i++) { 9709 hda_nid_t nid = spec->autocfg.input_pins[i]; 9710 if (nid >= 0x0c && nid <= 0x11) { 9711 snd_hda_codec_write(codec, nid, 0, 9712 AC_VERB_SET_PIN_WIDGET_CONTROL, 9713 i <= AUTO_PIN_FRONT_MIC ? 9714 PIN_VREF80 : PIN_IN); 9715 } 9716 } 9717} 9718 9719/* parse the BIOS configuration and set up the alc_spec */ 9720/* return 1 if successful, 0 if the proper config is not found, 9721 * or a negative error code 9722 */ 9723static int alc861_parse_auto_config(struct hda_codec *codec) 9724{ 9725 struct alc_spec *spec = codec->spec; 9726 int err; 9727 static hda_nid_t alc861_ignore[] = { 0x1d, 0 }; 9728 9729 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 9730 alc861_ignore); 9731 if (err < 0) 9732 return err; 9733 if (!spec->autocfg.line_outs) 9734 return 0; /* can't find valid BIOS pin config */ 9735 9736 err = alc861_auto_fill_dac_nids(spec, &spec->autocfg); 9737 if (err < 0) 9738 return err; 9739 err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg); 9740 if (err < 0) 9741 return err; 9742 err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 9743 if (err < 0) 9744 return err; 9745 err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg); 9746 if (err < 0) 9747 return err; 9748 9749 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 9750 9751 if (spec->autocfg.dig_out_pin) 9752 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; 9753 9754 if (spec->kctl_alloc) 9755 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 9756 9757 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; 9758 9759 spec->num_mux_defs = 1; 9760 spec->input_mux = &spec->private_imux; 9761 9762 spec->adc_nids = alc861_adc_nids; 9763 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); 9764 spec->mixers[spec->num_mixers] = alc861_capture_mixer; 9765 spec->num_mixers++; 9766 9767 return 1; 9768} 9769 9770/* additional initialization for auto-configuration model */ 9771static void alc861_auto_init(struct hda_codec *codec) 9772{ 9773 alc861_auto_init_multi_out(codec); 9774 alc861_auto_init_hp_out(codec); 9775 alc861_auto_init_analog_input(codec); 9776} 9777 9778#ifdef CONFIG_SND_HDA_POWER_SAVE 9779static struct hda_amp_list alc861_loopbacks[] = { 9780 { 0x15, HDA_INPUT, 0 }, 9781 { 0x15, HDA_INPUT, 1 }, 9782 { 0x15, HDA_INPUT, 2 }, 9783 { 0x15, HDA_INPUT, 3 }, 9784 { } /* end */ 9785}; 9786#endif 9787 9788 9789/* 9790 * configuration and preset 9791 */ 9792static const char *alc861_models[ALC861_MODEL_LAST] = { 9793 [ALC861_3ST] = "3stack", 9794 [ALC660_3ST] = "3stack-660", 9795 [ALC861_3ST_DIG] = "3stack-dig", 9796 [ALC861_6ST_DIG] = "6stack-dig", 9797 [ALC861_UNIWILL_M31] = "uniwill-m31", 9798 [ALC861_TOSHIBA] = "toshiba", 9799 [ALC861_ASUS] = "asus", 9800 [ALC861_ASUS_LAPTOP] = "asus-laptop", 9801 [ALC861_AUTO] = "auto", 9802}; 9803 9804static struct snd_pci_quirk alc861_cfg_tbl[] = { 9805 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST), 9806 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP), 9807 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP), 9808 SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP), 9809 SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP), 9810 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS), 9811 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG), 9812 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA), 9813 /* FIXME: the entry below breaks Toshiba A100 (model=auto works!) 9814 * Any other models that need this preset? 9815 */ 9816 /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */ 9817 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31), 9818 SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), 9819 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31), 9820 SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST), 9821 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST), 9822 SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST), 9823 SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST), 9824 {} 9825}; 9826 9827static struct alc_config_preset alc861_presets[] = { 9828 [ALC861_3ST] = { 9829 .mixers = { alc861_3ST_mixer }, 9830 .init_verbs = { alc861_threestack_init_verbs }, 9831 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9832 .dac_nids = alc861_dac_nids, 9833 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), 9834 .channel_mode = alc861_threestack_modes, 9835 .need_dac_fix = 1, 9836 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9837 .adc_nids = alc861_adc_nids, 9838 .input_mux = &alc861_capture_source, 9839 }, 9840 [ALC861_3ST_DIG] = { 9841 .mixers = { alc861_base_mixer }, 9842 .init_verbs = { alc861_threestack_init_verbs }, 9843 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9844 .dac_nids = alc861_dac_nids, 9845 .dig_out_nid = ALC861_DIGOUT_NID, 9846 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), 9847 .channel_mode = alc861_threestack_modes, 9848 .need_dac_fix = 1, 9849 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9850 .adc_nids = alc861_adc_nids, 9851 .input_mux = &alc861_capture_source, 9852 }, 9853 [ALC861_6ST_DIG] = { 9854 .mixers = { alc861_base_mixer }, 9855 .init_verbs = { alc861_base_init_verbs }, 9856 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9857 .dac_nids = alc861_dac_nids, 9858 .dig_out_nid = ALC861_DIGOUT_NID, 9859 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes), 9860 .channel_mode = alc861_8ch_modes, 9861 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9862 .adc_nids = alc861_adc_nids, 9863 .input_mux = &alc861_capture_source, 9864 }, 9865 [ALC660_3ST] = { 9866 .mixers = { alc861_3ST_mixer }, 9867 .init_verbs = { alc861_threestack_init_verbs }, 9868 .num_dacs = ARRAY_SIZE(alc660_dac_nids), 9869 .dac_nids = alc660_dac_nids, 9870 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), 9871 .channel_mode = alc861_threestack_modes, 9872 .need_dac_fix = 1, 9873 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9874 .adc_nids = alc861_adc_nids, 9875 .input_mux = &alc861_capture_source, 9876 }, 9877 [ALC861_UNIWILL_M31] = { 9878 .mixers = { alc861_uniwill_m31_mixer }, 9879 .init_verbs = { alc861_uniwill_m31_init_verbs }, 9880 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9881 .dac_nids = alc861_dac_nids, 9882 .dig_out_nid = ALC861_DIGOUT_NID, 9883 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes), 9884 .channel_mode = alc861_uniwill_m31_modes, 9885 .need_dac_fix = 1, 9886 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9887 .adc_nids = alc861_adc_nids, 9888 .input_mux = &alc861_capture_source, 9889 }, 9890 [ALC861_TOSHIBA] = { 9891 .mixers = { alc861_toshiba_mixer }, 9892 .init_verbs = { alc861_base_init_verbs, 9893 alc861_toshiba_init_verbs }, 9894 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9895 .dac_nids = alc861_dac_nids, 9896 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 9897 .channel_mode = alc883_3ST_2ch_modes, 9898 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9899 .adc_nids = alc861_adc_nids, 9900 .input_mux = &alc861_capture_source, 9901 .unsol_event = alc861_toshiba_unsol_event, 9902 .init_hook = alc861_toshiba_automute, 9903 }, 9904 [ALC861_ASUS] = { 9905 .mixers = { alc861_asus_mixer }, 9906 .init_verbs = { alc861_asus_init_verbs }, 9907 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9908 .dac_nids = alc861_dac_nids, 9909 .dig_out_nid = ALC861_DIGOUT_NID, 9910 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes), 9911 .channel_mode = alc861_asus_modes, 9912 .need_dac_fix = 1, 9913 .hp_nid = 0x06, 9914 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9915 .adc_nids = alc861_adc_nids, 9916 .input_mux = &alc861_capture_source, 9917 }, 9918 [ALC861_ASUS_LAPTOP] = { 9919 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer }, 9920 .init_verbs = { alc861_asus_init_verbs, 9921 alc861_asus_laptop_init_verbs }, 9922 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9923 .dac_nids = alc861_dac_nids, 9924 .dig_out_nid = ALC861_DIGOUT_NID, 9925 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 9926 .channel_mode = alc883_3ST_2ch_modes, 9927 .need_dac_fix = 1, 9928 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9929 .adc_nids = alc861_adc_nids, 9930 .input_mux = &alc861_capture_source, 9931 }, 9932}; 9933 9934 9935static int patch_alc861(struct hda_codec *codec) 9936{ 9937 struct alc_spec *spec; 9938 int board_config; 9939 int err; 9940 9941 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 9942 if (spec == NULL) 9943 return -ENOMEM; 9944 9945 codec->spec = spec; 9946 9947 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST, 9948 alc861_models, 9949 alc861_cfg_tbl); 9950 9951 if (board_config < 0) { 9952 printk(KERN_INFO "hda_codec: Unknown model for ALC861, " 9953 "trying auto-probe from BIOS...\n"); 9954 board_config = ALC861_AUTO; 9955 } 9956 9957 if (board_config == ALC861_AUTO) { 9958 /* automatic parse from the BIOS config */ 9959 err = alc861_parse_auto_config(codec); 9960 if (err < 0) { 9961 alc_free(codec); 9962 return err; 9963 } else if (!err) { 9964 printk(KERN_INFO 9965 "hda_codec: Cannot set up configuration " 9966 "from BIOS. Using base mode...\n"); 9967 board_config = ALC861_3ST_DIG; 9968 } 9969 } 9970 9971 if (board_config != ALC861_AUTO) 9972 setup_preset(spec, &alc861_presets[board_config]); 9973 9974 spec->stream_name_analog = "ALC861 Analog"; 9975 spec->stream_analog_playback = &alc861_pcm_analog_playback; 9976 spec->stream_analog_capture = &alc861_pcm_analog_capture; 9977 9978 spec->stream_name_digital = "ALC861 Digital"; 9979 spec->stream_digital_playback = &alc861_pcm_digital_playback; 9980 spec->stream_digital_capture = &alc861_pcm_digital_capture; 9981 9982 codec->patch_ops = alc_patch_ops; 9983 if (board_config == ALC861_AUTO) 9984 spec->init_hook = alc861_auto_init; 9985#ifdef CONFIG_SND_HDA_POWER_SAVE 9986 if (!spec->loopback.amplist) 9987 spec->loopback.amplist = alc861_loopbacks; 9988#endif 9989 9990 return 0; 9991} 9992 9993/* 9994 * ALC861-VD support 9995 * 9996 * Based on ALC882 9997 * 9998 * In addition, an independent DAC 9999 */ 10000#define ALC861VD_DIGOUT_NID 0x06 10001 10002static hda_nid_t alc861vd_dac_nids[4] = { 10003 /* front, surr, clfe, side surr */ 10004 0x02, 0x03, 0x04, 0x05 10005}; 10006 10007/* dac_nids for ALC660vd are in a different order - according to 10008 * Realtek's driver. 10009 * This should probably tesult in a different mixer for 6stack models 10010 * of ALC660vd codecs, but for now there is only 3stack mixer 10011 * - and it is the same as in 861vd. 10012 * adc_nids in ALC660vd are (is) the same as in 861vd 10013 */ 10014static hda_nid_t alc660vd_dac_nids[3] = { 10015 /* front, rear, clfe, rear_surr */ 10016 0x02, 0x04, 0x03 10017}; 10018 10019static hda_nid_t alc861vd_adc_nids[1] = { 10020 /* ADC0 */ 10021 0x09, 10022}; 10023 10024/* input MUX */ 10025/* FIXME: should be a matrix-type input source selection */ 10026static struct hda_input_mux alc861vd_capture_source = { 10027 .num_items = 4, 10028 .items = { 10029 { "Mic", 0x0 }, 10030 { "Front Mic", 0x1 }, 10031 { "Line", 0x2 }, 10032 { "CD", 0x4 }, 10033 }, 10034}; 10035 10036static struct hda_input_mux alc861vd_dallas_capture_source = { 10037 .num_items = 3, 10038 .items = { 10039 { "Front Mic", 0x0 }, 10040 { "ATAPI Mic", 0x1 }, 10041 { "Line In", 0x5 }, 10042 }, 10043}; 10044 10045static struct hda_input_mux alc861vd_hp_capture_source = { 10046 .num_items = 2, 10047 .items = { 10048 { "Front Mic", 0x0 }, 10049 { "ATAPI Mic", 0x1 }, 10050 }, 10051}; 10052 10053#define alc861vd_mux_enum_info alc_mux_enum_info 10054#define alc861vd_mux_enum_get alc_mux_enum_get 10055 10056static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol, 10057 struct snd_ctl_elem_value *ucontrol) 10058{ 10059 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 10060 struct alc_spec *spec = codec->spec; 10061 const struct hda_input_mux *imux = spec->input_mux; 10062 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 10063 static hda_nid_t capture_mixers[1] = { 0x22 }; 10064 hda_nid_t nid = capture_mixers[adc_idx]; 10065 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 10066 unsigned int i, idx; 10067 10068 idx = ucontrol->value.enumerated.item[0]; 10069 if (idx >= imux->num_items) 10070 idx = imux->num_items - 1; 10071 if (*cur_val == idx) 10072 return 0; 10073 for (i = 0; i < imux->num_items; i++) { 10074 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; 10075 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 10076 imux->items[i].index, 10077 HDA_AMP_MUTE, v); 10078 } 10079 *cur_val = idx; 10080 return 1; 10081} 10082 10083/* 10084 * 2ch mode 10085 */ 10086static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = { 10087 { 2, NULL } 10088}; 10089 10090/* 10091 * 6ch mode 10092 */ 10093static struct hda_verb alc861vd_6stack_ch6_init[] = { 10094 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 10095 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10096 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10097 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10098 { } /* end */ 10099}; 10100 10101/* 10102 * 8ch mode 10103 */ 10104static struct hda_verb alc861vd_6stack_ch8_init[] = { 10105 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10106 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10107 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10108 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10109 { } /* end */ 10110}; 10111 10112static struct hda_channel_mode alc861vd_6stack_modes[2] = { 10113 { 6, alc861vd_6stack_ch6_init }, 10114 { 8, alc861vd_6stack_ch8_init }, 10115}; 10116 10117static struct snd_kcontrol_new alc861vd_chmode_mixer[] = { 10118 { 10119 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10120 .name = "Channel Mode", 10121 .info = alc_ch_mode_info, 10122 .get = alc_ch_mode_get, 10123 .put = alc_ch_mode_put, 10124 }, 10125 { } /* end */ 10126}; 10127 10128static struct snd_kcontrol_new alc861vd_capture_mixer[] = { 10129 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 10130 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 10131 10132 { 10133 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10134 /* The multiple "Capture Source" controls confuse alsamixer 10135 * So call somewhat different.. 10136 *FIXME: the controls appear in the "playback" view! 10137 */ 10138 /* .name = "Capture Source", */ 10139 .name = "Input Source", 10140 .count = 1, 10141 .info = alc861vd_mux_enum_info, 10142 .get = alc861vd_mux_enum_get, 10143 .put = alc861vd_mux_enum_put, 10144 }, 10145 { } /* end */ 10146}; 10147 10148/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 10149 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 10150 */ 10151static struct snd_kcontrol_new alc861vd_6st_mixer[] = { 10152 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10153 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 10154 10155 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), 10156 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 10157 10158 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, 10159 HDA_OUTPUT), 10160 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, 10161 HDA_OUTPUT), 10162 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 10163 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 10164 10165 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT), 10166 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 10167 10168 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10169 10170 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 10171 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10172 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10173 10174 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 10175 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10176 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10177 10178 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 10179 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 10180 10181 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 10182 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 10183 10184 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 10185 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 10186 10187 { } /* end */ 10188}; 10189 10190static struct snd_kcontrol_new alc861vd_3st_mixer[] = { 10191 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10192 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 10193 10194 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10195 10196 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 10197 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10198 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10199 10200 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 10201 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10202 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10203 10204 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 10205 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 10206 10207 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 10208 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 10209 10210 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 10211 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 10212 10213 { } /* end */ 10214}; 10215 10216static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = { 10217 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10218 /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/ 10219 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 10220 10221 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10222 10223 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 10224 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10225 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10226 10227 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 10228 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10229 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10230 10231 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 10232 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 10233 10234 { } /* end */ 10235}; 10236 10237/* Pin assignment: Front=0x14, HP = 0x15, 10238 * Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d 10239 */ 10240static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { 10241 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10242 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 10243 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 10244 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), 10245 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10246 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10247 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10248 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10249 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT), 10250 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT), 10251 { } /* end */ 10252}; 10253 10254/* Pin assignment: Speaker=0x14, Line-out = 0x15, 10255 * Front Mic=0x18, ATAPI Mic = 0x19, 10256 */ 10257static struct snd_kcontrol_new alc861vd_hp_mixer[] = { 10258 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10259 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 10260 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 10261 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), 10262 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10263 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10264 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10265 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10266 10267 { } /* end */ 10268}; 10269 10270/* 10271 * generic initialization of ADC, input mixers and output mixers 10272 */ 10273static struct hda_verb alc861vd_volume_init_verbs[] = { 10274 /* 10275 * Unmute ADC0 and set the default input to mic-in 10276 */ 10277 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 10278 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10279 10280 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of 10281 * the analog-loopback mixer widget 10282 */ 10283 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 10284 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10285 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10286 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 10287 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 10288 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 10289 10290 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ 10291 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10292 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10293 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 10294 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 10295 10296 /* 10297 * Set up output mixers (0x02 - 0x05) 10298 */ 10299 /* set vol=0 to output mixers */ 10300 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10301 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10302 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10303 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10304 10305 /* set up input amps for analog loopback */ 10306 /* Amp Indices: DAC = 0, mixer = 1 */ 10307 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10308 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10309 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10310 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10311 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10312 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10313 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10314 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10315 10316 { } 10317}; 10318 10319/* 10320 * 3-stack pin configuration: 10321 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b 10322 */ 10323static struct hda_verb alc861vd_3stack_init_verbs[] = { 10324 /* 10325 * Set pin mode and muting 10326 */ 10327 /* set front pin widgets 0x14 for output */ 10328 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10329 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10330 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 10331 10332 /* Mic (rear) pin: input vref at 80% */ 10333 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10334 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10335 /* Front Mic pin: input vref at 80% */ 10336 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10337 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10338 /* Line In pin: input */ 10339 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10340 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10341 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 10342 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 10343 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10344 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 10345 /* CD pin widget for input */ 10346 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10347 10348 { } 10349}; 10350 10351/* 10352 * 6-stack pin configuration: 10353 */ 10354static struct hda_verb alc861vd_6stack_init_verbs[] = { 10355 /* 10356 * Set pin mode and muting 10357 */ 10358 /* set front pin widgets 0x14 for output */ 10359 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10360 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10361 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 10362 10363 /* Rear Pin: output 1 (0x0d) */ 10364 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10365 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10366 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 10367 /* CLFE Pin: output 2 (0x0e) */ 10368 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10369 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10370 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, 10371 /* Side Pin: output 3 (0x0f) */ 10372 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10373 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10374 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, 10375 10376 /* Mic (rear) pin: input vref at 80% */ 10377 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10378 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10379 /* Front Mic pin: input vref at 80% */ 10380 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10381 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10382 /* Line In pin: input */ 10383 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10384 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10385 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 10386 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 10387 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10388 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 10389 /* CD pin widget for input */ 10390 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10391 10392 { } 10393}; 10394 10395static struct hda_verb alc861vd_eapd_verbs[] = { 10396 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, 10397 { } 10398}; 10399 10400static struct hda_verb alc861vd_lenovo_unsol_verbs[] = { 10401 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10402 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10403 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 10404 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 10405 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, 10406 {} 10407}; 10408 10409/* toggle speaker-output according to the hp-jack state */ 10410static void alc861vd_lenovo_hp_automute(struct hda_codec *codec) 10411{ 10412 unsigned int present; 10413 unsigned char bits; 10414 10415 present = snd_hda_codec_read(codec, 0x1b, 0, 10416 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 10417 bits = present ? HDA_AMP_MUTE : 0; 10418 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 10419 HDA_AMP_MUTE, bits); 10420} 10421 10422static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) 10423{ 10424 unsigned int present; 10425 unsigned char bits; 10426 10427 present = snd_hda_codec_read(codec, 0x18, 0, 10428 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 10429 bits = present ? HDA_AMP_MUTE : 0; 10430 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, 10431 HDA_AMP_MUTE, bits); 10432} 10433 10434static void alc861vd_lenovo_automute(struct hda_codec *codec) 10435{ 10436 alc861vd_lenovo_hp_automute(codec); 10437 alc861vd_lenovo_mic_automute(codec); 10438} 10439 10440static void alc861vd_lenovo_unsol_event(struct hda_codec *codec, 10441 unsigned int res) 10442{ 10443 switch (res >> 26) { 10444 case ALC880_HP_EVENT: 10445 alc861vd_lenovo_hp_automute(codec); 10446 break; 10447 case ALC880_MIC_EVENT: 10448 alc861vd_lenovo_mic_automute(codec); 10449 break; 10450 } 10451} 10452 10453static struct hda_verb alc861vd_dallas_verbs[] = { 10454 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10455 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10456 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10457 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10458 10459 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10460 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10461 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10462 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10463 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10464 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10465 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10466 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10467 10468 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10469 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10470 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10471 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10472 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10473 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10474 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10475 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10476 10477 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, 10478 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10479 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, 10480 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10481 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10482 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10483 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10484 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10485 10486 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10487 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 10488 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 10489 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 10490 10491 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10492 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 10493 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 10494 10495 { } /* end */ 10496}; 10497 10498/* toggle speaker-output according to the hp-jack state */ 10499static void alc861vd_dallas_automute(struct hda_codec *codec) 10500{ 10501 unsigned int present; 10502 10503 present = snd_hda_codec_read(codec, 0x15, 0, 10504 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 10505 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 10506 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 10507} 10508 10509static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res) 10510{ 10511 if ((res >> 26) == ALC880_HP_EVENT) 10512 alc861vd_dallas_automute(codec); 10513} 10514 10515#ifdef CONFIG_SND_HDA_POWER_SAVE 10516#define alc861vd_loopbacks alc880_loopbacks 10517#endif 10518 10519/* pcm configuration: identiacal with ALC880 */ 10520#define alc861vd_pcm_analog_playback alc880_pcm_analog_playback 10521#define alc861vd_pcm_analog_capture alc880_pcm_analog_capture 10522#define alc861vd_pcm_digital_playback alc880_pcm_digital_playback 10523#define alc861vd_pcm_digital_capture alc880_pcm_digital_capture 10524 10525/* 10526 * configuration and preset 10527 */ 10528static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { 10529 [ALC660VD_3ST] = "3stack-660", 10530 [ALC660VD_3ST_DIG] = "3stack-660-digout", 10531 [ALC861VD_3ST] = "3stack", 10532 [ALC861VD_3ST_DIG] = "3stack-digout", 10533 [ALC861VD_6ST_DIG] = "6stack-digout", 10534 [ALC861VD_LENOVO] = "lenovo", 10535 [ALC861VD_DALLAS] = "dallas", 10536 [ALC861VD_HP] = "hp", 10537 [ALC861VD_AUTO] = "auto", 10538}; 10539 10540static struct snd_pci_quirk alc861vd_cfg_tbl[] = { 10541 SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), 10542 SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), 10543 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG), 10544 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), 10545 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), 10546 10547 /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/ 10548 SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), 10549 SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), 10550 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), 10551 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), 10552 SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), 10553 SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG), 10554 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP), 10555 {} 10556}; 10557 10558static struct alc_config_preset alc861vd_presets[] = { 10559 [ALC660VD_3ST] = { 10560 .mixers = { alc861vd_3st_mixer }, 10561 .init_verbs = { alc861vd_volume_init_verbs, 10562 alc861vd_3stack_init_verbs }, 10563 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), 10564 .dac_nids = alc660vd_dac_nids, 10565 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10566 .adc_nids = alc861vd_adc_nids, 10567 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10568 .channel_mode = alc861vd_3stack_2ch_modes, 10569 .input_mux = &alc861vd_capture_source, 10570 }, 10571 [ALC660VD_3ST_DIG] = { 10572 .mixers = { alc861vd_3st_mixer }, 10573 .init_verbs = { alc861vd_volume_init_verbs, 10574 alc861vd_3stack_init_verbs }, 10575 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), 10576 .dac_nids = alc660vd_dac_nids, 10577 .dig_out_nid = ALC861VD_DIGOUT_NID, 10578 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10579 .adc_nids = alc861vd_adc_nids, 10580 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10581 .channel_mode = alc861vd_3stack_2ch_modes, 10582 .input_mux = &alc861vd_capture_source, 10583 }, 10584 [ALC861VD_3ST] = { 10585 .mixers = { alc861vd_3st_mixer }, 10586 .init_verbs = { alc861vd_volume_init_verbs, 10587 alc861vd_3stack_init_verbs }, 10588 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10589 .dac_nids = alc861vd_dac_nids, 10590 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10591 .channel_mode = alc861vd_3stack_2ch_modes, 10592 .input_mux = &alc861vd_capture_source, 10593 }, 10594 [ALC861VD_3ST_DIG] = { 10595 .mixers = { alc861vd_3st_mixer }, 10596 .init_verbs = { alc861vd_volume_init_verbs, 10597 alc861vd_3stack_init_verbs }, 10598 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10599 .dac_nids = alc861vd_dac_nids, 10600 .dig_out_nid = ALC861VD_DIGOUT_NID, 10601 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10602 .channel_mode = alc861vd_3stack_2ch_modes, 10603 .input_mux = &alc861vd_capture_source, 10604 }, 10605 [ALC861VD_6ST_DIG] = { 10606 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer }, 10607 .init_verbs = { alc861vd_volume_init_verbs, 10608 alc861vd_6stack_init_verbs }, 10609 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10610 .dac_nids = alc861vd_dac_nids, 10611 .dig_out_nid = ALC861VD_DIGOUT_NID, 10612 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes), 10613 .channel_mode = alc861vd_6stack_modes, 10614 .input_mux = &alc861vd_capture_source, 10615 }, 10616 [ALC861VD_LENOVO] = { 10617 .mixers = { alc861vd_lenovo_mixer }, 10618 .init_verbs = { alc861vd_volume_init_verbs, 10619 alc861vd_3stack_init_verbs, 10620 alc861vd_eapd_verbs, 10621 alc861vd_lenovo_unsol_verbs }, 10622 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), 10623 .dac_nids = alc660vd_dac_nids, 10624 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10625 .adc_nids = alc861vd_adc_nids, 10626 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10627 .channel_mode = alc861vd_3stack_2ch_modes, 10628 .input_mux = &alc861vd_capture_source, 10629 .unsol_event = alc861vd_lenovo_unsol_event, 10630 .init_hook = alc861vd_lenovo_automute, 10631 }, 10632 [ALC861VD_DALLAS] = { 10633 .mixers = { alc861vd_dallas_mixer }, 10634 .init_verbs = { alc861vd_dallas_verbs }, 10635 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10636 .dac_nids = alc861vd_dac_nids, 10637 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10638 .adc_nids = alc861vd_adc_nids, 10639 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10640 .channel_mode = alc861vd_3stack_2ch_modes, 10641 .input_mux = &alc861vd_dallas_capture_source, 10642 .unsol_event = alc861vd_dallas_unsol_event, 10643 .init_hook = alc861vd_dallas_automute, 10644 }, 10645 [ALC861VD_HP] = { 10646 .mixers = { alc861vd_hp_mixer }, 10647 .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs }, 10648 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10649 .dac_nids = alc861vd_dac_nids, 10650 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10651 .dig_out_nid = ALC861VD_DIGOUT_NID, 10652 .adc_nids = alc861vd_adc_nids, 10653 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10654 .channel_mode = alc861vd_3stack_2ch_modes, 10655 .input_mux = &alc861vd_hp_capture_source, 10656 .unsol_event = alc861vd_dallas_unsol_event, 10657 .init_hook = alc861vd_dallas_automute, 10658 }, 10659}; 10660 10661/* 10662 * BIOS auto configuration 10663 */ 10664static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec, 10665 hda_nid_t nid, int pin_type, int dac_idx) 10666{ 10667 /* set as output */ 10668 snd_hda_codec_write(codec, nid, 0, 10669 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); 10670 snd_hda_codec_write(codec, nid, 0, 10671 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 10672} 10673 10674static void alc861vd_auto_init_multi_out(struct hda_codec *codec) 10675{ 10676 struct alc_spec *spec = codec->spec; 10677 int i; 10678 10679 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 10680 for (i = 0; i <= HDA_SIDE; i++) { 10681 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 10682 int pin_type = get_pin_type(spec->autocfg.line_out_type); 10683 if (nid) 10684 alc861vd_auto_set_output_and_unmute(codec, nid, 10685 pin_type, i); 10686 } 10687} 10688 10689 10690static void alc861vd_auto_init_hp_out(struct hda_codec *codec) 10691{ 10692 struct alc_spec *spec = codec->spec; 10693 hda_nid_t pin; 10694 10695 pin = spec->autocfg.hp_pins[0]; 10696 if (pin) /* connect to front and use dac 0 */ 10697 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 10698} 10699 10700#define alc861vd_is_input_pin(nid) alc880_is_input_pin(nid) 10701#define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID 10702 10703static void alc861vd_auto_init_analog_input(struct hda_codec *codec) 10704{ 10705 struct alc_spec *spec = codec->spec; 10706 int i; 10707 10708 for (i = 0; i < AUTO_PIN_LAST; i++) { 10709 hda_nid_t nid = spec->autocfg.input_pins[i]; 10710 if (alc861vd_is_input_pin(nid)) { 10711 snd_hda_codec_write(codec, nid, 0, 10712 AC_VERB_SET_PIN_WIDGET_CONTROL, 10713 i <= AUTO_PIN_FRONT_MIC ? 10714 PIN_VREF80 : PIN_IN); 10715 if (nid != ALC861VD_PIN_CD_NID) 10716 snd_hda_codec_write(codec, nid, 0, 10717 AC_VERB_SET_AMP_GAIN_MUTE, 10718 AMP_OUT_MUTE); 10719 } 10720 } 10721} 10722 10723#define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02) 10724#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c) 10725 10726/* add playback controls from the parsed DAC table */ 10727/* Based on ALC880 version. But ALC861VD has separate, 10728 * different NIDs for mute/unmute switch and volume control */ 10729static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, 10730 const struct auto_pin_cfg *cfg) 10731{ 10732 char name[32]; 10733 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"}; 10734 hda_nid_t nid_v, nid_s; 10735 int i, err; 10736 10737 for (i = 0; i < cfg->line_outs; i++) { 10738 if (!spec->multiout.dac_nids[i]) 10739 continue; 10740 nid_v = alc861vd_idx_to_mixer_vol( 10741 alc880_dac_to_idx( 10742 spec->multiout.dac_nids[i])); 10743 nid_s = alc861vd_idx_to_mixer_switch( 10744 alc880_dac_to_idx( 10745 spec->multiout.dac_nids[i])); 10746 10747 if (i == 2) { 10748 /* Center/LFE */ 10749 err = add_control(spec, ALC_CTL_WIDGET_VOL, 10750 "Center Playback Volume", 10751 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0, 10752 HDA_OUTPUT)); 10753 if (err < 0) 10754 return err; 10755 err = add_control(spec, ALC_CTL_WIDGET_VOL, 10756 "LFE Playback Volume", 10757 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0, 10758 HDA_OUTPUT)); 10759 if (err < 0) 10760 return err; 10761 err = add_control(spec, ALC_CTL_BIND_MUTE, 10762 "Center Playback Switch", 10763 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2, 10764 HDA_INPUT)); 10765 if (err < 0) 10766 return err; 10767 err = add_control(spec, ALC_CTL_BIND_MUTE, 10768 "LFE Playback Switch", 10769 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2, 10770 HDA_INPUT)); 10771 if (err < 0) 10772 return err; 10773 } else { 10774 sprintf(name, "%s Playback Volume", chname[i]); 10775 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 10776 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, 10777 HDA_OUTPUT)); 10778 if (err < 0) 10779 return err; 10780 sprintf(name, "%s Playback Switch", chname[i]); 10781 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 10782 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, 10783 HDA_INPUT)); 10784 if (err < 0) 10785 return err; 10786 } 10787 } 10788 return 0; 10789} 10790 10791/* add playback controls for speaker and HP outputs */ 10792/* Based on ALC880 version. But ALC861VD has separate, 10793 * different NIDs for mute/unmute switch and volume control */ 10794static int alc861vd_auto_create_extra_out(struct alc_spec *spec, 10795 hda_nid_t pin, const char *pfx) 10796{ 10797 hda_nid_t nid_v, nid_s; 10798 int err; 10799 char name[32]; 10800 10801 if (!pin) 10802 return 0; 10803 10804 if (alc880_is_fixed_pin(pin)) { 10805 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 10806 /* specify the DAC as the extra output */ 10807 if (!spec->multiout.hp_nid) 10808 spec->multiout.hp_nid = nid_v; 10809 else 10810 spec->multiout.extra_out_nid[0] = nid_v; 10811 /* control HP volume/switch on the output mixer amp */ 10812 nid_v = alc861vd_idx_to_mixer_vol( 10813 alc880_fixed_pin_idx(pin)); 10814 nid_s = alc861vd_idx_to_mixer_switch( 10815 alc880_fixed_pin_idx(pin)); 10816 10817 sprintf(name, "%s Playback Volume", pfx); 10818 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 10819 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT)); 10820 if (err < 0) 10821 return err; 10822 sprintf(name, "%s Playback Switch", pfx); 10823 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 10824 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT)); 10825 if (err < 0) 10826 return err; 10827 } else if (alc880_is_multi_pin(pin)) { 10828 /* set manual connection */ 10829 /* we have only a switch on HP-out PIN */ 10830 sprintf(name, "%s Playback Switch", pfx); 10831 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 10832 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 10833 if (err < 0) 10834 return err; 10835 } 10836 return 0; 10837} 10838 10839/* parse the BIOS configuration and set up the alc_spec 10840 * return 1 if successful, 0 if the proper config is not found, 10841 * or a negative error code 10842 * Based on ALC880 version - had to change it to override 10843 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */ 10844static int alc861vd_parse_auto_config(struct hda_codec *codec) 10845{ 10846 struct alc_spec *spec = codec->spec; 10847 int err; 10848 static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; 10849 10850 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 10851 alc861vd_ignore); 10852 if (err < 0) 10853 return err; 10854 if (!spec->autocfg.line_outs) 10855 return 0; /* can't find valid BIOS pin config */ 10856 10857 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 10858 if (err < 0) 10859 return err; 10860 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg); 10861 if (err < 0) 10862 return err; 10863 err = alc861vd_auto_create_extra_out(spec, 10864 spec->autocfg.speaker_pins[0], 10865 "Speaker"); 10866 if (err < 0) 10867 return err; 10868 err = alc861vd_auto_create_extra_out(spec, 10869 spec->autocfg.hp_pins[0], 10870 "Headphone"); 10871 if (err < 0) 10872 return err; 10873 err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg); 10874 if (err < 0) 10875 return err; 10876 10877 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 10878 10879 if (spec->autocfg.dig_out_pin) 10880 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; 10881 10882 if (spec->kctl_alloc) 10883 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 10884 10885 spec->init_verbs[spec->num_init_verbs++] 10886 = alc861vd_volume_init_verbs; 10887 10888 spec->num_mux_defs = 1; 10889 spec->input_mux = &spec->private_imux; 10890 10891 return 1; 10892} 10893 10894/* additional initialization for auto-configuration model */ 10895static void alc861vd_auto_init(struct hda_codec *codec) 10896{ 10897 alc861vd_auto_init_multi_out(codec); 10898 alc861vd_auto_init_hp_out(codec); 10899 alc861vd_auto_init_analog_input(codec); 10900} 10901 10902static int patch_alc861vd(struct hda_codec *codec) 10903{ 10904 struct alc_spec *spec; 10905 int err, board_config; 10906 10907 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 10908 if (spec == NULL) 10909 return -ENOMEM; 10910 10911 codec->spec = spec; 10912 10913 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST, 10914 alc861vd_models, 10915 alc861vd_cfg_tbl); 10916 10917 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) { 10918 printk(KERN_INFO "hda_codec: Unknown model for ALC660VD/" 10919 "ALC861VD, trying auto-probe from BIOS...\n"); 10920 board_config = ALC861VD_AUTO; 10921 } 10922 10923 if (board_config == ALC861VD_AUTO) { 10924 /* automatic parse from the BIOS config */ 10925 err = alc861vd_parse_auto_config(codec); 10926 if (err < 0) { 10927 alc_free(codec); 10928 return err; 10929 } else if (!err) { 10930 printk(KERN_INFO 10931 "hda_codec: Cannot set up configuration " 10932 "from BIOS. Using base mode...\n"); 10933 board_config = ALC861VD_3ST; 10934 } 10935 } 10936 10937 if (board_config != ALC861VD_AUTO) 10938 setup_preset(spec, &alc861vd_presets[board_config]); 10939 10940 spec->stream_name_analog = "ALC861VD Analog"; 10941 spec->stream_analog_playback = &alc861vd_pcm_analog_playback; 10942 spec->stream_analog_capture = &alc861vd_pcm_analog_capture; 10943 10944 spec->stream_name_digital = "ALC861VD Digital"; 10945 spec->stream_digital_playback = &alc861vd_pcm_digital_playback; 10946 spec->stream_digital_capture = &alc861vd_pcm_digital_capture; 10947 10948 spec->adc_nids = alc861vd_adc_nids; 10949 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); 10950 10951 spec->mixers[spec->num_mixers] = alc861vd_capture_mixer; 10952 spec->num_mixers++; 10953 10954 codec->patch_ops = alc_patch_ops; 10955 10956 if (board_config == ALC861VD_AUTO) 10957 spec->init_hook = alc861vd_auto_init; 10958#ifdef CONFIG_SND_HDA_POWER_SAVE 10959 if (!spec->loopback.amplist) 10960 spec->loopback.amplist = alc861vd_loopbacks; 10961#endif 10962 10963 return 0; 10964} 10965 10966/* 10967 * ALC662 support 10968 * 10969 * ALC662 is almost identical with ALC880 but has cleaner and more flexible 10970 * configuration. Each pin widget can choose any input DACs and a mixer. 10971 * Each ADC is connected from a mixer of all inputs. This makes possible 10972 * 6-channel independent captures. 10973 * 10974 * In addition, an independent DAC for the multi-playback (not used in this 10975 * driver yet). 10976 */ 10977#define ALC662_DIGOUT_NID 0x06 10978#define ALC662_DIGIN_NID 0x0a 10979 10980static hda_nid_t alc662_dac_nids[4] = { 10981 /* front, rear, clfe, rear_surr */ 10982 0x02, 0x03, 0x04 10983}; 10984 10985static hda_nid_t alc662_adc_nids[1] = { 10986 /* ADC1-2 */ 10987 0x09, 10988}; 10989/* input MUX */ 10990/* FIXME: should be a matrix-type input source selection */ 10991 10992static struct hda_input_mux alc662_capture_source = { 10993 .num_items = 4, 10994 .items = { 10995 { "Mic", 0x0 }, 10996 { "Front Mic", 0x1 }, 10997 { "Line", 0x2 }, 10998 { "CD", 0x4 }, 10999 }, 11000}; 11001 11002static struct hda_input_mux alc662_lenovo_101e_capture_source = { 11003 .num_items = 2, 11004 .items = { 11005 { "Mic", 0x1 }, 11006 { "Line", 0x2 }, 11007 }, 11008}; 11009#define alc662_mux_enum_info alc_mux_enum_info 11010#define alc662_mux_enum_get alc_mux_enum_get 11011 11012static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol, 11013 struct snd_ctl_elem_value *ucontrol) 11014{ 11015 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 11016 struct alc_spec *spec = codec->spec; 11017 const struct hda_input_mux *imux = spec->input_mux; 11018 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 11019 static hda_nid_t capture_mixers[2] = { 0x23, 0x22 }; 11020 hda_nid_t nid = capture_mixers[adc_idx]; 11021 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 11022 unsigned int i, idx; 11023 11024 idx = ucontrol->value.enumerated.item[0]; 11025 if (idx >= imux->num_items) 11026 idx = imux->num_items - 1; 11027 if (*cur_val == idx) 11028 return 0; 11029 for (i = 0; i < imux->num_items; i++) { 11030 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; 11031 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 11032 imux->items[i].index, 11033 HDA_AMP_MUTE, v); 11034 } 11035 *cur_val = idx; 11036 return 1; 11037} 11038/* 11039 * 2ch mode 11040 */ 11041static struct hda_channel_mode alc662_3ST_2ch_modes[1] = { 11042 { 2, NULL } 11043}; 11044 11045/* 11046 * 2ch mode 11047 */ 11048static struct hda_verb alc662_3ST_ch2_init[] = { 11049 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 11050 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 11051 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 11052 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 11053 { } /* end */ 11054}; 11055 11056/* 11057 * 6ch mode 11058 */ 11059static struct hda_verb alc662_3ST_ch6_init[] = { 11060 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 11061 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 11062 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, 11063 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 11064 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 11065 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, 11066 { } /* end */ 11067}; 11068 11069static struct hda_channel_mode alc662_3ST_6ch_modes[2] = { 11070 { 2, alc662_3ST_ch2_init }, 11071 { 6, alc662_3ST_ch6_init }, 11072}; 11073 11074/* 11075 * 2ch mode 11076 */ 11077static struct hda_verb alc662_sixstack_ch6_init[] = { 11078 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 11079 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 11080 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 11081 { } /* end */ 11082}; 11083 11084/* 11085 * 6ch mode 11086 */ 11087static struct hda_verb alc662_sixstack_ch8_init[] = { 11088 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 11089 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 11090 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 11091 { } /* end */ 11092}; 11093 11094static struct hda_channel_mode alc662_5stack_modes[2] = { 11095 { 2, alc662_sixstack_ch6_init }, 11096 { 6, alc662_sixstack_ch8_init }, 11097}; 11098 11099/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 11100 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 11101 */ 11102 11103static struct snd_kcontrol_new alc662_base_mixer[] = { 11104 /* output mixer control */ 11105 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), 11106 HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT), 11107 HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT), 11108 HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT), 11109 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), 11110 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), 11111 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), 11112 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), 11113 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 11114 11115 /*Input mixer control */ 11116 HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT), 11117 HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT), 11118 HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT), 11119 HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT), 11120 HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT), 11121 HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT), 11122 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT), 11123 HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT), 11124 11125 /* Capture mixer control */ 11126 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 11127 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 11128 { 11129 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 11130 .name = "Capture Source", 11131 .count = 1, 11132 .info = alc_mux_enum_info, 11133 .get = alc_mux_enum_get, 11134 .put = alc_mux_enum_put, 11135 }, 11136 { } /* end */ 11137}; 11138 11139static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = { 11140 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 11141 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), 11142 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 11143 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 11144 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 11145 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 11146 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 11147 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 11148 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 11149 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 11150 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 11151 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 11152 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 11153 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 11154 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 11155 { 11156 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 11157 /* .name = "Capture Source", */ 11158 .name = "Input Source", 11159 .count = 1, 11160 .info = alc662_mux_enum_info, 11161 .get = alc662_mux_enum_get, 11162 .put = alc662_mux_enum_put, 11163 }, 11164 { } /* end */ 11165}; 11166 11167static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = { 11168 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 11169 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), 11170 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), 11171 HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT), 11172 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), 11173 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), 11174 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), 11175 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), 11176 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 11177 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 11178 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 11179 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 11180 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 11181 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 11182 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 11183 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 11184 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 11185 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 11186 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 11187 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 11188 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 11189 { 11190 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 11191 /* .name = "Capture Source", */ 11192 .name = "Input Source", 11193 .count = 1, 11194 .info = alc662_mux_enum_info, 11195 .get = alc662_mux_enum_get, 11196 .put = alc662_mux_enum_put, 11197 }, 11198 { } /* end */ 11199}; 11200 11201static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = { 11202 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 11203 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), 11204 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x03, 0x0, HDA_OUTPUT), 11205 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x03, 2, HDA_INPUT), 11206 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 11207 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 11208 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 11209 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 11210 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 11211 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 11212 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 11213 { 11214 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 11215 /* .name = "Capture Source", */ 11216 .name = "Input Source", 11217 .count = 1, 11218 .info = alc662_mux_enum_info, 11219 .get = alc662_mux_enum_get, 11220 .put = alc662_mux_enum_put, 11221 }, 11222 { } /* end */ 11223}; 11224 11225static struct snd_kcontrol_new alc662_chmode_mixer[] = { 11226 { 11227 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 11228 .name = "Channel Mode", 11229 .info = alc_ch_mode_info, 11230 .get = alc_ch_mode_get, 11231 .put = alc_ch_mode_put, 11232 }, 11233 { } /* end */ 11234}; 11235 11236static struct hda_verb alc662_init_verbs[] = { 11237 /* ADC: mute amp left and right */ 11238 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 11239 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 11240 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 11241 11242 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 11243 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 11244 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 11245 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 11246 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 11247 11248 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11249 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11250 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11251 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11252 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11253 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11254 11255 /* Front Pin: output 0 (0x0c) */ 11256 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 11257 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 11258 11259 /* Rear Pin: output 1 (0x0d) */ 11260 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 11261 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 11262 11263 /* CLFE Pin: output 2 (0x0e) */ 11264 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 11265 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 11266 11267 /* Mic (rear) pin: input vref at 80% */ 11268 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 11269 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 11270 /* Front Mic pin: input vref at 80% */ 11271 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 11272 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 11273 /* Line In pin: input */ 11274 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 11275 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 11276 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 11277 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 11278 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 11279 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 11280 /* CD pin widget for input */ 11281 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 11282 11283 /* FIXME: use matrix-type input source selection */ 11284 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 11285 /* Input mixer */ 11286 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11287 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11288 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 11289 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 11290 { } 11291}; 11292 11293static struct hda_verb alc662_sue_init_verbs[] = { 11294 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, 11295 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, 11296 {} 11297}; 11298 11299/* 11300 * generic initialization of ADC, input mixers and output mixers 11301 */ 11302static struct hda_verb alc662_auto_init_verbs[] = { 11303 /* 11304 * Unmute ADC and set the default input to mic-in 11305 */ 11306 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 11307 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11308 11309 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 11310 * mixer widget 11311 * Note: PASD motherboards uses the Line In 2 as the input for front 11312 * panel mic (mic 2) 11313 */ 11314 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 11315 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 11316 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 11317 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 11318 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 11319 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 11320 11321 /* 11322 * Set up output mixers (0x0c - 0x0f) 11323 */ 11324 /* set vol=0 to output mixers */ 11325 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 11326 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 11327 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 11328 11329 /* set up input amps for analog loopback */ 11330 /* Amp Indices: DAC = 0, mixer = 1 */ 11331 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11332 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11333 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11334 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11335 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11336 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11337 11338 11339 /* FIXME: use matrix-type input source selection */ 11340 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 11341 /* Input mixer */ 11342 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11343 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11344 { } 11345}; 11346 11347/* capture mixer elements */ 11348static struct snd_kcontrol_new alc662_capture_mixer[] = { 11349 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 11350 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 11351 { 11352 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 11353 /* The multiple "Capture Source" controls confuse alsamixer 11354 * So call somewhat different.. 11355 * FIXME: the controls appear in the "playback" view! 11356 */ 11357 /* .name = "Capture Source", */ 11358 .name = "Input Source", 11359 .count = 1, 11360 .info = alc882_mux_enum_info, 11361 .get = alc882_mux_enum_get, 11362 .put = alc882_mux_enum_put, 11363 }, 11364 { } /* end */ 11365}; 11366 11367static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec) 11368{ 11369 unsigned int present; 11370 unsigned char bits; 11371 11372 present = snd_hda_codec_read(codec, 0x14, 0, 11373 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 11374 bits = present ? HDA_AMP_MUTE : 0; 11375 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 11376 HDA_AMP_MUTE, bits); 11377} 11378 11379static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) 11380{ 11381 unsigned int present; 11382 unsigned char bits; 11383 11384 present = snd_hda_codec_read(codec, 0x1b, 0, 11385 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 11386 bits = present ? HDA_AMP_MUTE : 0; 11387 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 11388 HDA_AMP_MUTE, bits); 11389 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 11390 HDA_AMP_MUTE, bits); 11391} 11392 11393static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, 11394 unsigned int res) 11395{ 11396 if ((res >> 26) == ALC880_HP_EVENT) 11397 alc662_lenovo_101e_all_automute(codec); 11398 if ((res >> 26) == ALC880_FRONT_EVENT) 11399 alc662_lenovo_101e_ispeaker_automute(codec); 11400} 11401 11402#ifdef CONFIG_SND_HDA_POWER_SAVE 11403#define alc662_loopbacks alc880_loopbacks 11404#endif 11405 11406 11407/* pcm configuration: identiacal with ALC880 */ 11408#define alc662_pcm_analog_playback alc880_pcm_analog_playback 11409#define alc662_pcm_analog_capture alc880_pcm_analog_capture 11410#define alc662_pcm_digital_playback alc880_pcm_digital_playback 11411#define alc662_pcm_digital_capture alc880_pcm_digital_capture 11412 11413/* 11414 * configuration and preset 11415 */ 11416static const char *alc662_models[ALC662_MODEL_LAST] = { 11417 [ALC662_3ST_2ch_DIG] = "3stack-dig", 11418 [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig", 11419 [ALC662_3ST_6ch] = "3stack-6ch", 11420 [ALC662_5ST_DIG] = "6stack-dig", 11421 [ALC662_LENOVO_101E] = "lenovo-101e", 11422 [ALC662_AUTO] = "auto", 11423}; 11424 11425static struct snd_pci_quirk alc662_cfg_tbl[] = { 11426 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), 11427 {} 11428}; 11429 11430static struct alc_config_preset alc662_presets[] = { 11431 [ALC662_3ST_2ch_DIG] = { 11432 .mixers = { alc662_3ST_2ch_mixer }, 11433 .init_verbs = { alc662_init_verbs }, 11434 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11435 .dac_nids = alc662_dac_nids, 11436 .dig_out_nid = ALC662_DIGOUT_NID, 11437 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11438 .adc_nids = alc662_adc_nids, 11439 .dig_in_nid = ALC662_DIGIN_NID, 11440 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), 11441 .channel_mode = alc662_3ST_2ch_modes, 11442 .input_mux = &alc662_capture_source, 11443 }, 11444 [ALC662_3ST_6ch_DIG] = { 11445 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, 11446 .init_verbs = { alc662_init_verbs }, 11447 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11448 .dac_nids = alc662_dac_nids, 11449 .dig_out_nid = ALC662_DIGOUT_NID, 11450 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11451 .adc_nids = alc662_adc_nids, 11452 .dig_in_nid = ALC662_DIGIN_NID, 11453 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), 11454 .channel_mode = alc662_3ST_6ch_modes, 11455 .need_dac_fix = 1, 11456 .input_mux = &alc662_capture_source, 11457 }, 11458 [ALC662_3ST_6ch] = { 11459 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, 11460 .init_verbs = { alc662_init_verbs }, 11461 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11462 .dac_nids = alc662_dac_nids, 11463 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11464 .adc_nids = alc662_adc_nids, 11465 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), 11466 .channel_mode = alc662_3ST_6ch_modes, 11467 .need_dac_fix = 1, 11468 .input_mux = &alc662_capture_source, 11469 }, 11470 [ALC662_5ST_DIG] = { 11471 .mixers = { alc662_base_mixer, alc662_chmode_mixer }, 11472 .init_verbs = { alc662_init_verbs }, 11473 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11474 .dac_nids = alc662_dac_nids, 11475 .dig_out_nid = ALC662_DIGOUT_NID, 11476 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11477 .adc_nids = alc662_adc_nids, 11478 .dig_in_nid = ALC662_DIGIN_NID, 11479 .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes), 11480 .channel_mode = alc662_5stack_modes, 11481 .input_mux = &alc662_capture_source, 11482 }, 11483 [ALC662_LENOVO_101E] = { 11484 .mixers = { alc662_lenovo_101e_mixer }, 11485 .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, 11486 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11487 .dac_nids = alc662_dac_nids, 11488 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11489 .adc_nids = alc662_adc_nids, 11490 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), 11491 .channel_mode = alc662_3ST_2ch_modes, 11492 .input_mux = &alc662_lenovo_101e_capture_source, 11493 .unsol_event = alc662_lenovo_101e_unsol_event, 11494 .init_hook = alc662_lenovo_101e_all_automute, 11495 }, 11496 11497}; 11498 11499 11500/* 11501 * BIOS auto configuration 11502 */ 11503 11504/* add playback controls from the parsed DAC table */ 11505static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, 11506 const struct auto_pin_cfg *cfg) 11507{ 11508 char name[32]; 11509 static const char *chname[4] = { 11510 "Front", "Surround", NULL /*CLFE*/, "Side" 11511 }; 11512 hda_nid_t nid; 11513 int i, err; 11514 11515 for (i = 0; i < cfg->line_outs; i++) { 11516 if (!spec->multiout.dac_nids[i]) 11517 continue; 11518 nid = alc880_idx_to_mixer(i); 11519 if (i == 2) { 11520 /* Center/LFE */ 11521 err = add_control(spec, ALC_CTL_WIDGET_VOL, 11522 "Center Playback Volume", 11523 HDA_COMPOSE_AMP_VAL(nid, 1, 0, 11524 HDA_OUTPUT)); 11525 if (err < 0) 11526 return err; 11527 err = add_control(spec, ALC_CTL_WIDGET_VOL, 11528 "LFE Playback Volume", 11529 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 11530 HDA_OUTPUT)); 11531 if (err < 0) 11532 return err; 11533 err = add_control(spec, ALC_CTL_BIND_MUTE, 11534 "Center Playback Switch", 11535 HDA_COMPOSE_AMP_VAL(nid, 1, 2, 11536 HDA_INPUT)); 11537 if (err < 0) 11538 return err; 11539 err = add_control(spec, ALC_CTL_BIND_MUTE, 11540 "LFE Playback Switch", 11541 HDA_COMPOSE_AMP_VAL(nid, 2, 2, 11542 HDA_INPUT)); 11543 if (err < 0) 11544 return err; 11545 } else { 11546 sprintf(name, "%s Playback Volume", chname[i]); 11547 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 11548 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 11549 HDA_OUTPUT)); 11550 if (err < 0) 11551 return err; 11552 sprintf(name, "%s Playback Switch", chname[i]); 11553 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 11554 HDA_COMPOSE_AMP_VAL(nid, 3, 2, 11555 HDA_INPUT)); 11556 if (err < 0) 11557 return err; 11558 } 11559 } 11560 return 0; 11561} 11562 11563/* add playback controls for speaker and HP outputs */ 11564static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, 11565 const char *pfx) 11566{ 11567 hda_nid_t nid; 11568 int err; 11569 char name[32]; 11570 11571 if (!pin) 11572 return 0; 11573 11574 if (alc880_is_fixed_pin(pin)) { 11575 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 11576 /* printk("DAC nid=%x\n",nid); */ 11577 /* specify the DAC as the extra output */ 11578 if (!spec->multiout.hp_nid) 11579 spec->multiout.hp_nid = nid; 11580 else 11581 spec->multiout.extra_out_nid[0] = nid; 11582 /* control HP volume/switch on the output mixer amp */ 11583 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 11584 sprintf(name, "%s Playback Volume", pfx); 11585 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 11586 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 11587 if (err < 0) 11588 return err; 11589 sprintf(name, "%s Playback Switch", pfx); 11590 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 11591 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); 11592 if (err < 0) 11593 return err; 11594 } else if (alc880_is_multi_pin(pin)) { 11595 /* set manual connection */ 11596 /* we have only a switch on HP-out PIN */ 11597 sprintf(name, "%s Playback Switch", pfx); 11598 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 11599 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 11600 if (err < 0) 11601 return err; 11602 } 11603 return 0; 11604} 11605 11606/* create playback/capture controls for input pins */ 11607static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec, 11608 const struct auto_pin_cfg *cfg) 11609{ 11610 struct hda_input_mux *imux = &spec->private_imux; 11611 int i, err, idx; 11612 11613 for (i = 0; i < AUTO_PIN_LAST; i++) { 11614 if (alc880_is_input_pin(cfg->input_pins[i])) { 11615 idx = alc880_input_pin_idx(cfg->input_pins[i]); 11616 err = new_analog_input(spec, cfg->input_pins[i], 11617 auto_pin_cfg_labels[i], 11618 idx, 0x0b); 11619 if (err < 0) 11620 return err; 11621 imux->items[imux->num_items].label = 11622 auto_pin_cfg_labels[i]; 11623 imux->items[imux->num_items].index = 11624 alc880_input_pin_idx(cfg->input_pins[i]); 11625 imux->num_items++; 11626 } 11627 } 11628 return 0; 11629} 11630 11631static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, 11632 hda_nid_t nid, int pin_type, 11633 int dac_idx) 11634{ 11635 /* set as output */ 11636 snd_hda_codec_write(codec, nid, 0, 11637 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); 11638 snd_hda_codec_write(codec, nid, 0, 11639 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 11640 /* need the manual connection? */ 11641 if (alc880_is_multi_pin(nid)) { 11642 struct alc_spec *spec = codec->spec; 11643 int idx = alc880_multi_pin_idx(nid); 11644 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, 11645 AC_VERB_SET_CONNECT_SEL, 11646 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); 11647 } 11648} 11649 11650static void alc662_auto_init_multi_out(struct hda_codec *codec) 11651{ 11652 struct alc_spec *spec = codec->spec; 11653 int i; 11654 11655 for (i = 0; i <= HDA_SIDE; i++) { 11656 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 11657 int pin_type = get_pin_type(spec->autocfg.line_out_type); 11658 if (nid) 11659 alc662_auto_set_output_and_unmute(codec, nid, pin_type, 11660 i); 11661 } 11662} 11663 11664static void alc662_auto_init_hp_out(struct hda_codec *codec) 11665{ 11666 struct alc_spec *spec = codec->spec; 11667 hda_nid_t pin; 11668 11669 pin = spec->autocfg.hp_pins[0]; 11670 if (pin) /* connect to front */ 11671 /* use dac 0 */ 11672 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 11673} 11674 11675#define alc662_is_input_pin(nid) alc880_is_input_pin(nid) 11676#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID 11677 11678static void alc662_auto_init_analog_input(struct hda_codec *codec) 11679{ 11680 struct alc_spec *spec = codec->spec; 11681 int i; 11682 11683 for (i = 0; i < AUTO_PIN_LAST; i++) { 11684 hda_nid_t nid = spec->autocfg.input_pins[i]; 11685 if (alc662_is_input_pin(nid)) { 11686 snd_hda_codec_write(codec, nid, 0, 11687 AC_VERB_SET_PIN_WIDGET_CONTROL, 11688 (i <= AUTO_PIN_FRONT_MIC ? 11689 PIN_VREF80 : PIN_IN)); 11690 if (nid != ALC662_PIN_CD_NID) 11691 snd_hda_codec_write(codec, nid, 0, 11692 AC_VERB_SET_AMP_GAIN_MUTE, 11693 AMP_OUT_MUTE); 11694 } 11695 } 11696} 11697 11698static int alc662_parse_auto_config(struct hda_codec *codec) 11699{ 11700 struct alc_spec *spec = codec->spec; 11701 int err; 11702 static hda_nid_t alc662_ignore[] = { 0x1d, 0 }; 11703 11704 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 11705 alc662_ignore); 11706 if (err < 0) 11707 return err; 11708 if (!spec->autocfg.line_outs) 11709 return 0; /* can't find valid BIOS pin config */ 11710 11711 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 11712 if (err < 0) 11713 return err; 11714 err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); 11715 if (err < 0) 11716 return err; 11717 err = alc662_auto_create_extra_out(spec, 11718 spec->autocfg.speaker_pins[0], 11719 "Speaker"); 11720 if (err < 0) 11721 return err; 11722 err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], 11723 "Headphone"); 11724 if (err < 0) 11725 return err; 11726 err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg); 11727 if (err < 0) 11728 return err; 11729 11730 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 11731 11732 if (spec->autocfg.dig_out_pin) 11733 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; 11734 11735 if (spec->kctl_alloc) 11736 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 11737 11738 spec->num_mux_defs = 1; 11739 spec->input_mux = &spec->private_imux; 11740 11741 spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs; 11742 spec->mixers[spec->num_mixers] = alc662_capture_mixer; 11743 spec->num_mixers++; 11744 return 1; 11745} 11746 11747/* additional initialization for auto-configuration model */ 11748static void alc662_auto_init(struct hda_codec *codec) 11749{ 11750 alc662_auto_init_multi_out(codec); 11751 alc662_auto_init_hp_out(codec); 11752 alc662_auto_init_analog_input(codec); 11753} 11754 11755static int patch_alc662(struct hda_codec *codec) 11756{ 11757 struct alc_spec *spec; 11758 int err, board_config; 11759 11760 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 11761 if (!spec) 11762 return -ENOMEM; 11763 11764 codec->spec = spec; 11765 11766 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, 11767 alc662_models, 11768 alc662_cfg_tbl); 11769 if (board_config < 0) { 11770 printk(KERN_INFO "hda_codec: Unknown model for ALC662, " 11771 "trying auto-probe from BIOS...\n"); 11772 board_config = ALC662_AUTO; 11773 } 11774 11775 if (board_config == ALC662_AUTO) { 11776 /* automatic parse from the BIOS config */ 11777 err = alc662_parse_auto_config(codec); 11778 if (err < 0) { 11779 alc_free(codec); 11780 return err; 11781 } else if (!err) { 11782 printk(KERN_INFO 11783 "hda_codec: Cannot set up configuration " 11784 "from BIOS. Using base mode...\n"); 11785 board_config = ALC662_3ST_2ch_DIG; 11786 } 11787 } 11788 11789 if (board_config != ALC662_AUTO) 11790 setup_preset(spec, &alc662_presets[board_config]); 11791 11792 spec->stream_name_analog = "ALC662 Analog"; 11793 spec->stream_analog_playback = &alc662_pcm_analog_playback; 11794 spec->stream_analog_capture = &alc662_pcm_analog_capture; 11795 11796 spec->stream_name_digital = "ALC662 Digital"; 11797 spec->stream_digital_playback = &alc662_pcm_digital_playback; 11798 spec->stream_digital_capture = &alc662_pcm_digital_capture; 11799 11800 if (!spec->adc_nids && spec->input_mux) { 11801 spec->adc_nids = alc662_adc_nids; 11802 spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); 11803 } 11804 11805 codec->patch_ops = alc_patch_ops; 11806 if (board_config == ALC662_AUTO) 11807 spec->init_hook = alc662_auto_init; 11808#ifdef CONFIG_SND_HDA_POWER_SAVE 11809 if (!spec->loopback.amplist) 11810 spec->loopback.amplist = alc662_loopbacks; 11811#endif 11812 11813 return 0; 11814} 11815 11816/* 11817 * patch entries 11818 */ 11819struct hda_codec_preset snd_hda_preset_realtek[] = { 11820 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, 11821 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, 11822 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 }, 11823 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", 11824 .patch = patch_alc861 }, 11825 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, 11826 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, 11827 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd }, 11828 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2", 11829 .patch = patch_alc883 }, 11830 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", 11831 .patch = patch_alc662 }, 11832 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, 11833 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, 11834 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, 11835 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, 11836 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, 11837 {} /* terminator */ 11838}; 11839