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