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