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