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