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