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