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