patch_realtek.c revision 625dc0bf4d91d379e8b4d5c3c9e05ad6fa978c51
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_AUTO, 106 ALC268_MODEL_LAST /* last tag */ 107}; 108 109/* ALC861 models */ 110enum { 111 ALC861_3ST, 112 ALC660_3ST, 113 ALC861_3ST_DIG, 114 ALC861_6ST_DIG, 115 ALC861_UNIWILL_M31, 116 ALC861_TOSHIBA, 117 ALC861_ASUS, 118 ALC861_ASUS_LAPTOP, 119 ALC861_AUTO, 120 ALC861_MODEL_LAST, 121}; 122 123/* ALC861-VD models */ 124enum { 125 ALC660VD_3ST, 126 ALC660VD_3ST_DIG, 127 ALC861VD_3ST, 128 ALC861VD_3ST_DIG, 129 ALC861VD_6ST_DIG, 130 ALC861VD_LENOVO, 131 ALC861VD_DALLAS, 132 ALC861VD_AUTO, 133 ALC861VD_MODEL_LAST, 134}; 135 136/* ALC662 models */ 137enum { 138 ALC662_3ST_2ch_DIG, 139 ALC662_3ST_6ch_DIG, 140 ALC662_3ST_6ch, 141 ALC662_5ST_DIG, 142 ALC662_LENOVO_101E, 143 ALC662_AUTO, 144 ALC662_MODEL_LAST, 145}; 146 147/* ALC882 models */ 148enum { 149 ALC882_3ST_DIG, 150 ALC882_6ST_DIG, 151 ALC882_ARIMA, 152 ALC882_W2JC, 153 ALC882_TARGA, 154 ALC882_ASUS_A7J, 155 ALC885_MACPRO, 156 ALC885_IMAC24, 157 ALC882_AUTO, 158 ALC882_MODEL_LAST, 159}; 160 161/* ALC883 models */ 162enum { 163 ALC883_3ST_2ch_DIG, 164 ALC883_3ST_6ch_DIG, 165 ALC883_3ST_6ch, 166 ALC883_6ST_DIG, 167 ALC883_TARGA_DIG, 168 ALC883_TARGA_2ch_DIG, 169 ALC883_ACER, 170 ALC883_MEDION, 171 ALC883_MEDION_MD2, 172 ALC883_LAPTOP_EAPD, 173 ALC883_LENOVO_101E_2ch, 174 ALC883_LENOVO_NB0763, 175 ALC888_LENOVO_MS7195_DIG, 176 ALC888_6ST_HP, 177 ALC888_3ST_HP, 178 ALC883_AUTO, 179 ALC883_MODEL_LAST, 180}; 181 182/* for GPIO Poll */ 183#define GPIO_MASK 0x03 184 185struct alc_spec { 186 /* codec parameterization */ 187 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ 188 unsigned int num_mixers; 189 190 const struct hda_verb *init_verbs[5]; /* initialization verbs 191 * don't forget NULL 192 * termination! 193 */ 194 unsigned int num_init_verbs; 195 196 char *stream_name_analog; /* analog PCM stream */ 197 struct hda_pcm_stream *stream_analog_playback; 198 struct hda_pcm_stream *stream_analog_capture; 199 200 char *stream_name_digital; /* digital PCM stream */ 201 struct hda_pcm_stream *stream_digital_playback; 202 struct hda_pcm_stream *stream_digital_capture; 203 204 /* playback */ 205 struct hda_multi_out multiout; /* playback set-up 206 * max_channels, dacs must be set 207 * dig_out_nid and hp_nid are optional 208 */ 209 210 /* capture */ 211 unsigned int num_adc_nids; 212 hda_nid_t *adc_nids; 213 hda_nid_t dig_in_nid; /* digital-in NID; optional */ 214 215 /* capture source */ 216 unsigned int num_mux_defs; 217 const struct hda_input_mux *input_mux; 218 unsigned int cur_mux[3]; 219 220 /* channel model */ 221 const struct hda_channel_mode *channel_mode; 222 int num_channel_mode; 223 int need_dac_fix; 224 225 /* PCM information */ 226 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ 227 228 /* dynamic controls, init_verbs and input_mux */ 229 struct auto_pin_cfg autocfg; 230 unsigned int num_kctl_alloc, num_kctl_used; 231 struct snd_kcontrol_new *kctl_alloc; 232 struct hda_input_mux private_imux; 233 hda_nid_t private_dac_nids[5]; 234 235 /* hooks */ 236 void (*init_hook)(struct hda_codec *codec); 237 void (*unsol_event)(struct hda_codec *codec, unsigned int res); 238 239 /* for pin sensing */ 240 unsigned int sense_updated: 1; 241 unsigned int jack_present: 1; 242}; 243 244/* 245 * configuration template - to be copied to the spec instance 246 */ 247struct alc_config_preset { 248 struct snd_kcontrol_new *mixers[5]; /* should be identical size 249 * with spec 250 */ 251 const struct hda_verb *init_verbs[5]; 252 unsigned int num_dacs; 253 hda_nid_t *dac_nids; 254 hda_nid_t dig_out_nid; /* optional */ 255 hda_nid_t hp_nid; /* optional */ 256 unsigned int num_adc_nids; 257 hda_nid_t *adc_nids; 258 hda_nid_t dig_in_nid; 259 unsigned int num_channel_mode; 260 const struct hda_channel_mode *channel_mode; 261 int need_dac_fix; 262 unsigned int num_mux_defs; 263 const struct hda_input_mux *input_mux; 264 void (*unsol_event)(struct hda_codec *, unsigned int); 265 void (*init_hook)(struct hda_codec *); 266}; 267 268 269/* 270 * input MUX handling 271 */ 272static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, 273 struct snd_ctl_elem_info *uinfo) 274{ 275 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 276 struct alc_spec *spec = codec->spec; 277 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id); 278 if (mux_idx >= spec->num_mux_defs) 279 mux_idx = 0; 280 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); 281} 282 283static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, 284 struct snd_ctl_elem_value *ucontrol) 285{ 286 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 287 struct alc_spec *spec = codec->spec; 288 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 289 290 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; 291 return 0; 292} 293 294static int alc_mux_enum_put(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 unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; 301 return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol, 302 spec->adc_nids[adc_idx], 303 &spec->cur_mux[adc_idx]); 304} 305 306 307/* 308 * channel mode setting 309 */ 310static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, 311 struct snd_ctl_elem_info *uinfo) 312{ 313 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 314 struct alc_spec *spec = codec->spec; 315 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, 316 spec->num_channel_mode); 317} 318 319static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, 320 struct snd_ctl_elem_value *ucontrol) 321{ 322 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 323 struct alc_spec *spec = codec->spec; 324 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, 325 spec->num_channel_mode, 326 spec->multiout.max_channels); 327} 328 329static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, 330 struct snd_ctl_elem_value *ucontrol) 331{ 332 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 333 struct alc_spec *spec = codec->spec; 334 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, 335 spec->num_channel_mode, 336 &spec->multiout.max_channels); 337 if (err >= 0 && spec->need_dac_fix) 338 spec->multiout.num_dacs = spec->multiout.max_channels / 2; 339 return err; 340} 341 342/* 343 * Control the mode of pin widget settings via the mixer. "pc" is used 344 * instead of "%" to avoid consequences of accidently treating the % as 345 * being part of a format specifier. Maximum allowed length of a value is 346 * 63 characters plus NULL terminator. 347 * 348 * Note: some retasking pin complexes seem to ignore requests for input 349 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these 350 * are requested. Therefore order this list so that this behaviour will not 351 * cause problems when mixer clients move through the enum sequentially. 352 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of 353 * March 2006. 354 */ 355static char *alc_pin_mode_names[] = { 356 "Mic 50pc bias", "Mic 80pc bias", 357 "Line in", "Line out", "Headphone out", 358}; 359static unsigned char alc_pin_mode_values[] = { 360 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, 361}; 362/* The control can present all 5 options, or it can limit the options based 363 * in the pin being assumed to be exclusively an input or an output pin. In 364 * addition, "input" pins may or may not process the mic bias option 365 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to 366 * accept requests for bias as of chip versions up to March 2006) and/or 367 * wiring in the computer. 368 */ 369#define ALC_PIN_DIR_IN 0x00 370#define ALC_PIN_DIR_OUT 0x01 371#define ALC_PIN_DIR_INOUT 0x02 372#define ALC_PIN_DIR_IN_NOMICBIAS 0x03 373#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04 374 375/* Info about the pin modes supported by the different pin direction modes. 376 * For each direction the minimum and maximum values are given. 377 */ 378static signed char alc_pin_mode_dir_info[5][2] = { 379 { 0, 2 }, /* ALC_PIN_DIR_IN */ 380 { 3, 4 }, /* ALC_PIN_DIR_OUT */ 381 { 0, 4 }, /* ALC_PIN_DIR_INOUT */ 382 { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */ 383 { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */ 384}; 385#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) 386#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) 387#define alc_pin_mode_n_items(_dir) \ 388 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1) 389 390static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, 391 struct snd_ctl_elem_info *uinfo) 392{ 393 unsigned int item_num = uinfo->value.enumerated.item; 394 unsigned char dir = (kcontrol->private_value >> 16) & 0xff; 395 396 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 397 uinfo->count = 1; 398 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir); 399 400 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir)) 401 item_num = alc_pin_mode_min(dir); 402 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]); 403 return 0; 404} 405 406static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, 407 struct snd_ctl_elem_value *ucontrol) 408{ 409 unsigned int i; 410 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 411 hda_nid_t nid = kcontrol->private_value & 0xffff; 412 unsigned char dir = (kcontrol->private_value >> 16) & 0xff; 413 long *valp = ucontrol->value.integer.value; 414 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, 415 AC_VERB_GET_PIN_WIDGET_CONTROL, 416 0x00); 417 418 /* Find enumerated value for current pinctl setting */ 419 i = alc_pin_mode_min(dir); 420 while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir)) 421 i++; 422 *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir); 423 return 0; 424} 425 426static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, 427 struct snd_ctl_elem_value *ucontrol) 428{ 429 signed int change; 430 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 431 hda_nid_t nid = kcontrol->private_value & 0xffff; 432 unsigned char dir = (kcontrol->private_value >> 16) & 0xff; 433 long val = *ucontrol->value.integer.value; 434 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, 435 AC_VERB_GET_PIN_WIDGET_CONTROL, 436 0x00); 437 438 if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) 439 val = alc_pin_mode_min(dir); 440 441 change = pinctl != alc_pin_mode_values[val]; 442 if (change) { 443 /* Set pin mode to that requested */ 444 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, 445 alc_pin_mode_values[val]); 446 447 /* Also enable the retasking pin's input/output as required 448 * for the requested pin mode. Enum values of 2 or less are 449 * input modes. 450 * 451 * Dynamically switching the input/output buffers probably 452 * reduces noise slightly (particularly on input) so we'll 453 * do it. However, having both input and output buffers 454 * enabled simultaneously doesn't seem to be problematic if 455 * this turns out to be necessary in the future. 456 */ 457 if (val <= 2) { 458 snd_hda_codec_write(codec, nid, 0, 459 AC_VERB_SET_AMP_GAIN_MUTE, 460 AMP_OUT_MUTE); 461 snd_hda_codec_write(codec, nid, 0, 462 AC_VERB_SET_AMP_GAIN_MUTE, 463 AMP_IN_UNMUTE(0)); 464 } else { 465 snd_hda_codec_write(codec, nid, 0, 466 AC_VERB_SET_AMP_GAIN_MUTE, 467 AMP_IN_MUTE(0)); 468 snd_hda_codec_write(codec, nid, 0, 469 AC_VERB_SET_AMP_GAIN_MUTE, 470 AMP_OUT_UNMUTE); 471 } 472 } 473 return change; 474} 475 476#define ALC_PIN_MODE(xname, nid, dir) \ 477 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 478 .info = alc_pin_mode_info, \ 479 .get = alc_pin_mode_get, \ 480 .put = alc_pin_mode_put, \ 481 .private_value = nid | (dir<<16) } 482 483/* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged 484 * together using a mask with more than one bit set. This control is 485 * currently used only by the ALC260 test model. At this stage they are not 486 * needed for any "production" models. 487 */ 488#ifdef CONFIG_SND_DEBUG 489#define alc_gpio_data_info snd_ctl_boolean_mono_info 490 491static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, 492 struct snd_ctl_elem_value *ucontrol) 493{ 494 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 495 hda_nid_t nid = kcontrol->private_value & 0xffff; 496 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 497 long *valp = ucontrol->value.integer.value; 498 unsigned int val = snd_hda_codec_read(codec, nid, 0, 499 AC_VERB_GET_GPIO_DATA, 0x00); 500 501 *valp = (val & mask) != 0; 502 return 0; 503} 504static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, 505 struct snd_ctl_elem_value *ucontrol) 506{ 507 signed int change; 508 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 509 hda_nid_t nid = kcontrol->private_value & 0xffff; 510 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 511 long val = *ucontrol->value.integer.value; 512 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, 513 AC_VERB_GET_GPIO_DATA, 514 0x00); 515 516 /* Set/unset the masked GPIO bit(s) as needed */ 517 change = (val == 0 ? 0 : mask) != (gpio_data & mask); 518 if (val == 0) 519 gpio_data &= ~mask; 520 else 521 gpio_data |= mask; 522 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); 523 524 return change; 525} 526#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ 527 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 528 .info = alc_gpio_data_info, \ 529 .get = alc_gpio_data_get, \ 530 .put = alc_gpio_data_put, \ 531 .private_value = nid | (mask<<16) } 532#endif /* CONFIG_SND_DEBUG */ 533 534/* A switch control to allow the enabling of the digital IO pins on the 535 * ALC260. This is incredibly simplistic; the intention of this control is 536 * to provide something in the test model allowing digital outputs to be 537 * identified if present. If models are found which can utilise these 538 * outputs a more complete mixer control can be devised for those models if 539 * necessary. 540 */ 541#ifdef CONFIG_SND_DEBUG 542#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info 543 544static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, 545 struct snd_ctl_elem_value *ucontrol) 546{ 547 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 548 hda_nid_t nid = kcontrol->private_value & 0xffff; 549 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 550 long *valp = ucontrol->value.integer.value; 551 unsigned int val = snd_hda_codec_read(codec, nid, 0, 552 AC_VERB_GET_DIGI_CONVERT, 0x00); 553 554 *valp = (val & mask) != 0; 555 return 0; 556} 557static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, 558 struct snd_ctl_elem_value *ucontrol) 559{ 560 signed int change; 561 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 562 hda_nid_t nid = kcontrol->private_value & 0xffff; 563 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 564 long val = *ucontrol->value.integer.value; 565 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, 566 AC_VERB_GET_DIGI_CONVERT, 567 0x00); 568 569 /* Set/unset the masked control bit(s) as needed */ 570 change = (val == 0 ? 0 : mask) != (ctrl_data & mask); 571 if (val==0) 572 ctrl_data &= ~mask; 573 else 574 ctrl_data |= mask; 575 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, 576 ctrl_data); 577 578 return change; 579} 580#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ 581 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 582 .info = alc_spdif_ctrl_info, \ 583 .get = alc_spdif_ctrl_get, \ 584 .put = alc_spdif_ctrl_put, \ 585 .private_value = nid | (mask<<16) } 586#endif /* CONFIG_SND_DEBUG */ 587 588/* 589 * set up from the preset table 590 */ 591static void setup_preset(struct alc_spec *spec, 592 const struct alc_config_preset *preset) 593{ 594 int i; 595 596 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) 597 spec->mixers[spec->num_mixers++] = preset->mixers[i]; 598 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; 599 i++) 600 spec->init_verbs[spec->num_init_verbs++] = 601 preset->init_verbs[i]; 602 603 spec->channel_mode = preset->channel_mode; 604 spec->num_channel_mode = preset->num_channel_mode; 605 spec->need_dac_fix = preset->need_dac_fix; 606 607 spec->multiout.max_channels = spec->channel_mode[0].channels; 608 609 spec->multiout.num_dacs = preset->num_dacs; 610 spec->multiout.dac_nids = preset->dac_nids; 611 spec->multiout.dig_out_nid = preset->dig_out_nid; 612 spec->multiout.hp_nid = preset->hp_nid; 613 614 spec->num_mux_defs = preset->num_mux_defs; 615 if (!spec->num_mux_defs) 616 spec->num_mux_defs = 1; 617 spec->input_mux = preset->input_mux; 618 619 spec->num_adc_nids = preset->num_adc_nids; 620 spec->adc_nids = preset->adc_nids; 621 spec->dig_in_nid = preset->dig_in_nid; 622 623 spec->unsol_event = preset->unsol_event; 624 spec->init_hook = preset->init_hook; 625} 626 627/* Enable GPIO mask and set output */ 628static struct hda_verb alc_gpio1_init_verbs[] = { 629 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 630 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 631 {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, 632 { } 633}; 634 635static struct hda_verb alc_gpio2_init_verbs[] = { 636 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 637 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 638 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, 639 { } 640}; 641 642static struct hda_verb alc_gpio3_init_verbs[] = { 643 {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 644 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 645 {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 646 { } 647}; 648 649/* 32-bit subsystem ID for BIOS loading in HD Audio codec. 650 * 31 ~ 16 : Manufacture ID 651 * 15 ~ 8 : SKU ID 652 * 7 ~ 0 : Assembly ID 653 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36 654 */ 655static void alc_subsystem_id(struct hda_codec *codec, 656 unsigned int porta, unsigned int porte, 657 unsigned int portd) 658{ 659 unsigned int ass, tmp; 660 661 ass = codec->subsystem_id; 662 if (!(ass & 1)) 663 return; 664 665 /* Override */ 666 tmp = (ass & 0x38) >> 3; /* external Amp control */ 667 switch (tmp) { 668 case 1: 669 snd_hda_sequence_write(codec, alc_gpio1_init_verbs); 670 break; 671 case 3: 672 snd_hda_sequence_write(codec, alc_gpio2_init_verbs); 673 break; 674 case 7: 675 snd_hda_sequence_write(codec, alc_gpio3_init_verbs); 676 break; 677 case 5: 678 switch (codec->vendor_id) { 679 case 0x10ec0862: 680 case 0x10ec0660: 681 case 0x10ec0662: 682 case 0x10ec0267: 683 case 0x10ec0268: 684 snd_hda_codec_write(codec, 0x14, 0, 685 AC_VERB_SET_EAPD_BTLENABLE, 2); 686 snd_hda_codec_write(codec, 0x15, 0, 687 AC_VERB_SET_EAPD_BTLENABLE, 2); 688 return; 689 } 690 case 6: 691 if (ass & 4) { /* bit 2 : 0 = Desktop, 1 = Laptop */ 692 hda_nid_t port = 0; 693 tmp = (ass & 0x1800) >> 11; 694 switch (tmp) { 695 case 0: port = porta; break; 696 case 1: port = porte; break; 697 case 2: port = portd; break; 698 } 699 if (port) 700 snd_hda_codec_write(codec, port, 0, 701 AC_VERB_SET_EAPD_BTLENABLE, 702 2); 703 } 704 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); 705 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, 706 (tmp == 5 ? 0x3040 : 0x3050)); 707 break; 708 } 709} 710 711/* 712 * Fix-up pin default configurations 713 */ 714 715struct alc_pincfg { 716 hda_nid_t nid; 717 u32 val; 718}; 719 720static void alc_fix_pincfg(struct hda_codec *codec, 721 const struct snd_pci_quirk *quirk, 722 const struct alc_pincfg **pinfix) 723{ 724 const struct alc_pincfg *cfg; 725 726 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); 727 if (!quirk) 728 return; 729 730 cfg = pinfix[quirk->value]; 731 for (; cfg->nid; cfg++) { 732 int i; 733 u32 val = cfg->val; 734 for (i = 0; i < 4; i++) { 735 snd_hda_codec_write(codec, cfg->nid, 0, 736 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i, 737 val & 0xff); 738 val >>= 8; 739 } 740 } 741} 742 743/* 744 * ALC880 3-stack model 745 * 746 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) 747 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, 748 * F-Mic = 0x1b, HP = 0x19 749 */ 750 751static hda_nid_t alc880_dac_nids[4] = { 752 /* front, rear, clfe, rear_surr */ 753 0x02, 0x05, 0x04, 0x03 754}; 755 756static hda_nid_t alc880_adc_nids[3] = { 757 /* ADC0-2 */ 758 0x07, 0x08, 0x09, 759}; 760 761/* The datasheet says the node 0x07 is connected from inputs, 762 * but it shows zero connection in the real implementation on some devices. 763 * Note: this is a 915GAV bug, fixed on 915GLV 764 */ 765static hda_nid_t alc880_adc_nids_alt[2] = { 766 /* ADC1-2 */ 767 0x08, 0x09, 768}; 769 770#define ALC880_DIGOUT_NID 0x06 771#define ALC880_DIGIN_NID 0x0a 772 773static struct hda_input_mux alc880_capture_source = { 774 .num_items = 4, 775 .items = { 776 { "Mic", 0x0 }, 777 { "Front Mic", 0x3 }, 778 { "Line", 0x2 }, 779 { "CD", 0x4 }, 780 }, 781}; 782 783/* channel source setting (2/6 channel selection for 3-stack) */ 784/* 2ch mode */ 785static struct hda_verb alc880_threestack_ch2_init[] = { 786 /* set line-in to input, mute it */ 787 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 788 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 789 /* set mic-in to input vref 80%, mute it */ 790 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 791 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 792 { } /* end */ 793}; 794 795/* 6ch mode */ 796static struct hda_verb alc880_threestack_ch6_init[] = { 797 /* set line-in to output, unmute it */ 798 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 799 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 800 /* set mic-in to output, unmute it */ 801 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 802 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 803 { } /* end */ 804}; 805 806static struct hda_channel_mode alc880_threestack_modes[2] = { 807 { 2, alc880_threestack_ch2_init }, 808 { 6, alc880_threestack_ch6_init }, 809}; 810 811static struct snd_kcontrol_new alc880_three_stack_mixer[] = { 812 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 813 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 814 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 815 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), 816 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 817 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 818 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 819 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 820 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 821 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 822 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 823 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 824 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 825 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 826 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), 827 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), 828 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 829 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 830 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), 831 { 832 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 833 .name = "Channel Mode", 834 .info = alc_ch_mode_info, 835 .get = alc_ch_mode_get, 836 .put = alc_ch_mode_put, 837 }, 838 { } /* end */ 839}; 840 841/* capture mixer elements */ 842static struct snd_kcontrol_new alc880_capture_mixer[] = { 843 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), 844 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), 845 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), 846 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), 847 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), 848 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), 849 { 850 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 851 /* The multiple "Capture Source" controls confuse alsamixer 852 * So call somewhat different.. 853 * FIXME: the controls appear in the "playback" view! 854 */ 855 /* .name = "Capture Source", */ 856 .name = "Input Source", 857 .count = 3, 858 .info = alc_mux_enum_info, 859 .get = alc_mux_enum_get, 860 .put = alc_mux_enum_put, 861 }, 862 { } /* end */ 863}; 864 865/* capture mixer elements (in case NID 0x07 not available) */ 866static struct snd_kcontrol_new alc880_capture_alt_mixer[] = { 867 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 868 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 869 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 870 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 871 { 872 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 873 /* The multiple "Capture Source" controls confuse alsamixer 874 * So call somewhat different.. 875 * FIXME: the controls appear in the "playback" view! 876 */ 877 /* .name = "Capture Source", */ 878 .name = "Input Source", 879 .count = 2, 880 .info = alc_mux_enum_info, 881 .get = alc_mux_enum_get, 882 .put = alc_mux_enum_put, 883 }, 884 { } /* end */ 885}; 886 887 888 889/* 890 * ALC880 5-stack model 891 * 892 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), 893 * Side = 0x02 (0xd) 894 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 895 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 896 */ 897 898/* additional mixers to alc880_three_stack_mixer */ 899static struct snd_kcontrol_new alc880_five_stack_mixer[] = { 900 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 901 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), 902 { } /* end */ 903}; 904 905/* channel source setting (6/8 channel selection for 5-stack) */ 906/* 6ch mode */ 907static struct hda_verb alc880_fivestack_ch6_init[] = { 908 /* set line-in to input, mute it */ 909 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 910 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 911 { } /* end */ 912}; 913 914/* 8ch mode */ 915static struct hda_verb alc880_fivestack_ch8_init[] = { 916 /* set line-in to output, unmute it */ 917 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 918 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 919 { } /* end */ 920}; 921 922static struct hda_channel_mode alc880_fivestack_modes[2] = { 923 { 6, alc880_fivestack_ch6_init }, 924 { 8, alc880_fivestack_ch8_init }, 925}; 926 927 928/* 929 * ALC880 6-stack model 930 * 931 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), 932 * Side = 0x05 (0x0f) 933 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, 934 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b 935 */ 936 937static hda_nid_t alc880_6st_dac_nids[4] = { 938 /* front, rear, clfe, rear_surr */ 939 0x02, 0x03, 0x04, 0x05 940}; 941 942static struct hda_input_mux alc880_6stack_capture_source = { 943 .num_items = 4, 944 .items = { 945 { "Mic", 0x0 }, 946 { "Front Mic", 0x1 }, 947 { "Line", 0x2 }, 948 { "CD", 0x4 }, 949 }, 950}; 951 952/* fixed 8-channels */ 953static struct hda_channel_mode alc880_sixstack_modes[1] = { 954 { 8, NULL }, 955}; 956 957static struct snd_kcontrol_new alc880_six_stack_mixer[] = { 958 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 959 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 960 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 961 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 962 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 963 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 964 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 965 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 966 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 967 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 968 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 969 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 970 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 971 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 972 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 973 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 974 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 975 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 976 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 977 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 978 { 979 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 980 .name = "Channel Mode", 981 .info = alc_ch_mode_info, 982 .get = alc_ch_mode_get, 983 .put = alc_ch_mode_put, 984 }, 985 { } /* end */ 986}; 987 988 989/* 990 * ALC880 W810 model 991 * 992 * W810 has rear IO for: 993 * Front (DAC 02) 994 * Surround (DAC 03) 995 * Center/LFE (DAC 04) 996 * Digital out (06) 997 * 998 * The system also has a pair of internal speakers, and a headphone jack. 999 * These are both connected to Line2 on the codec, hence to DAC 02. 1000 * 1001 * There is a variable resistor to control the speaker or headphone 1002 * volume. This is a hardware-only device without a software API. 1003 * 1004 * Plugging headphones in will disable the internal speakers. This is 1005 * implemented in hardware, not via the driver using jack sense. In 1006 * a similar fashion, plugging into the rear socket marked "front" will 1007 * disable both the speakers and headphones. 1008 * 1009 * For input, there's a microphone jack, and an "audio in" jack. 1010 * These may not do anything useful with this driver yet, because I 1011 * haven't setup any initialization verbs for these yet... 1012 */ 1013 1014static hda_nid_t alc880_w810_dac_nids[3] = { 1015 /* front, rear/surround, clfe */ 1016 0x02, 0x03, 0x04 1017}; 1018 1019/* fixed 6 channels */ 1020static struct hda_channel_mode alc880_w810_modes[1] = { 1021 { 6, NULL } 1022}; 1023 1024/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ 1025static struct snd_kcontrol_new alc880_w810_base_mixer[] = { 1026 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1027 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1028 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1029 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 1030 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1031 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1032 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1033 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1034 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 1035 { } /* end */ 1036}; 1037 1038 1039/* 1040 * Z710V model 1041 * 1042 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) 1043 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), 1044 * Line = 0x1a 1045 */ 1046 1047static hda_nid_t alc880_z71v_dac_nids[1] = { 1048 0x02 1049}; 1050#define ALC880_Z71V_HP_DAC 0x03 1051 1052/* fixed 2 channels */ 1053static struct hda_channel_mode alc880_2_jack_modes[1] = { 1054 { 2, NULL } 1055}; 1056 1057static struct snd_kcontrol_new alc880_z71v_mixer[] = { 1058 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1059 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1060 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1061 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), 1062 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1063 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1064 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1065 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1066 { } /* end */ 1067}; 1068 1069 1070/* FIXME! */ 1071/* 1072 * ALC880 F1734 model 1073 * 1074 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d) 1075 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18 1076 */ 1077 1078static hda_nid_t alc880_f1734_dac_nids[1] = { 1079 0x03 1080}; 1081#define ALC880_F1734_HP_DAC 0x02 1082 1083static struct snd_kcontrol_new alc880_f1734_mixer[] = { 1084 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1085 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), 1086 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1087 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT), 1088 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1089 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1090 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1091 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1092 { } /* end */ 1093}; 1094 1095 1096/* FIXME! */ 1097/* 1098 * ALC880 ASUS model 1099 * 1100 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) 1101 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, 1102 * Mic = 0x18, Line = 0x1a 1103 */ 1104 1105#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */ 1106#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */ 1107 1108static struct snd_kcontrol_new alc880_asus_mixer[] = { 1109 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1110 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1111 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1112 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 1113 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1114 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1115 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1116 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1117 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1118 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1119 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 1120 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 1121 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1122 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1123 { 1124 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1125 .name = "Channel Mode", 1126 .info = alc_ch_mode_info, 1127 .get = alc_ch_mode_get, 1128 .put = alc_ch_mode_put, 1129 }, 1130 { } /* end */ 1131}; 1132 1133/* FIXME! */ 1134/* 1135 * ALC880 ASUS W1V model 1136 * 1137 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) 1138 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, 1139 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b 1140 */ 1141 1142/* additional mixers to alc880_asus_mixer */ 1143static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { 1144 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT), 1145 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT), 1146 { } /* end */ 1147}; 1148 1149/* additional mixers to alc880_asus_mixer */ 1150static struct snd_kcontrol_new alc880_pcbeep_mixer[] = { 1151 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 1152 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 1153 { } /* end */ 1154}; 1155 1156/* TCL S700 */ 1157static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { 1158 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1159 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 1160 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 1161 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT), 1162 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT), 1163 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT), 1164 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT), 1165 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 1166 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 1167 { 1168 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1169 /* The multiple "Capture Source" controls confuse alsamixer 1170 * So call somewhat different.. 1171 * FIXME: the controls appear in the "playback" view! 1172 */ 1173 /* .name = "Capture Source", */ 1174 .name = "Input Source", 1175 .count = 1, 1176 .info = alc_mux_enum_info, 1177 .get = alc_mux_enum_get, 1178 .put = alc_mux_enum_put, 1179 }, 1180 { } /* end */ 1181}; 1182 1183/* Uniwill */ 1184static struct snd_kcontrol_new alc880_uniwill_mixer[] = { 1185 HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1186 HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT), 1187 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1188 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), 1189 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1190 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1191 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1192 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1193 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1194 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1195 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 1196 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 1197 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1198 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1199 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 1200 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 1201 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 1202 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 1203 { 1204 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1205 .name = "Channel Mode", 1206 .info = alc_ch_mode_info, 1207 .get = alc_ch_mode_get, 1208 .put = alc_ch_mode_put, 1209 }, 1210 { } /* end */ 1211}; 1212 1213static struct snd_kcontrol_new alc880_fujitsu_mixer[] = { 1214 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1215 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), 1216 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1217 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), 1218 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1219 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1220 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1221 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1222 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 1223 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 1224 { } /* end */ 1225}; 1226 1227static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = { 1228 HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1229 HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT), 1230 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1231 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), 1232 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1233 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1234 { } /* end */ 1235}; 1236 1237/* 1238 * build control elements 1239 */ 1240static int alc_build_controls(struct hda_codec *codec) 1241{ 1242 struct alc_spec *spec = codec->spec; 1243 int err; 1244 int i; 1245 1246 for (i = 0; i < spec->num_mixers; i++) { 1247 err = snd_hda_add_new_ctls(codec, spec->mixers[i]); 1248 if (err < 0) 1249 return err; 1250 } 1251 1252 if (spec->multiout.dig_out_nid) { 1253 err = snd_hda_create_spdif_out_ctls(codec, 1254 spec->multiout.dig_out_nid); 1255 if (err < 0) 1256 return err; 1257 } 1258 if (spec->dig_in_nid) { 1259 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 1260 if (err < 0) 1261 return err; 1262 } 1263 return 0; 1264} 1265 1266 1267/* 1268 * initialize the codec volumes, etc 1269 */ 1270 1271/* 1272 * generic initialization of ADC, input mixers and output mixers 1273 */ 1274static struct hda_verb alc880_volume_init_verbs[] = { 1275 /* 1276 * Unmute ADC0-2 and set the default input to mic-in 1277 */ 1278 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 1279 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1280 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 1281 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1282 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 1283 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1284 1285 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 1286 * mixer widget 1287 * Note: PASD motherboards uses the Line In 2 as the input for front 1288 * panel mic (mic 2) 1289 */ 1290 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 1291 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1292 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1293 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 1294 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 1295 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 1296 1297 /* 1298 * Set up output mixers (0x0c - 0x0f) 1299 */ 1300 /* set vol=0 to output mixers */ 1301 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1302 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1303 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1304 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1305 /* set up input amps for analog loopback */ 1306 /* Amp Indices: DAC = 0, mixer = 1 */ 1307 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1308 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1309 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1310 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1311 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1312 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1313 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1314 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1315 1316 { } 1317}; 1318 1319/* 1320 * 3-stack pin configuration: 1321 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b 1322 */ 1323static struct hda_verb alc880_pin_3stack_init_verbs[] = { 1324 /* 1325 * preset connection lists of input pins 1326 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround 1327 */ 1328 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 1329 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1330 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ 1331 1332 /* 1333 * Set pin mode and muting 1334 */ 1335 /* set front pin widgets 0x14 for output */ 1336 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1337 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1338 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 1339 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1340 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1341 /* Mic2 (as headphone out) for HP output */ 1342 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1343 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1344 /* Line In pin widget for input */ 1345 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1346 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1347 /* Line2 (as front mic) pin widget for input and vref at 80% */ 1348 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1349 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1350 /* CD pin widget for input */ 1351 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1352 1353 { } 1354}; 1355 1356/* 1357 * 5-stack pin configuration: 1358 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19, 1359 * line-in/side = 0x1a, f-mic = 0x1b 1360 */ 1361static struct hda_verb alc880_pin_5stack_init_verbs[] = { 1362 /* 1363 * preset connection lists of input pins 1364 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround 1365 */ 1366 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1367 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */ 1368 1369 /* 1370 * Set pin mode and muting 1371 */ 1372 /* set pin widgets 0x14-0x17 for output */ 1373 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1374 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1375 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1376 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1377 /* unmute pins for output (no gain on this amp) */ 1378 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1379 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1380 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1381 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1382 1383 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 1384 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1385 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1386 /* Mic2 (as headphone out) for HP output */ 1387 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1388 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1389 /* Line In pin widget for input */ 1390 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1391 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1392 /* Line2 (as front mic) pin widget for input and vref at 80% */ 1393 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1394 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1395 /* CD pin widget for input */ 1396 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1397 1398 { } 1399}; 1400 1401/* 1402 * W810 pin configuration: 1403 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b 1404 */ 1405static struct hda_verb alc880_pin_w810_init_verbs[] = { 1406 /* hphone/speaker input selector: front DAC */ 1407 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, 1408 1409 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1410 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1411 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1412 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1413 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1414 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1415 1416 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1417 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1418 1419 { } 1420}; 1421 1422/* 1423 * Z71V pin configuration: 1424 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) 1425 */ 1426static struct hda_verb alc880_pin_z71v_init_verbs[] = { 1427 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1428 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1429 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1430 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1431 1432 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1433 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1434 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1435 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1436 1437 { } 1438}; 1439 1440/* 1441 * 6-stack pin configuration: 1442 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, 1443 * f-mic = 0x19, line = 0x1a, HP = 0x1b 1444 */ 1445static struct hda_verb alc880_pin_6stack_init_verbs[] = { 1446 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1447 1448 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1449 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1450 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1451 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1452 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1453 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1454 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1455 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1456 1457 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1458 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1459 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1460 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1461 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1462 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1463 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1464 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1465 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1466 1467 { } 1468}; 1469 1470/* 1471 * Uniwill pin configuration: 1472 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19, 1473 * line = 0x1a 1474 */ 1475static struct hda_verb alc880_uniwill_init_verbs[] = { 1476 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1477 1478 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1479 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1480 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1481 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1482 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1483 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1484 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1485 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1486 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1487 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1488 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1489 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1490 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1491 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1492 1493 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1494 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1495 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1496 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1497 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1498 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1499 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */ 1500 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */ 1501 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1502 1503 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 1504 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, 1505 1506 { } 1507}; 1508 1509/* 1510* Uniwill P53 1511* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19, 1512 */ 1513static struct hda_verb alc880_uniwill_p53_init_verbs[] = { 1514 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1515 1516 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1517 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1518 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1519 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1520 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1521 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1522 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1523 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1524 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1525 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1526 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1527 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1528 1529 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1530 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1531 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1532 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1533 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1534 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1535 1536 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 1537 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT}, 1538 1539 { } 1540}; 1541 1542static struct hda_verb alc880_beep_init_verbs[] = { 1543 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) }, 1544 { } 1545}; 1546 1547/* toggle speaker-output according to the hp-jack state */ 1548static void alc880_uniwill_hp_automute(struct hda_codec *codec) 1549{ 1550 unsigned int present; 1551 unsigned char bits; 1552 1553 present = snd_hda_codec_read(codec, 0x14, 0, 1554 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1555 bits = present ? 0x80 : 0; 1556 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 1557 0x80, bits); 1558 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 1559 0x80, bits); 1560 snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0, 1561 0x80, bits); 1562 snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0, 1563 0x80, bits); 1564} 1565 1566/* auto-toggle front mic */ 1567static void alc880_uniwill_mic_automute(struct hda_codec *codec) 1568{ 1569 unsigned int present; 1570 unsigned char bits; 1571 1572 present = snd_hda_codec_read(codec, 0x18, 0, 1573 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1574 bits = present ? 0x80 : 0; 1575 snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, 1576 0x80, bits); 1577 snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, 1578 0x80, bits); 1579} 1580 1581static void alc880_uniwill_automute(struct hda_codec *codec) 1582{ 1583 alc880_uniwill_hp_automute(codec); 1584 alc880_uniwill_mic_automute(codec); 1585} 1586 1587static void alc880_uniwill_unsol_event(struct hda_codec *codec, 1588 unsigned int res) 1589{ 1590 /* Looks like the unsol event is incompatible with the standard 1591 * definition. 4bit tag is placed at 28 bit! 1592 */ 1593 switch (res >> 28) { 1594 case ALC880_HP_EVENT: 1595 alc880_uniwill_hp_automute(codec); 1596 break; 1597 case ALC880_MIC_EVENT: 1598 alc880_uniwill_mic_automute(codec); 1599 break; 1600 } 1601} 1602 1603static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec) 1604{ 1605 unsigned int present; 1606 unsigned char bits; 1607 1608 present = snd_hda_codec_read(codec, 0x14, 0, 1609 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1610 bits = present ? 0x80 : 0; 1611 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0, 1612 0x80, bits); 1613 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0, 1614 0x80, bits); 1615} 1616 1617static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) 1618{ 1619 unsigned int present; 1620 1621 present = snd_hda_codec_read(codec, 0x21, 0, 1622 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f; 1623 1624 snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0, 1625 0x7f, present); 1626 snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0, 1627 0x7f, present); 1628 1629 snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0, 1630 0x7f, present); 1631 snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0, 1632 0x7f, present); 1633 1634} 1635static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, 1636 unsigned int res) 1637{ 1638 /* Looks like the unsol event is incompatible with the standard 1639 * definition. 4bit tag is placed at 28 bit! 1640 */ 1641 if ((res >> 28) == ALC880_HP_EVENT) 1642 alc880_uniwill_p53_hp_automute(codec); 1643 if ((res >> 28) == ALC880_DCVOL_EVENT) 1644 alc880_uniwill_p53_dcvol_automute(codec); 1645} 1646 1647/* FIXME! */ 1648/* 1649 * F1734 pin configuration: 1650 * HP = 0x14, speaker-out = 0x15, mic = 0x18 1651 */ 1652static struct hda_verb alc880_pin_f1734_init_verbs[] = { 1653 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, 1654 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, 1655 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, 1656 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, 1657 1658 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1659 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1660 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1661 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1662 1663 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1664 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1665 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1666 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1667 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1668 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1669 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1670 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1671 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1672 1673 { } 1674}; 1675 1676/* FIXME! */ 1677/* 1678 * ASUS pin configuration: 1679 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a 1680 */ 1681static struct hda_verb alc880_pin_asus_init_verbs[] = { 1682 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, 1683 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, 1684 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, 1685 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, 1686 1687 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1688 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1689 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1690 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1691 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1692 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1693 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1694 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1695 1696 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1697 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1698 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1699 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1700 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1701 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1702 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1703 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1704 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1705 1706 { } 1707}; 1708 1709/* Enable GPIO mask and set output */ 1710#define alc880_gpio1_init_verbs alc_gpio1_init_verbs 1711#define alc880_gpio2_init_verbs alc_gpio2_init_verbs 1712 1713/* Clevo m520g init */ 1714static struct hda_verb alc880_pin_clevo_init_verbs[] = { 1715 /* headphone output */ 1716 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, 1717 /* line-out */ 1718 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1719 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1720 /* Line-in */ 1721 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1722 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1723 /* CD */ 1724 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1725 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1726 /* Mic1 (rear panel) */ 1727 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1728 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1729 /* Mic2 (front panel) */ 1730 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1731 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1732 /* headphone */ 1733 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1734 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1735 /* change to EAPD mode */ 1736 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 1737 {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, 1738 1739 { } 1740}; 1741 1742static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { 1743 /* change to EAPD mode */ 1744 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 1745 {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, 1746 1747 /* Headphone output */ 1748 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1749 /* Front output*/ 1750 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1751 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 1752 1753 /* Line In pin widget for input */ 1754 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1755 /* CD pin widget for input */ 1756 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1757 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 1758 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1759 1760 /* change to EAPD mode */ 1761 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 1762 {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, 1763 1764 { } 1765}; 1766 1767/* 1768 * LG m1 express dual 1769 * 1770 * Pin assignment: 1771 * Rear Line-In/Out (blue): 0x14 1772 * Build-in Mic-In: 0x15 1773 * Speaker-out: 0x17 1774 * HP-Out (green): 0x1b 1775 * Mic-In/Out (red): 0x19 1776 * SPDIF-Out: 0x1e 1777 */ 1778 1779/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */ 1780static hda_nid_t alc880_lg_dac_nids[3] = { 1781 0x05, 0x02, 0x03 1782}; 1783 1784/* seems analog CD is not working */ 1785static struct hda_input_mux alc880_lg_capture_source = { 1786 .num_items = 3, 1787 .items = { 1788 { "Mic", 0x1 }, 1789 { "Line", 0x5 }, 1790 { "Internal Mic", 0x6 }, 1791 }, 1792}; 1793 1794/* 2,4,6 channel modes */ 1795static struct hda_verb alc880_lg_ch2_init[] = { 1796 /* set line-in and mic-in to input */ 1797 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 1798 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 1799 { } 1800}; 1801 1802static struct hda_verb alc880_lg_ch4_init[] = { 1803 /* set line-in to out and mic-in to input */ 1804 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, 1805 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 1806 { } 1807}; 1808 1809static struct hda_verb alc880_lg_ch6_init[] = { 1810 /* set line-in and mic-in to output */ 1811 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, 1812 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, 1813 { } 1814}; 1815 1816static struct hda_channel_mode alc880_lg_ch_modes[3] = { 1817 { 2, alc880_lg_ch2_init }, 1818 { 4, alc880_lg_ch4_init }, 1819 { 6, alc880_lg_ch6_init }, 1820}; 1821 1822static struct snd_kcontrol_new alc880_lg_mixer[] = { 1823 /* FIXME: it's not really "master" but front channels */ 1824 HDA_CODEC_VOLUME("Master Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 1825 HDA_BIND_MUTE("Master Playback Switch", 0x0f, 2, HDA_INPUT), 1826 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1827 HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT), 1828 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), 1829 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), 1830 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), 1831 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), 1832 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 1833 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 1834 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT), 1835 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT), 1836 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT), 1837 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT), 1838 { 1839 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1840 .name = "Channel Mode", 1841 .info = alc_ch_mode_info, 1842 .get = alc_ch_mode_get, 1843 .put = alc_ch_mode_put, 1844 }, 1845 { } /* end */ 1846}; 1847 1848static struct hda_verb alc880_lg_init_verbs[] = { 1849 /* set capture source to mic-in */ 1850 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1851 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1852 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1853 /* mute all amp mixer inputs */ 1854 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, 1855 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, 1856 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, 1857 /* line-in to input */ 1858 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1859 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1860 /* built-in mic */ 1861 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1862 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1863 /* speaker-out */ 1864 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1865 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1866 /* mic-in to input */ 1867 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, 1868 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1869 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1870 /* HP-out */ 1871 {0x13, AC_VERB_SET_CONNECT_SEL, 0x03}, 1872 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1873 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1874 /* jack sense */ 1875 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1}, 1876 { } 1877}; 1878 1879/* toggle speaker-output according to the hp-jack state */ 1880static void alc880_lg_automute(struct hda_codec *codec) 1881{ 1882 unsigned int present; 1883 unsigned char bits; 1884 1885 present = snd_hda_codec_read(codec, 0x1b, 0, 1886 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1887 bits = present ? 0x80 : 0; 1888 snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0, 1889 0x80, bits); 1890 snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0, 1891 0x80, bits); 1892} 1893 1894static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) 1895{ 1896 /* Looks like the unsol event is incompatible with the standard 1897 * definition. 4bit tag is placed at 28 bit! 1898 */ 1899 if ((res >> 28) == 0x01) 1900 alc880_lg_automute(codec); 1901} 1902 1903/* 1904 * LG LW20 1905 * 1906 * Pin assignment: 1907 * Speaker-out: 0x14 1908 * Mic-In: 0x18 1909 * Built-in Mic-In: 0x19 1910 * Line-In: 0x1b 1911 * HP-Out: 0x1a 1912 * SPDIF-Out: 0x1e 1913 */ 1914 1915static struct hda_input_mux alc880_lg_lw_capture_source = { 1916 .num_items = 3, 1917 .items = { 1918 { "Mic", 0x0 }, 1919 { "Internal Mic", 0x1 }, 1920 { "Line In", 0x2 }, 1921 }, 1922}; 1923 1924#define alc880_lg_lw_modes alc880_threestack_modes 1925 1926static struct snd_kcontrol_new alc880_lg_lw_mixer[] = { 1927 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1928 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1929 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 1930 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), 1931 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1932 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1933 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1934 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1935 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 1936 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 1937 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1938 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1939 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 1940 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 1941 { 1942 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1943 .name = "Channel Mode", 1944 .info = alc_ch_mode_info, 1945 .get = alc_ch_mode_get, 1946 .put = alc_ch_mode_put, 1947 }, 1948 { } /* end */ 1949}; 1950 1951static struct hda_verb alc880_lg_lw_init_verbs[] = { 1952 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1953 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 1954 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ 1955 1956 /* set capture source to mic-in */ 1957 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1958 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1959 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1960 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, 1961 /* speaker-out */ 1962 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1963 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1964 /* HP-out */ 1965 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1966 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1967 /* mic-in to input */ 1968 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1969 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1970 /* built-in mic */ 1971 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1972 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1973 /* jack sense */ 1974 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1}, 1975 { } 1976}; 1977 1978/* toggle speaker-output according to the hp-jack state */ 1979static void alc880_lg_lw_automute(struct hda_codec *codec) 1980{ 1981 unsigned int present; 1982 unsigned char bits; 1983 1984 present = snd_hda_codec_read(codec, 0x1b, 0, 1985 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1986 bits = present ? 0x80 : 0; 1987 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 1988 0x80, bits); 1989 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 1990 0x80, bits); 1991} 1992 1993static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) 1994{ 1995 /* Looks like the unsol event is incompatible with the standard 1996 * definition. 4bit tag is placed at 28 bit! 1997 */ 1998 if ((res >> 28) == 0x01) 1999 alc880_lg_lw_automute(codec); 2000} 2001 2002/* 2003 * Common callbacks 2004 */ 2005 2006static int alc_init(struct hda_codec *codec) 2007{ 2008 struct alc_spec *spec = codec->spec; 2009 unsigned int i; 2010 2011 for (i = 0; i < spec->num_init_verbs; i++) 2012 snd_hda_sequence_write(codec, spec->init_verbs[i]); 2013 2014 if (spec->init_hook) 2015 spec->init_hook(codec); 2016 2017 return 0; 2018} 2019 2020static void alc_unsol_event(struct hda_codec *codec, unsigned int res) 2021{ 2022 struct alc_spec *spec = codec->spec; 2023 2024 if (spec->unsol_event) 2025 spec->unsol_event(codec, res); 2026} 2027 2028#ifdef CONFIG_PM 2029/* 2030 * resume 2031 */ 2032static int alc_resume(struct hda_codec *codec) 2033{ 2034 struct alc_spec *spec = codec->spec; 2035 int i; 2036 2037 alc_init(codec); 2038 for (i = 0; i < spec->num_mixers; i++) 2039 snd_hda_resume_ctls(codec, spec->mixers[i]); 2040 if (spec->multiout.dig_out_nid) 2041 snd_hda_resume_spdif_out(codec); 2042 if (spec->dig_in_nid) 2043 snd_hda_resume_spdif_in(codec); 2044 2045 return 0; 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_PM 2281 .resume = alc_resume, 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 snd_hda_codec_write(codec, nid, 0, 2380 AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); 2381 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 2382 (ucontrol->value.enumerated.item[0] >= 3 ? 2383 0xb080 : 0xb000)); 2384 return 1; 2385 } 2386 return 0; 2387} 2388 2389static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, 2390 struct snd_ctl_elem_info *uinfo) 2391{ 2392 static char *texts[] = { 2393 "Front", "Surround", "CLFE", "Side" 2394 }; 2395 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2396 uinfo->count = 1; 2397 uinfo->value.enumerated.items = 4; 2398 if (uinfo->value.enumerated.item >= 4) 2399 uinfo->value.enumerated.item = 3; 2400 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2401 return 0; 2402} 2403 2404static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, 2405 struct snd_ctl_elem_value *ucontrol) 2406{ 2407 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2408 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 2409 unsigned int sel; 2410 2411 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); 2412 ucontrol->value.enumerated.item[0] = sel & 3; 2413 return 0; 2414} 2415 2416static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, 2417 struct snd_ctl_elem_value *ucontrol) 2418{ 2419 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2420 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 2421 unsigned int sel; 2422 2423 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; 2424 if (ucontrol->value.enumerated.item[0] != sel) { 2425 sel = ucontrol->value.enumerated.item[0] & 3; 2426 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); 2427 return 1; 2428 } 2429 return 0; 2430} 2431 2432#define PIN_CTL_TEST(xname,nid) { \ 2433 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 2434 .name = xname, \ 2435 .info = alc_test_pin_ctl_info, \ 2436 .get = alc_test_pin_ctl_get, \ 2437 .put = alc_test_pin_ctl_put, \ 2438 .private_value = nid \ 2439 } 2440 2441#define PIN_SRC_TEST(xname,nid) { \ 2442 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 2443 .name = xname, \ 2444 .info = alc_test_pin_src_info, \ 2445 .get = alc_test_pin_src_get, \ 2446 .put = alc_test_pin_src_put, \ 2447 .private_value = nid \ 2448 } 2449 2450static struct snd_kcontrol_new alc880_test_mixer[] = { 2451 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 2452 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 2453 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), 2454 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 2455 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 2456 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 2457 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), 2458 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 2459 PIN_CTL_TEST("Front Pin Mode", 0x14), 2460 PIN_CTL_TEST("Surround Pin Mode", 0x15), 2461 PIN_CTL_TEST("CLFE Pin Mode", 0x16), 2462 PIN_CTL_TEST("Side Pin Mode", 0x17), 2463 PIN_CTL_TEST("In-1 Pin Mode", 0x18), 2464 PIN_CTL_TEST("In-2 Pin Mode", 0x19), 2465 PIN_CTL_TEST("In-3 Pin Mode", 0x1a), 2466 PIN_CTL_TEST("In-4 Pin Mode", 0x1b), 2467 PIN_SRC_TEST("In-1 Pin Source", 0x18), 2468 PIN_SRC_TEST("In-2 Pin Source", 0x19), 2469 PIN_SRC_TEST("In-3 Pin Source", 0x1a), 2470 PIN_SRC_TEST("In-4 Pin Source", 0x1b), 2471 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), 2472 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), 2473 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), 2474 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), 2475 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), 2476 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), 2477 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), 2478 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), 2479 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), 2480 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), 2481 { 2482 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2483 .name = "Channel Mode", 2484 .info = alc_ch_mode_info, 2485 .get = alc_ch_mode_get, 2486 .put = alc_ch_mode_put, 2487 }, 2488 { } /* end */ 2489}; 2490 2491static struct hda_verb alc880_test_init_verbs[] = { 2492 /* Unmute inputs of 0x0c - 0x0f */ 2493 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2494 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2495 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2496 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2497 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2498 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2499 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2500 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2501 /* Vol output for 0x0c-0x0f */ 2502 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2503 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2504 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2505 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2506 /* Set output pins 0x14-0x17 */ 2507 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2508 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2509 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2510 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2511 /* Unmute output pins 0x14-0x17 */ 2512 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2513 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2514 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2515 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2516 /* Set input pins 0x18-0x1c */ 2517 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2518 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2519 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2520 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2521 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2522 /* Mute input pins 0x18-0x1b */ 2523 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2524 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2525 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2526 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2527 /* ADC set up */ 2528 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2529 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 2530 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2531 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 2532 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2533 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 2534 /* Analog input/passthru */ 2535 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2536 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2537 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2538 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2539 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2540 { } 2541}; 2542#endif 2543 2544/* 2545 */ 2546 2547static const char *alc880_models[ALC880_MODEL_LAST] = { 2548 [ALC880_3ST] = "3stack", 2549 [ALC880_TCL_S700] = "tcl", 2550 [ALC880_3ST_DIG] = "3stack-digout", 2551 [ALC880_CLEVO] = "clevo", 2552 [ALC880_5ST] = "5stack", 2553 [ALC880_5ST_DIG] = "5stack-digout", 2554 [ALC880_W810] = "w810", 2555 [ALC880_Z71V] = "z71v", 2556 [ALC880_6ST] = "6stack", 2557 [ALC880_6ST_DIG] = "6stack-digout", 2558 [ALC880_ASUS] = "asus", 2559 [ALC880_ASUS_W1V] = "asus-w1v", 2560 [ALC880_ASUS_DIG] = "asus-dig", 2561 [ALC880_ASUS_DIG2] = "asus-dig2", 2562 [ALC880_UNIWILL_DIG] = "uniwill", 2563 [ALC880_UNIWILL_P53] = "uniwill-p53", 2564 [ALC880_FUJITSU] = "fujitsu", 2565 [ALC880_F1734] = "F1734", 2566 [ALC880_LG] = "lg", 2567 [ALC880_LG_LW] = "lg-lw", 2568#ifdef CONFIG_SND_DEBUG 2569 [ALC880_TEST] = "test", 2570#endif 2571 [ALC880_AUTO] = "auto", 2572}; 2573 2574static struct snd_pci_quirk alc880_cfg_tbl[] = { 2575 /* Broken BIOS configuration */ 2576 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), 2577 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG), 2578 2579 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG), 2580 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST), 2581 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810), 2582 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG), 2583 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG), 2584 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG), 2585 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG), 2586 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG), 2587 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST), 2588 2589 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG), 2590 SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST), 2591 2592 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V), 2593 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG), 2594 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG), 2595 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG), 2596 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG), 2597 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG), 2598 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V), 2599 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ 2600 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), 2601 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), 2602 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS), 2603 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), 2604 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), 2605 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), 2606 SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS), 2607 2608 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), 2609 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), 2610 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST), 2611 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST), 2612 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), 2613 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO), 2614 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO), 2615 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), 2616 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810), 2617 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), 2618 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700), 2619 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), 2620 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), 2621 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG), 2622 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG), 2623 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG), 2624 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG), 2625 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), 2626 2627 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), 2628 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), 2629 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53), 2630 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734), 2631 2632 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), 2633 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL), 2634 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), 2635 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), 2636 2637 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), 2638 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG), 2639 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW), 2640 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW), 2641 2642 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG), 2643 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG), 2644 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG), 2645 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG), 2646 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG), 2647 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG), 2648 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), 2649 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), 2650 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), 2651 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG), 2652 SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST), 2653 2654 {} 2655}; 2656 2657/* 2658 * ALC880 codec presets 2659 */ 2660static struct alc_config_preset alc880_presets[] = { 2661 [ALC880_3ST] = { 2662 .mixers = { alc880_three_stack_mixer }, 2663 .init_verbs = { alc880_volume_init_verbs, 2664 alc880_pin_3stack_init_verbs }, 2665 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2666 .dac_nids = alc880_dac_nids, 2667 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2668 .channel_mode = alc880_threestack_modes, 2669 .need_dac_fix = 1, 2670 .input_mux = &alc880_capture_source, 2671 }, 2672 [ALC880_3ST_DIG] = { 2673 .mixers = { alc880_three_stack_mixer }, 2674 .init_verbs = { alc880_volume_init_verbs, 2675 alc880_pin_3stack_init_verbs }, 2676 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2677 .dac_nids = alc880_dac_nids, 2678 .dig_out_nid = ALC880_DIGOUT_NID, 2679 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2680 .channel_mode = alc880_threestack_modes, 2681 .need_dac_fix = 1, 2682 .input_mux = &alc880_capture_source, 2683 }, 2684 [ALC880_TCL_S700] = { 2685 .mixers = { alc880_tcl_s700_mixer }, 2686 .init_verbs = { alc880_volume_init_verbs, 2687 alc880_pin_tcl_S700_init_verbs, 2688 alc880_gpio2_init_verbs }, 2689 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2690 .dac_nids = alc880_dac_nids, 2691 .hp_nid = 0x03, 2692 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2693 .channel_mode = alc880_2_jack_modes, 2694 .input_mux = &alc880_capture_source, 2695 }, 2696 [ALC880_5ST] = { 2697 .mixers = { alc880_three_stack_mixer, 2698 alc880_five_stack_mixer}, 2699 .init_verbs = { alc880_volume_init_verbs, 2700 alc880_pin_5stack_init_verbs }, 2701 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2702 .dac_nids = alc880_dac_nids, 2703 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), 2704 .channel_mode = alc880_fivestack_modes, 2705 .input_mux = &alc880_capture_source, 2706 }, 2707 [ALC880_5ST_DIG] = { 2708 .mixers = { alc880_three_stack_mixer, 2709 alc880_five_stack_mixer }, 2710 .init_verbs = { alc880_volume_init_verbs, 2711 alc880_pin_5stack_init_verbs }, 2712 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2713 .dac_nids = alc880_dac_nids, 2714 .dig_out_nid = ALC880_DIGOUT_NID, 2715 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), 2716 .channel_mode = alc880_fivestack_modes, 2717 .input_mux = &alc880_capture_source, 2718 }, 2719 [ALC880_6ST] = { 2720 .mixers = { alc880_six_stack_mixer }, 2721 .init_verbs = { alc880_volume_init_verbs, 2722 alc880_pin_6stack_init_verbs }, 2723 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), 2724 .dac_nids = alc880_6st_dac_nids, 2725 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), 2726 .channel_mode = alc880_sixstack_modes, 2727 .input_mux = &alc880_6stack_capture_source, 2728 }, 2729 [ALC880_6ST_DIG] = { 2730 .mixers = { alc880_six_stack_mixer }, 2731 .init_verbs = { alc880_volume_init_verbs, 2732 alc880_pin_6stack_init_verbs }, 2733 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), 2734 .dac_nids = alc880_6st_dac_nids, 2735 .dig_out_nid = ALC880_DIGOUT_NID, 2736 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), 2737 .channel_mode = alc880_sixstack_modes, 2738 .input_mux = &alc880_6stack_capture_source, 2739 }, 2740 [ALC880_W810] = { 2741 .mixers = { alc880_w810_base_mixer }, 2742 .init_verbs = { alc880_volume_init_verbs, 2743 alc880_pin_w810_init_verbs, 2744 alc880_gpio2_init_verbs }, 2745 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), 2746 .dac_nids = alc880_w810_dac_nids, 2747 .dig_out_nid = ALC880_DIGOUT_NID, 2748 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), 2749 .channel_mode = alc880_w810_modes, 2750 .input_mux = &alc880_capture_source, 2751 }, 2752 [ALC880_Z71V] = { 2753 .mixers = { alc880_z71v_mixer }, 2754 .init_verbs = { alc880_volume_init_verbs, 2755 alc880_pin_z71v_init_verbs }, 2756 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), 2757 .dac_nids = alc880_z71v_dac_nids, 2758 .dig_out_nid = ALC880_DIGOUT_NID, 2759 .hp_nid = 0x03, 2760 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2761 .channel_mode = alc880_2_jack_modes, 2762 .input_mux = &alc880_capture_source, 2763 }, 2764 [ALC880_F1734] = { 2765 .mixers = { alc880_f1734_mixer }, 2766 .init_verbs = { alc880_volume_init_verbs, 2767 alc880_pin_f1734_init_verbs }, 2768 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), 2769 .dac_nids = alc880_f1734_dac_nids, 2770 .hp_nid = 0x02, 2771 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2772 .channel_mode = alc880_2_jack_modes, 2773 .input_mux = &alc880_capture_source, 2774 }, 2775 [ALC880_ASUS] = { 2776 .mixers = { alc880_asus_mixer }, 2777 .init_verbs = { alc880_volume_init_verbs, 2778 alc880_pin_asus_init_verbs, 2779 alc880_gpio1_init_verbs }, 2780 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2781 .dac_nids = alc880_asus_dac_nids, 2782 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2783 .channel_mode = alc880_asus_modes, 2784 .need_dac_fix = 1, 2785 .input_mux = &alc880_capture_source, 2786 }, 2787 [ALC880_ASUS_DIG] = { 2788 .mixers = { alc880_asus_mixer }, 2789 .init_verbs = { alc880_volume_init_verbs, 2790 alc880_pin_asus_init_verbs, 2791 alc880_gpio1_init_verbs }, 2792 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2793 .dac_nids = alc880_asus_dac_nids, 2794 .dig_out_nid = ALC880_DIGOUT_NID, 2795 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2796 .channel_mode = alc880_asus_modes, 2797 .need_dac_fix = 1, 2798 .input_mux = &alc880_capture_source, 2799 }, 2800 [ALC880_ASUS_DIG2] = { 2801 .mixers = { alc880_asus_mixer }, 2802 .init_verbs = { alc880_volume_init_verbs, 2803 alc880_pin_asus_init_verbs, 2804 alc880_gpio2_init_verbs }, /* use GPIO2 */ 2805 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2806 .dac_nids = alc880_asus_dac_nids, 2807 .dig_out_nid = ALC880_DIGOUT_NID, 2808 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2809 .channel_mode = alc880_asus_modes, 2810 .need_dac_fix = 1, 2811 .input_mux = &alc880_capture_source, 2812 }, 2813 [ALC880_ASUS_W1V] = { 2814 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, 2815 .init_verbs = { alc880_volume_init_verbs, 2816 alc880_pin_asus_init_verbs, 2817 alc880_gpio1_init_verbs }, 2818 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2819 .dac_nids = alc880_asus_dac_nids, 2820 .dig_out_nid = ALC880_DIGOUT_NID, 2821 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2822 .channel_mode = alc880_asus_modes, 2823 .need_dac_fix = 1, 2824 .input_mux = &alc880_capture_source, 2825 }, 2826 [ALC880_UNIWILL_DIG] = { 2827 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer }, 2828 .init_verbs = { alc880_volume_init_verbs, 2829 alc880_pin_asus_init_verbs }, 2830 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2831 .dac_nids = alc880_asus_dac_nids, 2832 .dig_out_nid = ALC880_DIGOUT_NID, 2833 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2834 .channel_mode = alc880_asus_modes, 2835 .need_dac_fix = 1, 2836 .input_mux = &alc880_capture_source, 2837 }, 2838 [ALC880_UNIWILL] = { 2839 .mixers = { alc880_uniwill_mixer }, 2840 .init_verbs = { alc880_volume_init_verbs, 2841 alc880_uniwill_init_verbs }, 2842 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2843 .dac_nids = alc880_asus_dac_nids, 2844 .dig_out_nid = ALC880_DIGOUT_NID, 2845 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2846 .channel_mode = alc880_threestack_modes, 2847 .need_dac_fix = 1, 2848 .input_mux = &alc880_capture_source, 2849 .unsol_event = alc880_uniwill_unsol_event, 2850 .init_hook = alc880_uniwill_automute, 2851 }, 2852 [ALC880_UNIWILL_P53] = { 2853 .mixers = { alc880_uniwill_p53_mixer }, 2854 .init_verbs = { alc880_volume_init_verbs, 2855 alc880_uniwill_p53_init_verbs }, 2856 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2857 .dac_nids = alc880_asus_dac_nids, 2858 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), 2859 .channel_mode = alc880_threestack_modes, 2860 .input_mux = &alc880_capture_source, 2861 .unsol_event = alc880_uniwill_p53_unsol_event, 2862 .init_hook = alc880_uniwill_p53_hp_automute, 2863 }, 2864 [ALC880_FUJITSU] = { 2865 .mixers = { alc880_fujitsu_mixer, 2866 alc880_pcbeep_mixer, }, 2867 .init_verbs = { alc880_volume_init_verbs, 2868 alc880_uniwill_p53_init_verbs, 2869 alc880_beep_init_verbs }, 2870 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2871 .dac_nids = alc880_dac_nids, 2872 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2873 .channel_mode = alc880_2_jack_modes, 2874 .input_mux = &alc880_capture_source, 2875 .unsol_event = alc880_uniwill_p53_unsol_event, 2876 .init_hook = alc880_uniwill_p53_hp_automute, 2877 }, 2878 [ALC880_CLEVO] = { 2879 .mixers = { alc880_three_stack_mixer }, 2880 .init_verbs = { alc880_volume_init_verbs, 2881 alc880_pin_clevo_init_verbs }, 2882 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2883 .dac_nids = alc880_dac_nids, 2884 .hp_nid = 0x03, 2885 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2886 .channel_mode = alc880_threestack_modes, 2887 .need_dac_fix = 1, 2888 .input_mux = &alc880_capture_source, 2889 }, 2890 [ALC880_LG] = { 2891 .mixers = { alc880_lg_mixer }, 2892 .init_verbs = { alc880_volume_init_verbs, 2893 alc880_lg_init_verbs }, 2894 .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids), 2895 .dac_nids = alc880_lg_dac_nids, 2896 .dig_out_nid = ALC880_DIGOUT_NID, 2897 .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), 2898 .channel_mode = alc880_lg_ch_modes, 2899 .need_dac_fix = 1, 2900 .input_mux = &alc880_lg_capture_source, 2901 .unsol_event = alc880_lg_unsol_event, 2902 .init_hook = alc880_lg_automute, 2903 }, 2904 [ALC880_LG_LW] = { 2905 .mixers = { alc880_lg_lw_mixer }, 2906 .init_verbs = { alc880_volume_init_verbs, 2907 alc880_lg_lw_init_verbs }, 2908 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2909 .dac_nids = alc880_dac_nids, 2910 .dig_out_nid = ALC880_DIGOUT_NID, 2911 .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes), 2912 .channel_mode = alc880_lg_lw_modes, 2913 .input_mux = &alc880_lg_lw_capture_source, 2914 .unsol_event = alc880_lg_lw_unsol_event, 2915 .init_hook = alc880_lg_lw_automute, 2916 }, 2917#ifdef CONFIG_SND_DEBUG 2918 [ALC880_TEST] = { 2919 .mixers = { alc880_test_mixer }, 2920 .init_verbs = { alc880_test_init_verbs }, 2921 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids), 2922 .dac_nids = alc880_test_dac_nids, 2923 .dig_out_nid = ALC880_DIGOUT_NID, 2924 .num_channel_mode = ARRAY_SIZE(alc880_test_modes), 2925 .channel_mode = alc880_test_modes, 2926 .input_mux = &alc880_test_capture_source, 2927 }, 2928#endif 2929}; 2930 2931/* 2932 * Automatic parse of I/O pins from the BIOS configuration 2933 */ 2934 2935#define NUM_CONTROL_ALLOC 32 2936#define NUM_VERB_ALLOC 32 2937 2938enum { 2939 ALC_CTL_WIDGET_VOL, 2940 ALC_CTL_WIDGET_MUTE, 2941 ALC_CTL_BIND_MUTE, 2942}; 2943static struct snd_kcontrol_new alc880_control_templates[] = { 2944 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 2945 HDA_CODEC_MUTE(NULL, 0, 0, 0), 2946 HDA_BIND_MUTE(NULL, 0, 0, 0), 2947}; 2948 2949/* add dynamic controls */ 2950static int add_control(struct alc_spec *spec, int type, const char *name, 2951 unsigned long val) 2952{ 2953 struct snd_kcontrol_new *knew; 2954 2955 if (spec->num_kctl_used >= spec->num_kctl_alloc) { 2956 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; 2957 2958 /* array + terminator */ 2959 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); 2960 if (!knew) 2961 return -ENOMEM; 2962 if (spec->kctl_alloc) { 2963 memcpy(knew, spec->kctl_alloc, 2964 sizeof(*knew) * spec->num_kctl_alloc); 2965 kfree(spec->kctl_alloc); 2966 } 2967 spec->kctl_alloc = knew; 2968 spec->num_kctl_alloc = num; 2969 } 2970 2971 knew = &spec->kctl_alloc[spec->num_kctl_used]; 2972 *knew = alc880_control_templates[type]; 2973 knew->name = kstrdup(name, GFP_KERNEL); 2974 if (!knew->name) 2975 return -ENOMEM; 2976 knew->private_value = val; 2977 spec->num_kctl_used++; 2978 return 0; 2979} 2980 2981#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) 2982#define alc880_fixed_pin_idx(nid) ((nid) - 0x14) 2983#define alc880_is_multi_pin(nid) ((nid) >= 0x18) 2984#define alc880_multi_pin_idx(nid) ((nid) - 0x18) 2985#define alc880_is_input_pin(nid) ((nid) >= 0x18) 2986#define alc880_input_pin_idx(nid) ((nid) - 0x18) 2987#define alc880_idx_to_dac(nid) ((nid) + 0x02) 2988#define alc880_dac_to_idx(nid) ((nid) - 0x02) 2989#define alc880_idx_to_mixer(nid) ((nid) + 0x0c) 2990#define alc880_idx_to_selector(nid) ((nid) + 0x10) 2991#define ALC880_PIN_CD_NID 0x1c 2992 2993/* fill in the dac_nids table from the parsed pin configuration */ 2994static int alc880_auto_fill_dac_nids(struct alc_spec *spec, 2995 const struct auto_pin_cfg *cfg) 2996{ 2997 hda_nid_t nid; 2998 int assigned[4]; 2999 int i, j; 3000 3001 memset(assigned, 0, sizeof(assigned)); 3002 spec->multiout.dac_nids = spec->private_dac_nids; 3003 3004 /* check the pins hardwired to audio widget */ 3005 for (i = 0; i < cfg->line_outs; i++) { 3006 nid = cfg->line_out_pins[i]; 3007 if (alc880_is_fixed_pin(nid)) { 3008 int idx = alc880_fixed_pin_idx(nid); 3009 spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx); 3010 assigned[idx] = 1; 3011 } 3012 } 3013 /* left pins can be connect to any audio widget */ 3014 for (i = 0; i < cfg->line_outs; i++) { 3015 nid = cfg->line_out_pins[i]; 3016 if (alc880_is_fixed_pin(nid)) 3017 continue; 3018 /* search for an empty channel */ 3019 for (j = 0; j < cfg->line_outs; j++) { 3020 if (!assigned[j]) { 3021 spec->multiout.dac_nids[i] = 3022 alc880_idx_to_dac(j); 3023 assigned[j] = 1; 3024 break; 3025 } 3026 } 3027 } 3028 spec->multiout.num_dacs = cfg->line_outs; 3029 return 0; 3030} 3031 3032/* add playback controls from the parsed DAC table */ 3033static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, 3034 const struct auto_pin_cfg *cfg) 3035{ 3036 char name[32]; 3037 static const char *chname[4] = { 3038 "Front", "Surround", NULL /*CLFE*/, "Side" 3039 }; 3040 hda_nid_t nid; 3041 int i, err; 3042 3043 for (i = 0; i < cfg->line_outs; i++) { 3044 if (!spec->multiout.dac_nids[i]) 3045 continue; 3046 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); 3047 if (i == 2) { 3048 /* Center/LFE */ 3049 err = add_control(spec, ALC_CTL_WIDGET_VOL, 3050 "Center Playback Volume", 3051 HDA_COMPOSE_AMP_VAL(nid, 1, 0, 3052 HDA_OUTPUT)); 3053 if (err < 0) 3054 return err; 3055 err = add_control(spec, ALC_CTL_WIDGET_VOL, 3056 "LFE Playback Volume", 3057 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 3058 HDA_OUTPUT)); 3059 if (err < 0) 3060 return err; 3061 err = add_control(spec, ALC_CTL_BIND_MUTE, 3062 "Center Playback Switch", 3063 HDA_COMPOSE_AMP_VAL(nid, 1, 2, 3064 HDA_INPUT)); 3065 if (err < 0) 3066 return err; 3067 err = add_control(spec, ALC_CTL_BIND_MUTE, 3068 "LFE Playback Switch", 3069 HDA_COMPOSE_AMP_VAL(nid, 2, 2, 3070 HDA_INPUT)); 3071 if (err < 0) 3072 return err; 3073 } else { 3074 sprintf(name, "%s Playback Volume", chname[i]); 3075 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 3076 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 3077 HDA_OUTPUT)); 3078 if (err < 0) 3079 return err; 3080 sprintf(name, "%s Playback Switch", chname[i]); 3081 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 3082 HDA_COMPOSE_AMP_VAL(nid, 3, 2, 3083 HDA_INPUT)); 3084 if (err < 0) 3085 return err; 3086 } 3087 } 3088 return 0; 3089} 3090 3091/* add playback controls for speaker and HP outputs */ 3092static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, 3093 const char *pfx) 3094{ 3095 hda_nid_t nid; 3096 int err; 3097 char name[32]; 3098 3099 if (!pin) 3100 return 0; 3101 3102 if (alc880_is_fixed_pin(pin)) { 3103 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 3104 /* specify the DAC as the extra output */ 3105 if (!spec->multiout.hp_nid) 3106 spec->multiout.hp_nid = nid; 3107 else 3108 spec->multiout.extra_out_nid[0] = nid; 3109 /* control HP volume/switch on the output mixer amp */ 3110 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); 3111 sprintf(name, "%s Playback Volume", pfx); 3112 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 3113 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 3114 if (err < 0) 3115 return err; 3116 sprintf(name, "%s Playback Switch", pfx); 3117 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 3118 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); 3119 if (err < 0) 3120 return err; 3121 } else if (alc880_is_multi_pin(pin)) { 3122 /* set manual connection */ 3123 /* we have only a switch on HP-out PIN */ 3124 sprintf(name, "%s Playback Switch", pfx); 3125 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 3126 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 3127 if (err < 0) 3128 return err; 3129 } 3130 return 0; 3131} 3132 3133/* create input playback/capture controls for the given pin */ 3134static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, 3135 const char *ctlname, 3136 int idx, hda_nid_t mix_nid) 3137{ 3138 char name[32]; 3139 int err; 3140 3141 sprintf(name, "%s Playback Volume", ctlname); 3142 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 3143 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 3144 if (err < 0) 3145 return err; 3146 sprintf(name, "%s Playback Switch", ctlname); 3147 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 3148 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 3149 if (err < 0) 3150 return err; 3151 return 0; 3152} 3153 3154/* create playback/capture controls for input pins */ 3155static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, 3156 const struct auto_pin_cfg *cfg) 3157{ 3158 struct hda_input_mux *imux = &spec->private_imux; 3159 int i, err, idx; 3160 3161 for (i = 0; i < AUTO_PIN_LAST; i++) { 3162 if (alc880_is_input_pin(cfg->input_pins[i])) { 3163 idx = alc880_input_pin_idx(cfg->input_pins[i]); 3164 err = new_analog_input(spec, cfg->input_pins[i], 3165 auto_pin_cfg_labels[i], 3166 idx, 0x0b); 3167 if (err < 0) 3168 return err; 3169 imux->items[imux->num_items].label = 3170 auto_pin_cfg_labels[i]; 3171 imux->items[imux->num_items].index = 3172 alc880_input_pin_idx(cfg->input_pins[i]); 3173 imux->num_items++; 3174 } 3175 } 3176 return 0; 3177} 3178 3179static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, 3180 hda_nid_t nid, int pin_type, 3181 int dac_idx) 3182{ 3183 /* set as output */ 3184 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 3185 pin_type); 3186 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 3187 AMP_OUT_UNMUTE); 3188 /* need the manual connection? */ 3189 if (alc880_is_multi_pin(nid)) { 3190 struct alc_spec *spec = codec->spec; 3191 int idx = alc880_multi_pin_idx(nid); 3192 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, 3193 AC_VERB_SET_CONNECT_SEL, 3194 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); 3195 } 3196} 3197 3198static int get_pin_type(int line_out_type) 3199{ 3200 if (line_out_type == AUTO_PIN_HP_OUT) 3201 return PIN_HP; 3202 else 3203 return PIN_OUT; 3204} 3205 3206static void alc880_auto_init_multi_out(struct hda_codec *codec) 3207{ 3208 struct alc_spec *spec = codec->spec; 3209 int i; 3210 3211 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 3212 for (i = 0; i < spec->autocfg.line_outs; i++) { 3213 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 3214 int pin_type = get_pin_type(spec->autocfg.line_out_type); 3215 alc880_auto_set_output_and_unmute(codec, nid, pin_type, i); 3216 } 3217} 3218 3219static void alc880_auto_init_extra_out(struct hda_codec *codec) 3220{ 3221 struct alc_spec *spec = codec->spec; 3222 hda_nid_t pin; 3223 3224 pin = spec->autocfg.speaker_pins[0]; 3225 if (pin) /* connect to front */ 3226 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); 3227 pin = spec->autocfg.hp_pins[0]; 3228 if (pin) /* connect to front */ 3229 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 3230} 3231 3232static void alc880_auto_init_analog_input(struct hda_codec *codec) 3233{ 3234 struct alc_spec *spec = codec->spec; 3235 int i; 3236 3237 for (i = 0; i < AUTO_PIN_LAST; i++) { 3238 hda_nid_t nid = spec->autocfg.input_pins[i]; 3239 if (alc880_is_input_pin(nid)) { 3240 snd_hda_codec_write(codec, nid, 0, 3241 AC_VERB_SET_PIN_WIDGET_CONTROL, 3242 i <= AUTO_PIN_FRONT_MIC ? 3243 PIN_VREF80 : PIN_IN); 3244 if (nid != ALC880_PIN_CD_NID) 3245 snd_hda_codec_write(codec, nid, 0, 3246 AC_VERB_SET_AMP_GAIN_MUTE, 3247 AMP_OUT_MUTE); 3248 } 3249 } 3250} 3251 3252/* parse the BIOS configuration and set up the alc_spec */ 3253/* return 1 if successful, 0 if the proper config is not found, 3254 * or a negative error code 3255 */ 3256static int alc880_parse_auto_config(struct hda_codec *codec) 3257{ 3258 struct alc_spec *spec = codec->spec; 3259 int err; 3260 static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; 3261 3262 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 3263 alc880_ignore); 3264 if (err < 0) 3265 return err; 3266 if (!spec->autocfg.line_outs) 3267 return 0; /* can't find valid BIOS pin config */ 3268 3269 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 3270 if (err < 0) 3271 return err; 3272 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); 3273 if (err < 0) 3274 return err; 3275 err = alc880_auto_create_extra_out(spec, 3276 spec->autocfg.speaker_pins[0], 3277 "Speaker"); 3278 if (err < 0) 3279 return err; 3280 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], 3281 "Headphone"); 3282 if (err < 0) 3283 return err; 3284 err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg); 3285 if (err < 0) 3286 return err; 3287 3288 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 3289 3290 if (spec->autocfg.dig_out_pin) 3291 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; 3292 if (spec->autocfg.dig_in_pin) 3293 spec->dig_in_nid = ALC880_DIGIN_NID; 3294 3295 if (spec->kctl_alloc) 3296 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 3297 3298 spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; 3299 3300 spec->num_mux_defs = 1; 3301 spec->input_mux = &spec->private_imux; 3302 3303 return 1; 3304} 3305 3306/* additional initialization for auto-configuration model */ 3307static void alc880_auto_init(struct hda_codec *codec) 3308{ 3309 alc880_auto_init_multi_out(codec); 3310 alc880_auto_init_extra_out(codec); 3311 alc880_auto_init_analog_input(codec); 3312} 3313 3314/* 3315 * OK, here we have finally the patch for ALC880 3316 */ 3317 3318static int patch_alc880(struct hda_codec *codec) 3319{ 3320 struct alc_spec *spec; 3321 int board_config; 3322 int err; 3323 3324 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3325 if (spec == NULL) 3326 return -ENOMEM; 3327 3328 codec->spec = spec; 3329 3330 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST, 3331 alc880_models, 3332 alc880_cfg_tbl); 3333 if (board_config < 0) { 3334 printk(KERN_INFO "hda_codec: Unknown model for ALC880, " 3335 "trying auto-probe from BIOS...\n"); 3336 board_config = ALC880_AUTO; 3337 } 3338 3339 if (board_config == ALC880_AUTO) { 3340 /* automatic parse from the BIOS config */ 3341 err = alc880_parse_auto_config(codec); 3342 if (err < 0) { 3343 alc_free(codec); 3344 return err; 3345 } else if (!err) { 3346 printk(KERN_INFO 3347 "hda_codec: Cannot set up configuration " 3348 "from BIOS. Using 3-stack mode...\n"); 3349 board_config = ALC880_3ST; 3350 } 3351 } 3352 3353 if (board_config != ALC880_AUTO) 3354 setup_preset(spec, &alc880_presets[board_config]); 3355 3356 spec->stream_name_analog = "ALC880 Analog"; 3357 spec->stream_analog_playback = &alc880_pcm_analog_playback; 3358 spec->stream_analog_capture = &alc880_pcm_analog_capture; 3359 3360 spec->stream_name_digital = "ALC880 Digital"; 3361 spec->stream_digital_playback = &alc880_pcm_digital_playback; 3362 spec->stream_digital_capture = &alc880_pcm_digital_capture; 3363 3364 if (!spec->adc_nids && spec->input_mux) { 3365 /* check whether NID 0x07 is valid */ 3366 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]); 3367 /* get type */ 3368 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 3369 if (wcap != AC_WID_AUD_IN) { 3370 spec->adc_nids = alc880_adc_nids_alt; 3371 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); 3372 spec->mixers[spec->num_mixers] = 3373 alc880_capture_alt_mixer; 3374 spec->num_mixers++; 3375 } else { 3376 spec->adc_nids = alc880_adc_nids; 3377 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); 3378 spec->mixers[spec->num_mixers] = alc880_capture_mixer; 3379 spec->num_mixers++; 3380 } 3381 } 3382 3383 codec->patch_ops = alc_patch_ops; 3384 if (board_config == ALC880_AUTO) 3385 spec->init_hook = alc880_auto_init; 3386 3387 return 0; 3388} 3389 3390 3391/* 3392 * ALC260 support 3393 */ 3394 3395static hda_nid_t alc260_dac_nids[1] = { 3396 /* front */ 3397 0x02, 3398}; 3399 3400static hda_nid_t alc260_adc_nids[1] = { 3401 /* ADC0 */ 3402 0x04, 3403}; 3404 3405static hda_nid_t alc260_adc_nids_alt[1] = { 3406 /* ADC1 */ 3407 0x05, 3408}; 3409 3410static hda_nid_t alc260_hp_adc_nids[2] = { 3411 /* ADC1, 0 */ 3412 0x05, 0x04 3413}; 3414 3415/* NIDs used when simultaneous access to both ADCs makes sense. Note that 3416 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. 3417 */ 3418static hda_nid_t alc260_dual_adc_nids[2] = { 3419 /* ADC0, ADC1 */ 3420 0x04, 0x05 3421}; 3422 3423#define ALC260_DIGOUT_NID 0x03 3424#define ALC260_DIGIN_NID 0x06 3425 3426static struct hda_input_mux alc260_capture_source = { 3427 .num_items = 4, 3428 .items = { 3429 { "Mic", 0x0 }, 3430 { "Front Mic", 0x1 }, 3431 { "Line", 0x2 }, 3432 { "CD", 0x4 }, 3433 }, 3434}; 3435 3436/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, 3437 * headphone jack and the internal CD lines since these are the only pins at 3438 * which audio can appear. For flexibility, also allow the option of 3439 * recording the mixer output on the second ADC (ADC0 doesn't have a 3440 * connection to the mixer output). 3441 */ 3442static struct hda_input_mux alc260_fujitsu_capture_sources[2] = { 3443 { 3444 .num_items = 3, 3445 .items = { 3446 { "Mic/Line", 0x0 }, 3447 { "CD", 0x4 }, 3448 { "Headphone", 0x2 }, 3449 }, 3450 }, 3451 { 3452 .num_items = 4, 3453 .items = { 3454 { "Mic/Line", 0x0 }, 3455 { "CD", 0x4 }, 3456 { "Headphone", 0x2 }, 3457 { "Mixer", 0x5 }, 3458 }, 3459 }, 3460 3461}; 3462 3463/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to 3464 * the Fujitsu S702x, but jacks are marked differently. 3465 */ 3466static struct hda_input_mux alc260_acer_capture_sources[2] = { 3467 { 3468 .num_items = 4, 3469 .items = { 3470 { "Mic", 0x0 }, 3471 { "Line", 0x2 }, 3472 { "CD", 0x4 }, 3473 { "Headphone", 0x5 }, 3474 }, 3475 }, 3476 { 3477 .num_items = 5, 3478 .items = { 3479 { "Mic", 0x0 }, 3480 { "Line", 0x2 }, 3481 { "CD", 0x4 }, 3482 { "Headphone", 0x6 }, 3483 { "Mixer", 0x5 }, 3484 }, 3485 }, 3486}; 3487/* 3488 * This is just place-holder, so there's something for alc_build_pcms to look 3489 * at when it calculates the maximum number of channels. ALC260 has no mixer 3490 * element which allows changing the channel mode, so the verb list is 3491 * never used. 3492 */ 3493static struct hda_channel_mode alc260_modes[1] = { 3494 { 2, NULL }, 3495}; 3496 3497 3498/* Mixer combinations 3499 * 3500 * basic: base_output + input + pc_beep + capture 3501 * HP: base_output + input + capture_alt 3502 * HP_3013: hp_3013 + input + capture 3503 * fujitsu: fujitsu + capture 3504 * acer: acer + capture 3505 */ 3506 3507static struct snd_kcontrol_new alc260_base_output_mixer[] = { 3508 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3509 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), 3510 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), 3511 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), 3512 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 3513 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), 3514 { } /* end */ 3515}; 3516 3517static struct snd_kcontrol_new alc260_input_mixer[] = { 3518 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3519 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3520 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3521 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3522 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3523 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3524 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), 3525 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), 3526 { } /* end */ 3527}; 3528 3529static struct snd_kcontrol_new alc260_pc_beep_mixer[] = { 3530 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), 3531 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), 3532 { } /* end */ 3533}; 3534 3535static struct snd_kcontrol_new alc260_hp_3013_mixer[] = { 3536 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT), 3537 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT), 3538 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT), 3539 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT), 3540 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3541 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 3542 HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 3543 HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT), 3544 { } /* end */ 3545}; 3546 3547/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12, 3548 * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10. 3549 */ 3550static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { 3551 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3552 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), 3553 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3554 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3555 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3556 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), 3557 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), 3558 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), 3559 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 3560 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 3561 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), 3562 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT), 3563 { } /* end */ 3564}; 3565 3566/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current 3567 * versions of the ALC260 don't act on requests to enable mic bias from NID 3568 * 0x0f (used to drive the headphone jack in these laptops). The ALC260 3569 * datasheet doesn't mention this restriction. At this stage it's not clear 3570 * whether this behaviour is intentional or is a hardware bug in chip 3571 * revisions available in early 2006. Therefore for now allow the 3572 * "Headphone Jack Mode" control to span all choices, but if it turns out 3573 * that the lack of mic bias for this NID is intentional we could change the 3574 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. 3575 * 3576 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006 3577 * don't appear to make the mic bias available from the "line" jack, even 3578 * though the NID used for this jack (0x14) can supply it. The theory is 3579 * that perhaps Acer have included blocking capacitors between the ALC260 3580 * and the output jack. If this turns out to be the case for all such 3581 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT 3582 * to ALC_PIN_DIR_INOUT_NOMICBIAS. 3583 * 3584 * The C20x Tablet series have a mono internal speaker which is controlled 3585 * via the chip's Mono sum widget and pin complex, so include the necessary 3586 * controls for such models. On models without a "mono speaker" the control 3587 * won't do anything. 3588 */ 3589static struct snd_kcontrol_new alc260_acer_mixer[] = { 3590 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3591 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), 3592 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), 3593 HDA_CODEC_VOLUME_MONO("Mono Speaker Playback Volume", 0x0a, 1, 0x0, 3594 HDA_OUTPUT), 3595 HDA_BIND_MUTE_MONO("Mono Speaker Playback Switch", 0x0a, 1, 2, 3596 HDA_INPUT), 3597 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3598 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3599 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3600 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3601 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), 3602 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3603 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3604 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3605 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 3606 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 3607 { } /* end */ 3608}; 3609 3610/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12, 3611 * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17. 3612 */ 3613static struct snd_kcontrol_new alc260_will_mixer[] = { 3614 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3615 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), 3616 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3617 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3618 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), 3619 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3620 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3621 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3622 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3623 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3624 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 3625 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 3626 { } /* end */ 3627}; 3628 3629/* Replacer 672V ALC260 pin usage: Mic jack = 0x12, 3630 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f. 3631 */ 3632static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = { 3633 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3634 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), 3635 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3636 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3637 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), 3638 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT), 3639 HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT), 3640 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3641 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3642 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3643 { } /* end */ 3644}; 3645 3646/* capture mixer elements */ 3647static struct snd_kcontrol_new alc260_capture_mixer[] = { 3648 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), 3649 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), 3650 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT), 3651 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT), 3652 { 3653 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3654 /* The multiple "Capture Source" controls confuse alsamixer 3655 * So call somewhat different.. 3656 * FIXME: the controls appear in the "playback" view! 3657 */ 3658 /* .name = "Capture Source", */ 3659 .name = "Input Source", 3660 .count = 2, 3661 .info = alc_mux_enum_info, 3662 .get = alc_mux_enum_get, 3663 .put = alc_mux_enum_put, 3664 }, 3665 { } /* end */ 3666}; 3667 3668static struct snd_kcontrol_new alc260_capture_alt_mixer[] = { 3669 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), 3670 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT), 3671 { 3672 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3673 /* The multiple "Capture Source" controls confuse alsamixer 3674 * So call somewhat different.. 3675 * FIXME: the controls appear in the "playback" view! 3676 */ 3677 /* .name = "Capture Source", */ 3678 .name = "Input Source", 3679 .count = 1, 3680 .info = alc_mux_enum_info, 3681 .get = alc_mux_enum_get, 3682 .put = alc_mux_enum_put, 3683 }, 3684 { } /* end */ 3685}; 3686 3687/* 3688 * initialization verbs 3689 */ 3690static struct hda_verb alc260_init_verbs[] = { 3691 /* Line In pin widget for input */ 3692 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3693 /* CD pin widget for input */ 3694 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3695 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 3696 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3697 /* Mic2 (front panel) pin widget for input and vref at 80% */ 3698 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3699 /* LINE-2 is used for line-out in rear */ 3700 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3701 /* select line-out */ 3702 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, 3703 /* LINE-OUT pin */ 3704 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3705 /* enable HP */ 3706 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3707 /* enable Mono */ 3708 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3709 /* mute capture amp left and right */ 3710 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3711 /* set connection select to line in (default select for this ADC) */ 3712 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, 3713 /* mute capture amp left and right */ 3714 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3715 /* set connection select to line in (default select for this ADC) */ 3716 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, 3717 /* set vol=0 Line-Out mixer amp left and right */ 3718 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3719 /* unmute pin widget amp left and right (no gain on this amp) */ 3720 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3721 /* set vol=0 HP mixer amp left and right */ 3722 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3723 /* unmute pin widget amp left and right (no gain on this amp) */ 3724 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3725 /* set vol=0 Mono mixer amp left and right */ 3726 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3727 /* unmute pin widget amp left and right (no gain on this amp) */ 3728 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3729 /* unmute LINE-2 out pin */ 3730 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3731 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & 3732 * Line In 2 = 0x03 3733 */ 3734 /* mute CD */ 3735 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 3736 /* mute Line In */ 3737 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 3738 /* mute Mic */ 3739 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3740 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ 3741 /* mute Front out path */ 3742 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3743 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3744 /* mute Headphone out path */ 3745 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3746 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3747 /* mute Mono out path */ 3748 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3749 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3750 { } 3751}; 3752 3753#if 0 /* should be identical with alc260_init_verbs? */ 3754static struct hda_verb alc260_hp_init_verbs[] = { 3755 /* Headphone and output */ 3756 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 3757 /* mono output */ 3758 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3759 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 3760 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3761 /* Mic2 (front panel) pin widget for input and vref at 80% */ 3762 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3763 /* Line In pin widget for input */ 3764 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3765 /* Line-2 pin widget for output */ 3766 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3767 /* CD pin widget for input */ 3768 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3769 /* unmute amp left and right */ 3770 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, 3771 /* set connection select to line in (default select for this ADC) */ 3772 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, 3773 /* unmute Line-Out mixer amp left and right (volume = 0) */ 3774 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3775 /* mute pin widget amp left and right (no gain on this amp) */ 3776 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3777 /* unmute HP mixer amp left and right (volume = 0) */ 3778 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3779 /* mute pin widget amp left and right (no gain on this amp) */ 3780 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3781 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & 3782 * Line In 2 = 0x03 3783 */ 3784 /* unmute CD */ 3785 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 3786 /* unmute Line In */ 3787 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 3788 /* unmute Mic */ 3789 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3790 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ 3791 /* Unmute Front out path */ 3792 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3793 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3794 /* Unmute Headphone out path */ 3795 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3796 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3797 /* Unmute Mono out path */ 3798 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3799 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3800 { } 3801}; 3802#endif 3803 3804static struct hda_verb alc260_hp_3013_init_verbs[] = { 3805 /* Line out and output */ 3806 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3807 /* mono output */ 3808 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3809 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 3810 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3811 /* Mic2 (front panel) pin widget for input and vref at 80% */ 3812 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3813 /* Line In pin widget for input */ 3814 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3815 /* Headphone pin widget for output */ 3816 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 3817 /* CD pin widget for input */ 3818 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3819 /* unmute amp left and right */ 3820 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, 3821 /* set connection select to line in (default select for this ADC) */ 3822 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, 3823 /* unmute Line-Out mixer amp left and right (volume = 0) */ 3824 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3825 /* mute pin widget amp left and right (no gain on this amp) */ 3826 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3827 /* unmute HP mixer amp left and right (volume = 0) */ 3828 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3829 /* mute pin widget amp left and right (no gain on this amp) */ 3830 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3831 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & 3832 * Line In 2 = 0x03 3833 */ 3834 /* unmute CD */ 3835 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 3836 /* unmute Line In */ 3837 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 3838 /* unmute Mic */ 3839 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3840 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ 3841 /* Unmute Front out path */ 3842 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3843 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3844 /* Unmute Headphone out path */ 3845 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3846 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3847 /* Unmute Mono out path */ 3848 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3849 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3850 { } 3851}; 3852 3853/* Initialisation sequence for ALC260 as configured in Fujitsu S702x 3854 * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD 3855 * audio = 0x16, internal speaker = 0x10. 3856 */ 3857static struct hda_verb alc260_fujitsu_init_verbs[] = { 3858 /* Disable all GPIOs */ 3859 {0x01, AC_VERB_SET_GPIO_MASK, 0}, 3860 /* Internal speaker is connected to headphone pin */ 3861 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3862 /* Headphone/Line-out jack connects to Line1 pin; make it an output */ 3863 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3864 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */ 3865 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3866 /* Ensure all other unused pins are disabled and muted. */ 3867 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3868 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3869 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3870 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3871 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3872 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3873 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3874 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3875 3876 /* Disable digital (SPDIF) pins */ 3877 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3878 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3879 3880 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus 3881 * when acting as an output. 3882 */ 3883 {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, 3884 3885 /* Start with output sum widgets muted and their output gains at min */ 3886 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3887 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3888 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3889 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3890 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3891 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3892 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3893 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3894 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3895 3896 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */ 3897 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3898 /* Unmute Line1 pin widget output buffer since it starts as an output. 3899 * If the pin mode is changed by the user the pin mode control will 3900 * take care of enabling the pin's input/output buffers as needed. 3901 * Therefore there's no need to enable the input buffer at this 3902 * stage. 3903 */ 3904 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3905 /* Unmute input buffer of pin widget used for Line-in (no equiv 3906 * mixer ctrl) 3907 */ 3908 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3909 3910 /* Mute capture amp left and right */ 3911 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3912 /* Set ADC connection select to match default mixer setting - line 3913 * in (on mic1 pin) 3914 */ 3915 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 3916 3917 /* Do the same for the second ADC: mute capture input amp and 3918 * set ADC connection to line in (on mic1 pin) 3919 */ 3920 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3921 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 3922 3923 /* Mute all inputs to mixer widget (even unconnected ones) */ 3924 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 3925 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 3926 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 3927 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 3928 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 3929 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 3930 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 3931 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 3932 3933 { } 3934}; 3935 3936/* Initialisation sequence for ALC260 as configured in Acer TravelMate and 3937 * similar laptops (adapted from Fujitsu init verbs). 3938 */ 3939static struct hda_verb alc260_acer_init_verbs[] = { 3940 /* On TravelMate laptops, GPIO 0 enables the internal speaker and 3941 * the headphone jack. Turn this on and rely on the standard mute 3942 * methods whenever the user wants to turn these outputs off. 3943 */ 3944 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 3945 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 3946 {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, 3947 /* Internal speaker/Headphone jack is connected to Line-out pin */ 3948 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3949 /* Internal microphone/Mic jack is connected to Mic1 pin */ 3950 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, 3951 /* Line In jack is connected to Line1 pin */ 3952 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3953 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */ 3954 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3955 /* Ensure all other unused pins are disabled and muted. */ 3956 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3957 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3958 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3959 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3960 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3961 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3962 /* Disable digital (SPDIF) pins */ 3963 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3964 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3965 3966 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum 3967 * bus when acting as outputs. 3968 */ 3969 {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, 3970 {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, 3971 3972 /* Start with output sum widgets muted and their output gains at min */ 3973 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3974 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3975 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3976 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3977 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3978 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3979 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3980 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3981 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3982 3983 /* Unmute Line-out pin widget amp left and right 3984 * (no equiv mixer ctrl) 3985 */ 3986 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3987 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */ 3988 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3989 /* Unmute Mic1 and Line1 pin widget input buffers since they start as 3990 * inputs. If the pin mode is changed by the user the pin mode control 3991 * will take care of enabling the pin's input/output buffers as needed. 3992 * Therefore there's no need to enable the input buffer at this 3993 * stage. 3994 */ 3995 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3996 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3997 3998 /* Mute capture amp left and right */ 3999 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4000 /* Set ADC connection select to match default mixer setting - mic 4001 * (on mic1 pin) 4002 */ 4003 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 4004 4005 /* Do similar with the second ADC: mute capture input amp and 4006 * set ADC connection to mic to match ALSA's default state. 4007 */ 4008 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4009 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 4010 4011 /* Mute all inputs to mixer widget (even unconnected ones) */ 4012 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 4013 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 4014 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 4015 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 4016 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 4017 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 4018 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 4019 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 4020 4021 { } 4022}; 4023 4024static struct hda_verb alc260_will_verbs[] = { 4025 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4026 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, 4027 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, 4028 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4029 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, 4030 {0x1a, AC_VERB_SET_PROC_COEF, 0x3040}, 4031 {} 4032}; 4033 4034static struct hda_verb alc260_replacer_672v_verbs[] = { 4035 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4036 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, 4037 {0x1a, AC_VERB_SET_PROC_COEF, 0x3050}, 4038 4039 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 4040 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 4041 {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, 4042 4043 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 4044 {} 4045}; 4046 4047/* toggle speaker-output according to the hp-jack state */ 4048static void alc260_replacer_672v_automute(struct hda_codec *codec) 4049{ 4050 unsigned int present; 4051 4052 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */ 4053 present = snd_hda_codec_read(codec, 0x0f, 0, 4054 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 4055 if (present) { 4056 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1); 4057 snd_hda_codec_write(codec, 0x0f, 0, 4058 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); 4059 } else { 4060 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0); 4061 snd_hda_codec_write(codec, 0x0f, 0, 4062 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 4063 } 4064} 4065 4066static void alc260_replacer_672v_unsol_event(struct hda_codec *codec, 4067 unsigned int res) 4068{ 4069 if ((res >> 26) == ALC880_HP_EVENT) 4070 alc260_replacer_672v_automute(codec); 4071} 4072 4073/* Test configuration for debugging, modelled after the ALC880 test 4074 * configuration. 4075 */ 4076#ifdef CONFIG_SND_DEBUG 4077static hda_nid_t alc260_test_dac_nids[1] = { 4078 0x02, 4079}; 4080static hda_nid_t alc260_test_adc_nids[2] = { 4081 0x04, 0x05, 4082}; 4083/* For testing the ALC260, each input MUX needs its own definition since 4084 * the signal assignments are different. This assumes that the first ADC 4085 * is NID 0x04. 4086 */ 4087static struct hda_input_mux alc260_test_capture_sources[2] = { 4088 { 4089 .num_items = 7, 4090 .items = { 4091 { "MIC1 pin", 0x0 }, 4092 { "MIC2 pin", 0x1 }, 4093 { "LINE1 pin", 0x2 }, 4094 { "LINE2 pin", 0x3 }, 4095 { "CD pin", 0x4 }, 4096 { "LINE-OUT pin", 0x5 }, 4097 { "HP-OUT pin", 0x6 }, 4098 }, 4099 }, 4100 { 4101 .num_items = 8, 4102 .items = { 4103 { "MIC1 pin", 0x0 }, 4104 { "MIC2 pin", 0x1 }, 4105 { "LINE1 pin", 0x2 }, 4106 { "LINE2 pin", 0x3 }, 4107 { "CD pin", 0x4 }, 4108 { "Mixer", 0x5 }, 4109 { "LINE-OUT pin", 0x6 }, 4110 { "HP-OUT pin", 0x7 }, 4111 }, 4112 }, 4113}; 4114static struct snd_kcontrol_new alc260_test_mixer[] = { 4115 /* Output driver widgets */ 4116 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 4117 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), 4118 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT), 4119 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT), 4120 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), 4121 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), 4122 4123 /* Modes for retasking pin widgets 4124 * Note: the ALC260 doesn't seem to act on requests to enable mic 4125 * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't 4126 * mention this restriction. At this stage it's not clear whether 4127 * this behaviour is intentional or is a hardware bug in chip 4128 * revisions available at least up until early 2006. Therefore for 4129 * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all 4130 * choices, but if it turns out that the lack of mic bias for these 4131 * NIDs is intentional we could change their modes from 4132 * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. 4133 */ 4134 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), 4135 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), 4136 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), 4137 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT), 4138 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT), 4139 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT), 4140 4141 /* Loopback mixer controls */ 4142 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT), 4143 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT), 4144 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT), 4145 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT), 4146 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT), 4147 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT), 4148 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT), 4149 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), 4150 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 4151 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 4152 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 4153 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 4154 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), 4155 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), 4156 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), 4157 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT), 4158 4159 /* Controls for GPIO pins, assuming they are configured as outputs */ 4160 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), 4161 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), 4162 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), 4163 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), 4164 4165 /* Switches to allow the digital IO pins to be enabled. The datasheet 4166 * is ambigious as to which NID is which; testing on laptops which 4167 * make this output available should provide clarification. 4168 */ 4169 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01), 4170 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01), 4171 4172 { } /* end */ 4173}; 4174static struct hda_verb alc260_test_init_verbs[] = { 4175 /* Enable all GPIOs as outputs with an initial value of 0 */ 4176 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f}, 4177 {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, 4178 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f}, 4179 4180 /* Enable retasking pins as output, initially without power amp */ 4181 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4182 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4183 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4184 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4185 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4186 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4187 4188 /* Disable digital (SPDIF) pins initially, but users can enable 4189 * them via a mixer switch. In the case of SPDIF-out, this initverb 4190 * payload also sets the generation to 0, output to be in "consumer" 4191 * PCM format, copyright asserted, no pre-emphasis and no validity 4192 * control. 4193 */ 4194 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, 4195 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, 4196 4197 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the 4198 * OUT1 sum bus when acting as an output. 4199 */ 4200 {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, 4201 {0x0c, AC_VERB_SET_CONNECT_SEL, 0}, 4202 {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, 4203 {0x0e, AC_VERB_SET_CONNECT_SEL, 0}, 4204 4205 /* Start with output sum widgets muted and their output gains at min */ 4206 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4207 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4208 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4209 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4210 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4211 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4212 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4213 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4214 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4215 4216 /* Unmute retasking pin widget output buffers since the default 4217 * state appears to be output. As the pin mode is changed by the 4218 * user the pin mode control will take care of enabling the pin's 4219 * input/output buffers as needed. 4220 */ 4221 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4222 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4223 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4224 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4225 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4226 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4227 /* Also unmute the mono-out pin widget */ 4228 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4229 4230 /* Mute capture amp left and right */ 4231 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4232 /* Set ADC connection select to match default mixer setting (mic1 4233 * pin) 4234 */ 4235 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 4236 4237 /* Do the same for the second ADC: mute capture input amp and 4238 * set ADC connection to mic1 pin 4239 */ 4240 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4241 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 4242 4243 /* Mute all inputs to mixer widget (even unconnected ones) */ 4244 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 4245 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 4246 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 4247 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 4248 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 4249 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 4250 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 4251 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 4252 4253 { } 4254}; 4255#endif 4256 4257static struct hda_pcm_stream alc260_pcm_analog_playback = { 4258 .substreams = 1, 4259 .channels_min = 2, 4260 .channels_max = 2, 4261}; 4262 4263static struct hda_pcm_stream alc260_pcm_analog_capture = { 4264 .substreams = 1, 4265 .channels_min = 2, 4266 .channels_max = 2, 4267}; 4268 4269#define alc260_pcm_digital_playback alc880_pcm_digital_playback 4270#define alc260_pcm_digital_capture alc880_pcm_digital_capture 4271 4272/* 4273 * for BIOS auto-configuration 4274 */ 4275 4276static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid, 4277 const char *pfx) 4278{ 4279 hda_nid_t nid_vol; 4280 unsigned long vol_val, sw_val; 4281 char name[32]; 4282 int err; 4283 4284 if (nid >= 0x0f && nid < 0x11) { 4285 nid_vol = nid - 0x7; 4286 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT); 4287 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); 4288 } else if (nid == 0x11) { 4289 nid_vol = nid - 0x7; 4290 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT); 4291 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); 4292 } else if (nid >= 0x12 && nid <= 0x15) { 4293 nid_vol = 0x08; 4294 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT); 4295 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); 4296 } else 4297 return 0; /* N/A */ 4298 4299 snprintf(name, sizeof(name), "%s Playback Volume", pfx); 4300 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val); 4301 if (err < 0) 4302 return err; 4303 snprintf(name, sizeof(name), "%s Playback Switch", pfx); 4304 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val); 4305 if (err < 0) 4306 return err; 4307 return 1; 4308} 4309 4310/* add playback controls from the parsed DAC table */ 4311static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, 4312 const struct auto_pin_cfg *cfg) 4313{ 4314 hda_nid_t nid; 4315 int err; 4316 4317 spec->multiout.num_dacs = 1; 4318 spec->multiout.dac_nids = spec->private_dac_nids; 4319 spec->multiout.dac_nids[0] = 0x02; 4320 4321 nid = cfg->line_out_pins[0]; 4322 if (nid) { 4323 err = alc260_add_playback_controls(spec, nid, "Front"); 4324 if (err < 0) 4325 return err; 4326 } 4327 4328 nid = cfg->speaker_pins[0]; 4329 if (nid) { 4330 err = alc260_add_playback_controls(spec, nid, "Speaker"); 4331 if (err < 0) 4332 return err; 4333 } 4334 4335 nid = cfg->hp_pins[0]; 4336 if (nid) { 4337 err = alc260_add_playback_controls(spec, nid, "Headphone"); 4338 if (err < 0) 4339 return err; 4340 } 4341 return 0; 4342} 4343 4344/* create playback/capture controls for input pins */ 4345static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec, 4346 const struct auto_pin_cfg *cfg) 4347{ 4348 struct hda_input_mux *imux = &spec->private_imux; 4349 int i, err, idx; 4350 4351 for (i = 0; i < AUTO_PIN_LAST; i++) { 4352 if (cfg->input_pins[i] >= 0x12) { 4353 idx = cfg->input_pins[i] - 0x12; 4354 err = new_analog_input(spec, cfg->input_pins[i], 4355 auto_pin_cfg_labels[i], idx, 4356 0x07); 4357 if (err < 0) 4358 return err; 4359 imux->items[imux->num_items].label = 4360 auto_pin_cfg_labels[i]; 4361 imux->items[imux->num_items].index = idx; 4362 imux->num_items++; 4363 } 4364 if (cfg->input_pins[i] >= 0x0f && cfg->input_pins[i] <= 0x10){ 4365 idx = cfg->input_pins[i] - 0x09; 4366 err = new_analog_input(spec, cfg->input_pins[i], 4367 auto_pin_cfg_labels[i], idx, 4368 0x07); 4369 if (err < 0) 4370 return err; 4371 imux->items[imux->num_items].label = 4372 auto_pin_cfg_labels[i]; 4373 imux->items[imux->num_items].index = idx; 4374 imux->num_items++; 4375 } 4376 } 4377 return 0; 4378} 4379 4380static void alc260_auto_set_output_and_unmute(struct hda_codec *codec, 4381 hda_nid_t nid, int pin_type, 4382 int sel_idx) 4383{ 4384 /* set as output */ 4385 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 4386 pin_type); 4387 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 4388 AMP_OUT_UNMUTE); 4389 /* need the manual connection? */ 4390 if (nid >= 0x12) { 4391 int idx = nid - 0x12; 4392 snd_hda_codec_write(codec, idx + 0x0b, 0, 4393 AC_VERB_SET_CONNECT_SEL, sel_idx); 4394 } 4395} 4396 4397static void alc260_auto_init_multi_out(struct hda_codec *codec) 4398{ 4399 struct alc_spec *spec = codec->spec; 4400 hda_nid_t nid; 4401 4402 alc_subsystem_id(codec, 0x10, 0x15, 0x0f); 4403 nid = spec->autocfg.line_out_pins[0]; 4404 if (nid) { 4405 int pin_type = get_pin_type(spec->autocfg.line_out_type); 4406 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0); 4407 } 4408 4409 nid = spec->autocfg.speaker_pins[0]; 4410 if (nid) 4411 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); 4412 4413 nid = spec->autocfg.hp_pins[0]; 4414 if (nid) 4415 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0); 4416} 4417 4418#define ALC260_PIN_CD_NID 0x16 4419static void alc260_auto_init_analog_input(struct hda_codec *codec) 4420{ 4421 struct alc_spec *spec = codec->spec; 4422 int i; 4423 4424 for (i = 0; i < AUTO_PIN_LAST; i++) { 4425 hda_nid_t nid = spec->autocfg.input_pins[i]; 4426 if (nid >= 0x12) { 4427 snd_hda_codec_write(codec, nid, 0, 4428 AC_VERB_SET_PIN_WIDGET_CONTROL, 4429 i <= AUTO_PIN_FRONT_MIC ? 4430 PIN_VREF80 : PIN_IN); 4431 if (nid != ALC260_PIN_CD_NID) 4432 snd_hda_codec_write(codec, nid, 0, 4433 AC_VERB_SET_AMP_GAIN_MUTE, 4434 AMP_OUT_MUTE); 4435 } 4436 } 4437} 4438 4439/* 4440 * generic initialization of ADC, input mixers and output mixers 4441 */ 4442static struct hda_verb alc260_volume_init_verbs[] = { 4443 /* 4444 * Unmute ADC0-1 and set the default input to mic-in 4445 */ 4446 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 4447 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4448 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 4449 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4450 4451 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 4452 * mixer widget 4453 * Note: PASD motherboards uses the Line In 2 as the input for 4454 * front panel mic (mic 2) 4455 */ 4456 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 4457 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4458 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4459 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 4460 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 4461 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 4462 4463 /* 4464 * Set up output mixers (0x08 - 0x0a) 4465 */ 4466 /* set vol=0 to output mixers */ 4467 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4468 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4469 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4470 /* set up input amps for analog loopback */ 4471 /* Amp Indices: DAC = 0, mixer = 1 */ 4472 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4473 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4474 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4475 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4476 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4477 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4478 4479 { } 4480}; 4481 4482static int alc260_parse_auto_config(struct hda_codec *codec) 4483{ 4484 struct alc_spec *spec = codec->spec; 4485 unsigned int wcap; 4486 int err; 4487 static hda_nid_t alc260_ignore[] = { 0x17, 0 }; 4488 4489 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 4490 alc260_ignore); 4491 if (err < 0) 4492 return err; 4493 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); 4494 if (err < 0) 4495 return err; 4496 if (!spec->kctl_alloc) 4497 return 0; /* can't find valid BIOS pin config */ 4498 err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); 4499 if (err < 0) 4500 return err; 4501 4502 spec->multiout.max_channels = 2; 4503 4504 if (spec->autocfg.dig_out_pin) 4505 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; 4506 if (spec->kctl_alloc) 4507 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 4508 4509 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; 4510 4511 spec->num_mux_defs = 1; 4512 spec->input_mux = &spec->private_imux; 4513 4514 /* check whether NID 0x04 is valid */ 4515 wcap = get_wcaps(codec, 0x04); 4516 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ 4517 if (wcap != AC_WID_AUD_IN) { 4518 spec->adc_nids = alc260_adc_nids_alt; 4519 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt); 4520 spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer; 4521 } else { 4522 spec->adc_nids = alc260_adc_nids; 4523 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); 4524 spec->mixers[spec->num_mixers] = alc260_capture_mixer; 4525 } 4526 spec->num_mixers++; 4527 4528 return 1; 4529} 4530 4531/* additional initialization for auto-configuration model */ 4532static void alc260_auto_init(struct hda_codec *codec) 4533{ 4534 alc260_auto_init_multi_out(codec); 4535 alc260_auto_init_analog_input(codec); 4536} 4537 4538/* 4539 * ALC260 configurations 4540 */ 4541static const char *alc260_models[ALC260_MODEL_LAST] = { 4542 [ALC260_BASIC] = "basic", 4543 [ALC260_HP] = "hp", 4544 [ALC260_HP_3013] = "hp-3013", 4545 [ALC260_FUJITSU_S702X] = "fujitsu", 4546 [ALC260_ACER] = "acer", 4547 [ALC260_WILL] = "will", 4548 [ALC260_REPLACER_672V] = "replacer", 4549#ifdef CONFIG_SND_DEBUG 4550 [ALC260_TEST] = "test", 4551#endif 4552 [ALC260_AUTO] = "auto", 4553}; 4554 4555static struct snd_pci_quirk alc260_cfg_tbl[] = { 4556 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), 4557 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), 4558 SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013), 4559 SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013), 4560 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013), 4561 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP), 4562 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013), 4563 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013), 4564 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP), 4565 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP), 4566 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP), 4567 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC), 4568 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC), 4569 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), 4570 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), 4571 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), 4572 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL), 4573 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V), 4574 {} 4575}; 4576 4577static struct alc_config_preset alc260_presets[] = { 4578 [ALC260_BASIC] = { 4579 .mixers = { alc260_base_output_mixer, 4580 alc260_input_mixer, 4581 alc260_pc_beep_mixer, 4582 alc260_capture_mixer }, 4583 .init_verbs = { alc260_init_verbs }, 4584 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4585 .dac_nids = alc260_dac_nids, 4586 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), 4587 .adc_nids = alc260_adc_nids, 4588 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4589 .channel_mode = alc260_modes, 4590 .input_mux = &alc260_capture_source, 4591 }, 4592 [ALC260_HP] = { 4593 .mixers = { alc260_base_output_mixer, 4594 alc260_input_mixer, 4595 alc260_capture_alt_mixer }, 4596 .init_verbs = { alc260_init_verbs }, 4597 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4598 .dac_nids = alc260_dac_nids, 4599 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), 4600 .adc_nids = alc260_hp_adc_nids, 4601 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4602 .channel_mode = alc260_modes, 4603 .input_mux = &alc260_capture_source, 4604 }, 4605 [ALC260_HP_3013] = { 4606 .mixers = { alc260_hp_3013_mixer, 4607 alc260_input_mixer, 4608 alc260_capture_alt_mixer }, 4609 .init_verbs = { alc260_hp_3013_init_verbs }, 4610 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4611 .dac_nids = alc260_dac_nids, 4612 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), 4613 .adc_nids = alc260_hp_adc_nids, 4614 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4615 .channel_mode = alc260_modes, 4616 .input_mux = &alc260_capture_source, 4617 }, 4618 [ALC260_FUJITSU_S702X] = { 4619 .mixers = { alc260_fujitsu_mixer, 4620 alc260_capture_mixer }, 4621 .init_verbs = { alc260_fujitsu_init_verbs }, 4622 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4623 .dac_nids = alc260_dac_nids, 4624 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), 4625 .adc_nids = alc260_dual_adc_nids, 4626 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4627 .channel_mode = alc260_modes, 4628 .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources), 4629 .input_mux = alc260_fujitsu_capture_sources, 4630 }, 4631 [ALC260_ACER] = { 4632 .mixers = { alc260_acer_mixer, 4633 alc260_capture_mixer }, 4634 .init_verbs = { alc260_acer_init_verbs }, 4635 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4636 .dac_nids = alc260_dac_nids, 4637 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), 4638 .adc_nids = alc260_dual_adc_nids, 4639 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4640 .channel_mode = alc260_modes, 4641 .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), 4642 .input_mux = alc260_acer_capture_sources, 4643 }, 4644 [ALC260_WILL] = { 4645 .mixers = { alc260_will_mixer, 4646 alc260_capture_mixer }, 4647 .init_verbs = { alc260_init_verbs, alc260_will_verbs }, 4648 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4649 .dac_nids = alc260_dac_nids, 4650 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), 4651 .adc_nids = alc260_adc_nids, 4652 .dig_out_nid = ALC260_DIGOUT_NID, 4653 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4654 .channel_mode = alc260_modes, 4655 .input_mux = &alc260_capture_source, 4656 }, 4657 [ALC260_REPLACER_672V] = { 4658 .mixers = { alc260_replacer_672v_mixer, 4659 alc260_capture_mixer }, 4660 .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, 4661 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4662 .dac_nids = alc260_dac_nids, 4663 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), 4664 .adc_nids = alc260_adc_nids, 4665 .dig_out_nid = ALC260_DIGOUT_NID, 4666 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4667 .channel_mode = alc260_modes, 4668 .input_mux = &alc260_capture_source, 4669 .unsol_event = alc260_replacer_672v_unsol_event, 4670 .init_hook = alc260_replacer_672v_automute, 4671 }, 4672#ifdef CONFIG_SND_DEBUG 4673 [ALC260_TEST] = { 4674 .mixers = { alc260_test_mixer, 4675 alc260_capture_mixer }, 4676 .init_verbs = { alc260_test_init_verbs }, 4677 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), 4678 .dac_nids = alc260_test_dac_nids, 4679 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids), 4680 .adc_nids = alc260_test_adc_nids, 4681 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4682 .channel_mode = alc260_modes, 4683 .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources), 4684 .input_mux = alc260_test_capture_sources, 4685 }, 4686#endif 4687}; 4688 4689static int patch_alc260(struct hda_codec *codec) 4690{ 4691 struct alc_spec *spec; 4692 int err, board_config; 4693 4694 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 4695 if (spec == NULL) 4696 return -ENOMEM; 4697 4698 codec->spec = spec; 4699 4700 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST, 4701 alc260_models, 4702 alc260_cfg_tbl); 4703 if (board_config < 0) { 4704 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, " 4705 "trying auto-probe from BIOS...\n"); 4706 board_config = ALC260_AUTO; 4707 } 4708 4709 if (board_config == ALC260_AUTO) { 4710 /* automatic parse from the BIOS config */ 4711 err = alc260_parse_auto_config(codec); 4712 if (err < 0) { 4713 alc_free(codec); 4714 return err; 4715 } else if (!err) { 4716 printk(KERN_INFO 4717 "hda_codec: Cannot set up configuration " 4718 "from BIOS. Using base mode...\n"); 4719 board_config = ALC260_BASIC; 4720 } 4721 } 4722 4723 if (board_config != ALC260_AUTO) 4724 setup_preset(spec, &alc260_presets[board_config]); 4725 4726 spec->stream_name_analog = "ALC260 Analog"; 4727 spec->stream_analog_playback = &alc260_pcm_analog_playback; 4728 spec->stream_analog_capture = &alc260_pcm_analog_capture; 4729 4730 spec->stream_name_digital = "ALC260 Digital"; 4731 spec->stream_digital_playback = &alc260_pcm_digital_playback; 4732 spec->stream_digital_capture = &alc260_pcm_digital_capture; 4733 4734 codec->patch_ops = alc_patch_ops; 4735 if (board_config == ALC260_AUTO) 4736 spec->init_hook = alc260_auto_init; 4737 4738 return 0; 4739} 4740 4741 4742/* 4743 * ALC882 support 4744 * 4745 * ALC882 is almost identical with ALC880 but has cleaner and more flexible 4746 * configuration. Each pin widget can choose any input DACs and a mixer. 4747 * Each ADC is connected from a mixer of all inputs. This makes possible 4748 * 6-channel independent captures. 4749 * 4750 * In addition, an independent DAC for the multi-playback (not used in this 4751 * driver yet). 4752 */ 4753#define ALC882_DIGOUT_NID 0x06 4754#define ALC882_DIGIN_NID 0x0a 4755 4756static struct hda_channel_mode alc882_ch_modes[1] = { 4757 { 8, NULL } 4758}; 4759 4760static hda_nid_t alc882_dac_nids[4] = { 4761 /* front, rear, clfe, rear_surr */ 4762 0x02, 0x03, 0x04, 0x05 4763}; 4764 4765/* identical with ALC880 */ 4766#define alc882_adc_nids alc880_adc_nids 4767#define alc882_adc_nids_alt alc880_adc_nids_alt 4768 4769/* input MUX */ 4770/* FIXME: should be a matrix-type input source selection */ 4771 4772static struct hda_input_mux alc882_capture_source = { 4773 .num_items = 4, 4774 .items = { 4775 { "Mic", 0x0 }, 4776 { "Front Mic", 0x1 }, 4777 { "Line", 0x2 }, 4778 { "CD", 0x4 }, 4779 }, 4780}; 4781#define alc882_mux_enum_info alc_mux_enum_info 4782#define alc882_mux_enum_get alc_mux_enum_get 4783 4784static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, 4785 struct snd_ctl_elem_value *ucontrol) 4786{ 4787 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 4788 struct alc_spec *spec = codec->spec; 4789 const struct hda_input_mux *imux = spec->input_mux; 4790 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 4791 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; 4792 hda_nid_t nid = capture_mixers[adc_idx]; 4793 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 4794 unsigned int i, idx; 4795 4796 idx = ucontrol->value.enumerated.item[0]; 4797 if (idx >= imux->num_items) 4798 idx = imux->num_items - 1; 4799 if (*cur_val == idx && !codec->in_resume) 4800 return 0; 4801 for (i = 0; i < imux->num_items; i++) { 4802 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 4803 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 4804 v | (imux->items[i].index << 8)); 4805 } 4806 *cur_val = idx; 4807 return 1; 4808} 4809 4810/* 4811 * 2ch mode 4812 */ 4813static struct hda_verb alc882_3ST_ch2_init[] = { 4814 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 4815 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 4816 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 4817 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 4818 { } /* end */ 4819}; 4820 4821/* 4822 * 6ch mode 4823 */ 4824static struct hda_verb alc882_3ST_ch6_init[] = { 4825 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4826 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 4827 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, 4828 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4829 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 4830 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, 4831 { } /* end */ 4832}; 4833 4834static struct hda_channel_mode alc882_3ST_6ch_modes[2] = { 4835 { 2, alc882_3ST_ch2_init }, 4836 { 6, alc882_3ST_ch6_init }, 4837}; 4838 4839/* 4840 * 6ch mode 4841 */ 4842static struct hda_verb alc882_sixstack_ch6_init[] = { 4843 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 4844 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4845 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4846 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4847 { } /* end */ 4848}; 4849 4850/* 4851 * 8ch mode 4852 */ 4853static struct hda_verb alc882_sixstack_ch8_init[] = { 4854 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4855 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4856 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4857 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4858 { } /* end */ 4859}; 4860 4861static struct hda_channel_mode alc882_sixstack_modes[2] = { 4862 { 6, alc882_sixstack_ch6_init }, 4863 { 8, alc882_sixstack_ch8_init }, 4864}; 4865 4866/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 4867 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 4868 */ 4869static struct snd_kcontrol_new alc882_base_mixer[] = { 4870 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4871 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 4872 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 4873 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 4874 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 4875 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 4876 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 4877 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 4878 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 4879 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 4880 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 4881 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4882 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4883 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4884 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4885 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4886 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 4887 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4888 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 4889 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 4890 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 4891 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 4892 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 4893 { } /* end */ 4894}; 4895 4896static struct snd_kcontrol_new alc882_w2jc_mixer[] = { 4897 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4898 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 4899 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4900 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4901 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4902 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4903 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4904 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 4905 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4906 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 4907 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 4908 { } /* end */ 4909}; 4910 4911static struct snd_kcontrol_new alc882_targa_mixer[] = { 4912 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4913 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 4914 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 4915 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4916 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4917 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4918 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4919 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4920 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4921 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 4922 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 4923 { } /* end */ 4924}; 4925 4926/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ??? 4927 * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c 4928 */ 4929static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = { 4930 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4931 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 4932 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 4933 HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT), 4934 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4935 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4936 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4937 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4938 HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT), 4939 HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT), 4940 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4941 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4942 { } /* end */ 4943}; 4944 4945static struct snd_kcontrol_new alc882_chmode_mixer[] = { 4946 { 4947 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4948 .name = "Channel Mode", 4949 .info = alc_ch_mode_info, 4950 .get = alc_ch_mode_get, 4951 .put = alc_ch_mode_put, 4952 }, 4953 { } /* end */ 4954}; 4955 4956static struct hda_verb alc882_init_verbs[] = { 4957 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 4958 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4959 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4960 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4961 /* Rear mixer */ 4962 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4963 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4964 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4965 /* CLFE mixer */ 4966 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4967 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4968 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4969 /* Side mixer */ 4970 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4971 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4972 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4973 4974 /* Front Pin: output 0 (0x0c) */ 4975 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4976 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4977 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 4978 /* Rear Pin: output 1 (0x0d) */ 4979 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4980 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4981 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 4982 /* CLFE Pin: output 2 (0x0e) */ 4983 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4984 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4985 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, 4986 /* Side Pin: output 3 (0x0f) */ 4987 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4988 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4989 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, 4990 /* Mic (rear) pin: input vref at 80% */ 4991 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4992 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4993 /* Front Mic pin: input vref at 80% */ 4994 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4995 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4996 /* Line In pin: input */ 4997 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4998 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4999 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 5000 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5001 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5002 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 5003 /* CD pin widget for input */ 5004 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 5005 5006 /* FIXME: use matrix-type input source selection */ 5007 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 5008 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 5009 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5010 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5011 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5012 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5013 /* Input mixer2 */ 5014 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5015 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5016 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5017 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5018 /* Input mixer3 */ 5019 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5020 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5021 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5022 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5023 /* ADC1: mute amp left and right */ 5024 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5025 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 5026 /* ADC2: mute amp left and right */ 5027 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5028 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 5029 /* ADC3: mute amp left and right */ 5030 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5031 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 5032 5033 { } 5034}; 5035 5036static struct hda_verb alc882_eapd_verbs[] = { 5037 /* change to EAPD mode */ 5038 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 5039 {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, 5040 { } 5041}; 5042 5043/* Mac Pro test */ 5044static struct snd_kcontrol_new alc882_macpro_mixer[] = { 5045 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5046 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5047 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT), 5048 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), 5049 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), 5050 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT), 5051 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT), 5052 { } /* end */ 5053}; 5054 5055static struct hda_verb alc882_macpro_init_verbs[] = { 5056 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 5057 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5058 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5059 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5060 /* Front Pin: output 0 (0x0c) */ 5061 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5062 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5063 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 5064 /* Front Mic pin: input vref at 80% */ 5065 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5066 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5067 /* Speaker: output */ 5068 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5069 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5070 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04}, 5071 /* Headphone output (output 0 - 0x0c) */ 5072 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5073 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5074 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, 5075 5076 /* FIXME: use matrix-type input source selection */ 5077 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 5078 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 5079 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5080 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5081 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5082 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5083 /* Input mixer2 */ 5084 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5085 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5086 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5087 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5088 /* Input mixer3 */ 5089 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5090 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5091 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5092 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5093 /* ADC1: mute amp left and right */ 5094 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5095 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 5096 /* ADC2: mute amp left and right */ 5097 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5098 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 5099 /* ADC3: mute amp left and right */ 5100 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5101 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 5102 5103 { } 5104}; 5105 5106/* iMac 24 mixer. */ 5107static struct snd_kcontrol_new alc885_imac24_mixer[] = { 5108 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT), 5109 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT), 5110 { } /* end */ 5111}; 5112 5113/* iMac 24 init verbs. */ 5114static struct hda_verb alc885_imac24_init_verbs[] = { 5115 /* Internal speakers: output 0 (0x0c) */ 5116 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5117 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5118 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, 5119 /* Internal speakers: output 0 (0x0c) */ 5120 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5121 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5122 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, 5123 /* Headphone: output 0 (0x0c) */ 5124 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5125 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5126 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 5127 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 5128 /* Front Mic: input vref at 80% */ 5129 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5130 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5131 { } 5132}; 5133 5134/* Toggle speaker-output according to the hp-jack state */ 5135static void alc885_imac24_automute(struct hda_codec *codec) 5136{ 5137 unsigned int present; 5138 5139 present = snd_hda_codec_read(codec, 0x14, 0, 5140 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 5141 snd_hda_codec_amp_update(codec, 0x18, 0, HDA_OUTPUT, 0, 5142 0x80, present ? 0x80 : 0); 5143 snd_hda_codec_amp_update(codec, 0x18, 1, HDA_OUTPUT, 0, 5144 0x80, present ? 0x80 : 0); 5145 snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, 5146 0x80, present ? 0x80 : 0); 5147 snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, 5148 0x80, present ? 0x80 : 0); 5149} 5150 5151/* Processes unsolicited events. */ 5152static void alc885_imac24_unsol_event(struct hda_codec *codec, 5153 unsigned int res) 5154{ 5155 /* Headphone insertion or removal. */ 5156 if ((res >> 26) == ALC880_HP_EVENT) 5157 alc885_imac24_automute(codec); 5158} 5159 5160static struct hda_verb alc882_targa_verbs[] = { 5161 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5162 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5163 5164 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5165 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5166 5167 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 5168 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ 5169 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 5170 5171 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 5172 {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 5173 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 5174 {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 5175 { } /* end */ 5176}; 5177 5178/* toggle speaker-output according to the hp-jack state */ 5179static void alc882_targa_automute(struct hda_codec *codec) 5180{ 5181 unsigned int present; 5182 5183 present = snd_hda_codec_read(codec, 0x14, 0, 5184 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 5185 snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, 5186 0x80, present ? 0x80 : 0); 5187 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, 5188 0x80, present ? 0x80 : 0); 5189 snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3); 5190} 5191 5192static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res) 5193{ 5194 /* Looks like the unsol event is incompatible with the standard 5195 * definition. 4bit tag is placed at 26 bit! 5196 */ 5197 if (((res >> 26) == ALC880_HP_EVENT)) { 5198 alc882_targa_automute(codec); 5199 } 5200} 5201 5202static struct hda_verb alc882_asus_a7j_verbs[] = { 5203 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5204 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5205 5206 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5207 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5208 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5209 5210 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ 5211 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 5212 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ 5213 5214 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 5215 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ 5216 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 5217 { } /* end */ 5218}; 5219 5220static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) 5221{ 5222 unsigned int gpiostate, gpiomask, gpiodir; 5223 5224 gpiostate = snd_hda_codec_read(codec, codec->afg, 0, 5225 AC_VERB_GET_GPIO_DATA, 0); 5226 5227 if (!muted) 5228 gpiostate |= (1 << pin); 5229 else 5230 gpiostate &= ~(1 << pin); 5231 5232 gpiomask = snd_hda_codec_read(codec, codec->afg, 0, 5233 AC_VERB_GET_GPIO_MASK, 0); 5234 gpiomask |= (1 << pin); 5235 5236 gpiodir = snd_hda_codec_read(codec, codec->afg, 0, 5237 AC_VERB_GET_GPIO_DIRECTION, 0); 5238 gpiodir |= (1 << pin); 5239 5240 5241 snd_hda_codec_write(codec, codec->afg, 0, 5242 AC_VERB_SET_GPIO_MASK, gpiomask); 5243 snd_hda_codec_write(codec, codec->afg, 0, 5244 AC_VERB_SET_GPIO_DIRECTION, gpiodir); 5245 5246 msleep(1); 5247 5248 snd_hda_codec_write(codec, codec->afg, 0, 5249 AC_VERB_SET_GPIO_DATA, gpiostate); 5250} 5251 5252/* 5253 * generic initialization of ADC, input mixers and output mixers 5254 */ 5255static struct hda_verb alc882_auto_init_verbs[] = { 5256 /* 5257 * Unmute ADC0-2 and set the default input to mic-in 5258 */ 5259 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 5260 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5261 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 5262 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5263 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 5264 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5265 5266 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 5267 * mixer widget 5268 * Note: PASD motherboards uses the Line In 2 as the input for 5269 * front panel mic (mic 2) 5270 */ 5271 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 5272 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5273 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5274 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 5275 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 5276 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 5277 5278 /* 5279 * Set up output mixers (0x0c - 0x0f) 5280 */ 5281 /* set vol=0 to output mixers */ 5282 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5283 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5284 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5285 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5286 /* set up input amps for analog loopback */ 5287 /* Amp Indices: DAC = 0, mixer = 1 */ 5288 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5289 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5290 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5291 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5292 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5293 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5294 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5295 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5296 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5297 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5298 5299 /* FIXME: use matrix-type input source selection */ 5300 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 5301 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 5302 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 5303 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 5304 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 5305 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 5306 /* Input mixer2 */ 5307 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 5308 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 5309 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 5310 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 5311 /* Input mixer3 */ 5312 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 5313 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 5314 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 5315 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 5316 5317 { } 5318}; 5319 5320/* capture mixer elements */ 5321static struct snd_kcontrol_new alc882_capture_alt_mixer[] = { 5322 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5323 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5324 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5325 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5326 { 5327 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5328 /* The multiple "Capture Source" controls confuse alsamixer 5329 * So call somewhat different.. 5330 * FIXME: the controls appear in the "playback" view! 5331 */ 5332 /* .name = "Capture Source", */ 5333 .name = "Input Source", 5334 .count = 2, 5335 .info = alc882_mux_enum_info, 5336 .get = alc882_mux_enum_get, 5337 .put = alc882_mux_enum_put, 5338 }, 5339 { } /* end */ 5340}; 5341 5342static struct snd_kcontrol_new alc882_capture_mixer[] = { 5343 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), 5344 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), 5345 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), 5346 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), 5347 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), 5348 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), 5349 { 5350 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5351 /* The multiple "Capture Source" controls confuse alsamixer 5352 * So call somewhat different.. 5353 * FIXME: the controls appear in the "playback" view! 5354 */ 5355 /* .name = "Capture Source", */ 5356 .name = "Input Source", 5357 .count = 3, 5358 .info = alc882_mux_enum_info, 5359 .get = alc882_mux_enum_get, 5360 .put = alc882_mux_enum_put, 5361 }, 5362 { } /* end */ 5363}; 5364 5365/* pcm configuration: identiacal with ALC880 */ 5366#define alc882_pcm_analog_playback alc880_pcm_analog_playback 5367#define alc882_pcm_analog_capture alc880_pcm_analog_capture 5368#define alc882_pcm_digital_playback alc880_pcm_digital_playback 5369#define alc882_pcm_digital_capture alc880_pcm_digital_capture 5370 5371/* 5372 * configuration and preset 5373 */ 5374static const char *alc882_models[ALC882_MODEL_LAST] = { 5375 [ALC882_3ST_DIG] = "3stack-dig", 5376 [ALC882_6ST_DIG] = "6stack-dig", 5377 [ALC882_ARIMA] = "arima", 5378 [ALC882_W2JC] = "w2jc", 5379 [ALC885_MACPRO] = "macpro", 5380 [ALC885_IMAC24] = "imac24", 5381 [ALC882_AUTO] = "auto", 5382}; 5383 5384static struct snd_pci_quirk alc882_cfg_tbl[] = { 5385 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG), 5386 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG), 5387 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), 5388 SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ 5389 SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), 5390 SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), 5391 SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG), 5392 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), 5393 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), 5394 {} 5395}; 5396 5397static struct alc_config_preset alc882_presets[] = { 5398 [ALC882_3ST_DIG] = { 5399 .mixers = { alc882_base_mixer }, 5400 .init_verbs = { alc882_init_verbs }, 5401 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5402 .dac_nids = alc882_dac_nids, 5403 .dig_out_nid = ALC882_DIGOUT_NID, 5404 .dig_in_nid = ALC882_DIGIN_NID, 5405 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), 5406 .channel_mode = alc882_ch_modes, 5407 .need_dac_fix = 1, 5408 .input_mux = &alc882_capture_source, 5409 }, 5410 [ALC882_6ST_DIG] = { 5411 .mixers = { alc882_base_mixer, alc882_chmode_mixer }, 5412 .init_verbs = { alc882_init_verbs }, 5413 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5414 .dac_nids = alc882_dac_nids, 5415 .dig_out_nid = ALC882_DIGOUT_NID, 5416 .dig_in_nid = ALC882_DIGIN_NID, 5417 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), 5418 .channel_mode = alc882_sixstack_modes, 5419 .input_mux = &alc882_capture_source, 5420 }, 5421 [ALC882_ARIMA] = { 5422 .mixers = { alc882_base_mixer, alc882_chmode_mixer }, 5423 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs }, 5424 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5425 .dac_nids = alc882_dac_nids, 5426 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), 5427 .channel_mode = alc882_sixstack_modes, 5428 .input_mux = &alc882_capture_source, 5429 }, 5430 [ALC882_W2JC] = { 5431 .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer }, 5432 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, 5433 alc880_gpio1_init_verbs }, 5434 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5435 .dac_nids = alc882_dac_nids, 5436 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 5437 .channel_mode = alc880_threestack_modes, 5438 .need_dac_fix = 1, 5439 .input_mux = &alc882_capture_source, 5440 .dig_out_nid = ALC882_DIGOUT_NID, 5441 }, 5442 [ALC885_MACPRO] = { 5443 .mixers = { alc882_macpro_mixer }, 5444 .init_verbs = { alc882_macpro_init_verbs }, 5445 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5446 .dac_nids = alc882_dac_nids, 5447 .dig_out_nid = ALC882_DIGOUT_NID, 5448 .dig_in_nid = ALC882_DIGIN_NID, 5449 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), 5450 .channel_mode = alc882_ch_modes, 5451 .input_mux = &alc882_capture_source, 5452 }, 5453 [ALC885_IMAC24] = { 5454 .mixers = { alc885_imac24_mixer }, 5455 .init_verbs = { alc885_imac24_init_verbs }, 5456 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5457 .dac_nids = alc882_dac_nids, 5458 .dig_out_nid = ALC882_DIGOUT_NID, 5459 .dig_in_nid = ALC882_DIGIN_NID, 5460 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), 5461 .channel_mode = alc882_ch_modes, 5462 .input_mux = &alc882_capture_source, 5463 .unsol_event = alc885_imac24_unsol_event, 5464 .init_hook = alc885_imac24_automute, 5465 }, 5466 [ALC882_TARGA] = { 5467 .mixers = { alc882_targa_mixer, alc882_chmode_mixer, 5468 alc882_capture_mixer }, 5469 .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, 5470 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5471 .dac_nids = alc882_dac_nids, 5472 .dig_out_nid = ALC882_DIGOUT_NID, 5473 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), 5474 .adc_nids = alc882_adc_nids, 5475 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), 5476 .channel_mode = alc882_3ST_6ch_modes, 5477 .need_dac_fix = 1, 5478 .input_mux = &alc882_capture_source, 5479 .unsol_event = alc882_targa_unsol_event, 5480 .init_hook = alc882_targa_automute, 5481 }, 5482 [ALC882_ASUS_A7J] = { 5483 .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer, 5484 alc882_capture_mixer }, 5485 .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs}, 5486 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5487 .dac_nids = alc882_dac_nids, 5488 .dig_out_nid = ALC882_DIGOUT_NID, 5489 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), 5490 .adc_nids = alc882_adc_nids, 5491 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), 5492 .channel_mode = alc882_3ST_6ch_modes, 5493 .need_dac_fix = 1, 5494 .input_mux = &alc882_capture_source, 5495 }, 5496}; 5497 5498 5499/* 5500 * Pin config fixes 5501 */ 5502enum { 5503 PINFIX_ABIT_AW9D_MAX 5504}; 5505 5506static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { 5507 { 0x15, 0x01080104 }, /* side */ 5508 { 0x16, 0x01011012 }, /* rear */ 5509 { 0x17, 0x01016011 }, /* clfe */ 5510 { } 5511}; 5512 5513static const struct alc_pincfg *alc882_pin_fixes[] = { 5514 [PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix, 5515}; 5516 5517static struct snd_pci_quirk alc882_pinfix_tbl[] = { 5518 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), 5519 {} 5520}; 5521 5522/* 5523 * BIOS auto configuration 5524 */ 5525static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, 5526 hda_nid_t nid, int pin_type, 5527 int dac_idx) 5528{ 5529 /* set as output */ 5530 struct alc_spec *spec = codec->spec; 5531 int idx; 5532 5533 if (spec->multiout.dac_nids[dac_idx] == 0x25) 5534 idx = 4; 5535 else 5536 idx = spec->multiout.dac_nids[dac_idx] - 2; 5537 5538 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 5539 pin_type); 5540 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 5541 AMP_OUT_UNMUTE); 5542 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); 5543 5544} 5545 5546static void alc882_auto_init_multi_out(struct hda_codec *codec) 5547{ 5548 struct alc_spec *spec = codec->spec; 5549 int i; 5550 5551 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 5552 for (i = 0; i <= HDA_SIDE; i++) { 5553 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 5554 int pin_type = get_pin_type(spec->autocfg.line_out_type); 5555 if (nid) 5556 alc882_auto_set_output_and_unmute(codec, nid, pin_type, 5557 i); 5558 } 5559} 5560 5561static void alc882_auto_init_hp_out(struct hda_codec *codec) 5562{ 5563 struct alc_spec *spec = codec->spec; 5564 hda_nid_t pin; 5565 5566 pin = spec->autocfg.hp_pins[0]; 5567 if (pin) /* connect to front */ 5568 /* use dac 0 */ 5569 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 5570} 5571 5572#define alc882_is_input_pin(nid) alc880_is_input_pin(nid) 5573#define ALC882_PIN_CD_NID ALC880_PIN_CD_NID 5574 5575static void alc882_auto_init_analog_input(struct hda_codec *codec) 5576{ 5577 struct alc_spec *spec = codec->spec; 5578 int i; 5579 5580 for (i = 0; i < AUTO_PIN_LAST; i++) { 5581 hda_nid_t nid = spec->autocfg.input_pins[i]; 5582 if (alc882_is_input_pin(nid)) { 5583 snd_hda_codec_write(codec, nid, 0, 5584 AC_VERB_SET_PIN_WIDGET_CONTROL, 5585 i <= AUTO_PIN_FRONT_MIC ? 5586 PIN_VREF80 : PIN_IN); 5587 if (nid != ALC882_PIN_CD_NID) 5588 snd_hda_codec_write(codec, nid, 0, 5589 AC_VERB_SET_AMP_GAIN_MUTE, 5590 AMP_OUT_MUTE); 5591 } 5592 } 5593} 5594 5595/* almost identical with ALC880 parser... */ 5596static int alc882_parse_auto_config(struct hda_codec *codec) 5597{ 5598 struct alc_spec *spec = codec->spec; 5599 int err = alc880_parse_auto_config(codec); 5600 5601 if (err < 0) 5602 return err; 5603 else if (err > 0) 5604 /* hack - override the init verbs */ 5605 spec->init_verbs[0] = alc882_auto_init_verbs; 5606 return err; 5607} 5608 5609/* additional initialization for auto-configuration model */ 5610static void alc882_auto_init(struct hda_codec *codec) 5611{ 5612 alc882_auto_init_multi_out(codec); 5613 alc882_auto_init_hp_out(codec); 5614 alc882_auto_init_analog_input(codec); 5615} 5616 5617static int patch_alc882(struct hda_codec *codec) 5618{ 5619 struct alc_spec *spec; 5620 int err, board_config; 5621 5622 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 5623 if (spec == NULL) 5624 return -ENOMEM; 5625 5626 codec->spec = spec; 5627 5628 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST, 5629 alc882_models, 5630 alc882_cfg_tbl); 5631 5632 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) { 5633 /* Pick up systems that don't supply PCI SSID */ 5634 switch (codec->subsystem_id) { 5635 case 0x106b0c00: /* Mac Pro */ 5636 board_config = ALC885_MACPRO; 5637 break; 5638 case 0x106b1000: /* iMac 24 */ 5639 board_config = ALC885_IMAC24; 5640 break; 5641 default: 5642 printk(KERN_INFO "hda_codec: Unknown model for ALC882, " 5643 "trying auto-probe from BIOS...\n"); 5644 board_config = ALC882_AUTO; 5645 } 5646 } 5647 5648 alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes); 5649 5650 if (board_config == ALC882_AUTO) { 5651 /* automatic parse from the BIOS config */ 5652 err = alc882_parse_auto_config(codec); 5653 if (err < 0) { 5654 alc_free(codec); 5655 return err; 5656 } else if (!err) { 5657 printk(KERN_INFO 5658 "hda_codec: Cannot set up configuration " 5659 "from BIOS. Using base mode...\n"); 5660 board_config = ALC882_3ST_DIG; 5661 } 5662 } 5663 5664 if (board_config != ALC882_AUTO) 5665 setup_preset(spec, &alc882_presets[board_config]); 5666 5667 if (board_config == ALC885_MACPRO || board_config == ALC885_IMAC24) { 5668 alc882_gpio_mute(codec, 0, 0); 5669 alc882_gpio_mute(codec, 1, 0); 5670 } 5671 5672 spec->stream_name_analog = "ALC882 Analog"; 5673 spec->stream_analog_playback = &alc882_pcm_analog_playback; 5674 spec->stream_analog_capture = &alc882_pcm_analog_capture; 5675 5676 spec->stream_name_digital = "ALC882 Digital"; 5677 spec->stream_digital_playback = &alc882_pcm_digital_playback; 5678 spec->stream_digital_capture = &alc882_pcm_digital_capture; 5679 5680 if (!spec->adc_nids && spec->input_mux) { 5681 /* check whether NID 0x07 is valid */ 5682 unsigned int wcap = get_wcaps(codec, 0x07); 5683 /* get type */ 5684 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 5685 if (wcap != AC_WID_AUD_IN) { 5686 spec->adc_nids = alc882_adc_nids_alt; 5687 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); 5688 spec->mixers[spec->num_mixers] = 5689 alc882_capture_alt_mixer; 5690 spec->num_mixers++; 5691 } else { 5692 spec->adc_nids = alc882_adc_nids; 5693 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); 5694 spec->mixers[spec->num_mixers] = alc882_capture_mixer; 5695 spec->num_mixers++; 5696 } 5697 } 5698 5699 codec->patch_ops = alc_patch_ops; 5700 if (board_config == ALC882_AUTO) 5701 spec->init_hook = alc882_auto_init; 5702 5703 return 0; 5704} 5705 5706/* 5707 * ALC883 support 5708 * 5709 * ALC883 is almost identical with ALC880 but has cleaner and more flexible 5710 * configuration. Each pin widget can choose any input DACs and a mixer. 5711 * Each ADC is connected from a mixer of all inputs. This makes possible 5712 * 6-channel independent captures. 5713 * 5714 * In addition, an independent DAC for the multi-playback (not used in this 5715 * driver yet). 5716 */ 5717#define ALC883_DIGOUT_NID 0x06 5718#define ALC883_DIGIN_NID 0x0a 5719 5720static hda_nid_t alc883_dac_nids[4] = { 5721 /* front, rear, clfe, rear_surr */ 5722 0x02, 0x04, 0x03, 0x05 5723}; 5724 5725static hda_nid_t alc883_adc_nids[2] = { 5726 /* ADC1-2 */ 5727 0x08, 0x09, 5728}; 5729 5730/* input MUX */ 5731/* FIXME: should be a matrix-type input source selection */ 5732 5733static struct hda_input_mux alc883_capture_source = { 5734 .num_items = 4, 5735 .items = { 5736 { "Mic", 0x0 }, 5737 { "Front Mic", 0x1 }, 5738 { "Line", 0x2 }, 5739 { "CD", 0x4 }, 5740 }, 5741}; 5742 5743static struct hda_input_mux alc883_lenovo_101e_capture_source = { 5744 .num_items = 2, 5745 .items = { 5746 { "Mic", 0x1 }, 5747 { "Line", 0x2 }, 5748 }, 5749}; 5750 5751static struct hda_input_mux alc883_lenovo_nb0763_capture_source = { 5752 .num_items = 4, 5753 .items = { 5754 { "Mic", 0x0 }, 5755 { "iMic", 0x1 }, 5756 { "Line", 0x2 }, 5757 { "CD", 0x4 }, 5758 }, 5759}; 5760 5761#define alc883_mux_enum_info alc_mux_enum_info 5762#define alc883_mux_enum_get alc_mux_enum_get 5763 5764static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, 5765 struct snd_ctl_elem_value *ucontrol) 5766{ 5767 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 5768 struct alc_spec *spec = codec->spec; 5769 const struct hda_input_mux *imux = spec->input_mux; 5770 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 5771 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; 5772 hda_nid_t nid = capture_mixers[adc_idx]; 5773 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 5774 unsigned int i, idx; 5775 5776 idx = ucontrol->value.enumerated.item[0]; 5777 if (idx >= imux->num_items) 5778 idx = imux->num_items - 1; 5779 if (*cur_val == idx && !codec->in_resume) 5780 return 0; 5781 for (i = 0; i < imux->num_items; i++) { 5782 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 5783 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 5784 v | (imux->items[i].index << 8)); 5785 } 5786 *cur_val = idx; 5787 return 1; 5788} 5789 5790/* 5791 * 2ch mode 5792 */ 5793static struct hda_channel_mode alc883_3ST_2ch_modes[1] = { 5794 { 2, NULL } 5795}; 5796 5797/* 5798 * 2ch mode 5799 */ 5800static struct hda_verb alc883_3ST_ch2_init[] = { 5801 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 5802 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 5803 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 5804 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 5805 { } /* end */ 5806}; 5807 5808/* 5809 * 6ch mode 5810 */ 5811static struct hda_verb alc883_3ST_ch6_init[] = { 5812 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5813 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 5814 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, 5815 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5816 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 5817 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, 5818 { } /* end */ 5819}; 5820 5821static struct hda_channel_mode alc883_3ST_6ch_modes[2] = { 5822 { 2, alc883_3ST_ch2_init }, 5823 { 6, alc883_3ST_ch6_init }, 5824}; 5825 5826/* 5827 * 6ch mode 5828 */ 5829static struct hda_verb alc883_sixstack_ch6_init[] = { 5830 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 5831 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5832 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5833 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5834 { } /* end */ 5835}; 5836 5837/* 5838 * 8ch mode 5839 */ 5840static struct hda_verb alc883_sixstack_ch8_init[] = { 5841 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5842 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5843 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5844 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5845 { } /* end */ 5846}; 5847 5848static struct hda_channel_mode alc883_sixstack_modes[2] = { 5849 { 6, alc883_sixstack_ch6_init }, 5850 { 8, alc883_sixstack_ch8_init }, 5851}; 5852 5853static struct hda_verb alc883_medion_eapd_verbs[] = { 5854 /* eanable EAPD on medion laptop */ 5855 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 5856 {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, 5857 { } 5858}; 5859 5860/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 5861 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 5862 */ 5863 5864static struct snd_kcontrol_new alc883_base_mixer[] = { 5865 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5866 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5867 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 5868 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 5869 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 5870 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 5871 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 5872 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 5873 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 5874 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 5875 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5876 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5877 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5878 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5879 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5880 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5881 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5882 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5883 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5884 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 5885 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5886 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5887 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5888 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5889 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5890 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5891 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5892 { 5893 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5894 /* .name = "Capture Source", */ 5895 .name = "Input Source", 5896 .count = 2, 5897 .info = alc883_mux_enum_info, 5898 .get = alc883_mux_enum_get, 5899 .put = alc883_mux_enum_put, 5900 }, 5901 { } /* end */ 5902}; 5903 5904static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { 5905 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5906 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5907 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5908 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5909 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5910 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5911 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5912 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5913 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5914 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5915 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5916 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 5917 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5918 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5919 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5920 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5921 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5922 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5923 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5924 { 5925 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5926 /* .name = "Capture Source", */ 5927 .name = "Input Source", 5928 .count = 2, 5929 .info = alc883_mux_enum_info, 5930 .get = alc883_mux_enum_get, 5931 .put = alc883_mux_enum_put, 5932 }, 5933 { } /* end */ 5934}; 5935 5936static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { 5937 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5938 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5939 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 5940 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 5941 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 5942 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 5943 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 5944 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 5945 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5946 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5947 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5948 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5949 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5950 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5951 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5952 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5953 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5954 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 5955 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5956 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5957 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5958 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5959 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5960 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5961 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5962 { 5963 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5964 /* .name = "Capture Source", */ 5965 .name = "Input Source", 5966 .count = 2, 5967 .info = alc883_mux_enum_info, 5968 .get = alc883_mux_enum_get, 5969 .put = alc883_mux_enum_put, 5970 }, 5971 { } /* end */ 5972}; 5973 5974static struct snd_kcontrol_new alc883_fivestack_mixer[] = { 5975 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5976 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 5977 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 5978 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), 5979 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 5980 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 5981 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), 5982 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 5983 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5984 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5985 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5986 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5987 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5988 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5989 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5990 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5991 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5992 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 5993 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5994 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5995 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5996 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5997 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5998 5999 { 6000 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6001 /* .name = "Capture Source", */ 6002 .name = "Input Source", 6003 .count = 1, 6004 .info = alc883_mux_enum_info, 6005 .get = alc883_mux_enum_get, 6006 .put = alc883_mux_enum_put, 6007 }, 6008 { } /* end */ 6009}; 6010 6011static struct snd_kcontrol_new alc883_tagra_mixer[] = { 6012 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6013 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6014 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6015 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 6016 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 6017 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 6018 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 6019 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 6020 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 6021 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6022 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6023 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6024 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6025 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6026 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6027 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6028 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6029 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6030 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6031 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6032 { 6033 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6034 /* .name = "Capture Source", */ 6035 .name = "Input Source", 6036 .count = 2, 6037 .info = alc883_mux_enum_info, 6038 .get = alc883_mux_enum_get, 6039 .put = alc883_mux_enum_put, 6040 }, 6041 { } /* end */ 6042}; 6043 6044static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { 6045 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6046 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6047 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6048 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6049 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6050 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6051 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6052 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6053 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6054 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6055 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6056 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6057 { 6058 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6059 /* .name = "Capture Source", */ 6060 .name = "Input Source", 6061 .count = 2, 6062 .info = alc883_mux_enum_info, 6063 .get = alc883_mux_enum_get, 6064 .put = alc883_mux_enum_put, 6065 }, 6066 { } /* end */ 6067}; 6068 6069static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = { 6070 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6071 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 6072 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 6073 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), 6074 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6075 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6076 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6077 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6078 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6079 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6080 { 6081 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6082 /* .name = "Capture Source", */ 6083 .name = "Input Source", 6084 .count = 1, 6085 .info = alc883_mux_enum_info, 6086 .get = alc883_mux_enum_get, 6087 .put = alc883_mux_enum_put, 6088 }, 6089 { } /* end */ 6090}; 6091 6092static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = { 6093 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6094 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT), 6095 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6096 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6097 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6098 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6099 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6100 HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6101 HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6102 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6103 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6104 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6105 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6106 { 6107 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6108 /* .name = "Capture Source", */ 6109 .name = "Input Source", 6110 .count = 2, 6111 .info = alc883_mux_enum_info, 6112 .get = alc883_mux_enum_get, 6113 .put = alc883_mux_enum_put, 6114 }, 6115 { } /* end */ 6116}; 6117 6118static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { 6119 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6120 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6121 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), 6122 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6123 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6124 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6125 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6126 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6127 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6128 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6129 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6130 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6131 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6132 { 6133 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6134 /* .name = "Capture Source", */ 6135 .name = "Input Source", 6136 .count = 2, 6137 .info = alc883_mux_enum_info, 6138 .get = alc883_mux_enum_get, 6139 .put = alc883_mux_enum_put, 6140 }, 6141 { } /* end */ 6142}; 6143 6144static struct snd_kcontrol_new alc888_6st_hp_mixer[] = { 6145 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6146 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 6147 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT), 6148 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT), 6149 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), 6150 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), 6151 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), 6152 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), 6153 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 6154 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 6155 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6156 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6157 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6158 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6159 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6160 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6161 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6162 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6163 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6164 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 6165 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6166 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 6167 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 6168 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6169 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6170 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6171 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6172 { 6173 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6174 /* .name = "Capture Source", */ 6175 .name = "Input Source", 6176 .count = 2, 6177 .info = alc883_mux_enum_info, 6178 .get = alc883_mux_enum_get, 6179 .put = alc883_mux_enum_put, 6180 }, 6181 { } /* end */ 6182}; 6183 6184static struct snd_kcontrol_new alc888_3st_hp_mixer[] = { 6185 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6186 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 6187 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT), 6188 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT), 6189 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), 6190 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), 6191 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), 6192 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), 6193 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6194 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6195 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6196 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6197 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6198 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6199 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6200 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6201 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6202 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 6203 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6204 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 6205 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 6206 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6207 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6208 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6209 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6210 { 6211 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6212 /* .name = "Capture Source", */ 6213 .name = "Input Source", 6214 .count = 2, 6215 .info = alc883_mux_enum_info, 6216 .get = alc883_mux_enum_get, 6217 .put = alc883_mux_enum_put, 6218 }, 6219 { } /* end */ 6220}; 6221 6222static struct snd_kcontrol_new alc883_chmode_mixer[] = { 6223 { 6224 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6225 .name = "Channel Mode", 6226 .info = alc_ch_mode_info, 6227 .get = alc_ch_mode_get, 6228 .put = alc_ch_mode_put, 6229 }, 6230 { } /* end */ 6231}; 6232 6233static struct hda_verb alc883_init_verbs[] = { 6234 /* ADC1: mute amp left and right */ 6235 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6236 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 6237 /* ADC2: mute amp left and right */ 6238 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6239 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 6240 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 6241 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6242 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6243 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6244 /* Rear mixer */ 6245 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6246 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6247 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6248 /* CLFE mixer */ 6249 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6250 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6251 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6252 /* Side mixer */ 6253 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6254 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6255 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6256 6257 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6258 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6259 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6260 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 6261 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6262 6263 /* Front Pin: output 0 (0x0c) */ 6264 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6265 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6266 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 6267 /* Rear Pin: output 1 (0x0d) */ 6268 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6269 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6270 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 6271 /* CLFE Pin: output 2 (0x0e) */ 6272 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6273 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6274 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, 6275 /* Side Pin: output 3 (0x0f) */ 6276 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6277 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6278 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, 6279 /* Mic (rear) pin: input vref at 80% */ 6280 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 6281 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 6282 /* Front Mic pin: input vref at 80% */ 6283 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 6284 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 6285 /* Line In pin: input */ 6286 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 6287 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 6288 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 6289 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6290 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6291 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 6292 /* CD pin widget for input */ 6293 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 6294 6295 /* FIXME: use matrix-type input source selection */ 6296 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 6297 /* Input mixer2 */ 6298 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6299 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6300 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6301 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6302 /* Input mixer3 */ 6303 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6304 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6305 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6306 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6307 { } 6308}; 6309 6310static struct hda_verb alc883_tagra_verbs[] = { 6311 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6312 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6313 6314 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6315 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6316 6317 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 6318 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ 6319 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 6320 6321 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6322 {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 6323 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 6324 {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 6325 6326 { } /* end */ 6327}; 6328 6329static struct hda_verb alc883_lenovo_101e_verbs[] = { 6330 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 6331 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN}, 6332 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN}, 6333 { } /* end */ 6334}; 6335 6336static struct hda_verb alc883_lenovo_nb0763_verbs[] = { 6337 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 6338 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6339 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6340 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6341 { } /* end */ 6342}; 6343 6344static struct hda_verb alc888_lenovo_ms7195_verbs[] = { 6345 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6346 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6347 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 6348 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN}, 6349 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6350 { } /* end */ 6351}; 6352 6353static struct hda_verb alc888_6st_hp_verbs[] = { 6354 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ 6355 {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */ 6356 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* CLFE : output 1 (0x0d) */ 6357 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, /* Side : output 3 (0x0f) */ 6358 { } 6359}; 6360 6361static struct hda_verb alc888_3st_hp_verbs[] = { 6362 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ 6363 {0x18, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */ 6364 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */ 6365 { } 6366}; 6367 6368static struct hda_verb alc888_3st_hp_2ch_init[] = { 6369 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 6370 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 6371 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 6372 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 6373 { } 6374}; 6375 6376static struct hda_verb alc888_3st_hp_6ch_init[] = { 6377 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 6378 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 6379 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 6380 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 6381 { } 6382}; 6383 6384static struct hda_channel_mode alc888_3st_hp_modes[2] = { 6385 { 2, alc888_3st_hp_2ch_init }, 6386 { 6, alc888_3st_hp_6ch_init }, 6387}; 6388 6389/* toggle front-jack and RCA according to the hp-jack state */ 6390static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec) 6391{ 6392 unsigned int present; 6393 6394 present = snd_hda_codec_read(codec, 0x1b, 0, 6395 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6396 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 6397 0x80, present ? 0x80 : 0); 6398 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 6399 0x80, present ? 0x80 : 0); 6400 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 6401 0x80, present ? 0x80 : 0); 6402 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 6403 0x80, present ? 0x80 : 0); 6404 6405} 6406 6407/* toggle RCA according to the front-jack state */ 6408static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec) 6409{ 6410 unsigned int present; 6411 6412 present = snd_hda_codec_read(codec, 0x14, 0, 6413 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6414 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 6415 0x80, present ? 0x80 : 0); 6416 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 6417 0x80, present ? 0x80 : 0); 6418 6419} 6420static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec, 6421 unsigned int res) 6422{ 6423 if ((res >> 26) == ALC880_HP_EVENT) 6424 alc888_lenovo_ms7195_front_automute(codec); 6425 if ((res >> 26) == ALC880_FRONT_EVENT) 6426 alc888_lenovo_ms7195_rca_automute(codec); 6427} 6428 6429static struct hda_verb alc883_medion_md2_verbs[] = { 6430 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6431 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6432 6433 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6434 6435 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6436 { } /* end */ 6437}; 6438 6439/* toggle speaker-output according to the hp-jack state */ 6440static void alc883_medion_md2_automute(struct hda_codec *codec) 6441{ 6442 unsigned int present; 6443 6444 present = snd_hda_codec_read(codec, 0x14, 0, 6445 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6446 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 6447 0x80, present ? 0x80 : 0); 6448 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 6449 0x80, present ? 0x80 : 0); 6450} 6451 6452static void alc883_medion_md2_unsol_event(struct hda_codec *codec, 6453 unsigned int res) 6454{ 6455 if ((res >> 26) == ALC880_HP_EVENT) 6456 alc883_medion_md2_automute(codec); 6457} 6458 6459/* toggle speaker-output according to the hp-jack state */ 6460static void alc883_tagra_automute(struct hda_codec *codec) 6461{ 6462 unsigned int present; 6463 unsigned char bits; 6464 6465 present = snd_hda_codec_read(codec, 0x14, 0, 6466 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6467 bits = present ? 0x80 : 0; 6468 snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, 6469 0x80, bits); 6470 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, 6471 0x80, bits); 6472 snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, 6473 present ? 1 : 3); 6474} 6475 6476static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) 6477{ 6478 if ((res >> 26) == ALC880_HP_EVENT) 6479 alc883_tagra_automute(codec); 6480} 6481 6482static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) 6483{ 6484 unsigned int present; 6485 unsigned char bits; 6486 6487 present = snd_hda_codec_read(codec, 0x14, 0, 6488 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6489 bits = present ? 0x80 : 0; 6490 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 6491 0x80, bits); 6492 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 6493 0x80, bits); 6494} 6495 6496static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) 6497{ 6498 unsigned int present; 6499 unsigned char bits; 6500 6501 present = snd_hda_codec_read(codec, 0x1b, 0, 6502 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6503 bits = present ? 0x80 : 0; 6504 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 6505 0x80, bits); 6506 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 6507 0x80, bits); 6508 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 6509 0x80, bits); 6510 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 6511 0x80, bits); 6512} 6513 6514static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, 6515 unsigned int res) 6516{ 6517 if ((res >> 26) == ALC880_HP_EVENT) 6518 alc883_lenovo_101e_all_automute(codec); 6519 if ((res >> 26) == ALC880_FRONT_EVENT) 6520 alc883_lenovo_101e_ispeaker_automute(codec); 6521} 6522 6523/* 6524 * generic initialization of ADC, input mixers and output mixers 6525 */ 6526static struct hda_verb alc883_auto_init_verbs[] = { 6527 /* 6528 * Unmute ADC0-2 and set the default input to mic-in 6529 */ 6530 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 6531 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6532 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 6533 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6534 6535 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 6536 * mixer widget 6537 * Note: PASD motherboards uses the Line In 2 as the input for 6538 * front panel mic (mic 2) 6539 */ 6540 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 6541 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6542 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6543 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6544 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 6545 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6546 6547 /* 6548 * Set up output mixers (0x0c - 0x0f) 6549 */ 6550 /* set vol=0 to output mixers */ 6551 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6552 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6553 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6554 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6555 /* set up input amps for analog loopback */ 6556 /* Amp Indices: DAC = 0, mixer = 1 */ 6557 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6558 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6559 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6560 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6561 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6562 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6563 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6564 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6565 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6566 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6567 6568 /* FIXME: use matrix-type input source selection */ 6569 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 6570 /* Input mixer1 */ 6571 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6572 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6573 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6574 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ 6575 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6576 /* Input mixer2 */ 6577 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6578 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6579 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6580 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ 6581 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6582 6583 { } 6584}; 6585 6586/* capture mixer elements */ 6587static struct snd_kcontrol_new alc883_capture_mixer[] = { 6588 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6589 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6590 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6591 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6592 { 6593 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6594 /* The multiple "Capture Source" controls confuse alsamixer 6595 * So call somewhat different.. 6596 * FIXME: the controls appear in the "playback" view! 6597 */ 6598 /* .name = "Capture Source", */ 6599 .name = "Input Source", 6600 .count = 2, 6601 .info = alc882_mux_enum_info, 6602 .get = alc882_mux_enum_get, 6603 .put = alc882_mux_enum_put, 6604 }, 6605 { } /* end */ 6606}; 6607 6608/* pcm configuration: identiacal with ALC880 */ 6609#define alc883_pcm_analog_playback alc880_pcm_analog_playback 6610#define alc883_pcm_analog_capture alc880_pcm_analog_capture 6611#define alc883_pcm_digital_playback alc880_pcm_digital_playback 6612#define alc883_pcm_digital_capture alc880_pcm_digital_capture 6613 6614/* 6615 * configuration and preset 6616 */ 6617static const char *alc883_models[ALC883_MODEL_LAST] = { 6618 [ALC883_3ST_2ch_DIG] = "3stack-dig", 6619 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig", 6620 [ALC883_3ST_6ch] = "3stack-6ch", 6621 [ALC883_6ST_DIG] = "6stack-dig", 6622 [ALC883_TARGA_DIG] = "targa-dig", 6623 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", 6624 [ALC883_ACER] = "acer", 6625 [ALC883_MEDION] = "medion", 6626 [ALC883_MEDION_MD2] = "medion-md2", 6627 [ALC883_LAPTOP_EAPD] = "laptop-eapd", 6628 [ALC883_LENOVO_101E_2ch] = "lenovo-101e", 6629 [ALC883_LENOVO_NB0763] = "lenovo-nb0763", 6630 [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", 6631 [ALC888_6ST_HP] = "6stack-hp", 6632 [ALC888_3ST_HP] = "3stack-hp", 6633 [ALC883_AUTO] = "auto", 6634}; 6635 6636static struct snd_pci_quirk alc883_cfg_tbl[] = { 6637 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), 6638 SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), 6639 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), 6640 SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), 6641 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), 6642 SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG), 6643 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG), 6644 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), 6645 SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG), 6646 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), 6647 SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), 6648 SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG), 6649 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG), 6650 SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG), 6651 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG), 6652 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG), 6653 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG), 6654 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG), 6655 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG), 6656 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG), 6657 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG), 6658 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG), 6659 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), 6660 SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), 6661 SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), 6662 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), 6663 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), 6664 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), 6665 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch), 6666 SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763), 6667 SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763), 6668 SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_6ST_HP), 6669 SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), 6670 SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), 6671 SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), 6672 {} 6673}; 6674 6675static struct alc_config_preset alc883_presets[] = { 6676 [ALC883_3ST_2ch_DIG] = { 6677 .mixers = { alc883_3ST_2ch_mixer }, 6678 .init_verbs = { alc883_init_verbs }, 6679 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6680 .dac_nids = alc883_dac_nids, 6681 .dig_out_nid = ALC883_DIGOUT_NID, 6682 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6683 .adc_nids = alc883_adc_nids, 6684 .dig_in_nid = ALC883_DIGIN_NID, 6685 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6686 .channel_mode = alc883_3ST_2ch_modes, 6687 .input_mux = &alc883_capture_source, 6688 }, 6689 [ALC883_3ST_6ch_DIG] = { 6690 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, 6691 .init_verbs = { alc883_init_verbs }, 6692 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6693 .dac_nids = alc883_dac_nids, 6694 .dig_out_nid = ALC883_DIGOUT_NID, 6695 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6696 .adc_nids = alc883_adc_nids, 6697 .dig_in_nid = ALC883_DIGIN_NID, 6698 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6699 .channel_mode = alc883_3ST_6ch_modes, 6700 .need_dac_fix = 1, 6701 .input_mux = &alc883_capture_source, 6702 }, 6703 [ALC883_3ST_6ch] = { 6704 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, 6705 .init_verbs = { alc883_init_verbs }, 6706 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6707 .dac_nids = alc883_dac_nids, 6708 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6709 .adc_nids = alc883_adc_nids, 6710 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6711 .channel_mode = alc883_3ST_6ch_modes, 6712 .need_dac_fix = 1, 6713 .input_mux = &alc883_capture_source, 6714 }, 6715 [ALC883_6ST_DIG] = { 6716 .mixers = { alc883_base_mixer, alc883_chmode_mixer }, 6717 .init_verbs = { alc883_init_verbs }, 6718 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6719 .dac_nids = alc883_dac_nids, 6720 .dig_out_nid = ALC883_DIGOUT_NID, 6721 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6722 .adc_nids = alc883_adc_nids, 6723 .dig_in_nid = ALC883_DIGIN_NID, 6724 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), 6725 .channel_mode = alc883_sixstack_modes, 6726 .input_mux = &alc883_capture_source, 6727 }, 6728 [ALC883_TARGA_DIG] = { 6729 .mixers = { alc883_tagra_mixer, alc883_chmode_mixer }, 6730 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, 6731 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6732 .dac_nids = alc883_dac_nids, 6733 .dig_out_nid = ALC883_DIGOUT_NID, 6734 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6735 .adc_nids = alc883_adc_nids, 6736 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6737 .channel_mode = alc883_3ST_6ch_modes, 6738 .need_dac_fix = 1, 6739 .input_mux = &alc883_capture_source, 6740 .unsol_event = alc883_tagra_unsol_event, 6741 .init_hook = alc883_tagra_automute, 6742 }, 6743 [ALC883_TARGA_2ch_DIG] = { 6744 .mixers = { alc883_tagra_2ch_mixer}, 6745 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, 6746 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6747 .dac_nids = alc883_dac_nids, 6748 .dig_out_nid = ALC883_DIGOUT_NID, 6749 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6750 .adc_nids = alc883_adc_nids, 6751 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6752 .channel_mode = alc883_3ST_2ch_modes, 6753 .input_mux = &alc883_capture_source, 6754 .unsol_event = alc883_tagra_unsol_event, 6755 .init_hook = alc883_tagra_automute, 6756 }, 6757 [ALC883_ACER] = { 6758 .mixers = { alc883_base_mixer, 6759 alc883_chmode_mixer }, 6760 /* On TravelMate laptops, GPIO 0 enables the internal speaker 6761 * and the headphone jack. Turn this on and rely on the 6762 * standard mute methods whenever the user wants to turn 6763 * these outputs off. 6764 */ 6765 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs }, 6766 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6767 .dac_nids = alc883_dac_nids, 6768 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6769 .adc_nids = alc883_adc_nids, 6770 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6771 .channel_mode = alc883_3ST_2ch_modes, 6772 .input_mux = &alc883_capture_source, 6773 }, 6774 [ALC883_MEDION] = { 6775 .mixers = { alc883_fivestack_mixer, 6776 alc883_chmode_mixer }, 6777 .init_verbs = { alc883_init_verbs, 6778 alc883_medion_eapd_verbs }, 6779 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6780 .dac_nids = alc883_dac_nids, 6781 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6782 .adc_nids = alc883_adc_nids, 6783 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), 6784 .channel_mode = alc883_sixstack_modes, 6785 .input_mux = &alc883_capture_source, 6786 }, 6787 [ALC883_MEDION_MD2] = { 6788 .mixers = { alc883_medion_md2_mixer}, 6789 .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs}, 6790 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6791 .dac_nids = alc883_dac_nids, 6792 .dig_out_nid = ALC883_DIGOUT_NID, 6793 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6794 .adc_nids = alc883_adc_nids, 6795 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6796 .channel_mode = alc883_3ST_2ch_modes, 6797 .input_mux = &alc883_capture_source, 6798 .unsol_event = alc883_medion_md2_unsol_event, 6799 .init_hook = alc883_medion_md2_automute, 6800 }, 6801 [ALC883_LAPTOP_EAPD] = { 6802 .mixers = { alc883_base_mixer, 6803 alc883_chmode_mixer }, 6804 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, 6805 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6806 .dac_nids = alc883_dac_nids, 6807 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6808 .adc_nids = alc883_adc_nids, 6809 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6810 .channel_mode = alc883_3ST_2ch_modes, 6811 .input_mux = &alc883_capture_source, 6812 }, 6813 [ALC883_LENOVO_101E_2ch] = { 6814 .mixers = { alc883_lenovo_101e_2ch_mixer}, 6815 .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs}, 6816 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6817 .dac_nids = alc883_dac_nids, 6818 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6819 .adc_nids = alc883_adc_nids, 6820 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6821 .channel_mode = alc883_3ST_2ch_modes, 6822 .input_mux = &alc883_lenovo_101e_capture_source, 6823 .unsol_event = alc883_lenovo_101e_unsol_event, 6824 .init_hook = alc883_lenovo_101e_all_automute, 6825 }, 6826 [ALC883_LENOVO_NB0763] = { 6827 .mixers = { alc883_lenovo_nb0763_mixer }, 6828 .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs}, 6829 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6830 .dac_nids = alc883_dac_nids, 6831 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6832 .adc_nids = alc883_adc_nids, 6833 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6834 .channel_mode = alc883_3ST_2ch_modes, 6835 .need_dac_fix = 1, 6836 .input_mux = &alc883_lenovo_nb0763_capture_source, 6837 .unsol_event = alc883_medion_md2_unsol_event, 6838 .init_hook = alc883_medion_md2_automute, 6839 }, 6840 [ALC888_LENOVO_MS7195_DIG] = { 6841 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, 6842 .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs}, 6843 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6844 .dac_nids = alc883_dac_nids, 6845 .dig_out_nid = ALC883_DIGOUT_NID, 6846 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6847 .adc_nids = alc883_adc_nids, 6848 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6849 .channel_mode = alc883_3ST_6ch_modes, 6850 .need_dac_fix = 1, 6851 .input_mux = &alc883_capture_source, 6852 .unsol_event = alc883_lenovo_ms7195_unsol_event, 6853 .init_hook = alc888_lenovo_ms7195_front_automute, 6854 }, 6855 [ALC888_6ST_HP] = { 6856 .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer }, 6857 .init_verbs = { alc883_init_verbs, alc888_6st_hp_verbs }, 6858 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6859 .dac_nids = alc883_dac_nids, 6860 .dig_out_nid = ALC883_DIGOUT_NID, 6861 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6862 .adc_nids = alc883_adc_nids, 6863 .dig_in_nid = ALC883_DIGIN_NID, 6864 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), 6865 .channel_mode = alc883_sixstack_modes, 6866 .input_mux = &alc883_capture_source, 6867 }, 6868 [ALC888_3ST_HP] = { 6869 .mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer }, 6870 .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs }, 6871 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6872 .dac_nids = alc883_dac_nids, 6873 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6874 .adc_nids = alc883_adc_nids, 6875 .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes), 6876 .channel_mode = alc888_3st_hp_modes, 6877 .need_dac_fix = 1, 6878 .input_mux = &alc883_capture_source, 6879 }, 6880}; 6881 6882 6883/* 6884 * BIOS auto configuration 6885 */ 6886static void alc883_auto_set_output_and_unmute(struct hda_codec *codec, 6887 hda_nid_t nid, int pin_type, 6888 int dac_idx) 6889{ 6890 /* set as output */ 6891 struct alc_spec *spec = codec->spec; 6892 int idx; 6893 6894 if (spec->multiout.dac_nids[dac_idx] == 0x25) 6895 idx = 4; 6896 else 6897 idx = spec->multiout.dac_nids[dac_idx] - 2; 6898 6899 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 6900 pin_type); 6901 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 6902 AMP_OUT_UNMUTE); 6903 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); 6904 6905} 6906 6907static void alc883_auto_init_multi_out(struct hda_codec *codec) 6908{ 6909 struct alc_spec *spec = codec->spec; 6910 int i; 6911 6912 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 6913 for (i = 0; i <= HDA_SIDE; i++) { 6914 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 6915 int pin_type = get_pin_type(spec->autocfg.line_out_type); 6916 if (nid) 6917 alc883_auto_set_output_and_unmute(codec, nid, pin_type, 6918 i); 6919 } 6920} 6921 6922static void alc883_auto_init_hp_out(struct hda_codec *codec) 6923{ 6924 struct alc_spec *spec = codec->spec; 6925 hda_nid_t pin; 6926 6927 pin = spec->autocfg.hp_pins[0]; 6928 if (pin) /* connect to front */ 6929 /* use dac 0 */ 6930 alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 6931} 6932 6933#define alc883_is_input_pin(nid) alc880_is_input_pin(nid) 6934#define ALC883_PIN_CD_NID ALC880_PIN_CD_NID 6935 6936static void alc883_auto_init_analog_input(struct hda_codec *codec) 6937{ 6938 struct alc_spec *spec = codec->spec; 6939 int i; 6940 6941 for (i = 0; i < AUTO_PIN_LAST; i++) { 6942 hda_nid_t nid = spec->autocfg.input_pins[i]; 6943 if (alc883_is_input_pin(nid)) { 6944 snd_hda_codec_write(codec, nid, 0, 6945 AC_VERB_SET_PIN_WIDGET_CONTROL, 6946 (i <= AUTO_PIN_FRONT_MIC ? 6947 PIN_VREF80 : PIN_IN)); 6948 if (nid != ALC883_PIN_CD_NID) 6949 snd_hda_codec_write(codec, nid, 0, 6950 AC_VERB_SET_AMP_GAIN_MUTE, 6951 AMP_OUT_MUTE); 6952 } 6953 } 6954} 6955 6956/* almost identical with ALC880 parser... */ 6957static int alc883_parse_auto_config(struct hda_codec *codec) 6958{ 6959 struct alc_spec *spec = codec->spec; 6960 int err = alc880_parse_auto_config(codec); 6961 6962 if (err < 0) 6963 return err; 6964 else if (err > 0) 6965 /* hack - override the init verbs */ 6966 spec->init_verbs[0] = alc883_auto_init_verbs; 6967 spec->mixers[spec->num_mixers] = alc883_capture_mixer; 6968 spec->num_mixers++; 6969 return err; 6970} 6971 6972/* additional initialization for auto-configuration model */ 6973static void alc883_auto_init(struct hda_codec *codec) 6974{ 6975 alc883_auto_init_multi_out(codec); 6976 alc883_auto_init_hp_out(codec); 6977 alc883_auto_init_analog_input(codec); 6978} 6979 6980static int patch_alc883(struct hda_codec *codec) 6981{ 6982 struct alc_spec *spec; 6983 int err, board_config; 6984 6985 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 6986 if (spec == NULL) 6987 return -ENOMEM; 6988 6989 codec->spec = spec; 6990 6991 board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST, 6992 alc883_models, 6993 alc883_cfg_tbl); 6994 if (board_config < 0) { 6995 printk(KERN_INFO "hda_codec: Unknown model for ALC883, " 6996 "trying auto-probe from BIOS...\n"); 6997 board_config = ALC883_AUTO; 6998 } 6999 7000 if (board_config == ALC883_AUTO) { 7001 /* automatic parse from the BIOS config */ 7002 err = alc883_parse_auto_config(codec); 7003 if (err < 0) { 7004 alc_free(codec); 7005 return err; 7006 } else if (!err) { 7007 printk(KERN_INFO 7008 "hda_codec: Cannot set up configuration " 7009 "from BIOS. Using base mode...\n"); 7010 board_config = ALC883_3ST_2ch_DIG; 7011 } 7012 } 7013 7014 if (board_config != ALC883_AUTO) 7015 setup_preset(spec, &alc883_presets[board_config]); 7016 7017 spec->stream_name_analog = "ALC883 Analog"; 7018 spec->stream_analog_playback = &alc883_pcm_analog_playback; 7019 spec->stream_analog_capture = &alc883_pcm_analog_capture; 7020 7021 spec->stream_name_digital = "ALC883 Digital"; 7022 spec->stream_digital_playback = &alc883_pcm_digital_playback; 7023 spec->stream_digital_capture = &alc883_pcm_digital_capture; 7024 7025 if (!spec->adc_nids && spec->input_mux) { 7026 spec->adc_nids = alc883_adc_nids; 7027 spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); 7028 } 7029 7030 codec->patch_ops = alc_patch_ops; 7031 if (board_config == ALC883_AUTO) 7032 spec->init_hook = alc883_auto_init; 7033 7034 return 0; 7035} 7036 7037/* 7038 * ALC262 support 7039 */ 7040 7041#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID 7042#define ALC262_DIGIN_NID ALC880_DIGIN_NID 7043 7044#define alc262_dac_nids alc260_dac_nids 7045#define alc262_adc_nids alc882_adc_nids 7046#define alc262_adc_nids_alt alc882_adc_nids_alt 7047 7048#define alc262_modes alc260_modes 7049#define alc262_capture_source alc882_capture_source 7050 7051static struct snd_kcontrol_new alc262_base_mixer[] = { 7052 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7053 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 7054 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7055 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7056 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 7057 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 7058 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7059 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7060 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7061 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7062 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7063 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 7064 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7065 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */ 7066 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), 7067 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7068 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 7069 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 7070 { } /* end */ 7071}; 7072 7073static struct snd_kcontrol_new alc262_hippo1_mixer[] = { 7074 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7075 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 7076 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7077 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7078 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 7079 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 7080 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7081 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7082 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7083 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7084 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7085 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 7086 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7087 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */ 7088 /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/ 7089 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 7090 { } /* end */ 7091}; 7092 7093static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { 7094 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7095 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7096 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 7097 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 7098 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 7099 7100 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7101 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7102 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7103 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7104 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7105 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 7106 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 7107 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 7108 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7109 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7110 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7111 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), 7112 HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT), 7113 HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT), 7114 { } /* end */ 7115}; 7116 7117static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = { 7118 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7119 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 7120 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 7121 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7122 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 7123 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 7124 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT), 7125 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT), 7126 HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT), 7127 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), 7128 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), 7129 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7130 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7131 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7132 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), 7133 { } /* end */ 7134}; 7135 7136static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = { 7137 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7138 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7139 HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT), 7140 { } /* end */ 7141}; 7142 7143static struct hda_bind_ctls alc262_sony_bind_sw = { 7144 .ops = &snd_hda_bind_sw, 7145 .values = { 7146 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT), 7147 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), 7148 0, 7149 }, 7150}; 7151 7152static struct snd_kcontrol_new alc262_sony_mixer[] = { 7153 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7154 HDA_BIND_SW("Front Playback Switch", &alc262_sony_bind_sw), 7155 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7156 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7157 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7158 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7159 { } /* end */ 7160}; 7161 7162static struct snd_kcontrol_new alc262_benq_t31_mixer[] = { 7163 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7164 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 7165 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7166 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7167 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7168 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7169 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7170 { } /* end */ 7171}; 7172 7173#define alc262_capture_mixer alc882_capture_mixer 7174#define alc262_capture_alt_mixer alc882_capture_alt_mixer 7175 7176/* 7177 * generic initialization of ADC, input mixers and output mixers 7178 */ 7179static struct hda_verb alc262_init_verbs[] = { 7180 /* 7181 * Unmute ADC0-2 and set the default input to mic-in 7182 */ 7183 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7184 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7185 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7186 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7187 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7188 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7189 7190 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7191 * mixer widget 7192 * Note: PASD motherboards uses the Line In 2 as the input for 7193 * front panel mic (mic 2) 7194 */ 7195 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7196 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7197 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7198 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 7199 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 7200 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 7201 7202 /* 7203 * Set up output mixers (0x0c - 0x0e) 7204 */ 7205 /* set vol=0 to output mixers */ 7206 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7207 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7208 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7209 /* set up input amps for analog loopback */ 7210 /* Amp Indices: DAC = 0, mixer = 1 */ 7211 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7212 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7213 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7214 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7215 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7216 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7217 7218 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 7219 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7220 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 7221 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7222 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7223 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7224 7225 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7226 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7227 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7228 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7229 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7230 7231 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 7232 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 7233 7234 /* FIXME: use matrix-type input source selection */ 7235 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7236 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7237 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7238 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7239 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7240 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7241 /* Input mixer2 */ 7242 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7243 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7244 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7245 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7246 /* Input mixer3 */ 7247 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7248 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7249 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7250 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7251 7252 { } 7253}; 7254 7255static struct hda_verb alc262_hippo_unsol_verbs[] = { 7256 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 7257 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7258 {} 7259}; 7260 7261static struct hda_verb alc262_hippo1_unsol_verbs[] = { 7262 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7263 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 7264 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7265 7266 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 7267 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7268 {} 7269}; 7270 7271static struct hda_verb alc262_sony_unsol_verbs[] = { 7272 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7273 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 7274 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic 7275 7276 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 7277 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7278}; 7279 7280/* mute/unmute internal speaker according to the hp jack and mute state */ 7281static void alc262_hippo_automute(struct hda_codec *codec) 7282{ 7283 struct alc_spec *spec = codec->spec; 7284 unsigned int mute; 7285 unsigned int present; 7286 7287 /* need to execute and sync at first */ 7288 snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); 7289 present = snd_hda_codec_read(codec, 0x15, 0, 7290 AC_VERB_GET_PIN_SENSE, 0); 7291 spec->jack_present = (present & 0x80000000) != 0; 7292 if (spec->jack_present) { 7293 /* mute internal speaker */ 7294 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7295 0x80, 0x80); 7296 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7297 0x80, 0x80); 7298 } else { 7299 /* unmute internal speaker if necessary */ 7300 mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0); 7301 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7302 0x80, mute & 0x80); 7303 mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0); 7304 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7305 0x80, mute & 0x80); 7306 } 7307} 7308 7309/* unsolicited event for HP jack sensing */ 7310static void alc262_hippo_unsol_event(struct hda_codec *codec, 7311 unsigned int res) 7312{ 7313 if ((res >> 26) != ALC880_HP_EVENT) 7314 return; 7315 alc262_hippo_automute(codec); 7316} 7317 7318static void alc262_hippo1_automute(struct hda_codec *codec) 7319{ 7320 unsigned int mute; 7321 unsigned int present; 7322 7323 snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); 7324 present = snd_hda_codec_read(codec, 0x1b, 0, 7325 AC_VERB_GET_PIN_SENSE, 0); 7326 present = (present & 0x80000000) != 0; 7327 if (present) { 7328 /* mute internal speaker */ 7329 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7330 0x80, 0x80); 7331 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7332 0x80, 0x80); 7333 } else { 7334 /* unmute internal speaker if necessary */ 7335 mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); 7336 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7337 0x80, mute & 0x80); 7338 mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0); 7339 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7340 0x80, mute & 0x80); 7341 } 7342} 7343 7344/* unsolicited event for HP jack sensing */ 7345static void alc262_hippo1_unsol_event(struct hda_codec *codec, 7346 unsigned int res) 7347{ 7348 if ((res >> 26) != ALC880_HP_EVENT) 7349 return; 7350 alc262_hippo1_automute(codec); 7351} 7352 7353/* 7354 * fujitsu model 7355 * 0x14 = headphone/spdif-out, 0x15 = internal speaker 7356 */ 7357 7358#define ALC_HP_EVENT 0x37 7359 7360static struct hda_verb alc262_fujitsu_unsol_verbs[] = { 7361 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, 7362 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7363 {} 7364}; 7365 7366static struct hda_input_mux alc262_fujitsu_capture_source = { 7367 .num_items = 2, 7368 .items = { 7369 { "Mic", 0x0 }, 7370 { "CD", 0x4 }, 7371 }, 7372}; 7373 7374static struct hda_input_mux alc262_HP_capture_source = { 7375 .num_items = 5, 7376 .items = { 7377 { "Mic", 0x0 }, 7378 { "Front Mic", 0x3 }, 7379 { "Line", 0x2 }, 7380 { "CD", 0x4 }, 7381 { "AUX IN", 0x6 }, 7382 }, 7383}; 7384 7385/* mute/unmute internal speaker according to the hp jack and mute state */ 7386static void alc262_fujitsu_automute(struct hda_codec *codec, int force) 7387{ 7388 struct alc_spec *spec = codec->spec; 7389 unsigned int mute; 7390 7391 if (force || !spec->sense_updated) { 7392 unsigned int present; 7393 /* need to execute and sync at first */ 7394 snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); 7395 present = snd_hda_codec_read(codec, 0x14, 0, 7396 AC_VERB_GET_PIN_SENSE, 0); 7397 spec->jack_present = (present & 0x80000000) != 0; 7398 spec->sense_updated = 1; 7399 } 7400 if (spec->jack_present) { 7401 /* mute internal speaker */ 7402 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 7403 0x80, 0x80); 7404 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 7405 0x80, 0x80); 7406 } else { 7407 /* unmute internal speaker if necessary */ 7408 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); 7409 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 7410 0x80, mute & 0x80); 7411 mute = snd_hda_codec_amp_read(codec, 0x14, 1, HDA_OUTPUT, 0); 7412 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 7413 0x80, mute & 0x80); 7414 } 7415} 7416 7417/* unsolicited event for HP jack sensing */ 7418static void alc262_fujitsu_unsol_event(struct hda_codec *codec, 7419 unsigned int res) 7420{ 7421 if ((res >> 26) != ALC_HP_EVENT) 7422 return; 7423 alc262_fujitsu_automute(codec, 1); 7424} 7425 7426/* bind volumes of both NID 0x0c and 0x0d */ 7427static int alc262_fujitsu_master_vol_put(struct snd_kcontrol *kcontrol, 7428 struct snd_ctl_elem_value *ucontrol) 7429{ 7430 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 7431 long *valp = ucontrol->value.integer.value; 7432 int change; 7433 7434 change = snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0, 7435 0x7f, valp[0] & 0x7f); 7436 change |= snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0, 7437 0x7f, valp[1] & 0x7f); 7438 snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0, 7439 0x7f, valp[0] & 0x7f); 7440 snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0, 7441 0x7f, valp[1] & 0x7f); 7442 return change; 7443} 7444 7445/* bind hp and internal speaker mute (with plug check) */ 7446static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, 7447 struct snd_ctl_elem_value *ucontrol) 7448{ 7449 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 7450 long *valp = ucontrol->value.integer.value; 7451 int change; 7452 7453 change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7454 0x80, valp[0] ? 0 : 0x80); 7455 change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7456 0x80, valp[1] ? 0 : 0x80); 7457 if (change || codec->in_resume) 7458 alc262_fujitsu_automute(codec, codec->in_resume); 7459 return change; 7460} 7461 7462static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { 7463 { 7464 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 7465 .name = "Master Playback Volume", 7466 .info = snd_hda_mixer_amp_volume_info, 7467 .get = snd_hda_mixer_amp_volume_get, 7468 .put = alc262_fujitsu_master_vol_put, 7469 .tlv = { .c = snd_hda_mixer_amp_tlv }, 7470 .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), 7471 }, 7472 { 7473 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 7474 .name = "Master Playback Switch", 7475 .info = snd_hda_mixer_amp_switch_info, 7476 .get = snd_hda_mixer_amp_switch_get, 7477 .put = alc262_fujitsu_master_sw_put, 7478 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), 7479 }, 7480 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7481 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7482 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7483 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7484 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7485 { } /* end */ 7486}; 7487 7488/* additional init verbs for Benq laptops */ 7489static struct hda_verb alc262_EAPD_verbs[] = { 7490 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 7491 {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, 7492 {} 7493}; 7494 7495static struct hda_verb alc262_benq_t31_EAPD_verbs[] = { 7496 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 7497 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7498 7499 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 7500 {0x20, AC_VERB_SET_PROC_COEF, 0x3050}, 7501 {} 7502}; 7503 7504/* add playback controls from the parsed DAC table */ 7505static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, 7506 const struct auto_pin_cfg *cfg) 7507{ 7508 hda_nid_t nid; 7509 int err; 7510 7511 spec->multiout.num_dacs = 1; /* only use one dac */ 7512 spec->multiout.dac_nids = spec->private_dac_nids; 7513 spec->multiout.dac_nids[0] = 2; 7514 7515 nid = cfg->line_out_pins[0]; 7516 if (nid) { 7517 err = add_control(spec, ALC_CTL_WIDGET_VOL, 7518 "Front Playback Volume", 7519 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT)); 7520 if (err < 0) 7521 return err; 7522 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7523 "Front Playback Switch", 7524 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 7525 if (err < 0) 7526 return err; 7527 } 7528 7529 nid = cfg->speaker_pins[0]; 7530 if (nid) { 7531 if (nid == 0x16) { 7532 err = add_control(spec, ALC_CTL_WIDGET_VOL, 7533 "Speaker Playback Volume", 7534 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, 7535 HDA_OUTPUT)); 7536 if (err < 0) 7537 return err; 7538 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7539 "Speaker Playback Switch", 7540 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 7541 HDA_OUTPUT)); 7542 if (err < 0) 7543 return err; 7544 } else { 7545 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7546 "Speaker Playback Switch", 7547 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 7548 HDA_OUTPUT)); 7549 if (err < 0) 7550 return err; 7551 } 7552 } 7553 nid = cfg->hp_pins[0]; 7554 if (nid) { 7555 /* spec->multiout.hp_nid = 2; */ 7556 if (nid == 0x16) { 7557 err = add_control(spec, ALC_CTL_WIDGET_VOL, 7558 "Headphone Playback Volume", 7559 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, 7560 HDA_OUTPUT)); 7561 if (err < 0) 7562 return err; 7563 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7564 "Headphone Playback Switch", 7565 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 7566 HDA_OUTPUT)); 7567 if (err < 0) 7568 return err; 7569 } else { 7570 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7571 "Headphone Playback Switch", 7572 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 7573 HDA_OUTPUT)); 7574 if (err < 0) 7575 return err; 7576 } 7577 } 7578 return 0; 7579} 7580 7581/* identical with ALC880 */ 7582#define alc262_auto_create_analog_input_ctls \ 7583 alc880_auto_create_analog_input_ctls 7584 7585/* 7586 * generic initialization of ADC, input mixers and output mixers 7587 */ 7588static struct hda_verb alc262_volume_init_verbs[] = { 7589 /* 7590 * Unmute ADC0-2 and set the default input to mic-in 7591 */ 7592 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7593 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7594 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7595 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7596 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7597 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7598 7599 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7600 * mixer widget 7601 * Note: PASD motherboards uses the Line In 2 as the input for 7602 * front panel mic (mic 2) 7603 */ 7604 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7605 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7606 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7607 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 7608 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 7609 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 7610 7611 /* 7612 * Set up output mixers (0x0c - 0x0f) 7613 */ 7614 /* set vol=0 to output mixers */ 7615 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7616 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7617 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7618 7619 /* set up input amps for analog loopback */ 7620 /* Amp Indices: DAC = 0, mixer = 1 */ 7621 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7622 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7623 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7624 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7625 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7626 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7627 7628 /* FIXME: use matrix-type input source selection */ 7629 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7630 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7631 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7632 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7633 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7634 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7635 /* Input mixer2 */ 7636 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7637 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7638 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7639 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7640 /* Input mixer3 */ 7641 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7642 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7643 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7644 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7645 7646 { } 7647}; 7648 7649static struct hda_verb alc262_HP_BPC_init_verbs[] = { 7650 /* 7651 * Unmute ADC0-2 and set the default input to mic-in 7652 */ 7653 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7654 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7655 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7656 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7657 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7658 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7659 7660 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7661 * mixer widget 7662 * Note: PASD motherboards uses the Line In 2 as the input for 7663 * front panel mic (mic 2) 7664 */ 7665 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7666 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7667 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7668 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 7669 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 7670 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 7671 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, 7672 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, 7673 7674 /* 7675 * Set up output mixers (0x0c - 0x0e) 7676 */ 7677 /* set vol=0 to output mixers */ 7678 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7679 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7680 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7681 7682 /* set up input amps for analog loopback */ 7683 /* Amp Indices: DAC = 0, mixer = 1 */ 7684 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7685 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7686 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7687 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7688 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7689 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7690 7691 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7692 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 7693 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 7694 7695 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7696 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7697 7698 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 7699 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 7700 7701 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7702 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7703 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7704 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7705 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7706 7707 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, 7708 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7709 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7710 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, 7711 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7712 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7713 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, (0x7000 | (0x03 << 8))}, 7720 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7721 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7722 /* Input mixer2 */ 7723 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7724 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7725 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7726 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7727 /* Input mixer3 */ 7728 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7729 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7730 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7731 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7732 7733 { } 7734}; 7735 7736static struct hda_verb alc262_HP_BPC_WildWest_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 /* Unmute 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 front 7750 * 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_UNMUTE(0)}, 7754 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7755 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 7756 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 7757 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 7758 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, 7759 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, 7760 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, 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 7779 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */ 7780 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */ 7781 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */ 7782 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */ 7783 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */ 7784 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */ 7785 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */ 7786 7787 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7788 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7789 7790 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 7791 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 7792 7793 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */ 7794 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7795 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7796 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, 7797 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7798 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7799 7800 /* FIXME: use matrix-type input source selection */ 7801 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7802 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7803 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/ 7804 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/ 7805 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/ 7806 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/ 7807 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/ 7808 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */ 7809 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/ 7810 /* Input mixer2 */ 7811 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7812 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 7813 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7814 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7815 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7816 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */ 7817 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, 7818 /* Input mixer3 */ 7819 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7820 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 7821 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7822 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7823 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7824 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */ 7825 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, 7826 7827 { } 7828}; 7829 7830/* pcm configuration: identiacal with ALC880 */ 7831#define alc262_pcm_analog_playback alc880_pcm_analog_playback 7832#define alc262_pcm_analog_capture alc880_pcm_analog_capture 7833#define alc262_pcm_digital_playback alc880_pcm_digital_playback 7834#define alc262_pcm_digital_capture alc880_pcm_digital_capture 7835 7836/* 7837 * BIOS auto configuration 7838 */ 7839static int alc262_parse_auto_config(struct hda_codec *codec) 7840{ 7841 struct alc_spec *spec = codec->spec; 7842 int err; 7843 static hda_nid_t alc262_ignore[] = { 0x1d, 0 }; 7844 7845 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 7846 alc262_ignore); 7847 if (err < 0) 7848 return err; 7849 if (!spec->autocfg.line_outs) 7850 return 0; /* can't find valid BIOS pin config */ 7851 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); 7852 if (err < 0) 7853 return err; 7854 err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg); 7855 if (err < 0) 7856 return err; 7857 7858 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 7859 7860 if (spec->autocfg.dig_out_pin) 7861 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; 7862 if (spec->autocfg.dig_in_pin) 7863 spec->dig_in_nid = ALC262_DIGIN_NID; 7864 7865 if (spec->kctl_alloc) 7866 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 7867 7868 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; 7869 spec->num_mux_defs = 1; 7870 spec->input_mux = &spec->private_imux; 7871 7872 return 1; 7873} 7874 7875#define alc262_auto_init_multi_out alc882_auto_init_multi_out 7876#define alc262_auto_init_hp_out alc882_auto_init_hp_out 7877#define alc262_auto_init_analog_input alc882_auto_init_analog_input 7878 7879 7880/* init callback for auto-configuration model -- overriding the default init */ 7881static void alc262_auto_init(struct hda_codec *codec) 7882{ 7883 alc262_auto_init_multi_out(codec); 7884 alc262_auto_init_hp_out(codec); 7885 alc262_auto_init_analog_input(codec); 7886} 7887 7888/* 7889 * configuration and preset 7890 */ 7891static const char *alc262_models[ALC262_MODEL_LAST] = { 7892 [ALC262_BASIC] = "basic", 7893 [ALC262_HIPPO] = "hippo", 7894 [ALC262_HIPPO_1] = "hippo_1", 7895 [ALC262_FUJITSU] = "fujitsu", 7896 [ALC262_HP_BPC] = "hp-bpc", 7897 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000", 7898 [ALC262_BENQ_ED8] = "benq", 7899 [ALC262_BENQ_T31] = "benq-t31", 7900 [ALC262_SONY_ASSAMD] = "sony-assamd", 7901 [ALC262_AUTO] = "auto", 7902}; 7903 7904static struct snd_pci_quirk alc262_cfg_tbl[] = { 7905 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), 7906 SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC), 7907 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC), 7908 SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC), 7909 SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC), 7910 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC), 7911 SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC), 7912 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC), 7913 SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC), 7914 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), 7915 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), 7916 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL), 7917 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL), 7918 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), 7919 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF), 7920 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF), 7921 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF), 7922 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO), 7923 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), 7924 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), 7925 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), 7926 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), 7927 SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), 7928 SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), 7929 SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), 7930 SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), 7931 {} 7932}; 7933 7934static struct alc_config_preset alc262_presets[] = { 7935 [ALC262_BASIC] = { 7936 .mixers = { alc262_base_mixer }, 7937 .init_verbs = { alc262_init_verbs }, 7938 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7939 .dac_nids = alc262_dac_nids, 7940 .hp_nid = 0x03, 7941 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7942 .channel_mode = alc262_modes, 7943 .input_mux = &alc262_capture_source, 7944 }, 7945 [ALC262_HIPPO] = { 7946 .mixers = { alc262_base_mixer }, 7947 .init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs}, 7948 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7949 .dac_nids = alc262_dac_nids, 7950 .hp_nid = 0x03, 7951 .dig_out_nid = ALC262_DIGOUT_NID, 7952 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7953 .channel_mode = alc262_modes, 7954 .input_mux = &alc262_capture_source, 7955 .unsol_event = alc262_hippo_unsol_event, 7956 .init_hook = alc262_hippo_automute, 7957 }, 7958 [ALC262_HIPPO_1] = { 7959 .mixers = { alc262_hippo1_mixer }, 7960 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs}, 7961 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7962 .dac_nids = alc262_dac_nids, 7963 .hp_nid = 0x02, 7964 .dig_out_nid = ALC262_DIGOUT_NID, 7965 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7966 .channel_mode = alc262_modes, 7967 .input_mux = &alc262_capture_source, 7968 .unsol_event = alc262_hippo1_unsol_event, 7969 .init_hook = alc262_hippo1_automute, 7970 }, 7971 [ALC262_FUJITSU] = { 7972 .mixers = { alc262_fujitsu_mixer }, 7973 .init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs }, 7974 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7975 .dac_nids = alc262_dac_nids, 7976 .hp_nid = 0x03, 7977 .dig_out_nid = ALC262_DIGOUT_NID, 7978 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7979 .channel_mode = alc262_modes, 7980 .input_mux = &alc262_fujitsu_capture_source, 7981 .unsol_event = alc262_fujitsu_unsol_event, 7982 }, 7983 [ALC262_HP_BPC] = { 7984 .mixers = { alc262_HP_BPC_mixer }, 7985 .init_verbs = { alc262_HP_BPC_init_verbs }, 7986 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7987 .dac_nids = alc262_dac_nids, 7988 .hp_nid = 0x03, 7989 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7990 .channel_mode = alc262_modes, 7991 .input_mux = &alc262_HP_capture_source, 7992 }, 7993 [ALC262_HP_BPC_D7000_WF] = { 7994 .mixers = { alc262_HP_BPC_WildWest_mixer }, 7995 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs }, 7996 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7997 .dac_nids = alc262_dac_nids, 7998 .hp_nid = 0x03, 7999 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8000 .channel_mode = alc262_modes, 8001 .input_mux = &alc262_HP_capture_source, 8002 }, 8003 [ALC262_HP_BPC_D7000_WL] = { 8004 .mixers = { alc262_HP_BPC_WildWest_mixer, 8005 alc262_HP_BPC_WildWest_option_mixer }, 8006 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs }, 8007 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8008 .dac_nids = alc262_dac_nids, 8009 .hp_nid = 0x03, 8010 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8011 .channel_mode = alc262_modes, 8012 .input_mux = &alc262_HP_capture_source, 8013 }, 8014 [ALC262_BENQ_ED8] = { 8015 .mixers = { alc262_base_mixer }, 8016 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs }, 8017 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8018 .dac_nids = alc262_dac_nids, 8019 .hp_nid = 0x03, 8020 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8021 .channel_mode = alc262_modes, 8022 .input_mux = &alc262_capture_source, 8023 }, 8024 [ALC262_SONY_ASSAMD] = { 8025 .mixers = { alc262_sony_mixer }, 8026 .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs}, 8027 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8028 .dac_nids = alc262_dac_nids, 8029 .hp_nid = 0x02, 8030 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8031 .channel_mode = alc262_modes, 8032 .input_mux = &alc262_capture_source, 8033 .unsol_event = alc262_hippo_unsol_event, 8034 .init_hook = alc262_hippo_automute, 8035 }, 8036 [ALC262_BENQ_T31] = { 8037 .mixers = { alc262_benq_t31_mixer }, 8038 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs, alc262_hippo_unsol_verbs }, 8039 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 8040 .dac_nids = alc262_dac_nids, 8041 .hp_nid = 0x03, 8042 .num_channel_mode = ARRAY_SIZE(alc262_modes), 8043 .channel_mode = alc262_modes, 8044 .input_mux = &alc262_capture_source, 8045 .unsol_event = alc262_hippo_unsol_event, 8046 .init_hook = alc262_hippo_automute, 8047 }, 8048}; 8049 8050static int patch_alc262(struct hda_codec *codec) 8051{ 8052 struct alc_spec *spec; 8053 int board_config; 8054 int err; 8055 8056 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 8057 if (spec == NULL) 8058 return -ENOMEM; 8059 8060 codec->spec = spec; 8061#if 0 8062 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is 8063 * under-run 8064 */ 8065 { 8066 int tmp; 8067 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); 8068 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); 8069 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); 8070 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80); 8071 } 8072#endif 8073 8074 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST, 8075 alc262_models, 8076 alc262_cfg_tbl); 8077 8078 if (board_config < 0) { 8079 printk(KERN_INFO "hda_codec: Unknown model for ALC262, " 8080 "trying auto-probe from BIOS...\n"); 8081 board_config = ALC262_AUTO; 8082 } 8083 8084 if (board_config == ALC262_AUTO) { 8085 /* automatic parse from the BIOS config */ 8086 err = alc262_parse_auto_config(codec); 8087 if (err < 0) { 8088 alc_free(codec); 8089 return err; 8090 } else if (!err) { 8091 printk(KERN_INFO 8092 "hda_codec: Cannot set up configuration " 8093 "from BIOS. Using base mode...\n"); 8094 board_config = ALC262_BASIC; 8095 } 8096 } 8097 8098 if (board_config != ALC262_AUTO) 8099 setup_preset(spec, &alc262_presets[board_config]); 8100 8101 spec->stream_name_analog = "ALC262 Analog"; 8102 spec->stream_analog_playback = &alc262_pcm_analog_playback; 8103 spec->stream_analog_capture = &alc262_pcm_analog_capture; 8104 8105 spec->stream_name_digital = "ALC262 Digital"; 8106 spec->stream_digital_playback = &alc262_pcm_digital_playback; 8107 spec->stream_digital_capture = &alc262_pcm_digital_capture; 8108 8109 if (!spec->adc_nids && spec->input_mux) { 8110 /* check whether NID 0x07 is valid */ 8111 unsigned int wcap = get_wcaps(codec, 0x07); 8112 8113 /* get type */ 8114 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 8115 if (wcap != AC_WID_AUD_IN) { 8116 spec->adc_nids = alc262_adc_nids_alt; 8117 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); 8118 spec->mixers[spec->num_mixers] = 8119 alc262_capture_alt_mixer; 8120 spec->num_mixers++; 8121 } else { 8122 spec->adc_nids = alc262_adc_nids; 8123 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids); 8124 spec->mixers[spec->num_mixers] = alc262_capture_mixer; 8125 spec->num_mixers++; 8126 } 8127 } 8128 8129 codec->patch_ops = alc_patch_ops; 8130 if (board_config == ALC262_AUTO) 8131 spec->init_hook = alc262_auto_init; 8132 8133 return 0; 8134} 8135 8136/* 8137 * ALC268 channel source setting (2 channel) 8138 */ 8139#define ALC268_DIGOUT_NID ALC880_DIGOUT_NID 8140#define alc268_modes alc260_modes 8141 8142static hda_nid_t alc268_dac_nids[2] = { 8143 /* front, hp */ 8144 0x02, 0x03 8145}; 8146 8147static hda_nid_t alc268_adc_nids[2] = { 8148 /* ADC0-1 */ 8149 0x08, 0x07 8150}; 8151 8152static hda_nid_t alc268_adc_nids_alt[1] = { 8153 /* ADC0 */ 8154 0x08 8155}; 8156 8157static struct snd_kcontrol_new alc268_base_mixer[] = { 8158 /* output mixer control */ 8159 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), 8160 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 8161 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), 8162 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 8163 { } 8164}; 8165 8166/* 8167 * generic initialization of ADC, input mixers and output mixers 8168 */ 8169static struct hda_verb alc268_base_init_verbs[] = { 8170 /* Unmute DAC0-1 and set vol = 0 */ 8171 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8172 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8173 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8174 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8175 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8176 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8177 8178 /* 8179 * Set up output mixers (0x0c - 0x0e) 8180 */ 8181 /* set vol=0 to output mixers */ 8182 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8183 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8184 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8185 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, 8186 8187 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8188 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8189 8190 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 8191 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 8192 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 8193 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8194 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8195 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8196 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8197 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8198 8199 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8200 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8201 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8202 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8203 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8204 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8205 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8206 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 8207 8208 /* FIXME: use matrix-type input source selection */ 8209 /* Mixer elements: 0x18, 19, 1a, 1c, 14, 15, 0b */ 8210 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 8211 /* Input mixer2 */ 8212 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 8213 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 8214 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 8215 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 8216 8217 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 8218 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 8219 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 8220 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 8221 { } 8222}; 8223 8224/* 8225 * generic initialization of ADC, input mixers and output mixers 8226 */ 8227static struct hda_verb alc268_volume_init_verbs[] = { 8228 /* set output DAC */ 8229 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8230 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8231 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8232 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8233 8234 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8235 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8236 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8237 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8238 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8239 8240 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8241 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8242 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8243 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8244 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8245 8246 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8247 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8248 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8249 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8250 8251 /* set PCBEEP vol = 0 */ 8252 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0xb000 | (0x00 << 8))}, 8253 8254 { } 8255}; 8256 8257#define alc268_mux_enum_info alc_mux_enum_info 8258#define alc268_mux_enum_get alc_mux_enum_get 8259 8260static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol, 8261 struct snd_ctl_elem_value *ucontrol) 8262{ 8263 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 8264 struct alc_spec *spec = codec->spec; 8265 const struct hda_input_mux *imux = spec->input_mux; 8266 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 8267 static hda_nid_t capture_mixers[3] = { 0x23, 0x24 }; 8268 hda_nid_t nid = capture_mixers[adc_idx]; 8269 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 8270 unsigned int i, idx; 8271 8272 idx = ucontrol->value.enumerated.item[0]; 8273 if (idx >= imux->num_items) 8274 idx = imux->num_items - 1; 8275 if (*cur_val == idx && !codec->in_resume) 8276 return 0; 8277 for (i = 0; i < imux->num_items; i++) { 8278 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 8279 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 8280 v | (imux->items[i].index << 8)); 8281 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, 8282 idx ); 8283 } 8284 *cur_val = idx; 8285 return 1; 8286} 8287 8288static struct snd_kcontrol_new alc268_capture_alt_mixer[] = { 8289 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), 8290 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), 8291 { 8292 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8293 /* The multiple "Capture Source" controls confuse alsamixer 8294 * So call somewhat different.. 8295 * FIXME: the controls appear in the "playback" view! 8296 */ 8297 /* .name = "Capture Source", */ 8298 .name = "Input Source", 8299 .count = 1, 8300 .info = alc268_mux_enum_info, 8301 .get = alc268_mux_enum_get, 8302 .put = alc268_mux_enum_put, 8303 }, 8304 { } /* end */ 8305}; 8306 8307static struct snd_kcontrol_new alc268_capture_mixer[] = { 8308 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), 8309 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), 8310 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT), 8311 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT), 8312 { 8313 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8314 /* The multiple "Capture Source" controls confuse alsamixer 8315 * So call somewhat different.. 8316 * FIXME: the controls appear in the "playback" view! 8317 */ 8318 /* .name = "Capture Source", */ 8319 .name = "Input Source", 8320 .count = 2, 8321 .info = alc268_mux_enum_info, 8322 .get = alc268_mux_enum_get, 8323 .put = alc268_mux_enum_put, 8324 }, 8325 { } /* end */ 8326}; 8327 8328static struct hda_input_mux alc268_capture_source = { 8329 .num_items = 4, 8330 .items = { 8331 { "Mic", 0x0 }, 8332 { "Front Mic", 0x1 }, 8333 { "Line", 0x2 }, 8334 { "CD", 0x3 }, 8335 }, 8336}; 8337 8338/* create input playback/capture controls for the given pin */ 8339static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, 8340 const char *ctlname, int idx) 8341{ 8342 char name[32]; 8343 int err; 8344 8345 sprintf(name, "%s Playback Volume", ctlname); 8346 if (nid == 0x14) { 8347 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 8348 HDA_COMPOSE_AMP_VAL(0x02, 3, idx, 8349 HDA_OUTPUT)); 8350 if (err < 0) 8351 return err; 8352 } else if (nid == 0x15) { 8353 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 8354 HDA_COMPOSE_AMP_VAL(0x03, 3, idx, 8355 HDA_OUTPUT)); 8356 if (err < 0) 8357 return err; 8358 } else 8359 return -1; 8360 sprintf(name, "%s Playback Switch", ctlname); 8361 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 8362 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT)); 8363 if (err < 0) 8364 return err; 8365 return 0; 8366} 8367 8368/* add playback controls from the parsed DAC table */ 8369static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec, 8370 const struct auto_pin_cfg *cfg) 8371{ 8372 hda_nid_t nid; 8373 int err; 8374 8375 spec->multiout.num_dacs = 2; /* only use one dac */ 8376 spec->multiout.dac_nids = spec->private_dac_nids; 8377 spec->multiout.dac_nids[0] = 2; 8378 spec->multiout.dac_nids[1] = 3; 8379 8380 nid = cfg->line_out_pins[0]; 8381 if (nid) 8382 alc268_new_analog_output(spec, nid, "Front", 0); 8383 8384 nid = cfg->speaker_pins[0]; 8385 if (nid == 0x1d) { 8386 err = add_control(spec, ALC_CTL_WIDGET_VOL, 8387 "Speaker Playback Volume", 8388 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); 8389 if (err < 0) 8390 return err; 8391 } 8392 nid = cfg->hp_pins[0]; 8393 if (nid) 8394 alc268_new_analog_output(spec, nid, "Headphone", 0); 8395 8396 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2]; 8397 if (nid == 0x16) { 8398 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 8399 "Mono Playback Switch", 8400 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_INPUT)); 8401 if (err < 0) 8402 return err; 8403 } 8404 return 0; 8405} 8406 8407/* create playback/capture controls for input pins */ 8408static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec, 8409 const struct auto_pin_cfg *cfg) 8410{ 8411 struct hda_input_mux *imux = &spec->private_imux; 8412 int i, idx1; 8413 8414 for (i = 0; i < AUTO_PIN_LAST; i++) { 8415 switch(cfg->input_pins[i]) { 8416 case 0x18: 8417 idx1 = 0; /* Mic 1 */ 8418 break; 8419 case 0x19: 8420 idx1 = 1; /* Mic 2 */ 8421 break; 8422 case 0x1a: 8423 idx1 = 2; /* Line In */ 8424 break; 8425 case 0x1c: 8426 idx1 = 3; /* CD */ 8427 break; 8428 default: 8429 continue; 8430 } 8431 imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; 8432 imux->items[imux->num_items].index = idx1; 8433 imux->num_items++; 8434 } 8435 return 0; 8436} 8437 8438static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) 8439{ 8440 struct alc_spec *spec = codec->spec; 8441 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0]; 8442 hda_nid_t hp_nid = spec->autocfg.hp_pins[0]; 8443 hda_nid_t line_nid = spec->autocfg.line_out_pins[0]; 8444 unsigned int dac_vol1, dac_vol2; 8445 8446 if (speaker_nid) { 8447 snd_hda_codec_write(codec, speaker_nid, 0, 8448 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 8449 snd_hda_codec_write(codec, 0x0f, 0, 8450 AC_VERB_SET_AMP_GAIN_MUTE, 8451 AMP_IN_UNMUTE(1)); 8452 snd_hda_codec_write(codec, 0x10, 0, 8453 AC_VERB_SET_AMP_GAIN_MUTE, 8454 AMP_IN_UNMUTE(1)); 8455 } else { 8456 snd_hda_codec_write(codec, 0x0f, 0, 8457 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)); 8458 snd_hda_codec_write(codec, 0x10, 0, 8459 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)); 8460 } 8461 8462 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */ 8463 if (line_nid == 0x14) 8464 dac_vol2 = AMP_OUT_ZERO; 8465 else if (line_nid == 0x15) 8466 dac_vol1 = AMP_OUT_ZERO; 8467 if (hp_nid == 0x14) 8468 dac_vol2 = AMP_OUT_ZERO; 8469 else if (hp_nid == 0x15) 8470 dac_vol1 = AMP_OUT_ZERO; 8471 if (line_nid != 0x16 || hp_nid != 0x16 || 8472 spec->autocfg.line_out_pins[1] != 0x16 || 8473 spec->autocfg.line_out_pins[2] != 0x16) 8474 dac_vol1 = dac_vol2 = AMP_OUT_ZERO; 8475 8476 snd_hda_codec_write(codec, 0x02, 0, 8477 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1); 8478 snd_hda_codec_write(codec, 0x03, 0, 8479 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2); 8480} 8481 8482/* pcm configuration: identiacal with ALC880 */ 8483#define alc268_pcm_analog_playback alc880_pcm_analog_playback 8484#define alc268_pcm_analog_capture alc880_pcm_analog_capture 8485#define alc268_pcm_digital_playback alc880_pcm_digital_playback 8486 8487/* 8488 * BIOS auto configuration 8489 */ 8490static int alc268_parse_auto_config(struct hda_codec *codec) 8491{ 8492 struct alc_spec *spec = codec->spec; 8493 int err; 8494 static hda_nid_t alc268_ignore[] = { 0 }; 8495 8496 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 8497 alc268_ignore); 8498 if (err < 0) 8499 return err; 8500 if (!spec->autocfg.line_outs) 8501 return 0; /* can't find valid BIOS pin config */ 8502 8503 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg); 8504 if (err < 0) 8505 return err; 8506 err = alc268_auto_create_analog_input_ctls(spec, &spec->autocfg); 8507 if (err < 0) 8508 return err; 8509 8510 spec->multiout.max_channels = 2; 8511 8512 /* digital only support output */ 8513 if (spec->autocfg.dig_out_pin) 8514 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; 8515 8516 if (spec->kctl_alloc) 8517 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 8518 8519 spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs; 8520 spec->num_mux_defs = 1; 8521 spec->input_mux = &spec->private_imux; 8522 8523 return 1; 8524} 8525 8526#define alc268_auto_init_multi_out alc882_auto_init_multi_out 8527#define alc268_auto_init_hp_out alc882_auto_init_hp_out 8528#define alc268_auto_init_analog_input alc882_auto_init_analog_input 8529 8530/* init callback for auto-configuration model -- overriding the default init */ 8531static void alc268_auto_init(struct hda_codec *codec) 8532{ 8533 alc268_auto_init_multi_out(codec); 8534 alc268_auto_init_hp_out(codec); 8535 alc268_auto_init_mono_speaker_out(codec); 8536 alc268_auto_init_analog_input(codec); 8537} 8538 8539/* 8540 * configuration and preset 8541 */ 8542static const char *alc268_models[ALC268_MODEL_LAST] = { 8543 [ALC268_3ST] = "3stack", 8544 [ALC268_AUTO] = "auto", 8545}; 8546 8547static struct snd_pci_quirk alc268_cfg_tbl[] = { 8548 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), 8549 {} 8550}; 8551 8552static struct alc_config_preset alc268_presets[] = { 8553 [ALC268_3ST] = { 8554 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer }, 8555 .init_verbs = { alc268_base_init_verbs }, 8556 .num_dacs = ARRAY_SIZE(alc268_dac_nids), 8557 .dac_nids = alc268_dac_nids, 8558 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), 8559 .adc_nids = alc268_adc_nids_alt, 8560 .hp_nid = 0x03, 8561 .dig_out_nid = ALC268_DIGOUT_NID, 8562 .num_channel_mode = ARRAY_SIZE(alc268_modes), 8563 .channel_mode = alc268_modes, 8564 .input_mux = &alc268_capture_source, 8565 }, 8566}; 8567 8568static int patch_alc268(struct hda_codec *codec) 8569{ 8570 struct alc_spec *spec; 8571 int board_config; 8572 int err; 8573 8574 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); 8575 if (spec == NULL) 8576 return -ENOMEM; 8577 8578 codec->spec = spec; 8579 8580 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST, 8581 alc268_models, 8582 alc268_cfg_tbl); 8583 8584 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) { 8585 printk(KERN_INFO "hda_codec: Unknown model for ALC268, " 8586 "trying auto-probe from BIOS...\n"); 8587 board_config = ALC268_AUTO; 8588 } 8589 8590 if (board_config == ALC268_AUTO) { 8591 /* automatic parse from the BIOS config */ 8592 err = alc268_parse_auto_config(codec); 8593 if (err < 0) { 8594 alc_free(codec); 8595 return err; 8596 } else if (!err) { 8597 printk(KERN_INFO 8598 "hda_codec: Cannot set up configuration " 8599 "from BIOS. Using base mode...\n"); 8600 board_config = ALC268_3ST; 8601 } 8602 } 8603 8604 if (board_config != ALC268_AUTO) 8605 setup_preset(spec, &alc268_presets[board_config]); 8606 8607 spec->stream_name_analog = "ALC268 Analog"; 8608 spec->stream_analog_playback = &alc268_pcm_analog_playback; 8609 spec->stream_analog_capture = &alc268_pcm_analog_capture; 8610 8611 spec->stream_name_digital = "ALC268 Digital"; 8612 spec->stream_digital_playback = &alc268_pcm_digital_playback; 8613 8614 if (board_config == ALC268_AUTO) { 8615 if (!spec->adc_nids && spec->input_mux) { 8616 /* check whether NID 0x07 is valid */ 8617 unsigned int wcap = get_wcaps(codec, 0x07); 8618 8619 /* get type */ 8620 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 8621 if (wcap != AC_WID_AUD_IN) { 8622 spec->adc_nids = alc268_adc_nids_alt; 8623 spec->num_adc_nids = 8624 ARRAY_SIZE(alc268_adc_nids_alt); 8625 spec->mixers[spec->num_mixers] = 8626 alc268_capture_alt_mixer; 8627 spec->num_mixers++; 8628 } else { 8629 spec->adc_nids = alc268_adc_nids; 8630 spec->num_adc_nids = 8631 ARRAY_SIZE(alc268_adc_nids); 8632 spec->mixers[spec->num_mixers] = 8633 alc268_capture_mixer; 8634 spec->num_mixers++; 8635 } 8636 } 8637 } 8638 codec->patch_ops = alc_patch_ops; 8639 if (board_config == ALC268_AUTO) 8640 spec->init_hook = alc268_auto_init; 8641 8642 return 0; 8643} 8644 8645/* 8646 * ALC861 channel source setting (2/6 channel selection for 3-stack) 8647 */ 8648 8649/* 8650 * set the path ways for 2 channel output 8651 * need to set the codec line out and mic 1 pin widgets to inputs 8652 */ 8653static struct hda_verb alc861_threestack_ch2_init[] = { 8654 /* set pin widget 1Ah (line in) for input */ 8655 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8656 /* set pin widget 18h (mic1/2) for input, for mic also enable 8657 * the vref 8658 */ 8659 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8660 8661 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, 8662#if 0 8663 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ 8664 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/ 8665#endif 8666 { } /* end */ 8667}; 8668/* 8669 * 6ch mode 8670 * need to set the codec line out and mic 1 pin widgets to outputs 8671 */ 8672static struct hda_verb alc861_threestack_ch6_init[] = { 8673 /* set pin widget 1Ah (line in) for output (Back Surround)*/ 8674 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8675 /* set pin widget 18h (mic1) for output (CLFE)*/ 8676 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8677 8678 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8679 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8680 8681 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, 8682#if 0 8683 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ 8684 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/ 8685#endif 8686 { } /* end */ 8687}; 8688 8689static struct hda_channel_mode alc861_threestack_modes[2] = { 8690 { 2, alc861_threestack_ch2_init }, 8691 { 6, alc861_threestack_ch6_init }, 8692}; 8693/* Set mic1 as input and unmute the mixer */ 8694static struct hda_verb alc861_uniwill_m31_ch2_init[] = { 8695 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8696 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ 8697 { } /* end */ 8698}; 8699/* Set mic1 as output and mute mixer */ 8700static struct hda_verb alc861_uniwill_m31_ch4_init[] = { 8701 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8702 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ 8703 { } /* end */ 8704}; 8705 8706static struct hda_channel_mode alc861_uniwill_m31_modes[2] = { 8707 { 2, alc861_uniwill_m31_ch2_init }, 8708 { 4, alc861_uniwill_m31_ch4_init }, 8709}; 8710 8711/* Set mic1 and line-in as input and unmute the mixer */ 8712static struct hda_verb alc861_asus_ch2_init[] = { 8713 /* set pin widget 1Ah (line in) for input */ 8714 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8715 /* set pin widget 18h (mic1/2) for input, for mic also enable 8716 * the vref 8717 */ 8718 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8719 8720 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, 8721#if 0 8722 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ 8723 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/ 8724#endif 8725 { } /* end */ 8726}; 8727/* Set mic1 nad line-in as output and mute mixer */ 8728static struct hda_verb alc861_asus_ch6_init[] = { 8729 /* set pin widget 1Ah (line in) for output (Back Surround)*/ 8730 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8731 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */ 8732 /* set pin widget 18h (mic1) for output (CLFE)*/ 8733 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8734 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */ 8735 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8736 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8737 8738 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, 8739#if 0 8740 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ 8741 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/ 8742#endif 8743 { } /* end */ 8744}; 8745 8746static struct hda_channel_mode alc861_asus_modes[2] = { 8747 { 2, alc861_asus_ch2_init }, 8748 { 6, alc861_asus_ch6_init }, 8749}; 8750 8751/* patch-ALC861 */ 8752 8753static struct snd_kcontrol_new alc861_base_mixer[] = { 8754 /* output mixer control */ 8755 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8756 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 8757 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 8758 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 8759 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), 8760 8761 /*Input mixer control */ 8762 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 8763 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ 8764 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8765 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8766 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 8767 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 8768 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8769 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8770 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 8771 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), 8772 8773 /* Capture mixer control */ 8774 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8775 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8776 { 8777 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8778 .name = "Capture Source", 8779 .count = 1, 8780 .info = alc_mux_enum_info, 8781 .get = alc_mux_enum_get, 8782 .put = alc_mux_enum_put, 8783 }, 8784 { } /* end */ 8785}; 8786 8787static struct snd_kcontrol_new alc861_3ST_mixer[] = { 8788 /* output mixer control */ 8789 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8790 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 8791 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 8792 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 8793 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */ 8794 8795 /* Input mixer control */ 8796 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 8797 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ 8798 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8799 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8800 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 8801 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 8802 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8803 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8804 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 8805 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), 8806 8807 /* Capture mixer control */ 8808 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8809 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8810 { 8811 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8812 .name = "Capture Source", 8813 .count = 1, 8814 .info = alc_mux_enum_info, 8815 .get = alc_mux_enum_get, 8816 .put = alc_mux_enum_put, 8817 }, 8818 { 8819 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8820 .name = "Channel Mode", 8821 .info = alc_ch_mode_info, 8822 .get = alc_ch_mode_get, 8823 .put = alc_ch_mode_put, 8824 .private_value = ARRAY_SIZE(alc861_threestack_modes), 8825 }, 8826 { } /* end */ 8827}; 8828 8829static struct snd_kcontrol_new alc861_toshiba_mixer[] = { 8830 /* output mixer control */ 8831 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8832 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8833 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8834 8835 /*Capture mixer control */ 8836 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8837 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8838 { 8839 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8840 .name = "Capture Source", 8841 .count = 1, 8842 .info = alc_mux_enum_info, 8843 .get = alc_mux_enum_get, 8844 .put = alc_mux_enum_put, 8845 }, 8846 8847 { } /* end */ 8848}; 8849 8850static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { 8851 /* output mixer control */ 8852 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8853 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 8854 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 8855 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 8856 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */ 8857 8858 /* Input mixer control */ 8859 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 8860 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ 8861 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8862 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8863 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 8864 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 8865 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8866 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8867 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 8868 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), 8869 8870 /* Capture mixer control */ 8871 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8872 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8873 { 8874 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8875 .name = "Capture Source", 8876 .count = 1, 8877 .info = alc_mux_enum_info, 8878 .get = alc_mux_enum_get, 8879 .put = alc_mux_enum_put, 8880 }, 8881 { 8882 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8883 .name = "Channel Mode", 8884 .info = alc_ch_mode_info, 8885 .get = alc_ch_mode_get, 8886 .put = alc_ch_mode_put, 8887 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes), 8888 }, 8889 { } /* end */ 8890}; 8891 8892static struct snd_kcontrol_new alc861_asus_mixer[] = { 8893 /* output mixer control */ 8894 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8895 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 8896 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 8897 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 8898 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), 8899 8900 /* Input mixer control */ 8901 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 8902 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), 8903 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8904 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8905 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 8906 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 8907 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8908 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8909 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 8910 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), 8911 8912 /* Capture mixer control */ 8913 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8914 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8915 { 8916 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8917 .name = "Capture Source", 8918 .count = 1, 8919 .info = alc_mux_enum_info, 8920 .get = alc_mux_enum_get, 8921 .put = alc_mux_enum_put, 8922 }, 8923 { 8924 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8925 .name = "Channel Mode", 8926 .info = alc_ch_mode_info, 8927 .get = alc_ch_mode_get, 8928 .put = alc_ch_mode_put, 8929 .private_value = ARRAY_SIZE(alc861_asus_modes), 8930 }, 8931 { } 8932}; 8933 8934/* additional mixer */ 8935static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = { 8936 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8937 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8938 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT), 8939 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT), 8940 { } 8941}; 8942 8943/* 8944 * generic initialization of ADC, input mixers and output mixers 8945 */ 8946static struct hda_verb alc861_base_init_verbs[] = { 8947 /* 8948 * Unmute ADC0 and set the default input to mic-in 8949 */ 8950 /* port-A for surround (rear panel) */ 8951 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8952 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8953 /* port-B for mic-in (rear panel) with vref */ 8954 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8955 /* port-C for line-in (rear panel) */ 8956 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8957 /* port-D for Front */ 8958 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8959 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8960 /* port-E for HP out (front panel) */ 8961 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 8962 /* route front PCM to HP */ 8963 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8964 /* port-F for mic-in (front panel) with vref */ 8965 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8966 /* port-G for CLFE (rear panel) */ 8967 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8968 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8969 /* port-H for side (rear panel) */ 8970 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8971 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8972 /* CD-in */ 8973 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8974 /* route front mic to ADC1*/ 8975 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 8976 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8977 8978 /* Unmute DAC0~3 & spdif out*/ 8979 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8980 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8981 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8982 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8983 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8984 8985 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 8986 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8987 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8988 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8989 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8990 8991 /* Unmute Stereo Mixer 15 */ 8992 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8993 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8994 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 8995 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 8996 8997 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8998 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8999 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9000 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9001 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9002 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9003 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9004 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9005 /* hp used DAC 3 (Front) */ 9006 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9007 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9008 9009 { } 9010}; 9011 9012static struct hda_verb alc861_threestack_init_verbs[] = { 9013 /* 9014 * Unmute ADC0 and set the default input to mic-in 9015 */ 9016 /* port-A for surround (rear panel) */ 9017 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9018 /* port-B for mic-in (rear panel) with vref */ 9019 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9020 /* port-C for line-in (rear panel) */ 9021 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9022 /* port-D for Front */ 9023 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9024 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9025 /* port-E for HP out (front panel) */ 9026 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 9027 /* route front PCM to HP */ 9028 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9029 /* port-F for mic-in (front panel) with vref */ 9030 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9031 /* port-G for CLFE (rear panel) */ 9032 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9033 /* port-H for side (rear panel) */ 9034 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9035 /* CD-in */ 9036 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9037 /* route front mic to ADC1*/ 9038 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 9039 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9040 /* Unmute DAC0~3 & spdif out*/ 9041 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9042 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9043 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9044 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9045 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9046 9047 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9048 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9049 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9050 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9051 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9052 9053 /* Unmute Stereo Mixer 15 */ 9054 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9055 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9056 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9057 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 9058 9059 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9060 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9061 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9062 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9063 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9064 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9065 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9066 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9067 /* hp used DAC 3 (Front) */ 9068 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9069 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9070 { } 9071}; 9072 9073static struct hda_verb alc861_uniwill_m31_init_verbs[] = { 9074 /* 9075 * Unmute ADC0 and set the default input to mic-in 9076 */ 9077 /* port-A for surround (rear panel) */ 9078 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9079 /* port-B for mic-in (rear panel) with vref */ 9080 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9081 /* port-C for line-in (rear panel) */ 9082 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9083 /* port-D for Front */ 9084 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9085 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9086 /* port-E for HP out (front panel) */ 9087 /* this has to be set to VREF80 */ 9088 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9089 /* route front PCM to HP */ 9090 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9091 /* port-F for mic-in (front panel) with vref */ 9092 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9093 /* port-G for CLFE (rear panel) */ 9094 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9095 /* port-H for side (rear panel) */ 9096 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9097 /* CD-in */ 9098 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9099 /* route front mic to ADC1*/ 9100 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 9101 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9102 /* Unmute DAC0~3 & spdif out*/ 9103 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9104 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9105 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9106 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9107 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9108 9109 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9110 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9111 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9112 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9113 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9114 9115 /* Unmute Stereo Mixer 15 */ 9116 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9117 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9118 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9119 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 9120 9121 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9122 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9123 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9124 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9125 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9126 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9127 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9128 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9129 /* hp used DAC 3 (Front) */ 9130 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9131 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9132 { } 9133}; 9134 9135static struct hda_verb alc861_asus_init_verbs[] = { 9136 /* 9137 * Unmute ADC0 and set the default input to mic-in 9138 */ 9139 /* port-A for surround (rear panel) 9140 * according to codec#0 this is the HP jack 9141 */ 9142 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */ 9143 /* route front PCM to HP */ 9144 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 }, 9145 /* port-B for mic-in (rear panel) with vref */ 9146 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9147 /* port-C for line-in (rear panel) */ 9148 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9149 /* port-D for Front */ 9150 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9151 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9152 /* port-E for HP out (front panel) */ 9153 /* this has to be set to VREF80 */ 9154 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9155 /* route front PCM to HP */ 9156 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9157 /* port-F for mic-in (front panel) with vref */ 9158 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9159 /* port-G for CLFE (rear panel) */ 9160 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9161 /* port-H for side (rear panel) */ 9162 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9163 /* CD-in */ 9164 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9165 /* route front mic to ADC1*/ 9166 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 9167 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 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 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9175 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9176 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9177 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9178 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9179 9180 /* Unmute Stereo Mixer 15 */ 9181 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9182 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9183 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9184 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 9185 9186 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9187 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9188 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9189 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9190 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9191 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9192 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9193 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9194 /* hp used DAC 3 (Front) */ 9195 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9196 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9197 { } 9198}; 9199 9200/* additional init verbs for ASUS laptops */ 9201static struct hda_verb alc861_asus_laptop_init_verbs[] = { 9202 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */ 9203 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */ 9204 { } 9205}; 9206 9207/* 9208 * generic initialization of ADC, input mixers and output mixers 9209 */ 9210static struct hda_verb alc861_auto_init_verbs[] = { 9211 /* 9212 * Unmute ADC0 and set the default input to mic-in 9213 */ 9214 /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */ 9215 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9216 9217 /* Unmute DAC0~3 & spdif out*/ 9218 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9219 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9220 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9221 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9222 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9223 9224 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9225 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9226 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9227 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9228 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9229 9230 /* Unmute Stereo Mixer 15 */ 9231 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9232 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9233 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9234 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, 9235 9236 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9237 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9238 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9239 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9240 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9241 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9242 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9243 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9244 9245 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 9246 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 9247 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9248 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9249 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 9250 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 9251 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9252 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9253 9254 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */ 9255 9256 { } 9257}; 9258 9259static struct hda_verb alc861_toshiba_init_verbs[] = { 9260 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 9261 9262 { } 9263}; 9264 9265/* toggle speaker-output according to the hp-jack state */ 9266static void alc861_toshiba_automute(struct hda_codec *codec) 9267{ 9268 unsigned int present; 9269 9270 present = snd_hda_codec_read(codec, 0x0f, 0, 9271 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 9272 snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0, 9273 0x80, present ? 0x80 : 0); 9274 snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0, 9275 0x80, present ? 0x80 : 0); 9276 snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3, 9277 0x80, present ? 0 : 0x80); 9278 snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3, 9279 0x80, present ? 0 : 0x80); 9280} 9281 9282static void alc861_toshiba_unsol_event(struct hda_codec *codec, 9283 unsigned int res) 9284{ 9285 if ((res >> 26) == ALC880_HP_EVENT) 9286 alc861_toshiba_automute(codec); 9287} 9288 9289/* pcm configuration: identiacal with ALC880 */ 9290#define alc861_pcm_analog_playback alc880_pcm_analog_playback 9291#define alc861_pcm_analog_capture alc880_pcm_analog_capture 9292#define alc861_pcm_digital_playback alc880_pcm_digital_playback 9293#define alc861_pcm_digital_capture alc880_pcm_digital_capture 9294 9295 9296#define ALC861_DIGOUT_NID 0x07 9297 9298static struct hda_channel_mode alc861_8ch_modes[1] = { 9299 { 8, NULL } 9300}; 9301 9302static hda_nid_t alc861_dac_nids[4] = { 9303 /* front, surround, clfe, side */ 9304 0x03, 0x06, 0x05, 0x04 9305}; 9306 9307static hda_nid_t alc660_dac_nids[3] = { 9308 /* front, clfe, surround */ 9309 0x03, 0x05, 0x06 9310}; 9311 9312static hda_nid_t alc861_adc_nids[1] = { 9313 /* ADC0-2 */ 9314 0x08, 9315}; 9316 9317static struct hda_input_mux alc861_capture_source = { 9318 .num_items = 5, 9319 .items = { 9320 { "Mic", 0x0 }, 9321 { "Front Mic", 0x3 }, 9322 { "Line", 0x1 }, 9323 { "CD", 0x4 }, 9324 { "Mixer", 0x5 }, 9325 }, 9326}; 9327 9328/* fill in the dac_nids table from the parsed pin configuration */ 9329static int alc861_auto_fill_dac_nids(struct alc_spec *spec, 9330 const struct auto_pin_cfg *cfg) 9331{ 9332 int i; 9333 hda_nid_t nid; 9334 9335 spec->multiout.dac_nids = spec->private_dac_nids; 9336 for (i = 0; i < cfg->line_outs; i++) { 9337 nid = cfg->line_out_pins[i]; 9338 if (nid) { 9339 if (i >= ARRAY_SIZE(alc861_dac_nids)) 9340 continue; 9341 spec->multiout.dac_nids[i] = alc861_dac_nids[i]; 9342 } 9343 } 9344 spec->multiout.num_dacs = cfg->line_outs; 9345 return 0; 9346} 9347 9348/* add playback controls from the parsed DAC table */ 9349static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec, 9350 const struct auto_pin_cfg *cfg) 9351{ 9352 char name[32]; 9353 static const char *chname[4] = { 9354 "Front", "Surround", NULL /*CLFE*/, "Side" 9355 }; 9356 hda_nid_t nid; 9357 int i, idx, err; 9358 9359 for (i = 0; i < cfg->line_outs; i++) { 9360 nid = spec->multiout.dac_nids[i]; 9361 if (!nid) 9362 continue; 9363 if (nid == 0x05) { 9364 /* Center/LFE */ 9365 err = add_control(spec, ALC_CTL_BIND_MUTE, 9366 "Center Playback Switch", 9367 HDA_COMPOSE_AMP_VAL(nid, 1, 0, 9368 HDA_OUTPUT)); 9369 if (err < 0) 9370 return err; 9371 err = add_control(spec, ALC_CTL_BIND_MUTE, 9372 "LFE Playback Switch", 9373 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 9374 HDA_OUTPUT)); 9375 if (err < 0) 9376 return err; 9377 } else { 9378 for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; 9379 idx++) 9380 if (nid == alc861_dac_nids[idx]) 9381 break; 9382 sprintf(name, "%s Playback Switch", chname[idx]); 9383 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 9384 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 9385 HDA_OUTPUT)); 9386 if (err < 0) 9387 return err; 9388 } 9389 } 9390 return 0; 9391} 9392 9393static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) 9394{ 9395 int err; 9396 hda_nid_t nid; 9397 9398 if (!pin) 9399 return 0; 9400 9401 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) { 9402 nid = 0x03; 9403 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 9404 "Headphone Playback Switch", 9405 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 9406 if (err < 0) 9407 return err; 9408 spec->multiout.hp_nid = nid; 9409 } 9410 return 0; 9411} 9412 9413/* create playback/capture controls for input pins */ 9414static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, 9415 const struct auto_pin_cfg *cfg) 9416{ 9417 struct hda_input_mux *imux = &spec->private_imux; 9418 int i, err, idx, idx1; 9419 9420 for (i = 0; i < AUTO_PIN_LAST; i++) { 9421 switch (cfg->input_pins[i]) { 9422 case 0x0c: 9423 idx1 = 1; 9424 idx = 2; /* Line In */ 9425 break; 9426 case 0x0f: 9427 idx1 = 2; 9428 idx = 2; /* Line In */ 9429 break; 9430 case 0x0d: 9431 idx1 = 0; 9432 idx = 1; /* Mic In */ 9433 break; 9434 case 0x10: 9435 idx1 = 3; 9436 idx = 1; /* Mic In */ 9437 break; 9438 case 0x11: 9439 idx1 = 4; 9440 idx = 0; /* CD */ 9441 break; 9442 default: 9443 continue; 9444 } 9445 9446 err = new_analog_input(spec, cfg->input_pins[i], 9447 auto_pin_cfg_labels[i], idx, 0x15); 9448 if (err < 0) 9449 return err; 9450 9451 imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; 9452 imux->items[imux->num_items].index = idx1; 9453 imux->num_items++; 9454 } 9455 return 0; 9456} 9457 9458static struct snd_kcontrol_new alc861_capture_mixer[] = { 9459 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 9460 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 9461 9462 { 9463 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9464 /* The multiple "Capture Source" controls confuse alsamixer 9465 * So call somewhat different.. 9466 *FIXME: the controls appear in the "playback" view! 9467 */ 9468 /* .name = "Capture Source", */ 9469 .name = "Input Source", 9470 .count = 1, 9471 .info = alc_mux_enum_info, 9472 .get = alc_mux_enum_get, 9473 .put = alc_mux_enum_put, 9474 }, 9475 { } /* end */ 9476}; 9477 9478static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, 9479 hda_nid_t nid, 9480 int pin_type, int dac_idx) 9481{ 9482 /* set as output */ 9483 9484 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 9485 pin_type); 9486 snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, 9487 AMP_OUT_UNMUTE); 9488 9489} 9490 9491static void alc861_auto_init_multi_out(struct hda_codec *codec) 9492{ 9493 struct alc_spec *spec = codec->spec; 9494 int i; 9495 9496 alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b); 9497 for (i = 0; i < spec->autocfg.line_outs; i++) { 9498 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 9499 int pin_type = get_pin_type(spec->autocfg.line_out_type); 9500 if (nid) 9501 alc861_auto_set_output_and_unmute(codec, nid, pin_type, 9502 spec->multiout.dac_nids[i]); 9503 } 9504} 9505 9506static void alc861_auto_init_hp_out(struct hda_codec *codec) 9507{ 9508 struct alc_spec *spec = codec->spec; 9509 hda_nid_t pin; 9510 9511 pin = spec->autocfg.hp_pins[0]; 9512 if (pin) /* connect to front */ 9513 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, 9514 spec->multiout.dac_nids[0]); 9515} 9516 9517static void alc861_auto_init_analog_input(struct hda_codec *codec) 9518{ 9519 struct alc_spec *spec = codec->spec; 9520 int i; 9521 9522 for (i = 0; i < AUTO_PIN_LAST; i++) { 9523 hda_nid_t nid = spec->autocfg.input_pins[i]; 9524 if (nid >= 0x0c && nid <= 0x11) { 9525 snd_hda_codec_write(codec, nid, 0, 9526 AC_VERB_SET_PIN_WIDGET_CONTROL, 9527 i <= AUTO_PIN_FRONT_MIC ? 9528 PIN_VREF80 : PIN_IN); 9529 } 9530 } 9531} 9532 9533/* parse the BIOS configuration and set up the alc_spec */ 9534/* return 1 if successful, 0 if the proper config is not found, 9535 * or a negative error code 9536 */ 9537static int alc861_parse_auto_config(struct hda_codec *codec) 9538{ 9539 struct alc_spec *spec = codec->spec; 9540 int err; 9541 static hda_nid_t alc861_ignore[] = { 0x1d, 0 }; 9542 9543 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 9544 alc861_ignore); 9545 if (err < 0) 9546 return err; 9547 if (!spec->autocfg.line_outs) 9548 return 0; /* can't find valid BIOS pin config */ 9549 9550 err = alc861_auto_fill_dac_nids(spec, &spec->autocfg); 9551 if (err < 0) 9552 return err; 9553 err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg); 9554 if (err < 0) 9555 return err; 9556 err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 9557 if (err < 0) 9558 return err; 9559 err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg); 9560 if (err < 0) 9561 return err; 9562 9563 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 9564 9565 if (spec->autocfg.dig_out_pin) 9566 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; 9567 9568 if (spec->kctl_alloc) 9569 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 9570 9571 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; 9572 9573 spec->num_mux_defs = 1; 9574 spec->input_mux = &spec->private_imux; 9575 9576 spec->adc_nids = alc861_adc_nids; 9577 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); 9578 spec->mixers[spec->num_mixers] = alc861_capture_mixer; 9579 spec->num_mixers++; 9580 9581 return 1; 9582} 9583 9584/* additional initialization for auto-configuration model */ 9585static void alc861_auto_init(struct hda_codec *codec) 9586{ 9587 alc861_auto_init_multi_out(codec); 9588 alc861_auto_init_hp_out(codec); 9589 alc861_auto_init_analog_input(codec); 9590} 9591 9592 9593/* 9594 * configuration and preset 9595 */ 9596static const char *alc861_models[ALC861_MODEL_LAST] = { 9597 [ALC861_3ST] = "3stack", 9598 [ALC660_3ST] = "3stack-660", 9599 [ALC861_3ST_DIG] = "3stack-dig", 9600 [ALC861_6ST_DIG] = "6stack-dig", 9601 [ALC861_UNIWILL_M31] = "uniwill-m31", 9602 [ALC861_TOSHIBA] = "toshiba", 9603 [ALC861_ASUS] = "asus", 9604 [ALC861_ASUS_LAPTOP] = "asus-laptop", 9605 [ALC861_AUTO] = "auto", 9606}; 9607 9608static struct snd_pci_quirk alc861_cfg_tbl[] = { 9609 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST), 9610 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP), 9611 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP), 9612 SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP), 9613 SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP), 9614 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS), 9615 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG), 9616 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA), 9617 /* FIXME: the entry below breaks Toshiba A100 (model=auto works!) 9618 * Any other models that need this preset? 9619 */ 9620 /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */ 9621 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31), 9622 SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), 9623 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31), 9624 SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST), 9625 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST), 9626 SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST), 9627 SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST), 9628 {} 9629}; 9630 9631static struct alc_config_preset alc861_presets[] = { 9632 [ALC861_3ST] = { 9633 .mixers = { alc861_3ST_mixer }, 9634 .init_verbs = { alc861_threestack_init_verbs }, 9635 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9636 .dac_nids = alc861_dac_nids, 9637 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), 9638 .channel_mode = alc861_threestack_modes, 9639 .need_dac_fix = 1, 9640 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9641 .adc_nids = alc861_adc_nids, 9642 .input_mux = &alc861_capture_source, 9643 }, 9644 [ALC861_3ST_DIG] = { 9645 .mixers = { alc861_base_mixer }, 9646 .init_verbs = { alc861_threestack_init_verbs }, 9647 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9648 .dac_nids = alc861_dac_nids, 9649 .dig_out_nid = ALC861_DIGOUT_NID, 9650 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), 9651 .channel_mode = alc861_threestack_modes, 9652 .need_dac_fix = 1, 9653 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9654 .adc_nids = alc861_adc_nids, 9655 .input_mux = &alc861_capture_source, 9656 }, 9657 [ALC861_6ST_DIG] = { 9658 .mixers = { alc861_base_mixer }, 9659 .init_verbs = { alc861_base_init_verbs }, 9660 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9661 .dac_nids = alc861_dac_nids, 9662 .dig_out_nid = ALC861_DIGOUT_NID, 9663 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes), 9664 .channel_mode = alc861_8ch_modes, 9665 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9666 .adc_nids = alc861_adc_nids, 9667 .input_mux = &alc861_capture_source, 9668 }, 9669 [ALC660_3ST] = { 9670 .mixers = { alc861_3ST_mixer }, 9671 .init_verbs = { alc861_threestack_init_verbs }, 9672 .num_dacs = ARRAY_SIZE(alc660_dac_nids), 9673 .dac_nids = alc660_dac_nids, 9674 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), 9675 .channel_mode = alc861_threestack_modes, 9676 .need_dac_fix = 1, 9677 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9678 .adc_nids = alc861_adc_nids, 9679 .input_mux = &alc861_capture_source, 9680 }, 9681 [ALC861_UNIWILL_M31] = { 9682 .mixers = { alc861_uniwill_m31_mixer }, 9683 .init_verbs = { alc861_uniwill_m31_init_verbs }, 9684 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9685 .dac_nids = alc861_dac_nids, 9686 .dig_out_nid = ALC861_DIGOUT_NID, 9687 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes), 9688 .channel_mode = alc861_uniwill_m31_modes, 9689 .need_dac_fix = 1, 9690 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9691 .adc_nids = alc861_adc_nids, 9692 .input_mux = &alc861_capture_source, 9693 }, 9694 [ALC861_TOSHIBA] = { 9695 .mixers = { alc861_toshiba_mixer }, 9696 .init_verbs = { alc861_base_init_verbs, 9697 alc861_toshiba_init_verbs }, 9698 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9699 .dac_nids = alc861_dac_nids, 9700 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 9701 .channel_mode = alc883_3ST_2ch_modes, 9702 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9703 .adc_nids = alc861_adc_nids, 9704 .input_mux = &alc861_capture_source, 9705 .unsol_event = alc861_toshiba_unsol_event, 9706 .init_hook = alc861_toshiba_automute, 9707 }, 9708 [ALC861_ASUS] = { 9709 .mixers = { alc861_asus_mixer }, 9710 .init_verbs = { alc861_asus_init_verbs }, 9711 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9712 .dac_nids = alc861_dac_nids, 9713 .dig_out_nid = ALC861_DIGOUT_NID, 9714 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes), 9715 .channel_mode = alc861_asus_modes, 9716 .need_dac_fix = 1, 9717 .hp_nid = 0x06, 9718 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9719 .adc_nids = alc861_adc_nids, 9720 .input_mux = &alc861_capture_source, 9721 }, 9722 [ALC861_ASUS_LAPTOP] = { 9723 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer }, 9724 .init_verbs = { alc861_asus_init_verbs, 9725 alc861_asus_laptop_init_verbs }, 9726 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9727 .dac_nids = alc861_dac_nids, 9728 .dig_out_nid = ALC861_DIGOUT_NID, 9729 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 9730 .channel_mode = alc883_3ST_2ch_modes, 9731 .need_dac_fix = 1, 9732 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9733 .adc_nids = alc861_adc_nids, 9734 .input_mux = &alc861_capture_source, 9735 }, 9736}; 9737 9738 9739static int patch_alc861(struct hda_codec *codec) 9740{ 9741 struct alc_spec *spec; 9742 int board_config; 9743 int err; 9744 9745 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 9746 if (spec == NULL) 9747 return -ENOMEM; 9748 9749 codec->spec = spec; 9750 9751 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST, 9752 alc861_models, 9753 alc861_cfg_tbl); 9754 9755 if (board_config < 0) { 9756 printk(KERN_INFO "hda_codec: Unknown model for ALC861, " 9757 "trying auto-probe from BIOS...\n"); 9758 board_config = ALC861_AUTO; 9759 } 9760 9761 if (board_config == ALC861_AUTO) { 9762 /* automatic parse from the BIOS config */ 9763 err = alc861_parse_auto_config(codec); 9764 if (err < 0) { 9765 alc_free(codec); 9766 return err; 9767 } else if (!err) { 9768 printk(KERN_INFO 9769 "hda_codec: Cannot set up configuration " 9770 "from BIOS. Using base mode...\n"); 9771 board_config = ALC861_3ST_DIG; 9772 } 9773 } 9774 9775 if (board_config != ALC861_AUTO) 9776 setup_preset(spec, &alc861_presets[board_config]); 9777 9778 spec->stream_name_analog = "ALC861 Analog"; 9779 spec->stream_analog_playback = &alc861_pcm_analog_playback; 9780 spec->stream_analog_capture = &alc861_pcm_analog_capture; 9781 9782 spec->stream_name_digital = "ALC861 Digital"; 9783 spec->stream_digital_playback = &alc861_pcm_digital_playback; 9784 spec->stream_digital_capture = &alc861_pcm_digital_capture; 9785 9786 codec->patch_ops = alc_patch_ops; 9787 if (board_config == ALC861_AUTO) 9788 spec->init_hook = alc861_auto_init; 9789 9790 return 0; 9791} 9792 9793/* 9794 * ALC861-VD support 9795 * 9796 * Based on ALC882 9797 * 9798 * In addition, an independent DAC 9799 */ 9800#define ALC861VD_DIGOUT_NID 0x06 9801 9802static hda_nid_t alc861vd_dac_nids[4] = { 9803 /* front, surr, clfe, side surr */ 9804 0x02, 0x03, 0x04, 0x05 9805}; 9806 9807/* dac_nids for ALC660vd are in a different order - according to 9808 * Realtek's driver. 9809 * This should probably tesult in a different mixer for 6stack models 9810 * of ALC660vd codecs, but for now there is only 3stack mixer 9811 * - and it is the same as in 861vd. 9812 * adc_nids in ALC660vd are (is) the same as in 861vd 9813 */ 9814static hda_nid_t alc660vd_dac_nids[3] = { 9815 /* front, rear, clfe, rear_surr */ 9816 0x02, 0x04, 0x03 9817}; 9818 9819static hda_nid_t alc861vd_adc_nids[1] = { 9820 /* ADC0 */ 9821 0x09, 9822}; 9823 9824/* input MUX */ 9825/* FIXME: should be a matrix-type input source selection */ 9826static struct hda_input_mux alc861vd_capture_source = { 9827 .num_items = 4, 9828 .items = { 9829 { "Mic", 0x0 }, 9830 { "Front Mic", 0x1 }, 9831 { "Line", 0x2 }, 9832 { "CD", 0x4 }, 9833 }, 9834}; 9835 9836static struct hda_input_mux alc861vd_dallas_capture_source = { 9837 .num_items = 3, 9838 .items = { 9839 { "Front Mic", 0x0 }, 9840 { "ATAPI Mic", 0x1 }, 9841 { "Line In", 0x5 }, 9842 }, 9843}; 9844 9845#define alc861vd_mux_enum_info alc_mux_enum_info 9846#define alc861vd_mux_enum_get alc_mux_enum_get 9847 9848static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol, 9849 struct snd_ctl_elem_value *ucontrol) 9850{ 9851 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 9852 struct alc_spec *spec = codec->spec; 9853 const struct hda_input_mux *imux = spec->input_mux; 9854 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 9855 static hda_nid_t capture_mixers[1] = { 0x22 }; 9856 hda_nid_t nid = capture_mixers[adc_idx]; 9857 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 9858 unsigned int i, idx; 9859 9860 idx = ucontrol->value.enumerated.item[0]; 9861 if (idx >= imux->num_items) 9862 idx = imux->num_items - 1; 9863 if (*cur_val == idx && !codec->in_resume) 9864 return 0; 9865 for (i = 0; i < imux->num_items; i++) { 9866 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 9867 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 9868 v | (imux->items[i].index << 8)); 9869 } 9870 *cur_val = idx; 9871 return 1; 9872} 9873 9874/* 9875 * 2ch mode 9876 */ 9877static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = { 9878 { 2, NULL } 9879}; 9880 9881/* 9882 * 6ch mode 9883 */ 9884static struct hda_verb alc861vd_6stack_ch6_init[] = { 9885 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9886 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9887 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9888 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9889 { } /* end */ 9890}; 9891 9892/* 9893 * 8ch mode 9894 */ 9895static struct hda_verb alc861vd_6stack_ch8_init[] = { 9896 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9897 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9898 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9899 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9900 { } /* end */ 9901}; 9902 9903static struct hda_channel_mode alc861vd_6stack_modes[2] = { 9904 { 6, alc861vd_6stack_ch6_init }, 9905 { 8, alc861vd_6stack_ch8_init }, 9906}; 9907 9908static struct snd_kcontrol_new alc861vd_chmode_mixer[] = { 9909 { 9910 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9911 .name = "Channel Mode", 9912 .info = alc_ch_mode_info, 9913 .get = alc_ch_mode_get, 9914 .put = alc_ch_mode_put, 9915 }, 9916 { } /* end */ 9917}; 9918 9919static struct snd_kcontrol_new alc861vd_capture_mixer[] = { 9920 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 9921 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 9922 9923 { 9924 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9925 /* The multiple "Capture Source" controls confuse alsamixer 9926 * So call somewhat different.. 9927 *FIXME: the controls appear in the "playback" view! 9928 */ 9929 /* .name = "Capture Source", */ 9930 .name = "Input Source", 9931 .count = 1, 9932 .info = alc861vd_mux_enum_info, 9933 .get = alc861vd_mux_enum_get, 9934 .put = alc861vd_mux_enum_put, 9935 }, 9936 { } /* end */ 9937}; 9938 9939/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 9940 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 9941 */ 9942static struct snd_kcontrol_new alc861vd_6st_mixer[] = { 9943 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 9944 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 9945 9946 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), 9947 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 9948 9949 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, 9950 HDA_OUTPUT), 9951 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, 9952 HDA_OUTPUT), 9953 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 9954 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 9955 9956 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT), 9957 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 9958 9959 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 9960 9961 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 9962 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 9963 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 9964 9965 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 9966 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 9967 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 9968 9969 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 9970 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 9971 9972 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 9973 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 9974 9975 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 9976 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 9977 9978 { } /* end */ 9979}; 9980 9981static struct snd_kcontrol_new alc861vd_3st_mixer[] = { 9982 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 9983 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 9984 9985 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 9986 9987 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 9988 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 9989 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 9990 9991 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 9992 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 9993 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 9994 9995 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 9996 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 9997 9998 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 9999 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 10000 10001 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 10002 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 10003 10004 { } /* end */ 10005}; 10006 10007static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = { 10008 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10009 /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/ 10010 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 10011 10012 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10013 10014 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 10015 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10016 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10017 10018 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 10019 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10020 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10021 10022 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 10023 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 10024 10025 { } /* end */ 10026}; 10027 10028/* Pin assignment: Front=0x14, HP = 0x15, 10029 * Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d 10030 */ 10031static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { 10032 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10033 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 10034 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 10035 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), 10036 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10037 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10038 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10039 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10040 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT), 10041 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT), 10042 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 10043 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 10044 { 10045 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10046 /* .name = "Capture Source", */ 10047 .name = "Input Source", 10048 .count = 1, 10049 .info = alc882_mux_enum_info, 10050 .get = alc882_mux_enum_get, 10051 .put = alc882_mux_enum_put, 10052 }, 10053 { } /* end */ 10054}; 10055 10056/* 10057 * generic initialization of ADC, input mixers and output mixers 10058 */ 10059static struct hda_verb alc861vd_volume_init_verbs[] = { 10060 /* 10061 * Unmute ADC0 and set the default input to mic-in 10062 */ 10063 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 10064 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10065 10066 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of 10067 * the analog-loopback mixer widget 10068 */ 10069 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 10070 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10071 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10072 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 10073 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 10074 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 10075 10076 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ 10077 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10078 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10079 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 10080 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 10081 10082 /* 10083 * Set up output mixers (0x02 - 0x05) 10084 */ 10085 /* set vol=0 to output mixers */ 10086 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10087 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10088 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10089 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10090 10091 /* set up input amps for analog loopback */ 10092 /* Amp Indices: DAC = 0, mixer = 1 */ 10093 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10094 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10095 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10096 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10097 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10098 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10099 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10100 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10101 10102 { } 10103}; 10104 10105/* 10106 * 3-stack pin configuration: 10107 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b 10108 */ 10109static struct hda_verb alc861vd_3stack_init_verbs[] = { 10110 /* 10111 * Set pin mode and muting 10112 */ 10113 /* set front pin widgets 0x14 for output */ 10114 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10115 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10116 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 10117 10118 /* Mic (rear) pin: input vref at 80% */ 10119 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10120 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10121 /* Front Mic pin: input vref at 80% */ 10122 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10123 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10124 /* Line In pin: input */ 10125 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10126 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10127 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 10128 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 10129 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10130 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 10131 /* CD pin widget for input */ 10132 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10133 10134 { } 10135}; 10136 10137/* 10138 * 6-stack pin configuration: 10139 */ 10140static struct hda_verb alc861vd_6stack_init_verbs[] = { 10141 /* 10142 * Set pin mode and muting 10143 */ 10144 /* set front pin widgets 0x14 for output */ 10145 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10146 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10147 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 10148 10149 /* Rear Pin: output 1 (0x0d) */ 10150 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10151 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10152 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 10153 /* CLFE Pin: output 2 (0x0e) */ 10154 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10155 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10156 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, 10157 /* Side Pin: output 3 (0x0f) */ 10158 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10159 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10160 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, 10161 10162 /* Mic (rear) pin: input vref at 80% */ 10163 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10164 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10165 /* Front Mic pin: input vref at 80% */ 10166 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10167 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10168 /* Line In pin: input */ 10169 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10170 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10171 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 10172 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 10173 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10174 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 10175 /* CD pin widget for input */ 10176 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10177 10178 { } 10179}; 10180 10181static struct hda_verb alc861vd_eapd_verbs[] = { 10182 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, 10183 { } 10184}; 10185 10186static struct hda_verb alc861vd_lenovo_unsol_verbs[] = { 10187 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10188 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10189 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 10190 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 10191 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, 10192 {} 10193}; 10194 10195/* toggle speaker-output according to the hp-jack state */ 10196static void alc861vd_lenovo_hp_automute(struct hda_codec *codec) 10197{ 10198 unsigned int present; 10199 unsigned char bits; 10200 10201 present = snd_hda_codec_read(codec, 0x1b, 0, 10202 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 10203 bits = present ? 0x80 : 0; 10204 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 10205 0x80, bits); 10206 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 10207 0x80, bits); 10208} 10209 10210static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) 10211{ 10212 unsigned int present; 10213 unsigned char bits; 10214 10215 present = snd_hda_codec_read(codec, 0x18, 0, 10216 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 10217 bits = present ? 0x80 : 0; 10218 snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, 10219 0x80, bits); 10220 snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, 10221 0x80, bits); 10222} 10223 10224static void alc861vd_lenovo_automute(struct hda_codec *codec) 10225{ 10226 alc861vd_lenovo_hp_automute(codec); 10227 alc861vd_lenovo_mic_automute(codec); 10228} 10229 10230static void alc861vd_lenovo_unsol_event(struct hda_codec *codec, 10231 unsigned int res) 10232{ 10233 switch (res >> 26) { 10234 case ALC880_HP_EVENT: 10235 alc861vd_lenovo_hp_automute(codec); 10236 break; 10237 case ALC880_MIC_EVENT: 10238 alc861vd_lenovo_mic_automute(codec); 10239 break; 10240 } 10241} 10242 10243static struct hda_verb alc861vd_dallas_verbs[] = { 10244 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10245 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10246 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10247 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10248 10249 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10250 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10251 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10252 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10253 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10254 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10255 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10256 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10257 10258 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10259 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10260 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10261 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10262 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10263 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10264 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10265 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10266 10267 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, 10268 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10269 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, 10270 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10271 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10272 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10273 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10274 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10275 10276 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10277 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 10278 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 10279 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 10280 10281 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10282 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 10283 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 10284 10285 { } /* end */ 10286}; 10287 10288/* toggle speaker-output according to the hp-jack state */ 10289static void alc861vd_dallas_automute(struct hda_codec *codec) 10290{ 10291 unsigned int present; 10292 10293 present = snd_hda_codec_read(codec, 0x15, 0, 10294 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 10295 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 10296 0x80, present ? 0x80 : 0); 10297 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 10298 0x80, present ? 0x80 : 0); 10299} 10300 10301static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res) 10302{ 10303 if ((res >> 26) == ALC880_HP_EVENT) 10304 alc861vd_dallas_automute(codec); 10305} 10306 10307/* pcm configuration: identiacal with ALC880 */ 10308#define alc861vd_pcm_analog_playback alc880_pcm_analog_playback 10309#define alc861vd_pcm_analog_capture alc880_pcm_analog_capture 10310#define alc861vd_pcm_digital_playback alc880_pcm_digital_playback 10311#define alc861vd_pcm_digital_capture alc880_pcm_digital_capture 10312 10313/* 10314 * configuration and preset 10315 */ 10316static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { 10317 [ALC660VD_3ST] = "3stack-660", 10318 [ALC660VD_3ST_DIG]= "3stack-660-digout", 10319 [ALC861VD_3ST] = "3stack", 10320 [ALC861VD_3ST_DIG] = "3stack-digout", 10321 [ALC861VD_6ST_DIG] = "6stack-digout", 10322 [ALC861VD_LENOVO] = "lenovo", 10323 [ALC861VD_DALLAS] = "dallas", 10324 [ALC861VD_AUTO] = "auto", 10325}; 10326 10327static struct snd_pci_quirk alc861vd_cfg_tbl[] = { 10328 SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), 10329 SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), 10330 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG), 10331 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), 10332 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), 10333 10334 SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS), 10335 SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), 10336 SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), 10337 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), 10338 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), 10339 SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG), 10340 {} 10341}; 10342 10343static struct alc_config_preset alc861vd_presets[] = { 10344 [ALC660VD_3ST] = { 10345 .mixers = { alc861vd_3st_mixer }, 10346 .init_verbs = { alc861vd_volume_init_verbs, 10347 alc861vd_3stack_init_verbs }, 10348 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), 10349 .dac_nids = alc660vd_dac_nids, 10350 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10351 .adc_nids = alc861vd_adc_nids, 10352 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10353 .channel_mode = alc861vd_3stack_2ch_modes, 10354 .input_mux = &alc861vd_capture_source, 10355 }, 10356 [ALC660VD_3ST_DIG] = { 10357 .mixers = { alc861vd_3st_mixer }, 10358 .init_verbs = { alc861vd_volume_init_verbs, 10359 alc861vd_3stack_init_verbs }, 10360 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), 10361 .dac_nids = alc660vd_dac_nids, 10362 .dig_out_nid = ALC861VD_DIGOUT_NID, 10363 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10364 .adc_nids = alc861vd_adc_nids, 10365 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10366 .channel_mode = alc861vd_3stack_2ch_modes, 10367 .input_mux = &alc861vd_capture_source, 10368 }, 10369 [ALC861VD_3ST] = { 10370 .mixers = { alc861vd_3st_mixer }, 10371 .init_verbs = { alc861vd_volume_init_verbs, 10372 alc861vd_3stack_init_verbs }, 10373 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10374 .dac_nids = alc861vd_dac_nids, 10375 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10376 .channel_mode = alc861vd_3stack_2ch_modes, 10377 .input_mux = &alc861vd_capture_source, 10378 }, 10379 [ALC861VD_3ST_DIG] = { 10380 .mixers = { alc861vd_3st_mixer }, 10381 .init_verbs = { alc861vd_volume_init_verbs, 10382 alc861vd_3stack_init_verbs }, 10383 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10384 .dac_nids = alc861vd_dac_nids, 10385 .dig_out_nid = ALC861VD_DIGOUT_NID, 10386 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10387 .channel_mode = alc861vd_3stack_2ch_modes, 10388 .input_mux = &alc861vd_capture_source, 10389 }, 10390 [ALC861VD_6ST_DIG] = { 10391 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer }, 10392 .init_verbs = { alc861vd_volume_init_verbs, 10393 alc861vd_6stack_init_verbs }, 10394 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10395 .dac_nids = alc861vd_dac_nids, 10396 .dig_out_nid = ALC861VD_DIGOUT_NID, 10397 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes), 10398 .channel_mode = alc861vd_6stack_modes, 10399 .input_mux = &alc861vd_capture_source, 10400 }, 10401 [ALC861VD_LENOVO] = { 10402 .mixers = { alc861vd_lenovo_mixer }, 10403 .init_verbs = { alc861vd_volume_init_verbs, 10404 alc861vd_3stack_init_verbs, 10405 alc861vd_eapd_verbs, 10406 alc861vd_lenovo_unsol_verbs }, 10407 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), 10408 .dac_nids = alc660vd_dac_nids, 10409 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10410 .adc_nids = alc861vd_adc_nids, 10411 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10412 .channel_mode = alc861vd_3stack_2ch_modes, 10413 .input_mux = &alc861vd_capture_source, 10414 .unsol_event = alc861vd_lenovo_unsol_event, 10415 .init_hook = alc861vd_lenovo_automute, 10416 }, 10417 [ALC861VD_DALLAS] = { 10418 .mixers = { alc861vd_dallas_mixer }, 10419 .init_verbs = { alc861vd_dallas_verbs }, 10420 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10421 .dac_nids = alc861vd_dac_nids, 10422 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10423 .adc_nids = alc861vd_adc_nids, 10424 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10425 .channel_mode = alc861vd_3stack_2ch_modes, 10426 .input_mux = &alc861vd_dallas_capture_source, 10427 .unsol_event = alc861vd_dallas_unsol_event, 10428 .init_hook = alc861vd_dallas_automute, 10429 }, 10430}; 10431 10432/* 10433 * BIOS auto configuration 10434 */ 10435static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec, 10436 hda_nid_t nid, int pin_type, int dac_idx) 10437{ 10438 /* set as output */ 10439 snd_hda_codec_write(codec, nid, 0, 10440 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); 10441 snd_hda_codec_write(codec, nid, 0, 10442 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 10443} 10444 10445static void alc861vd_auto_init_multi_out(struct hda_codec *codec) 10446{ 10447 struct alc_spec *spec = codec->spec; 10448 int i; 10449 10450 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 10451 for (i = 0; i <= HDA_SIDE; i++) { 10452 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 10453 int pin_type = get_pin_type(spec->autocfg.line_out_type); 10454 if (nid) 10455 alc861vd_auto_set_output_and_unmute(codec, nid, 10456 pin_type, i); 10457 } 10458} 10459 10460 10461static void alc861vd_auto_init_hp_out(struct hda_codec *codec) 10462{ 10463 struct alc_spec *spec = codec->spec; 10464 hda_nid_t pin; 10465 10466 pin = spec->autocfg.hp_pins[0]; 10467 if (pin) /* connect to front and use dac 0 */ 10468 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 10469} 10470 10471#define alc861vd_is_input_pin(nid) alc880_is_input_pin(nid) 10472#define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID 10473 10474static void alc861vd_auto_init_analog_input(struct hda_codec *codec) 10475{ 10476 struct alc_spec *spec = codec->spec; 10477 int i; 10478 10479 for (i = 0; i < AUTO_PIN_LAST; i++) { 10480 hda_nid_t nid = spec->autocfg.input_pins[i]; 10481 if (alc861vd_is_input_pin(nid)) { 10482 snd_hda_codec_write(codec, nid, 0, 10483 AC_VERB_SET_PIN_WIDGET_CONTROL, 10484 i <= AUTO_PIN_FRONT_MIC ? 10485 PIN_VREF80 : PIN_IN); 10486 if (nid != ALC861VD_PIN_CD_NID) 10487 snd_hda_codec_write(codec, nid, 0, 10488 AC_VERB_SET_AMP_GAIN_MUTE, 10489 AMP_OUT_MUTE); 10490 } 10491 } 10492} 10493 10494#define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02) 10495#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c) 10496 10497/* add playback controls from the parsed DAC table */ 10498/* Based on ALC880 version. But ALC861VD has separate, 10499 * different NIDs for mute/unmute switch and volume control */ 10500static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, 10501 const struct auto_pin_cfg *cfg) 10502{ 10503 char name[32]; 10504 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"}; 10505 hda_nid_t nid_v, nid_s; 10506 int i, err; 10507 10508 for (i = 0; i < cfg->line_outs; i++) { 10509 if (!spec->multiout.dac_nids[i]) 10510 continue; 10511 nid_v = alc861vd_idx_to_mixer_vol( 10512 alc880_dac_to_idx( 10513 spec->multiout.dac_nids[i])); 10514 nid_s = alc861vd_idx_to_mixer_switch( 10515 alc880_dac_to_idx( 10516 spec->multiout.dac_nids[i])); 10517 10518 if (i == 2) { 10519 /* Center/LFE */ 10520 err = add_control(spec, ALC_CTL_WIDGET_VOL, 10521 "Center Playback Volume", 10522 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0, 10523 HDA_OUTPUT)); 10524 if (err < 0) 10525 return err; 10526 err = add_control(spec, ALC_CTL_WIDGET_VOL, 10527 "LFE Playback Volume", 10528 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0, 10529 HDA_OUTPUT)); 10530 if (err < 0) 10531 return err; 10532 err = add_control(spec, ALC_CTL_BIND_MUTE, 10533 "Center Playback Switch", 10534 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2, 10535 HDA_INPUT)); 10536 if (err < 0) 10537 return err; 10538 err = add_control(spec, ALC_CTL_BIND_MUTE, 10539 "LFE Playback Switch", 10540 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2, 10541 HDA_INPUT)); 10542 if (err < 0) 10543 return err; 10544 } else { 10545 sprintf(name, "%s Playback Volume", chname[i]); 10546 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 10547 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, 10548 HDA_OUTPUT)); 10549 if (err < 0) 10550 return err; 10551 sprintf(name, "%s Playback Switch", chname[i]); 10552 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 10553 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, 10554 HDA_INPUT)); 10555 if (err < 0) 10556 return err; 10557 } 10558 } 10559 return 0; 10560} 10561 10562/* add playback controls for speaker and HP outputs */ 10563/* Based on ALC880 version. But ALC861VD has separate, 10564 * different NIDs for mute/unmute switch and volume control */ 10565static int alc861vd_auto_create_extra_out(struct alc_spec *spec, 10566 hda_nid_t pin, const char *pfx) 10567{ 10568 hda_nid_t nid_v, nid_s; 10569 int err; 10570 char name[32]; 10571 10572 if (!pin) 10573 return 0; 10574 10575 if (alc880_is_fixed_pin(pin)) { 10576 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 10577 /* specify the DAC as the extra output */ 10578 if (!spec->multiout.hp_nid) 10579 spec->multiout.hp_nid = nid_v; 10580 else 10581 spec->multiout.extra_out_nid[0] = nid_v; 10582 /* control HP volume/switch on the output mixer amp */ 10583 nid_v = alc861vd_idx_to_mixer_vol( 10584 alc880_fixed_pin_idx(pin)); 10585 nid_s = alc861vd_idx_to_mixer_switch( 10586 alc880_fixed_pin_idx(pin)); 10587 10588 sprintf(name, "%s Playback Volume", pfx); 10589 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 10590 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT)); 10591 if (err < 0) 10592 return err; 10593 sprintf(name, "%s Playback Switch", pfx); 10594 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 10595 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT)); 10596 if (err < 0) 10597 return err; 10598 } else if (alc880_is_multi_pin(pin)) { 10599 /* set manual connection */ 10600 /* we have only a switch on HP-out PIN */ 10601 sprintf(name, "%s Playback Switch", pfx); 10602 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 10603 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 10604 if (err < 0) 10605 return err; 10606 } 10607 return 0; 10608} 10609 10610/* parse the BIOS configuration and set up the alc_spec 10611 * return 1 if successful, 0 if the proper config is not found, 10612 * or a negative error code 10613 * Based on ALC880 version - had to change it to override 10614 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */ 10615static int alc861vd_parse_auto_config(struct hda_codec *codec) 10616{ 10617 struct alc_spec *spec = codec->spec; 10618 int err; 10619 static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; 10620 10621 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 10622 alc861vd_ignore); 10623 if (err < 0) 10624 return err; 10625 if (!spec->autocfg.line_outs) 10626 return 0; /* can't find valid BIOS pin config */ 10627 10628 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 10629 if (err < 0) 10630 return err; 10631 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg); 10632 if (err < 0) 10633 return err; 10634 err = alc861vd_auto_create_extra_out(spec, 10635 spec->autocfg.speaker_pins[0], 10636 "Speaker"); 10637 if (err < 0) 10638 return err; 10639 err = alc861vd_auto_create_extra_out(spec, 10640 spec->autocfg.hp_pins[0], 10641 "Headphone"); 10642 if (err < 0) 10643 return err; 10644 err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg); 10645 if (err < 0) 10646 return err; 10647 10648 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 10649 10650 if (spec->autocfg.dig_out_pin) 10651 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; 10652 10653 if (spec->kctl_alloc) 10654 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 10655 10656 spec->init_verbs[spec->num_init_verbs++] 10657 = alc861vd_volume_init_verbs; 10658 10659 spec->num_mux_defs = 1; 10660 spec->input_mux = &spec->private_imux; 10661 10662 return 1; 10663} 10664 10665/* additional initialization for auto-configuration model */ 10666static void alc861vd_auto_init(struct hda_codec *codec) 10667{ 10668 alc861vd_auto_init_multi_out(codec); 10669 alc861vd_auto_init_hp_out(codec); 10670 alc861vd_auto_init_analog_input(codec); 10671} 10672 10673static int patch_alc861vd(struct hda_codec *codec) 10674{ 10675 struct alc_spec *spec; 10676 int err, board_config; 10677 10678 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 10679 if (spec == NULL) 10680 return -ENOMEM; 10681 10682 codec->spec = spec; 10683 10684 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST, 10685 alc861vd_models, 10686 alc861vd_cfg_tbl); 10687 10688 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) { 10689 printk(KERN_INFO "hda_codec: Unknown model for ALC660VD/" 10690 "ALC861VD, trying auto-probe from BIOS...\n"); 10691 board_config = ALC861VD_AUTO; 10692 } 10693 10694 if (board_config == ALC861VD_AUTO) { 10695 /* automatic parse from the BIOS config */ 10696 err = alc861vd_parse_auto_config(codec); 10697 if (err < 0) { 10698 alc_free(codec); 10699 return err; 10700 } else if (!err) { 10701 printk(KERN_INFO 10702 "hda_codec: Cannot set up configuration " 10703 "from BIOS. Using base mode...\n"); 10704 board_config = ALC861VD_3ST; 10705 } 10706 } 10707 10708 if (board_config != ALC861VD_AUTO) 10709 setup_preset(spec, &alc861vd_presets[board_config]); 10710 10711 spec->stream_name_analog = "ALC861VD Analog"; 10712 spec->stream_analog_playback = &alc861vd_pcm_analog_playback; 10713 spec->stream_analog_capture = &alc861vd_pcm_analog_capture; 10714 10715 spec->stream_name_digital = "ALC861VD Digital"; 10716 spec->stream_digital_playback = &alc861vd_pcm_digital_playback; 10717 spec->stream_digital_capture = &alc861vd_pcm_digital_capture; 10718 10719 spec->adc_nids = alc861vd_adc_nids; 10720 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); 10721 10722 spec->mixers[spec->num_mixers] = alc861vd_capture_mixer; 10723 spec->num_mixers++; 10724 10725 codec->patch_ops = alc_patch_ops; 10726 10727 if (board_config == ALC861VD_AUTO) 10728 spec->init_hook = alc861vd_auto_init; 10729 10730 return 0; 10731} 10732 10733/* 10734 * ALC662 support 10735 * 10736 * ALC662 is almost identical with ALC880 but has cleaner and more flexible 10737 * configuration. Each pin widget can choose any input DACs and a mixer. 10738 * Each ADC is connected from a mixer of all inputs. This makes possible 10739 * 6-channel independent captures. 10740 * 10741 * In addition, an independent DAC for the multi-playback (not used in this 10742 * driver yet). 10743 */ 10744#define ALC662_DIGOUT_NID 0x06 10745#define ALC662_DIGIN_NID 0x0a 10746 10747static hda_nid_t alc662_dac_nids[4] = { 10748 /* front, rear, clfe, rear_surr */ 10749 0x02, 0x03, 0x04 10750}; 10751 10752static hda_nid_t alc662_adc_nids[1] = { 10753 /* ADC1-2 */ 10754 0x09, 10755}; 10756/* input MUX */ 10757/* FIXME: should be a matrix-type input source selection */ 10758 10759static struct hda_input_mux alc662_capture_source = { 10760 .num_items = 4, 10761 .items = { 10762 { "Mic", 0x0 }, 10763 { "Front Mic", 0x1 }, 10764 { "Line", 0x2 }, 10765 { "CD", 0x4 }, 10766 }, 10767}; 10768 10769static struct hda_input_mux alc662_lenovo_101e_capture_source = { 10770 .num_items = 2, 10771 .items = { 10772 { "Mic", 0x1 }, 10773 { "Line", 0x2 }, 10774 }, 10775}; 10776#define alc662_mux_enum_info alc_mux_enum_info 10777#define alc662_mux_enum_get alc_mux_enum_get 10778 10779static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol, 10780 struct snd_ctl_elem_value *ucontrol) 10781{ 10782 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 10783 struct alc_spec *spec = codec->spec; 10784 const struct hda_input_mux *imux = spec->input_mux; 10785 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 10786 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; 10787 hda_nid_t nid = capture_mixers[adc_idx]; 10788 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 10789 unsigned int i, idx; 10790 10791 idx = ucontrol->value.enumerated.item[0]; 10792 if (idx >= imux->num_items) 10793 idx = imux->num_items - 1; 10794 if (*cur_val == idx && !codec->in_resume) 10795 return 0; 10796 for (i = 0; i < imux->num_items; i++) { 10797 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 10798 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 10799 v | (imux->items[i].index << 8)); 10800 } 10801 *cur_val = idx; 10802 return 1; 10803} 10804/* 10805 * 2ch mode 10806 */ 10807static struct hda_channel_mode alc662_3ST_2ch_modes[1] = { 10808 { 2, NULL } 10809}; 10810 10811/* 10812 * 2ch mode 10813 */ 10814static struct hda_verb alc662_3ST_ch2_init[] = { 10815 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 10816 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 10817 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 10818 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 10819 { } /* end */ 10820}; 10821 10822/* 10823 * 6ch mode 10824 */ 10825static struct hda_verb alc662_3ST_ch6_init[] = { 10826 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10827 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 10828 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, 10829 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10830 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 10831 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, 10832 { } /* end */ 10833}; 10834 10835static struct hda_channel_mode alc662_3ST_6ch_modes[2] = { 10836 { 2, alc662_3ST_ch2_init }, 10837 { 6, alc662_3ST_ch6_init }, 10838}; 10839 10840/* 10841 * 2ch mode 10842 */ 10843static struct hda_verb alc662_sixstack_ch6_init[] = { 10844 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 10845 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 10846 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10847 { } /* end */ 10848}; 10849 10850/* 10851 * 6ch mode 10852 */ 10853static struct hda_verb alc662_sixstack_ch8_init[] = { 10854 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10855 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10856 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10857 { } /* end */ 10858}; 10859 10860static struct hda_channel_mode alc662_5stack_modes[2] = { 10861 { 2, alc662_sixstack_ch6_init }, 10862 { 6, alc662_sixstack_ch8_init }, 10863}; 10864 10865/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 10866 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 10867 */ 10868 10869static struct snd_kcontrol_new alc662_base_mixer[] = { 10870 /* output mixer control */ 10871 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), 10872 HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT), 10873 HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT), 10874 HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT), 10875 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), 10876 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), 10877 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), 10878 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), 10879 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10880 10881 /*Input mixer control */ 10882 HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT), 10883 HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT), 10884 HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT), 10885 HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT), 10886 HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT), 10887 HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT), 10888 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT), 10889 HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT), 10890 10891 /* Capture mixer control */ 10892 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 10893 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 10894 { 10895 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10896 .name = "Capture Source", 10897 .count = 1, 10898 .info = alc_mux_enum_info, 10899 .get = alc_mux_enum_get, 10900 .put = alc_mux_enum_put, 10901 }, 10902 { } /* end */ 10903}; 10904 10905static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = { 10906 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10907 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), 10908 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10909 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 10910 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 10911 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 10912 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 10913 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10914 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10915 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10916 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10917 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 10918 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 10919 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 10920 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 10921 { 10922 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10923 /* .name = "Capture Source", */ 10924 .name = "Input Source", 10925 .count = 1, 10926 .info = alc662_mux_enum_info, 10927 .get = alc662_mux_enum_get, 10928 .put = alc662_mux_enum_put, 10929 }, 10930 { } /* end */ 10931}; 10932 10933static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = { 10934 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10935 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), 10936 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), 10937 HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT), 10938 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), 10939 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), 10940 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), 10941 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), 10942 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10943 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 10944 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 10945 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 10946 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 10947 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10948 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10949 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10950 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10951 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 10952 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 10953 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 10954 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 10955 { 10956 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10957 /* .name = "Capture Source", */ 10958 .name = "Input Source", 10959 .count = 1, 10960 .info = alc662_mux_enum_info, 10961 .get = alc662_mux_enum_get, 10962 .put = alc662_mux_enum_put, 10963 }, 10964 { } /* end */ 10965}; 10966 10967static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = { 10968 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10969 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), 10970 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x03, 0x0, HDA_OUTPUT), 10971 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x03, 2, HDA_INPUT), 10972 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10973 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 10974 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 10975 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10976 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10977 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 10978 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 10979 { 10980 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10981 /* .name = "Capture Source", */ 10982 .name = "Input Source", 10983 .count = 1, 10984 .info = alc662_mux_enum_info, 10985 .get = alc662_mux_enum_get, 10986 .put = alc662_mux_enum_put, 10987 }, 10988 { } /* end */ 10989}; 10990 10991static struct snd_kcontrol_new alc662_chmode_mixer[] = { 10992 { 10993 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10994 .name = "Channel Mode", 10995 .info = alc_ch_mode_info, 10996 .get = alc_ch_mode_get, 10997 .put = alc_ch_mode_put, 10998 }, 10999 { } /* end */ 11000}; 11001 11002static struct hda_verb alc662_init_verbs[] = { 11003 /* ADC: mute amp left and right */ 11004 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 11005 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 11006 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 11007 11008 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11009 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11010 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 11011 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 11012 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 11013 11014 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11015 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11016 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11017 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11018 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11019 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11020 11021 /* Front Pin: output 0 (0x0c) */ 11022 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 11023 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 11024 11025 /* Rear Pin: output 1 (0x0d) */ 11026 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 11027 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 11028 11029 /* CLFE Pin: output 2 (0x0e) */ 11030 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 11031 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 11032 11033 /* Mic (rear) pin: input vref at 80% */ 11034 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 11035 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 11036 /* Front Mic pin: input vref at 80% */ 11037 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 11038 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 11039 /* Line In pin: input */ 11040 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 11041 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 11042 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 11043 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 11044 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 11045 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 11046 /* CD pin widget for input */ 11047 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 11048 11049 /* FIXME: use matrix-type input source selection */ 11050 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 11051 /* Input mixer */ 11052 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11053 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11054 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 11055 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 11056 { } 11057}; 11058 11059static struct hda_verb alc662_sue_init_verbs[] = { 11060 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, 11061 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, 11062 {} 11063}; 11064 11065/* 11066 * generic initialization of ADC, input mixers and output mixers 11067 */ 11068static struct hda_verb alc662_auto_init_verbs[] = { 11069 /* 11070 * Unmute ADC and set the default input to mic-in 11071 */ 11072 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 11073 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11074 11075 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 11076 * mixer widget 11077 * Note: PASD motherboards uses the Line In 2 as the input for front 11078 * panel mic (mic 2) 11079 */ 11080 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 11081 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11082 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11083 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 11084 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 11085 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 11086 11087 /* 11088 * Set up output mixers (0x0c - 0x0f) 11089 */ 11090 /* set vol=0 to output mixers */ 11091 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 11092 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 11093 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 11094 11095 /* set up input amps for analog loopback */ 11096 /* Amp Indices: DAC = 0, mixer = 1 */ 11097 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11098 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11099 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11100 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11101 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11102 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11103 11104 11105 /* FIXME: use matrix-type input source selection */ 11106 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 11107 /* Input mixer */ 11108 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11109 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11110 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 11111 /*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/ 11112 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 11113 11114 { } 11115}; 11116 11117/* capture mixer elements */ 11118static struct snd_kcontrol_new alc662_capture_mixer[] = { 11119 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 11120 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 11121 { 11122 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 11123 /* The multiple "Capture Source" controls confuse alsamixer 11124 * So call somewhat different.. 11125 * FIXME: the controls appear in the "playback" view! 11126 */ 11127 /* .name = "Capture Source", */ 11128 .name = "Input Source", 11129 .count = 1, 11130 .info = alc882_mux_enum_info, 11131 .get = alc882_mux_enum_get, 11132 .put = alc882_mux_enum_put, 11133 }, 11134 { } /* end */ 11135}; 11136 11137static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec) 11138{ 11139 unsigned int present; 11140 unsigned char bits; 11141 11142 present = snd_hda_codec_read(codec, 0x14, 0, 11143 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 11144 bits = present ? 0x80 : 0; 11145 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 11146 0x80, bits); 11147 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 11148 0x80, bits); 11149} 11150 11151static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) 11152{ 11153 unsigned int present; 11154 unsigned char bits; 11155 11156 present = snd_hda_codec_read(codec, 0x1b, 0, 11157 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 11158 bits = present ? 0x80 : 0; 11159 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 11160 0x80, bits); 11161 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 11162 0x80, bits); 11163 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 11164 0x80, bits); 11165 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 11166 0x80, bits); 11167} 11168 11169static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, 11170 unsigned int res) 11171{ 11172 if ((res >> 26) == ALC880_HP_EVENT) 11173 alc662_lenovo_101e_all_automute(codec); 11174 if ((res >> 26) == ALC880_FRONT_EVENT) 11175 alc662_lenovo_101e_ispeaker_automute(codec); 11176} 11177 11178 11179/* pcm configuration: identiacal with ALC880 */ 11180#define alc662_pcm_analog_playback alc880_pcm_analog_playback 11181#define alc662_pcm_analog_capture alc880_pcm_analog_capture 11182#define alc662_pcm_digital_playback alc880_pcm_digital_playback 11183#define alc662_pcm_digital_capture alc880_pcm_digital_capture 11184 11185/* 11186 * configuration and preset 11187 */ 11188static const char *alc662_models[ALC662_MODEL_LAST] = { 11189 [ALC662_3ST_2ch_DIG] = "3stack-dig", 11190 [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig", 11191 [ALC662_3ST_6ch] = "3stack-6ch", 11192 [ALC662_5ST_DIG] = "6stack-dig", 11193 [ALC662_LENOVO_101E] = "lenovo-101e", 11194 [ALC662_AUTO] = "auto", 11195}; 11196 11197static struct snd_pci_quirk alc662_cfg_tbl[] = { 11198 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), 11199 {} 11200}; 11201 11202static struct alc_config_preset alc662_presets[] = { 11203 [ALC662_3ST_2ch_DIG] = { 11204 .mixers = { alc662_3ST_2ch_mixer }, 11205 .init_verbs = { alc662_init_verbs }, 11206 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11207 .dac_nids = alc662_dac_nids, 11208 .dig_out_nid = ALC662_DIGOUT_NID, 11209 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11210 .adc_nids = alc662_adc_nids, 11211 .dig_in_nid = ALC662_DIGIN_NID, 11212 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), 11213 .channel_mode = alc662_3ST_2ch_modes, 11214 .input_mux = &alc662_capture_source, 11215 }, 11216 [ALC662_3ST_6ch_DIG] = { 11217 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, 11218 .init_verbs = { alc662_init_verbs }, 11219 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11220 .dac_nids = alc662_dac_nids, 11221 .dig_out_nid = ALC662_DIGOUT_NID, 11222 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11223 .adc_nids = alc662_adc_nids, 11224 .dig_in_nid = ALC662_DIGIN_NID, 11225 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), 11226 .channel_mode = alc662_3ST_6ch_modes, 11227 .need_dac_fix = 1, 11228 .input_mux = &alc662_capture_source, 11229 }, 11230 [ALC662_3ST_6ch] = { 11231 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, 11232 .init_verbs = { alc662_init_verbs }, 11233 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11234 .dac_nids = alc662_dac_nids, 11235 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11236 .adc_nids = alc662_adc_nids, 11237 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), 11238 .channel_mode = alc662_3ST_6ch_modes, 11239 .need_dac_fix = 1, 11240 .input_mux = &alc662_capture_source, 11241 }, 11242 [ALC662_5ST_DIG] = { 11243 .mixers = { alc662_base_mixer, alc662_chmode_mixer }, 11244 .init_verbs = { alc662_init_verbs }, 11245 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11246 .dac_nids = alc662_dac_nids, 11247 .dig_out_nid = ALC662_DIGOUT_NID, 11248 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11249 .adc_nids = alc662_adc_nids, 11250 .dig_in_nid = ALC662_DIGIN_NID, 11251 .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes), 11252 .channel_mode = alc662_5stack_modes, 11253 .input_mux = &alc662_capture_source, 11254 }, 11255 [ALC662_LENOVO_101E] = { 11256 .mixers = { alc662_lenovo_101e_mixer }, 11257 .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, 11258 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11259 .dac_nids = alc662_dac_nids, 11260 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11261 .adc_nids = alc662_adc_nids, 11262 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), 11263 .channel_mode = alc662_3ST_2ch_modes, 11264 .input_mux = &alc662_lenovo_101e_capture_source, 11265 .unsol_event = alc662_lenovo_101e_unsol_event, 11266 .init_hook = alc662_lenovo_101e_all_automute, 11267 }, 11268 11269}; 11270 11271 11272/* 11273 * BIOS auto configuration 11274 */ 11275 11276/* add playback controls from the parsed DAC table */ 11277static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, 11278 const struct auto_pin_cfg *cfg) 11279{ 11280 char name[32]; 11281 static const char *chname[4] = { 11282 "Front", "Surround", NULL /*CLFE*/, "Side" 11283 }; 11284 hda_nid_t nid; 11285 int i, err; 11286 11287 for (i = 0; i < cfg->line_outs; i++) { 11288 if (!spec->multiout.dac_nids[i]) 11289 continue; 11290 nid = alc880_idx_to_mixer(i); 11291 if (i == 2) { 11292 /* Center/LFE */ 11293 err = add_control(spec, ALC_CTL_WIDGET_VOL, 11294 "Center Playback Volume", 11295 HDA_COMPOSE_AMP_VAL(nid, 1, 0, 11296 HDA_OUTPUT)); 11297 if (err < 0) 11298 return err; 11299 err = add_control(spec, ALC_CTL_WIDGET_VOL, 11300 "LFE Playback Volume", 11301 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 11302 HDA_OUTPUT)); 11303 if (err < 0) 11304 return err; 11305 err = add_control(spec, ALC_CTL_BIND_MUTE, 11306 "Center Playback Switch", 11307 HDA_COMPOSE_AMP_VAL(nid, 1, 2, 11308 HDA_INPUT)); 11309 if (err < 0) 11310 return err; 11311 err = add_control(spec, ALC_CTL_BIND_MUTE, 11312 "LFE Playback Switch", 11313 HDA_COMPOSE_AMP_VAL(nid, 2, 2, 11314 HDA_INPUT)); 11315 if (err < 0) 11316 return err; 11317 } else { 11318 sprintf(name, "%s Playback Volume", chname[i]); 11319 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 11320 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 11321 HDA_OUTPUT)); 11322 if (err < 0) 11323 return err; 11324 sprintf(name, "%s Playback Switch", chname[i]); 11325 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 11326 HDA_COMPOSE_AMP_VAL(nid, 3, 2, 11327 HDA_INPUT)); 11328 if (err < 0) 11329 return err; 11330 } 11331 } 11332 return 0; 11333} 11334 11335/* add playback controls for speaker and HP outputs */ 11336static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, 11337 const char *pfx) 11338{ 11339 hda_nid_t nid; 11340 int err; 11341 char name[32]; 11342 11343 if (!pin) 11344 return 0; 11345 11346 if (alc880_is_fixed_pin(pin)) { 11347 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 11348 /* printk("DAC nid=%x\n",nid); */ 11349 /* specify the DAC as the extra output */ 11350 if (!spec->multiout.hp_nid) 11351 spec->multiout.hp_nid = nid; 11352 else 11353 spec->multiout.extra_out_nid[0] = nid; 11354 /* control HP volume/switch on the output mixer amp */ 11355 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 11356 sprintf(name, "%s Playback Volume", pfx); 11357 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 11358 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 11359 if (err < 0) 11360 return err; 11361 sprintf(name, "%s Playback Switch", pfx); 11362 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 11363 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); 11364 if (err < 0) 11365 return err; 11366 } else if (alc880_is_multi_pin(pin)) { 11367 /* set manual connection */ 11368 /* we have only a switch on HP-out PIN */ 11369 sprintf(name, "%s Playback Switch", pfx); 11370 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 11371 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 11372 if (err < 0) 11373 return err; 11374 } 11375 return 0; 11376} 11377 11378/* create playback/capture controls for input pins */ 11379static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec, 11380 const struct auto_pin_cfg *cfg) 11381{ 11382 struct hda_input_mux *imux = &spec->private_imux; 11383 int i, err, idx; 11384 11385 for (i = 0; i < AUTO_PIN_LAST; i++) { 11386 if (alc880_is_input_pin(cfg->input_pins[i])) { 11387 idx = alc880_input_pin_idx(cfg->input_pins[i]); 11388 err = new_analog_input(spec, cfg->input_pins[i], 11389 auto_pin_cfg_labels[i], 11390 idx, 0x0b); 11391 if (err < 0) 11392 return err; 11393 imux->items[imux->num_items].label = 11394 auto_pin_cfg_labels[i]; 11395 imux->items[imux->num_items].index = 11396 alc880_input_pin_idx(cfg->input_pins[i]); 11397 imux->num_items++; 11398 } 11399 } 11400 return 0; 11401} 11402 11403static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, 11404 hda_nid_t nid, int pin_type, 11405 int dac_idx) 11406{ 11407 /* set as output */ 11408 snd_hda_codec_write(codec, nid, 0, 11409 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); 11410 snd_hda_codec_write(codec, nid, 0, 11411 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 11412 /* need the manual connection? */ 11413 if (alc880_is_multi_pin(nid)) { 11414 struct alc_spec *spec = codec->spec; 11415 int idx = alc880_multi_pin_idx(nid); 11416 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, 11417 AC_VERB_SET_CONNECT_SEL, 11418 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); 11419 } 11420} 11421 11422static void alc662_auto_init_multi_out(struct hda_codec *codec) 11423{ 11424 struct alc_spec *spec = codec->spec; 11425 int i; 11426 11427 for (i = 0; i <= HDA_SIDE; i++) { 11428 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 11429 int pin_type = get_pin_type(spec->autocfg.line_out_type); 11430 if (nid) 11431 alc662_auto_set_output_and_unmute(codec, nid, pin_type, 11432 i); 11433 } 11434} 11435 11436static void alc662_auto_init_hp_out(struct hda_codec *codec) 11437{ 11438 struct alc_spec *spec = codec->spec; 11439 hda_nid_t pin; 11440 11441 pin = spec->autocfg.hp_pins[0]; 11442 if (pin) /* connect to front */ 11443 /* use dac 0 */ 11444 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 11445} 11446 11447#define alc662_is_input_pin(nid) alc880_is_input_pin(nid) 11448#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID 11449 11450static void alc662_auto_init_analog_input(struct hda_codec *codec) 11451{ 11452 struct alc_spec *spec = codec->spec; 11453 int i; 11454 11455 for (i = 0; i < AUTO_PIN_LAST; i++) { 11456 hda_nid_t nid = spec->autocfg.input_pins[i]; 11457 if (alc662_is_input_pin(nid)) { 11458 snd_hda_codec_write(codec, nid, 0, 11459 AC_VERB_SET_PIN_WIDGET_CONTROL, 11460 (i <= AUTO_PIN_FRONT_MIC ? 11461 PIN_VREF80 : PIN_IN)); 11462 if (nid != ALC662_PIN_CD_NID) 11463 snd_hda_codec_write(codec, nid, 0, 11464 AC_VERB_SET_AMP_GAIN_MUTE, 11465 AMP_OUT_MUTE); 11466 } 11467 } 11468} 11469 11470static int alc662_parse_auto_config(struct hda_codec *codec) 11471{ 11472 struct alc_spec *spec = codec->spec; 11473 int err; 11474 static hda_nid_t alc662_ignore[] = { 0x1d, 0 }; 11475 11476 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 11477 alc662_ignore); 11478 if (err < 0) 11479 return err; 11480 if (!spec->autocfg.line_outs) 11481 return 0; /* can't find valid BIOS pin config */ 11482 11483 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 11484 if (err < 0) 11485 return err; 11486 err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); 11487 if (err < 0) 11488 return err; 11489 err = alc662_auto_create_extra_out(spec, 11490 spec->autocfg.speaker_pins[0], 11491 "Speaker"); 11492 if (err < 0) 11493 return err; 11494 err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], 11495 "Headphone"); 11496 if (err < 0) 11497 return err; 11498 err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg); 11499 if (err < 0) 11500 return err; 11501 11502 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 11503 11504 if (spec->autocfg.dig_out_pin) 11505 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; 11506 11507 if (spec->kctl_alloc) 11508 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 11509 11510 spec->num_mux_defs = 1; 11511 spec->input_mux = &spec->private_imux; 11512 11513 spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs; 11514 spec->mixers[spec->num_mixers] = alc662_capture_mixer; 11515 spec->num_mixers++; 11516 return 1; 11517} 11518 11519/* additional initialization for auto-configuration model */ 11520static void alc662_auto_init(struct hda_codec *codec) 11521{ 11522 alc662_auto_init_multi_out(codec); 11523 alc662_auto_init_hp_out(codec); 11524 alc662_auto_init_analog_input(codec); 11525} 11526 11527static int patch_alc662(struct hda_codec *codec) 11528{ 11529 struct alc_spec *spec; 11530 int err, board_config; 11531 11532 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 11533 if (!spec) 11534 return -ENOMEM; 11535 11536 codec->spec = spec; 11537 11538 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, 11539 alc662_models, 11540 alc662_cfg_tbl); 11541 if (board_config < 0) { 11542 printk(KERN_INFO "hda_codec: Unknown model for ALC662, " 11543 "trying auto-probe from BIOS...\n"); 11544 board_config = ALC662_AUTO; 11545 } 11546 11547 if (board_config == ALC662_AUTO) { 11548 /* automatic parse from the BIOS config */ 11549 err = alc662_parse_auto_config(codec); 11550 if (err < 0) { 11551 alc_free(codec); 11552 return err; 11553 } else if (!err) { 11554 printk(KERN_INFO 11555 "hda_codec: Cannot set up configuration " 11556 "from BIOS. Using base mode...\n"); 11557 board_config = ALC662_3ST_2ch_DIG; 11558 } 11559 } 11560 11561 if (board_config != ALC662_AUTO) 11562 setup_preset(spec, &alc662_presets[board_config]); 11563 11564 spec->stream_name_analog = "ALC662 Analog"; 11565 spec->stream_analog_playback = &alc662_pcm_analog_playback; 11566 spec->stream_analog_capture = &alc662_pcm_analog_capture; 11567 11568 spec->stream_name_digital = "ALC662 Digital"; 11569 spec->stream_digital_playback = &alc662_pcm_digital_playback; 11570 spec->stream_digital_capture = &alc662_pcm_digital_capture; 11571 11572 if (!spec->adc_nids && spec->input_mux) { 11573 spec->adc_nids = alc662_adc_nids; 11574 spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); 11575 } 11576 11577 codec->patch_ops = alc_patch_ops; 11578 if (board_config == ALC662_AUTO) 11579 spec->init_hook = alc662_auto_init; 11580 11581 return 0; 11582} 11583 11584/* 11585 * patch entries 11586 */ 11587struct hda_codec_preset snd_hda_preset_realtek[] = { 11588 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, 11589 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, 11590 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 }, 11591 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", 11592 .patch = patch_alc861 }, 11593 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, 11594 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, 11595 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd }, 11596 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2", 11597 .patch = patch_alc883 }, 11598 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", 11599 .patch = patch_alc662 }, 11600 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, 11601 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, 11602 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, 11603 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, 11604 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, 11605 {} /* terminator */ 11606}; 11607