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