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