patch_realtek.c revision e87f97a3e842a816f30f087d5bfac68ef2afaef2
1/* 2 * Universal Interface for Intel High Definition Audio Codec 3 * 4 * HD audio interface patch for ALC 260/880/882 codecs 5 * 6 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw> 7 * PeiSen Hou <pshou@realtek.com.tw> 8 * Takashi Iwai <tiwai@suse.de> 9 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au> 10 * 11 * This driver is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This driver is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26#include <sound/driver.h> 27#include <linux/init.h> 28#include <linux/delay.h> 29#include <linux/slab.h> 30#include <linux/pci.h> 31#include <sound/core.h> 32#include "hda_codec.h" 33#include "hda_local.h" 34 35#define ALC880_FRONT_EVENT 0x01 36#define ALC880_DCVOL_EVENT 0x02 37#define ALC880_HP_EVENT 0x04 38#define ALC880_MIC_EVENT 0x08 39 40/* ALC880 board config type */ 41enum { 42 ALC880_3ST, 43 ALC880_3ST_DIG, 44 ALC880_5ST, 45 ALC880_5ST_DIG, 46 ALC880_W810, 47 ALC880_Z71V, 48 ALC880_6ST, 49 ALC880_6ST_DIG, 50 ALC880_F1734, 51 ALC880_ASUS, 52 ALC880_ASUS_DIG, 53 ALC880_ASUS_W1V, 54 ALC880_ASUS_DIG2, 55 ALC880_FUJITSU, 56 ALC880_UNIWILL_DIG, 57 ALC880_UNIWILL, 58 ALC880_UNIWILL_P53, 59 ALC880_CLEVO, 60 ALC880_TCL_S700, 61 ALC880_LG, 62 ALC880_LG_LW, 63#ifdef CONFIG_SND_DEBUG 64 ALC880_TEST, 65#endif 66 ALC880_AUTO, 67 ALC880_MODEL_LAST /* last tag */ 68}; 69 70/* ALC260 models */ 71enum { 72 ALC260_BASIC, 73 ALC260_HP, 74 ALC260_HP_3013, 75 ALC260_FUJITSU_S702X, 76 ALC260_ACER, 77 ALC260_WILL, 78 ALC260_REPLACER_672V, 79#ifdef CONFIG_SND_DEBUG 80 ALC260_TEST, 81#endif 82 ALC260_AUTO, 83 ALC260_MODEL_LAST /* last tag */ 84}; 85 86/* ALC262 models */ 87enum { 88 ALC262_BASIC, 89 ALC262_HIPPO, 90 ALC262_HIPPO_1, 91 ALC262_FUJITSU, 92 ALC262_HP_BPC, 93 ALC262_HP_BPC_D7000_WL, 94 ALC262_HP_BPC_D7000_WF, 95 ALC262_BENQ_ED8, 96 ALC262_SONY_ASSAMD, 97 ALC262_BENQ_T31, 98 ALC262_AUTO, 99 ALC262_MODEL_LAST /* last tag */ 100}; 101 102/* ALC268 models */ 103enum { 104 ALC268_3ST, 105 ALC268_AUTO, 106 ALC268_MODEL_LAST /* last tag */ 107}; 108 109/* ALC861 models */ 110enum { 111 ALC861_3ST, 112 ALC660_3ST, 113 ALC861_3ST_DIG, 114 ALC861_6ST_DIG, 115 ALC861_UNIWILL_M31, 116 ALC861_TOSHIBA, 117 ALC861_ASUS, 118 ALC861_ASUS_LAPTOP, 119 ALC861_AUTO, 120 ALC861_MODEL_LAST, 121}; 122 123/* ALC861-VD models */ 124enum { 125 ALC660VD_3ST, 126 ALC660VD_3ST_DIG, 127 ALC861VD_3ST, 128 ALC861VD_3ST_DIG, 129 ALC861VD_6ST_DIG, 130 ALC861VD_LENOVO, 131 ALC861VD_DALLAS, 132 ALC861VD_AUTO, 133 ALC861VD_MODEL_LAST, 134}; 135 136/* ALC662 models */ 137enum { 138 ALC662_3ST_2ch_DIG, 139 ALC662_3ST_6ch_DIG, 140 ALC662_3ST_6ch, 141 ALC662_5ST_DIG, 142 ALC662_LENOVO_101E, 143 ALC662_AUTO, 144 ALC662_MODEL_LAST, 145}; 146 147/* ALC882 models */ 148enum { 149 ALC882_3ST_DIG, 150 ALC882_6ST_DIG, 151 ALC882_ARIMA, 152 ALC882_W2JC, 153 ALC882_TARGA, 154 ALC882_ASUS_A7J, 155 ALC885_MACPRO, 156 ALC882_AUTO, 157 ALC882_MODEL_LAST, 158}; 159 160/* ALC883 models */ 161enum { 162 ALC883_3ST_2ch_DIG, 163 ALC883_3ST_6ch_DIG, 164 ALC883_3ST_6ch, 165 ALC883_6ST_DIG, 166 ALC883_TARGA_DIG, 167 ALC883_TARGA_2ch_DIG, 168 ALC883_ACER, 169 ALC883_MEDION, 170 ALC883_MEDION_MD2, 171 ALC883_LAPTOP_EAPD, 172 ALC883_LENOVO_101E_2ch, 173 ALC883_LENOVO_NB0763, 174 ALC888_LENOVO_MS7195_DIG, 175 ALC888_HP_NETTLE, 176 ALC888_HP_LUCKNOW, 177 ALC883_AUTO, 178 ALC883_MODEL_LAST, 179}; 180 181/* for GPIO Poll */ 182#define GPIO_MASK 0x03 183 184struct alc_spec { 185 /* codec parameterization */ 186 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ 187 unsigned int num_mixers; 188 189 const struct hda_verb *init_verbs[5]; /* initialization verbs 190 * don't forget NULL 191 * termination! 192 */ 193 unsigned int num_init_verbs; 194 195 char *stream_name_analog; /* analog PCM stream */ 196 struct hda_pcm_stream *stream_analog_playback; 197 struct hda_pcm_stream *stream_analog_capture; 198 199 char *stream_name_digital; /* digital PCM stream */ 200 struct hda_pcm_stream *stream_digital_playback; 201 struct hda_pcm_stream *stream_digital_capture; 202 203 /* playback */ 204 struct hda_multi_out multiout; /* playback set-up 205 * max_channels, dacs must be set 206 * dig_out_nid and hp_nid are optional 207 */ 208 209 /* capture */ 210 unsigned int num_adc_nids; 211 hda_nid_t *adc_nids; 212 hda_nid_t dig_in_nid; /* digital-in NID; optional */ 213 214 /* capture source */ 215 unsigned int num_mux_defs; 216 const struct hda_input_mux *input_mux; 217 unsigned int cur_mux[3]; 218 219 /* channel model */ 220 const struct hda_channel_mode *channel_mode; 221 int num_channel_mode; 222 int need_dac_fix; 223 224 /* PCM information */ 225 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ 226 227 /* dynamic controls, init_verbs and input_mux */ 228 struct auto_pin_cfg autocfg; 229 unsigned int num_kctl_alloc, num_kctl_used; 230 struct snd_kcontrol_new *kctl_alloc; 231 struct hda_input_mux private_imux; 232 hda_nid_t private_dac_nids[5]; 233 234 /* hooks */ 235 void (*init_hook)(struct hda_codec *codec); 236 void (*unsol_event)(struct hda_codec *codec, unsigned int res); 237 238 /* for pin sensing */ 239 unsigned int sense_updated: 1; 240 unsigned int jack_present: 1; 241}; 242 243/* 244 * configuration template - to be copied to the spec instance 245 */ 246struct alc_config_preset { 247 struct snd_kcontrol_new *mixers[5]; /* should be identical size 248 * with spec 249 */ 250 const struct hda_verb *init_verbs[5]; 251 unsigned int num_dacs; 252 hda_nid_t *dac_nids; 253 hda_nid_t dig_out_nid; /* optional */ 254 hda_nid_t hp_nid; /* optional */ 255 unsigned int num_adc_nids; 256 hda_nid_t *adc_nids; 257 hda_nid_t dig_in_nid; 258 unsigned int num_channel_mode; 259 const struct hda_channel_mode *channel_mode; 260 int need_dac_fix; 261 unsigned int num_mux_defs; 262 const struct hda_input_mux *input_mux; 263 void (*unsol_event)(struct hda_codec *, unsigned int); 264 void (*init_hook)(struct hda_codec *); 265}; 266 267 268/* 269 * input MUX handling 270 */ 271static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, 272 struct snd_ctl_elem_info *uinfo) 273{ 274 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 275 struct alc_spec *spec = codec->spec; 276 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id); 277 if (mux_idx >= spec->num_mux_defs) 278 mux_idx = 0; 279 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); 280} 281 282static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, 283 struct snd_ctl_elem_value *ucontrol) 284{ 285 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 286 struct alc_spec *spec = codec->spec; 287 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 288 289 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; 290 return 0; 291} 292 293static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, 294 struct snd_ctl_elem_value *ucontrol) 295{ 296 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 297 struct alc_spec *spec = codec->spec; 298 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 299 unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; 300 return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol, 301 spec->adc_nids[adc_idx], 302 &spec->cur_mux[adc_idx]); 303} 304 305 306/* 307 * channel mode setting 308 */ 309static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, 310 struct snd_ctl_elem_info *uinfo) 311{ 312 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 313 struct alc_spec *spec = codec->spec; 314 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, 315 spec->num_channel_mode); 316} 317 318static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, 319 struct snd_ctl_elem_value *ucontrol) 320{ 321 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 322 struct alc_spec *spec = codec->spec; 323 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, 324 spec->num_channel_mode, 325 spec->multiout.max_channels); 326} 327 328static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, 329 struct snd_ctl_elem_value *ucontrol) 330{ 331 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 332 struct alc_spec *spec = codec->spec; 333 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, 334 spec->num_channel_mode, 335 &spec->multiout.max_channels); 336 if (err >= 0 && spec->need_dac_fix) 337 spec->multiout.num_dacs = spec->multiout.max_channels / 2; 338 return err; 339} 340 341/* 342 * Control the mode of pin widget settings via the mixer. "pc" is used 343 * instead of "%" to avoid consequences of accidently treating the % as 344 * being part of a format specifier. Maximum allowed length of a value is 345 * 63 characters plus NULL terminator. 346 * 347 * Note: some retasking pin complexes seem to ignore requests for input 348 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these 349 * are requested. Therefore order this list so that this behaviour will not 350 * cause problems when mixer clients move through the enum sequentially. 351 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of 352 * March 2006. 353 */ 354static char *alc_pin_mode_names[] = { 355 "Mic 50pc bias", "Mic 80pc bias", 356 "Line in", "Line out", "Headphone out", 357}; 358static unsigned char alc_pin_mode_values[] = { 359 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, 360}; 361/* The control can present all 5 options, or it can limit the options based 362 * in the pin being assumed to be exclusively an input or an output pin. In 363 * addition, "input" pins may or may not process the mic bias option 364 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to 365 * accept requests for bias as of chip versions up to March 2006) and/or 366 * wiring in the computer. 367 */ 368#define ALC_PIN_DIR_IN 0x00 369#define ALC_PIN_DIR_OUT 0x01 370#define ALC_PIN_DIR_INOUT 0x02 371#define ALC_PIN_DIR_IN_NOMICBIAS 0x03 372#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04 373 374/* Info about the pin modes supported by the different pin direction modes. 375 * For each direction the minimum and maximum values are given. 376 */ 377static signed char alc_pin_mode_dir_info[5][2] = { 378 { 0, 2 }, /* ALC_PIN_DIR_IN */ 379 { 3, 4 }, /* ALC_PIN_DIR_OUT */ 380 { 0, 4 }, /* ALC_PIN_DIR_INOUT */ 381 { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */ 382 { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */ 383}; 384#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) 385#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) 386#define alc_pin_mode_n_items(_dir) \ 387 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1) 388 389static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, 390 struct snd_ctl_elem_info *uinfo) 391{ 392 unsigned int item_num = uinfo->value.enumerated.item; 393 unsigned char dir = (kcontrol->private_value >> 16) & 0xff; 394 395 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 396 uinfo->count = 1; 397 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir); 398 399 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir)) 400 item_num = alc_pin_mode_min(dir); 401 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]); 402 return 0; 403} 404 405static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, 406 struct snd_ctl_elem_value *ucontrol) 407{ 408 unsigned int i; 409 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 410 hda_nid_t nid = kcontrol->private_value & 0xffff; 411 unsigned char dir = (kcontrol->private_value >> 16) & 0xff; 412 long *valp = ucontrol->value.integer.value; 413 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, 414 AC_VERB_GET_PIN_WIDGET_CONTROL, 415 0x00); 416 417 /* Find enumerated value for current pinctl setting */ 418 i = alc_pin_mode_min(dir); 419 while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir)) 420 i++; 421 *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir); 422 return 0; 423} 424 425static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, 426 struct snd_ctl_elem_value *ucontrol) 427{ 428 signed int change; 429 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 430 hda_nid_t nid = kcontrol->private_value & 0xffff; 431 unsigned char dir = (kcontrol->private_value >> 16) & 0xff; 432 long val = *ucontrol->value.integer.value; 433 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, 434 AC_VERB_GET_PIN_WIDGET_CONTROL, 435 0x00); 436 437 if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) 438 val = alc_pin_mode_min(dir); 439 440 change = pinctl != alc_pin_mode_values[val]; 441 if (change) { 442 /* Set pin mode to that requested */ 443 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, 444 alc_pin_mode_values[val]); 445 446 /* Also enable the retasking pin's input/output as required 447 * for the requested pin mode. Enum values of 2 or less are 448 * input modes. 449 * 450 * Dynamically switching the input/output buffers probably 451 * reduces noise slightly (particularly on input) so we'll 452 * do it. However, having both input and output buffers 453 * enabled simultaneously doesn't seem to be problematic if 454 * this turns out to be necessary in the future. 455 */ 456 if (val <= 2) { 457 snd_hda_codec_write(codec, nid, 0, 458 AC_VERB_SET_AMP_GAIN_MUTE, 459 AMP_OUT_MUTE); 460 snd_hda_codec_write(codec, nid, 0, 461 AC_VERB_SET_AMP_GAIN_MUTE, 462 AMP_IN_UNMUTE(0)); 463 } else { 464 snd_hda_codec_write(codec, nid, 0, 465 AC_VERB_SET_AMP_GAIN_MUTE, 466 AMP_IN_MUTE(0)); 467 snd_hda_codec_write(codec, nid, 0, 468 AC_VERB_SET_AMP_GAIN_MUTE, 469 AMP_OUT_UNMUTE); 470 } 471 } 472 return change; 473} 474 475#define ALC_PIN_MODE(xname, nid, dir) \ 476 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 477 .info = alc_pin_mode_info, \ 478 .get = alc_pin_mode_get, \ 479 .put = alc_pin_mode_put, \ 480 .private_value = nid | (dir<<16) } 481 482/* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged 483 * together using a mask with more than one bit set. This control is 484 * currently used only by the ALC260 test model. At this stage they are not 485 * needed for any "production" models. 486 */ 487#ifdef CONFIG_SND_DEBUG 488static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, 489 struct snd_ctl_elem_info *uinfo) 490{ 491 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 492 uinfo->count = 1; 493 uinfo->value.integer.min = 0; 494 uinfo->value.integer.max = 1; 495 return 0; 496} 497 498static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, 499 struct snd_ctl_elem_value *ucontrol) 500{ 501 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 502 hda_nid_t nid = kcontrol->private_value & 0xffff; 503 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 504 long *valp = ucontrol->value.integer.value; 505 unsigned int val = snd_hda_codec_read(codec, nid, 0, 506 AC_VERB_GET_GPIO_DATA, 0x00); 507 508 *valp = (val & mask) != 0; 509 return 0; 510} 511static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, 512 struct snd_ctl_elem_value *ucontrol) 513{ 514 signed int change; 515 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 516 hda_nid_t nid = kcontrol->private_value & 0xffff; 517 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 518 long val = *ucontrol->value.integer.value; 519 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, 520 AC_VERB_GET_GPIO_DATA, 521 0x00); 522 523 /* Set/unset the masked GPIO bit(s) as needed */ 524 change = (val == 0 ? 0 : mask) != (gpio_data & mask); 525 if (val == 0) 526 gpio_data &= ~mask; 527 else 528 gpio_data |= mask; 529 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); 530 531 return change; 532} 533#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ 534 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 535 .info = alc_gpio_data_info, \ 536 .get = alc_gpio_data_get, \ 537 .put = alc_gpio_data_put, \ 538 .private_value = nid | (mask<<16) } 539#endif /* CONFIG_SND_DEBUG */ 540 541/* A switch control to allow the enabling of the digital IO pins on the 542 * ALC260. This is incredibly simplistic; the intention of this control is 543 * to provide something in the test model allowing digital outputs to be 544 * identified if present. If models are found which can utilise these 545 * outputs a more complete mixer control can be devised for those models if 546 * necessary. 547 */ 548#ifdef CONFIG_SND_DEBUG 549static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, 550 struct snd_ctl_elem_info *uinfo) 551{ 552 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 553 uinfo->count = 1; 554 uinfo->value.integer.min = 0; 555 uinfo->value.integer.max = 1; 556 return 0; 557} 558 559static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, 560 struct snd_ctl_elem_value *ucontrol) 561{ 562 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 563 hda_nid_t nid = kcontrol->private_value & 0xffff; 564 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 565 long *valp = ucontrol->value.integer.value; 566 unsigned int val = snd_hda_codec_read(codec, nid, 0, 567 AC_VERB_GET_DIGI_CONVERT, 0x00); 568 569 *valp = (val & mask) != 0; 570 return 0; 571} 572static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, 573 struct snd_ctl_elem_value *ucontrol) 574{ 575 signed int change; 576 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 577 hda_nid_t nid = kcontrol->private_value & 0xffff; 578 unsigned char mask = (kcontrol->private_value >> 16) & 0xff; 579 long val = *ucontrol->value.integer.value; 580 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, 581 AC_VERB_GET_DIGI_CONVERT, 582 0x00); 583 584 /* Set/unset the masked control bit(s) as needed */ 585 change = (val == 0 ? 0 : mask) != (ctrl_data & mask); 586 if (val==0) 587 ctrl_data &= ~mask; 588 else 589 ctrl_data |= mask; 590 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, 591 ctrl_data); 592 593 return change; 594} 595#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ 596 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 597 .info = alc_spdif_ctrl_info, \ 598 .get = alc_spdif_ctrl_get, \ 599 .put = alc_spdif_ctrl_put, \ 600 .private_value = nid | (mask<<16) } 601#endif /* CONFIG_SND_DEBUG */ 602 603/* 604 * set up from the preset table 605 */ 606static void setup_preset(struct alc_spec *spec, 607 const struct alc_config_preset *preset) 608{ 609 int i; 610 611 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) 612 spec->mixers[spec->num_mixers++] = preset->mixers[i]; 613 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; 614 i++) 615 spec->init_verbs[spec->num_init_verbs++] = 616 preset->init_verbs[i]; 617 618 spec->channel_mode = preset->channel_mode; 619 spec->num_channel_mode = preset->num_channel_mode; 620 spec->need_dac_fix = preset->need_dac_fix; 621 622 spec->multiout.max_channels = spec->channel_mode[0].channels; 623 624 spec->multiout.num_dacs = preset->num_dacs; 625 spec->multiout.dac_nids = preset->dac_nids; 626 spec->multiout.dig_out_nid = preset->dig_out_nid; 627 spec->multiout.hp_nid = preset->hp_nid; 628 629 spec->num_mux_defs = preset->num_mux_defs; 630 if (!spec->num_mux_defs) 631 spec->num_mux_defs = 1; 632 spec->input_mux = preset->input_mux; 633 634 spec->num_adc_nids = preset->num_adc_nids; 635 spec->adc_nids = preset->adc_nids; 636 spec->dig_in_nid = preset->dig_in_nid; 637 638 spec->unsol_event = preset->unsol_event; 639 spec->init_hook = preset->init_hook; 640} 641 642/* Enable GPIO mask and set output */ 643static struct hda_verb alc_gpio1_init_verbs[] = { 644 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 645 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 646 {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, 647 { } 648}; 649 650static struct hda_verb alc_gpio2_init_verbs[] = { 651 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 652 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 653 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, 654 { } 655}; 656 657static struct hda_verb alc_gpio3_init_verbs[] = { 658 {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 659 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 660 {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 661 { } 662}; 663 664/* 32-bit subsystem ID for BIOS loading in HD Audio codec. 665 * 31 ~ 16 : Manufacture ID 666 * 15 ~ 8 : SKU ID 667 * 7 ~ 0 : Assembly ID 668 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36 669 */ 670static void alc_subsystem_id(struct hda_codec *codec, 671 unsigned int porta, unsigned int porte, 672 unsigned int portd) 673{ 674 unsigned int ass, tmp; 675 676 ass = codec->subsystem_id; 677 if (!(ass & 1)) 678 return; 679 680 /* Override */ 681 tmp = (ass & 0x38) >> 3; /* external Amp control */ 682 switch (tmp) { 683 case 1: 684 snd_hda_sequence_write(codec, alc_gpio1_init_verbs); 685 break; 686 case 3: 687 snd_hda_sequence_write(codec, alc_gpio2_init_verbs); 688 break; 689 case 7: 690 snd_hda_sequence_write(codec, alc_gpio3_init_verbs); 691 break; 692 case 5: 693 switch (codec->vendor_id) { 694 case 0x10ec0862: 695 case 0x10ec0660: 696 case 0x10ec0662: 697 case 0x10ec0267: 698 case 0x10ec0268: 699 snd_hda_codec_write(codec, 0x14, 0, 700 AC_VERB_SET_EAPD_BTLENABLE, 2); 701 snd_hda_codec_write(codec, 0x15, 0, 702 AC_VERB_SET_EAPD_BTLENABLE, 2); 703 return; 704 } 705 case 6: 706 if (ass & 4) { /* bit 2 : 0 = Desktop, 1 = Laptop */ 707 hda_nid_t port = 0; 708 tmp = (ass & 0x1800) >> 11; 709 switch (tmp) { 710 case 0: port = porta; break; 711 case 1: port = porte; break; 712 case 2: port = portd; break; 713 } 714 if (port) 715 snd_hda_codec_write(codec, port, 0, 716 AC_VERB_SET_EAPD_BTLENABLE, 717 2); 718 } 719 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); 720 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, 721 (tmp == 5 ? 0x3040 : 0x3050)); 722 break; 723 } 724} 725 726/* 727 * Fix-up pin default configurations 728 */ 729 730struct alc_pincfg { 731 hda_nid_t nid; 732 u32 val; 733}; 734 735static void alc_fix_pincfg(struct hda_codec *codec, 736 const struct snd_pci_quirk *quirk, 737 const struct alc_pincfg **pinfix) 738{ 739 const struct alc_pincfg *cfg; 740 741 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); 742 if (!quirk) 743 return; 744 745 cfg = pinfix[quirk->value]; 746 for (; cfg->nid; cfg++) { 747 int i; 748 u32 val = cfg->val; 749 for (i = 0; i < 4; i++) { 750 snd_hda_codec_write(codec, cfg->nid, 0, 751 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i, 752 val & 0xff); 753 val >>= 8; 754 } 755 } 756} 757 758/* 759 * ALC880 3-stack model 760 * 761 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) 762 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, 763 * F-Mic = 0x1b, HP = 0x19 764 */ 765 766static hda_nid_t alc880_dac_nids[4] = { 767 /* front, rear, clfe, rear_surr */ 768 0x02, 0x05, 0x04, 0x03 769}; 770 771static hda_nid_t alc880_adc_nids[3] = { 772 /* ADC0-2 */ 773 0x07, 0x08, 0x09, 774}; 775 776/* The datasheet says the node 0x07 is connected from inputs, 777 * but it shows zero connection in the real implementation on some devices. 778 * Note: this is a 915GAV bug, fixed on 915GLV 779 */ 780static hda_nid_t alc880_adc_nids_alt[2] = { 781 /* ADC1-2 */ 782 0x08, 0x09, 783}; 784 785#define ALC880_DIGOUT_NID 0x06 786#define ALC880_DIGIN_NID 0x0a 787 788static struct hda_input_mux alc880_capture_source = { 789 .num_items = 4, 790 .items = { 791 { "Mic", 0x0 }, 792 { "Front Mic", 0x3 }, 793 { "Line", 0x2 }, 794 { "CD", 0x4 }, 795 }, 796}; 797 798/* channel source setting (2/6 channel selection for 3-stack) */ 799/* 2ch mode */ 800static struct hda_verb alc880_threestack_ch2_init[] = { 801 /* set line-in to input, mute it */ 802 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 803 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 804 /* set mic-in to input vref 80%, mute it */ 805 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 806 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 807 { } /* end */ 808}; 809 810/* 6ch mode */ 811static struct hda_verb alc880_threestack_ch6_init[] = { 812 /* set line-in to output, unmute it */ 813 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 814 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 815 /* set mic-in to output, unmute it */ 816 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 817 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 818 { } /* end */ 819}; 820 821static struct hda_channel_mode alc880_threestack_modes[2] = { 822 { 2, alc880_threestack_ch2_init }, 823 { 6, alc880_threestack_ch6_init }, 824}; 825 826static struct snd_kcontrol_new alc880_three_stack_mixer[] = { 827 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 828 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 829 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 830 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), 831 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 832 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 833 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 834 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 835 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 836 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 837 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 838 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 839 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 840 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 841 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), 842 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), 843 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 844 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 845 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), 846 { 847 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 848 .name = "Channel Mode", 849 .info = alc_ch_mode_info, 850 .get = alc_ch_mode_get, 851 .put = alc_ch_mode_put, 852 }, 853 { } /* end */ 854}; 855 856/* capture mixer elements */ 857static struct snd_kcontrol_new alc880_capture_mixer[] = { 858 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), 859 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), 860 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), 861 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), 862 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), 863 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), 864 { 865 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 866 /* The multiple "Capture Source" controls confuse alsamixer 867 * So call somewhat different.. 868 * FIXME: the controls appear in the "playback" view! 869 */ 870 /* .name = "Capture Source", */ 871 .name = "Input Source", 872 .count = 3, 873 .info = alc_mux_enum_info, 874 .get = alc_mux_enum_get, 875 .put = alc_mux_enum_put, 876 }, 877 { } /* end */ 878}; 879 880/* capture mixer elements (in case NID 0x07 not available) */ 881static struct snd_kcontrol_new alc880_capture_alt_mixer[] = { 882 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 883 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 884 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 885 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 886 { 887 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 888 /* The multiple "Capture Source" controls confuse alsamixer 889 * So call somewhat different.. 890 * FIXME: the controls appear in the "playback" view! 891 */ 892 /* .name = "Capture Source", */ 893 .name = "Input Source", 894 .count = 2, 895 .info = alc_mux_enum_info, 896 .get = alc_mux_enum_get, 897 .put = alc_mux_enum_put, 898 }, 899 { } /* end */ 900}; 901 902 903 904/* 905 * ALC880 5-stack model 906 * 907 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), 908 * Side = 0x02 (0xd) 909 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 910 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 911 */ 912 913/* additional mixers to alc880_three_stack_mixer */ 914static struct snd_kcontrol_new alc880_five_stack_mixer[] = { 915 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 916 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), 917 { } /* end */ 918}; 919 920/* channel source setting (6/8 channel selection for 5-stack) */ 921/* 6ch mode */ 922static struct hda_verb alc880_fivestack_ch6_init[] = { 923 /* set line-in to input, mute it */ 924 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 925 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 926 { } /* end */ 927}; 928 929/* 8ch mode */ 930static struct hda_verb alc880_fivestack_ch8_init[] = { 931 /* set line-in to output, unmute it */ 932 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 933 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 934 { } /* end */ 935}; 936 937static struct hda_channel_mode alc880_fivestack_modes[2] = { 938 { 6, alc880_fivestack_ch6_init }, 939 { 8, alc880_fivestack_ch8_init }, 940}; 941 942 943/* 944 * ALC880 6-stack model 945 * 946 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), 947 * Side = 0x05 (0x0f) 948 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, 949 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b 950 */ 951 952static hda_nid_t alc880_6st_dac_nids[4] = { 953 /* front, rear, clfe, rear_surr */ 954 0x02, 0x03, 0x04, 0x05 955}; 956 957static struct hda_input_mux alc880_6stack_capture_source = { 958 .num_items = 4, 959 .items = { 960 { "Mic", 0x0 }, 961 { "Front Mic", 0x1 }, 962 { "Line", 0x2 }, 963 { "CD", 0x4 }, 964 }, 965}; 966 967/* fixed 8-channels */ 968static struct hda_channel_mode alc880_sixstack_modes[1] = { 969 { 8, NULL }, 970}; 971 972static struct snd_kcontrol_new alc880_six_stack_mixer[] = { 973 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 974 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 975 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 976 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 977 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 978 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 979 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 980 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 981 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 982 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 983 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 984 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 985 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 986 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 987 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 988 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 989 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 990 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 991 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 992 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 993 { 994 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 995 .name = "Channel Mode", 996 .info = alc_ch_mode_info, 997 .get = alc_ch_mode_get, 998 .put = alc_ch_mode_put, 999 }, 1000 { } /* end */ 1001}; 1002 1003 1004/* 1005 * ALC880 W810 model 1006 * 1007 * W810 has rear IO for: 1008 * Front (DAC 02) 1009 * Surround (DAC 03) 1010 * Center/LFE (DAC 04) 1011 * Digital out (06) 1012 * 1013 * The system also has a pair of internal speakers, and a headphone jack. 1014 * These are both connected to Line2 on the codec, hence to DAC 02. 1015 * 1016 * There is a variable resistor to control the speaker or headphone 1017 * volume. This is a hardware-only device without a software API. 1018 * 1019 * Plugging headphones in will disable the internal speakers. This is 1020 * implemented in hardware, not via the driver using jack sense. In 1021 * a similar fashion, plugging into the rear socket marked "front" will 1022 * disable both the speakers and headphones. 1023 * 1024 * For input, there's a microphone jack, and an "audio in" jack. 1025 * These may not do anything useful with this driver yet, because I 1026 * haven't setup any initialization verbs for these yet... 1027 */ 1028 1029static hda_nid_t alc880_w810_dac_nids[3] = { 1030 /* front, rear/surround, clfe */ 1031 0x02, 0x03, 0x04 1032}; 1033 1034/* fixed 6 channels */ 1035static struct hda_channel_mode alc880_w810_modes[1] = { 1036 { 6, NULL } 1037}; 1038 1039/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ 1040static struct snd_kcontrol_new alc880_w810_base_mixer[] = { 1041 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1042 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1043 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1044 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 1045 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1046 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1047 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1048 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1049 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 1050 { } /* end */ 1051}; 1052 1053 1054/* 1055 * Z710V model 1056 * 1057 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) 1058 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), 1059 * Line = 0x1a 1060 */ 1061 1062static hda_nid_t alc880_z71v_dac_nids[1] = { 1063 0x02 1064}; 1065#define ALC880_Z71V_HP_DAC 0x03 1066 1067/* fixed 2 channels */ 1068static struct hda_channel_mode alc880_2_jack_modes[1] = { 1069 { 2, NULL } 1070}; 1071 1072static struct snd_kcontrol_new alc880_z71v_mixer[] = { 1073 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1074 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1075 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1076 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), 1077 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1078 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1079 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1080 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1081 { } /* end */ 1082}; 1083 1084 1085/* FIXME! */ 1086/* 1087 * ALC880 F1734 model 1088 * 1089 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d) 1090 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18 1091 */ 1092 1093static hda_nid_t alc880_f1734_dac_nids[1] = { 1094 0x03 1095}; 1096#define ALC880_F1734_HP_DAC 0x02 1097 1098static struct snd_kcontrol_new alc880_f1734_mixer[] = { 1099 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1100 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), 1101 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1102 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT), 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 { } /* end */ 1108}; 1109 1110 1111/* FIXME! */ 1112/* 1113 * ALC880 ASUS model 1114 * 1115 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) 1116 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, 1117 * Mic = 0x18, Line = 0x1a 1118 */ 1119 1120#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */ 1121#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */ 1122 1123static struct snd_kcontrol_new alc880_asus_mixer[] = { 1124 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1125 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1126 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1127 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 1128 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1129 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1130 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1131 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1132 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1133 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1134 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 1135 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 1136 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1137 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1138 { 1139 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1140 .name = "Channel Mode", 1141 .info = alc_ch_mode_info, 1142 .get = alc_ch_mode_get, 1143 .put = alc_ch_mode_put, 1144 }, 1145 { } /* end */ 1146}; 1147 1148/* FIXME! */ 1149/* 1150 * ALC880 ASUS W1V model 1151 * 1152 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) 1153 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, 1154 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b 1155 */ 1156 1157/* additional mixers to alc880_asus_mixer */ 1158static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { 1159 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT), 1160 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT), 1161 { } /* end */ 1162}; 1163 1164/* additional mixers to alc880_asus_mixer */ 1165static struct snd_kcontrol_new alc880_pcbeep_mixer[] = { 1166 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 1167 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 1168 { } /* end */ 1169}; 1170 1171/* TCL S700 */ 1172static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { 1173 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1174 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 1175 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 1176 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT), 1177 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT), 1178 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT), 1179 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT), 1180 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 1181 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 1182 { 1183 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1184 /* The multiple "Capture Source" controls confuse alsamixer 1185 * So call somewhat different.. 1186 * FIXME: the controls appear in the "playback" view! 1187 */ 1188 /* .name = "Capture Source", */ 1189 .name = "Input Source", 1190 .count = 1, 1191 .info = alc_mux_enum_info, 1192 .get = alc_mux_enum_get, 1193 .put = alc_mux_enum_put, 1194 }, 1195 { } /* end */ 1196}; 1197 1198/* Uniwill */ 1199static struct snd_kcontrol_new alc880_uniwill_mixer[] = { 1200 HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1201 HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT), 1202 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1203 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), 1204 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1205 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1206 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1207 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1208 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1209 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1210 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 1211 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 1212 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1213 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1214 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 1215 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 1216 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 1217 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 1218 { 1219 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1220 .name = "Channel Mode", 1221 .info = alc_ch_mode_info, 1222 .get = alc_ch_mode_get, 1223 .put = alc_ch_mode_put, 1224 }, 1225 { } /* end */ 1226}; 1227 1228static struct snd_kcontrol_new alc880_fujitsu_mixer[] = { 1229 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1230 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), 1231 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1232 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), 1233 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 1234 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 1235 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1236 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1237 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 1238 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 1239 { } /* end */ 1240}; 1241 1242static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = { 1243 HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1244 HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT), 1245 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1246 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), 1247 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1248 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1249 { } /* end */ 1250}; 1251 1252/* 1253 * build control elements 1254 */ 1255static int alc_build_controls(struct hda_codec *codec) 1256{ 1257 struct alc_spec *spec = codec->spec; 1258 int err; 1259 int i; 1260 1261 for (i = 0; i < spec->num_mixers; i++) { 1262 err = snd_hda_add_new_ctls(codec, spec->mixers[i]); 1263 if (err < 0) 1264 return err; 1265 } 1266 1267 if (spec->multiout.dig_out_nid) { 1268 err = snd_hda_create_spdif_out_ctls(codec, 1269 spec->multiout.dig_out_nid); 1270 if (err < 0) 1271 return err; 1272 } 1273 if (spec->dig_in_nid) { 1274 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 1275 if (err < 0) 1276 return err; 1277 } 1278 return 0; 1279} 1280 1281 1282/* 1283 * initialize the codec volumes, etc 1284 */ 1285 1286/* 1287 * generic initialization of ADC, input mixers and output mixers 1288 */ 1289static struct hda_verb alc880_volume_init_verbs[] = { 1290 /* 1291 * Unmute ADC0-2 and set the default input to mic-in 1292 */ 1293 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 1294 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1295 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 1296 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1297 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 1298 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1299 1300 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 1301 * mixer widget 1302 * Note: PASD motherboards uses the Line In 2 as the input for front 1303 * panel mic (mic 2) 1304 */ 1305 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 1306 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1307 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1308 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 1309 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 1310 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 1311 1312 /* 1313 * Set up output mixers (0x0c - 0x0f) 1314 */ 1315 /* set vol=0 to output mixers */ 1316 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1317 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1318 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1319 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1320 /* set up input amps for analog loopback */ 1321 /* Amp Indices: DAC = 0, mixer = 1 */ 1322 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1323 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1324 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1325 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1326 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1327 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1328 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1329 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1330 1331 { } 1332}; 1333 1334/* 1335 * 3-stack pin configuration: 1336 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b 1337 */ 1338static struct hda_verb alc880_pin_3stack_init_verbs[] = { 1339 /* 1340 * preset connection lists of input pins 1341 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround 1342 */ 1343 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 1344 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1345 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ 1346 1347 /* 1348 * Set pin mode and muting 1349 */ 1350 /* set front pin widgets 0x14 for output */ 1351 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1352 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1353 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 1354 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1355 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1356 /* Mic2 (as headphone out) for HP output */ 1357 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1358 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1359 /* Line In pin widget for input */ 1360 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1361 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1362 /* Line2 (as front mic) pin widget for input and vref at 80% */ 1363 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1364 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1365 /* CD pin widget for input */ 1366 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1367 1368 { } 1369}; 1370 1371/* 1372 * 5-stack pin configuration: 1373 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19, 1374 * line-in/side = 0x1a, f-mic = 0x1b 1375 */ 1376static struct hda_verb alc880_pin_5stack_init_verbs[] = { 1377 /* 1378 * preset connection lists of input pins 1379 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround 1380 */ 1381 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1382 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */ 1383 1384 /* 1385 * Set pin mode and muting 1386 */ 1387 /* set pin widgets 0x14-0x17 for output */ 1388 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1389 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1390 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1391 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1392 /* unmute pins for output (no gain on this amp) */ 1393 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1394 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1395 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1396 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1397 1398 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 1399 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1400 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1401 /* Mic2 (as headphone out) for HP output */ 1402 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1403 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1404 /* Line In pin widget for input */ 1405 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1406 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1407 /* Line2 (as front mic) pin widget for input and vref at 80% */ 1408 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1409 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1410 /* CD pin widget for input */ 1411 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1412 1413 { } 1414}; 1415 1416/* 1417 * W810 pin configuration: 1418 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b 1419 */ 1420static struct hda_verb alc880_pin_w810_init_verbs[] = { 1421 /* hphone/speaker input selector: front DAC */ 1422 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, 1423 1424 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1425 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1426 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1427 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1428 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1429 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1430 1431 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1432 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1433 1434 { } 1435}; 1436 1437/* 1438 * Z71V pin configuration: 1439 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) 1440 */ 1441static struct hda_verb alc880_pin_z71v_init_verbs[] = { 1442 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1443 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1444 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1445 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1446 1447 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1448 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1449 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1450 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1451 1452 { } 1453}; 1454 1455/* 1456 * 6-stack pin configuration: 1457 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, 1458 * f-mic = 0x19, line = 0x1a, HP = 0x1b 1459 */ 1460static struct hda_verb alc880_pin_6stack_init_verbs[] = { 1461 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1462 1463 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1464 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1465 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1466 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1467 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1468 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1469 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1470 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1471 1472 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1473 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1474 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1475 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1476 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1477 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1478 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1479 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1480 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1481 1482 { } 1483}; 1484 1485/* 1486 * Uniwill pin configuration: 1487 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19, 1488 * line = 0x1a 1489 */ 1490static struct hda_verb alc880_uniwill_init_verbs[] = { 1491 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1492 1493 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1494 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1495 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1496 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1497 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1498 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1499 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1500 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1501 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1502 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1503 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1504 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1505 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1506 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1507 1508 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1509 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1510 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1511 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1512 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1513 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1514 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */ 1515 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */ 1516 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1517 1518 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 1519 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, 1520 1521 { } 1522}; 1523 1524/* 1525* Uniwill P53 1526* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19, 1527 */ 1528static struct hda_verb alc880_uniwill_p53_init_verbs[] = { 1529 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1530 1531 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1532 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1533 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1534 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1535 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1536 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1537 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1538 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1539 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1540 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1541 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 1542 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 1543 1544 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1545 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1546 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1547 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1548 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1549 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1550 1551 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 1552 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT}, 1553 1554 { } 1555}; 1556 1557static struct hda_verb alc880_beep_init_verbs[] = { 1558 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) }, 1559 { } 1560}; 1561 1562/* toggle speaker-output according to the hp-jack state */ 1563static void alc880_uniwill_hp_automute(struct hda_codec *codec) 1564{ 1565 unsigned int present; 1566 unsigned char bits; 1567 1568 present = snd_hda_codec_read(codec, 0x14, 0, 1569 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1570 bits = present ? 0x80 : 0; 1571 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 1572 0x80, bits); 1573 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 1574 0x80, bits); 1575 snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0, 1576 0x80, bits); 1577 snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0, 1578 0x80, bits); 1579} 1580 1581/* auto-toggle front mic */ 1582static void alc880_uniwill_mic_automute(struct hda_codec *codec) 1583{ 1584 unsigned int present; 1585 unsigned char bits; 1586 1587 present = snd_hda_codec_read(codec, 0x18, 0, 1588 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1589 bits = present ? 0x80 : 0; 1590 snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, 1591 0x80, bits); 1592 snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, 1593 0x80, bits); 1594} 1595 1596static void alc880_uniwill_automute(struct hda_codec *codec) 1597{ 1598 alc880_uniwill_hp_automute(codec); 1599 alc880_uniwill_mic_automute(codec); 1600} 1601 1602static void alc880_uniwill_unsol_event(struct hda_codec *codec, 1603 unsigned int res) 1604{ 1605 /* Looks like the unsol event is incompatible with the standard 1606 * definition. 4bit tag is placed at 28 bit! 1607 */ 1608 switch (res >> 28) { 1609 case ALC880_HP_EVENT: 1610 alc880_uniwill_hp_automute(codec); 1611 break; 1612 case ALC880_MIC_EVENT: 1613 alc880_uniwill_mic_automute(codec); 1614 break; 1615 } 1616} 1617 1618static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec) 1619{ 1620 unsigned int present; 1621 unsigned char bits; 1622 1623 present = snd_hda_codec_read(codec, 0x14, 0, 1624 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1625 bits = present ? 0x80 : 0; 1626 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0, 1627 0x80, bits); 1628 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0, 1629 0x80, bits); 1630} 1631 1632static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) 1633{ 1634 unsigned int present; 1635 1636 present = snd_hda_codec_read(codec, 0x21, 0, 1637 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f; 1638 1639 snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0, 1640 0x7f, present); 1641 snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0, 1642 0x7f, present); 1643 1644 snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0, 1645 0x7f, present); 1646 snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0, 1647 0x7f, present); 1648 1649} 1650static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, 1651 unsigned int res) 1652{ 1653 /* Looks like the unsol event is incompatible with the standard 1654 * definition. 4bit tag is placed at 28 bit! 1655 */ 1656 if ((res >> 28) == ALC880_HP_EVENT) 1657 alc880_uniwill_p53_hp_automute(codec); 1658 if ((res >> 28) == ALC880_DCVOL_EVENT) 1659 alc880_uniwill_p53_dcvol_automute(codec); 1660} 1661 1662/* FIXME! */ 1663/* 1664 * F1734 pin configuration: 1665 * HP = 0x14, speaker-out = 0x15, mic = 0x18 1666 */ 1667static struct hda_verb alc880_pin_f1734_init_verbs[] = { 1668 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, 1669 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, 1670 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, 1671 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, 1672 1673 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1674 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1675 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1676 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1677 1678 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1679 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1680 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1681 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1682 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1683 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1684 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1685 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1686 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1687 1688 { } 1689}; 1690 1691/* FIXME! */ 1692/* 1693 * ASUS pin configuration: 1694 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a 1695 */ 1696static struct hda_verb alc880_pin_asus_init_verbs[] = { 1697 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, 1698 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, 1699 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, 1700 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, 1701 1702 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1703 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1704 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1705 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1706 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1707 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1708 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1709 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1710 1711 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1712 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1713 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1714 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1715 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1716 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1717 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1718 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1719 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1720 1721 { } 1722}; 1723 1724/* Enable GPIO mask and set output */ 1725#define alc880_gpio1_init_verbs alc_gpio1_init_verbs 1726#define alc880_gpio2_init_verbs alc_gpio2_init_verbs 1727 1728/* Clevo m520g init */ 1729static struct hda_verb alc880_pin_clevo_init_verbs[] = { 1730 /* headphone output */ 1731 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, 1732 /* line-out */ 1733 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1734 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1735 /* Line-in */ 1736 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1737 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1738 /* CD */ 1739 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1740 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1741 /* Mic1 (rear panel) */ 1742 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1743 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1744 /* Mic2 (front panel) */ 1745 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1746 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1747 /* headphone */ 1748 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1749 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1750 /* change to EAPD mode */ 1751 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 1752 {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, 1753 1754 { } 1755}; 1756 1757static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { 1758 /* change to EAPD mode */ 1759 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 1760 {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, 1761 1762 /* Headphone output */ 1763 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1764 /* Front output*/ 1765 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1766 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 1767 1768 /* Line In pin widget for input */ 1769 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1770 /* CD pin widget for input */ 1771 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1772 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 1773 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1774 1775 /* change to EAPD mode */ 1776 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 1777 {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, 1778 1779 { } 1780}; 1781 1782/* 1783 * LG m1 express dual 1784 * 1785 * Pin assignment: 1786 * Rear Line-In/Out (blue): 0x14 1787 * Build-in Mic-In: 0x15 1788 * Speaker-out: 0x17 1789 * HP-Out (green): 0x1b 1790 * Mic-In/Out (red): 0x19 1791 * SPDIF-Out: 0x1e 1792 */ 1793 1794/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */ 1795static hda_nid_t alc880_lg_dac_nids[3] = { 1796 0x05, 0x02, 0x03 1797}; 1798 1799/* seems analog CD is not working */ 1800static struct hda_input_mux alc880_lg_capture_source = { 1801 .num_items = 3, 1802 .items = { 1803 { "Mic", 0x1 }, 1804 { "Line", 0x5 }, 1805 { "Internal Mic", 0x6 }, 1806 }, 1807}; 1808 1809/* 2,4,6 channel modes */ 1810static struct hda_verb alc880_lg_ch2_init[] = { 1811 /* set line-in and mic-in to input */ 1812 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 1813 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 1814 { } 1815}; 1816 1817static struct hda_verb alc880_lg_ch4_init[] = { 1818 /* set line-in to out and mic-in to input */ 1819 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, 1820 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 1821 { } 1822}; 1823 1824static struct hda_verb alc880_lg_ch6_init[] = { 1825 /* set line-in and mic-in to output */ 1826 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, 1827 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, 1828 { } 1829}; 1830 1831static struct hda_channel_mode alc880_lg_ch_modes[3] = { 1832 { 2, alc880_lg_ch2_init }, 1833 { 4, alc880_lg_ch4_init }, 1834 { 6, alc880_lg_ch6_init }, 1835}; 1836 1837static struct snd_kcontrol_new alc880_lg_mixer[] = { 1838 /* FIXME: it's not really "master" but front channels */ 1839 HDA_CODEC_VOLUME("Master Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 1840 HDA_BIND_MUTE("Master Playback Switch", 0x0f, 2, HDA_INPUT), 1841 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1842 HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT), 1843 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), 1844 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), 1845 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), 1846 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), 1847 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 1848 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 1849 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT), 1850 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT), 1851 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT), 1852 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT), 1853 { 1854 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1855 .name = "Channel Mode", 1856 .info = alc_ch_mode_info, 1857 .get = alc_ch_mode_get, 1858 .put = alc_ch_mode_put, 1859 }, 1860 { } /* end */ 1861}; 1862 1863static struct hda_verb alc880_lg_init_verbs[] = { 1864 /* set capture source to mic-in */ 1865 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1866 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1867 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1868 /* mute all amp mixer inputs */ 1869 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, 1870 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, 1871 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, 1872 /* line-in to input */ 1873 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1874 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1875 /* built-in mic */ 1876 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1877 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1878 /* speaker-out */ 1879 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1880 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1881 /* mic-in to input */ 1882 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, 1883 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1884 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1885 /* HP-out */ 1886 {0x13, AC_VERB_SET_CONNECT_SEL, 0x03}, 1887 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1888 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1889 /* jack sense */ 1890 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1}, 1891 { } 1892}; 1893 1894/* toggle speaker-output according to the hp-jack state */ 1895static void alc880_lg_automute(struct hda_codec *codec) 1896{ 1897 unsigned int present; 1898 unsigned char bits; 1899 1900 present = snd_hda_codec_read(codec, 0x1b, 0, 1901 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1902 bits = present ? 0x80 : 0; 1903 snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0, 1904 0x80, bits); 1905 snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0, 1906 0x80, bits); 1907} 1908 1909static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) 1910{ 1911 /* Looks like the unsol event is incompatible with the standard 1912 * definition. 4bit tag is placed at 28 bit! 1913 */ 1914 if ((res >> 28) == 0x01) 1915 alc880_lg_automute(codec); 1916} 1917 1918/* 1919 * LG LW20 1920 * 1921 * Pin assignment: 1922 * Speaker-out: 0x14 1923 * Mic-In: 0x18 1924 * Built-in Mic-In: 0x19 1925 * Line-In: 0x1b 1926 * HP-Out: 0x1a 1927 * SPDIF-Out: 0x1e 1928 */ 1929 1930static struct hda_input_mux alc880_lg_lw_capture_source = { 1931 .num_items = 3, 1932 .items = { 1933 { "Mic", 0x0 }, 1934 { "Internal Mic", 0x1 }, 1935 { "Line In", 0x2 }, 1936 }, 1937}; 1938 1939#define alc880_lg_lw_modes alc880_threestack_modes 1940 1941static struct snd_kcontrol_new alc880_lg_lw_mixer[] = { 1942 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1943 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1944 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 1945 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), 1946 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 1947 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 1948 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 1949 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 1950 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 1951 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 1952 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 1953 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 1954 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 1955 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 1956 { 1957 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1958 .name = "Channel Mode", 1959 .info = alc_ch_mode_info, 1960 .get = alc_ch_mode_get, 1961 .put = alc_ch_mode_put, 1962 }, 1963 { } /* end */ 1964}; 1965 1966static struct hda_verb alc880_lg_lw_init_verbs[] = { 1967 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 1968 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 1969 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ 1970 1971 /* set capture source to mic-in */ 1972 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1973 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1974 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1975 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, 1976 /* speaker-out */ 1977 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1978 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1979 /* HP-out */ 1980 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1981 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1982 /* mic-in to input */ 1983 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1984 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1985 /* built-in mic */ 1986 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1987 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1988 /* jack sense */ 1989 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1}, 1990 { } 1991}; 1992 1993/* toggle speaker-output according to the hp-jack state */ 1994static void alc880_lg_lw_automute(struct hda_codec *codec) 1995{ 1996 unsigned int present; 1997 unsigned char bits; 1998 1999 present = snd_hda_codec_read(codec, 0x1b, 0, 2000 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 2001 bits = present ? 0x80 : 0; 2002 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 2003 0x80, bits); 2004 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 2005 0x80, bits); 2006} 2007 2008static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) 2009{ 2010 /* Looks like the unsol event is incompatible with the standard 2011 * definition. 4bit tag is placed at 28 bit! 2012 */ 2013 if ((res >> 28) == 0x01) 2014 alc880_lg_lw_automute(codec); 2015} 2016 2017/* 2018 * Common callbacks 2019 */ 2020 2021static int alc_init(struct hda_codec *codec) 2022{ 2023 struct alc_spec *spec = codec->spec; 2024 unsigned int i; 2025 2026 for (i = 0; i < spec->num_init_verbs; i++) 2027 snd_hda_sequence_write(codec, spec->init_verbs[i]); 2028 2029 if (spec->init_hook) 2030 spec->init_hook(codec); 2031 2032 return 0; 2033} 2034 2035static void alc_unsol_event(struct hda_codec *codec, unsigned int res) 2036{ 2037 struct alc_spec *spec = codec->spec; 2038 2039 if (spec->unsol_event) 2040 spec->unsol_event(codec, res); 2041} 2042 2043#ifdef CONFIG_PM 2044/* 2045 * resume 2046 */ 2047static int alc_resume(struct hda_codec *codec) 2048{ 2049 struct alc_spec *spec = codec->spec; 2050 int i; 2051 2052 alc_init(codec); 2053 for (i = 0; i < spec->num_mixers; i++) 2054 snd_hda_resume_ctls(codec, spec->mixers[i]); 2055 if (spec->multiout.dig_out_nid) 2056 snd_hda_resume_spdif_out(codec); 2057 if (spec->dig_in_nid) 2058 snd_hda_resume_spdif_in(codec); 2059 2060 return 0; 2061} 2062#endif 2063 2064/* 2065 * Analog playback callbacks 2066 */ 2067static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo, 2068 struct hda_codec *codec, 2069 struct snd_pcm_substream *substream) 2070{ 2071 struct alc_spec *spec = codec->spec; 2072 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); 2073} 2074 2075static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 2076 struct hda_codec *codec, 2077 unsigned int stream_tag, 2078 unsigned int format, 2079 struct snd_pcm_substream *substream) 2080{ 2081 struct alc_spec *spec = codec->spec; 2082 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, 2083 stream_tag, format, substream); 2084} 2085 2086static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, 2087 struct hda_codec *codec, 2088 struct snd_pcm_substream *substream) 2089{ 2090 struct alc_spec *spec = codec->spec; 2091 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); 2092} 2093 2094/* 2095 * Digital out 2096 */ 2097static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, 2098 struct hda_codec *codec, 2099 struct snd_pcm_substream *substream) 2100{ 2101 struct alc_spec *spec = codec->spec; 2102 return snd_hda_multi_out_dig_open(codec, &spec->multiout); 2103} 2104 2105static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 2106 struct hda_codec *codec, 2107 unsigned int stream_tag, 2108 unsigned int format, 2109 struct snd_pcm_substream *substream) 2110{ 2111 struct alc_spec *spec = codec->spec; 2112 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, 2113 stream_tag, format, substream); 2114} 2115 2116static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, 2117 struct hda_codec *codec, 2118 struct snd_pcm_substream *substream) 2119{ 2120 struct alc_spec *spec = codec->spec; 2121 return snd_hda_multi_out_dig_close(codec, &spec->multiout); 2122} 2123 2124/* 2125 * Analog capture 2126 */ 2127static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, 2128 struct hda_codec *codec, 2129 unsigned int stream_tag, 2130 unsigned int format, 2131 struct snd_pcm_substream *substream) 2132{ 2133 struct alc_spec *spec = codec->spec; 2134 2135 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 2136 stream_tag, 0, format); 2137 return 0; 2138} 2139 2140static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, 2141 struct hda_codec *codec, 2142 struct snd_pcm_substream *substream) 2143{ 2144 struct alc_spec *spec = codec->spec; 2145 2146 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 2147 0, 0, 0); 2148 return 0; 2149} 2150 2151 2152/* 2153 */ 2154static struct hda_pcm_stream alc880_pcm_analog_playback = { 2155 .substreams = 1, 2156 .channels_min = 2, 2157 .channels_max = 8, 2158 /* NID is set in alc_build_pcms */ 2159 .ops = { 2160 .open = alc880_playback_pcm_open, 2161 .prepare = alc880_playback_pcm_prepare, 2162 .cleanup = alc880_playback_pcm_cleanup 2163 }, 2164}; 2165 2166static struct hda_pcm_stream alc880_pcm_analog_capture = { 2167 .substreams = 2, 2168 .channels_min = 2, 2169 .channels_max = 2, 2170 /* NID is set in alc_build_pcms */ 2171 .ops = { 2172 .prepare = alc880_capture_pcm_prepare, 2173 .cleanup = alc880_capture_pcm_cleanup 2174 }, 2175}; 2176 2177static struct hda_pcm_stream alc880_pcm_digital_playback = { 2178 .substreams = 1, 2179 .channels_min = 2, 2180 .channels_max = 2, 2181 /* NID is set in alc_build_pcms */ 2182 .ops = { 2183 .open = alc880_dig_playback_pcm_open, 2184 .close = alc880_dig_playback_pcm_close, 2185 .prepare = alc880_dig_playback_pcm_prepare 2186 }, 2187}; 2188 2189static struct hda_pcm_stream alc880_pcm_digital_capture = { 2190 .substreams = 1, 2191 .channels_min = 2, 2192 .channels_max = 2, 2193 /* NID is set in alc_build_pcms */ 2194}; 2195 2196/* Used by alc_build_pcms to flag that a PCM has no playback stream */ 2197static struct hda_pcm_stream alc_pcm_null_playback = { 2198 .substreams = 0, 2199 .channels_min = 0, 2200 .channels_max = 0, 2201}; 2202 2203static int alc_build_pcms(struct hda_codec *codec) 2204{ 2205 struct alc_spec *spec = codec->spec; 2206 struct hda_pcm *info = spec->pcm_rec; 2207 int i; 2208 2209 codec->num_pcms = 1; 2210 codec->pcm_info = info; 2211 2212 info->name = spec->stream_name_analog; 2213 if (spec->stream_analog_playback) { 2214 snd_assert(spec->multiout.dac_nids, return -EINVAL); 2215 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); 2216 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; 2217 } 2218 if (spec->stream_analog_capture) { 2219 snd_assert(spec->adc_nids, return -EINVAL); 2220 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); 2221 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; 2222 } 2223 2224 if (spec->channel_mode) { 2225 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0; 2226 for (i = 0; i < spec->num_channel_mode; i++) { 2227 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) { 2228 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels; 2229 } 2230 } 2231 } 2232 2233 /* SPDIF for stream index #1 */ 2234 if (spec->multiout.dig_out_nid || spec->dig_in_nid) { 2235 codec->num_pcms = 2; 2236 info = spec->pcm_rec + 1; 2237 info->name = spec->stream_name_digital; 2238 if (spec->multiout.dig_out_nid && 2239 spec->stream_digital_playback) { 2240 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); 2241 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; 2242 } 2243 if (spec->dig_in_nid && 2244 spec->stream_digital_capture) { 2245 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture); 2246 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; 2247 } 2248 } 2249 2250 /* If the use of more than one ADC is requested for the current 2251 * model, configure a second analog capture-only PCM. 2252 */ 2253 /* Additional Analaog capture for index #2 */ 2254 if (spec->num_adc_nids > 1 && spec->stream_analog_capture && 2255 spec->adc_nids) { 2256 codec->num_pcms = 3; 2257 info = spec->pcm_rec + 2; 2258 info->name = spec->stream_name_analog; 2259 /* No playback stream for second PCM */ 2260 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; 2261 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; 2262 if (spec->stream_analog_capture) { 2263 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); 2264 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1]; 2265 } 2266 } 2267 2268 return 0; 2269} 2270 2271static void alc_free(struct hda_codec *codec) 2272{ 2273 struct alc_spec *spec = codec->spec; 2274 unsigned int i; 2275 2276 if (!spec) 2277 return; 2278 2279 if (spec->kctl_alloc) { 2280 for (i = 0; i < spec->num_kctl_used; i++) 2281 kfree(spec->kctl_alloc[i].name); 2282 kfree(spec->kctl_alloc); 2283 } 2284 kfree(spec); 2285} 2286 2287/* 2288 */ 2289static struct hda_codec_ops alc_patch_ops = { 2290 .build_controls = alc_build_controls, 2291 .build_pcms = alc_build_pcms, 2292 .init = alc_init, 2293 .free = alc_free, 2294 .unsol_event = alc_unsol_event, 2295#ifdef CONFIG_PM 2296 .resume = alc_resume, 2297#endif 2298}; 2299 2300 2301/* 2302 * Test configuration for debugging 2303 * 2304 * Almost all inputs/outputs are enabled. I/O pins can be configured via 2305 * enum controls. 2306 */ 2307#ifdef CONFIG_SND_DEBUG 2308static hda_nid_t alc880_test_dac_nids[4] = { 2309 0x02, 0x03, 0x04, 0x05 2310}; 2311 2312static struct hda_input_mux alc880_test_capture_source = { 2313 .num_items = 7, 2314 .items = { 2315 { "In-1", 0x0 }, 2316 { "In-2", 0x1 }, 2317 { "In-3", 0x2 }, 2318 { "In-4", 0x3 }, 2319 { "CD", 0x4 }, 2320 { "Front", 0x5 }, 2321 { "Surround", 0x6 }, 2322 }, 2323}; 2324 2325static struct hda_channel_mode alc880_test_modes[4] = { 2326 { 2, NULL }, 2327 { 4, NULL }, 2328 { 6, NULL }, 2329 { 8, NULL }, 2330}; 2331 2332static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, 2333 struct snd_ctl_elem_info *uinfo) 2334{ 2335 static char *texts[] = { 2336 "N/A", "Line Out", "HP Out", 2337 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" 2338 }; 2339 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2340 uinfo->count = 1; 2341 uinfo->value.enumerated.items = 8; 2342 if (uinfo->value.enumerated.item >= 8) 2343 uinfo->value.enumerated.item = 7; 2344 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2345 return 0; 2346} 2347 2348static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, 2349 struct snd_ctl_elem_value *ucontrol) 2350{ 2351 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2352 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 2353 unsigned int pin_ctl, item = 0; 2354 2355 pin_ctl = snd_hda_codec_read(codec, nid, 0, 2356 AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 2357 if (pin_ctl & AC_PINCTL_OUT_EN) { 2358 if (pin_ctl & AC_PINCTL_HP_EN) 2359 item = 2; 2360 else 2361 item = 1; 2362 } else if (pin_ctl & AC_PINCTL_IN_EN) { 2363 switch (pin_ctl & AC_PINCTL_VREFEN) { 2364 case AC_PINCTL_VREF_HIZ: item = 3; break; 2365 case AC_PINCTL_VREF_50: item = 4; break; 2366 case AC_PINCTL_VREF_GRD: item = 5; break; 2367 case AC_PINCTL_VREF_80: item = 6; break; 2368 case AC_PINCTL_VREF_100: item = 7; break; 2369 } 2370 } 2371 ucontrol->value.enumerated.item[0] = item; 2372 return 0; 2373} 2374 2375static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, 2376 struct snd_ctl_elem_value *ucontrol) 2377{ 2378 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2379 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 2380 static unsigned int ctls[] = { 2381 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, 2382 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, 2383 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, 2384 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, 2385 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, 2386 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, 2387 }; 2388 unsigned int old_ctl, new_ctl; 2389 2390 old_ctl = snd_hda_codec_read(codec, nid, 0, 2391 AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 2392 new_ctl = ctls[ucontrol->value.enumerated.item[0]]; 2393 if (old_ctl != new_ctl) { 2394 snd_hda_codec_write(codec, nid, 0, 2395 AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); 2396 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 2397 (ucontrol->value.enumerated.item[0] >= 3 ? 2398 0xb080 : 0xb000)); 2399 return 1; 2400 } 2401 return 0; 2402} 2403 2404static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, 2405 struct snd_ctl_elem_info *uinfo) 2406{ 2407 static char *texts[] = { 2408 "Front", "Surround", "CLFE", "Side" 2409 }; 2410 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2411 uinfo->count = 1; 2412 uinfo->value.enumerated.items = 4; 2413 if (uinfo->value.enumerated.item >= 4) 2414 uinfo->value.enumerated.item = 3; 2415 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2416 return 0; 2417} 2418 2419static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, 2420 struct snd_ctl_elem_value *ucontrol) 2421{ 2422 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2423 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 2424 unsigned int sel; 2425 2426 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); 2427 ucontrol->value.enumerated.item[0] = sel & 3; 2428 return 0; 2429} 2430 2431static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, 2432 struct snd_ctl_elem_value *ucontrol) 2433{ 2434 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2435 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 2436 unsigned int sel; 2437 2438 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; 2439 if (ucontrol->value.enumerated.item[0] != sel) { 2440 sel = ucontrol->value.enumerated.item[0] & 3; 2441 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); 2442 return 1; 2443 } 2444 return 0; 2445} 2446 2447#define PIN_CTL_TEST(xname,nid) { \ 2448 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 2449 .name = xname, \ 2450 .info = alc_test_pin_ctl_info, \ 2451 .get = alc_test_pin_ctl_get, \ 2452 .put = alc_test_pin_ctl_put, \ 2453 .private_value = nid \ 2454 } 2455 2456#define PIN_SRC_TEST(xname,nid) { \ 2457 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 2458 .name = xname, \ 2459 .info = alc_test_pin_src_info, \ 2460 .get = alc_test_pin_src_get, \ 2461 .put = alc_test_pin_src_put, \ 2462 .private_value = nid \ 2463 } 2464 2465static struct snd_kcontrol_new alc880_test_mixer[] = { 2466 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 2467 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 2468 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), 2469 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 2470 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 2471 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 2472 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), 2473 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 2474 PIN_CTL_TEST("Front Pin Mode", 0x14), 2475 PIN_CTL_TEST("Surround Pin Mode", 0x15), 2476 PIN_CTL_TEST("CLFE Pin Mode", 0x16), 2477 PIN_CTL_TEST("Side Pin Mode", 0x17), 2478 PIN_CTL_TEST("In-1 Pin Mode", 0x18), 2479 PIN_CTL_TEST("In-2 Pin Mode", 0x19), 2480 PIN_CTL_TEST("In-3 Pin Mode", 0x1a), 2481 PIN_CTL_TEST("In-4 Pin Mode", 0x1b), 2482 PIN_SRC_TEST("In-1 Pin Source", 0x18), 2483 PIN_SRC_TEST("In-2 Pin Source", 0x19), 2484 PIN_SRC_TEST("In-3 Pin Source", 0x1a), 2485 PIN_SRC_TEST("In-4 Pin Source", 0x1b), 2486 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), 2487 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), 2488 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), 2489 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), 2490 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), 2491 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), 2492 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), 2493 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), 2494 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), 2495 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), 2496 { 2497 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2498 .name = "Channel Mode", 2499 .info = alc_ch_mode_info, 2500 .get = alc_ch_mode_get, 2501 .put = alc_ch_mode_put, 2502 }, 2503 { } /* end */ 2504}; 2505 2506static struct hda_verb alc880_test_init_verbs[] = { 2507 /* Unmute inputs of 0x0c - 0x0f */ 2508 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2509 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2510 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2511 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2512 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2513 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2514 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2515 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2516 /* Vol output for 0x0c-0x0f */ 2517 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2518 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2519 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2520 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2521 /* Set output pins 0x14-0x17 */ 2522 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2523 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2524 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2525 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2526 /* Unmute output pins 0x14-0x17 */ 2527 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2528 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2529 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2530 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2531 /* Set input pins 0x18-0x1c */ 2532 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2533 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2534 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2535 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2536 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2537 /* Mute input pins 0x18-0x1b */ 2538 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2539 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2540 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2541 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2542 /* ADC set up */ 2543 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2544 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 2545 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2546 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 2547 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2548 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 2549 /* Analog input/passthru */ 2550 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2551 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2552 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2553 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2554 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2555 { } 2556}; 2557#endif 2558 2559/* 2560 */ 2561 2562static const char *alc880_models[ALC880_MODEL_LAST] = { 2563 [ALC880_3ST] = "3stack", 2564 [ALC880_TCL_S700] = "tcl", 2565 [ALC880_3ST_DIG] = "3stack-digout", 2566 [ALC880_CLEVO] = "clevo", 2567 [ALC880_5ST] = "5stack", 2568 [ALC880_5ST_DIG] = "5stack-digout", 2569 [ALC880_W810] = "w810", 2570 [ALC880_Z71V] = "z71v", 2571 [ALC880_6ST] = "6stack", 2572 [ALC880_6ST_DIG] = "6stack-digout", 2573 [ALC880_ASUS] = "asus", 2574 [ALC880_ASUS_W1V] = "asus-w1v", 2575 [ALC880_ASUS_DIG] = "asus-dig", 2576 [ALC880_ASUS_DIG2] = "asus-dig2", 2577 [ALC880_UNIWILL_DIG] = "uniwill", 2578 [ALC880_UNIWILL_P53] = "uniwill-p53", 2579 [ALC880_FUJITSU] = "fujitsu", 2580 [ALC880_F1734] = "F1734", 2581 [ALC880_LG] = "lg", 2582 [ALC880_LG_LW] = "lg-lw", 2583#ifdef CONFIG_SND_DEBUG 2584 [ALC880_TEST] = "test", 2585#endif 2586 [ALC880_AUTO] = "auto", 2587}; 2588 2589static struct snd_pci_quirk alc880_cfg_tbl[] = { 2590 /* Broken BIOS configuration */ 2591 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), 2592 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG), 2593 2594 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG), 2595 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST), 2596 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810), 2597 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG), 2598 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG), 2599 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG), 2600 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG), 2601 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG), 2602 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST), 2603 2604 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG), 2605 SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST), 2606 2607 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V), 2608 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG), 2609 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG), 2610 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG), 2611 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG), 2612 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG), 2613 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V), 2614 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ 2615 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), 2616 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), 2617 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS), 2618 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), 2619 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), 2620 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), 2621 SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS), 2622 2623 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), 2624 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), 2625 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST), 2626 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST), 2627 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), 2628 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO), 2629 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO), 2630 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), 2631 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810), 2632 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), 2633 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700), 2634 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), 2635 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), 2636 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG), 2637 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG), 2638 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG), 2639 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG), 2640 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), 2641 2642 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), 2643 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), 2644 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53), 2645 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734), 2646 2647 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), 2648 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL), 2649 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), 2650 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), 2651 2652 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), 2653 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG), 2654 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW), 2655 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW), 2656 2657 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG), 2658 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG), 2659 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG), 2660 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG), 2661 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG), 2662 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG), 2663 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), 2664 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), 2665 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), 2666 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG), 2667 SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST), 2668 2669 {} 2670}; 2671 2672/* 2673 * ALC880 codec presets 2674 */ 2675static struct alc_config_preset alc880_presets[] = { 2676 [ALC880_3ST] = { 2677 .mixers = { alc880_three_stack_mixer }, 2678 .init_verbs = { alc880_volume_init_verbs, 2679 alc880_pin_3stack_init_verbs }, 2680 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2681 .dac_nids = alc880_dac_nids, 2682 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2683 .channel_mode = alc880_threestack_modes, 2684 .need_dac_fix = 1, 2685 .input_mux = &alc880_capture_source, 2686 }, 2687 [ALC880_3ST_DIG] = { 2688 .mixers = { alc880_three_stack_mixer }, 2689 .init_verbs = { alc880_volume_init_verbs, 2690 alc880_pin_3stack_init_verbs }, 2691 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2692 .dac_nids = alc880_dac_nids, 2693 .dig_out_nid = ALC880_DIGOUT_NID, 2694 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2695 .channel_mode = alc880_threestack_modes, 2696 .need_dac_fix = 1, 2697 .input_mux = &alc880_capture_source, 2698 }, 2699 [ALC880_TCL_S700] = { 2700 .mixers = { alc880_tcl_s700_mixer }, 2701 .init_verbs = { alc880_volume_init_verbs, 2702 alc880_pin_tcl_S700_init_verbs, 2703 alc880_gpio2_init_verbs }, 2704 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2705 .dac_nids = alc880_dac_nids, 2706 .hp_nid = 0x03, 2707 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2708 .channel_mode = alc880_2_jack_modes, 2709 .input_mux = &alc880_capture_source, 2710 }, 2711 [ALC880_5ST] = { 2712 .mixers = { alc880_three_stack_mixer, 2713 alc880_five_stack_mixer}, 2714 .init_verbs = { alc880_volume_init_verbs, 2715 alc880_pin_5stack_init_verbs }, 2716 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2717 .dac_nids = alc880_dac_nids, 2718 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), 2719 .channel_mode = alc880_fivestack_modes, 2720 .input_mux = &alc880_capture_source, 2721 }, 2722 [ALC880_5ST_DIG] = { 2723 .mixers = { alc880_three_stack_mixer, 2724 alc880_five_stack_mixer }, 2725 .init_verbs = { alc880_volume_init_verbs, 2726 alc880_pin_5stack_init_verbs }, 2727 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2728 .dac_nids = alc880_dac_nids, 2729 .dig_out_nid = ALC880_DIGOUT_NID, 2730 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), 2731 .channel_mode = alc880_fivestack_modes, 2732 .input_mux = &alc880_capture_source, 2733 }, 2734 [ALC880_6ST] = { 2735 .mixers = { alc880_six_stack_mixer }, 2736 .init_verbs = { alc880_volume_init_verbs, 2737 alc880_pin_6stack_init_verbs }, 2738 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), 2739 .dac_nids = alc880_6st_dac_nids, 2740 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), 2741 .channel_mode = alc880_sixstack_modes, 2742 .input_mux = &alc880_6stack_capture_source, 2743 }, 2744 [ALC880_6ST_DIG] = { 2745 .mixers = { alc880_six_stack_mixer }, 2746 .init_verbs = { alc880_volume_init_verbs, 2747 alc880_pin_6stack_init_verbs }, 2748 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), 2749 .dac_nids = alc880_6st_dac_nids, 2750 .dig_out_nid = ALC880_DIGOUT_NID, 2751 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), 2752 .channel_mode = alc880_sixstack_modes, 2753 .input_mux = &alc880_6stack_capture_source, 2754 }, 2755 [ALC880_W810] = { 2756 .mixers = { alc880_w810_base_mixer }, 2757 .init_verbs = { alc880_volume_init_verbs, 2758 alc880_pin_w810_init_verbs, 2759 alc880_gpio2_init_verbs }, 2760 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), 2761 .dac_nids = alc880_w810_dac_nids, 2762 .dig_out_nid = ALC880_DIGOUT_NID, 2763 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), 2764 .channel_mode = alc880_w810_modes, 2765 .input_mux = &alc880_capture_source, 2766 }, 2767 [ALC880_Z71V] = { 2768 .mixers = { alc880_z71v_mixer }, 2769 .init_verbs = { alc880_volume_init_verbs, 2770 alc880_pin_z71v_init_verbs }, 2771 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), 2772 .dac_nids = alc880_z71v_dac_nids, 2773 .dig_out_nid = ALC880_DIGOUT_NID, 2774 .hp_nid = 0x03, 2775 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2776 .channel_mode = alc880_2_jack_modes, 2777 .input_mux = &alc880_capture_source, 2778 }, 2779 [ALC880_F1734] = { 2780 .mixers = { alc880_f1734_mixer }, 2781 .init_verbs = { alc880_volume_init_verbs, 2782 alc880_pin_f1734_init_verbs }, 2783 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), 2784 .dac_nids = alc880_f1734_dac_nids, 2785 .hp_nid = 0x02, 2786 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2787 .channel_mode = alc880_2_jack_modes, 2788 .input_mux = &alc880_capture_source, 2789 }, 2790 [ALC880_ASUS] = { 2791 .mixers = { alc880_asus_mixer }, 2792 .init_verbs = { alc880_volume_init_verbs, 2793 alc880_pin_asus_init_verbs, 2794 alc880_gpio1_init_verbs }, 2795 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2796 .dac_nids = alc880_asus_dac_nids, 2797 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2798 .channel_mode = alc880_asus_modes, 2799 .need_dac_fix = 1, 2800 .input_mux = &alc880_capture_source, 2801 }, 2802 [ALC880_ASUS_DIG] = { 2803 .mixers = { alc880_asus_mixer }, 2804 .init_verbs = { alc880_volume_init_verbs, 2805 alc880_pin_asus_init_verbs, 2806 alc880_gpio1_init_verbs }, 2807 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2808 .dac_nids = alc880_asus_dac_nids, 2809 .dig_out_nid = ALC880_DIGOUT_NID, 2810 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2811 .channel_mode = alc880_asus_modes, 2812 .need_dac_fix = 1, 2813 .input_mux = &alc880_capture_source, 2814 }, 2815 [ALC880_ASUS_DIG2] = { 2816 .mixers = { alc880_asus_mixer }, 2817 .init_verbs = { alc880_volume_init_verbs, 2818 alc880_pin_asus_init_verbs, 2819 alc880_gpio2_init_verbs }, /* use GPIO2 */ 2820 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2821 .dac_nids = alc880_asus_dac_nids, 2822 .dig_out_nid = ALC880_DIGOUT_NID, 2823 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2824 .channel_mode = alc880_asus_modes, 2825 .need_dac_fix = 1, 2826 .input_mux = &alc880_capture_source, 2827 }, 2828 [ALC880_ASUS_W1V] = { 2829 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, 2830 .init_verbs = { alc880_volume_init_verbs, 2831 alc880_pin_asus_init_verbs, 2832 alc880_gpio1_init_verbs }, 2833 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2834 .dac_nids = alc880_asus_dac_nids, 2835 .dig_out_nid = ALC880_DIGOUT_NID, 2836 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2837 .channel_mode = alc880_asus_modes, 2838 .need_dac_fix = 1, 2839 .input_mux = &alc880_capture_source, 2840 }, 2841 [ALC880_UNIWILL_DIG] = { 2842 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer }, 2843 .init_verbs = { alc880_volume_init_verbs, 2844 alc880_pin_asus_init_verbs }, 2845 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2846 .dac_nids = alc880_asus_dac_nids, 2847 .dig_out_nid = ALC880_DIGOUT_NID, 2848 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 2849 .channel_mode = alc880_asus_modes, 2850 .need_dac_fix = 1, 2851 .input_mux = &alc880_capture_source, 2852 }, 2853 [ALC880_UNIWILL] = { 2854 .mixers = { alc880_uniwill_mixer }, 2855 .init_verbs = { alc880_volume_init_verbs, 2856 alc880_uniwill_init_verbs }, 2857 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2858 .dac_nids = alc880_asus_dac_nids, 2859 .dig_out_nid = ALC880_DIGOUT_NID, 2860 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2861 .channel_mode = alc880_threestack_modes, 2862 .need_dac_fix = 1, 2863 .input_mux = &alc880_capture_source, 2864 .unsol_event = alc880_uniwill_unsol_event, 2865 .init_hook = alc880_uniwill_automute, 2866 }, 2867 [ALC880_UNIWILL_P53] = { 2868 .mixers = { alc880_uniwill_p53_mixer }, 2869 .init_verbs = { alc880_volume_init_verbs, 2870 alc880_uniwill_p53_init_verbs }, 2871 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2872 .dac_nids = alc880_asus_dac_nids, 2873 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), 2874 .channel_mode = alc880_threestack_modes, 2875 .input_mux = &alc880_capture_source, 2876 .unsol_event = alc880_uniwill_p53_unsol_event, 2877 .init_hook = alc880_uniwill_p53_hp_automute, 2878 }, 2879 [ALC880_FUJITSU] = { 2880 .mixers = { alc880_fujitsu_mixer, 2881 alc880_pcbeep_mixer, }, 2882 .init_verbs = { alc880_volume_init_verbs, 2883 alc880_uniwill_p53_init_verbs, 2884 alc880_beep_init_verbs }, 2885 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2886 .dac_nids = alc880_dac_nids, 2887 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 2888 .channel_mode = alc880_2_jack_modes, 2889 .input_mux = &alc880_capture_source, 2890 .unsol_event = alc880_uniwill_p53_unsol_event, 2891 .init_hook = alc880_uniwill_p53_hp_automute, 2892 }, 2893 [ALC880_CLEVO] = { 2894 .mixers = { alc880_three_stack_mixer }, 2895 .init_verbs = { alc880_volume_init_verbs, 2896 alc880_pin_clevo_init_verbs }, 2897 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2898 .dac_nids = alc880_dac_nids, 2899 .hp_nid = 0x03, 2900 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 2901 .channel_mode = alc880_threestack_modes, 2902 .need_dac_fix = 1, 2903 .input_mux = &alc880_capture_source, 2904 }, 2905 [ALC880_LG] = { 2906 .mixers = { alc880_lg_mixer }, 2907 .init_verbs = { alc880_volume_init_verbs, 2908 alc880_lg_init_verbs }, 2909 .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids), 2910 .dac_nids = alc880_lg_dac_nids, 2911 .dig_out_nid = ALC880_DIGOUT_NID, 2912 .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), 2913 .channel_mode = alc880_lg_ch_modes, 2914 .need_dac_fix = 1, 2915 .input_mux = &alc880_lg_capture_source, 2916 .unsol_event = alc880_lg_unsol_event, 2917 .init_hook = alc880_lg_automute, 2918 }, 2919 [ALC880_LG_LW] = { 2920 .mixers = { alc880_lg_lw_mixer }, 2921 .init_verbs = { alc880_volume_init_verbs, 2922 alc880_lg_lw_init_verbs }, 2923 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 2924 .dac_nids = alc880_dac_nids, 2925 .dig_out_nid = ALC880_DIGOUT_NID, 2926 .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes), 2927 .channel_mode = alc880_lg_lw_modes, 2928 .input_mux = &alc880_lg_lw_capture_source, 2929 .unsol_event = alc880_lg_lw_unsol_event, 2930 .init_hook = alc880_lg_lw_automute, 2931 }, 2932#ifdef CONFIG_SND_DEBUG 2933 [ALC880_TEST] = { 2934 .mixers = { alc880_test_mixer }, 2935 .init_verbs = { alc880_test_init_verbs }, 2936 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids), 2937 .dac_nids = alc880_test_dac_nids, 2938 .dig_out_nid = ALC880_DIGOUT_NID, 2939 .num_channel_mode = ARRAY_SIZE(alc880_test_modes), 2940 .channel_mode = alc880_test_modes, 2941 .input_mux = &alc880_test_capture_source, 2942 }, 2943#endif 2944}; 2945 2946/* 2947 * Automatic parse of I/O pins from the BIOS configuration 2948 */ 2949 2950#define NUM_CONTROL_ALLOC 32 2951#define NUM_VERB_ALLOC 32 2952 2953enum { 2954 ALC_CTL_WIDGET_VOL, 2955 ALC_CTL_WIDGET_MUTE, 2956 ALC_CTL_BIND_MUTE, 2957}; 2958static struct snd_kcontrol_new alc880_control_templates[] = { 2959 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 2960 HDA_CODEC_MUTE(NULL, 0, 0, 0), 2961 HDA_BIND_MUTE(NULL, 0, 0, 0), 2962}; 2963 2964/* add dynamic controls */ 2965static int add_control(struct alc_spec *spec, int type, const char *name, 2966 unsigned long val) 2967{ 2968 struct snd_kcontrol_new *knew; 2969 2970 if (spec->num_kctl_used >= spec->num_kctl_alloc) { 2971 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; 2972 2973 /* array + terminator */ 2974 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); 2975 if (!knew) 2976 return -ENOMEM; 2977 if (spec->kctl_alloc) { 2978 memcpy(knew, spec->kctl_alloc, 2979 sizeof(*knew) * spec->num_kctl_alloc); 2980 kfree(spec->kctl_alloc); 2981 } 2982 spec->kctl_alloc = knew; 2983 spec->num_kctl_alloc = num; 2984 } 2985 2986 knew = &spec->kctl_alloc[spec->num_kctl_used]; 2987 *knew = alc880_control_templates[type]; 2988 knew->name = kstrdup(name, GFP_KERNEL); 2989 if (!knew->name) 2990 return -ENOMEM; 2991 knew->private_value = val; 2992 spec->num_kctl_used++; 2993 return 0; 2994} 2995 2996#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) 2997#define alc880_fixed_pin_idx(nid) ((nid) - 0x14) 2998#define alc880_is_multi_pin(nid) ((nid) >= 0x18) 2999#define alc880_multi_pin_idx(nid) ((nid) - 0x18) 3000#define alc880_is_input_pin(nid) ((nid) >= 0x18) 3001#define alc880_input_pin_idx(nid) ((nid) - 0x18) 3002#define alc880_idx_to_dac(nid) ((nid) + 0x02) 3003#define alc880_dac_to_idx(nid) ((nid) - 0x02) 3004#define alc880_idx_to_mixer(nid) ((nid) + 0x0c) 3005#define alc880_idx_to_selector(nid) ((nid) + 0x10) 3006#define ALC880_PIN_CD_NID 0x1c 3007 3008/* fill in the dac_nids table from the parsed pin configuration */ 3009static int alc880_auto_fill_dac_nids(struct alc_spec *spec, 3010 const struct auto_pin_cfg *cfg) 3011{ 3012 hda_nid_t nid; 3013 int assigned[4]; 3014 int i, j; 3015 3016 memset(assigned, 0, sizeof(assigned)); 3017 spec->multiout.dac_nids = spec->private_dac_nids; 3018 3019 /* check the pins hardwired to audio widget */ 3020 for (i = 0; i < cfg->line_outs; i++) { 3021 nid = cfg->line_out_pins[i]; 3022 if (alc880_is_fixed_pin(nid)) { 3023 int idx = alc880_fixed_pin_idx(nid); 3024 spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx); 3025 assigned[idx] = 1; 3026 } 3027 } 3028 /* left pins can be connect to any audio widget */ 3029 for (i = 0; i < cfg->line_outs; i++) { 3030 nid = cfg->line_out_pins[i]; 3031 if (alc880_is_fixed_pin(nid)) 3032 continue; 3033 /* search for an empty channel */ 3034 for (j = 0; j < cfg->line_outs; j++) { 3035 if (!assigned[j]) { 3036 spec->multiout.dac_nids[i] = 3037 alc880_idx_to_dac(j); 3038 assigned[j] = 1; 3039 break; 3040 } 3041 } 3042 } 3043 spec->multiout.num_dacs = cfg->line_outs; 3044 return 0; 3045} 3046 3047/* add playback controls from the parsed DAC table */ 3048static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, 3049 const struct auto_pin_cfg *cfg) 3050{ 3051 char name[32]; 3052 static const char *chname[4] = { 3053 "Front", "Surround", NULL /*CLFE*/, "Side" 3054 }; 3055 hda_nid_t nid; 3056 int i, err; 3057 3058 for (i = 0; i < cfg->line_outs; i++) { 3059 if (!spec->multiout.dac_nids[i]) 3060 continue; 3061 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); 3062 if (i == 2) { 3063 /* Center/LFE */ 3064 err = add_control(spec, ALC_CTL_WIDGET_VOL, 3065 "Center Playback Volume", 3066 HDA_COMPOSE_AMP_VAL(nid, 1, 0, 3067 HDA_OUTPUT)); 3068 if (err < 0) 3069 return err; 3070 err = add_control(spec, ALC_CTL_WIDGET_VOL, 3071 "LFE Playback Volume", 3072 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 3073 HDA_OUTPUT)); 3074 if (err < 0) 3075 return err; 3076 err = add_control(spec, ALC_CTL_BIND_MUTE, 3077 "Center Playback Switch", 3078 HDA_COMPOSE_AMP_VAL(nid, 1, 2, 3079 HDA_INPUT)); 3080 if (err < 0) 3081 return err; 3082 err = add_control(spec, ALC_CTL_BIND_MUTE, 3083 "LFE Playback Switch", 3084 HDA_COMPOSE_AMP_VAL(nid, 2, 2, 3085 HDA_INPUT)); 3086 if (err < 0) 3087 return err; 3088 } else { 3089 sprintf(name, "%s Playback Volume", chname[i]); 3090 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 3091 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 3092 HDA_OUTPUT)); 3093 if (err < 0) 3094 return err; 3095 sprintf(name, "%s Playback Switch", chname[i]); 3096 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 3097 HDA_COMPOSE_AMP_VAL(nid, 3, 2, 3098 HDA_INPUT)); 3099 if (err < 0) 3100 return err; 3101 } 3102 } 3103 return 0; 3104} 3105 3106/* add playback controls for speaker and HP outputs */ 3107static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, 3108 const char *pfx) 3109{ 3110 hda_nid_t nid; 3111 int err; 3112 char name[32]; 3113 3114 if (!pin) 3115 return 0; 3116 3117 if (alc880_is_fixed_pin(pin)) { 3118 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 3119 /* specify the DAC as the extra output */ 3120 if (!spec->multiout.hp_nid) 3121 spec->multiout.hp_nid = nid; 3122 else 3123 spec->multiout.extra_out_nid[0] = nid; 3124 /* control HP volume/switch on the output mixer amp */ 3125 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); 3126 sprintf(name, "%s Playback Volume", pfx); 3127 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 3128 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 3129 if (err < 0) 3130 return err; 3131 sprintf(name, "%s Playback Switch", pfx); 3132 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 3133 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); 3134 if (err < 0) 3135 return err; 3136 } else if (alc880_is_multi_pin(pin)) { 3137 /* set manual connection */ 3138 /* we have only a switch on HP-out PIN */ 3139 sprintf(name, "%s Playback Switch", pfx); 3140 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 3141 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 3142 if (err < 0) 3143 return err; 3144 } 3145 return 0; 3146} 3147 3148/* create input playback/capture controls for the given pin */ 3149static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, 3150 const char *ctlname, 3151 int idx, hda_nid_t mix_nid) 3152{ 3153 char name[32]; 3154 int err; 3155 3156 sprintf(name, "%s Playback Volume", ctlname); 3157 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 3158 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 3159 if (err < 0) 3160 return err; 3161 sprintf(name, "%s Playback Switch", ctlname); 3162 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 3163 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 3164 if (err < 0) 3165 return err; 3166 return 0; 3167} 3168 3169/* create playback/capture controls for input pins */ 3170static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, 3171 const struct auto_pin_cfg *cfg) 3172{ 3173 struct hda_input_mux *imux = &spec->private_imux; 3174 int i, err, idx; 3175 3176 for (i = 0; i < AUTO_PIN_LAST; i++) { 3177 if (alc880_is_input_pin(cfg->input_pins[i])) { 3178 idx = alc880_input_pin_idx(cfg->input_pins[i]); 3179 err = new_analog_input(spec, cfg->input_pins[i], 3180 auto_pin_cfg_labels[i], 3181 idx, 0x0b); 3182 if (err < 0) 3183 return err; 3184 imux->items[imux->num_items].label = 3185 auto_pin_cfg_labels[i]; 3186 imux->items[imux->num_items].index = 3187 alc880_input_pin_idx(cfg->input_pins[i]); 3188 imux->num_items++; 3189 } 3190 } 3191 return 0; 3192} 3193 3194static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, 3195 hda_nid_t nid, int pin_type, 3196 int dac_idx) 3197{ 3198 /* set as output */ 3199 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 3200 pin_type); 3201 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 3202 AMP_OUT_UNMUTE); 3203 /* need the manual connection? */ 3204 if (alc880_is_multi_pin(nid)) { 3205 struct alc_spec *spec = codec->spec; 3206 int idx = alc880_multi_pin_idx(nid); 3207 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, 3208 AC_VERB_SET_CONNECT_SEL, 3209 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); 3210 } 3211} 3212 3213static int get_pin_type(int line_out_type) 3214{ 3215 if (line_out_type == AUTO_PIN_HP_OUT) 3216 return PIN_HP; 3217 else 3218 return PIN_OUT; 3219} 3220 3221static void alc880_auto_init_multi_out(struct hda_codec *codec) 3222{ 3223 struct alc_spec *spec = codec->spec; 3224 int i; 3225 3226 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 3227 for (i = 0; i < spec->autocfg.line_outs; i++) { 3228 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 3229 int pin_type = get_pin_type(spec->autocfg.line_out_type); 3230 alc880_auto_set_output_and_unmute(codec, nid, pin_type, i); 3231 } 3232} 3233 3234static void alc880_auto_init_extra_out(struct hda_codec *codec) 3235{ 3236 struct alc_spec *spec = codec->spec; 3237 hda_nid_t pin; 3238 3239 pin = spec->autocfg.speaker_pins[0]; 3240 if (pin) /* connect to front */ 3241 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); 3242 pin = spec->autocfg.hp_pins[0]; 3243 if (pin) /* connect to front */ 3244 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 3245} 3246 3247static void alc880_auto_init_analog_input(struct hda_codec *codec) 3248{ 3249 struct alc_spec *spec = codec->spec; 3250 int i; 3251 3252 for (i = 0; i < AUTO_PIN_LAST; i++) { 3253 hda_nid_t nid = spec->autocfg.input_pins[i]; 3254 if (alc880_is_input_pin(nid)) { 3255 snd_hda_codec_write(codec, nid, 0, 3256 AC_VERB_SET_PIN_WIDGET_CONTROL, 3257 i <= AUTO_PIN_FRONT_MIC ? 3258 PIN_VREF80 : PIN_IN); 3259 if (nid != ALC880_PIN_CD_NID) 3260 snd_hda_codec_write(codec, nid, 0, 3261 AC_VERB_SET_AMP_GAIN_MUTE, 3262 AMP_OUT_MUTE); 3263 } 3264 } 3265} 3266 3267/* parse the BIOS configuration and set up the alc_spec */ 3268/* return 1 if successful, 0 if the proper config is not found, 3269 * or a negative error code 3270 */ 3271static int alc880_parse_auto_config(struct hda_codec *codec) 3272{ 3273 struct alc_spec *spec = codec->spec; 3274 int err; 3275 static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; 3276 3277 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 3278 alc880_ignore); 3279 if (err < 0) 3280 return err; 3281 if (!spec->autocfg.line_outs) 3282 return 0; /* can't find valid BIOS pin config */ 3283 3284 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 3285 if (err < 0) 3286 return err; 3287 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); 3288 if (err < 0) 3289 return err; 3290 err = alc880_auto_create_extra_out(spec, 3291 spec->autocfg.speaker_pins[0], 3292 "Speaker"); 3293 if (err < 0) 3294 return err; 3295 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], 3296 "Headphone"); 3297 if (err < 0) 3298 return err; 3299 err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg); 3300 if (err < 0) 3301 return err; 3302 3303 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 3304 3305 if (spec->autocfg.dig_out_pin) 3306 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; 3307 if (spec->autocfg.dig_in_pin) 3308 spec->dig_in_nid = ALC880_DIGIN_NID; 3309 3310 if (spec->kctl_alloc) 3311 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 3312 3313 spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; 3314 3315 spec->num_mux_defs = 1; 3316 spec->input_mux = &spec->private_imux; 3317 3318 return 1; 3319} 3320 3321/* additional initialization for auto-configuration model */ 3322static void alc880_auto_init(struct hda_codec *codec) 3323{ 3324 alc880_auto_init_multi_out(codec); 3325 alc880_auto_init_extra_out(codec); 3326 alc880_auto_init_analog_input(codec); 3327} 3328 3329/* 3330 * OK, here we have finally the patch for ALC880 3331 */ 3332 3333static int patch_alc880(struct hda_codec *codec) 3334{ 3335 struct alc_spec *spec; 3336 int board_config; 3337 int err; 3338 3339 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3340 if (spec == NULL) 3341 return -ENOMEM; 3342 3343 codec->spec = spec; 3344 3345 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST, 3346 alc880_models, 3347 alc880_cfg_tbl); 3348 if (board_config < 0) { 3349 printk(KERN_INFO "hda_codec: Unknown model for ALC880, " 3350 "trying auto-probe from BIOS...\n"); 3351 board_config = ALC880_AUTO; 3352 } 3353 3354 if (board_config == ALC880_AUTO) { 3355 /* automatic parse from the BIOS config */ 3356 err = alc880_parse_auto_config(codec); 3357 if (err < 0) { 3358 alc_free(codec); 3359 return err; 3360 } else if (!err) { 3361 printk(KERN_INFO 3362 "hda_codec: Cannot set up configuration " 3363 "from BIOS. Using 3-stack mode...\n"); 3364 board_config = ALC880_3ST; 3365 } 3366 } 3367 3368 if (board_config != ALC880_AUTO) 3369 setup_preset(spec, &alc880_presets[board_config]); 3370 3371 spec->stream_name_analog = "ALC880 Analog"; 3372 spec->stream_analog_playback = &alc880_pcm_analog_playback; 3373 spec->stream_analog_capture = &alc880_pcm_analog_capture; 3374 3375 spec->stream_name_digital = "ALC880 Digital"; 3376 spec->stream_digital_playback = &alc880_pcm_digital_playback; 3377 spec->stream_digital_capture = &alc880_pcm_digital_capture; 3378 3379 if (!spec->adc_nids && spec->input_mux) { 3380 /* check whether NID 0x07 is valid */ 3381 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]); 3382 /* get type */ 3383 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 3384 if (wcap != AC_WID_AUD_IN) { 3385 spec->adc_nids = alc880_adc_nids_alt; 3386 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); 3387 spec->mixers[spec->num_mixers] = 3388 alc880_capture_alt_mixer; 3389 spec->num_mixers++; 3390 } else { 3391 spec->adc_nids = alc880_adc_nids; 3392 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); 3393 spec->mixers[spec->num_mixers] = alc880_capture_mixer; 3394 spec->num_mixers++; 3395 } 3396 } 3397 3398 codec->patch_ops = alc_patch_ops; 3399 if (board_config == ALC880_AUTO) 3400 spec->init_hook = alc880_auto_init; 3401 3402 return 0; 3403} 3404 3405 3406/* 3407 * ALC260 support 3408 */ 3409 3410static hda_nid_t alc260_dac_nids[1] = { 3411 /* front */ 3412 0x02, 3413}; 3414 3415static hda_nid_t alc260_adc_nids[1] = { 3416 /* ADC0 */ 3417 0x04, 3418}; 3419 3420static hda_nid_t alc260_adc_nids_alt[1] = { 3421 /* ADC1 */ 3422 0x05, 3423}; 3424 3425static hda_nid_t alc260_hp_adc_nids[2] = { 3426 /* ADC1, 0 */ 3427 0x05, 0x04 3428}; 3429 3430/* NIDs used when simultaneous access to both ADCs makes sense. Note that 3431 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. 3432 */ 3433static hda_nid_t alc260_dual_adc_nids[2] = { 3434 /* ADC0, ADC1 */ 3435 0x04, 0x05 3436}; 3437 3438#define ALC260_DIGOUT_NID 0x03 3439#define ALC260_DIGIN_NID 0x06 3440 3441static struct hda_input_mux alc260_capture_source = { 3442 .num_items = 4, 3443 .items = { 3444 { "Mic", 0x0 }, 3445 { "Front Mic", 0x1 }, 3446 { "Line", 0x2 }, 3447 { "CD", 0x4 }, 3448 }, 3449}; 3450 3451/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, 3452 * headphone jack and the internal CD lines since these are the only pins at 3453 * which audio can appear. For flexibility, also allow the option of 3454 * recording the mixer output on the second ADC (ADC0 doesn't have a 3455 * connection to the mixer output). 3456 */ 3457static struct hda_input_mux alc260_fujitsu_capture_sources[2] = { 3458 { 3459 .num_items = 3, 3460 .items = { 3461 { "Mic/Line", 0x0 }, 3462 { "CD", 0x4 }, 3463 { "Headphone", 0x2 }, 3464 }, 3465 }, 3466 { 3467 .num_items = 4, 3468 .items = { 3469 { "Mic/Line", 0x0 }, 3470 { "CD", 0x4 }, 3471 { "Headphone", 0x2 }, 3472 { "Mixer", 0x5 }, 3473 }, 3474 }, 3475 3476}; 3477 3478/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to 3479 * the Fujitsu S702x, but jacks are marked differently. 3480 */ 3481static struct hda_input_mux alc260_acer_capture_sources[2] = { 3482 { 3483 .num_items = 4, 3484 .items = { 3485 { "Mic", 0x0 }, 3486 { "Line", 0x2 }, 3487 { "CD", 0x4 }, 3488 { "Headphone", 0x5 }, 3489 }, 3490 }, 3491 { 3492 .num_items = 5, 3493 .items = { 3494 { "Mic", 0x0 }, 3495 { "Line", 0x2 }, 3496 { "CD", 0x4 }, 3497 { "Headphone", 0x6 }, 3498 { "Mixer", 0x5 }, 3499 }, 3500 }, 3501}; 3502/* 3503 * This is just place-holder, so there's something for alc_build_pcms to look 3504 * at when it calculates the maximum number of channels. ALC260 has no mixer 3505 * element which allows changing the channel mode, so the verb list is 3506 * never used. 3507 */ 3508static struct hda_channel_mode alc260_modes[1] = { 3509 { 2, NULL }, 3510}; 3511 3512 3513/* Mixer combinations 3514 * 3515 * basic: base_output + input + pc_beep + capture 3516 * HP: base_output + input + capture_alt 3517 * HP_3013: hp_3013 + input + capture 3518 * fujitsu: fujitsu + capture 3519 * acer: acer + capture 3520 */ 3521 3522static struct snd_kcontrol_new alc260_base_output_mixer[] = { 3523 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3524 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), 3525 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), 3526 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), 3527 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 3528 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), 3529 { } /* end */ 3530}; 3531 3532static struct snd_kcontrol_new alc260_input_mixer[] = { 3533 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3534 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3535 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3536 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3537 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3538 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3539 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), 3540 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), 3541 { } /* end */ 3542}; 3543 3544static struct snd_kcontrol_new alc260_pc_beep_mixer[] = { 3545 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), 3546 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), 3547 { } /* end */ 3548}; 3549 3550static struct snd_kcontrol_new alc260_hp_3013_mixer[] = { 3551 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT), 3552 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT), 3553 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT), 3554 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT), 3555 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3556 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 3557 HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 3558 HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT), 3559 { } /* end */ 3560}; 3561 3562/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12, 3563 * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10. 3564 */ 3565static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { 3566 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3567 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), 3568 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3569 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3570 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3571 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), 3572 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), 3573 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), 3574 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 3575 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 3576 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), 3577 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT), 3578 { } /* end */ 3579}; 3580 3581/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current 3582 * versions of the ALC260 don't act on requests to enable mic bias from NID 3583 * 0x0f (used to drive the headphone jack in these laptops). The ALC260 3584 * datasheet doesn't mention this restriction. At this stage it's not clear 3585 * whether this behaviour is intentional or is a hardware bug in chip 3586 * revisions available in early 2006. Therefore for now allow the 3587 * "Headphone Jack Mode" control to span all choices, but if it turns out 3588 * that the lack of mic bias for this NID is intentional we could change the 3589 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. 3590 * 3591 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006 3592 * don't appear to make the mic bias available from the "line" jack, even 3593 * though the NID used for this jack (0x14) can supply it. The theory is 3594 * that perhaps Acer have included blocking capacitors between the ALC260 3595 * and the output jack. If this turns out to be the case for all such 3596 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT 3597 * to ALC_PIN_DIR_INOUT_NOMICBIAS. 3598 * 3599 * The C20x Tablet series have a mono internal speaker which is controlled 3600 * via the chip's Mono sum widget and pin complex, so include the necessary 3601 * controls for such models. On models without a "mono speaker" the control 3602 * won't do anything. 3603 */ 3604static struct snd_kcontrol_new alc260_acer_mixer[] = { 3605 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3606 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), 3607 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), 3608 HDA_CODEC_VOLUME_MONO("Mono Speaker Playback Volume", 0x0a, 1, 0x0, 3609 HDA_OUTPUT), 3610 HDA_BIND_MUTE_MONO("Mono Speaker Playback Switch", 0x0a, 1, 2, 3611 HDA_INPUT), 3612 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3613 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3614 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3615 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3616 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), 3617 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3618 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3619 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3620 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 3621 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 3622 { } /* end */ 3623}; 3624 3625/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12, 3626 * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17. 3627 */ 3628static struct snd_kcontrol_new alc260_will_mixer[] = { 3629 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3630 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), 3631 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3632 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3633 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), 3634 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3635 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3636 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3637 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3638 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3639 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 3640 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 3641 { } /* end */ 3642}; 3643 3644/* Replacer 672V ALC260 pin usage: Mic jack = 0x12, 3645 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f. 3646 */ 3647static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = { 3648 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3649 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), 3650 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3651 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 3652 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), 3653 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT), 3654 HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT), 3655 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 3656 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 3657 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), 3658 { } /* end */ 3659}; 3660 3661/* capture mixer elements */ 3662static struct snd_kcontrol_new alc260_capture_mixer[] = { 3663 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), 3664 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), 3665 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT), 3666 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT), 3667 { 3668 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3669 /* The multiple "Capture Source" controls confuse alsamixer 3670 * So call somewhat different.. 3671 * FIXME: the controls appear in the "playback" view! 3672 */ 3673 /* .name = "Capture Source", */ 3674 .name = "Input Source", 3675 .count = 2, 3676 .info = alc_mux_enum_info, 3677 .get = alc_mux_enum_get, 3678 .put = alc_mux_enum_put, 3679 }, 3680 { } /* end */ 3681}; 3682 3683static struct snd_kcontrol_new alc260_capture_alt_mixer[] = { 3684 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), 3685 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT), 3686 { 3687 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3688 /* The multiple "Capture Source" controls confuse alsamixer 3689 * So call somewhat different.. 3690 * FIXME: the controls appear in the "playback" view! 3691 */ 3692 /* .name = "Capture Source", */ 3693 .name = "Input Source", 3694 .count = 1, 3695 .info = alc_mux_enum_info, 3696 .get = alc_mux_enum_get, 3697 .put = alc_mux_enum_put, 3698 }, 3699 { } /* end */ 3700}; 3701 3702/* 3703 * initialization verbs 3704 */ 3705static struct hda_verb alc260_init_verbs[] = { 3706 /* Line In pin widget for input */ 3707 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3708 /* CD pin widget for input */ 3709 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3710 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 3711 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3712 /* Mic2 (front panel) pin widget for input and vref at 80% */ 3713 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3714 /* LINE-2 is used for line-out in rear */ 3715 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3716 /* select line-out */ 3717 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, 3718 /* LINE-OUT pin */ 3719 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3720 /* enable HP */ 3721 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3722 /* enable Mono */ 3723 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3724 /* mute capture amp left and right */ 3725 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3726 /* set connection select to line in (default select for this ADC) */ 3727 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, 3728 /* mute capture amp left and right */ 3729 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3730 /* set connection select to line in (default select for this ADC) */ 3731 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, 3732 /* set vol=0 Line-Out mixer amp left and right */ 3733 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3734 /* unmute pin widget amp left and right (no gain on this amp) */ 3735 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3736 /* set vol=0 HP mixer amp left and right */ 3737 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3738 /* unmute pin widget amp left and right (no gain on this amp) */ 3739 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3740 /* set vol=0 Mono mixer amp left and right */ 3741 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3742 /* unmute pin widget amp left and right (no gain on this amp) */ 3743 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3744 /* unmute LINE-2 out pin */ 3745 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3746 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & 3747 * Line In 2 = 0x03 3748 */ 3749 /* mute CD */ 3750 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 3751 /* mute Line In */ 3752 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 3753 /* mute Mic */ 3754 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3755 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ 3756 /* mute Front out path */ 3757 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3758 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3759 /* mute Headphone out path */ 3760 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3761 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3762 /* mute Mono out path */ 3763 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3764 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3765 { } 3766}; 3767 3768#if 0 /* should be identical with alc260_init_verbs? */ 3769static struct hda_verb alc260_hp_init_verbs[] = { 3770 /* Headphone and output */ 3771 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 3772 /* mono output */ 3773 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3774 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 3775 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3776 /* Mic2 (front panel) pin widget for input and vref at 80% */ 3777 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3778 /* Line In pin widget for input */ 3779 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3780 /* Line-2 pin widget for output */ 3781 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3782 /* CD pin widget for input */ 3783 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3784 /* unmute amp left and right */ 3785 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, 3786 /* set connection select to line in (default select for this ADC) */ 3787 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, 3788 /* unmute Line-Out mixer amp left and right (volume = 0) */ 3789 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3790 /* mute pin widget amp left and right (no gain on this amp) */ 3791 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3792 /* unmute HP mixer amp left and right (volume = 0) */ 3793 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3794 /* mute pin widget amp left and right (no gain on this amp) */ 3795 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3796 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & 3797 * Line In 2 = 0x03 3798 */ 3799 /* unmute CD */ 3800 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 3801 /* unmute Line In */ 3802 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 3803 /* unmute Mic */ 3804 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3805 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ 3806 /* Unmute Front out path */ 3807 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3808 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3809 /* Unmute Headphone out path */ 3810 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3811 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3812 /* Unmute Mono out path */ 3813 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3814 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3815 { } 3816}; 3817#endif 3818 3819static struct hda_verb alc260_hp_3013_init_verbs[] = { 3820 /* Line out and output */ 3821 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3822 /* mono output */ 3823 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3824 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 3825 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3826 /* Mic2 (front panel) pin widget for input and vref at 80% */ 3827 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 3828 /* Line In pin widget for input */ 3829 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3830 /* Headphone pin widget for output */ 3831 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 3832 /* CD pin widget for input */ 3833 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 3834 /* unmute amp left and right */ 3835 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, 3836 /* set connection select to line in (default select for this ADC) */ 3837 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, 3838 /* unmute Line-Out mixer amp left and right (volume = 0) */ 3839 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3840 /* mute pin widget amp left and right (no gain on this amp) */ 3841 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3842 /* unmute HP mixer amp left and right (volume = 0) */ 3843 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 3844 /* mute pin widget amp left and right (no gain on this amp) */ 3845 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 3846 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & 3847 * Line In 2 = 0x03 3848 */ 3849 /* unmute CD */ 3850 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 3851 /* unmute Line In */ 3852 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 3853 /* unmute Mic */ 3854 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3855 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ 3856 /* Unmute Front out path */ 3857 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3858 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3859 /* Unmute Headphone out path */ 3860 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3861 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3862 /* Unmute Mono out path */ 3863 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 3864 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3865 { } 3866}; 3867 3868/* Initialisation sequence for ALC260 as configured in Fujitsu S702x 3869 * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD 3870 * audio = 0x16, internal speaker = 0x10. 3871 */ 3872static struct hda_verb alc260_fujitsu_init_verbs[] = { 3873 /* Disable all GPIOs */ 3874 {0x01, AC_VERB_SET_GPIO_MASK, 0}, 3875 /* Internal speaker is connected to headphone pin */ 3876 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3877 /* Headphone/Line-out jack connects to Line1 pin; make it an output */ 3878 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3879 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */ 3880 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3881 /* Ensure all other unused pins are disabled and muted. */ 3882 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3883 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3884 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3885 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3886 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3887 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3888 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3889 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3890 3891 /* Disable digital (SPDIF) pins */ 3892 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3893 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3894 3895 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus 3896 * when acting as an output. 3897 */ 3898 {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, 3899 3900 /* Start with output sum widgets muted and their output gains at min */ 3901 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3902 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3903 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3904 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3905 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3906 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3907 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3908 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3909 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3910 3911 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */ 3912 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3913 /* Unmute Line1 pin widget output buffer since it starts as an output. 3914 * If the pin mode is changed by the user the pin mode control will 3915 * take care of enabling the pin's input/output buffers as needed. 3916 * Therefore there's no need to enable the input buffer at this 3917 * stage. 3918 */ 3919 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3920 /* Unmute input buffer of pin widget used for Line-in (no equiv 3921 * mixer ctrl) 3922 */ 3923 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3924 3925 /* Mute capture amp left and right */ 3926 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3927 /* Set ADC connection select to match default mixer setting - line 3928 * in (on mic1 pin) 3929 */ 3930 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 3931 3932 /* Do the same for the second ADC: mute capture input amp and 3933 * set ADC connection to line in (on mic1 pin) 3934 */ 3935 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3936 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 3937 3938 /* Mute all inputs to mixer widget (even unconnected ones) */ 3939 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 3940 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 3941 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 3942 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 3943 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 3944 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 3945 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 3946 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 3947 3948 { } 3949}; 3950 3951/* Initialisation sequence for ALC260 as configured in Acer TravelMate and 3952 * similar laptops (adapted from Fujitsu init verbs). 3953 */ 3954static struct hda_verb alc260_acer_init_verbs[] = { 3955 /* On TravelMate laptops, GPIO 0 enables the internal speaker and 3956 * the headphone jack. Turn this on and rely on the standard mute 3957 * methods whenever the user wants to turn these outputs off. 3958 */ 3959 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 3960 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 3961 {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, 3962 /* Internal speaker/Headphone jack is connected to Line-out pin */ 3963 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3964 /* Internal microphone/Mic jack is connected to Mic1 pin */ 3965 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, 3966 /* Line In jack is connected to Line1 pin */ 3967 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3968 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */ 3969 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3970 /* Ensure all other unused pins are disabled and muted. */ 3971 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3972 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3973 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3974 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3975 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3976 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3977 /* Disable digital (SPDIF) pins */ 3978 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3979 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, 3980 3981 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum 3982 * bus when acting as outputs. 3983 */ 3984 {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, 3985 {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, 3986 3987 /* Start with output sum widgets muted and their output gains at min */ 3988 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3989 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3990 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3991 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3992 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3993 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3994 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3995 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3996 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3997 3998 /* Unmute Line-out pin widget amp left and right 3999 * (no equiv mixer ctrl) 4000 */ 4001 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4002 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */ 4003 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4004 /* Unmute Mic1 and Line1 pin widget input buffers since they start as 4005 * inputs. If the pin mode is changed by the user the pin mode control 4006 * will take care of enabling the pin's input/output buffers as needed. 4007 * Therefore there's no need to enable the input buffer at this 4008 * stage. 4009 */ 4010 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4011 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4012 4013 /* Mute capture amp left and right */ 4014 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4015 /* Set ADC connection select to match default mixer setting - mic 4016 * (on mic1 pin) 4017 */ 4018 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 4019 4020 /* Do similar with the second ADC: mute capture input amp and 4021 * set ADC connection to mic to match ALSA's default state. 4022 */ 4023 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4024 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 4025 4026 /* Mute all inputs to mixer widget (even unconnected ones) */ 4027 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 4028 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 4029 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 4030 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 4031 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 4032 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 4033 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 4034 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 4035 4036 { } 4037}; 4038 4039static struct hda_verb alc260_will_verbs[] = { 4040 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4041 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, 4042 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, 4043 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4044 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, 4045 {0x1a, AC_VERB_SET_PROC_COEF, 0x3040}, 4046 {} 4047}; 4048 4049static struct hda_verb alc260_replacer_672v_verbs[] = { 4050 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4051 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, 4052 {0x1a, AC_VERB_SET_PROC_COEF, 0x3050}, 4053 4054 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 4055 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 4056 {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, 4057 4058 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 4059 {} 4060}; 4061 4062/* toggle speaker-output according to the hp-jack state */ 4063static void alc260_replacer_672v_automute(struct hda_codec *codec) 4064{ 4065 unsigned int present; 4066 4067 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */ 4068 present = snd_hda_codec_read(codec, 0x0f, 0, 4069 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 4070 if (present) { 4071 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1); 4072 snd_hda_codec_write(codec, 0x0f, 0, 4073 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); 4074 } else { 4075 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0); 4076 snd_hda_codec_write(codec, 0x0f, 0, 4077 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 4078 } 4079} 4080 4081static void alc260_replacer_672v_unsol_event(struct hda_codec *codec, 4082 unsigned int res) 4083{ 4084 if ((res >> 26) == ALC880_HP_EVENT) 4085 alc260_replacer_672v_automute(codec); 4086} 4087 4088/* Test configuration for debugging, modelled after the ALC880 test 4089 * configuration. 4090 */ 4091#ifdef CONFIG_SND_DEBUG 4092static hda_nid_t alc260_test_dac_nids[1] = { 4093 0x02, 4094}; 4095static hda_nid_t alc260_test_adc_nids[2] = { 4096 0x04, 0x05, 4097}; 4098/* For testing the ALC260, each input MUX needs its own definition since 4099 * the signal assignments are different. This assumes that the first ADC 4100 * is NID 0x04. 4101 */ 4102static struct hda_input_mux alc260_test_capture_sources[2] = { 4103 { 4104 .num_items = 7, 4105 .items = { 4106 { "MIC1 pin", 0x0 }, 4107 { "MIC2 pin", 0x1 }, 4108 { "LINE1 pin", 0x2 }, 4109 { "LINE2 pin", 0x3 }, 4110 { "CD pin", 0x4 }, 4111 { "LINE-OUT pin", 0x5 }, 4112 { "HP-OUT pin", 0x6 }, 4113 }, 4114 }, 4115 { 4116 .num_items = 8, 4117 .items = { 4118 { "MIC1 pin", 0x0 }, 4119 { "MIC2 pin", 0x1 }, 4120 { "LINE1 pin", 0x2 }, 4121 { "LINE2 pin", 0x3 }, 4122 { "CD pin", 0x4 }, 4123 { "Mixer", 0x5 }, 4124 { "LINE-OUT pin", 0x6 }, 4125 { "HP-OUT pin", 0x7 }, 4126 }, 4127 }, 4128}; 4129static struct snd_kcontrol_new alc260_test_mixer[] = { 4130 /* Output driver widgets */ 4131 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 4132 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), 4133 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT), 4134 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT), 4135 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), 4136 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), 4137 4138 /* Modes for retasking pin widgets 4139 * Note: the ALC260 doesn't seem to act on requests to enable mic 4140 * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't 4141 * mention this restriction. At this stage it's not clear whether 4142 * this behaviour is intentional or is a hardware bug in chip 4143 * revisions available at least up until early 2006. Therefore for 4144 * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all 4145 * choices, but if it turns out that the lack of mic bias for these 4146 * NIDs is intentional we could change their modes from 4147 * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. 4148 */ 4149 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), 4150 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), 4151 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), 4152 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT), 4153 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT), 4154 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT), 4155 4156 /* Loopback mixer controls */ 4157 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT), 4158 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT), 4159 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT), 4160 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT), 4161 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT), 4162 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT), 4163 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT), 4164 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), 4165 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 4166 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 4167 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 4168 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 4169 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), 4170 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), 4171 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), 4172 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT), 4173 4174 /* Controls for GPIO pins, assuming they are configured as outputs */ 4175 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), 4176 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), 4177 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), 4178 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), 4179 4180 /* Switches to allow the digital IO pins to be enabled. The datasheet 4181 * is ambigious as to which NID is which; testing on laptops which 4182 * make this output available should provide clarification. 4183 */ 4184 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01), 4185 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01), 4186 4187 { } /* end */ 4188}; 4189static struct hda_verb alc260_test_init_verbs[] = { 4190 /* Enable all GPIOs as outputs with an initial value of 0 */ 4191 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f}, 4192 {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, 4193 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f}, 4194 4195 /* Enable retasking pins as output, initially without power amp */ 4196 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4197 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4198 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4199 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4200 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4201 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4202 4203 /* Disable digital (SPDIF) pins initially, but users can enable 4204 * them via a mixer switch. In the case of SPDIF-out, this initverb 4205 * payload also sets the generation to 0, output to be in "consumer" 4206 * PCM format, copyright asserted, no pre-emphasis and no validity 4207 * control. 4208 */ 4209 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, 4210 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, 4211 4212 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the 4213 * OUT1 sum bus when acting as an output. 4214 */ 4215 {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, 4216 {0x0c, AC_VERB_SET_CONNECT_SEL, 0}, 4217 {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, 4218 {0x0e, AC_VERB_SET_CONNECT_SEL, 0}, 4219 4220 /* Start with output sum widgets muted and their output gains at min */ 4221 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4222 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4223 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4224 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4225 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4226 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4227 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4228 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4229 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4230 4231 /* Unmute retasking pin widget output buffers since the default 4232 * state appears to be output. As the pin mode is changed by the 4233 * user the pin mode control will take care of enabling the pin's 4234 * input/output buffers as needed. 4235 */ 4236 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4237 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4238 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4239 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4240 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4241 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4242 /* Also unmute the mono-out pin widget */ 4243 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4244 4245 /* Mute capture amp left and right */ 4246 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4247 /* Set ADC connection select to match default mixer setting (mic1 4248 * pin) 4249 */ 4250 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 4251 4252 /* Do the same for the second ADC: mute capture input amp and 4253 * set ADC connection to mic1 pin 4254 */ 4255 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4256 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 4257 4258 /* Mute all inputs to mixer widget (even unconnected ones) */ 4259 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 4260 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 4261 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 4262 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 4263 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 4264 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 4265 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 4266 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 4267 4268 { } 4269}; 4270#endif 4271 4272static struct hda_pcm_stream alc260_pcm_analog_playback = { 4273 .substreams = 1, 4274 .channels_min = 2, 4275 .channels_max = 2, 4276}; 4277 4278static struct hda_pcm_stream alc260_pcm_analog_capture = { 4279 .substreams = 1, 4280 .channels_min = 2, 4281 .channels_max = 2, 4282}; 4283 4284#define alc260_pcm_digital_playback alc880_pcm_digital_playback 4285#define alc260_pcm_digital_capture alc880_pcm_digital_capture 4286 4287/* 4288 * for BIOS auto-configuration 4289 */ 4290 4291static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid, 4292 const char *pfx) 4293{ 4294 hda_nid_t nid_vol; 4295 unsigned long vol_val, sw_val; 4296 char name[32]; 4297 int err; 4298 4299 if (nid >= 0x0f && nid < 0x11) { 4300 nid_vol = nid - 0x7; 4301 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT); 4302 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); 4303 } else if (nid == 0x11) { 4304 nid_vol = nid - 0x7; 4305 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT); 4306 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); 4307 } else if (nid >= 0x12 && nid <= 0x15) { 4308 nid_vol = 0x08; 4309 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT); 4310 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); 4311 } else 4312 return 0; /* N/A */ 4313 4314 snprintf(name, sizeof(name), "%s Playback Volume", pfx); 4315 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val); 4316 if (err < 0) 4317 return err; 4318 snprintf(name, sizeof(name), "%s Playback Switch", pfx); 4319 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val); 4320 if (err < 0) 4321 return err; 4322 return 1; 4323} 4324 4325/* add playback controls from the parsed DAC table */ 4326static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, 4327 const struct auto_pin_cfg *cfg) 4328{ 4329 hda_nid_t nid; 4330 int err; 4331 4332 spec->multiout.num_dacs = 1; 4333 spec->multiout.dac_nids = spec->private_dac_nids; 4334 spec->multiout.dac_nids[0] = 0x02; 4335 4336 nid = cfg->line_out_pins[0]; 4337 if (nid) { 4338 err = alc260_add_playback_controls(spec, nid, "Front"); 4339 if (err < 0) 4340 return err; 4341 } 4342 4343 nid = cfg->speaker_pins[0]; 4344 if (nid) { 4345 err = alc260_add_playback_controls(spec, nid, "Speaker"); 4346 if (err < 0) 4347 return err; 4348 } 4349 4350 nid = cfg->hp_pins[0]; 4351 if (nid) { 4352 err = alc260_add_playback_controls(spec, nid, "Headphone"); 4353 if (err < 0) 4354 return err; 4355 } 4356 return 0; 4357} 4358 4359/* create playback/capture controls for input pins */ 4360static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec, 4361 const struct auto_pin_cfg *cfg) 4362{ 4363 struct hda_input_mux *imux = &spec->private_imux; 4364 int i, err, idx; 4365 4366 for (i = 0; i < AUTO_PIN_LAST; i++) { 4367 if (cfg->input_pins[i] >= 0x12) { 4368 idx = cfg->input_pins[i] - 0x12; 4369 err = new_analog_input(spec, cfg->input_pins[i], 4370 auto_pin_cfg_labels[i], idx, 4371 0x07); 4372 if (err < 0) 4373 return err; 4374 imux->items[imux->num_items].label = 4375 auto_pin_cfg_labels[i]; 4376 imux->items[imux->num_items].index = idx; 4377 imux->num_items++; 4378 } 4379 if (cfg->input_pins[i] >= 0x0f && cfg->input_pins[i] <= 0x10){ 4380 idx = cfg->input_pins[i] - 0x09; 4381 err = new_analog_input(spec, cfg->input_pins[i], 4382 auto_pin_cfg_labels[i], idx, 4383 0x07); 4384 if (err < 0) 4385 return err; 4386 imux->items[imux->num_items].label = 4387 auto_pin_cfg_labels[i]; 4388 imux->items[imux->num_items].index = idx; 4389 imux->num_items++; 4390 } 4391 } 4392 return 0; 4393} 4394 4395static void alc260_auto_set_output_and_unmute(struct hda_codec *codec, 4396 hda_nid_t nid, int pin_type, 4397 int sel_idx) 4398{ 4399 /* set as output */ 4400 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 4401 pin_type); 4402 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 4403 AMP_OUT_UNMUTE); 4404 /* need the manual connection? */ 4405 if (nid >= 0x12) { 4406 int idx = nid - 0x12; 4407 snd_hda_codec_write(codec, idx + 0x0b, 0, 4408 AC_VERB_SET_CONNECT_SEL, sel_idx); 4409 } 4410} 4411 4412static void alc260_auto_init_multi_out(struct hda_codec *codec) 4413{ 4414 struct alc_spec *spec = codec->spec; 4415 hda_nid_t nid; 4416 4417 alc_subsystem_id(codec, 0x10, 0x15, 0x0f); 4418 nid = spec->autocfg.line_out_pins[0]; 4419 if (nid) { 4420 int pin_type = get_pin_type(spec->autocfg.line_out_type); 4421 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0); 4422 } 4423 4424 nid = spec->autocfg.speaker_pins[0]; 4425 if (nid) 4426 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); 4427 4428 nid = spec->autocfg.hp_pins[0]; 4429 if (nid) 4430 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0); 4431} 4432 4433#define ALC260_PIN_CD_NID 0x16 4434static void alc260_auto_init_analog_input(struct hda_codec *codec) 4435{ 4436 struct alc_spec *spec = codec->spec; 4437 int i; 4438 4439 for (i = 0; i < AUTO_PIN_LAST; i++) { 4440 hda_nid_t nid = spec->autocfg.input_pins[i]; 4441 if (nid >= 0x12) { 4442 snd_hda_codec_write(codec, nid, 0, 4443 AC_VERB_SET_PIN_WIDGET_CONTROL, 4444 i <= AUTO_PIN_FRONT_MIC ? 4445 PIN_VREF80 : PIN_IN); 4446 if (nid != ALC260_PIN_CD_NID) 4447 snd_hda_codec_write(codec, nid, 0, 4448 AC_VERB_SET_AMP_GAIN_MUTE, 4449 AMP_OUT_MUTE); 4450 } 4451 } 4452} 4453 4454/* 4455 * generic initialization of ADC, input mixers and output mixers 4456 */ 4457static struct hda_verb alc260_volume_init_verbs[] = { 4458 /* 4459 * Unmute ADC0-1 and set the default input to mic-in 4460 */ 4461 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 4462 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4463 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, 4464 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4465 4466 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 4467 * mixer widget 4468 * Note: PASD motherboards uses the Line In 2 as the input for 4469 * front panel mic (mic 2) 4470 */ 4471 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 4472 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4473 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4474 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 4475 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 4476 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 4477 4478 /* 4479 * Set up output mixers (0x08 - 0x0a) 4480 */ 4481 /* set vol=0 to output mixers */ 4482 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4483 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4484 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4485 /* set up input amps for analog loopback */ 4486 /* Amp Indices: DAC = 0, mixer = 1 */ 4487 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4488 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4489 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4490 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4491 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4492 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4493 4494 { } 4495}; 4496 4497static int alc260_parse_auto_config(struct hda_codec *codec) 4498{ 4499 struct alc_spec *spec = codec->spec; 4500 unsigned int wcap; 4501 int err; 4502 static hda_nid_t alc260_ignore[] = { 0x17, 0 }; 4503 4504 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 4505 alc260_ignore); 4506 if (err < 0) 4507 return err; 4508 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); 4509 if (err < 0) 4510 return err; 4511 if (!spec->kctl_alloc) 4512 return 0; /* can't find valid BIOS pin config */ 4513 err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); 4514 if (err < 0) 4515 return err; 4516 4517 spec->multiout.max_channels = 2; 4518 4519 if (spec->autocfg.dig_out_pin) 4520 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; 4521 if (spec->kctl_alloc) 4522 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 4523 4524 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; 4525 4526 spec->num_mux_defs = 1; 4527 spec->input_mux = &spec->private_imux; 4528 4529 /* check whether NID 0x04 is valid */ 4530 wcap = get_wcaps(codec, 0x04); 4531 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ 4532 if (wcap != AC_WID_AUD_IN) { 4533 spec->adc_nids = alc260_adc_nids_alt; 4534 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt); 4535 spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer; 4536 } else { 4537 spec->adc_nids = alc260_adc_nids; 4538 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); 4539 spec->mixers[spec->num_mixers] = alc260_capture_mixer; 4540 } 4541 spec->num_mixers++; 4542 4543 return 1; 4544} 4545 4546/* additional initialization for auto-configuration model */ 4547static void alc260_auto_init(struct hda_codec *codec) 4548{ 4549 alc260_auto_init_multi_out(codec); 4550 alc260_auto_init_analog_input(codec); 4551} 4552 4553/* 4554 * ALC260 configurations 4555 */ 4556static const char *alc260_models[ALC260_MODEL_LAST] = { 4557 [ALC260_BASIC] = "basic", 4558 [ALC260_HP] = "hp", 4559 [ALC260_HP_3013] = "hp-3013", 4560 [ALC260_FUJITSU_S702X] = "fujitsu", 4561 [ALC260_ACER] = "acer", 4562 [ALC260_WILL] = "will", 4563 [ALC260_REPLACER_672V] = "replacer", 4564#ifdef CONFIG_SND_DEBUG 4565 [ALC260_TEST] = "test", 4566#endif 4567 [ALC260_AUTO] = "auto", 4568}; 4569 4570static struct snd_pci_quirk alc260_cfg_tbl[] = { 4571 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), 4572 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), 4573 SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013), 4574 SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013), 4575 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013), 4576 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP), 4577 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013), 4578 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013), 4579 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP), 4580 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP), 4581 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP), 4582 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC), 4583 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC), 4584 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), 4585 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), 4586 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), 4587 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL), 4588 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V), 4589 {} 4590}; 4591 4592static struct alc_config_preset alc260_presets[] = { 4593 [ALC260_BASIC] = { 4594 .mixers = { alc260_base_output_mixer, 4595 alc260_input_mixer, 4596 alc260_pc_beep_mixer, 4597 alc260_capture_mixer }, 4598 .init_verbs = { alc260_init_verbs }, 4599 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4600 .dac_nids = alc260_dac_nids, 4601 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), 4602 .adc_nids = alc260_adc_nids, 4603 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4604 .channel_mode = alc260_modes, 4605 .input_mux = &alc260_capture_source, 4606 }, 4607 [ALC260_HP] = { 4608 .mixers = { alc260_base_output_mixer, 4609 alc260_input_mixer, 4610 alc260_capture_alt_mixer }, 4611 .init_verbs = { alc260_init_verbs }, 4612 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4613 .dac_nids = alc260_dac_nids, 4614 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), 4615 .adc_nids = alc260_hp_adc_nids, 4616 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4617 .channel_mode = alc260_modes, 4618 .input_mux = &alc260_capture_source, 4619 }, 4620 [ALC260_HP_3013] = { 4621 .mixers = { alc260_hp_3013_mixer, 4622 alc260_input_mixer, 4623 alc260_capture_alt_mixer }, 4624 .init_verbs = { alc260_hp_3013_init_verbs }, 4625 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4626 .dac_nids = alc260_dac_nids, 4627 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), 4628 .adc_nids = alc260_hp_adc_nids, 4629 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4630 .channel_mode = alc260_modes, 4631 .input_mux = &alc260_capture_source, 4632 }, 4633 [ALC260_FUJITSU_S702X] = { 4634 .mixers = { alc260_fujitsu_mixer, 4635 alc260_capture_mixer }, 4636 .init_verbs = { alc260_fujitsu_init_verbs }, 4637 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4638 .dac_nids = alc260_dac_nids, 4639 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), 4640 .adc_nids = alc260_dual_adc_nids, 4641 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4642 .channel_mode = alc260_modes, 4643 .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources), 4644 .input_mux = alc260_fujitsu_capture_sources, 4645 }, 4646 [ALC260_ACER] = { 4647 .mixers = { alc260_acer_mixer, 4648 alc260_capture_mixer }, 4649 .init_verbs = { alc260_acer_init_verbs }, 4650 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4651 .dac_nids = alc260_dac_nids, 4652 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), 4653 .adc_nids = alc260_dual_adc_nids, 4654 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4655 .channel_mode = alc260_modes, 4656 .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), 4657 .input_mux = alc260_acer_capture_sources, 4658 }, 4659 [ALC260_WILL] = { 4660 .mixers = { alc260_will_mixer, 4661 alc260_capture_mixer }, 4662 .init_verbs = { alc260_init_verbs, alc260_will_verbs }, 4663 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4664 .dac_nids = alc260_dac_nids, 4665 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), 4666 .adc_nids = alc260_adc_nids, 4667 .dig_out_nid = ALC260_DIGOUT_NID, 4668 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4669 .channel_mode = alc260_modes, 4670 .input_mux = &alc260_capture_source, 4671 }, 4672 [ALC260_REPLACER_672V] = { 4673 .mixers = { alc260_replacer_672v_mixer, 4674 alc260_capture_mixer }, 4675 .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, 4676 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 4677 .dac_nids = alc260_dac_nids, 4678 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), 4679 .adc_nids = alc260_adc_nids, 4680 .dig_out_nid = ALC260_DIGOUT_NID, 4681 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4682 .channel_mode = alc260_modes, 4683 .input_mux = &alc260_capture_source, 4684 .unsol_event = alc260_replacer_672v_unsol_event, 4685 .init_hook = alc260_replacer_672v_automute, 4686 }, 4687#ifdef CONFIG_SND_DEBUG 4688 [ALC260_TEST] = { 4689 .mixers = { alc260_test_mixer, 4690 alc260_capture_mixer }, 4691 .init_verbs = { alc260_test_init_verbs }, 4692 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), 4693 .dac_nids = alc260_test_dac_nids, 4694 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids), 4695 .adc_nids = alc260_test_adc_nids, 4696 .num_channel_mode = ARRAY_SIZE(alc260_modes), 4697 .channel_mode = alc260_modes, 4698 .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources), 4699 .input_mux = alc260_test_capture_sources, 4700 }, 4701#endif 4702}; 4703 4704static int patch_alc260(struct hda_codec *codec) 4705{ 4706 struct alc_spec *spec; 4707 int err, board_config; 4708 4709 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 4710 if (spec == NULL) 4711 return -ENOMEM; 4712 4713 codec->spec = spec; 4714 4715 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST, 4716 alc260_models, 4717 alc260_cfg_tbl); 4718 if (board_config < 0) { 4719 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, " 4720 "trying auto-probe from BIOS...\n"); 4721 board_config = ALC260_AUTO; 4722 } 4723 4724 if (board_config == ALC260_AUTO) { 4725 /* automatic parse from the BIOS config */ 4726 err = alc260_parse_auto_config(codec); 4727 if (err < 0) { 4728 alc_free(codec); 4729 return err; 4730 } else if (!err) { 4731 printk(KERN_INFO 4732 "hda_codec: Cannot set up configuration " 4733 "from BIOS. Using base mode...\n"); 4734 board_config = ALC260_BASIC; 4735 } 4736 } 4737 4738 if (board_config != ALC260_AUTO) 4739 setup_preset(spec, &alc260_presets[board_config]); 4740 4741 spec->stream_name_analog = "ALC260 Analog"; 4742 spec->stream_analog_playback = &alc260_pcm_analog_playback; 4743 spec->stream_analog_capture = &alc260_pcm_analog_capture; 4744 4745 spec->stream_name_digital = "ALC260 Digital"; 4746 spec->stream_digital_playback = &alc260_pcm_digital_playback; 4747 spec->stream_digital_capture = &alc260_pcm_digital_capture; 4748 4749 codec->patch_ops = alc_patch_ops; 4750 if (board_config == ALC260_AUTO) 4751 spec->init_hook = alc260_auto_init; 4752 4753 return 0; 4754} 4755 4756 4757/* 4758 * ALC882 support 4759 * 4760 * ALC882 is almost identical with ALC880 but has cleaner and more flexible 4761 * configuration. Each pin widget can choose any input DACs and a mixer. 4762 * Each ADC is connected from a mixer of all inputs. This makes possible 4763 * 6-channel independent captures. 4764 * 4765 * In addition, an independent DAC for the multi-playback (not used in this 4766 * driver yet). 4767 */ 4768#define ALC882_DIGOUT_NID 0x06 4769#define ALC882_DIGIN_NID 0x0a 4770 4771static struct hda_channel_mode alc882_ch_modes[1] = { 4772 { 8, NULL } 4773}; 4774 4775static hda_nid_t alc882_dac_nids[4] = { 4776 /* front, rear, clfe, rear_surr */ 4777 0x02, 0x03, 0x04, 0x05 4778}; 4779 4780/* identical with ALC880 */ 4781#define alc882_adc_nids alc880_adc_nids 4782#define alc882_adc_nids_alt alc880_adc_nids_alt 4783 4784/* input MUX */ 4785/* FIXME: should be a matrix-type input source selection */ 4786 4787static struct hda_input_mux alc882_capture_source = { 4788 .num_items = 4, 4789 .items = { 4790 { "Mic", 0x0 }, 4791 { "Front Mic", 0x1 }, 4792 { "Line", 0x2 }, 4793 { "CD", 0x4 }, 4794 }, 4795}; 4796#define alc882_mux_enum_info alc_mux_enum_info 4797#define alc882_mux_enum_get alc_mux_enum_get 4798 4799static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, 4800 struct snd_ctl_elem_value *ucontrol) 4801{ 4802 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 4803 struct alc_spec *spec = codec->spec; 4804 const struct hda_input_mux *imux = spec->input_mux; 4805 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 4806 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; 4807 hda_nid_t nid = capture_mixers[adc_idx]; 4808 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 4809 unsigned int i, idx; 4810 4811 idx = ucontrol->value.enumerated.item[0]; 4812 if (idx >= imux->num_items) 4813 idx = imux->num_items - 1; 4814 if (*cur_val == idx && !codec->in_resume) 4815 return 0; 4816 for (i = 0; i < imux->num_items; i++) { 4817 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 4818 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 4819 v | (imux->items[i].index << 8)); 4820 } 4821 *cur_val = idx; 4822 return 1; 4823} 4824 4825/* 4826 * 2ch mode 4827 */ 4828static struct hda_verb alc882_3ST_ch2_init[] = { 4829 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 4830 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 4831 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 4832 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 4833 { } /* end */ 4834}; 4835 4836/* 4837 * 6ch mode 4838 */ 4839static struct hda_verb alc882_3ST_ch6_init[] = { 4840 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4841 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 4842 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, 4843 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4844 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 4845 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, 4846 { } /* end */ 4847}; 4848 4849static struct hda_channel_mode alc882_3ST_6ch_modes[2] = { 4850 { 2, alc882_3ST_ch2_init }, 4851 { 6, alc882_3ST_ch6_init }, 4852}; 4853 4854/* 4855 * 6ch mode 4856 */ 4857static struct hda_verb alc882_sixstack_ch6_init[] = { 4858 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 4859 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4860 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4861 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4862 { } /* end */ 4863}; 4864 4865/* 4866 * 8ch mode 4867 */ 4868static struct hda_verb alc882_sixstack_ch8_init[] = { 4869 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4870 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4871 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4872 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 4873 { } /* end */ 4874}; 4875 4876static struct hda_channel_mode alc882_sixstack_modes[2] = { 4877 { 6, alc882_sixstack_ch6_init }, 4878 { 8, alc882_sixstack_ch8_init }, 4879}; 4880 4881/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 4882 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 4883 */ 4884static struct snd_kcontrol_new alc882_base_mixer[] = { 4885 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4886 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 4887 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 4888 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 4889 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 4890 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 4891 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 4892 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 4893 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 4894 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 4895 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 4896 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4897 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4898 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4899 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4900 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4901 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 4902 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4903 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 4904 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 4905 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 4906 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 4907 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 4908 { } /* end */ 4909}; 4910 4911static struct snd_kcontrol_new alc882_w2jc_mixer[] = { 4912 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4913 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 4914 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4915 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4916 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4917 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4918 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4919 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 4920 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4921 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 4922 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 4923 { } /* end */ 4924}; 4925 4926static struct snd_kcontrol_new alc882_targa_mixer[] = { 4927 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4928 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 4929 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 4930 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4931 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4932 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4933 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4934 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4935 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4936 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 4937 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 4938 { } /* end */ 4939}; 4940 4941/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ??? 4942 * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c 4943 */ 4944static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = { 4945 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 4946 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 4947 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 4948 HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT), 4949 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 4950 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 4951 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4952 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4953 HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT), 4954 HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT), 4955 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4956 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4957 { } /* end */ 4958}; 4959 4960static struct snd_kcontrol_new alc882_chmode_mixer[] = { 4961 { 4962 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4963 .name = "Channel Mode", 4964 .info = alc_ch_mode_info, 4965 .get = alc_ch_mode_get, 4966 .put = alc_ch_mode_put, 4967 }, 4968 { } /* end */ 4969}; 4970 4971static struct hda_verb alc882_init_verbs[] = { 4972 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 4973 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4974 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4975 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4976 /* Rear mixer */ 4977 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4978 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4979 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4980 /* CLFE mixer */ 4981 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4982 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4983 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4984 /* Side mixer */ 4985 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4986 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4987 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4988 4989 /* Front Pin: output 0 (0x0c) */ 4990 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4991 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4992 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 4993 /* Rear Pin: output 1 (0x0d) */ 4994 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4995 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4996 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 4997 /* CLFE Pin: output 2 (0x0e) */ 4998 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4999 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5000 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, 5001 /* Side Pin: output 3 (0x0f) */ 5002 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5003 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5004 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, 5005 /* Mic (rear) pin: input vref at 80% */ 5006 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5007 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5008 /* Front Mic pin: input vref at 80% */ 5009 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5010 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5011 /* Line In pin: input */ 5012 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 5013 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5014 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 5015 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5016 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5017 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 5018 /* CD pin widget for input */ 5019 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 5020 5021 /* FIXME: use matrix-type input source selection */ 5022 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 5023 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 5024 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5025 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5026 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5027 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5028 /* Input mixer2 */ 5029 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5030 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5031 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5032 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5033 /* Input mixer3 */ 5034 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5035 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5036 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5037 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5038 /* ADC1: mute amp left and right */ 5039 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5040 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 5041 /* ADC2: mute amp left and right */ 5042 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5043 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 5044 /* ADC3: mute amp left and right */ 5045 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5046 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 5047 5048 { } 5049}; 5050 5051static struct hda_verb alc882_eapd_verbs[] = { 5052 /* change to EAPD mode */ 5053 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 5054 {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, 5055 { } 5056}; 5057 5058/* Mac Pro test */ 5059static struct snd_kcontrol_new alc882_macpro_mixer[] = { 5060 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5061 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5062 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT), 5063 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), 5064 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), 5065 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT), 5066 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT), 5067 { } /* end */ 5068}; 5069 5070static struct hda_verb alc882_macpro_init_verbs[] = { 5071 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 5072 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5073 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5074 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5075 /* Front Pin: output 0 (0x0c) */ 5076 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5077 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5078 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 5079 /* Front Mic pin: input vref at 80% */ 5080 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5081 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5082 /* Speaker: output */ 5083 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5084 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5085 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04}, 5086 /* Headphone output (output 0 - 0x0c) */ 5087 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5088 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 5089 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, 5090 5091 /* FIXME: use matrix-type input source selection */ 5092 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 5093 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 5094 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5095 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5096 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5097 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5098 /* Input mixer2 */ 5099 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5100 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5101 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5102 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5103 /* Input mixer3 */ 5104 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5105 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5106 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5107 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5108 /* ADC1: mute amp left and right */ 5109 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5110 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 5111 /* ADC2: mute amp left and right */ 5112 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5113 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 5114 /* ADC3: mute amp left and right */ 5115 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5116 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 5117 5118 { } 5119}; 5120 5121static struct hda_verb alc882_targa_verbs[] = { 5122 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5123 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5124 5125 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5126 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5127 5128 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 5129 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ 5130 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 5131 5132 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 5133 {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 5134 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 5135 {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 5136 { } /* end */ 5137}; 5138 5139/* toggle speaker-output according to the hp-jack state */ 5140static void alc882_targa_automute(struct hda_codec *codec) 5141{ 5142 unsigned int present; 5143 5144 present = snd_hda_codec_read(codec, 0x14, 0, 5145 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 5146 snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, 5147 0x80, present ? 0x80 : 0); 5148 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, 5149 0x80, present ? 0x80 : 0); 5150 snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3); 5151} 5152 5153static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res) 5154{ 5155 /* Looks like the unsol event is incompatible with the standard 5156 * definition. 4bit tag is placed at 26 bit! 5157 */ 5158 if (((res >> 26) == ALC880_HP_EVENT)) { 5159 alc882_targa_automute(codec); 5160 } 5161} 5162 5163static struct hda_verb alc882_asus_a7j_verbs[] = { 5164 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5165 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5166 5167 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5168 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5169 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5170 5171 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ 5172 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 5173 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ 5174 5175 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 5176 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ 5177 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 5178 { } /* end */ 5179}; 5180 5181static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) 5182{ 5183 unsigned int gpiostate, gpiomask, gpiodir; 5184 5185 gpiostate = snd_hda_codec_read(codec, codec->afg, 0, 5186 AC_VERB_GET_GPIO_DATA, 0); 5187 5188 if (!muted) 5189 gpiostate |= (1 << pin); 5190 else 5191 gpiostate &= ~(1 << pin); 5192 5193 gpiomask = snd_hda_codec_read(codec, codec->afg, 0, 5194 AC_VERB_GET_GPIO_MASK, 0); 5195 gpiomask |= (1 << pin); 5196 5197 gpiodir = snd_hda_codec_read(codec, codec->afg, 0, 5198 AC_VERB_GET_GPIO_DIRECTION, 0); 5199 gpiodir |= (1 << pin); 5200 5201 5202 snd_hda_codec_write(codec, codec->afg, 0, 5203 AC_VERB_SET_GPIO_MASK, gpiomask); 5204 snd_hda_codec_write(codec, codec->afg, 0, 5205 AC_VERB_SET_GPIO_DIRECTION, gpiodir); 5206 5207 msleep(1); 5208 5209 snd_hda_codec_write(codec, codec->afg, 0, 5210 AC_VERB_SET_GPIO_DATA, gpiostate); 5211} 5212 5213/* 5214 * generic initialization of ADC, input mixers and output mixers 5215 */ 5216static struct hda_verb alc882_auto_init_verbs[] = { 5217 /* 5218 * Unmute ADC0-2 and set the default input to mic-in 5219 */ 5220 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 5221 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5222 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 5223 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5224 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 5225 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5226 5227 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 5228 * mixer widget 5229 * Note: PASD motherboards uses the Line In 2 as the input for 5230 * front panel mic (mic 2) 5231 */ 5232 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 5233 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5234 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5235 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 5236 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 5237 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 5238 5239 /* 5240 * Set up output mixers (0x0c - 0x0f) 5241 */ 5242 /* set vol=0 to output mixers */ 5243 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5244 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5245 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5246 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5247 /* set up input amps for analog loopback */ 5248 /* Amp Indices: DAC = 0, mixer = 1 */ 5249 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5250 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5251 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5252 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5253 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5254 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5255 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5256 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5257 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5258 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5259 5260 /* FIXME: use matrix-type input source selection */ 5261 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 5262 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 5263 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 5264 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 5265 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 5266 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 5267 /* Input mixer2 */ 5268 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 5269 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 5270 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 5271 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 5272 /* Input mixer3 */ 5273 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 5274 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 5275 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 5276 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 5277 5278 { } 5279}; 5280 5281/* capture mixer elements */ 5282static struct snd_kcontrol_new alc882_capture_alt_mixer[] = { 5283 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5284 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5285 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5286 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5287 { 5288 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5289 /* The multiple "Capture Source" controls confuse alsamixer 5290 * So call somewhat different.. 5291 * FIXME: the controls appear in the "playback" view! 5292 */ 5293 /* .name = "Capture Source", */ 5294 .name = "Input Source", 5295 .count = 2, 5296 .info = alc882_mux_enum_info, 5297 .get = alc882_mux_enum_get, 5298 .put = alc882_mux_enum_put, 5299 }, 5300 { } /* end */ 5301}; 5302 5303static struct snd_kcontrol_new alc882_capture_mixer[] = { 5304 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), 5305 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), 5306 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), 5307 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), 5308 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), 5309 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), 5310 { 5311 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5312 /* The multiple "Capture Source" controls confuse alsamixer 5313 * So call somewhat different.. 5314 * FIXME: the controls appear in the "playback" view! 5315 */ 5316 /* .name = "Capture Source", */ 5317 .name = "Input Source", 5318 .count = 3, 5319 .info = alc882_mux_enum_info, 5320 .get = alc882_mux_enum_get, 5321 .put = alc882_mux_enum_put, 5322 }, 5323 { } /* end */ 5324}; 5325 5326/* pcm configuration: identiacal with ALC880 */ 5327#define alc882_pcm_analog_playback alc880_pcm_analog_playback 5328#define alc882_pcm_analog_capture alc880_pcm_analog_capture 5329#define alc882_pcm_digital_playback alc880_pcm_digital_playback 5330#define alc882_pcm_digital_capture alc880_pcm_digital_capture 5331 5332/* 5333 * configuration and preset 5334 */ 5335static const char *alc882_models[ALC882_MODEL_LAST] = { 5336 [ALC882_3ST_DIG] = "3stack-dig", 5337 [ALC882_6ST_DIG] = "6stack-dig", 5338 [ALC882_ARIMA] = "arima", 5339 [ALC882_W2JC] = "w2jc", 5340 [ALC885_MACPRO] = "macpro", 5341 [ALC882_AUTO] = "auto", 5342}; 5343 5344static struct snd_pci_quirk alc882_cfg_tbl[] = { 5345 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG), 5346 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG), 5347 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), 5348 SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ 5349 SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), 5350 SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), 5351 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), 5352 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), 5353 {} 5354}; 5355 5356static struct alc_config_preset alc882_presets[] = { 5357 [ALC882_3ST_DIG] = { 5358 .mixers = { alc882_base_mixer }, 5359 .init_verbs = { alc882_init_verbs }, 5360 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5361 .dac_nids = alc882_dac_nids, 5362 .dig_out_nid = ALC882_DIGOUT_NID, 5363 .dig_in_nid = ALC882_DIGIN_NID, 5364 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), 5365 .channel_mode = alc882_ch_modes, 5366 .need_dac_fix = 1, 5367 .input_mux = &alc882_capture_source, 5368 }, 5369 [ALC882_6ST_DIG] = { 5370 .mixers = { alc882_base_mixer, alc882_chmode_mixer }, 5371 .init_verbs = { alc882_init_verbs }, 5372 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5373 .dac_nids = alc882_dac_nids, 5374 .dig_out_nid = ALC882_DIGOUT_NID, 5375 .dig_in_nid = ALC882_DIGIN_NID, 5376 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), 5377 .channel_mode = alc882_sixstack_modes, 5378 .input_mux = &alc882_capture_source, 5379 }, 5380 [ALC882_ARIMA] = { 5381 .mixers = { alc882_base_mixer, alc882_chmode_mixer }, 5382 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs }, 5383 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5384 .dac_nids = alc882_dac_nids, 5385 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), 5386 .channel_mode = alc882_sixstack_modes, 5387 .input_mux = &alc882_capture_source, 5388 }, 5389 [ALC882_W2JC] = { 5390 .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer }, 5391 .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, 5392 alc880_gpio1_init_verbs }, 5393 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5394 .dac_nids = alc882_dac_nids, 5395 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 5396 .channel_mode = alc880_threestack_modes, 5397 .need_dac_fix = 1, 5398 .input_mux = &alc882_capture_source, 5399 .dig_out_nid = ALC882_DIGOUT_NID, 5400 }, 5401 [ALC885_MACPRO] = { 5402 .mixers = { alc882_macpro_mixer }, 5403 .init_verbs = { alc882_macpro_init_verbs }, 5404 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5405 .dac_nids = alc882_dac_nids, 5406 .dig_out_nid = ALC882_DIGOUT_NID, 5407 .dig_in_nid = ALC882_DIGIN_NID, 5408 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), 5409 .channel_mode = alc882_ch_modes, 5410 .input_mux = &alc882_capture_source, 5411 }, 5412 [ALC882_TARGA] = { 5413 .mixers = { alc882_targa_mixer, alc882_chmode_mixer, 5414 alc882_capture_mixer }, 5415 .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, 5416 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5417 .dac_nids = alc882_dac_nids, 5418 .dig_out_nid = ALC882_DIGOUT_NID, 5419 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), 5420 .adc_nids = alc882_adc_nids, 5421 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), 5422 .channel_mode = alc882_3ST_6ch_modes, 5423 .need_dac_fix = 1, 5424 .input_mux = &alc882_capture_source, 5425 .unsol_event = alc882_targa_unsol_event, 5426 .init_hook = alc882_targa_automute, 5427 }, 5428 [ALC882_ASUS_A7J] = { 5429 .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer, 5430 alc882_capture_mixer }, 5431 .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs}, 5432 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 5433 .dac_nids = alc882_dac_nids, 5434 .dig_out_nid = ALC882_DIGOUT_NID, 5435 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), 5436 .adc_nids = alc882_adc_nids, 5437 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), 5438 .channel_mode = alc882_3ST_6ch_modes, 5439 .need_dac_fix = 1, 5440 .input_mux = &alc882_capture_source, 5441 }, 5442}; 5443 5444 5445/* 5446 * Pin config fixes 5447 */ 5448enum { 5449 PINFIX_ABIT_AW9D_MAX 5450}; 5451 5452static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { 5453 { 0x15, 0x01080104 }, /* side */ 5454 { 0x16, 0x01011012 }, /* rear */ 5455 { 0x17, 0x01016011 }, /* clfe */ 5456 { } 5457}; 5458 5459static const struct alc_pincfg *alc882_pin_fixes[] = { 5460 [PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix, 5461}; 5462 5463static struct snd_pci_quirk alc882_pinfix_tbl[] = { 5464 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), 5465 {} 5466}; 5467 5468/* 5469 * BIOS auto configuration 5470 */ 5471static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, 5472 hda_nid_t nid, int pin_type, 5473 int dac_idx) 5474{ 5475 /* set as output */ 5476 struct alc_spec *spec = codec->spec; 5477 int idx; 5478 5479 if (spec->multiout.dac_nids[dac_idx] == 0x25) 5480 idx = 4; 5481 else 5482 idx = spec->multiout.dac_nids[dac_idx] - 2; 5483 5484 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 5485 pin_type); 5486 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 5487 AMP_OUT_UNMUTE); 5488 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); 5489 5490} 5491 5492static void alc882_auto_init_multi_out(struct hda_codec *codec) 5493{ 5494 struct alc_spec *spec = codec->spec; 5495 int i; 5496 5497 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 5498 for (i = 0; i <= HDA_SIDE; i++) { 5499 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 5500 int pin_type = get_pin_type(spec->autocfg.line_out_type); 5501 if (nid) 5502 alc882_auto_set_output_and_unmute(codec, nid, pin_type, 5503 i); 5504 } 5505} 5506 5507static void alc882_auto_init_hp_out(struct hda_codec *codec) 5508{ 5509 struct alc_spec *spec = codec->spec; 5510 hda_nid_t pin; 5511 5512 pin = spec->autocfg.hp_pins[0]; 5513 if (pin) /* connect to front */ 5514 /* use dac 0 */ 5515 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 5516} 5517 5518#define alc882_is_input_pin(nid) alc880_is_input_pin(nid) 5519#define ALC882_PIN_CD_NID ALC880_PIN_CD_NID 5520 5521static void alc882_auto_init_analog_input(struct hda_codec *codec) 5522{ 5523 struct alc_spec *spec = codec->spec; 5524 int i; 5525 5526 for (i = 0; i < AUTO_PIN_LAST; i++) { 5527 hda_nid_t nid = spec->autocfg.input_pins[i]; 5528 if (alc882_is_input_pin(nid)) { 5529 snd_hda_codec_write(codec, nid, 0, 5530 AC_VERB_SET_PIN_WIDGET_CONTROL, 5531 i <= AUTO_PIN_FRONT_MIC ? 5532 PIN_VREF80 : PIN_IN); 5533 if (nid != ALC882_PIN_CD_NID) 5534 snd_hda_codec_write(codec, nid, 0, 5535 AC_VERB_SET_AMP_GAIN_MUTE, 5536 AMP_OUT_MUTE); 5537 } 5538 } 5539} 5540 5541/* almost identical with ALC880 parser... */ 5542static int alc882_parse_auto_config(struct hda_codec *codec) 5543{ 5544 struct alc_spec *spec = codec->spec; 5545 int err = alc880_parse_auto_config(codec); 5546 5547 if (err < 0) 5548 return err; 5549 else if (err > 0) 5550 /* hack - override the init verbs */ 5551 spec->init_verbs[0] = alc882_auto_init_verbs; 5552 return err; 5553} 5554 5555/* additional initialization for auto-configuration model */ 5556static void alc882_auto_init(struct hda_codec *codec) 5557{ 5558 alc882_auto_init_multi_out(codec); 5559 alc882_auto_init_hp_out(codec); 5560 alc882_auto_init_analog_input(codec); 5561} 5562 5563static int patch_alc882(struct hda_codec *codec) 5564{ 5565 struct alc_spec *spec; 5566 int err, board_config; 5567 5568 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 5569 if (spec == NULL) 5570 return -ENOMEM; 5571 5572 codec->spec = spec; 5573 5574 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST, 5575 alc882_models, 5576 alc882_cfg_tbl); 5577 5578 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) { 5579 /* Pick up systems that don't supply PCI SSID */ 5580 switch (codec->subsystem_id) { 5581 case 0x106b0c00: /* Mac Pro */ 5582 board_config = ALC885_MACPRO; 5583 break; 5584 default: 5585 printk(KERN_INFO "hda_codec: Unknown model for ALC882, " 5586 "trying auto-probe from BIOS...\n"); 5587 board_config = ALC882_AUTO; 5588 } 5589 } 5590 5591 alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes); 5592 5593 if (board_config == ALC882_AUTO) { 5594 /* automatic parse from the BIOS config */ 5595 err = alc882_parse_auto_config(codec); 5596 if (err < 0) { 5597 alc_free(codec); 5598 return err; 5599 } else if (!err) { 5600 printk(KERN_INFO 5601 "hda_codec: Cannot set up configuration " 5602 "from BIOS. Using base mode...\n"); 5603 board_config = ALC882_3ST_DIG; 5604 } 5605 } 5606 5607 if (board_config != ALC882_AUTO) 5608 setup_preset(spec, &alc882_presets[board_config]); 5609 5610 if (board_config == ALC885_MACPRO) { 5611 alc882_gpio_mute(codec, 0, 0); 5612 alc882_gpio_mute(codec, 1, 0); 5613 } 5614 5615 spec->stream_name_analog = "ALC882 Analog"; 5616 spec->stream_analog_playback = &alc882_pcm_analog_playback; 5617 spec->stream_analog_capture = &alc882_pcm_analog_capture; 5618 5619 spec->stream_name_digital = "ALC882 Digital"; 5620 spec->stream_digital_playback = &alc882_pcm_digital_playback; 5621 spec->stream_digital_capture = &alc882_pcm_digital_capture; 5622 5623 if (!spec->adc_nids && spec->input_mux) { 5624 /* check whether NID 0x07 is valid */ 5625 unsigned int wcap = get_wcaps(codec, 0x07); 5626 /* get type */ 5627 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 5628 if (wcap != AC_WID_AUD_IN) { 5629 spec->adc_nids = alc882_adc_nids_alt; 5630 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); 5631 spec->mixers[spec->num_mixers] = 5632 alc882_capture_alt_mixer; 5633 spec->num_mixers++; 5634 } else { 5635 spec->adc_nids = alc882_adc_nids; 5636 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); 5637 spec->mixers[spec->num_mixers] = alc882_capture_mixer; 5638 spec->num_mixers++; 5639 } 5640 } 5641 5642 codec->patch_ops = alc_patch_ops; 5643 if (board_config == ALC882_AUTO) 5644 spec->init_hook = alc882_auto_init; 5645 5646 return 0; 5647} 5648 5649/* 5650 * ALC883 support 5651 * 5652 * ALC883 is almost identical with ALC880 but has cleaner and more flexible 5653 * configuration. Each pin widget can choose any input DACs and a mixer. 5654 * Each ADC is connected from a mixer of all inputs. This makes possible 5655 * 6-channel independent captures. 5656 * 5657 * In addition, an independent DAC for the multi-playback (not used in this 5658 * driver yet). 5659 */ 5660#define ALC883_DIGOUT_NID 0x06 5661#define ALC883_DIGIN_NID 0x0a 5662 5663static hda_nid_t alc883_dac_nids[4] = { 5664 /* front, rear, clfe, rear_surr */ 5665 0x02, 0x04, 0x03, 0x05 5666}; 5667 5668static hda_nid_t alc883_adc_nids[2] = { 5669 /* ADC1-2 */ 5670 0x08, 0x09, 5671}; 5672 5673/* input MUX */ 5674/* FIXME: should be a matrix-type input source selection */ 5675 5676static struct hda_input_mux alc883_capture_source = { 5677 .num_items = 4, 5678 .items = { 5679 { "Mic", 0x0 }, 5680 { "Front Mic", 0x1 }, 5681 { "Line", 0x2 }, 5682 { "CD", 0x4 }, 5683 }, 5684}; 5685 5686static struct hda_input_mux alc883_lenovo_101e_capture_source = { 5687 .num_items = 2, 5688 .items = { 5689 { "Mic", 0x1 }, 5690 { "Line", 0x2 }, 5691 }, 5692}; 5693 5694static struct hda_input_mux alc883_lenovo_nb0763_capture_source = { 5695 .num_items = 4, 5696 .items = { 5697 { "Mic", 0x0 }, 5698 { "iMic", 0x1 }, 5699 { "Line", 0x2 }, 5700 { "CD", 0x4 }, 5701 }, 5702}; 5703 5704#define alc883_mux_enum_info alc_mux_enum_info 5705#define alc883_mux_enum_get alc_mux_enum_get 5706 5707static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, 5708 struct snd_ctl_elem_value *ucontrol) 5709{ 5710 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 5711 struct alc_spec *spec = codec->spec; 5712 const struct hda_input_mux *imux = spec->input_mux; 5713 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 5714 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; 5715 hda_nid_t nid = capture_mixers[adc_idx]; 5716 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 5717 unsigned int i, idx; 5718 5719 idx = ucontrol->value.enumerated.item[0]; 5720 if (idx >= imux->num_items) 5721 idx = imux->num_items - 1; 5722 if (*cur_val == idx && !codec->in_resume) 5723 return 0; 5724 for (i = 0; i < imux->num_items; i++) { 5725 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 5726 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 5727 v | (imux->items[i].index << 8)); 5728 } 5729 *cur_val = idx; 5730 return 1; 5731} 5732 5733/* 5734 * 2ch mode 5735 */ 5736static struct hda_channel_mode alc883_3ST_2ch_modes[1] = { 5737 { 2, NULL } 5738}; 5739 5740/* 5741 * 2ch mode 5742 */ 5743static struct hda_verb alc883_3ST_ch2_init[] = { 5744 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 5745 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 5746 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 5747 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 5748 { } /* end */ 5749}; 5750 5751/* 5752 * 6ch mode 5753 */ 5754static struct hda_verb alc883_3ST_ch6_init[] = { 5755 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5756 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 5757 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, 5758 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5759 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 5760 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, 5761 { } /* end */ 5762}; 5763 5764static struct hda_channel_mode alc883_3ST_6ch_modes[2] = { 5765 { 2, alc883_3ST_ch2_init }, 5766 { 6, alc883_3ST_ch6_init }, 5767}; 5768 5769/* 5770 * 6ch mode 5771 */ 5772static struct hda_verb alc883_sixstack_ch6_init[] = { 5773 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 5774 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5775 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5776 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5777 { } /* end */ 5778}; 5779 5780/* 5781 * 8ch mode 5782 */ 5783static struct hda_verb alc883_sixstack_ch8_init[] = { 5784 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5785 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5786 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5787 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 5788 { } /* end */ 5789}; 5790 5791static struct hda_channel_mode alc883_sixstack_modes[2] = { 5792 { 6, alc883_sixstack_ch6_init }, 5793 { 8, alc883_sixstack_ch8_init }, 5794}; 5795 5796static struct hda_verb alc883_medion_eapd_verbs[] = { 5797 /* eanable EAPD on medion laptop */ 5798 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 5799 {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, 5800 { } 5801}; 5802 5803/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 5804 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 5805 */ 5806 5807static struct snd_kcontrol_new alc883_base_mixer[] = { 5808 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5809 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5810 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 5811 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 5812 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 5813 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 5814 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 5815 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 5816 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 5817 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 5818 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5819 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5820 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5821 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5822 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5823 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5824 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5825 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5826 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5827 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 5828 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5829 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5830 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5831 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5832 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5833 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5834 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5835 { 5836 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5837 /* .name = "Capture Source", */ 5838 .name = "Input Source", 5839 .count = 2, 5840 .info = alc883_mux_enum_info, 5841 .get = alc883_mux_enum_get, 5842 .put = alc883_mux_enum_put, 5843 }, 5844 { } /* end */ 5845}; 5846 5847static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { 5848 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5849 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5850 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5851 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5852 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5853 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5854 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5855 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5856 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5857 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5858 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5859 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 5860 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5861 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5862 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5863 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5864 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5865 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5866 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5867 { 5868 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5869 /* .name = "Capture Source", */ 5870 .name = "Input Source", 5871 .count = 2, 5872 .info = alc883_mux_enum_info, 5873 .get = alc883_mux_enum_get, 5874 .put = alc883_mux_enum_put, 5875 }, 5876 { } /* end */ 5877}; 5878 5879static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { 5880 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5881 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 5882 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 5883 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 5884 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 5885 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 5886 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 5887 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 5888 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5889 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5890 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5891 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5892 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5893 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5894 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5895 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5896 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5897 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 5898 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5899 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5900 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5901 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5902 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5903 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5904 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5905 { 5906 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5907 /* .name = "Capture Source", */ 5908 .name = "Input Source", 5909 .count = 2, 5910 .info = alc883_mux_enum_info, 5911 .get = alc883_mux_enum_get, 5912 .put = alc883_mux_enum_put, 5913 }, 5914 { } /* end */ 5915}; 5916 5917static struct snd_kcontrol_new alc883_fivestack_mixer[] = { 5918 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5919 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 5920 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 5921 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), 5922 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 5923 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 5924 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), 5925 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 5926 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5927 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5928 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5929 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5930 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5931 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5932 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5933 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5934 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5935 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 5936 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5937 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5938 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5939 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5940 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5941 5942 { 5943 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5944 /* .name = "Capture Source", */ 5945 .name = "Input Source", 5946 .count = 1, 5947 .info = alc883_mux_enum_info, 5948 .get = alc883_mux_enum_get, 5949 .put = alc883_mux_enum_put, 5950 }, 5951 { } /* end */ 5952}; 5953 5954static struct snd_kcontrol_new alc883_tagra_mixer[] = { 5955 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5956 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 5957 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5958 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 5959 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 5960 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 5961 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 5962 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 5963 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 5964 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5965 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5966 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5967 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5968 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5969 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5970 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5971 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5972 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5973 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5974 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 5975 { 5976 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5977 /* .name = "Capture Source", */ 5978 .name = "Input Source", 5979 .count = 2, 5980 .info = alc883_mux_enum_info, 5981 .get = alc883_mux_enum_get, 5982 .put = alc883_mux_enum_put, 5983 }, 5984 { } /* end */ 5985}; 5986 5987static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { 5988 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5989 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 5990 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 5991 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 5992 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 5993 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5994 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 5995 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5996 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 5997 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 5998 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 5999 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6000 { 6001 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6002 /* .name = "Capture Source", */ 6003 .name = "Input Source", 6004 .count = 2, 6005 .info = alc883_mux_enum_info, 6006 .get = alc883_mux_enum_get, 6007 .put = alc883_mux_enum_put, 6008 }, 6009 { } /* end */ 6010}; 6011 6012static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = { 6013 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6014 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 6015 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 6016 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), 6017 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6018 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6019 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6020 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6021 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6022 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6023 { 6024 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6025 /* .name = "Capture Source", */ 6026 .name = "Input Source", 6027 .count = 1, 6028 .info = alc883_mux_enum_info, 6029 .get = alc883_mux_enum_get, 6030 .put = alc883_mux_enum_put, 6031 }, 6032 { } /* end */ 6033}; 6034 6035static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = { 6036 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6037 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT), 6038 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6039 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6040 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6041 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6042 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6043 HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6044 HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6045 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6046 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6047 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6048 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6049 { 6050 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6051 /* .name = "Capture Source", */ 6052 .name = "Input Source", 6053 .count = 2, 6054 .info = alc883_mux_enum_info, 6055 .get = alc883_mux_enum_get, 6056 .put = alc883_mux_enum_put, 6057 }, 6058 { } /* end */ 6059}; 6060 6061static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { 6062 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6063 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6064 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), 6065 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6066 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6067 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6068 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6069 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6070 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6071 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6072 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6073 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6074 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6075 { 6076 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6077 /* .name = "Capture Source", */ 6078 .name = "Input Source", 6079 .count = 2, 6080 .info = alc883_mux_enum_info, 6081 .get = alc883_mux_enum_get, 6082 .put = alc883_mux_enum_put, 6083 }, 6084 { } /* end */ 6085}; 6086 6087static struct snd_kcontrol_new alc888_hp_nettle_mixer[] = { 6088 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6089 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 6090 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT), 6091 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT), 6092 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), 6093 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), 6094 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), 6095 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), 6096 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 6097 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 6098 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6099 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6100 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6101 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6102 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6103 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6104 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6105 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6106 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6107 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 6108 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6109 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 6110 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 6111 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6112 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6113 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6114 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6115 { 6116 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6117 /* .name = "Capture Source", */ 6118 .name = "Input Source", 6119 .count = 2, 6120 .info = alc883_mux_enum_info, 6121 .get = alc883_mux_enum_get, 6122 .put = alc883_mux_enum_put, 6123 }, 6124 { } /* end */ 6125}; 6126 6127static struct snd_kcontrol_new alc888_hp_lucknow_mixer[] = { 6128 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6129 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 6130 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT), 6131 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT), 6132 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), 6133 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), 6134 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), 6135 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), 6136 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 6137 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6138 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6139 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 6140 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 6141 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 6142 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 6143 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 6144 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 6145 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 6146 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 6147 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 6148 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 6149 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6150 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6151 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6152 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6153 { 6154 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6155 /* .name = "Capture Source", */ 6156 .name = "Input Source", 6157 .count = 2, 6158 .info = alc883_mux_enum_info, 6159 .get = alc883_mux_enum_get, 6160 .put = alc883_mux_enum_put, 6161 }, 6162 { } /* end */ 6163}; 6164 6165static struct snd_kcontrol_new alc883_chmode_mixer[] = { 6166 { 6167 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6168 .name = "Channel Mode", 6169 .info = alc_ch_mode_info, 6170 .get = alc_ch_mode_get, 6171 .put = alc_ch_mode_put, 6172 }, 6173 { } /* end */ 6174}; 6175 6176static struct hda_verb alc883_init_verbs[] = { 6177 /* ADC1: mute amp left and right */ 6178 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6179 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 6180 /* ADC2: mute amp left and right */ 6181 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6182 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 6183 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 6184 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6185 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6186 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6187 /* Rear mixer */ 6188 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6189 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6190 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6191 /* CLFE mixer */ 6192 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6193 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6194 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6195 /* Side mixer */ 6196 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6197 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 6198 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 6199 6200 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6201 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6202 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6203 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 6204 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6205 6206 /* Front Pin: output 0 (0x0c) */ 6207 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6208 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6209 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 6210 /* Rear Pin: output 1 (0x0d) */ 6211 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6212 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6213 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 6214 /* CLFE Pin: output 2 (0x0e) */ 6215 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6216 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6217 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, 6218 /* Side Pin: output 3 (0x0f) */ 6219 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6220 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6221 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, 6222 /* Mic (rear) pin: input vref at 80% */ 6223 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 6224 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 6225 /* Front Mic pin: input vref at 80% */ 6226 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 6227 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 6228 /* Line In pin: input */ 6229 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 6230 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 6231 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 6232 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6233 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 6234 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 6235 /* CD pin widget for input */ 6236 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 6237 6238 /* FIXME: use matrix-type input source selection */ 6239 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 6240 /* Input mixer2 */ 6241 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6242 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6243 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6244 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6245 /* Input mixer3 */ 6246 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6247 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6248 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6249 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6250 { } 6251}; 6252 6253static struct hda_verb alc883_tagra_verbs[] = { 6254 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6255 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6256 6257 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6258 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 6259 6260 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 6261 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ 6262 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 6263 6264 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6265 {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 6266 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 6267 {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 6268 6269 { } /* end */ 6270}; 6271 6272static struct hda_verb alc883_lenovo_101e_verbs[] = { 6273 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 6274 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN}, 6275 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN}, 6276 { } /* end */ 6277}; 6278 6279static struct hda_verb alc883_lenovo_nb0763_verbs[] = { 6280 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 6281 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6282 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6283 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6284 { } /* end */ 6285}; 6286 6287static struct hda_verb alc888_lenovo_ms7195_verbs[] = { 6288 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6289 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6290 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 6291 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN}, 6292 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6293 { } /* end */ 6294}; 6295 6296static struct hda_verb alc888_hp_nettle_verbs[] = { 6297 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ 6298 {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */ 6299 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* CLFE : output 1 (0x0d) */ 6300 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, /* Side : output 3 (0x0f) */ 6301 { } 6302}; 6303 6304static struct hda_verb alc888_hp_lucknow_verbs[] = { 6305 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ 6306 {0x18, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */ 6307 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */ 6308 { } 6309}; 6310 6311static struct hda_verb alc888_hp_lucknow_2ch_init[] = { 6312 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 6313 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 6314 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 6315 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 6316 { } 6317}; 6318 6319static struct hda_verb alc888_hp_lucknow_6ch_init[] = { 6320 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 6321 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 6322 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 6323 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 6324 { } 6325}; 6326 6327static struct hda_channel_mode alc888_hp_lucknow_modes[2] = { 6328 { 2, alc888_hp_lucknow_2ch_init }, 6329 { 6, alc888_hp_lucknow_6ch_init }, 6330}; 6331 6332/* toggle front-jack and RCA according to the hp-jack state */ 6333static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec) 6334{ 6335 unsigned int present; 6336 6337 present = snd_hda_codec_read(codec, 0x1b, 0, 6338 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6339 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 6340 0x80, present ? 0x80 : 0); 6341 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 6342 0x80, present ? 0x80 : 0); 6343 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 6344 0x80, present ? 0x80 : 0); 6345 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 6346 0x80, present ? 0x80 : 0); 6347 6348} 6349 6350/* toggle RCA according to the front-jack state */ 6351static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec) 6352{ 6353 unsigned int present; 6354 6355 present = snd_hda_codec_read(codec, 0x14, 0, 6356 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6357 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 6358 0x80, present ? 0x80 : 0); 6359 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 6360 0x80, present ? 0x80 : 0); 6361 6362} 6363static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec, 6364 unsigned int res) 6365{ 6366 if ((res >> 26) == ALC880_HP_EVENT) 6367 alc888_lenovo_ms7195_front_automute(codec); 6368 if ((res >> 26) == ALC880_FRONT_EVENT) 6369 alc888_lenovo_ms7195_rca_automute(codec); 6370} 6371 6372static struct hda_verb alc883_medion_md2_verbs[] = { 6373 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6374 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6375 6376 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 6377 6378 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 6379 { } /* end */ 6380}; 6381 6382/* toggle speaker-output according to the hp-jack state */ 6383static void alc883_medion_md2_automute(struct hda_codec *codec) 6384{ 6385 unsigned int present; 6386 6387 present = snd_hda_codec_read(codec, 0x14, 0, 6388 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6389 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 6390 0x80, present ? 0x80 : 0); 6391 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 6392 0x80, present ? 0x80 : 0); 6393} 6394 6395static void alc883_medion_md2_unsol_event(struct hda_codec *codec, 6396 unsigned int res) 6397{ 6398 if ((res >> 26) == ALC880_HP_EVENT) 6399 alc883_medion_md2_automute(codec); 6400} 6401 6402/* toggle speaker-output according to the hp-jack state */ 6403static void alc883_tagra_automute(struct hda_codec *codec) 6404{ 6405 unsigned int present; 6406 unsigned char bits; 6407 6408 present = snd_hda_codec_read(codec, 0x14, 0, 6409 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6410 bits = present ? 0x80 : 0; 6411 snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, 6412 0x80, bits); 6413 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, 6414 0x80, bits); 6415 snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, 6416 present ? 1 : 3); 6417} 6418 6419static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) 6420{ 6421 if ((res >> 26) == ALC880_HP_EVENT) 6422 alc883_tagra_automute(codec); 6423} 6424 6425static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) 6426{ 6427 unsigned int present; 6428 unsigned char bits; 6429 6430 present = snd_hda_codec_read(codec, 0x14, 0, 6431 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6432 bits = present ? 0x80 : 0; 6433 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 6434 0x80, bits); 6435 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 6436 0x80, bits); 6437} 6438 6439static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) 6440{ 6441 unsigned int present; 6442 unsigned char bits; 6443 6444 present = snd_hda_codec_read(codec, 0x1b, 0, 6445 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 6446 bits = present ? 0x80 : 0; 6447 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 6448 0x80, bits); 6449 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 6450 0x80, bits); 6451 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 6452 0x80, bits); 6453 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 6454 0x80, bits); 6455} 6456 6457static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, 6458 unsigned int res) 6459{ 6460 if ((res >> 26) == ALC880_HP_EVENT) 6461 alc883_lenovo_101e_all_automute(codec); 6462 if ((res >> 26) == ALC880_FRONT_EVENT) 6463 alc883_lenovo_101e_ispeaker_automute(codec); 6464} 6465 6466/* 6467 * generic initialization of ADC, input mixers and output mixers 6468 */ 6469static struct hda_verb alc883_auto_init_verbs[] = { 6470 /* 6471 * Unmute ADC0-2 and set the default input to mic-in 6472 */ 6473 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 6474 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6475 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 6476 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6477 6478 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 6479 * mixer widget 6480 * Note: PASD motherboards uses the Line In 2 as the input for 6481 * front panel mic (mic 2) 6482 */ 6483 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 6484 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6485 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6486 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6487 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 6488 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6489 6490 /* 6491 * Set up output mixers (0x0c - 0x0f) 6492 */ 6493 /* set vol=0 to output mixers */ 6494 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6495 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6496 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6497 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 6498 /* set up input amps for analog loopback */ 6499 /* Amp Indices: DAC = 0, mixer = 1 */ 6500 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6501 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6502 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6503 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6504 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6505 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6506 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6507 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6508 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6509 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6510 6511 /* FIXME: use matrix-type input source selection */ 6512 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 6513 /* Input mixer1 */ 6514 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6515 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6516 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6517 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ 6518 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6519 /* Input mixer2 */ 6520 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 6521 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 6522 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 6523 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ 6524 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 6525 6526 { } 6527}; 6528 6529/* capture mixer elements */ 6530static struct snd_kcontrol_new alc883_capture_mixer[] = { 6531 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 6532 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 6533 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 6534 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 6535 { 6536 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6537 /* The multiple "Capture Source" controls confuse alsamixer 6538 * So call somewhat different.. 6539 * FIXME: the controls appear in the "playback" view! 6540 */ 6541 /* .name = "Capture Source", */ 6542 .name = "Input Source", 6543 .count = 2, 6544 .info = alc882_mux_enum_info, 6545 .get = alc882_mux_enum_get, 6546 .put = alc882_mux_enum_put, 6547 }, 6548 { } /* end */ 6549}; 6550 6551/* pcm configuration: identiacal with ALC880 */ 6552#define alc883_pcm_analog_playback alc880_pcm_analog_playback 6553#define alc883_pcm_analog_capture alc880_pcm_analog_capture 6554#define alc883_pcm_digital_playback alc880_pcm_digital_playback 6555#define alc883_pcm_digital_capture alc880_pcm_digital_capture 6556 6557/* 6558 * configuration and preset 6559 */ 6560static const char *alc883_models[ALC883_MODEL_LAST] = { 6561 [ALC883_3ST_2ch_DIG] = "3stack-dig", 6562 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig", 6563 [ALC883_3ST_6ch] = "3stack-6ch", 6564 [ALC883_6ST_DIG] = "6stack-dig", 6565 [ALC883_TARGA_DIG] = "targa-dig", 6566 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", 6567 [ALC883_ACER] = "acer", 6568 [ALC883_MEDION] = "medion", 6569 [ALC883_MEDION_MD2] = "medion-md2", 6570 [ALC883_LAPTOP_EAPD] = "laptop-eapd", 6571 [ALC883_LENOVO_101E_2ch] = "lenovo-101e", 6572 [ALC883_LENOVO_NB0763] = "lenovo-nb0763", 6573 [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", 6574 [ALC888_HP_NETTLE] = "hp-nettle", 6575 [ALC888_HP_LUCKNOW] = "hp-lucknow", 6576 [ALC883_AUTO] = "auto", 6577}; 6578 6579static struct snd_pci_quirk alc883_cfg_tbl[] = { 6580 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), 6581 SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), 6582 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), 6583 SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), 6584 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), 6585 SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG), 6586 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG), 6587 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), 6588 SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG), 6589 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), 6590 SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), 6591 SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG), 6592 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG), 6593 SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG), 6594 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG), 6595 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG), 6596 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG), 6597 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG), 6598 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG), 6599 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG), 6600 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG), 6601 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG), 6602 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), 6603 SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), 6604 SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), 6605 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), 6606 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), 6607 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), 6608 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch), 6609 SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763), 6610 SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763), 6611 SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_HP_NETTLE), 6612 SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_HP_LUCKNOW), 6613 SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_HP_LUCKNOW), 6614 SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), 6615 {} 6616}; 6617 6618static struct alc_config_preset alc883_presets[] = { 6619 [ALC883_3ST_2ch_DIG] = { 6620 .mixers = { alc883_3ST_2ch_mixer }, 6621 .init_verbs = { alc883_init_verbs }, 6622 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6623 .dac_nids = alc883_dac_nids, 6624 .dig_out_nid = ALC883_DIGOUT_NID, 6625 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6626 .adc_nids = alc883_adc_nids, 6627 .dig_in_nid = ALC883_DIGIN_NID, 6628 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6629 .channel_mode = alc883_3ST_2ch_modes, 6630 .input_mux = &alc883_capture_source, 6631 }, 6632 [ALC883_3ST_6ch_DIG] = { 6633 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, 6634 .init_verbs = { alc883_init_verbs }, 6635 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6636 .dac_nids = alc883_dac_nids, 6637 .dig_out_nid = ALC883_DIGOUT_NID, 6638 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6639 .adc_nids = alc883_adc_nids, 6640 .dig_in_nid = ALC883_DIGIN_NID, 6641 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6642 .channel_mode = alc883_3ST_6ch_modes, 6643 .need_dac_fix = 1, 6644 .input_mux = &alc883_capture_source, 6645 }, 6646 [ALC883_3ST_6ch] = { 6647 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, 6648 .init_verbs = { alc883_init_verbs }, 6649 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6650 .dac_nids = alc883_dac_nids, 6651 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6652 .adc_nids = alc883_adc_nids, 6653 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6654 .channel_mode = alc883_3ST_6ch_modes, 6655 .need_dac_fix = 1, 6656 .input_mux = &alc883_capture_source, 6657 }, 6658 [ALC883_6ST_DIG] = { 6659 .mixers = { alc883_base_mixer, alc883_chmode_mixer }, 6660 .init_verbs = { alc883_init_verbs }, 6661 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6662 .dac_nids = alc883_dac_nids, 6663 .dig_out_nid = ALC883_DIGOUT_NID, 6664 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6665 .adc_nids = alc883_adc_nids, 6666 .dig_in_nid = ALC883_DIGIN_NID, 6667 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), 6668 .channel_mode = alc883_sixstack_modes, 6669 .input_mux = &alc883_capture_source, 6670 }, 6671 [ALC883_TARGA_DIG] = { 6672 .mixers = { alc883_tagra_mixer, alc883_chmode_mixer }, 6673 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, 6674 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6675 .dac_nids = alc883_dac_nids, 6676 .dig_out_nid = ALC883_DIGOUT_NID, 6677 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6678 .adc_nids = alc883_adc_nids, 6679 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6680 .channel_mode = alc883_3ST_6ch_modes, 6681 .need_dac_fix = 1, 6682 .input_mux = &alc883_capture_source, 6683 .unsol_event = alc883_tagra_unsol_event, 6684 .init_hook = alc883_tagra_automute, 6685 }, 6686 [ALC883_TARGA_2ch_DIG] = { 6687 .mixers = { alc883_tagra_2ch_mixer}, 6688 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, 6689 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6690 .dac_nids = alc883_dac_nids, 6691 .dig_out_nid = ALC883_DIGOUT_NID, 6692 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6693 .adc_nids = alc883_adc_nids, 6694 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6695 .channel_mode = alc883_3ST_2ch_modes, 6696 .input_mux = &alc883_capture_source, 6697 .unsol_event = alc883_tagra_unsol_event, 6698 .init_hook = alc883_tagra_automute, 6699 }, 6700 [ALC883_ACER] = { 6701 .mixers = { alc883_base_mixer, 6702 alc883_chmode_mixer }, 6703 /* On TravelMate laptops, GPIO 0 enables the internal speaker 6704 * and the headphone jack. Turn this on and rely on the 6705 * standard mute methods whenever the user wants to turn 6706 * these outputs off. 6707 */ 6708 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs }, 6709 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6710 .dac_nids = alc883_dac_nids, 6711 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6712 .adc_nids = alc883_adc_nids, 6713 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6714 .channel_mode = alc883_3ST_2ch_modes, 6715 .input_mux = &alc883_capture_source, 6716 }, 6717 [ALC883_MEDION] = { 6718 .mixers = { alc883_fivestack_mixer, 6719 alc883_chmode_mixer }, 6720 .init_verbs = { alc883_init_verbs, 6721 alc883_medion_eapd_verbs }, 6722 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6723 .dac_nids = alc883_dac_nids, 6724 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6725 .adc_nids = alc883_adc_nids, 6726 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), 6727 .channel_mode = alc883_sixstack_modes, 6728 .input_mux = &alc883_capture_source, 6729 }, 6730 [ALC883_MEDION_MD2] = { 6731 .mixers = { alc883_medion_md2_mixer}, 6732 .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs}, 6733 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6734 .dac_nids = alc883_dac_nids, 6735 .dig_out_nid = ALC883_DIGOUT_NID, 6736 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6737 .adc_nids = alc883_adc_nids, 6738 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6739 .channel_mode = alc883_3ST_2ch_modes, 6740 .input_mux = &alc883_capture_source, 6741 .unsol_event = alc883_medion_md2_unsol_event, 6742 .init_hook = alc883_medion_md2_automute, 6743 }, 6744 [ALC883_LAPTOP_EAPD] = { 6745 .mixers = { alc883_base_mixer, 6746 alc883_chmode_mixer }, 6747 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, 6748 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6749 .dac_nids = alc883_dac_nids, 6750 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6751 .adc_nids = alc883_adc_nids, 6752 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6753 .channel_mode = alc883_3ST_2ch_modes, 6754 .input_mux = &alc883_capture_source, 6755 }, 6756 [ALC883_LENOVO_101E_2ch] = { 6757 .mixers = { alc883_lenovo_101e_2ch_mixer}, 6758 .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs}, 6759 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6760 .dac_nids = alc883_dac_nids, 6761 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6762 .adc_nids = alc883_adc_nids, 6763 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6764 .channel_mode = alc883_3ST_2ch_modes, 6765 .input_mux = &alc883_lenovo_101e_capture_source, 6766 .unsol_event = alc883_lenovo_101e_unsol_event, 6767 .init_hook = alc883_lenovo_101e_all_automute, 6768 }, 6769 [ALC883_LENOVO_NB0763] = { 6770 .mixers = { alc883_lenovo_nb0763_mixer }, 6771 .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs}, 6772 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6773 .dac_nids = alc883_dac_nids, 6774 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6775 .adc_nids = alc883_adc_nids, 6776 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 6777 .channel_mode = alc883_3ST_2ch_modes, 6778 .need_dac_fix = 1, 6779 .input_mux = &alc883_lenovo_nb0763_capture_source, 6780 .unsol_event = alc883_medion_md2_unsol_event, 6781 .init_hook = alc883_medion_md2_automute, 6782 }, 6783 [ALC888_LENOVO_MS7195_DIG] = { 6784 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, 6785 .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs}, 6786 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6787 .dac_nids = alc883_dac_nids, 6788 .dig_out_nid = ALC883_DIGOUT_NID, 6789 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6790 .adc_nids = alc883_adc_nids, 6791 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), 6792 .channel_mode = alc883_3ST_6ch_modes, 6793 .need_dac_fix = 1, 6794 .input_mux = &alc883_capture_source, 6795 .unsol_event = alc883_lenovo_ms7195_unsol_event, 6796 .init_hook = alc888_lenovo_ms7195_front_automute, 6797 }, 6798 [ALC888_HP_NETTLE] = { 6799 .mixers = { alc888_hp_nettle_mixer, alc883_chmode_mixer }, 6800 .init_verbs = { alc883_init_verbs, alc888_hp_nettle_verbs }, 6801 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6802 .dac_nids = alc883_dac_nids, 6803 .dig_out_nid = ALC883_DIGOUT_NID, 6804 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6805 .adc_nids = alc883_adc_nids, 6806 .dig_in_nid = ALC883_DIGIN_NID, 6807 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), 6808 .channel_mode = alc883_sixstack_modes, 6809 .input_mux = &alc883_capture_source, 6810 }, 6811 [ALC888_HP_LUCKNOW] = { 6812 .mixers = { alc888_hp_lucknow_mixer, alc883_chmode_mixer }, 6813 .init_verbs = { alc883_init_verbs, alc888_hp_lucknow_verbs }, 6814 .num_dacs = ARRAY_SIZE(alc883_dac_nids), 6815 .dac_nids = alc883_dac_nids, 6816 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), 6817 .adc_nids = alc883_adc_nids, 6818 .num_channel_mode = ARRAY_SIZE(alc888_hp_lucknow_modes), 6819 .channel_mode = alc888_hp_lucknow_modes, 6820 .need_dac_fix = 1, 6821 .input_mux = &alc883_capture_source, 6822 }, 6823}; 6824 6825 6826/* 6827 * BIOS auto configuration 6828 */ 6829static void alc883_auto_set_output_and_unmute(struct hda_codec *codec, 6830 hda_nid_t nid, int pin_type, 6831 int dac_idx) 6832{ 6833 /* set as output */ 6834 struct alc_spec *spec = codec->spec; 6835 int idx; 6836 6837 if (spec->multiout.dac_nids[dac_idx] == 0x25) 6838 idx = 4; 6839 else 6840 idx = spec->multiout.dac_nids[dac_idx] - 2; 6841 6842 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 6843 pin_type); 6844 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 6845 AMP_OUT_UNMUTE); 6846 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); 6847 6848} 6849 6850static void alc883_auto_init_multi_out(struct hda_codec *codec) 6851{ 6852 struct alc_spec *spec = codec->spec; 6853 int i; 6854 6855 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 6856 for (i = 0; i <= HDA_SIDE; i++) { 6857 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 6858 int pin_type = get_pin_type(spec->autocfg.line_out_type); 6859 if (nid) 6860 alc883_auto_set_output_and_unmute(codec, nid, pin_type, 6861 i); 6862 } 6863} 6864 6865static void alc883_auto_init_hp_out(struct hda_codec *codec) 6866{ 6867 struct alc_spec *spec = codec->spec; 6868 hda_nid_t pin; 6869 6870 pin = spec->autocfg.hp_pins[0]; 6871 if (pin) /* connect to front */ 6872 /* use dac 0 */ 6873 alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 6874} 6875 6876#define alc883_is_input_pin(nid) alc880_is_input_pin(nid) 6877#define ALC883_PIN_CD_NID ALC880_PIN_CD_NID 6878 6879static void alc883_auto_init_analog_input(struct hda_codec *codec) 6880{ 6881 struct alc_spec *spec = codec->spec; 6882 int i; 6883 6884 for (i = 0; i < AUTO_PIN_LAST; i++) { 6885 hda_nid_t nid = spec->autocfg.input_pins[i]; 6886 if (alc883_is_input_pin(nid)) { 6887 snd_hda_codec_write(codec, nid, 0, 6888 AC_VERB_SET_PIN_WIDGET_CONTROL, 6889 (i <= AUTO_PIN_FRONT_MIC ? 6890 PIN_VREF80 : PIN_IN)); 6891 if (nid != ALC883_PIN_CD_NID) 6892 snd_hda_codec_write(codec, nid, 0, 6893 AC_VERB_SET_AMP_GAIN_MUTE, 6894 AMP_OUT_MUTE); 6895 } 6896 } 6897} 6898 6899/* almost identical with ALC880 parser... */ 6900static int alc883_parse_auto_config(struct hda_codec *codec) 6901{ 6902 struct alc_spec *spec = codec->spec; 6903 int err = alc880_parse_auto_config(codec); 6904 6905 if (err < 0) 6906 return err; 6907 else if (err > 0) 6908 /* hack - override the init verbs */ 6909 spec->init_verbs[0] = alc883_auto_init_verbs; 6910 spec->mixers[spec->num_mixers] = alc883_capture_mixer; 6911 spec->num_mixers++; 6912 return err; 6913} 6914 6915/* additional initialization for auto-configuration model */ 6916static void alc883_auto_init(struct hda_codec *codec) 6917{ 6918 alc883_auto_init_multi_out(codec); 6919 alc883_auto_init_hp_out(codec); 6920 alc883_auto_init_analog_input(codec); 6921} 6922 6923static int patch_alc883(struct hda_codec *codec) 6924{ 6925 struct alc_spec *spec; 6926 int err, board_config; 6927 6928 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 6929 if (spec == NULL) 6930 return -ENOMEM; 6931 6932 codec->spec = spec; 6933 6934 board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST, 6935 alc883_models, 6936 alc883_cfg_tbl); 6937 if (board_config < 0) { 6938 printk(KERN_INFO "hda_codec: Unknown model for ALC883, " 6939 "trying auto-probe from BIOS...\n"); 6940 board_config = ALC883_AUTO; 6941 } 6942 6943 if (board_config == ALC883_AUTO) { 6944 /* automatic parse from the BIOS config */ 6945 err = alc883_parse_auto_config(codec); 6946 if (err < 0) { 6947 alc_free(codec); 6948 return err; 6949 } else if (!err) { 6950 printk(KERN_INFO 6951 "hda_codec: Cannot set up configuration " 6952 "from BIOS. Using base mode...\n"); 6953 board_config = ALC883_3ST_2ch_DIG; 6954 } 6955 } 6956 6957 if (board_config != ALC883_AUTO) 6958 setup_preset(spec, &alc883_presets[board_config]); 6959 6960 spec->stream_name_analog = "ALC883 Analog"; 6961 spec->stream_analog_playback = &alc883_pcm_analog_playback; 6962 spec->stream_analog_capture = &alc883_pcm_analog_capture; 6963 6964 spec->stream_name_digital = "ALC883 Digital"; 6965 spec->stream_digital_playback = &alc883_pcm_digital_playback; 6966 spec->stream_digital_capture = &alc883_pcm_digital_capture; 6967 6968 if (!spec->adc_nids && spec->input_mux) { 6969 spec->adc_nids = alc883_adc_nids; 6970 spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); 6971 } 6972 6973 codec->patch_ops = alc_patch_ops; 6974 if (board_config == ALC883_AUTO) 6975 spec->init_hook = alc883_auto_init; 6976 6977 return 0; 6978} 6979 6980/* 6981 * ALC262 support 6982 */ 6983 6984#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID 6985#define ALC262_DIGIN_NID ALC880_DIGIN_NID 6986 6987#define alc262_dac_nids alc260_dac_nids 6988#define alc262_adc_nids alc882_adc_nids 6989#define alc262_adc_nids_alt alc882_adc_nids_alt 6990 6991#define alc262_modes alc260_modes 6992#define alc262_capture_source alc882_capture_source 6993 6994static struct snd_kcontrol_new alc262_base_mixer[] = { 6995 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 6996 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 6997 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 6998 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 6999 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 7000 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 7001 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7002 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7003 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7004 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7005 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7006 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 7007 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7008 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */ 7009 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), 7010 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7011 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 7012 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 7013 { } /* end */ 7014}; 7015 7016static struct snd_kcontrol_new alc262_hippo1_mixer[] = { 7017 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7018 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 7019 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7020 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7021 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 7022 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 7023 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7024 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7025 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7026 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7027 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7028 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 7029 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7030 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */ 7031 /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/ 7032 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 7033 { } /* end */ 7034}; 7035 7036static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { 7037 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7038 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7039 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 7040 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 7041 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 7042 7043 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7044 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7045 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7046 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7047 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7048 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 7049 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 7050 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 7051 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7052 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7053 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7054 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), 7055 HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT), 7056 HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT), 7057 { } /* end */ 7058}; 7059 7060static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = { 7061 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7062 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 7063 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 7064 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7065 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 7066 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), 7067 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT), 7068 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT), 7069 HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT), 7070 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), 7071 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), 7072 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7073 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7074 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), 7075 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), 7076 { } /* end */ 7077}; 7078 7079static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = { 7080 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7081 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7082 HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT), 7083 { } /* end */ 7084}; 7085 7086static struct snd_kcontrol_new alc262_sony_mixer[] = { 7087 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7088 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7089 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7090 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7091 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7092 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7093 { } /* end */ 7094}; 7095 7096static struct snd_kcontrol_new alc262_benq_t31_mixer[] = { 7097 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 7098 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 7099 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 7100 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7101 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7102 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), 7103 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), 7104 { } /* end */ 7105}; 7106 7107#define alc262_capture_mixer alc882_capture_mixer 7108#define alc262_capture_alt_mixer alc882_capture_alt_mixer 7109 7110/* 7111 * generic initialization of ADC, input mixers and output mixers 7112 */ 7113static struct hda_verb alc262_init_verbs[] = { 7114 /* 7115 * Unmute ADC0-2 and set the default input to mic-in 7116 */ 7117 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7118 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7119 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7120 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7121 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7122 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7123 7124 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7125 * mixer widget 7126 * Note: PASD motherboards uses the Line In 2 as the input for 7127 * front panel mic (mic 2) 7128 */ 7129 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7130 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7131 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7132 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 7133 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 7134 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 7135 7136 /* 7137 * Set up output mixers (0x0c - 0x0e) 7138 */ 7139 /* set vol=0 to output mixers */ 7140 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7141 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7142 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7143 /* set up input amps for analog loopback */ 7144 /* Amp Indices: DAC = 0, mixer = 1 */ 7145 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7146 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7147 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7148 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7149 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7150 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7151 7152 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 7153 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7154 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 7155 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7156 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7157 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7158 7159 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7160 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7161 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7162 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7163 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7164 7165 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 7166 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 7167 7168 /* FIXME: use matrix-type input source selection */ 7169 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7170 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7171 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7172 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7173 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7174 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7175 /* Input mixer2 */ 7176 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7177 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7178 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7179 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7180 /* Input mixer3 */ 7181 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7182 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7183 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7184 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7185 7186 { } 7187}; 7188 7189static struct hda_verb alc262_hippo_unsol_verbs[] = { 7190 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 7191 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7192 {} 7193}; 7194 7195static struct hda_verb alc262_hippo1_unsol_verbs[] = { 7196 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7197 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 7198 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, 7199 7200 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 7201 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7202 {} 7203}; 7204 7205static struct hda_verb alc262_sony_unsol_verbs[] = { 7206 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7207 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 7208 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic 7209 7210 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 7211 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7212}; 7213 7214/* mute/unmute internal speaker according to the hp jack and mute state */ 7215static void alc262_hippo_automute(struct hda_codec *codec, int force) 7216{ 7217 struct alc_spec *spec = codec->spec; 7218 unsigned int mute; 7219 7220 if (force || !spec->sense_updated) { 7221 unsigned int present; 7222 /* need to execute and sync at first */ 7223 snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); 7224 present = snd_hda_codec_read(codec, 0x15, 0, 7225 AC_VERB_GET_PIN_SENSE, 0); 7226 spec->jack_present = (present & 0x80000000) != 0; 7227 spec->sense_updated = 1; 7228 } 7229 if (spec->jack_present) { 7230 /* mute internal speaker */ 7231 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7232 0x80, 0x80); 7233 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7234 0x80, 0x80); 7235 } else { 7236 /* unmute internal speaker if necessary */ 7237 mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0); 7238 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7239 0x80, mute & 0x80); 7240 mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0); 7241 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7242 0x80, mute & 0x80); 7243 } 7244} 7245 7246/* unsolicited event for HP jack sensing */ 7247static void alc262_hippo_unsol_event(struct hda_codec *codec, 7248 unsigned int res) 7249{ 7250 if ((res >> 26) != ALC880_HP_EVENT) 7251 return; 7252 alc262_hippo_automute(codec, 1); 7253} 7254 7255static void alc262_hippo1_automute(struct hda_codec *codec, int force) 7256{ 7257 struct alc_spec *spec = codec->spec; 7258 unsigned int mute; 7259 7260 if (force || !spec->sense_updated) { 7261 unsigned int present; 7262 /* need to execute and sync at first */ 7263 snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); 7264 present = snd_hda_codec_read(codec, 0x1b, 0, 7265 AC_VERB_GET_PIN_SENSE, 0); 7266 spec->jack_present = (present & 0x80000000) != 0; 7267 spec->sense_updated = 1; 7268 } 7269 if (spec->jack_present) { 7270 /* mute internal speaker */ 7271 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7272 0x80, 0x80); 7273 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7274 0x80, 0x80); 7275 } else { 7276 /* unmute internal speaker if necessary */ 7277 mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); 7278 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7279 0x80, mute & 0x80); 7280 mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0); 7281 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7282 0x80, mute & 0x80); 7283 } 7284} 7285 7286/* unsolicited event for HP jack sensing */ 7287static void alc262_hippo1_unsol_event(struct hda_codec *codec, 7288 unsigned int res) 7289{ 7290 if ((res >> 26) != ALC880_HP_EVENT) 7291 return; 7292 alc262_hippo1_automute(codec, 1); 7293} 7294 7295/* 7296 * fujitsu model 7297 * 0x14 = headphone/spdif-out, 0x15 = internal speaker 7298 */ 7299 7300#define ALC_HP_EVENT 0x37 7301 7302static struct hda_verb alc262_fujitsu_unsol_verbs[] = { 7303 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, 7304 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 7305 {} 7306}; 7307 7308static struct hda_input_mux alc262_fujitsu_capture_source = { 7309 .num_items = 2, 7310 .items = { 7311 { "Mic", 0x0 }, 7312 { "CD", 0x4 }, 7313 }, 7314}; 7315 7316static struct hda_input_mux alc262_HP_capture_source = { 7317 .num_items = 5, 7318 .items = { 7319 { "Mic", 0x0 }, 7320 { "Front Mic", 0x3 }, 7321 { "Line", 0x2 }, 7322 { "CD", 0x4 }, 7323 { "AUX IN", 0x6 }, 7324 }, 7325}; 7326 7327/* mute/unmute internal speaker according to the hp jack and mute state */ 7328static void alc262_fujitsu_automute(struct hda_codec *codec, int force) 7329{ 7330 struct alc_spec *spec = codec->spec; 7331 unsigned int mute; 7332 7333 if (force || !spec->sense_updated) { 7334 unsigned int present; 7335 /* need to execute and sync at first */ 7336 snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); 7337 present = snd_hda_codec_read(codec, 0x14, 0, 7338 AC_VERB_GET_PIN_SENSE, 0); 7339 spec->jack_present = (present & 0x80000000) != 0; 7340 spec->sense_updated = 1; 7341 } 7342 if (spec->jack_present) { 7343 /* mute internal speaker */ 7344 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 7345 0x80, 0x80); 7346 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 7347 0x80, 0x80); 7348 } else { 7349 /* unmute internal speaker if necessary */ 7350 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); 7351 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 7352 0x80, mute & 0x80); 7353 mute = snd_hda_codec_amp_read(codec, 0x14, 1, HDA_OUTPUT, 0); 7354 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 7355 0x80, mute & 0x80); 7356 } 7357} 7358 7359/* unsolicited event for HP jack sensing */ 7360static void alc262_fujitsu_unsol_event(struct hda_codec *codec, 7361 unsigned int res) 7362{ 7363 if ((res >> 26) != ALC_HP_EVENT) 7364 return; 7365 alc262_fujitsu_automute(codec, 1); 7366} 7367 7368/* bind volumes of both NID 0x0c and 0x0d */ 7369static int alc262_fujitsu_master_vol_put(struct snd_kcontrol *kcontrol, 7370 struct snd_ctl_elem_value *ucontrol) 7371{ 7372 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 7373 long *valp = ucontrol->value.integer.value; 7374 int change; 7375 7376 change = snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0, 7377 0x7f, valp[0] & 0x7f); 7378 change |= snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0, 7379 0x7f, valp[1] & 0x7f); 7380 snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0, 7381 0x7f, valp[0] & 0x7f); 7382 snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0, 7383 0x7f, valp[1] & 0x7f); 7384 return change; 7385} 7386 7387/* bind hp and internal speaker mute (with plug check) */ 7388static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, 7389 struct snd_ctl_elem_value *ucontrol) 7390{ 7391 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 7392 long *valp = ucontrol->value.integer.value; 7393 int change; 7394 7395 change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 7396 0x80, valp[0] ? 0 : 0x80); 7397 change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7398 0x80, valp[1] ? 0 : 0x80); 7399 if (change || codec->in_resume) 7400 alc262_fujitsu_automute(codec, codec->in_resume); 7401 return change; 7402} 7403 7404static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { 7405 { 7406 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 7407 .name = "Master Playback Volume", 7408 .info = snd_hda_mixer_amp_volume_info, 7409 .get = snd_hda_mixer_amp_volume_get, 7410 .put = alc262_fujitsu_master_vol_put, 7411 .tlv = { .c = snd_hda_mixer_amp_tlv }, 7412 .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), 7413 }, 7414 { 7415 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 7416 .name = "Master Playback Switch", 7417 .info = snd_hda_mixer_amp_switch_info, 7418 .get = snd_hda_mixer_amp_switch_get, 7419 .put = alc262_fujitsu_master_sw_put, 7420 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), 7421 }, 7422 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 7423 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 7424 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 7425 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 7426 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 7427 { } /* end */ 7428}; 7429 7430/* additional init verbs for Benq laptops */ 7431static struct hda_verb alc262_EAPD_verbs[] = { 7432 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 7433 {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, 7434 {} 7435}; 7436 7437static struct hda_verb alc262_benq_t31_EAPD_verbs[] = { 7438 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 7439 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7440 7441 {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, 7442 {0x20, AC_VERB_SET_PROC_COEF, 0x3050}, 7443 {} 7444}; 7445 7446/* add playback controls from the parsed DAC table */ 7447static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, 7448 const struct auto_pin_cfg *cfg) 7449{ 7450 hda_nid_t nid; 7451 int err; 7452 7453 spec->multiout.num_dacs = 1; /* only use one dac */ 7454 spec->multiout.dac_nids = spec->private_dac_nids; 7455 spec->multiout.dac_nids[0] = 2; 7456 7457 nid = cfg->line_out_pins[0]; 7458 if (nid) { 7459 err = add_control(spec, ALC_CTL_WIDGET_VOL, 7460 "Front Playback Volume", 7461 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT)); 7462 if (err < 0) 7463 return err; 7464 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7465 "Front Playback Switch", 7466 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 7467 if (err < 0) 7468 return err; 7469 } 7470 7471 nid = cfg->speaker_pins[0]; 7472 if (nid) { 7473 if (nid == 0x16) { 7474 err = add_control(spec, ALC_CTL_WIDGET_VOL, 7475 "Speaker Playback Volume", 7476 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, 7477 HDA_OUTPUT)); 7478 if (err < 0) 7479 return err; 7480 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7481 "Speaker Playback Switch", 7482 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 7483 HDA_OUTPUT)); 7484 if (err < 0) 7485 return err; 7486 } else { 7487 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7488 "Speaker Playback Switch", 7489 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 7490 HDA_OUTPUT)); 7491 if (err < 0) 7492 return err; 7493 } 7494 } 7495 nid = cfg->hp_pins[0]; 7496 if (nid) { 7497 /* spec->multiout.hp_nid = 2; */ 7498 if (nid == 0x16) { 7499 err = add_control(spec, ALC_CTL_WIDGET_VOL, 7500 "Headphone Playback Volume", 7501 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, 7502 HDA_OUTPUT)); 7503 if (err < 0) 7504 return err; 7505 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7506 "Headphone Playback Switch", 7507 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 7508 HDA_OUTPUT)); 7509 if (err < 0) 7510 return err; 7511 } else { 7512 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 7513 "Headphone Playback Switch", 7514 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 7515 HDA_OUTPUT)); 7516 if (err < 0) 7517 return err; 7518 } 7519 } 7520 return 0; 7521} 7522 7523/* identical with ALC880 */ 7524#define alc262_auto_create_analog_input_ctls \ 7525 alc880_auto_create_analog_input_ctls 7526 7527/* 7528 * generic initialization of ADC, input mixers and output mixers 7529 */ 7530static struct hda_verb alc262_volume_init_verbs[] = { 7531 /* 7532 * Unmute ADC0-2 and set the default input to mic-in 7533 */ 7534 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7535 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7536 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7537 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7538 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7539 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7540 7541 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7542 * mixer widget 7543 * Note: PASD motherboards uses the Line In 2 as the input for 7544 * front panel mic (mic 2) 7545 */ 7546 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7547 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7548 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7549 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 7550 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 7551 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 7552 7553 /* 7554 * Set up output mixers (0x0c - 0x0f) 7555 */ 7556 /* set vol=0 to output mixers */ 7557 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7558 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7559 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7560 7561 /* set up input amps for analog loopback */ 7562 /* Amp Indices: DAC = 0, mixer = 1 */ 7563 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7564 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7565 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7566 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7567 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7568 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7569 7570 /* FIXME: use matrix-type input source selection */ 7571 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7572 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7573 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7574 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7575 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7576 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7577 /* Input mixer2 */ 7578 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7579 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7580 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7581 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7582 /* Input mixer3 */ 7583 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7584 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, 7585 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, 7586 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, 7587 7588 { } 7589}; 7590 7591static struct hda_verb alc262_HP_BPC_init_verbs[] = { 7592 /* 7593 * Unmute ADC0-2 and set the default input to mic-in 7594 */ 7595 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7596 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7597 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7598 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7599 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7600 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7601 7602 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7603 * mixer widget 7604 * Note: PASD motherboards uses the Line In 2 as the input for 7605 * front panel mic (mic 2) 7606 */ 7607 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7608 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7609 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7610 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 7611 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 7612 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 7613 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, 7614 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, 7615 7616 /* 7617 * Set up output mixers (0x0c - 0x0e) 7618 */ 7619 /* set vol=0 to output mixers */ 7620 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7621 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7622 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7623 7624 /* set up input amps for analog loopback */ 7625 /* Amp Indices: DAC = 0, mixer = 1 */ 7626 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7627 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7628 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7629 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7630 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7631 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7632 7633 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 7634 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 7635 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 7636 7637 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7638 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7639 7640 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 7641 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 7642 7643 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7644 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7645 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 7646 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7647 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 7648 7649 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, 7650 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7651 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7652 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, 7653 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7654 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7655 7656 7657 /* FIXME: use matrix-type input source selection */ 7658 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7659 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7660 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7661 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7662 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7663 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7664 /* Input mixer2 */ 7665 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7666 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7667 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7668 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7669 /* Input mixer3 */ 7670 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7671 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7672 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7673 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7674 7675 { } 7676}; 7677 7678static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = { 7679 /* 7680 * Unmute ADC0-2 and set the default input to mic-in 7681 */ 7682 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 7683 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7684 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 7685 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7686 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 7687 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7688 7689 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 7690 * mixer widget 7691 * Note: PASD motherboards uses the Line In 2 as the input for front 7692 * panel mic (mic 2) 7693 */ 7694 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 7695 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7696 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7697 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 7698 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 7699 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 7700 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, 7701 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, 7702 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, 7703 /* 7704 * Set up output mixers (0x0c - 0x0e) 7705 */ 7706 /* set vol=0 to output mixers */ 7707 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7708 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7709 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 7710 7711 /* set up input amps for analog loopback */ 7712 /* Amp Indices: DAC = 0, mixer = 1 */ 7713 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7714 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7715 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7716 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7717 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 7718 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 7719 7720 7721 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */ 7722 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */ 7723 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */ 7724 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */ 7725 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */ 7726 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */ 7727 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */ 7728 7729 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7730 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 7731 7732 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 7733 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 7734 7735 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */ 7736 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7737 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7738 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, 7739 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7740 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, 7741 7742 /* FIXME: use matrix-type input source selection */ 7743 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 7744 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 7745 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/ 7746 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/ 7747 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/ 7748 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/ 7749 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/ 7750 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */ 7751 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/ 7752 /* Input mixer2 */ 7753 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7754 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 7755 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7756 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7757 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7758 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */ 7759 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, 7760 /* Input mixer3 */ 7761 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 7762 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 7763 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 7764 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 7765 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, 7766 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */ 7767 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, 7768 7769 { } 7770}; 7771 7772/* pcm configuration: identiacal with ALC880 */ 7773#define alc262_pcm_analog_playback alc880_pcm_analog_playback 7774#define alc262_pcm_analog_capture alc880_pcm_analog_capture 7775#define alc262_pcm_digital_playback alc880_pcm_digital_playback 7776#define alc262_pcm_digital_capture alc880_pcm_digital_capture 7777 7778/* 7779 * BIOS auto configuration 7780 */ 7781static int alc262_parse_auto_config(struct hda_codec *codec) 7782{ 7783 struct alc_spec *spec = codec->spec; 7784 int err; 7785 static hda_nid_t alc262_ignore[] = { 0x1d, 0 }; 7786 7787 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 7788 alc262_ignore); 7789 if (err < 0) 7790 return err; 7791 if (!spec->autocfg.line_outs) 7792 return 0; /* can't find valid BIOS pin config */ 7793 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); 7794 if (err < 0) 7795 return err; 7796 err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg); 7797 if (err < 0) 7798 return err; 7799 7800 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 7801 7802 if (spec->autocfg.dig_out_pin) 7803 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; 7804 if (spec->autocfg.dig_in_pin) 7805 spec->dig_in_nid = ALC262_DIGIN_NID; 7806 7807 if (spec->kctl_alloc) 7808 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 7809 7810 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; 7811 spec->num_mux_defs = 1; 7812 spec->input_mux = &spec->private_imux; 7813 7814 return 1; 7815} 7816 7817#define alc262_auto_init_multi_out alc882_auto_init_multi_out 7818#define alc262_auto_init_hp_out alc882_auto_init_hp_out 7819#define alc262_auto_init_analog_input alc882_auto_init_analog_input 7820 7821 7822/* init callback for auto-configuration model -- overriding the default init */ 7823static void alc262_auto_init(struct hda_codec *codec) 7824{ 7825 alc262_auto_init_multi_out(codec); 7826 alc262_auto_init_hp_out(codec); 7827 alc262_auto_init_analog_input(codec); 7828} 7829 7830/* 7831 * configuration and preset 7832 */ 7833static const char *alc262_models[ALC262_MODEL_LAST] = { 7834 [ALC262_BASIC] = "basic", 7835 [ALC262_HIPPO] = "hippo", 7836 [ALC262_HIPPO_1] = "hippo_1", 7837 [ALC262_FUJITSU] = "fujitsu", 7838 [ALC262_HP_BPC] = "hp-bpc", 7839 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000", 7840 [ALC262_BENQ_ED8] = "benq", 7841 [ALC262_BENQ_T31] = "benq-t31", 7842 [ALC262_SONY_ASSAMD] = "sony-assamd", 7843 [ALC262_AUTO] = "auto", 7844}; 7845 7846static struct snd_pci_quirk alc262_cfg_tbl[] = { 7847 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), 7848 SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC), 7849 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC), 7850 SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC), 7851 SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC), 7852 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC), 7853 SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC), 7854 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC), 7855 SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC), 7856 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), 7857 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), 7858 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL), 7859 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL), 7860 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), 7861 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF), 7862 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF), 7863 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF), 7864 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO), 7865 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), 7866 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), 7867 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), 7868 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), 7869 SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), 7870 SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), 7871 SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), 7872 {} 7873}; 7874 7875static struct alc_config_preset alc262_presets[] = { 7876 [ALC262_BASIC] = { 7877 .mixers = { alc262_base_mixer }, 7878 .init_verbs = { alc262_init_verbs }, 7879 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7880 .dac_nids = alc262_dac_nids, 7881 .hp_nid = 0x03, 7882 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7883 .channel_mode = alc262_modes, 7884 .input_mux = &alc262_capture_source, 7885 }, 7886 [ALC262_HIPPO] = { 7887 .mixers = { alc262_base_mixer }, 7888 .init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs}, 7889 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7890 .dac_nids = alc262_dac_nids, 7891 .hp_nid = 0x03, 7892 .dig_out_nid = ALC262_DIGOUT_NID, 7893 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7894 .channel_mode = alc262_modes, 7895 .input_mux = &alc262_capture_source, 7896 .unsol_event = alc262_hippo_unsol_event, 7897 }, 7898 [ALC262_HIPPO_1] = { 7899 .mixers = { alc262_hippo1_mixer }, 7900 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs}, 7901 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7902 .dac_nids = alc262_dac_nids, 7903 .hp_nid = 0x02, 7904 .dig_out_nid = ALC262_DIGOUT_NID, 7905 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7906 .channel_mode = alc262_modes, 7907 .input_mux = &alc262_capture_source, 7908 .unsol_event = alc262_hippo1_unsol_event, 7909 }, 7910 [ALC262_FUJITSU] = { 7911 .mixers = { alc262_fujitsu_mixer }, 7912 .init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs }, 7913 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7914 .dac_nids = alc262_dac_nids, 7915 .hp_nid = 0x03, 7916 .dig_out_nid = ALC262_DIGOUT_NID, 7917 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7918 .channel_mode = alc262_modes, 7919 .input_mux = &alc262_fujitsu_capture_source, 7920 .unsol_event = alc262_fujitsu_unsol_event, 7921 }, 7922 [ALC262_HP_BPC] = { 7923 .mixers = { alc262_HP_BPC_mixer }, 7924 .init_verbs = { alc262_HP_BPC_init_verbs }, 7925 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7926 .dac_nids = alc262_dac_nids, 7927 .hp_nid = 0x03, 7928 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7929 .channel_mode = alc262_modes, 7930 .input_mux = &alc262_HP_capture_source, 7931 }, 7932 [ALC262_HP_BPC_D7000_WF] = { 7933 .mixers = { alc262_HP_BPC_WildWest_mixer }, 7934 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs }, 7935 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7936 .dac_nids = alc262_dac_nids, 7937 .hp_nid = 0x03, 7938 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7939 .channel_mode = alc262_modes, 7940 .input_mux = &alc262_HP_capture_source, 7941 }, 7942 [ALC262_HP_BPC_D7000_WL] = { 7943 .mixers = { alc262_HP_BPC_WildWest_mixer, 7944 alc262_HP_BPC_WildWest_option_mixer }, 7945 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs }, 7946 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7947 .dac_nids = alc262_dac_nids, 7948 .hp_nid = 0x03, 7949 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7950 .channel_mode = alc262_modes, 7951 .input_mux = &alc262_HP_capture_source, 7952 }, 7953 [ALC262_BENQ_ED8] = { 7954 .mixers = { alc262_base_mixer }, 7955 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs }, 7956 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7957 .dac_nids = alc262_dac_nids, 7958 .hp_nid = 0x03, 7959 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7960 .channel_mode = alc262_modes, 7961 .input_mux = &alc262_capture_source, 7962 }, 7963 [ALC262_SONY_ASSAMD] = { 7964 .mixers = { alc262_sony_mixer }, 7965 .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs}, 7966 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7967 .dac_nids = alc262_dac_nids, 7968 .hp_nid = 0x02, 7969 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7970 .channel_mode = alc262_modes, 7971 .input_mux = &alc262_capture_source, 7972 .unsol_event = alc262_hippo_unsol_event, 7973 }, 7974 [ALC262_BENQ_T31] = { 7975 .mixers = { alc262_benq_t31_mixer }, 7976 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs, alc262_hippo_unsol_verbs }, 7977 .num_dacs = ARRAY_SIZE(alc262_dac_nids), 7978 .dac_nids = alc262_dac_nids, 7979 .hp_nid = 0x03, 7980 .num_channel_mode = ARRAY_SIZE(alc262_modes), 7981 .channel_mode = alc262_modes, 7982 .input_mux = &alc262_capture_source, 7983 .unsol_event = alc262_hippo_unsol_event, 7984 }, 7985}; 7986 7987static int patch_alc262(struct hda_codec *codec) 7988{ 7989 struct alc_spec *spec; 7990 int board_config; 7991 int err; 7992 7993 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 7994 if (spec == NULL) 7995 return -ENOMEM; 7996 7997 codec->spec = spec; 7998#if 0 7999 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is 8000 * under-run 8001 */ 8002 { 8003 int tmp; 8004 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); 8005 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); 8006 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); 8007 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80); 8008 } 8009#endif 8010 8011 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST, 8012 alc262_models, 8013 alc262_cfg_tbl); 8014 8015 if (board_config < 0) { 8016 printk(KERN_INFO "hda_codec: Unknown model for ALC262, " 8017 "trying auto-probe from BIOS...\n"); 8018 board_config = ALC262_AUTO; 8019 } 8020 8021 if (board_config == ALC262_AUTO) { 8022 /* automatic parse from the BIOS config */ 8023 err = alc262_parse_auto_config(codec); 8024 if (err < 0) { 8025 alc_free(codec); 8026 return err; 8027 } else if (!err) { 8028 printk(KERN_INFO 8029 "hda_codec: Cannot set up configuration " 8030 "from BIOS. Using base mode...\n"); 8031 board_config = ALC262_BASIC; 8032 } 8033 } 8034 8035 if (board_config != ALC262_AUTO) 8036 setup_preset(spec, &alc262_presets[board_config]); 8037 8038 spec->stream_name_analog = "ALC262 Analog"; 8039 spec->stream_analog_playback = &alc262_pcm_analog_playback; 8040 spec->stream_analog_capture = &alc262_pcm_analog_capture; 8041 8042 spec->stream_name_digital = "ALC262 Digital"; 8043 spec->stream_digital_playback = &alc262_pcm_digital_playback; 8044 spec->stream_digital_capture = &alc262_pcm_digital_capture; 8045 8046 if (!spec->adc_nids && spec->input_mux) { 8047 /* check whether NID 0x07 is valid */ 8048 unsigned int wcap = get_wcaps(codec, 0x07); 8049 8050 /* get type */ 8051 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 8052 if (wcap != AC_WID_AUD_IN) { 8053 spec->adc_nids = alc262_adc_nids_alt; 8054 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); 8055 spec->mixers[spec->num_mixers] = 8056 alc262_capture_alt_mixer; 8057 spec->num_mixers++; 8058 } else { 8059 spec->adc_nids = alc262_adc_nids; 8060 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids); 8061 spec->mixers[spec->num_mixers] = alc262_capture_mixer; 8062 spec->num_mixers++; 8063 } 8064 } 8065 8066 codec->patch_ops = alc_patch_ops; 8067 if (board_config == ALC262_AUTO) 8068 spec->init_hook = alc262_auto_init; 8069 8070 return 0; 8071} 8072 8073/* 8074 * ALC268 channel source setting (2 channel) 8075 */ 8076#define ALC268_DIGOUT_NID ALC880_DIGOUT_NID 8077#define alc268_modes alc260_modes 8078 8079static hda_nid_t alc268_dac_nids[2] = { 8080 /* front, hp */ 8081 0x02, 0x03 8082}; 8083 8084static hda_nid_t alc268_adc_nids[2] = { 8085 /* ADC0-1 */ 8086 0x08, 0x07 8087}; 8088 8089static hda_nid_t alc268_adc_nids_alt[1] = { 8090 /* ADC0 */ 8091 0x08 8092}; 8093 8094static struct snd_kcontrol_new alc268_base_mixer[] = { 8095 /* output mixer control */ 8096 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), 8097 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 8098 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), 8099 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), 8100 { } 8101}; 8102 8103/* 8104 * generic initialization of ADC, input mixers and output mixers 8105 */ 8106static struct hda_verb alc268_base_init_verbs[] = { 8107 /* Unmute DAC0-1 and set vol = 0 */ 8108 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8109 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8110 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8111 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8112 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8113 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8114 8115 /* 8116 * Set up output mixers (0x0c - 0x0e) 8117 */ 8118 /* set vol=0 to output mixers */ 8119 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8120 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8121 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8122 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, 8123 8124 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8125 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8126 8127 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 8128 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 8129 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 8130 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8131 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8132 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8133 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8134 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8135 8136 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8137 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8138 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8139 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8140 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8141 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8142 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8143 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 8144 8145 /* FIXME: use matrix-type input source selection */ 8146 /* Mixer elements: 0x18, 19, 1a, 1c, 14, 15, 0b */ 8147 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 8148 /* Input mixer2 */ 8149 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 8150 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 8151 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 8152 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 8153 8154 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, 8155 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 8156 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, 8157 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, 8158 { } 8159}; 8160 8161/* 8162 * generic initialization of ADC, input mixers and output mixers 8163 */ 8164static struct hda_verb alc268_volume_init_verbs[] = { 8165 /* set output DAC */ 8166 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8167 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8168 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8169 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8170 8171 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8172 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, 8173 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8174 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8175 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, 8176 8177 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 8178 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8179 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8180 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8181 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8182 8183 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8184 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8185 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8186 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 8187 8188 /* set PCBEEP vol = 0 */ 8189 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0xb000 | (0x00 << 8))}, 8190 8191 { } 8192}; 8193 8194#define alc268_mux_enum_info alc_mux_enum_info 8195#define alc268_mux_enum_get alc_mux_enum_get 8196 8197static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol, 8198 struct snd_ctl_elem_value *ucontrol) 8199{ 8200 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 8201 struct alc_spec *spec = codec->spec; 8202 const struct hda_input_mux *imux = spec->input_mux; 8203 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 8204 static hda_nid_t capture_mixers[3] = { 0x23, 0x24 }; 8205 hda_nid_t nid = capture_mixers[adc_idx]; 8206 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 8207 unsigned int i, idx; 8208 8209 idx = ucontrol->value.enumerated.item[0]; 8210 if (idx >= imux->num_items) 8211 idx = imux->num_items - 1; 8212 if (*cur_val == idx && !codec->in_resume) 8213 return 0; 8214 for (i = 0; i < imux->num_items; i++) { 8215 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 8216 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 8217 v | (imux->items[i].index << 8)); 8218 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, 8219 idx ); 8220 } 8221 *cur_val = idx; 8222 return 1; 8223} 8224 8225static struct snd_kcontrol_new alc268_capture_alt_mixer[] = { 8226 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), 8227 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), 8228 { 8229 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8230 /* The multiple "Capture Source" controls confuse alsamixer 8231 * So call somewhat different.. 8232 * FIXME: the controls appear in the "playback" view! 8233 */ 8234 /* .name = "Capture Source", */ 8235 .name = "Input Source", 8236 .count = 1, 8237 .info = alc268_mux_enum_info, 8238 .get = alc268_mux_enum_get, 8239 .put = alc268_mux_enum_put, 8240 }, 8241 { } /* end */ 8242}; 8243 8244static struct snd_kcontrol_new alc268_capture_mixer[] = { 8245 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), 8246 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), 8247 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT), 8248 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT), 8249 { 8250 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8251 /* The multiple "Capture Source" controls confuse alsamixer 8252 * So call somewhat different.. 8253 * FIXME: the controls appear in the "playback" view! 8254 */ 8255 /* .name = "Capture Source", */ 8256 .name = "Input Source", 8257 .count = 2, 8258 .info = alc268_mux_enum_info, 8259 .get = alc268_mux_enum_get, 8260 .put = alc268_mux_enum_put, 8261 }, 8262 { } /* end */ 8263}; 8264 8265static struct hda_input_mux alc268_capture_source = { 8266 .num_items = 4, 8267 .items = { 8268 { "Mic", 0x0 }, 8269 { "Front Mic", 0x1 }, 8270 { "Line", 0x2 }, 8271 { "CD", 0x3 }, 8272 }, 8273}; 8274 8275/* create input playback/capture controls for the given pin */ 8276static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, 8277 const char *ctlname, int idx) 8278{ 8279 char name[32]; 8280 int err; 8281 8282 sprintf(name, "%s Playback Volume", ctlname); 8283 if (nid == 0x14) { 8284 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 8285 HDA_COMPOSE_AMP_VAL(0x02, 3, idx, 8286 HDA_OUTPUT)); 8287 if (err < 0) 8288 return err; 8289 } else if (nid == 0x15) { 8290 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 8291 HDA_COMPOSE_AMP_VAL(0x03, 3, idx, 8292 HDA_OUTPUT)); 8293 if (err < 0) 8294 return err; 8295 } else 8296 return -1; 8297 sprintf(name, "%s Playback Switch", ctlname); 8298 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 8299 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT)); 8300 if (err < 0) 8301 return err; 8302 return 0; 8303} 8304 8305/* add playback controls from the parsed DAC table */ 8306static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec, 8307 const struct auto_pin_cfg *cfg) 8308{ 8309 hda_nid_t nid; 8310 int err; 8311 8312 spec->multiout.num_dacs = 2; /* only use one dac */ 8313 spec->multiout.dac_nids = spec->private_dac_nids; 8314 spec->multiout.dac_nids[0] = 2; 8315 spec->multiout.dac_nids[1] = 3; 8316 8317 nid = cfg->line_out_pins[0]; 8318 if (nid) 8319 alc268_new_analog_output(spec, nid, "Front", 0); 8320 8321 nid = cfg->speaker_pins[0]; 8322 if (nid == 0x1d) { 8323 err = add_control(spec, ALC_CTL_WIDGET_VOL, 8324 "Speaker Playback Volume", 8325 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); 8326 if (err < 0) 8327 return err; 8328 } 8329 nid = cfg->hp_pins[0]; 8330 if (nid) 8331 alc268_new_analog_output(spec, nid, "Headphone", 0); 8332 8333 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2]; 8334 if (nid == 0x16) { 8335 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 8336 "Mono Playback Switch", 8337 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_INPUT)); 8338 if (err < 0) 8339 return err; 8340 } 8341 return 0; 8342} 8343 8344/* create playback/capture controls for input pins */ 8345static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec, 8346 const struct auto_pin_cfg *cfg) 8347{ 8348 struct hda_input_mux *imux = &spec->private_imux; 8349 int i, idx1; 8350 8351 for (i = 0; i < AUTO_PIN_LAST; i++) { 8352 switch(cfg->input_pins[i]) { 8353 case 0x18: 8354 idx1 = 0; /* Mic 1 */ 8355 break; 8356 case 0x19: 8357 idx1 = 1; /* Mic 2 */ 8358 break; 8359 case 0x1a: 8360 idx1 = 2; /* Line In */ 8361 break; 8362 case 0x1c: 8363 idx1 = 3; /* CD */ 8364 break; 8365 default: 8366 continue; 8367 } 8368 imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; 8369 imux->items[imux->num_items].index = idx1; 8370 imux->num_items++; 8371 } 8372 return 0; 8373} 8374 8375static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) 8376{ 8377 struct alc_spec *spec = codec->spec; 8378 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0]; 8379 hda_nid_t hp_nid = spec->autocfg.hp_pins[0]; 8380 hda_nid_t line_nid = spec->autocfg.line_out_pins[0]; 8381 unsigned int dac_vol1, dac_vol2; 8382 8383 if (speaker_nid) { 8384 snd_hda_codec_write(codec, speaker_nid, 0, 8385 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 8386 snd_hda_codec_write(codec, 0x0f, 0, 8387 AC_VERB_SET_AMP_GAIN_MUTE, 8388 AMP_IN_UNMUTE(1)); 8389 snd_hda_codec_write(codec, 0x10, 0, 8390 AC_VERB_SET_AMP_GAIN_MUTE, 8391 AMP_IN_UNMUTE(1)); 8392 } else { 8393 snd_hda_codec_write(codec, 0x0f, 0, 8394 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)); 8395 snd_hda_codec_write(codec, 0x10, 0, 8396 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)); 8397 } 8398 8399 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */ 8400 if (line_nid == 0x14) 8401 dac_vol2 = AMP_OUT_ZERO; 8402 else if (line_nid == 0x15) 8403 dac_vol1 = AMP_OUT_ZERO; 8404 if (hp_nid == 0x14) 8405 dac_vol2 = AMP_OUT_ZERO; 8406 else if (hp_nid == 0x15) 8407 dac_vol1 = AMP_OUT_ZERO; 8408 if (line_nid != 0x16 || hp_nid != 0x16 || 8409 spec->autocfg.line_out_pins[1] != 0x16 || 8410 spec->autocfg.line_out_pins[2] != 0x16) 8411 dac_vol1 = dac_vol2 = AMP_OUT_ZERO; 8412 8413 snd_hda_codec_write(codec, 0x02, 0, 8414 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1); 8415 snd_hda_codec_write(codec, 0x03, 0, 8416 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2); 8417} 8418 8419/* pcm configuration: identiacal with ALC880 */ 8420#define alc268_pcm_analog_playback alc880_pcm_analog_playback 8421#define alc268_pcm_analog_capture alc880_pcm_analog_capture 8422#define alc268_pcm_digital_playback alc880_pcm_digital_playback 8423 8424/* 8425 * BIOS auto configuration 8426 */ 8427static int alc268_parse_auto_config(struct hda_codec *codec) 8428{ 8429 struct alc_spec *spec = codec->spec; 8430 int err; 8431 static hda_nid_t alc268_ignore[] = { 0 }; 8432 8433 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 8434 alc268_ignore); 8435 if (err < 0) 8436 return err; 8437 if (!spec->autocfg.line_outs) 8438 return 0; /* can't find valid BIOS pin config */ 8439 8440 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg); 8441 if (err < 0) 8442 return err; 8443 err = alc268_auto_create_analog_input_ctls(spec, &spec->autocfg); 8444 if (err < 0) 8445 return err; 8446 8447 spec->multiout.max_channels = 2; 8448 8449 /* digital only support output */ 8450 if (spec->autocfg.dig_out_pin) 8451 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; 8452 8453 if (spec->kctl_alloc) 8454 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 8455 8456 spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs; 8457 spec->num_mux_defs = 1; 8458 spec->input_mux = &spec->private_imux; 8459 8460 return 1; 8461} 8462 8463#define alc268_auto_init_multi_out alc882_auto_init_multi_out 8464#define alc268_auto_init_hp_out alc882_auto_init_hp_out 8465#define alc268_auto_init_analog_input alc882_auto_init_analog_input 8466 8467/* init callback for auto-configuration model -- overriding the default init */ 8468static void alc268_auto_init(struct hda_codec *codec) 8469{ 8470 alc268_auto_init_multi_out(codec); 8471 alc268_auto_init_hp_out(codec); 8472 alc268_auto_init_mono_speaker_out(codec); 8473 alc268_auto_init_analog_input(codec); 8474} 8475 8476/* 8477 * configuration and preset 8478 */ 8479static const char *alc268_models[ALC268_MODEL_LAST] = { 8480 [ALC268_3ST] = "3stack", 8481 [ALC268_AUTO] = "auto", 8482}; 8483 8484static struct snd_pci_quirk alc268_cfg_tbl[] = { 8485 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), 8486 {} 8487}; 8488 8489static struct alc_config_preset alc268_presets[] = { 8490 [ALC268_3ST] = { 8491 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer }, 8492 .init_verbs = { alc268_base_init_verbs }, 8493 .num_dacs = ARRAY_SIZE(alc268_dac_nids), 8494 .dac_nids = alc268_dac_nids, 8495 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), 8496 .adc_nids = alc268_adc_nids_alt, 8497 .hp_nid = 0x03, 8498 .dig_out_nid = ALC268_DIGOUT_NID, 8499 .num_channel_mode = ARRAY_SIZE(alc268_modes), 8500 .channel_mode = alc268_modes, 8501 .input_mux = &alc268_capture_source, 8502 }, 8503}; 8504 8505static int patch_alc268(struct hda_codec *codec) 8506{ 8507 struct alc_spec *spec; 8508 int board_config; 8509 int err; 8510 8511 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); 8512 if (spec == NULL) 8513 return -ENOMEM; 8514 8515 codec->spec = spec; 8516 8517 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST, 8518 alc268_models, 8519 alc268_cfg_tbl); 8520 8521 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) { 8522 printk(KERN_INFO "hda_codec: Unknown model for ALC268, " 8523 "trying auto-probe from BIOS...\n"); 8524 board_config = ALC268_AUTO; 8525 } 8526 8527 if (board_config == ALC268_AUTO) { 8528 /* automatic parse from the BIOS config */ 8529 err = alc268_parse_auto_config(codec); 8530 if (err < 0) { 8531 alc_free(codec); 8532 return err; 8533 } else if (!err) { 8534 printk(KERN_INFO 8535 "hda_codec: Cannot set up configuration " 8536 "from BIOS. Using base mode...\n"); 8537 board_config = ALC268_3ST; 8538 } 8539 } 8540 8541 if (board_config != ALC268_AUTO) 8542 setup_preset(spec, &alc268_presets[board_config]); 8543 8544 spec->stream_name_analog = "ALC268 Analog"; 8545 spec->stream_analog_playback = &alc268_pcm_analog_playback; 8546 spec->stream_analog_capture = &alc268_pcm_analog_capture; 8547 8548 spec->stream_name_digital = "ALC268 Digital"; 8549 spec->stream_digital_playback = &alc268_pcm_digital_playback; 8550 8551 if (board_config == ALC268_AUTO) { 8552 if (!spec->adc_nids && spec->input_mux) { 8553 /* check whether NID 0x07 is valid */ 8554 unsigned int wcap = get_wcaps(codec, 0x07); 8555 8556 /* get type */ 8557 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 8558 if (wcap != AC_WID_AUD_IN) { 8559 spec->adc_nids = alc268_adc_nids_alt; 8560 spec->num_adc_nids = 8561 ARRAY_SIZE(alc268_adc_nids_alt); 8562 spec->mixers[spec->num_mixers] = 8563 alc268_capture_alt_mixer; 8564 spec->num_mixers++; 8565 } else { 8566 spec->adc_nids = alc268_adc_nids; 8567 spec->num_adc_nids = 8568 ARRAY_SIZE(alc268_adc_nids); 8569 spec->mixers[spec->num_mixers] = 8570 alc268_capture_mixer; 8571 spec->num_mixers++; 8572 } 8573 } 8574 } 8575 codec->patch_ops = alc_patch_ops; 8576 if (board_config == ALC268_AUTO) 8577 spec->init_hook = alc268_auto_init; 8578 8579 return 0; 8580} 8581 8582/* 8583 * ALC861 channel source setting (2/6 channel selection for 3-stack) 8584 */ 8585 8586/* 8587 * set the path ways for 2 channel output 8588 * need to set the codec line out and mic 1 pin widgets to inputs 8589 */ 8590static struct hda_verb alc861_threestack_ch2_init[] = { 8591 /* set pin widget 1Ah (line in) for input */ 8592 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8593 /* set pin widget 18h (mic1/2) for input, for mic also enable 8594 * the vref 8595 */ 8596 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8597 8598 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, 8599#if 0 8600 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ 8601 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/ 8602#endif 8603 { } /* end */ 8604}; 8605/* 8606 * 6ch mode 8607 * need to set the codec line out and mic 1 pin widgets to outputs 8608 */ 8609static struct hda_verb alc861_threestack_ch6_init[] = { 8610 /* set pin widget 1Ah (line in) for output (Back Surround)*/ 8611 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8612 /* set pin widget 18h (mic1) for output (CLFE)*/ 8613 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8614 8615 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8616 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8617 8618 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, 8619#if 0 8620 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ 8621 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/ 8622#endif 8623 { } /* end */ 8624}; 8625 8626static struct hda_channel_mode alc861_threestack_modes[2] = { 8627 { 2, alc861_threestack_ch2_init }, 8628 { 6, alc861_threestack_ch6_init }, 8629}; 8630/* Set mic1 as input and unmute the mixer */ 8631static struct hda_verb alc861_uniwill_m31_ch2_init[] = { 8632 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8633 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ 8634 { } /* end */ 8635}; 8636/* Set mic1 as output and mute mixer */ 8637static struct hda_verb alc861_uniwill_m31_ch4_init[] = { 8638 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8639 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ 8640 { } /* end */ 8641}; 8642 8643static struct hda_channel_mode alc861_uniwill_m31_modes[2] = { 8644 { 2, alc861_uniwill_m31_ch2_init }, 8645 { 4, alc861_uniwill_m31_ch4_init }, 8646}; 8647 8648/* Set mic1 and line-in as input and unmute the mixer */ 8649static struct hda_verb alc861_asus_ch2_init[] = { 8650 /* set pin widget 1Ah (line in) for input */ 8651 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8652 /* set pin widget 18h (mic1/2) for input, for mic also enable 8653 * the vref 8654 */ 8655 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8656 8657 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, 8658#if 0 8659 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ 8660 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/ 8661#endif 8662 { } /* end */ 8663}; 8664/* Set mic1 nad line-in as output and mute mixer */ 8665static struct hda_verb alc861_asus_ch6_init[] = { 8666 /* set pin widget 1Ah (line in) for output (Back Surround)*/ 8667 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8668 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */ 8669 /* set pin widget 18h (mic1) for output (CLFE)*/ 8670 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8671 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */ 8672 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8673 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8674 8675 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, 8676#if 0 8677 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ 8678 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/ 8679#endif 8680 { } /* end */ 8681}; 8682 8683static struct hda_channel_mode alc861_asus_modes[2] = { 8684 { 2, alc861_asus_ch2_init }, 8685 { 6, alc861_asus_ch6_init }, 8686}; 8687 8688/* patch-ALC861 */ 8689 8690static struct snd_kcontrol_new alc861_base_mixer[] = { 8691 /* output mixer control */ 8692 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8693 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 8694 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 8695 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 8696 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), 8697 8698 /*Input mixer control */ 8699 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 8700 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ 8701 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8702 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8703 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 8704 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 8705 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8706 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8707 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 8708 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), 8709 8710 /* Capture mixer control */ 8711 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8712 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8713 { 8714 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8715 .name = "Capture Source", 8716 .count = 1, 8717 .info = alc_mux_enum_info, 8718 .get = alc_mux_enum_get, 8719 .put = alc_mux_enum_put, 8720 }, 8721 { } /* end */ 8722}; 8723 8724static struct snd_kcontrol_new alc861_3ST_mixer[] = { 8725 /* output mixer control */ 8726 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8727 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 8728 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 8729 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 8730 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */ 8731 8732 /* Input mixer control */ 8733 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 8734 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ 8735 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8736 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8737 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 8738 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 8739 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8740 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8741 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 8742 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), 8743 8744 /* Capture mixer control */ 8745 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8746 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8747 { 8748 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8749 .name = "Capture Source", 8750 .count = 1, 8751 .info = alc_mux_enum_info, 8752 .get = alc_mux_enum_get, 8753 .put = alc_mux_enum_put, 8754 }, 8755 { 8756 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8757 .name = "Channel Mode", 8758 .info = alc_ch_mode_info, 8759 .get = alc_ch_mode_get, 8760 .put = alc_ch_mode_put, 8761 .private_value = ARRAY_SIZE(alc861_threestack_modes), 8762 }, 8763 { } /* end */ 8764}; 8765 8766static struct snd_kcontrol_new alc861_toshiba_mixer[] = { 8767 /* output mixer control */ 8768 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8769 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8770 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8771 8772 /*Capture mixer control */ 8773 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8774 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8775 { 8776 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8777 .name = "Capture Source", 8778 .count = 1, 8779 .info = alc_mux_enum_info, 8780 .get = alc_mux_enum_get, 8781 .put = alc_mux_enum_put, 8782 }, 8783 8784 { } /* end */ 8785}; 8786 8787static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { 8788 /* output mixer control */ 8789 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8790 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 8791 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 8792 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 8793 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */ 8794 8795 /* Input mixer control */ 8796 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 8797 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ 8798 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8799 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8800 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 8801 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 8802 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8803 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8804 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 8805 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), 8806 8807 /* Capture mixer control */ 8808 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8809 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8810 { 8811 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8812 .name = "Capture Source", 8813 .count = 1, 8814 .info = alc_mux_enum_info, 8815 .get = alc_mux_enum_get, 8816 .put = alc_mux_enum_put, 8817 }, 8818 { 8819 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8820 .name = "Channel Mode", 8821 .info = alc_ch_mode_info, 8822 .get = alc_ch_mode_get, 8823 .put = alc_ch_mode_put, 8824 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes), 8825 }, 8826 { } /* end */ 8827}; 8828 8829static struct snd_kcontrol_new alc861_asus_mixer[] = { 8830 /* output mixer control */ 8831 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 8832 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), 8833 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), 8834 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), 8835 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), 8836 8837 /* Input mixer control */ 8838 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), 8839 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), 8840 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8841 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8842 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), 8843 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), 8844 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), 8845 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), 8846 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), 8847 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), 8848 8849 /* Capture mixer control */ 8850 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 8851 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 8852 { 8853 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8854 .name = "Capture Source", 8855 .count = 1, 8856 .info = alc_mux_enum_info, 8857 .get = alc_mux_enum_get, 8858 .put = alc_mux_enum_put, 8859 }, 8860 { 8861 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8862 .name = "Channel Mode", 8863 .info = alc_ch_mode_info, 8864 .get = alc_ch_mode_get, 8865 .put = alc_ch_mode_put, 8866 .private_value = ARRAY_SIZE(alc861_asus_modes), 8867 }, 8868 { } 8869}; 8870 8871/* additional mixer */ 8872static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = { 8873 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), 8874 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), 8875 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT), 8876 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT), 8877 { } 8878}; 8879 8880/* 8881 * generic initialization of ADC, input mixers and output mixers 8882 */ 8883static struct hda_verb alc861_base_init_verbs[] = { 8884 /* 8885 * Unmute ADC0 and set the default input to mic-in 8886 */ 8887 /* port-A for surround (rear panel) */ 8888 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8889 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8890 /* port-B for mic-in (rear panel) with vref */ 8891 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8892 /* port-C for line-in (rear panel) */ 8893 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8894 /* port-D for Front */ 8895 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8896 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8897 /* port-E for HP out (front panel) */ 8898 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 8899 /* route front PCM to HP */ 8900 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8901 /* port-F for mic-in (front panel) with vref */ 8902 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8903 /* port-G for CLFE (rear panel) */ 8904 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8905 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8906 /* port-H for side (rear panel) */ 8907 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8908 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8909 /* CD-in */ 8910 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8911 /* route front mic to ADC1*/ 8912 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 8913 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8914 8915 /* Unmute DAC0~3 & spdif out*/ 8916 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8917 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8918 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8919 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8920 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8921 8922 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 8923 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8924 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8925 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8926 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8927 8928 /* Unmute Stereo Mixer 15 */ 8929 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8930 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8931 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 8932 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 8933 8934 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8935 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8936 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8937 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8938 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8939 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8940 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8941 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8942 /* hp used DAC 3 (Front) */ 8943 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 8944 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 8945 8946 { } 8947}; 8948 8949static struct hda_verb alc861_threestack_init_verbs[] = { 8950 /* 8951 * Unmute ADC0 and set the default input to mic-in 8952 */ 8953 /* port-A for surround (rear panel) */ 8954 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 8955 /* port-B for mic-in (rear panel) with vref */ 8956 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8957 /* port-C for line-in (rear panel) */ 8958 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8959 /* port-D for Front */ 8960 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 8961 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8962 /* port-E for HP out (front panel) */ 8963 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 8964 /* route front PCM to HP */ 8965 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 8966 /* port-F for mic-in (front panel) with vref */ 8967 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 8968 /* port-G for CLFE (rear panel) */ 8969 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 8970 /* port-H for side (rear panel) */ 8971 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 8972 /* CD-in */ 8973 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 8974 /* route front mic to ADC1*/ 8975 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 8976 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8977 /* Unmute DAC0~3 & spdif out*/ 8978 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8979 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8980 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8981 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8982 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 8983 8984 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 8985 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8986 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8987 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8988 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8989 8990 /* Unmute Stereo Mixer 15 */ 8991 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8992 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8993 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 8994 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 8995 8996 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8997 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 8998 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 8999 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9000 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9001 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9002 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9003 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9004 /* hp used DAC 3 (Front) */ 9005 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9006 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9007 { } 9008}; 9009 9010static struct hda_verb alc861_uniwill_m31_init_verbs[] = { 9011 /* 9012 * Unmute ADC0 and set the default input to mic-in 9013 */ 9014 /* port-A for surround (rear panel) */ 9015 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9016 /* port-B for mic-in (rear panel) with vref */ 9017 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9018 /* port-C for line-in (rear panel) */ 9019 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9020 /* port-D for Front */ 9021 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9022 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9023 /* port-E for HP out (front panel) */ 9024 /* this has to be set to VREF80 */ 9025 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9026 /* route front PCM to HP */ 9027 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9028 /* port-F for mic-in (front panel) with vref */ 9029 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9030 /* port-G for CLFE (rear panel) */ 9031 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9032 /* port-H for side (rear panel) */ 9033 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9034 /* CD-in */ 9035 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9036 /* route front mic to ADC1*/ 9037 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 9038 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9039 /* Unmute DAC0~3 & spdif out*/ 9040 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9041 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9042 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9043 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9044 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9045 9046 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9047 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9048 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9049 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9050 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9051 9052 /* Unmute Stereo Mixer 15 */ 9053 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9054 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9055 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9056 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 9057 9058 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9059 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9060 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9061 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9062 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9063 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9064 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9065 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9066 /* hp used DAC 3 (Front) */ 9067 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9068 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9069 { } 9070}; 9071 9072static struct hda_verb alc861_asus_init_verbs[] = { 9073 /* 9074 * Unmute ADC0 and set the default input to mic-in 9075 */ 9076 /* port-A for surround (rear panel) 9077 * according to codec#0 this is the HP jack 9078 */ 9079 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */ 9080 /* route front PCM to HP */ 9081 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 }, 9082 /* port-B for mic-in (rear panel) with vref */ 9083 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9084 /* port-C for line-in (rear panel) */ 9085 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9086 /* port-D for Front */ 9087 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9088 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9089 /* port-E for HP out (front panel) */ 9090 /* this has to be set to VREF80 */ 9091 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9092 /* route front PCM to HP */ 9093 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 9094 /* port-F for mic-in (front panel) with vref */ 9095 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 9096 /* port-G for CLFE (rear panel) */ 9097 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9098 /* port-H for side (rear panel) */ 9099 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 9100 /* CD-in */ 9101 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 9102 /* route front mic to ADC1*/ 9103 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 9104 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9105 /* Unmute DAC0~3 & spdif out*/ 9106 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9107 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9108 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9109 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9110 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9111 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9112 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9113 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9114 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9115 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9116 9117 /* Unmute Stereo Mixer 15 */ 9118 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9119 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9120 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9121 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ 9122 9123 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9124 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9125 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9126 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9127 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9128 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9129 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9130 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9131 /* hp used DAC 3 (Front) */ 9132 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9133 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9134 { } 9135}; 9136 9137/* additional init verbs for ASUS laptops */ 9138static struct hda_verb alc861_asus_laptop_init_verbs[] = { 9139 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */ 9140 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */ 9141 { } 9142}; 9143 9144/* 9145 * generic initialization of ADC, input mixers and output mixers 9146 */ 9147static struct hda_verb alc861_auto_init_verbs[] = { 9148 /* 9149 * Unmute ADC0 and set the default input to mic-in 9150 */ 9151 /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */ 9152 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9153 9154 /* Unmute DAC0~3 & spdif out*/ 9155 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9156 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9157 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9158 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 9159 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 9160 9161 /* Unmute Mixer 14 (mic) 1c (Line in)*/ 9162 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9163 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9164 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9165 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9166 9167 /* Unmute Stereo Mixer 15 */ 9168 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9169 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9170 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9171 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, 9172 9173 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9174 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9175 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9176 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9177 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9178 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9179 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 9180 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 9181 9182 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 9183 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 9184 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9185 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9186 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 9187 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 9188 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 9189 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 9190 9191 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */ 9192 9193 { } 9194}; 9195 9196static struct hda_verb alc861_toshiba_init_verbs[] = { 9197 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 9198 9199 { } 9200}; 9201 9202/* toggle speaker-output according to the hp-jack state */ 9203static void alc861_toshiba_automute(struct hda_codec *codec) 9204{ 9205 unsigned int present; 9206 9207 present = snd_hda_codec_read(codec, 0x0f, 0, 9208 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 9209 snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0, 9210 0x80, present ? 0x80 : 0); 9211 snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0, 9212 0x80, present ? 0x80 : 0); 9213 snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3, 9214 0x80, present ? 0 : 0x80); 9215 snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3, 9216 0x80, present ? 0 : 0x80); 9217} 9218 9219static void alc861_toshiba_unsol_event(struct hda_codec *codec, 9220 unsigned int res) 9221{ 9222 if ((res >> 26) == ALC880_HP_EVENT) 9223 alc861_toshiba_automute(codec); 9224} 9225 9226/* pcm configuration: identiacal with ALC880 */ 9227#define alc861_pcm_analog_playback alc880_pcm_analog_playback 9228#define alc861_pcm_analog_capture alc880_pcm_analog_capture 9229#define alc861_pcm_digital_playback alc880_pcm_digital_playback 9230#define alc861_pcm_digital_capture alc880_pcm_digital_capture 9231 9232 9233#define ALC861_DIGOUT_NID 0x07 9234 9235static struct hda_channel_mode alc861_8ch_modes[1] = { 9236 { 8, NULL } 9237}; 9238 9239static hda_nid_t alc861_dac_nids[4] = { 9240 /* front, surround, clfe, side */ 9241 0x03, 0x06, 0x05, 0x04 9242}; 9243 9244static hda_nid_t alc660_dac_nids[3] = { 9245 /* front, clfe, surround */ 9246 0x03, 0x05, 0x06 9247}; 9248 9249static hda_nid_t alc861_adc_nids[1] = { 9250 /* ADC0-2 */ 9251 0x08, 9252}; 9253 9254static struct hda_input_mux alc861_capture_source = { 9255 .num_items = 5, 9256 .items = { 9257 { "Mic", 0x0 }, 9258 { "Front Mic", 0x3 }, 9259 { "Line", 0x1 }, 9260 { "CD", 0x4 }, 9261 { "Mixer", 0x5 }, 9262 }, 9263}; 9264 9265/* fill in the dac_nids table from the parsed pin configuration */ 9266static int alc861_auto_fill_dac_nids(struct alc_spec *spec, 9267 const struct auto_pin_cfg *cfg) 9268{ 9269 int i; 9270 hda_nid_t nid; 9271 9272 spec->multiout.dac_nids = spec->private_dac_nids; 9273 for (i = 0; i < cfg->line_outs; i++) { 9274 nid = cfg->line_out_pins[i]; 9275 if (nid) { 9276 if (i >= ARRAY_SIZE(alc861_dac_nids)) 9277 continue; 9278 spec->multiout.dac_nids[i] = alc861_dac_nids[i]; 9279 } 9280 } 9281 spec->multiout.num_dacs = cfg->line_outs; 9282 return 0; 9283} 9284 9285/* add playback controls from the parsed DAC table */ 9286static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec, 9287 const struct auto_pin_cfg *cfg) 9288{ 9289 char name[32]; 9290 static const char *chname[4] = { 9291 "Front", "Surround", NULL /*CLFE*/, "Side" 9292 }; 9293 hda_nid_t nid; 9294 int i, idx, err; 9295 9296 for (i = 0; i < cfg->line_outs; i++) { 9297 nid = spec->multiout.dac_nids[i]; 9298 if (!nid) 9299 continue; 9300 if (nid == 0x05) { 9301 /* Center/LFE */ 9302 err = add_control(spec, ALC_CTL_BIND_MUTE, 9303 "Center Playback Switch", 9304 HDA_COMPOSE_AMP_VAL(nid, 1, 0, 9305 HDA_OUTPUT)); 9306 if (err < 0) 9307 return err; 9308 err = add_control(spec, ALC_CTL_BIND_MUTE, 9309 "LFE Playback Switch", 9310 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 9311 HDA_OUTPUT)); 9312 if (err < 0) 9313 return err; 9314 } else { 9315 for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; 9316 idx++) 9317 if (nid == alc861_dac_nids[idx]) 9318 break; 9319 sprintf(name, "%s Playback Switch", chname[idx]); 9320 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 9321 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 9322 HDA_OUTPUT)); 9323 if (err < 0) 9324 return err; 9325 } 9326 } 9327 return 0; 9328} 9329 9330static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) 9331{ 9332 int err; 9333 hda_nid_t nid; 9334 9335 if (!pin) 9336 return 0; 9337 9338 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) { 9339 nid = 0x03; 9340 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 9341 "Headphone Playback Switch", 9342 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 9343 if (err < 0) 9344 return err; 9345 spec->multiout.hp_nid = nid; 9346 } 9347 return 0; 9348} 9349 9350/* create playback/capture controls for input pins */ 9351static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, 9352 const struct auto_pin_cfg *cfg) 9353{ 9354 struct hda_input_mux *imux = &spec->private_imux; 9355 int i, err, idx, idx1; 9356 9357 for (i = 0; i < AUTO_PIN_LAST; i++) { 9358 switch (cfg->input_pins[i]) { 9359 case 0x0c: 9360 idx1 = 1; 9361 idx = 2; /* Line In */ 9362 break; 9363 case 0x0f: 9364 idx1 = 2; 9365 idx = 2; /* Line In */ 9366 break; 9367 case 0x0d: 9368 idx1 = 0; 9369 idx = 1; /* Mic In */ 9370 break; 9371 case 0x10: 9372 idx1 = 3; 9373 idx = 1; /* Mic In */ 9374 break; 9375 case 0x11: 9376 idx1 = 4; 9377 idx = 0; /* CD */ 9378 break; 9379 default: 9380 continue; 9381 } 9382 9383 err = new_analog_input(spec, cfg->input_pins[i], 9384 auto_pin_cfg_labels[i], idx, 0x15); 9385 if (err < 0) 9386 return err; 9387 9388 imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; 9389 imux->items[imux->num_items].index = idx1; 9390 imux->num_items++; 9391 } 9392 return 0; 9393} 9394 9395static struct snd_kcontrol_new alc861_capture_mixer[] = { 9396 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 9397 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 9398 9399 { 9400 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9401 /* The multiple "Capture Source" controls confuse alsamixer 9402 * So call somewhat different.. 9403 *FIXME: the controls appear in the "playback" view! 9404 */ 9405 /* .name = "Capture Source", */ 9406 .name = "Input Source", 9407 .count = 1, 9408 .info = alc_mux_enum_info, 9409 .get = alc_mux_enum_get, 9410 .put = alc_mux_enum_put, 9411 }, 9412 { } /* end */ 9413}; 9414 9415static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, 9416 hda_nid_t nid, 9417 int pin_type, int dac_idx) 9418{ 9419 /* set as output */ 9420 9421 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 9422 pin_type); 9423 snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, 9424 AMP_OUT_UNMUTE); 9425 9426} 9427 9428static void alc861_auto_init_multi_out(struct hda_codec *codec) 9429{ 9430 struct alc_spec *spec = codec->spec; 9431 int i; 9432 9433 alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b); 9434 for (i = 0; i < spec->autocfg.line_outs; i++) { 9435 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 9436 int pin_type = get_pin_type(spec->autocfg.line_out_type); 9437 if (nid) 9438 alc861_auto_set_output_and_unmute(codec, nid, pin_type, 9439 spec->multiout.dac_nids[i]); 9440 } 9441} 9442 9443static void alc861_auto_init_hp_out(struct hda_codec *codec) 9444{ 9445 struct alc_spec *spec = codec->spec; 9446 hda_nid_t pin; 9447 9448 pin = spec->autocfg.hp_pins[0]; 9449 if (pin) /* connect to front */ 9450 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, 9451 spec->multiout.dac_nids[0]); 9452} 9453 9454static void alc861_auto_init_analog_input(struct hda_codec *codec) 9455{ 9456 struct alc_spec *spec = codec->spec; 9457 int i; 9458 9459 for (i = 0; i < AUTO_PIN_LAST; i++) { 9460 hda_nid_t nid = spec->autocfg.input_pins[i]; 9461 if (nid >= 0x0c && nid <= 0x11) { 9462 snd_hda_codec_write(codec, nid, 0, 9463 AC_VERB_SET_PIN_WIDGET_CONTROL, 9464 i <= AUTO_PIN_FRONT_MIC ? 9465 PIN_VREF80 : PIN_IN); 9466 } 9467 } 9468} 9469 9470/* parse the BIOS configuration and set up the alc_spec */ 9471/* return 1 if successful, 0 if the proper config is not found, 9472 * or a negative error code 9473 */ 9474static int alc861_parse_auto_config(struct hda_codec *codec) 9475{ 9476 struct alc_spec *spec = codec->spec; 9477 int err; 9478 static hda_nid_t alc861_ignore[] = { 0x1d, 0 }; 9479 9480 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 9481 alc861_ignore); 9482 if (err < 0) 9483 return err; 9484 if (!spec->autocfg.line_outs) 9485 return 0; /* can't find valid BIOS pin config */ 9486 9487 err = alc861_auto_fill_dac_nids(spec, &spec->autocfg); 9488 if (err < 0) 9489 return err; 9490 err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg); 9491 if (err < 0) 9492 return err; 9493 err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 9494 if (err < 0) 9495 return err; 9496 err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg); 9497 if (err < 0) 9498 return err; 9499 9500 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 9501 9502 if (spec->autocfg.dig_out_pin) 9503 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; 9504 9505 if (spec->kctl_alloc) 9506 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 9507 9508 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; 9509 9510 spec->num_mux_defs = 1; 9511 spec->input_mux = &spec->private_imux; 9512 9513 spec->adc_nids = alc861_adc_nids; 9514 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); 9515 spec->mixers[spec->num_mixers] = alc861_capture_mixer; 9516 spec->num_mixers++; 9517 9518 return 1; 9519} 9520 9521/* additional initialization for auto-configuration model */ 9522static void alc861_auto_init(struct hda_codec *codec) 9523{ 9524 alc861_auto_init_multi_out(codec); 9525 alc861_auto_init_hp_out(codec); 9526 alc861_auto_init_analog_input(codec); 9527} 9528 9529 9530/* 9531 * configuration and preset 9532 */ 9533static const char *alc861_models[ALC861_MODEL_LAST] = { 9534 [ALC861_3ST] = "3stack", 9535 [ALC660_3ST] = "3stack-660", 9536 [ALC861_3ST_DIG] = "3stack-dig", 9537 [ALC861_6ST_DIG] = "6stack-dig", 9538 [ALC861_UNIWILL_M31] = "uniwill-m31", 9539 [ALC861_TOSHIBA] = "toshiba", 9540 [ALC861_ASUS] = "asus", 9541 [ALC861_ASUS_LAPTOP] = "asus-laptop", 9542 [ALC861_AUTO] = "auto", 9543}; 9544 9545static struct snd_pci_quirk alc861_cfg_tbl[] = { 9546 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST), 9547 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP), 9548 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP), 9549 SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP), 9550 SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP), 9551 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS), 9552 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG), 9553 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA), 9554 /* FIXME: the entry below breaks Toshiba A100 (model=auto works!) 9555 * Any other models that need this preset? 9556 */ 9557 /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */ 9558 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31), 9559 SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), 9560 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31), 9561 SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST), 9562 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST), 9563 {} 9564}; 9565 9566static struct alc_config_preset alc861_presets[] = { 9567 [ALC861_3ST] = { 9568 .mixers = { alc861_3ST_mixer }, 9569 .init_verbs = { alc861_threestack_init_verbs }, 9570 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9571 .dac_nids = alc861_dac_nids, 9572 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), 9573 .channel_mode = alc861_threestack_modes, 9574 .need_dac_fix = 1, 9575 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9576 .adc_nids = alc861_adc_nids, 9577 .input_mux = &alc861_capture_source, 9578 }, 9579 [ALC861_3ST_DIG] = { 9580 .mixers = { alc861_base_mixer }, 9581 .init_verbs = { alc861_threestack_init_verbs }, 9582 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9583 .dac_nids = alc861_dac_nids, 9584 .dig_out_nid = ALC861_DIGOUT_NID, 9585 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), 9586 .channel_mode = alc861_threestack_modes, 9587 .need_dac_fix = 1, 9588 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9589 .adc_nids = alc861_adc_nids, 9590 .input_mux = &alc861_capture_source, 9591 }, 9592 [ALC861_6ST_DIG] = { 9593 .mixers = { alc861_base_mixer }, 9594 .init_verbs = { alc861_base_init_verbs }, 9595 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9596 .dac_nids = alc861_dac_nids, 9597 .dig_out_nid = ALC861_DIGOUT_NID, 9598 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes), 9599 .channel_mode = alc861_8ch_modes, 9600 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9601 .adc_nids = alc861_adc_nids, 9602 .input_mux = &alc861_capture_source, 9603 }, 9604 [ALC660_3ST] = { 9605 .mixers = { alc861_3ST_mixer }, 9606 .init_verbs = { alc861_threestack_init_verbs }, 9607 .num_dacs = ARRAY_SIZE(alc660_dac_nids), 9608 .dac_nids = alc660_dac_nids, 9609 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), 9610 .channel_mode = alc861_threestack_modes, 9611 .need_dac_fix = 1, 9612 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9613 .adc_nids = alc861_adc_nids, 9614 .input_mux = &alc861_capture_source, 9615 }, 9616 [ALC861_UNIWILL_M31] = { 9617 .mixers = { alc861_uniwill_m31_mixer }, 9618 .init_verbs = { alc861_uniwill_m31_init_verbs }, 9619 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9620 .dac_nids = alc861_dac_nids, 9621 .dig_out_nid = ALC861_DIGOUT_NID, 9622 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes), 9623 .channel_mode = alc861_uniwill_m31_modes, 9624 .need_dac_fix = 1, 9625 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9626 .adc_nids = alc861_adc_nids, 9627 .input_mux = &alc861_capture_source, 9628 }, 9629 [ALC861_TOSHIBA] = { 9630 .mixers = { alc861_toshiba_mixer }, 9631 .init_verbs = { alc861_base_init_verbs, 9632 alc861_toshiba_init_verbs }, 9633 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9634 .dac_nids = alc861_dac_nids, 9635 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 9636 .channel_mode = alc883_3ST_2ch_modes, 9637 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9638 .adc_nids = alc861_adc_nids, 9639 .input_mux = &alc861_capture_source, 9640 .unsol_event = alc861_toshiba_unsol_event, 9641 .init_hook = alc861_toshiba_automute, 9642 }, 9643 [ALC861_ASUS] = { 9644 .mixers = { alc861_asus_mixer }, 9645 .init_verbs = { alc861_asus_init_verbs }, 9646 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9647 .dac_nids = alc861_dac_nids, 9648 .dig_out_nid = ALC861_DIGOUT_NID, 9649 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes), 9650 .channel_mode = alc861_asus_modes, 9651 .need_dac_fix = 1, 9652 .hp_nid = 0x06, 9653 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9654 .adc_nids = alc861_adc_nids, 9655 .input_mux = &alc861_capture_source, 9656 }, 9657 [ALC861_ASUS_LAPTOP] = { 9658 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer }, 9659 .init_verbs = { alc861_asus_init_verbs, 9660 alc861_asus_laptop_init_verbs }, 9661 .num_dacs = ARRAY_SIZE(alc861_dac_nids), 9662 .dac_nids = alc861_dac_nids, 9663 .dig_out_nid = ALC861_DIGOUT_NID, 9664 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 9665 .channel_mode = alc883_3ST_2ch_modes, 9666 .need_dac_fix = 1, 9667 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), 9668 .adc_nids = alc861_adc_nids, 9669 .input_mux = &alc861_capture_source, 9670 }, 9671}; 9672 9673 9674static int patch_alc861(struct hda_codec *codec) 9675{ 9676 struct alc_spec *spec; 9677 int board_config; 9678 int err; 9679 9680 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 9681 if (spec == NULL) 9682 return -ENOMEM; 9683 9684 codec->spec = spec; 9685 9686 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST, 9687 alc861_models, 9688 alc861_cfg_tbl); 9689 9690 if (board_config < 0) { 9691 printk(KERN_INFO "hda_codec: Unknown model for ALC861, " 9692 "trying auto-probe from BIOS...\n"); 9693 board_config = ALC861_AUTO; 9694 } 9695 9696 if (board_config == ALC861_AUTO) { 9697 /* automatic parse from the BIOS config */ 9698 err = alc861_parse_auto_config(codec); 9699 if (err < 0) { 9700 alc_free(codec); 9701 return err; 9702 } else if (!err) { 9703 printk(KERN_INFO 9704 "hda_codec: Cannot set up configuration " 9705 "from BIOS. Using base mode...\n"); 9706 board_config = ALC861_3ST_DIG; 9707 } 9708 } 9709 9710 if (board_config != ALC861_AUTO) 9711 setup_preset(spec, &alc861_presets[board_config]); 9712 9713 spec->stream_name_analog = "ALC861 Analog"; 9714 spec->stream_analog_playback = &alc861_pcm_analog_playback; 9715 spec->stream_analog_capture = &alc861_pcm_analog_capture; 9716 9717 spec->stream_name_digital = "ALC861 Digital"; 9718 spec->stream_digital_playback = &alc861_pcm_digital_playback; 9719 spec->stream_digital_capture = &alc861_pcm_digital_capture; 9720 9721 codec->patch_ops = alc_patch_ops; 9722 if (board_config == ALC861_AUTO) 9723 spec->init_hook = alc861_auto_init; 9724 9725 return 0; 9726} 9727 9728/* 9729 * ALC861-VD support 9730 * 9731 * Based on ALC882 9732 * 9733 * In addition, an independent DAC 9734 */ 9735#define ALC861VD_DIGOUT_NID 0x06 9736 9737static hda_nid_t alc861vd_dac_nids[4] = { 9738 /* front, surr, clfe, side surr */ 9739 0x02, 0x03, 0x04, 0x05 9740}; 9741 9742/* dac_nids for ALC660vd are in a different order - according to 9743 * Realtek's driver. 9744 * This should probably tesult in a different mixer for 6stack models 9745 * of ALC660vd codecs, but for now there is only 3stack mixer 9746 * - and it is the same as in 861vd. 9747 * adc_nids in ALC660vd are (is) the same as in 861vd 9748 */ 9749static hda_nid_t alc660vd_dac_nids[3] = { 9750 /* front, rear, clfe, rear_surr */ 9751 0x02, 0x04, 0x03 9752}; 9753 9754static hda_nid_t alc861vd_adc_nids[1] = { 9755 /* ADC0 */ 9756 0x09, 9757}; 9758 9759/* input MUX */ 9760/* FIXME: should be a matrix-type input source selection */ 9761static struct hda_input_mux alc861vd_capture_source = { 9762 .num_items = 4, 9763 .items = { 9764 { "Mic", 0x0 }, 9765 { "Front Mic", 0x1 }, 9766 { "Line", 0x2 }, 9767 { "CD", 0x4 }, 9768 }, 9769}; 9770 9771static struct hda_input_mux alc861vd_dallas_capture_source = { 9772 .num_items = 3, 9773 .items = { 9774 { "Front Mic", 0x0 }, 9775 { "ATAPI Mic", 0x1 }, 9776 { "Line In", 0x5 }, 9777 }, 9778}; 9779 9780#define alc861vd_mux_enum_info alc_mux_enum_info 9781#define alc861vd_mux_enum_get alc_mux_enum_get 9782 9783static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol, 9784 struct snd_ctl_elem_value *ucontrol) 9785{ 9786 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 9787 struct alc_spec *spec = codec->spec; 9788 const struct hda_input_mux *imux = spec->input_mux; 9789 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 9790 static hda_nid_t capture_mixers[1] = { 0x22 }; 9791 hda_nid_t nid = capture_mixers[adc_idx]; 9792 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 9793 unsigned int i, idx; 9794 9795 idx = ucontrol->value.enumerated.item[0]; 9796 if (idx >= imux->num_items) 9797 idx = imux->num_items - 1; 9798 if (*cur_val == idx && !codec->in_resume) 9799 return 0; 9800 for (i = 0; i < imux->num_items; i++) { 9801 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 9802 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 9803 v | (imux->items[i].index << 8)); 9804 } 9805 *cur_val = idx; 9806 return 1; 9807} 9808 9809/* 9810 * 2ch mode 9811 */ 9812static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = { 9813 { 2, NULL } 9814}; 9815 9816/* 9817 * 6ch mode 9818 */ 9819static struct hda_verb alc861vd_6stack_ch6_init[] = { 9820 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 9821 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9822 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9823 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9824 { } /* end */ 9825}; 9826 9827/* 9828 * 8ch mode 9829 */ 9830static struct hda_verb alc861vd_6stack_ch8_init[] = { 9831 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9832 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9833 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9834 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 9835 { } /* end */ 9836}; 9837 9838static struct hda_channel_mode alc861vd_6stack_modes[2] = { 9839 { 6, alc861vd_6stack_ch6_init }, 9840 { 8, alc861vd_6stack_ch8_init }, 9841}; 9842 9843static struct snd_kcontrol_new alc861vd_chmode_mixer[] = { 9844 { 9845 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9846 .name = "Channel Mode", 9847 .info = alc_ch_mode_info, 9848 .get = alc_ch_mode_get, 9849 .put = alc_ch_mode_put, 9850 }, 9851 { } /* end */ 9852}; 9853 9854static struct snd_kcontrol_new alc861vd_capture_mixer[] = { 9855 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 9856 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 9857 9858 { 9859 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9860 /* The multiple "Capture Source" controls confuse alsamixer 9861 * So call somewhat different.. 9862 *FIXME: the controls appear in the "playback" view! 9863 */ 9864 /* .name = "Capture Source", */ 9865 .name = "Input Source", 9866 .count = 1, 9867 .info = alc861vd_mux_enum_info, 9868 .get = alc861vd_mux_enum_get, 9869 .put = alc861vd_mux_enum_put, 9870 }, 9871 { } /* end */ 9872}; 9873 9874/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 9875 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 9876 */ 9877static struct snd_kcontrol_new alc861vd_6st_mixer[] = { 9878 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 9879 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 9880 9881 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), 9882 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 9883 9884 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, 9885 HDA_OUTPUT), 9886 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, 9887 HDA_OUTPUT), 9888 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 9889 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 9890 9891 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT), 9892 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 9893 9894 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 9895 9896 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 9897 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 9898 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 9899 9900 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 9901 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 9902 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 9903 9904 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 9905 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 9906 9907 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 9908 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 9909 9910 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 9911 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 9912 9913 { } /* end */ 9914}; 9915 9916static struct snd_kcontrol_new alc861vd_3st_mixer[] = { 9917 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 9918 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 9919 9920 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 9921 9922 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 9923 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 9924 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 9925 9926 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 9927 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 9928 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 9929 9930 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 9931 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 9932 9933 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 9934 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 9935 9936 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 9937 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 9938 9939 { } /* end */ 9940}; 9941 9942static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = { 9943 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 9944 /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/ 9945 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), 9946 9947 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 9948 9949 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), 9950 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 9951 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 9952 9953 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), 9954 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 9955 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 9956 9957 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 9958 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 9959 9960 { } /* end */ 9961}; 9962 9963/* Pin assignment: Front=0x14, HP = 0x15, 9964 * Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d 9965 */ 9966static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { 9967 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 9968 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 9969 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 9970 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), 9971 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 9972 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 9973 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 9974 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 9975 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT), 9976 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT), 9977 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 9978 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 9979 { 9980 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 9981 /* .name = "Capture Source", */ 9982 .name = "Input Source", 9983 .count = 1, 9984 .info = alc882_mux_enum_info, 9985 .get = alc882_mux_enum_get, 9986 .put = alc882_mux_enum_put, 9987 }, 9988 { } /* end */ 9989}; 9990 9991/* 9992 * generic initialization of ADC, input mixers and output mixers 9993 */ 9994static struct hda_verb alc861vd_volume_init_verbs[] = { 9995 /* 9996 * Unmute ADC0 and set the default input to mic-in 9997 */ 9998 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 9999 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10000 10001 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of 10002 * the analog-loopback mixer widget 10003 */ 10004 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 10005 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10006 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10007 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 10008 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 10009 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 10010 10011 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ 10012 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10013 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10014 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 10015 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 10016 10017 /* 10018 * Set up output mixers (0x02 - 0x05) 10019 */ 10020 /* set vol=0 to output mixers */ 10021 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10022 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10023 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10024 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10025 10026 /* set up input amps for analog loopback */ 10027 /* Amp Indices: DAC = 0, mixer = 1 */ 10028 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10029 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10030 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10031 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10032 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10033 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10034 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10035 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10036 10037 { } 10038}; 10039 10040/* 10041 * 3-stack pin configuration: 10042 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b 10043 */ 10044static struct hda_verb alc861vd_3stack_init_verbs[] = { 10045 /* 10046 * Set pin mode and muting 10047 */ 10048 /* set front pin widgets 0x14 for output */ 10049 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10050 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10051 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 10052 10053 /* Mic (rear) pin: input vref at 80% */ 10054 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10055 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10056 /* Front Mic pin: input vref at 80% */ 10057 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10058 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10059 /* Line In pin: input */ 10060 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10061 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10062 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 10063 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 10064 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10065 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 10066 /* CD pin widget for input */ 10067 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10068 10069 { } 10070}; 10071 10072/* 10073 * 6-stack pin configuration: 10074 */ 10075static struct hda_verb alc861vd_6stack_init_verbs[] = { 10076 /* 10077 * Set pin mode and muting 10078 */ 10079 /* set front pin widgets 0x14 for output */ 10080 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10081 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10082 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 10083 10084 /* Rear Pin: output 1 (0x0d) */ 10085 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10086 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10087 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 10088 /* CLFE Pin: output 2 (0x0e) */ 10089 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10090 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10091 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, 10092 /* Side Pin: output 3 (0x0f) */ 10093 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10094 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10095 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, 10096 10097 /* Mic (rear) pin: input vref at 80% */ 10098 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10099 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10100 /* Front Mic pin: input vref at 80% */ 10101 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10102 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10103 /* Line In pin: input */ 10104 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10105 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10106 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 10107 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 10108 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10109 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 10110 /* CD pin widget for input */ 10111 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10112 10113 { } 10114}; 10115 10116static struct hda_verb alc861vd_eapd_verbs[] = { 10117 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, 10118 { } 10119}; 10120 10121static struct hda_verb alc861vd_lenovo_unsol_verbs[] = { 10122 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10123 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10124 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 10125 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 10126 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, 10127 {} 10128}; 10129 10130/* toggle speaker-output according to the hp-jack state */ 10131static void alc861vd_lenovo_hp_automute(struct hda_codec *codec) 10132{ 10133 unsigned int present; 10134 unsigned char bits; 10135 10136 present = snd_hda_codec_read(codec, 0x1b, 0, 10137 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 10138 bits = present ? 0x80 : 0; 10139 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 10140 0x80, bits); 10141 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 10142 0x80, bits); 10143} 10144 10145static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) 10146{ 10147 unsigned int present; 10148 unsigned char bits; 10149 10150 present = snd_hda_codec_read(codec, 0x18, 0, 10151 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 10152 bits = present ? 0x80 : 0; 10153 snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, 10154 0x80, bits); 10155 snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, 10156 0x80, bits); 10157} 10158 10159static void alc861vd_lenovo_automute(struct hda_codec *codec) 10160{ 10161 alc861vd_lenovo_hp_automute(codec); 10162 alc861vd_lenovo_mic_automute(codec); 10163} 10164 10165static void alc861vd_lenovo_unsol_event(struct hda_codec *codec, 10166 unsigned int res) 10167{ 10168 switch (res >> 26) { 10169 case ALC880_HP_EVENT: 10170 alc861vd_lenovo_hp_automute(codec); 10171 break; 10172 case ALC880_MIC_EVENT: 10173 alc861vd_lenovo_mic_automute(codec); 10174 break; 10175 } 10176} 10177 10178static struct hda_verb alc861vd_dallas_verbs[] = { 10179 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10180 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10181 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10182 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 10183 10184 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10185 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10186 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10187 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10188 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10189 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10190 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10191 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 10192 10193 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10194 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10195 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10196 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10197 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10198 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10199 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10200 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10201 10202 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, 10203 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10204 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, 10205 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10206 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10207 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10208 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10209 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10210 10211 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10212 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 10213 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 10214 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 10215 10216 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10217 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 10218 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, 10219 10220 { } /* end */ 10221}; 10222 10223/* toggle speaker-output according to the hp-jack state */ 10224static void alc861vd_dallas_automute(struct hda_codec *codec) 10225{ 10226 unsigned int present; 10227 10228 present = snd_hda_codec_read(codec, 0x15, 0, 10229 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 10230 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 10231 0x80, present ? 0x80 : 0); 10232 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 10233 0x80, present ? 0x80 : 0); 10234} 10235 10236static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res) 10237{ 10238 if ((res >> 26) == ALC880_HP_EVENT) 10239 alc861vd_dallas_automute(codec); 10240} 10241 10242/* pcm configuration: identiacal with ALC880 */ 10243#define alc861vd_pcm_analog_playback alc880_pcm_analog_playback 10244#define alc861vd_pcm_analog_capture alc880_pcm_analog_capture 10245#define alc861vd_pcm_digital_playback alc880_pcm_digital_playback 10246#define alc861vd_pcm_digital_capture alc880_pcm_digital_capture 10247 10248/* 10249 * configuration and preset 10250 */ 10251static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { 10252 [ALC660VD_3ST] = "3stack-660", 10253 [ALC660VD_3ST_DIG]= "3stack-660-digout", 10254 [ALC861VD_3ST] = "3stack", 10255 [ALC861VD_3ST_DIG] = "3stack-digout", 10256 [ALC861VD_6ST_DIG] = "6stack-digout", 10257 [ALC861VD_LENOVO] = "lenovo", 10258 [ALC861VD_DALLAS] = "dallas", 10259 [ALC861VD_AUTO] = "auto", 10260}; 10261 10262static struct snd_pci_quirk alc861vd_cfg_tbl[] = { 10263 SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), 10264 SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), 10265 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG), 10266 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), 10267 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), 10268 10269 SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS), 10270 SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), 10271 SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), 10272 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), 10273 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), 10274 {} 10275}; 10276 10277static struct alc_config_preset alc861vd_presets[] = { 10278 [ALC660VD_3ST] = { 10279 .mixers = { alc861vd_3st_mixer }, 10280 .init_verbs = { alc861vd_volume_init_verbs, 10281 alc861vd_3stack_init_verbs }, 10282 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), 10283 .dac_nids = alc660vd_dac_nids, 10284 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10285 .adc_nids = alc861vd_adc_nids, 10286 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10287 .channel_mode = alc861vd_3stack_2ch_modes, 10288 .input_mux = &alc861vd_capture_source, 10289 }, 10290 [ALC660VD_3ST_DIG] = { 10291 .mixers = { alc861vd_3st_mixer }, 10292 .init_verbs = { alc861vd_volume_init_verbs, 10293 alc861vd_3stack_init_verbs }, 10294 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), 10295 .dac_nids = alc660vd_dac_nids, 10296 .dig_out_nid = ALC861VD_DIGOUT_NID, 10297 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10298 .adc_nids = alc861vd_adc_nids, 10299 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10300 .channel_mode = alc861vd_3stack_2ch_modes, 10301 .input_mux = &alc861vd_capture_source, 10302 }, 10303 [ALC861VD_3ST] = { 10304 .mixers = { alc861vd_3st_mixer }, 10305 .init_verbs = { alc861vd_volume_init_verbs, 10306 alc861vd_3stack_init_verbs }, 10307 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10308 .dac_nids = alc861vd_dac_nids, 10309 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10310 .channel_mode = alc861vd_3stack_2ch_modes, 10311 .input_mux = &alc861vd_capture_source, 10312 }, 10313 [ALC861VD_3ST_DIG] = { 10314 .mixers = { alc861vd_3st_mixer }, 10315 .init_verbs = { alc861vd_volume_init_verbs, 10316 alc861vd_3stack_init_verbs }, 10317 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10318 .dac_nids = alc861vd_dac_nids, 10319 .dig_out_nid = ALC861VD_DIGOUT_NID, 10320 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10321 .channel_mode = alc861vd_3stack_2ch_modes, 10322 .input_mux = &alc861vd_capture_source, 10323 }, 10324 [ALC861VD_6ST_DIG] = { 10325 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer }, 10326 .init_verbs = { alc861vd_volume_init_verbs, 10327 alc861vd_6stack_init_verbs }, 10328 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10329 .dac_nids = alc861vd_dac_nids, 10330 .dig_out_nid = ALC861VD_DIGOUT_NID, 10331 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes), 10332 .channel_mode = alc861vd_6stack_modes, 10333 .input_mux = &alc861vd_capture_source, 10334 }, 10335 [ALC861VD_LENOVO] = { 10336 .mixers = { alc861vd_lenovo_mixer }, 10337 .init_verbs = { alc861vd_volume_init_verbs, 10338 alc861vd_3stack_init_verbs, 10339 alc861vd_eapd_verbs, 10340 alc861vd_lenovo_unsol_verbs }, 10341 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), 10342 .dac_nids = alc660vd_dac_nids, 10343 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10344 .adc_nids = alc861vd_adc_nids, 10345 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10346 .channel_mode = alc861vd_3stack_2ch_modes, 10347 .input_mux = &alc861vd_capture_source, 10348 .unsol_event = alc861vd_lenovo_unsol_event, 10349 .init_hook = alc861vd_lenovo_automute, 10350 }, 10351 [ALC861VD_DALLAS] = { 10352 .mixers = { alc861vd_dallas_mixer }, 10353 .init_verbs = { alc861vd_dallas_verbs }, 10354 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), 10355 .dac_nids = alc861vd_dac_nids, 10356 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), 10357 .adc_nids = alc861vd_adc_nids, 10358 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), 10359 .channel_mode = alc861vd_3stack_2ch_modes, 10360 .input_mux = &alc861vd_dallas_capture_source, 10361 .unsol_event = alc861vd_dallas_unsol_event, 10362 .init_hook = alc861vd_dallas_automute, 10363 }, 10364}; 10365 10366/* 10367 * BIOS auto configuration 10368 */ 10369static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec, 10370 hda_nid_t nid, int pin_type, int dac_idx) 10371{ 10372 /* set as output */ 10373 snd_hda_codec_write(codec, nid, 0, 10374 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); 10375 snd_hda_codec_write(codec, nid, 0, 10376 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 10377} 10378 10379static void alc861vd_auto_init_multi_out(struct hda_codec *codec) 10380{ 10381 struct alc_spec *spec = codec->spec; 10382 int i; 10383 10384 alc_subsystem_id(codec, 0x15, 0x1b, 0x14); 10385 for (i = 0; i <= HDA_SIDE; i++) { 10386 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 10387 int pin_type = get_pin_type(spec->autocfg.line_out_type); 10388 if (nid) 10389 alc861vd_auto_set_output_and_unmute(codec, nid, 10390 pin_type, i); 10391 } 10392} 10393 10394 10395static void alc861vd_auto_init_hp_out(struct hda_codec *codec) 10396{ 10397 struct alc_spec *spec = codec->spec; 10398 hda_nid_t pin; 10399 10400 pin = spec->autocfg.hp_pins[0]; 10401 if (pin) /* connect to front and use dac 0 */ 10402 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 10403} 10404 10405#define alc861vd_is_input_pin(nid) alc880_is_input_pin(nid) 10406#define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID 10407 10408static void alc861vd_auto_init_analog_input(struct hda_codec *codec) 10409{ 10410 struct alc_spec *spec = codec->spec; 10411 int i; 10412 10413 for (i = 0; i < AUTO_PIN_LAST; i++) { 10414 hda_nid_t nid = spec->autocfg.input_pins[i]; 10415 if (alc861vd_is_input_pin(nid)) { 10416 snd_hda_codec_write(codec, nid, 0, 10417 AC_VERB_SET_PIN_WIDGET_CONTROL, 10418 i <= AUTO_PIN_FRONT_MIC ? 10419 PIN_VREF80 : PIN_IN); 10420 if (nid != ALC861VD_PIN_CD_NID) 10421 snd_hda_codec_write(codec, nid, 0, 10422 AC_VERB_SET_AMP_GAIN_MUTE, 10423 AMP_OUT_MUTE); 10424 } 10425 } 10426} 10427 10428#define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02) 10429#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c) 10430 10431/* add playback controls from the parsed DAC table */ 10432/* Based on ALC880 version. But ALC861VD has separate, 10433 * different NIDs for mute/unmute switch and volume control */ 10434static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, 10435 const struct auto_pin_cfg *cfg) 10436{ 10437 char name[32]; 10438 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"}; 10439 hda_nid_t nid_v, nid_s; 10440 int i, err; 10441 10442 for (i = 0; i < cfg->line_outs; i++) { 10443 if (!spec->multiout.dac_nids[i]) 10444 continue; 10445 nid_v = alc861vd_idx_to_mixer_vol( 10446 alc880_dac_to_idx( 10447 spec->multiout.dac_nids[i])); 10448 nid_s = alc861vd_idx_to_mixer_switch( 10449 alc880_dac_to_idx( 10450 spec->multiout.dac_nids[i])); 10451 10452 if (i == 2) { 10453 /* Center/LFE */ 10454 err = add_control(spec, ALC_CTL_WIDGET_VOL, 10455 "Center Playback Volume", 10456 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0, 10457 HDA_OUTPUT)); 10458 if (err < 0) 10459 return err; 10460 err = add_control(spec, ALC_CTL_WIDGET_VOL, 10461 "LFE Playback Volume", 10462 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0, 10463 HDA_OUTPUT)); 10464 if (err < 0) 10465 return err; 10466 err = add_control(spec, ALC_CTL_BIND_MUTE, 10467 "Center Playback Switch", 10468 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2, 10469 HDA_INPUT)); 10470 if (err < 0) 10471 return err; 10472 err = add_control(spec, ALC_CTL_BIND_MUTE, 10473 "LFE Playback Switch", 10474 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2, 10475 HDA_INPUT)); 10476 if (err < 0) 10477 return err; 10478 } else { 10479 sprintf(name, "%s Playback Volume", chname[i]); 10480 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 10481 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, 10482 HDA_OUTPUT)); 10483 if (err < 0) 10484 return err; 10485 sprintf(name, "%s Playback Switch", chname[i]); 10486 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 10487 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, 10488 HDA_INPUT)); 10489 if (err < 0) 10490 return err; 10491 } 10492 } 10493 return 0; 10494} 10495 10496/* add playback controls for speaker and HP outputs */ 10497/* Based on ALC880 version. But ALC861VD has separate, 10498 * different NIDs for mute/unmute switch and volume control */ 10499static int alc861vd_auto_create_extra_out(struct alc_spec *spec, 10500 hda_nid_t pin, const char *pfx) 10501{ 10502 hda_nid_t nid_v, nid_s; 10503 int err; 10504 char name[32]; 10505 10506 if (!pin) 10507 return 0; 10508 10509 if (alc880_is_fixed_pin(pin)) { 10510 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 10511 /* specify the DAC as the extra output */ 10512 if (!spec->multiout.hp_nid) 10513 spec->multiout.hp_nid = nid_v; 10514 else 10515 spec->multiout.extra_out_nid[0] = nid_v; 10516 /* control HP volume/switch on the output mixer amp */ 10517 nid_v = alc861vd_idx_to_mixer_vol( 10518 alc880_fixed_pin_idx(pin)); 10519 nid_s = alc861vd_idx_to_mixer_switch( 10520 alc880_fixed_pin_idx(pin)); 10521 10522 sprintf(name, "%s Playback Volume", pfx); 10523 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 10524 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT)); 10525 if (err < 0) 10526 return err; 10527 sprintf(name, "%s Playback Switch", pfx); 10528 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 10529 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT)); 10530 if (err < 0) 10531 return err; 10532 } else if (alc880_is_multi_pin(pin)) { 10533 /* set manual connection */ 10534 /* we have only a switch on HP-out PIN */ 10535 sprintf(name, "%s Playback Switch", pfx); 10536 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 10537 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 10538 if (err < 0) 10539 return err; 10540 } 10541 return 0; 10542} 10543 10544/* parse the BIOS configuration and set up the alc_spec 10545 * return 1 if successful, 0 if the proper config is not found, 10546 * or a negative error code 10547 * Based on ALC880 version - had to change it to override 10548 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */ 10549static int alc861vd_parse_auto_config(struct hda_codec *codec) 10550{ 10551 struct alc_spec *spec = codec->spec; 10552 int err; 10553 static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; 10554 10555 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 10556 alc861vd_ignore); 10557 if (err < 0) 10558 return err; 10559 if (!spec->autocfg.line_outs) 10560 return 0; /* can't find valid BIOS pin config */ 10561 10562 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 10563 if (err < 0) 10564 return err; 10565 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg); 10566 if (err < 0) 10567 return err; 10568 err = alc861vd_auto_create_extra_out(spec, 10569 spec->autocfg.speaker_pins[0], 10570 "Speaker"); 10571 if (err < 0) 10572 return err; 10573 err = alc861vd_auto_create_extra_out(spec, 10574 spec->autocfg.hp_pins[0], 10575 "Headphone"); 10576 if (err < 0) 10577 return err; 10578 err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg); 10579 if (err < 0) 10580 return err; 10581 10582 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 10583 10584 if (spec->autocfg.dig_out_pin) 10585 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; 10586 10587 if (spec->kctl_alloc) 10588 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 10589 10590 spec->init_verbs[spec->num_init_verbs++] 10591 = alc861vd_volume_init_verbs; 10592 10593 spec->num_mux_defs = 1; 10594 spec->input_mux = &spec->private_imux; 10595 10596 return 1; 10597} 10598 10599/* additional initialization for auto-configuration model */ 10600static void alc861vd_auto_init(struct hda_codec *codec) 10601{ 10602 alc861vd_auto_init_multi_out(codec); 10603 alc861vd_auto_init_hp_out(codec); 10604 alc861vd_auto_init_analog_input(codec); 10605} 10606 10607static int patch_alc861vd(struct hda_codec *codec) 10608{ 10609 struct alc_spec *spec; 10610 int err, board_config; 10611 10612 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 10613 if (spec == NULL) 10614 return -ENOMEM; 10615 10616 codec->spec = spec; 10617 10618 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST, 10619 alc861vd_models, 10620 alc861vd_cfg_tbl); 10621 10622 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) { 10623 printk(KERN_INFO "hda_codec: Unknown model for ALC660VD/" 10624 "ALC861VD, trying auto-probe from BIOS...\n"); 10625 board_config = ALC861VD_AUTO; 10626 } 10627 10628 if (board_config == ALC861VD_AUTO) { 10629 /* automatic parse from the BIOS config */ 10630 err = alc861vd_parse_auto_config(codec); 10631 if (err < 0) { 10632 alc_free(codec); 10633 return err; 10634 } else if (!err) { 10635 printk(KERN_INFO 10636 "hda_codec: Cannot set up configuration " 10637 "from BIOS. Using base mode...\n"); 10638 board_config = ALC861VD_3ST; 10639 } 10640 } 10641 10642 if (board_config != ALC861VD_AUTO) 10643 setup_preset(spec, &alc861vd_presets[board_config]); 10644 10645 spec->stream_name_analog = "ALC861VD Analog"; 10646 spec->stream_analog_playback = &alc861vd_pcm_analog_playback; 10647 spec->stream_analog_capture = &alc861vd_pcm_analog_capture; 10648 10649 spec->stream_name_digital = "ALC861VD Digital"; 10650 spec->stream_digital_playback = &alc861vd_pcm_digital_playback; 10651 spec->stream_digital_capture = &alc861vd_pcm_digital_capture; 10652 10653 spec->adc_nids = alc861vd_adc_nids; 10654 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); 10655 10656 spec->mixers[spec->num_mixers] = alc861vd_capture_mixer; 10657 spec->num_mixers++; 10658 10659 codec->patch_ops = alc_patch_ops; 10660 10661 if (board_config == ALC861VD_AUTO) 10662 spec->init_hook = alc861vd_auto_init; 10663 10664 return 0; 10665} 10666 10667/* 10668 * ALC662 support 10669 * 10670 * ALC662 is almost identical with ALC880 but has cleaner and more flexible 10671 * configuration. Each pin widget can choose any input DACs and a mixer. 10672 * Each ADC is connected from a mixer of all inputs. This makes possible 10673 * 6-channel independent captures. 10674 * 10675 * In addition, an independent DAC for the multi-playback (not used in this 10676 * driver yet). 10677 */ 10678#define ALC662_DIGOUT_NID 0x06 10679#define ALC662_DIGIN_NID 0x0a 10680 10681static hda_nid_t alc662_dac_nids[4] = { 10682 /* front, rear, clfe, rear_surr */ 10683 0x02, 0x03, 0x04 10684}; 10685 10686static hda_nid_t alc662_adc_nids[1] = { 10687 /* ADC1-2 */ 10688 0x09, 10689}; 10690/* input MUX */ 10691/* FIXME: should be a matrix-type input source selection */ 10692 10693static struct hda_input_mux alc662_capture_source = { 10694 .num_items = 4, 10695 .items = { 10696 { "Mic", 0x0 }, 10697 { "Front Mic", 0x1 }, 10698 { "Line", 0x2 }, 10699 { "CD", 0x4 }, 10700 }, 10701}; 10702 10703static struct hda_input_mux alc662_lenovo_101e_capture_source = { 10704 .num_items = 2, 10705 .items = { 10706 { "Mic", 0x1 }, 10707 { "Line", 0x2 }, 10708 }, 10709}; 10710#define alc662_mux_enum_info alc_mux_enum_info 10711#define alc662_mux_enum_get alc_mux_enum_get 10712 10713static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol, 10714 struct snd_ctl_elem_value *ucontrol) 10715{ 10716 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 10717 struct alc_spec *spec = codec->spec; 10718 const struct hda_input_mux *imux = spec->input_mux; 10719 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 10720 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; 10721 hda_nid_t nid = capture_mixers[adc_idx]; 10722 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 10723 unsigned int i, idx; 10724 10725 idx = ucontrol->value.enumerated.item[0]; 10726 if (idx >= imux->num_items) 10727 idx = imux->num_items - 1; 10728 if (*cur_val == idx && !codec->in_resume) 10729 return 0; 10730 for (i = 0; i < imux->num_items; i++) { 10731 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 10732 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 10733 v | (imux->items[i].index << 8)); 10734 } 10735 *cur_val = idx; 10736 return 1; 10737} 10738/* 10739 * 2ch mode 10740 */ 10741static struct hda_channel_mode alc662_3ST_2ch_modes[1] = { 10742 { 2, NULL } 10743}; 10744 10745/* 10746 * 2ch mode 10747 */ 10748static struct hda_verb alc662_3ST_ch2_init[] = { 10749 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 10750 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 10751 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 10752 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 10753 { } /* end */ 10754}; 10755 10756/* 10757 * 6ch mode 10758 */ 10759static struct hda_verb alc662_3ST_ch6_init[] = { 10760 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10761 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 10762 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, 10763 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10764 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 10765 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, 10766 { } /* end */ 10767}; 10768 10769static struct hda_channel_mode alc662_3ST_6ch_modes[2] = { 10770 { 2, alc662_3ST_ch2_init }, 10771 { 6, alc662_3ST_ch6_init }, 10772}; 10773 10774/* 10775 * 2ch mode 10776 */ 10777static struct hda_verb alc662_sixstack_ch6_init[] = { 10778 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 10779 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, 10780 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10781 { } /* end */ 10782}; 10783 10784/* 10785 * 6ch mode 10786 */ 10787static struct hda_verb alc662_sixstack_ch8_init[] = { 10788 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10789 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10790 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 10791 { } /* end */ 10792}; 10793 10794static struct hda_channel_mode alc662_5stack_modes[2] = { 10795 { 2, alc662_sixstack_ch6_init }, 10796 { 6, alc662_sixstack_ch8_init }, 10797}; 10798 10799/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 10800 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 10801 */ 10802 10803static struct snd_kcontrol_new alc662_base_mixer[] = { 10804 /* output mixer control */ 10805 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), 10806 HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT), 10807 HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT), 10808 HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT), 10809 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), 10810 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), 10811 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), 10812 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), 10813 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10814 10815 /*Input mixer control */ 10816 HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT), 10817 HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT), 10818 HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT), 10819 HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT), 10820 HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT), 10821 HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT), 10822 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT), 10823 HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT), 10824 10825 /* Capture mixer control */ 10826 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 10827 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 10828 { 10829 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10830 .name = "Capture Source", 10831 .count = 1, 10832 .info = alc_mux_enum_info, 10833 .get = alc_mux_enum_get, 10834 .put = alc_mux_enum_put, 10835 }, 10836 { } /* end */ 10837}; 10838 10839static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = { 10840 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10841 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), 10842 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10843 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 10844 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 10845 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 10846 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 10847 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10848 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10849 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10850 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10851 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 10852 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 10853 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 10854 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 10855 { 10856 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10857 /* .name = "Capture Source", */ 10858 .name = "Input Source", 10859 .count = 1, 10860 .info = alc662_mux_enum_info, 10861 .get = alc662_mux_enum_get, 10862 .put = alc662_mux_enum_put, 10863 }, 10864 { } /* end */ 10865}; 10866 10867static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = { 10868 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10869 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), 10870 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), 10871 HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT), 10872 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), 10873 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), 10874 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), 10875 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), 10876 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10877 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 10878 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 10879 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 10880 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 10881 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 10882 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 10883 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10884 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10885 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 10886 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 10887 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 10888 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 10889 { 10890 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10891 /* .name = "Capture Source", */ 10892 .name = "Input Source", 10893 .count = 1, 10894 .info = alc662_mux_enum_info, 10895 .get = alc662_mux_enum_get, 10896 .put = alc662_mux_enum_put, 10897 }, 10898 { } /* end */ 10899}; 10900 10901static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = { 10902 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), 10903 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), 10904 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x03, 0x0, HDA_OUTPUT), 10905 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x03, 2, HDA_INPUT), 10906 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 10907 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 10908 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 10909 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 10910 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 10911 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 10912 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 10913 { 10914 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10915 /* .name = "Capture Source", */ 10916 .name = "Input Source", 10917 .count = 1, 10918 .info = alc662_mux_enum_info, 10919 .get = alc662_mux_enum_get, 10920 .put = alc662_mux_enum_put, 10921 }, 10922 { } /* end */ 10923}; 10924 10925static struct snd_kcontrol_new alc662_chmode_mixer[] = { 10926 { 10927 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 10928 .name = "Channel Mode", 10929 .info = alc_ch_mode_info, 10930 .get = alc_ch_mode_get, 10931 .put = alc_ch_mode_put, 10932 }, 10933 { } /* end */ 10934}; 10935 10936static struct hda_verb alc662_init_verbs[] = { 10937 /* ADC: mute amp left and right */ 10938 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 10939 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 10940 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 10941 10942 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10943 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10944 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 10945 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 10946 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 10947 10948 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10949 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10950 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10951 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10952 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10953 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10954 10955 /* Front Pin: output 0 (0x0c) */ 10956 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10957 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10958 10959 /* Rear Pin: output 1 (0x0d) */ 10960 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10961 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10962 10963 /* CLFE Pin: output 2 (0x0e) */ 10964 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 10965 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10966 10967 /* Mic (rear) pin: input vref at 80% */ 10968 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10969 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10970 /* Front Mic pin: input vref at 80% */ 10971 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 10972 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10973 /* Line In pin: input */ 10974 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10975 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 10976 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 10977 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 10978 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 10979 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 10980 /* CD pin widget for input */ 10981 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 10982 10983 /* FIXME: use matrix-type input source selection */ 10984 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 10985 /* Input mixer */ 10986 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 10987 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 10988 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 10989 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 10990 { } 10991}; 10992 10993static struct hda_verb alc662_sue_init_verbs[] = { 10994 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, 10995 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, 10996 {} 10997}; 10998 10999/* 11000 * generic initialization of ADC, input mixers and output mixers 11001 */ 11002static struct hda_verb alc662_auto_init_verbs[] = { 11003 /* 11004 * Unmute ADC and set the default input to mic-in 11005 */ 11006 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 11007 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11008 11009 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 11010 * mixer widget 11011 * Note: PASD motherboards uses the Line In 2 as the input for front 11012 * panel mic (mic 2) 11013 */ 11014 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 11015 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11016 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11017 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 11018 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 11019 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 11020 11021 /* 11022 * Set up output mixers (0x0c - 0x0f) 11023 */ 11024 /* set vol=0 to output mixers */ 11025 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 11026 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 11027 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 11028 11029 /* set up input amps for analog loopback */ 11030 /* Amp Indices: DAC = 0, mixer = 1 */ 11031 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11032 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11033 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11034 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11035 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11036 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11037 11038 11039 /* FIXME: use matrix-type input source selection */ 11040 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 11041 /* Input mixer */ 11042 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 11043 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 11044 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 11045 /*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/ 11046 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 11047 11048 { } 11049}; 11050 11051/* capture mixer elements */ 11052static struct snd_kcontrol_new alc662_capture_mixer[] = { 11053 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), 11054 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), 11055 { 11056 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 11057 /* The multiple "Capture Source" controls confuse alsamixer 11058 * So call somewhat different.. 11059 * FIXME: the controls appear in the "playback" view! 11060 */ 11061 /* .name = "Capture Source", */ 11062 .name = "Input Source", 11063 .count = 1, 11064 .info = alc882_mux_enum_info, 11065 .get = alc882_mux_enum_get, 11066 .put = alc882_mux_enum_put, 11067 }, 11068 { } /* end */ 11069}; 11070 11071static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec) 11072{ 11073 unsigned int present; 11074 unsigned char bits; 11075 11076 present = snd_hda_codec_read(codec, 0x14, 0, 11077 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 11078 bits = present ? 0x80 : 0; 11079 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 11080 0x80, bits); 11081 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 11082 0x80, bits); 11083} 11084 11085static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) 11086{ 11087 unsigned int present; 11088 unsigned char bits; 11089 11090 present = snd_hda_codec_read(codec, 0x1b, 0, 11091 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 11092 bits = present ? 0x80 : 0; 11093 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, 11094 0x80, bits); 11095 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, 11096 0x80, bits); 11097 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, 11098 0x80, bits); 11099 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 11100 0x80, bits); 11101} 11102 11103static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, 11104 unsigned int res) 11105{ 11106 if ((res >> 26) == ALC880_HP_EVENT) 11107 alc662_lenovo_101e_all_automute(codec); 11108 if ((res >> 26) == ALC880_FRONT_EVENT) 11109 alc662_lenovo_101e_ispeaker_automute(codec); 11110} 11111 11112 11113/* pcm configuration: identiacal with ALC880 */ 11114#define alc662_pcm_analog_playback alc880_pcm_analog_playback 11115#define alc662_pcm_analog_capture alc880_pcm_analog_capture 11116#define alc662_pcm_digital_playback alc880_pcm_digital_playback 11117#define alc662_pcm_digital_capture alc880_pcm_digital_capture 11118 11119/* 11120 * configuration and preset 11121 */ 11122static const char *alc662_models[ALC662_MODEL_LAST] = { 11123 [ALC662_3ST_2ch_DIG] = "3stack-dig", 11124 [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig", 11125 [ALC662_3ST_6ch] = "3stack-6ch", 11126 [ALC662_5ST_DIG] = "6stack-dig", 11127 [ALC662_LENOVO_101E] = "lenovo-101e", 11128 [ALC662_AUTO] = "auto", 11129}; 11130 11131static struct snd_pci_quirk alc662_cfg_tbl[] = { 11132 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), 11133 {} 11134}; 11135 11136static struct alc_config_preset alc662_presets[] = { 11137 [ALC662_3ST_2ch_DIG] = { 11138 .mixers = { alc662_3ST_2ch_mixer }, 11139 .init_verbs = { alc662_init_verbs }, 11140 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11141 .dac_nids = alc662_dac_nids, 11142 .dig_out_nid = ALC662_DIGOUT_NID, 11143 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11144 .adc_nids = alc662_adc_nids, 11145 .dig_in_nid = ALC662_DIGIN_NID, 11146 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), 11147 .channel_mode = alc662_3ST_2ch_modes, 11148 .input_mux = &alc662_capture_source, 11149 }, 11150 [ALC662_3ST_6ch_DIG] = { 11151 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, 11152 .init_verbs = { alc662_init_verbs }, 11153 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11154 .dac_nids = alc662_dac_nids, 11155 .dig_out_nid = ALC662_DIGOUT_NID, 11156 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11157 .adc_nids = alc662_adc_nids, 11158 .dig_in_nid = ALC662_DIGIN_NID, 11159 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), 11160 .channel_mode = alc662_3ST_6ch_modes, 11161 .need_dac_fix = 1, 11162 .input_mux = &alc662_capture_source, 11163 }, 11164 [ALC662_3ST_6ch] = { 11165 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, 11166 .init_verbs = { alc662_init_verbs }, 11167 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11168 .dac_nids = alc662_dac_nids, 11169 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11170 .adc_nids = alc662_adc_nids, 11171 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), 11172 .channel_mode = alc662_3ST_6ch_modes, 11173 .need_dac_fix = 1, 11174 .input_mux = &alc662_capture_source, 11175 }, 11176 [ALC662_5ST_DIG] = { 11177 .mixers = { alc662_base_mixer, alc662_chmode_mixer }, 11178 .init_verbs = { alc662_init_verbs }, 11179 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11180 .dac_nids = alc662_dac_nids, 11181 .dig_out_nid = ALC662_DIGOUT_NID, 11182 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11183 .adc_nids = alc662_adc_nids, 11184 .dig_in_nid = ALC662_DIGIN_NID, 11185 .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes), 11186 .channel_mode = alc662_5stack_modes, 11187 .input_mux = &alc662_capture_source, 11188 }, 11189 [ALC662_LENOVO_101E] = { 11190 .mixers = { alc662_lenovo_101e_mixer }, 11191 .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, 11192 .num_dacs = ARRAY_SIZE(alc662_dac_nids), 11193 .dac_nids = alc662_dac_nids, 11194 .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), 11195 .adc_nids = alc662_adc_nids, 11196 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), 11197 .channel_mode = alc662_3ST_2ch_modes, 11198 .input_mux = &alc662_lenovo_101e_capture_source, 11199 .unsol_event = alc662_lenovo_101e_unsol_event, 11200 .init_hook = alc662_lenovo_101e_all_automute, 11201 }, 11202 11203}; 11204 11205 11206/* 11207 * BIOS auto configuration 11208 */ 11209 11210/* add playback controls from the parsed DAC table */ 11211static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, 11212 const struct auto_pin_cfg *cfg) 11213{ 11214 char name[32]; 11215 static const char *chname[4] = { 11216 "Front", "Surround", NULL /*CLFE*/, "Side" 11217 }; 11218 hda_nid_t nid; 11219 int i, err; 11220 11221 for (i = 0; i < cfg->line_outs; i++) { 11222 if (!spec->multiout.dac_nids[i]) 11223 continue; 11224 nid = alc880_idx_to_mixer(i); 11225 if (i == 2) { 11226 /* Center/LFE */ 11227 err = add_control(spec, ALC_CTL_WIDGET_VOL, 11228 "Center Playback Volume", 11229 HDA_COMPOSE_AMP_VAL(nid, 1, 0, 11230 HDA_OUTPUT)); 11231 if (err < 0) 11232 return err; 11233 err = add_control(spec, ALC_CTL_WIDGET_VOL, 11234 "LFE Playback Volume", 11235 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 11236 HDA_OUTPUT)); 11237 if (err < 0) 11238 return err; 11239 err = add_control(spec, ALC_CTL_BIND_MUTE, 11240 "Center Playback Switch", 11241 HDA_COMPOSE_AMP_VAL(nid, 1, 2, 11242 HDA_INPUT)); 11243 if (err < 0) 11244 return err; 11245 err = add_control(spec, ALC_CTL_BIND_MUTE, 11246 "LFE Playback Switch", 11247 HDA_COMPOSE_AMP_VAL(nid, 2, 2, 11248 HDA_INPUT)); 11249 if (err < 0) 11250 return err; 11251 } else { 11252 sprintf(name, "%s Playback Volume", chname[i]); 11253 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 11254 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 11255 HDA_OUTPUT)); 11256 if (err < 0) 11257 return err; 11258 sprintf(name, "%s Playback Switch", chname[i]); 11259 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 11260 HDA_COMPOSE_AMP_VAL(nid, 3, 2, 11261 HDA_INPUT)); 11262 if (err < 0) 11263 return err; 11264 } 11265 } 11266 return 0; 11267} 11268 11269/* add playback controls for speaker and HP outputs */ 11270static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, 11271 const char *pfx) 11272{ 11273 hda_nid_t nid; 11274 int err; 11275 char name[32]; 11276 11277 if (!pin) 11278 return 0; 11279 11280 if (alc880_is_fixed_pin(pin)) { 11281 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 11282 /* printk("DAC nid=%x\n",nid); */ 11283 /* specify the DAC as the extra output */ 11284 if (!spec->multiout.hp_nid) 11285 spec->multiout.hp_nid = nid; 11286 else 11287 spec->multiout.extra_out_nid[0] = nid; 11288 /* control HP volume/switch on the output mixer amp */ 11289 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 11290 sprintf(name, "%s Playback Volume", pfx); 11291 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 11292 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 11293 if (err < 0) 11294 return err; 11295 sprintf(name, "%s Playback Switch", pfx); 11296 err = add_control(spec, ALC_CTL_BIND_MUTE, name, 11297 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); 11298 if (err < 0) 11299 return err; 11300 } else if (alc880_is_multi_pin(pin)) { 11301 /* set manual connection */ 11302 /* we have only a switch on HP-out PIN */ 11303 sprintf(name, "%s Playback Switch", pfx); 11304 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 11305 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 11306 if (err < 0) 11307 return err; 11308 } 11309 return 0; 11310} 11311 11312/* create playback/capture controls for input pins */ 11313static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec, 11314 const struct auto_pin_cfg *cfg) 11315{ 11316 struct hda_input_mux *imux = &spec->private_imux; 11317 int i, err, idx; 11318 11319 for (i = 0; i < AUTO_PIN_LAST; i++) { 11320 if (alc880_is_input_pin(cfg->input_pins[i])) { 11321 idx = alc880_input_pin_idx(cfg->input_pins[i]); 11322 err = new_analog_input(spec, cfg->input_pins[i], 11323 auto_pin_cfg_labels[i], 11324 idx, 0x0b); 11325 if (err < 0) 11326 return err; 11327 imux->items[imux->num_items].label = 11328 auto_pin_cfg_labels[i]; 11329 imux->items[imux->num_items].index = 11330 alc880_input_pin_idx(cfg->input_pins[i]); 11331 imux->num_items++; 11332 } 11333 } 11334 return 0; 11335} 11336 11337static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, 11338 hda_nid_t nid, int pin_type, 11339 int dac_idx) 11340{ 11341 /* set as output */ 11342 snd_hda_codec_write(codec, nid, 0, 11343 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); 11344 snd_hda_codec_write(codec, nid, 0, 11345 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 11346 /* need the manual connection? */ 11347 if (alc880_is_multi_pin(nid)) { 11348 struct alc_spec *spec = codec->spec; 11349 int idx = alc880_multi_pin_idx(nid); 11350 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, 11351 AC_VERB_SET_CONNECT_SEL, 11352 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); 11353 } 11354} 11355 11356static void alc662_auto_init_multi_out(struct hda_codec *codec) 11357{ 11358 struct alc_spec *spec = codec->spec; 11359 int i; 11360 11361 for (i = 0; i <= HDA_SIDE; i++) { 11362 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 11363 int pin_type = get_pin_type(spec->autocfg.line_out_type); 11364 if (nid) 11365 alc662_auto_set_output_and_unmute(codec, nid, pin_type, 11366 i); 11367 } 11368} 11369 11370static void alc662_auto_init_hp_out(struct hda_codec *codec) 11371{ 11372 struct alc_spec *spec = codec->spec; 11373 hda_nid_t pin; 11374 11375 pin = spec->autocfg.hp_pins[0]; 11376 if (pin) /* connect to front */ 11377 /* use dac 0 */ 11378 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 11379} 11380 11381#define alc662_is_input_pin(nid) alc880_is_input_pin(nid) 11382#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID 11383 11384static void alc662_auto_init_analog_input(struct hda_codec *codec) 11385{ 11386 struct alc_spec *spec = codec->spec; 11387 int i; 11388 11389 for (i = 0; i < AUTO_PIN_LAST; i++) { 11390 hda_nid_t nid = spec->autocfg.input_pins[i]; 11391 if (alc662_is_input_pin(nid)) { 11392 snd_hda_codec_write(codec, nid, 0, 11393 AC_VERB_SET_PIN_WIDGET_CONTROL, 11394 (i <= AUTO_PIN_FRONT_MIC ? 11395 PIN_VREF80 : PIN_IN)); 11396 if (nid != ALC662_PIN_CD_NID) 11397 snd_hda_codec_write(codec, nid, 0, 11398 AC_VERB_SET_AMP_GAIN_MUTE, 11399 AMP_OUT_MUTE); 11400 } 11401 } 11402} 11403 11404static int alc662_parse_auto_config(struct hda_codec *codec) 11405{ 11406 struct alc_spec *spec = codec->spec; 11407 int err; 11408 static hda_nid_t alc662_ignore[] = { 0x1d, 0 }; 11409 11410 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 11411 alc662_ignore); 11412 if (err < 0) 11413 return err; 11414 if (!spec->autocfg.line_outs) 11415 return 0; /* can't find valid BIOS pin config */ 11416 11417 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 11418 if (err < 0) 11419 return err; 11420 err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); 11421 if (err < 0) 11422 return err; 11423 err = alc662_auto_create_extra_out(spec, 11424 spec->autocfg.speaker_pins[0], 11425 "Speaker"); 11426 if (err < 0) 11427 return err; 11428 err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], 11429 "Headphone"); 11430 if (err < 0) 11431 return err; 11432 err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg); 11433 if (err < 0) 11434 return err; 11435 11436 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 11437 11438 if (spec->autocfg.dig_out_pin) 11439 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; 11440 11441 if (spec->kctl_alloc) 11442 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 11443 11444 spec->num_mux_defs = 1; 11445 spec->input_mux = &spec->private_imux; 11446 11447 spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs; 11448 spec->mixers[spec->num_mixers] = alc662_capture_mixer; 11449 spec->num_mixers++; 11450 return 1; 11451} 11452 11453/* additional initialization for auto-configuration model */ 11454static void alc662_auto_init(struct hda_codec *codec) 11455{ 11456 alc662_auto_init_multi_out(codec); 11457 alc662_auto_init_hp_out(codec); 11458 alc662_auto_init_analog_input(codec); 11459} 11460 11461static int patch_alc662(struct hda_codec *codec) 11462{ 11463 struct alc_spec *spec; 11464 int err, board_config; 11465 11466 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 11467 if (!spec) 11468 return -ENOMEM; 11469 11470 codec->spec = spec; 11471 11472 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, 11473 alc662_models, 11474 alc662_cfg_tbl); 11475 if (board_config < 0) { 11476 printk(KERN_INFO "hda_codec: Unknown model for ALC662, " 11477 "trying auto-probe from BIOS...\n"); 11478 board_config = ALC662_AUTO; 11479 } 11480 11481 if (board_config == ALC662_AUTO) { 11482 /* automatic parse from the BIOS config */ 11483 err = alc662_parse_auto_config(codec); 11484 if (err < 0) { 11485 alc_free(codec); 11486 return err; 11487 } else if (!err) { 11488 printk(KERN_INFO 11489 "hda_codec: Cannot set up configuration " 11490 "from BIOS. Using base mode...\n"); 11491 board_config = ALC662_3ST_2ch_DIG; 11492 } 11493 } 11494 11495 if (board_config != ALC662_AUTO) 11496 setup_preset(spec, &alc662_presets[board_config]); 11497 11498 spec->stream_name_analog = "ALC662 Analog"; 11499 spec->stream_analog_playback = &alc662_pcm_analog_playback; 11500 spec->stream_analog_capture = &alc662_pcm_analog_capture; 11501 11502 spec->stream_name_digital = "ALC662 Digital"; 11503 spec->stream_digital_playback = &alc662_pcm_digital_playback; 11504 spec->stream_digital_capture = &alc662_pcm_digital_capture; 11505 11506 if (!spec->adc_nids && spec->input_mux) { 11507 spec->adc_nids = alc662_adc_nids; 11508 spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); 11509 } 11510 11511 codec->patch_ops = alc_patch_ops; 11512 if (board_config == ALC662_AUTO) 11513 spec->init_hook = alc662_auto_init; 11514 11515 return 0; 11516} 11517 11518/* 11519 * patch entries 11520 */ 11521struct hda_codec_preset snd_hda_preset_realtek[] = { 11522 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, 11523 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, 11524 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 }, 11525 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", 11526 .patch = patch_alc861 }, 11527 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, 11528 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, 11529 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd }, 11530 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2", 11531 .patch = patch_alc883 }, 11532 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", 11533 .patch = patch_alc662 }, 11534 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, 11535 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, 11536 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, 11537 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, 11538 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, 11539 {} /* terminator */ 11540}; 11541