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