patch_realtek.c revision a9430dd8fc232cfddcfaedde1a6a915e241366a8
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 PeiSen Hou <pshou@realtek.com.tw> 7 * Takashi Iwai <tiwai@suse.de> 8 * 9 * This driver is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This driver is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24#include <sound/driver.h> 25#include <linux/init.h> 26#include <linux/delay.h> 27#include <linux/slab.h> 28#include <linux/pci.h> 29#include <sound/core.h> 30#include "hda_codec.h" 31#include "hda_local.h" 32 33 34/* ALC880 board config type */ 35enum { 36 ALC880_3ST, 37 ALC880_3ST_DIG, 38 ALC880_5ST, 39 ALC880_5ST_DIG, 40 ALC880_W810, 41 ALC880_Z71V, 42 ALC880_AUTO, 43 ALC880_6ST, 44 ALC880_6ST_DIG, 45 ALC880_F1734, 46 ALC880_ASUS, 47 ALC880_ASUS_DIG, 48 ALC880_ASUS_W1V, 49 ALC880_UNIWILL_DIG, 50#ifdef CONFIG_SND_DEBUG 51 ALC880_TEST, 52#endif 53 ALC880_MODEL_LAST /* last tag */ 54}; 55 56/* ALC260 models */ 57enum { 58 ALC260_BASIC, 59 ALC260_HP, 60 ALC260_FUJITSU_S702x, 61 ALC260_MODEL_LAST /* last tag */ 62}; 63 64/* amp values */ 65#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) 66#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) 67#define AMP_OUT_MUTE 0xb080 68#define AMP_OUT_UNMUTE 0xb000 69#define AMP_OUT_ZERO 0xb000 70/* pinctl values */ 71#define PIN_IN 0x20 72#define PIN_VREF80 0x24 73#define PIN_VREF50 0x21 74#define PIN_OUT 0x40 75#define PIN_HP 0xc0 76#define PIN_HP_AMP 0x80 77 78struct alc_spec { 79 /* codec parameterization */ 80 snd_kcontrol_new_t *mixers[3]; /* mixer arrays */ 81 unsigned int num_mixers; 82 83 const struct hda_verb *init_verbs[3]; /* initialization verbs 84 * don't forget NULL termination! 85 */ 86 unsigned int num_init_verbs; 87 88 char *stream_name_analog; /* analog PCM stream */ 89 struct hda_pcm_stream *stream_analog_playback; 90 struct hda_pcm_stream *stream_analog_capture; 91 92 char *stream_name_digital; /* digital PCM stream */ 93 struct hda_pcm_stream *stream_digital_playback; 94 struct hda_pcm_stream *stream_digital_capture; 95 96 /* playback */ 97 struct hda_multi_out multiout; /* playback set-up 98 * max_channels, dacs must be set 99 * dig_out_nid and hp_nid are optional 100 */ 101 102 /* capture */ 103 unsigned int num_adc_nids; 104 hda_nid_t *adc_nids; 105 hda_nid_t dig_in_nid; /* digital-in NID; optional */ 106 107 /* capture source */ 108 const struct hda_input_mux *input_mux; 109 unsigned int cur_mux[3]; 110 111 /* channel model */ 112 const struct alc_channel_mode *channel_mode; 113 int num_channel_mode; 114 115 /* PCM information */ 116 struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ 117 118 struct semaphore bind_mutex; /* for bound controls */ 119 120 /* dynamic controls, init_verbs and input_mux */ 121 struct auto_pin_cfg autocfg; 122 unsigned int num_kctl_alloc, num_kctl_used; 123 snd_kcontrol_new_t *kctl_alloc; 124 struct hda_input_mux private_imux; 125 hda_nid_t private_dac_nids[4]; 126}; 127 128 129/* 130 * input MUX handling 131 */ 132static int alc_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 133{ 134 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 135 struct alc_spec *spec = codec->spec; 136 return snd_hda_input_mux_info(spec->input_mux, uinfo); 137} 138 139static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 140{ 141 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 142 struct alc_spec *spec = codec->spec; 143 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 144 145 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; 146 return 0; 147} 148 149static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 150{ 151 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 152 struct alc_spec *spec = codec->spec; 153 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 154 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, 155 spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); 156} 157 158 159/* 160 * channel mode setting 161 */ 162struct alc_channel_mode { 163 int channels; 164 const struct hda_verb *sequence; 165}; 166 167static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 168{ 169 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 170 struct alc_spec *spec = codec->spec; 171 int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; 172 173 snd_assert(spec->channel_mode, return -ENXIO); 174 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 175 uinfo->count = 1; 176 uinfo->value.enumerated.items = items; 177 if (uinfo->value.enumerated.item >= items) 178 uinfo->value.enumerated.item = items - 1; 179 sprintf(uinfo->value.enumerated.name, "%dch", 180 spec->channel_mode[uinfo->value.enumerated.item].channels); 181 return 0; 182} 183 184static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 185{ 186 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 187 struct alc_spec *spec = codec->spec; 188 int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; 189 int i; 190 191 snd_assert(spec->channel_mode, return -ENXIO); 192 for (i = 0; i < items; i++) { 193 if (spec->multiout.max_channels == spec->channel_mode[i].channels) { 194 ucontrol->value.enumerated.item[0] = i; 195 break; 196 } 197 } 198 return 0; 199} 200 201static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 202{ 203 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 204 struct alc_spec *spec = codec->spec; 205 int mode; 206 207 snd_assert(spec->channel_mode, return -ENXIO); 208 mode = ucontrol->value.enumerated.item[0] ? 1 : 0; 209 if (spec->multiout.max_channels == spec->channel_mode[mode].channels && 210 ! codec->in_resume) 211 return 0; 212 213 /* change the current channel setting */ 214 spec->multiout.max_channels = spec->channel_mode[mode].channels; 215 if (spec->channel_mode[mode].sequence) 216 snd_hda_sequence_write(codec, spec->channel_mode[mode].sequence); 217 218 return 1; 219} 220 221 222/* 223 * bound volume controls 224 * 225 * bind multiple volumes (# indices, from 0) 226 */ 227 228#define AMP_VAL_IDX_SHIFT 19 229#define AMP_VAL_IDX_MASK (0x0f<<19) 230 231static int alc_bind_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 232{ 233 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 234 struct alc_spec *spec = codec->spec; 235 unsigned long pval; 236 237 down(&spec->bind_mutex); 238 pval = kcontrol->private_value; 239 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ 240 snd_hda_mixer_amp_switch_info(kcontrol, uinfo); 241 kcontrol->private_value = pval; 242 up(&spec->bind_mutex); 243 return 0; 244} 245 246static int alc_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 247{ 248 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 249 struct alc_spec *spec = codec->spec; 250 unsigned long pval; 251 252 down(&spec->bind_mutex); 253 pval = kcontrol->private_value; 254 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ 255 snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); 256 kcontrol->private_value = pval; 257 up(&spec->bind_mutex); 258 return 0; 259} 260 261static int alc_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 262{ 263 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 264 struct alc_spec *spec = codec->spec; 265 unsigned long pval; 266 int i, indices, change = 0; 267 268 down(&spec->bind_mutex); 269 pval = kcontrol->private_value; 270 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; 271 for (i = 0; i < indices; i++) { 272 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT); 273 change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); 274 } 275 kcontrol->private_value = pval; 276 up(&spec->bind_mutex); 277 return change; 278} 279 280#define ALC_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ 281 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 282 .info = alc_bind_switch_info, \ 283 .get = alc_bind_switch_get, \ 284 .put = alc_bind_switch_put, \ 285 .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } 286 287#define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir) 288 289/* 290 * Control of pin widget settings via the mixer. Only boolean settings are 291 * supported, so VrefEn can't be controlled using these functions as they 292 * stand. 293 */ 294static int alc_pinctl_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 295{ 296 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 297 uinfo->count = 1; 298 uinfo->value.integer.min = 0; 299 uinfo->value.integer.max = 1; 300 return 0; 301} 302 303static int alc_pinctl_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 304{ 305 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 306 hda_nid_t nid = kcontrol->private_value & 0xffff; 307 long mask = (kcontrol->private_value >> 16) & 0xff; 308 long *valp = ucontrol->value.integer.value; 309 310 *valp = 0; 311 if (snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00) & mask) 312 *valp = 1; 313 return 0; 314} 315 316static int alc_pinctl_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 317{ 318 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 319 hda_nid_t nid = kcontrol->private_value & 0xffff; 320 long mask = (kcontrol->private_value >> 16) & 0xff; 321 long *valp = ucontrol->value.integer.value; 322 unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00); 323 int change = ((pinctl & mask)!=0) != *valp; 324 325 if (change) 326 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, 327 *valp?(pinctl|mask):(pinctl&~mask)); 328 return change; 329} 330 331#define ALC_PINCTL_SWITCH(xname, nid, mask) \ 332 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 333 .info = alc_pinctl_switch_info, \ 334 .get = alc_pinctl_switch_get, \ 335 .put = alc_pinctl_switch_put, \ 336 .private_value = (nid) | (mask<<16) } 337 338/* 339 * ALC880 3-stack model 340 * 341 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) 342 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b 343 * HP = 0x19 344 */ 345 346static hda_nid_t alc880_dac_nids[4] = { 347 /* front, rear, clfe, rear_surr */ 348 0x02, 0x05, 0x04, 0x03 349}; 350 351static hda_nid_t alc880_adc_nids[3] = { 352 /* ADC0-2 */ 353 0x07, 0x08, 0x09, 354}; 355 356/* The datasheet says the node 0x07 is connected from inputs, 357 * but it shows zero connection in the real implementation on some devices. 358 */ 359static hda_nid_t alc880_adc_nids_alt[2] = { 360 /* ADC1-2 */ 361 0x08, 0x09, 362}; 363 364#define ALC880_DIGOUT_NID 0x06 365#define ALC880_DIGIN_NID 0x0a 366 367static struct hda_input_mux alc880_capture_source = { 368 .num_items = 4, 369 .items = { 370 { "Mic", 0x0 }, 371 { "Front Mic", 0x3 }, 372 { "Line", 0x2 }, 373 { "CD", 0x4 }, 374 }, 375}; 376 377/* channel source setting (2/6 channel selection for 3-stack) */ 378/* 2ch mode */ 379static struct hda_verb alc880_threestack_ch2_init[] = { 380 /* set line-in to input, mute it */ 381 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 382 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 383 /* set mic-in to input vref 80%, mute it */ 384 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 385 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 386 { } /* end */ 387}; 388 389/* 6ch mode */ 390static struct hda_verb alc880_threestack_ch6_init[] = { 391 /* set line-in to output, unmute it */ 392 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 393 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 394 /* set mic-in to output, unmute it */ 395 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 396 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 397 { } /* end */ 398}; 399 400static struct alc_channel_mode alc880_threestack_modes[2] = { 401 { 2, alc880_threestack_ch2_init }, 402 { 6, alc880_threestack_ch6_init }, 403}; 404 405static snd_kcontrol_new_t alc880_three_stack_mixer[] = { 406 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 407 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 408 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 409 ALC_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), 410 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 411 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 412 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 413 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 414 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 415 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 416 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 417 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 418 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 419 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 420 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), 421 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), 422 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 423 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 424 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), 425 { 426 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 427 .name = "Channel Mode", 428 .info = alc880_ch_mode_info, 429 .get = alc880_ch_mode_get, 430 .put = alc880_ch_mode_put, 431 }, 432 { } /* end */ 433}; 434 435/* capture mixer elements */ 436static snd_kcontrol_new_t alc880_capture_mixer[] = { 437 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), 438 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), 439 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), 440 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), 441 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), 442 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), 443 { 444 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 445 /* The multiple "Capture Source" controls confuse alsamixer 446 * So call somewhat different.. 447 * FIXME: the controls appear in the "playback" view! 448 */ 449 /* .name = "Capture Source", */ 450 .name = "Input Source", 451 .count = 3, 452 .info = alc_mux_enum_info, 453 .get = alc_mux_enum_get, 454 .put = alc_mux_enum_put, 455 }, 456 { } /* end */ 457}; 458 459/* capture mixer elements (in case NID 0x07 not available) */ 460static snd_kcontrol_new_t alc880_capture_alt_mixer[] = { 461 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), 462 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), 463 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), 464 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), 465 { 466 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 467 /* The multiple "Capture Source" controls confuse alsamixer 468 * So call somewhat different.. 469 * FIXME: the controls appear in the "playback" view! 470 */ 471 /* .name = "Capture Source", */ 472 .name = "Input Source", 473 .count = 2, 474 .info = alc_mux_enum_info, 475 .get = alc_mux_enum_get, 476 .put = alc_mux_enum_put, 477 }, 478 { } /* end */ 479}; 480 481 482 483/* 484 * ALC880 5-stack model 485 * 486 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd) 487 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 488 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 489 */ 490 491/* additional mixers to alc880_three_stack_mixer */ 492static snd_kcontrol_new_t alc880_five_stack_mixer[] = { 493 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 494 ALC_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), 495 { } /* end */ 496}; 497 498/* channel source setting (6/8 channel selection for 5-stack) */ 499/* 6ch mode */ 500static struct hda_verb alc880_fivestack_ch6_init[] = { 501 /* set line-in to input, mute it */ 502 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 503 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 504 { } /* end */ 505}; 506 507/* 8ch mode */ 508static struct hda_verb alc880_fivestack_ch8_init[] = { 509 /* set line-in to output, unmute it */ 510 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 511 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 512 { } /* end */ 513}; 514 515static struct alc_channel_mode alc880_fivestack_modes[2] = { 516 { 6, alc880_fivestack_ch6_init }, 517 { 8, alc880_fivestack_ch8_init }, 518}; 519 520 521/* 522 * ALC880 6-stack model 523 * 524 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f) 525 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, 526 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b 527 */ 528 529static hda_nid_t alc880_6st_dac_nids[4] = { 530 /* front, rear, clfe, rear_surr */ 531 0x02, 0x03, 0x04, 0x05 532}; 533 534static struct hda_input_mux alc880_6stack_capture_source = { 535 .num_items = 4, 536 .items = { 537 { "Mic", 0x0 }, 538 { "Front Mic", 0x1 }, 539 { "Line", 0x2 }, 540 { "CD", 0x4 }, 541 }, 542}; 543 544/* fixed 8-channels */ 545static struct alc_channel_mode alc880_sixstack_modes[1] = { 546 { 8, NULL }, 547}; 548 549static snd_kcontrol_new_t alc880_six_stack_mixer[] = { 550 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 551 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 552 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 553 ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 554 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 555 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 556 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 557 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 558 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 559 ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 560 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 561 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 562 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 563 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 564 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 565 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 566 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 567 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 568 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 569 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 570 { 571 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 572 .name = "Channel Mode", 573 .info = alc880_ch_mode_info, 574 .get = alc880_ch_mode_get, 575 .put = alc880_ch_mode_put, 576 }, 577 { } /* end */ 578}; 579 580 581/* 582 * ALC880 W810 model 583 * 584 * W810 has rear IO for: 585 * Front (DAC 02) 586 * Surround (DAC 03) 587 * Center/LFE (DAC 04) 588 * Digital out (06) 589 * 590 * The system also has a pair of internal speakers, and a headphone jack. 591 * These are both connected to Line2 on the codec, hence to DAC 02. 592 * 593 * There is a variable resistor to control the speaker or headphone 594 * volume. This is a hardware-only device without a software API. 595 * 596 * Plugging headphones in will disable the internal speakers. This is 597 * implemented in hardware, not via the driver using jack sense. In 598 * a similar fashion, plugging into the rear socket marked "front" will 599 * disable both the speakers and headphones. 600 * 601 * For input, there's a microphone jack, and an "audio in" jack. 602 * These may not do anything useful with this driver yet, because I 603 * haven't setup any initialization verbs for these yet... 604 */ 605 606static hda_nid_t alc880_w810_dac_nids[3] = { 607 /* front, rear/surround, clfe */ 608 0x02, 0x03, 0x04 609}; 610 611/* fixed 6 channels */ 612static struct alc_channel_mode alc880_w810_modes[1] = { 613 { 6, NULL } 614}; 615 616/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ 617static snd_kcontrol_new_t alc880_w810_base_mixer[] = { 618 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 619 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 620 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 621 ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 622 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 623 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 624 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 625 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 626 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 627 { } /* end */ 628}; 629 630 631/* 632 * Z710V model 633 * 634 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) 635 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a 636 */ 637 638static hda_nid_t alc880_z71v_dac_nids[1] = { 639 0x02 640}; 641#define ALC880_Z71V_HP_DAC 0x03 642 643/* fixed 2 channels */ 644static struct alc_channel_mode alc880_2_jack_modes[1] = { 645 { 2, NULL } 646}; 647 648static snd_kcontrol_new_t alc880_z71v_mixer[] = { 649 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 650 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 651 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 652 ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), 653 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 654 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 655 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 656 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 657 { } /* end */ 658}; 659 660 661/* FIXME! */ 662/* 663 * ALC880 F1734 model 664 * 665 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d) 666 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18 667 */ 668 669static hda_nid_t alc880_f1734_dac_nids[1] = { 670 0x03 671}; 672#define ALC880_F1734_HP_DAC 0x02 673 674static snd_kcontrol_new_t alc880_f1734_mixer[] = { 675 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 676 ALC_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), 677 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 678 ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT), 679 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 680 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 681 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 682 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 683 { } /* end */ 684}; 685 686 687/* FIXME! */ 688/* 689 * ALC880 ASUS model 690 * 691 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) 692 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, 693 * Mic = 0x18, Line = 0x1a 694 */ 695 696#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */ 697#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */ 698 699static snd_kcontrol_new_t alc880_asus_mixer[] = { 700 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 701 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 702 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 703 ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 704 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 705 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 706 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 707 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 708 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 709 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 710 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 711 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 712 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 713 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 714 { 715 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 716 .name = "Channel Mode", 717 .info = alc880_ch_mode_info, 718 .get = alc880_ch_mode_get, 719 .put = alc880_ch_mode_put, 720 }, 721 { } /* end */ 722}; 723 724/* FIXME! */ 725/* 726 * ALC880 ASUS W1V model 727 * 728 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) 729 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, 730 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b 731 */ 732 733/* additional mixers to alc880_asus_mixer */ 734static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = { 735 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT), 736 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT), 737 { } /* end */ 738}; 739 740/* additional mixers to alc880_asus_mixer */ 741static snd_kcontrol_new_t alc880_pcbeep_mixer[] = { 742 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 743 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 744 { } /* end */ 745}; 746 747/* 748 * build control elements 749 */ 750static int alc_build_controls(struct hda_codec *codec) 751{ 752 struct alc_spec *spec = codec->spec; 753 int err; 754 int i; 755 756 for (i = 0; i < spec->num_mixers; i++) { 757 err = snd_hda_add_new_ctls(codec, spec->mixers[i]); 758 if (err < 0) 759 return err; 760 } 761 762 if (spec->multiout.dig_out_nid) { 763 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); 764 if (err < 0) 765 return err; 766 } 767 if (spec->dig_in_nid) { 768 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 769 if (err < 0) 770 return err; 771 } 772 return 0; 773} 774 775 776/* 777 * initialize the codec volumes, etc 778 */ 779 780/* 781 * generic initialization of ADC, input mixers and output mixers 782 */ 783static struct hda_verb alc880_volume_init_verbs[] = { 784 /* 785 * Unmute ADC0-2 and set the default input to mic-in 786 */ 787 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 788 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 789 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 790 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 791 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 792 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 793 794 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 795 * mixer widget 796 * Note: PASD motherboards uses the Line In 2 as the input for front panel 797 * mic (mic 2) 798 */ 799 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 800 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 801 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 802 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 803 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 804 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 805 806 /* 807 * Set up output mixers (0x0c - 0x0f) 808 */ 809 /* set vol=0 to output mixers */ 810 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 811 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 812 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 813 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 814 /* set up input amps for analog loopback */ 815 /* Amp Indices: DAC = 0, mixer = 1 */ 816 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 817 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 818 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 819 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 820 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 821 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 822 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 823 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 824 825 { } 826}; 827 828/* 829 * 3-stack pin configuration: 830 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b 831 */ 832static struct hda_verb alc880_pin_3stack_init_verbs[] = { 833 /* 834 * preset connection lists of input pins 835 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround 836 */ 837 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ 838 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 839 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ 840 841 /* 842 * Set pin mode and muting 843 */ 844 /* set front pin widgets 0x14 for output */ 845 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 846 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 847 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 848 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 849 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 850 /* Mic2 (as headphone out) for HP output */ 851 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 852 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 853 /* Line In pin widget for input */ 854 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 855 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 856 /* Line2 (as front mic) pin widget for input and vref at 80% */ 857 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 858 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 859 /* CD pin widget for input */ 860 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 861 862 { } 863}; 864 865/* 866 * 5-stack pin configuration: 867 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19, 868 * line-in/side = 0x1a, f-mic = 0x1b 869 */ 870static struct hda_verb alc880_pin_5stack_init_verbs[] = { 871 /* 872 * preset connection lists of input pins 873 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround 874 */ 875 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 876 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */ 877 878 /* 879 * Set pin mode and muting 880 */ 881 /* set pin widgets 0x14-0x17 for output */ 882 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 883 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 884 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 885 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 886 /* unmute pins for output (no gain on this amp) */ 887 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 888 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 889 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 890 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 891 892 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 893 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 894 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 895 /* Mic2 (as headphone out) for HP output */ 896 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 897 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 898 /* Line In pin widget for input */ 899 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 900 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 901 /* Line2 (as front mic) pin widget for input and vref at 80% */ 902 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 903 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 904 /* CD pin widget for input */ 905 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 906 907 { } 908}; 909 910/* 911 * W810 pin configuration: 912 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b 913 */ 914static struct hda_verb alc880_pin_w810_init_verbs[] = { 915 /* hphone/speaker input selector: front DAC */ 916 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, 917 918 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 919 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 920 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 921 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 922 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 923 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 924 925 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 926 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 927 928 { } 929}; 930 931/* 932 * Z71V pin configuration: 933 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) 934 */ 935static struct hda_verb alc880_pin_z71v_init_verbs[] = { 936 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 937 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 938 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 939 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 940 941 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 942 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 943 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 944 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 945 946 { } 947}; 948 949/* 950 * 6-stack pin configuration: 951 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19, 952 * line = 0x1a, HP = 0x1b 953 */ 954static struct hda_verb alc880_pin_6stack_init_verbs[] = { 955 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ 956 957 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 958 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 959 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 960 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 961 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 962 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 963 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 964 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 965 966 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 967 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 968 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 969 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 970 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 971 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 972 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 973 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 974 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 975 976 { } 977}; 978 979/* FIXME! */ 980/* 981 * F1734 pin configuration: 982 * HP = 0x14, speaker-out = 0x15, mic = 0x18 983 */ 984static struct hda_verb alc880_pin_f1734_init_verbs[] = { 985 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, 986 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, 987 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, 988 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, 989 990 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 991 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 992 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 993 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 994 995 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 996 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 997 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 998 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 999 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1000 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1001 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1002 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1003 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1004 1005 { } 1006}; 1007 1008/* FIXME! */ 1009/* 1010 * ASUS pin configuration: 1011 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a 1012 */ 1013static struct hda_verb alc880_pin_asus_init_verbs[] = { 1014 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, 1015 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, 1016 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, 1017 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, 1018 1019 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1020 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1021 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1022 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1023 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1024 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1025 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1026 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1027 1028 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1029 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1030 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1031 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1032 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1033 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1034 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1035 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1036 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1037 1038 { } 1039}; 1040 1041/* Enable GPIO mask and set output */ 1042static struct hda_verb alc880_gpio1_init_verbs[] = { 1043 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 1044 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 1045 {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, 1046}; 1047 1048/* Enable GPIO mask and set output */ 1049static struct hda_verb alc880_gpio2_init_verbs[] = { 1050 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 1051 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 1052 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, 1053}; 1054 1055 1056/* 1057 */ 1058 1059static int alc_init(struct hda_codec *codec) 1060{ 1061 struct alc_spec *spec = codec->spec; 1062 unsigned int i; 1063 1064 for (i = 0; i < spec->num_init_verbs; i++) 1065 snd_hda_sequence_write(codec, spec->init_verbs[i]); 1066 return 0; 1067} 1068 1069#ifdef CONFIG_PM 1070/* 1071 * resume 1072 */ 1073static int alc_resume(struct hda_codec *codec) 1074{ 1075 struct alc_spec *spec = codec->spec; 1076 int i; 1077 1078 alc_init(codec); 1079 for (i = 0; i < spec->num_mixers; i++) 1080 snd_hda_resume_ctls(codec, spec->mixers[i]); 1081 if (spec->multiout.dig_out_nid) 1082 snd_hda_resume_spdif_out(codec); 1083 if (spec->dig_in_nid) 1084 snd_hda_resume_spdif_in(codec); 1085 1086 return 0; 1087} 1088#endif 1089 1090/* 1091 * Analog playback callbacks 1092 */ 1093static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo, 1094 struct hda_codec *codec, 1095 snd_pcm_substream_t *substream) 1096{ 1097 struct alc_spec *spec = codec->spec; 1098 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); 1099} 1100 1101static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 1102 struct hda_codec *codec, 1103 unsigned int stream_tag, 1104 unsigned int format, 1105 snd_pcm_substream_t *substream) 1106{ 1107 struct alc_spec *spec = codec->spec; 1108 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, 1109 format, substream); 1110} 1111 1112static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, 1113 struct hda_codec *codec, 1114 snd_pcm_substream_t *substream) 1115{ 1116 struct alc_spec *spec = codec->spec; 1117 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); 1118} 1119 1120/* 1121 * Digital out 1122 */ 1123static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, 1124 struct hda_codec *codec, 1125 snd_pcm_substream_t *substream) 1126{ 1127 struct alc_spec *spec = codec->spec; 1128 return snd_hda_multi_out_dig_open(codec, &spec->multiout); 1129} 1130 1131static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, 1132 struct hda_codec *codec, 1133 snd_pcm_substream_t *substream) 1134{ 1135 struct alc_spec *spec = codec->spec; 1136 return snd_hda_multi_out_dig_close(codec, &spec->multiout); 1137} 1138 1139/* 1140 * Analog capture 1141 */ 1142static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, 1143 struct hda_codec *codec, 1144 unsigned int stream_tag, 1145 unsigned int format, 1146 snd_pcm_substream_t *substream) 1147{ 1148 struct alc_spec *spec = codec->spec; 1149 1150 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 1151 stream_tag, 0, format); 1152 return 0; 1153} 1154 1155static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, 1156 struct hda_codec *codec, 1157 snd_pcm_substream_t *substream) 1158{ 1159 struct alc_spec *spec = codec->spec; 1160 1161 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0); 1162 return 0; 1163} 1164 1165 1166/* 1167 */ 1168static struct hda_pcm_stream alc880_pcm_analog_playback = { 1169 .substreams = 1, 1170 .channels_min = 2, 1171 .channels_max = 8, 1172 /* NID is set in alc_build_pcms */ 1173 .ops = { 1174 .open = alc880_playback_pcm_open, 1175 .prepare = alc880_playback_pcm_prepare, 1176 .cleanup = alc880_playback_pcm_cleanup 1177 }, 1178}; 1179 1180static struct hda_pcm_stream alc880_pcm_analog_capture = { 1181 .substreams = 2, 1182 .channels_min = 2, 1183 .channels_max = 2, 1184 /* NID is set in alc_build_pcms */ 1185 .ops = { 1186 .prepare = alc880_capture_pcm_prepare, 1187 .cleanup = alc880_capture_pcm_cleanup 1188 }, 1189}; 1190 1191static struct hda_pcm_stream alc880_pcm_digital_playback = { 1192 .substreams = 1, 1193 .channels_min = 2, 1194 .channels_max = 2, 1195 /* NID is set in alc_build_pcms */ 1196 .ops = { 1197 .open = alc880_dig_playback_pcm_open, 1198 .close = alc880_dig_playback_pcm_close 1199 }, 1200}; 1201 1202static struct hda_pcm_stream alc880_pcm_digital_capture = { 1203 .substreams = 1, 1204 .channels_min = 2, 1205 .channels_max = 2, 1206 /* NID is set in alc_build_pcms */ 1207}; 1208 1209static int alc_build_pcms(struct hda_codec *codec) 1210{ 1211 struct alc_spec *spec = codec->spec; 1212 struct hda_pcm *info = spec->pcm_rec; 1213 int i; 1214 1215 codec->num_pcms = 1; 1216 codec->pcm_info = info; 1217 1218 info->name = spec->stream_name_analog; 1219 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); 1220 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; 1221 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); 1222 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; 1223 1224 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0; 1225 for (i = 0; i < spec->num_channel_mode; i++) { 1226 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) { 1227 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels; 1228 } 1229 } 1230 1231 if (spec->multiout.dig_out_nid || spec->dig_in_nid) { 1232 codec->num_pcms++; 1233 info++; 1234 info->name = spec->stream_name_digital; 1235 if (spec->multiout.dig_out_nid) { 1236 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); 1237 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; 1238 } 1239 if (spec->dig_in_nid) { 1240 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture); 1241 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; 1242 } 1243 } 1244 1245 return 0; 1246} 1247 1248static void alc_free(struct hda_codec *codec) 1249{ 1250 struct alc_spec *spec = codec->spec; 1251 unsigned int i; 1252 1253 if (! spec) 1254 return; 1255 1256 if (spec->kctl_alloc) { 1257 for (i = 0; i < spec->num_kctl_used; i++) 1258 kfree(spec->kctl_alloc[i].name); 1259 kfree(spec->kctl_alloc); 1260 } 1261 kfree(spec); 1262} 1263 1264/* 1265 */ 1266static struct hda_codec_ops alc_patch_ops = { 1267 .build_controls = alc_build_controls, 1268 .build_pcms = alc_build_pcms, 1269 .init = alc_init, 1270 .free = alc_free, 1271#ifdef CONFIG_PM 1272 .resume = alc_resume, 1273#endif 1274}; 1275 1276 1277/* 1278 * Test configuration for debugging 1279 * 1280 * Almost all inputs/outputs are enabled. I/O pins can be configured via 1281 * enum controls. 1282 */ 1283#ifdef CONFIG_SND_DEBUG 1284static hda_nid_t alc880_test_dac_nids[4] = { 1285 0x02, 0x03, 0x04, 0x05 1286}; 1287 1288static struct hda_input_mux alc880_test_capture_source = { 1289 .num_items = 5, 1290 .items = { 1291 { "In-1", 0x0 }, 1292 { "In-2", 0x1 }, 1293 { "In-3", 0x2 }, 1294 { "In-4", 0x3 }, 1295 { "CD", 0x4 }, 1296 }, 1297}; 1298 1299static struct alc_channel_mode alc880_test_modes[4] = { 1300 { 2, NULL }, 1301 { 4, NULL }, 1302 { 6, NULL }, 1303 { 8, NULL }, 1304}; 1305 1306static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 1307{ 1308 static char *texts[] = { 1309 "N/A", "Line Out", "HP Out", 1310 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" 1311 }; 1312 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1313 uinfo->count = 1; 1314 uinfo->value.enumerated.items = 8; 1315 if (uinfo->value.enumerated.item >= 8) 1316 uinfo->value.enumerated.item = 7; 1317 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 1318 return 0; 1319} 1320 1321static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 1322{ 1323 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1324 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 1325 unsigned int pin_ctl, item = 0; 1326 1327 pin_ctl = snd_hda_codec_read(codec, nid, 0, 1328 AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 1329 if (pin_ctl & AC_PINCTL_OUT_EN) { 1330 if (pin_ctl & AC_PINCTL_HP_EN) 1331 item = 2; 1332 else 1333 item = 1; 1334 } else if (pin_ctl & AC_PINCTL_IN_EN) { 1335 switch (pin_ctl & AC_PINCTL_VREFEN) { 1336 case AC_PINCTL_VREF_HIZ: item = 3; break; 1337 case AC_PINCTL_VREF_50: item = 4; break; 1338 case AC_PINCTL_VREF_GRD: item = 5; break; 1339 case AC_PINCTL_VREF_80: item = 6; break; 1340 case AC_PINCTL_VREF_100: item = 7; break; 1341 } 1342 } 1343 ucontrol->value.enumerated.item[0] = item; 1344 return 0; 1345} 1346 1347static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 1348{ 1349 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1350 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 1351 static unsigned int ctls[] = { 1352 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, 1353 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, 1354 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, 1355 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, 1356 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, 1357 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, 1358 }; 1359 unsigned int old_ctl, new_ctl; 1360 1361 old_ctl = snd_hda_codec_read(codec, nid, 0, 1362 AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 1363 new_ctl = ctls[ucontrol->value.enumerated.item[0]]; 1364 if (old_ctl != new_ctl) { 1365 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); 1366 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 1367 ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000); 1368 return 1; 1369 } 1370 return 0; 1371} 1372 1373static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 1374{ 1375 static char *texts[] = { 1376 "Front", "Surround", "CLFE", "Side" 1377 }; 1378 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1379 uinfo->count = 1; 1380 uinfo->value.enumerated.items = 4; 1381 if (uinfo->value.enumerated.item >= 4) 1382 uinfo->value.enumerated.item = 3; 1383 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 1384 return 0; 1385} 1386 1387static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 1388{ 1389 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1390 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 1391 unsigned int sel; 1392 1393 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); 1394 ucontrol->value.enumerated.item[0] = sel & 3; 1395 return 0; 1396} 1397 1398static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 1399{ 1400 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1401 hda_nid_t nid = (hda_nid_t)kcontrol->private_value; 1402 unsigned int sel; 1403 1404 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; 1405 if (ucontrol->value.enumerated.item[0] != sel) { 1406 sel = ucontrol->value.enumerated.item[0] & 3; 1407 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); 1408 return 1; 1409 } 1410 return 0; 1411} 1412 1413#define PIN_CTL_TEST(xname,nid) { \ 1414 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 1415 .name = xname, \ 1416 .info = alc_test_pin_ctl_info, \ 1417 .get = alc_test_pin_ctl_get, \ 1418 .put = alc_test_pin_ctl_put, \ 1419 .private_value = nid \ 1420 } 1421 1422#define PIN_SRC_TEST(xname,nid) { \ 1423 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 1424 .name = xname, \ 1425 .info = alc_test_pin_src_info, \ 1426 .get = alc_test_pin_src_get, \ 1427 .put = alc_test_pin_src_put, \ 1428 .private_value = nid \ 1429 } 1430 1431static snd_kcontrol_new_t alc880_test_mixer[] = { 1432 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 1433 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 1434 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), 1435 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 1436 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 1437 ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 1438 ALC_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), 1439 ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 1440 PIN_CTL_TEST("Front Pin Mode", 0x14), 1441 PIN_CTL_TEST("Surround Pin Mode", 0x15), 1442 PIN_CTL_TEST("CLFE Pin Mode", 0x16), 1443 PIN_CTL_TEST("Side Pin Mode", 0x17), 1444 PIN_CTL_TEST("In-1 Pin Mode", 0x18), 1445 PIN_CTL_TEST("In-2 Pin Mode", 0x19), 1446 PIN_CTL_TEST("In-3 Pin Mode", 0x1a), 1447 PIN_CTL_TEST("In-4 Pin Mode", 0x1b), 1448 PIN_SRC_TEST("In-1 Pin Source", 0x18), 1449 PIN_SRC_TEST("In-2 Pin Source", 0x19), 1450 PIN_SRC_TEST("In-3 Pin Source", 0x1a), 1451 PIN_SRC_TEST("In-4 Pin Source", 0x1b), 1452 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), 1453 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), 1454 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), 1455 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), 1456 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), 1457 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), 1458 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), 1459 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), 1460 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), 1461 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), 1462 { 1463 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1464 .name = "Channel Mode", 1465 .info = alc880_ch_mode_info, 1466 .get = alc880_ch_mode_get, 1467 .put = alc880_ch_mode_put, 1468 }, 1469 { } /* end */ 1470}; 1471 1472static struct hda_verb alc880_test_init_verbs[] = { 1473 /* Unmute inputs of 0x0c - 0x0f */ 1474 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1475 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1476 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1477 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1478 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1479 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1480 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1481 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1482 /* Vol output for 0x0c-0x0f */ 1483 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1484 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1485 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1486 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1487 /* Set output pins 0x14-0x17 */ 1488 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1489 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1490 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1491 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1492 /* Unmute output pins 0x14-0x17 */ 1493 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1494 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1495 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1496 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1497 /* Set input pins 0x18-0x1c */ 1498 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1499 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1500 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1501 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1502 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1503 /* Mute input pins 0x18-0x1b */ 1504 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1505 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1506 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1507 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1508 /* ADC set up */ 1509 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1510 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 1511 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1512 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 1513 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1514 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 1515 /* Analog input/passthru */ 1516 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1517 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1518 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 1519 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 1520 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 1521 { } 1522}; 1523#endif 1524 1525/* 1526 */ 1527 1528static struct hda_board_config alc880_cfg_tbl[] = { 1529 /* Back 3 jack, front 2 jack */ 1530 { .modelname = "3stack", .config = ALC880_3ST }, 1531 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST }, 1532 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST }, 1533 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST }, 1534 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST }, 1535 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST }, 1536 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST }, 1537 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST }, 1538 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST }, 1539 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST }, 1540 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST }, 1541 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST }, 1542 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST }, 1543 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST }, 1544 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST }, 1545 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST }, 1546 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, 1547 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, 1548 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, 1549 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST }, 1550 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST }, 1551 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST }, 1552 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST }, 1553 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST }, 1554 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST }, 1555 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST }, 1556 { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST }, 1557 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST }, 1558 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST }, 1559 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST }, 1560 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST }, 1561 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, 1562 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, 1563 1564 /* Back 3 jack, front 2 jack (Internal add Aux-In) */ 1565 { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST }, 1566 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST }, 1567 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST }, 1568 1569 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ 1570 { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, 1571 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, 1572 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG }, 1573 1574 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ 1575 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, 1576 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG }, 1577 { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG }, 1578 1579 /* Back 5 jack, front 2 jack */ 1580 { .modelname = "5stack", .config = ALC880_5ST }, 1581 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST }, 1582 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST }, 1583 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST }, 1584 { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST }, 1585 { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST }, 1586 1587 /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */ 1588 { .modelname = "5stack-digout", .config = ALC880_5ST_DIG }, 1589 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG }, 1590 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG }, 1591 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG }, 1592 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG }, 1593 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG }, 1594 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG }, 1595 { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG }, 1596 { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG }, 1597 { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG }, 1598 /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */ 1599 { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG }, 1600 /* note subvendor = 0 below */ 1601 /* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */ 1602 1603 { .modelname = "w810", .config = ALC880_W810 }, 1604 { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 }, 1605 1606 { .modelname = "z71v", .config = ALC880_Z71V }, 1607 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V }, 1608 1609 { .modelname = "6stack", .config = ALC880_6ST }, 1610 { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */ 1611 1612 { .modelname = "6stack-digout", .config = ALC880_6ST_DIG }, 1613 { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG }, 1614 { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG }, 1615 { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG }, 1616 { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG }, 1617 1618 { .modelname = "asus", .config = ALC880_ASUS }, 1619 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG }, 1620 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG }, 1621 { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG }, 1622 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG }, 1623 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG }, 1624 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS }, 1625 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG }, 1626 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS }, 1627 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, 1628 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, 1629 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, 1630 1631 { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, 1632 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG }, 1633 1634 { .modelname = "F1734", .config = ALC880_F1734 }, 1635 { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 }, 1636 1637#ifdef CONFIG_SND_DEBUG 1638 { .modelname = "test", .config = ALC880_TEST }, 1639#endif 1640 1641 {} 1642}; 1643 1644/* 1645 * configuration template - to be copied to the spec instance 1646 */ 1647struct alc_config_preset { 1648 snd_kcontrol_new_t *mixers[4]; 1649 const struct hda_verb *init_verbs[4]; 1650 unsigned int num_dacs; 1651 hda_nid_t *dac_nids; 1652 hda_nid_t dig_out_nid; /* optional */ 1653 hda_nid_t hp_nid; /* optional */ 1654 unsigned int num_adc_nids; 1655 hda_nid_t *adc_nids; 1656 unsigned int num_channel_mode; 1657 const struct alc_channel_mode *channel_mode; 1658 const struct hda_input_mux *input_mux; 1659}; 1660 1661static struct alc_config_preset alc880_presets[] = { 1662 [ALC880_3ST] = { 1663 .mixers = { alc880_three_stack_mixer }, 1664 .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, 1665 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 1666 .dac_nids = alc880_dac_nids, 1667 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 1668 .channel_mode = alc880_threestack_modes, 1669 .input_mux = &alc880_capture_source, 1670 }, 1671 [ALC880_3ST_DIG] = { 1672 .mixers = { alc880_three_stack_mixer }, 1673 .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, 1674 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 1675 .dac_nids = alc880_dac_nids, 1676 .dig_out_nid = ALC880_DIGOUT_NID, 1677 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), 1678 .channel_mode = alc880_threestack_modes, 1679 .input_mux = &alc880_capture_source, 1680 }, 1681 [ALC880_5ST] = { 1682 .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer}, 1683 .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, 1684 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 1685 .dac_nids = alc880_dac_nids, 1686 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), 1687 .channel_mode = alc880_fivestack_modes, 1688 .input_mux = &alc880_capture_source, 1689 }, 1690 [ALC880_5ST_DIG] = { 1691 .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer }, 1692 .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, 1693 .num_dacs = ARRAY_SIZE(alc880_dac_nids), 1694 .dac_nids = alc880_dac_nids, 1695 .dig_out_nid = ALC880_DIGOUT_NID, 1696 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), 1697 .channel_mode = alc880_fivestack_modes, 1698 .input_mux = &alc880_capture_source, 1699 }, 1700 [ALC880_6ST] = { 1701 .mixers = { alc880_six_stack_mixer }, 1702 .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, 1703 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), 1704 .dac_nids = alc880_6st_dac_nids, 1705 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), 1706 .channel_mode = alc880_sixstack_modes, 1707 .input_mux = &alc880_6stack_capture_source, 1708 }, 1709 [ALC880_6ST_DIG] = { 1710 .mixers = { alc880_six_stack_mixer }, 1711 .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, 1712 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), 1713 .dac_nids = alc880_6st_dac_nids, 1714 .dig_out_nid = ALC880_DIGOUT_NID, 1715 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), 1716 .channel_mode = alc880_sixstack_modes, 1717 .input_mux = &alc880_6stack_capture_source, 1718 }, 1719 [ALC880_W810] = { 1720 .mixers = { alc880_w810_base_mixer }, 1721 .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs, 1722 alc880_gpio2_init_verbs }, 1723 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), 1724 .dac_nids = alc880_w810_dac_nids, 1725 .dig_out_nid = ALC880_DIGOUT_NID, 1726 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), 1727 .channel_mode = alc880_w810_modes, 1728 .input_mux = &alc880_capture_source, 1729 }, 1730 [ALC880_Z71V] = { 1731 .mixers = { alc880_z71v_mixer }, 1732 .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs }, 1733 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), 1734 .dac_nids = alc880_z71v_dac_nids, 1735 .dig_out_nid = ALC880_DIGOUT_NID, 1736 .hp_nid = 0x03, 1737 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 1738 .channel_mode = alc880_2_jack_modes, 1739 .input_mux = &alc880_capture_source, 1740 }, 1741 [ALC880_F1734] = { 1742 .mixers = { alc880_f1734_mixer }, 1743 .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs }, 1744 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), 1745 .dac_nids = alc880_f1734_dac_nids, 1746 .hp_nid = 0x02, 1747 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), 1748 .channel_mode = alc880_2_jack_modes, 1749 .input_mux = &alc880_capture_source, 1750 }, 1751 [ALC880_ASUS] = { 1752 .mixers = { alc880_asus_mixer }, 1753 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, 1754 alc880_gpio1_init_verbs }, 1755 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 1756 .dac_nids = alc880_asus_dac_nids, 1757 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 1758 .channel_mode = alc880_asus_modes, 1759 .input_mux = &alc880_capture_source, 1760 }, 1761 [ALC880_ASUS_DIG] = { 1762 .mixers = { alc880_asus_mixer }, 1763 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, 1764 alc880_gpio1_init_verbs }, 1765 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 1766 .dac_nids = alc880_asus_dac_nids, 1767 .dig_out_nid = ALC880_DIGOUT_NID, 1768 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 1769 .channel_mode = alc880_asus_modes, 1770 .input_mux = &alc880_capture_source, 1771 }, 1772 [ALC880_ASUS_W1V] = { 1773 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, 1774 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, 1775 alc880_gpio1_init_verbs }, 1776 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 1777 .dac_nids = alc880_asus_dac_nids, 1778 .dig_out_nid = ALC880_DIGOUT_NID, 1779 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 1780 .channel_mode = alc880_asus_modes, 1781 .input_mux = &alc880_capture_source, 1782 }, 1783 [ALC880_UNIWILL_DIG] = { 1784 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer }, 1785 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs }, 1786 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 1787 .dac_nids = alc880_asus_dac_nids, 1788 .dig_out_nid = ALC880_DIGOUT_NID, 1789 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), 1790 .channel_mode = alc880_asus_modes, 1791 .input_mux = &alc880_capture_source, 1792 }, 1793#ifdef CONFIG_SND_DEBUG 1794 [ALC880_TEST] = { 1795 .mixers = { alc880_test_mixer }, 1796 .init_verbs = { alc880_test_init_verbs }, 1797 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids), 1798 .dac_nids = alc880_test_dac_nids, 1799 .dig_out_nid = ALC880_DIGOUT_NID, 1800 .num_channel_mode = ARRAY_SIZE(alc880_test_modes), 1801 .channel_mode = alc880_test_modes, 1802 .input_mux = &alc880_test_capture_source, 1803 }, 1804#endif 1805}; 1806 1807/* 1808 * Automatic parse of I/O pins from the BIOS configuration 1809 */ 1810 1811#define NUM_CONTROL_ALLOC 32 1812#define NUM_VERB_ALLOC 32 1813 1814enum { 1815 ALC_CTL_WIDGET_VOL, 1816 ALC_CTL_WIDGET_MUTE, 1817 ALC_CTL_BIND_MUTE, 1818}; 1819static snd_kcontrol_new_t alc880_control_templates[] = { 1820 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 1821 HDA_CODEC_MUTE(NULL, 0, 0, 0), 1822 ALC_BIND_MUTE(NULL, 0, 0, 0), 1823}; 1824 1825/* add dynamic controls */ 1826static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val) 1827{ 1828 snd_kcontrol_new_t *knew; 1829 1830 if (spec->num_kctl_used >= spec->num_kctl_alloc) { 1831 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; 1832 1833 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ 1834 if (! knew) 1835 return -ENOMEM; 1836 if (spec->kctl_alloc) { 1837 memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); 1838 kfree(spec->kctl_alloc); 1839 } 1840 spec->kctl_alloc = knew; 1841 spec->num_kctl_alloc = num; 1842 } 1843 1844 knew = &spec->kctl_alloc[spec->num_kctl_used]; 1845 *knew = alc880_control_templates[type]; 1846 knew->name = kstrdup(name, GFP_KERNEL); 1847 if (! knew->name) 1848 return -ENOMEM; 1849 knew->private_value = val; 1850 spec->num_kctl_used++; 1851 return 0; 1852} 1853 1854#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) 1855#define alc880_fixed_pin_idx(nid) ((nid) - 0x14) 1856#define alc880_is_multi_pin(nid) ((nid) >= 0x18) 1857#define alc880_multi_pin_idx(nid) ((nid) - 0x18) 1858#define alc880_is_input_pin(nid) ((nid) >= 0x18) 1859#define alc880_input_pin_idx(nid) ((nid) - 0x18) 1860#define alc880_idx_to_dac(nid) ((nid) + 0x02) 1861#define alc880_dac_to_idx(nid) ((nid) - 0x02) 1862#define alc880_idx_to_mixer(nid) ((nid) + 0x0c) 1863#define alc880_idx_to_selector(nid) ((nid) + 0x10) 1864#define ALC880_PIN_CD_NID 0x1c 1865 1866/* fill in the dac_nids table from the parsed pin configuration */ 1867static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg) 1868{ 1869 hda_nid_t nid; 1870 int assigned[4]; 1871 int i, j; 1872 1873 memset(assigned, 0, sizeof(assigned)); 1874 spec->multiout.dac_nids = spec->private_dac_nids; 1875 1876 /* check the pins hardwired to audio widget */ 1877 for (i = 0; i < cfg->line_outs; i++) { 1878 nid = cfg->line_out_pins[i]; 1879 if (alc880_is_fixed_pin(nid)) { 1880 int idx = alc880_fixed_pin_idx(nid); 1881 spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx); 1882 assigned[idx] = 1; 1883 } 1884 } 1885 /* left pins can be connect to any audio widget */ 1886 for (i = 0; i < cfg->line_outs; i++) { 1887 nid = cfg->line_out_pins[i]; 1888 if (alc880_is_fixed_pin(nid)) 1889 continue; 1890 /* search for an empty channel */ 1891 for (j = 0; j < cfg->line_outs; j++) { 1892 if (! assigned[j]) { 1893 spec->multiout.dac_nids[i] = alc880_idx_to_dac(j); 1894 assigned[j] = 1; 1895 break; 1896 } 1897 } 1898 } 1899 spec->multiout.num_dacs = cfg->line_outs; 1900 return 0; 1901} 1902 1903/* add playback controls from the parsed DAC table */ 1904static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) 1905{ 1906 char name[32]; 1907 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; 1908 hda_nid_t nid; 1909 int i, err; 1910 1911 for (i = 0; i < cfg->line_outs; i++) { 1912 if (! spec->multiout.dac_nids[i]) 1913 continue; 1914 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); 1915 if (i == 2) { 1916 /* Center/LFE */ 1917 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume", 1918 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) 1919 return err; 1920 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume", 1921 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) 1922 return err; 1923 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch", 1924 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0) 1925 return err; 1926 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch", 1927 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0) 1928 return err; 1929 } else { 1930 sprintf(name, "%s Playback Volume", chname[i]); 1931 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 1932 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) 1933 return err; 1934 sprintf(name, "%s Playback Switch", chname[i]); 1935 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, 1936 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) 1937 return err; 1938 } 1939 } 1940 1941 return 0; 1942} 1943 1944/* add playback controls for HP output */ 1945static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) 1946{ 1947 hda_nid_t nid; 1948 int err; 1949 1950 if (! pin) 1951 return 0; 1952 1953 if (alc880_is_fixed_pin(pin)) { 1954 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 1955 if (! spec->multiout.dac_nids[0]) { 1956 /* use this as the primary output */ 1957 spec->multiout.dac_nids[0] = nid; 1958 if (! spec->multiout.num_dacs) 1959 spec->multiout.num_dacs = 1; 1960 } else 1961 /* specify the DAC as the extra HP output */ 1962 spec->multiout.hp_nid = nid; 1963 /* control HP volume/switch on the output mixer amp */ 1964 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); 1965 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume", 1966 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) 1967 return err; 1968 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Headphone Playback Switch", 1969 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) 1970 return err; 1971 } else if (alc880_is_multi_pin(pin)) { 1972 /* set manual connection */ 1973 if (! spec->multiout.dac_nids[0]) { 1974 /* use this as the primary output */ 1975 spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin)); 1976 if (! spec->multiout.num_dacs) 1977 spec->multiout.num_dacs = 1; 1978 } 1979 /* we have only a switch on HP-out PIN */ 1980 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", 1981 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0) 1982 return err; 1983 } 1984 return 0; 1985} 1986 1987/* create input playback/capture controls for the given pin */ 1988static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname) 1989{ 1990 char name[32]; 1991 int err, idx; 1992 1993 sprintf(name, "%s Playback Volume", ctlname); 1994 idx = alc880_input_pin_idx(pin); 1995 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 1996 HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0) 1997 return err; 1998 sprintf(name, "%s Playback Switch", ctlname); 1999 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 2000 HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0) 2001 return err; 2002 return 0; 2003} 2004 2005/* create playback/capture controls for input pins */ 2006static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) 2007{ 2008 static char *labels[AUTO_PIN_LAST] = { 2009 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" 2010 }; 2011 struct hda_input_mux *imux = &spec->private_imux; 2012 int i, err; 2013 2014 for (i = 0; i < AUTO_PIN_LAST; i++) { 2015 if (alc880_is_input_pin(cfg->input_pins[i])) { 2016 err = new_analog_input(spec, cfg->input_pins[i], labels[i]); 2017 if (err < 0) 2018 return err; 2019 imux->items[imux->num_items].label = labels[i]; 2020 imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]); 2021 imux->num_items++; 2022 } 2023 } 2024 return 0; 2025} 2026 2027static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type, 2028 int dac_idx) 2029{ 2030 /* set as output */ 2031 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); 2032 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 2033 /* need the manual connection? */ 2034 if (alc880_is_multi_pin(nid)) { 2035 struct alc_spec *spec = codec->spec; 2036 int idx = alc880_multi_pin_idx(nid); 2037 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, 2038 AC_VERB_SET_CONNECT_SEL, 2039 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); 2040 } 2041} 2042 2043static void alc880_auto_init_multi_out(struct hda_codec *codec) 2044{ 2045 struct alc_spec *spec = codec->spec; 2046 int i; 2047 2048 for (i = 0; i < spec->autocfg.line_outs; i++) { 2049 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 2050 alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); 2051 } 2052} 2053 2054static void alc880_auto_init_hp_out(struct hda_codec *codec) 2055{ 2056 struct alc_spec *spec = codec->spec; 2057 hda_nid_t pin; 2058 2059 pin = spec->autocfg.hp_pin; 2060 if (pin) /* connect to front */ 2061 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 2062} 2063 2064static void alc880_auto_init_analog_input(struct hda_codec *codec) 2065{ 2066 struct alc_spec *spec = codec->spec; 2067 int i; 2068 2069 for (i = 0; i < AUTO_PIN_LAST; i++) { 2070 hda_nid_t nid = spec->autocfg.input_pins[i]; 2071 if (alc880_is_input_pin(nid)) { 2072 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 2073 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); 2074 if (nid != ALC880_PIN_CD_NID) 2075 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 2076 AMP_OUT_MUTE); 2077 } 2078 } 2079} 2080 2081/* parse the BIOS configuration and set up the alc_spec */ 2082/* return 1 if successful, 0 if the proper config is not found, or a negative error code */ 2083static int alc880_parse_auto_config(struct hda_codec *codec) 2084{ 2085 struct alc_spec *spec = codec->spec; 2086 int err; 2087 2088 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0) 2089 return err; 2090 if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0) 2091 return err; 2092 if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) 2093 return 0; /* can't find valid BIOS pin config */ 2094 if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || 2095 (err = alc880_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 || 2096 (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) 2097 return err; 2098 2099 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 2100 2101 if (spec->autocfg.dig_out_pin) 2102 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; 2103 if (spec->autocfg.dig_in_pin) 2104 spec->dig_in_nid = ALC880_DIGIN_NID; 2105 2106 if (spec->kctl_alloc) 2107 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 2108 2109 spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; 2110 2111 spec->input_mux = &spec->private_imux; 2112 2113 return 1; 2114} 2115 2116/* init callback for auto-configuration model -- overriding the default init */ 2117static int alc880_auto_init(struct hda_codec *codec) 2118{ 2119 alc_init(codec); 2120 alc880_auto_init_multi_out(codec); 2121 alc880_auto_init_hp_out(codec); 2122 alc880_auto_init_analog_input(codec); 2123 return 0; 2124} 2125 2126/* 2127 * OK, here we have finally the patch for ALC880 2128 */ 2129 2130static int patch_alc880(struct hda_codec *codec) 2131{ 2132 struct alc_spec *spec; 2133 int board_config; 2134 int i, err; 2135 2136 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 2137 if (spec == NULL) 2138 return -ENOMEM; 2139 2140 init_MUTEX(&spec->bind_mutex); 2141 codec->spec = spec; 2142 2143 board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); 2144 if (board_config < 0 || board_config >= ALC880_MODEL_LAST) { 2145 printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n"); 2146 board_config = ALC880_AUTO; 2147 } 2148 2149 if (board_config == ALC880_AUTO) { 2150 /* automatic parse from the BIOS config */ 2151 err = alc880_parse_auto_config(codec); 2152 if (err < 0) { 2153 alc_free(codec); 2154 return err; 2155 } else if (! err) { 2156 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n"); 2157 board_config = ALC880_3ST; 2158 } 2159 } 2160 2161 if (board_config != ALC880_AUTO) { 2162 /* set up from the preset table */ 2163 const struct alc_config_preset *preset; 2164 2165 preset = &alc880_presets[board_config]; 2166 2167 for (i = 0; preset->mixers[i]; i++) { 2168 snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break); 2169 spec->mixers[spec->num_mixers++] = preset->mixers[i]; 2170 } 2171 for (i = 0; preset->init_verbs[i]; i++) { 2172 snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break); 2173 spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i]; 2174 } 2175 2176 spec->channel_mode = preset->channel_mode; 2177 spec->num_channel_mode = preset->num_channel_mode; 2178 2179 spec->multiout.max_channels = spec->channel_mode[0].channels; 2180 2181 spec->multiout.num_dacs = preset->num_dacs; 2182 spec->multiout.dac_nids = preset->dac_nids; 2183 spec->multiout.dig_out_nid = preset->dig_out_nid; 2184 spec->multiout.hp_nid = preset->hp_nid; 2185 2186 spec->input_mux = preset->input_mux; 2187 2188 spec->num_adc_nids = preset->num_adc_nids; 2189 spec->adc_nids = preset->adc_nids; 2190 } 2191 2192 spec->stream_name_analog = "ALC880 Analog"; 2193 spec->stream_analog_playback = &alc880_pcm_analog_playback; 2194 spec->stream_analog_capture = &alc880_pcm_analog_capture; 2195 2196 spec->stream_name_digital = "ALC880 Digital"; 2197 spec->stream_digital_playback = &alc880_pcm_digital_playback; 2198 spec->stream_digital_capture = &alc880_pcm_digital_capture; 2199 2200 if (! spec->adc_nids && spec->input_mux) { 2201 /* check whether NID 0x07 is valid */ 2202 unsigned int wcap = snd_hda_param_read(codec, alc880_adc_nids[0], 2203 AC_PAR_AUDIO_WIDGET_CAP); 2204 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ 2205 if (wcap != AC_WID_AUD_IN) { 2206 spec->adc_nids = alc880_adc_nids_alt; 2207 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); 2208 spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer; 2209 spec->num_mixers++; 2210 } else { 2211 spec->adc_nids = alc880_adc_nids; 2212 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); 2213 spec->mixers[spec->num_mixers] = alc880_capture_mixer; 2214 spec->num_mixers++; 2215 } 2216 } 2217 2218 codec->patch_ops = alc_patch_ops; 2219 if (board_config == ALC880_AUTO) 2220 codec->patch_ops.init = alc880_auto_init; 2221 2222 return 0; 2223} 2224 2225 2226/* 2227 * ALC260 support 2228 */ 2229 2230static hda_nid_t alc260_dac_nids[1] = { 2231 /* front */ 2232 0x02, 2233}; 2234 2235static hda_nid_t alc260_adc_nids[1] = { 2236 /* ADC0 */ 2237 0x04, 2238}; 2239 2240static hda_nid_t alc260_hp_adc_nids[1] = { 2241 /* ADC1 */ 2242 0x05, 2243}; 2244 2245#define ALC260_DIGOUT_NID 0x03 2246#define ALC260_DIGIN_NID 0x06 2247 2248static struct hda_input_mux alc260_capture_source = { 2249 .num_items = 4, 2250 .items = { 2251 { "Mic", 0x0 }, 2252 { "Front Mic", 0x1 }, 2253 { "Line", 0x2 }, 2254 { "CD", 0x4 }, 2255 }, 2256}; 2257 2258/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack 2259 * and the internal CD lines. 2260 */ 2261static struct hda_input_mux alc260_fujitsu_capture_source = { 2262 .num_items = 2, 2263 .items = { 2264 { "Mic/Line", 0x0 }, 2265 { "CD", 0x4 }, 2266 }, 2267}; 2268 2269/* 2270 * This is just place-holder, so there's something for alc_build_pcms to look 2271 * at when it calculates the maximum number of channels. ALC260 has no mixer 2272 * element which allows changing the channel mode, so the verb list is 2273 * never used. 2274 */ 2275static struct alc_channel_mode alc260_modes[1] = { 2276 { 2, NULL }, 2277}; 2278 2279static snd_kcontrol_new_t alc260_base_mixer[] = { 2280 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), 2281 ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), 2282 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 2283 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 2284 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 2285 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 2286 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 2287 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 2288 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), 2289 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), 2290 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), 2291 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), 2292 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), 2293 ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), 2294 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 2295 ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), 2296 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), 2297 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), 2298 { 2299 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2300 .name = "Capture Source", 2301 .info = alc_mux_enum_info, 2302 .get = alc_mux_enum_get, 2303 .put = alc_mux_enum_put, 2304 }, 2305 { } /* end */ 2306}; 2307 2308static snd_kcontrol_new_t alc260_hp_mixer[] = { 2309 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), 2310 ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), 2311 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 2312 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 2313 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 2314 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), 2315 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 2316 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 2317 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), 2318 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), 2319 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), 2320 ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), 2321 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 2322 ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), 2323 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), 2324 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT), 2325 { 2326 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2327 .name = "Capture Source", 2328 .info = alc_mux_enum_info, 2329 .get = alc_mux_enum_get, 2330 .put = alc_mux_enum_put, 2331 }, 2332 { } /* end */ 2333}; 2334 2335static snd_kcontrol_new_t alc260_fujitsu_mixer[] = { 2336 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), 2337 ALC_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), 2338 ALC_PINCTL_SWITCH("Headphone Amp Switch", 0x14, PIN_HP_AMP), 2339 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 2340 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 2341 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), 2342 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), 2343 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), 2344 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 2345 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), 2346 ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT), 2347 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), 2348 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), 2349 { 2350 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2351 .name = "Capture Source", 2352 .info = alc_mux_enum_info, 2353 .get = alc_mux_enum_get, 2354 .put = alc_mux_enum_put, 2355 }, 2356 { } /* end */ 2357}; 2358 2359static struct hda_verb alc260_init_verbs[] = { 2360 /* Line In pin widget for input */ 2361 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2362 /* CD pin widget for input */ 2363 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2364 /* Mic1 (rear panel) pin widget for input and vref at 80% */ 2365 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2366 /* Mic2 (front panel) pin widget for input and vref at 80% */ 2367 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2368 /* LINE-2 is used for line-out in rear */ 2369 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2370 /* select line-out */ 2371 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, 2372 /* LINE-OUT pin */ 2373 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2374 /* enable HP */ 2375 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2376 /* enable Mono */ 2377 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2378 /* mute capture amp left and right */ 2379 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2380 /* set connection select to line in (default select for this ADC) */ 2381 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, 2382 /* mute capture amp left and right */ 2383 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2384 /* set connection select to line in (default select for this ADC) */ 2385 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, 2386 /* set vol=0 Line-Out mixer amp left and right */ 2387 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2388 /* unmute pin widget amp left and right (no gain on this amp) */ 2389 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2390 /* set vol=0 HP mixer amp left and right */ 2391 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2392 /* unmute pin widget amp left and right (no gain on this amp) */ 2393 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2394 /* set vol=0 Mono mixer amp left and right */ 2395 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2396 /* unmute pin widget amp left and right (no gain on this amp) */ 2397 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2398 /* unmute LINE-2 out pin */ 2399 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2400 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ 2401 /* mute CD */ 2402 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 2403 /* mute Line In */ 2404 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 2405 /* mute Mic */ 2406 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2407 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ 2408 /* mute Front out path */ 2409 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2410 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2411 /* mute Headphone out path */ 2412 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2413 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2414 /* mute Mono out path */ 2415 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2416 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2417 { } 2418}; 2419 2420/* Initialisation sequence for ALC260 as configured in Fujitsu S702x 2421 * laptops. 2422 */ 2423static struct hda_verb alc260_fujitsu_init_verbs[] = { 2424 /* Disable all GPIOs */ 2425 {0x01, AC_VERB_SET_GPIO_MASK, 0}, 2426 /* Internal speaker is connected to headphone pin */ 2427 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2428 /* Headphone/Line-out jack connects to Line1 pin; make it an output */ 2429 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2430 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */ 2431 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2432 /* Ensure all other unused pins are disabled and muted. 2433 * Note: trying to set widget 0x15 to anything blocks all audio 2434 * output for some reason, so just leave that at the default. 2435 */ 2436 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2437 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2438 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2439 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2440 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2441 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2442 /* Disable digital (SPDIF) pins */ 2443 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, 2444 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, 2445 2446 /* Start with mixer outputs muted */ 2447 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2448 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2449 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2450 2451 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */ 2452 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2453 /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */ 2454 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2455 /* Unmute pin widget used for Line-in (no equiv mixer ctrl) */ 2456 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2457 2458 /* Mute capture amp left and right */ 2459 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2460 /* Set ADC connection select to line in (on mic1 pin) */ 2461 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, 2462 2463 /* Mute all inputs to mixer widget (even unconnected ones) */ 2464 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 2465 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 2466 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 2467 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 2468 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 2469 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 2470 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 2471 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 2472}; 2473 2474static struct hda_pcm_stream alc260_pcm_analog_playback = { 2475 .substreams = 1, 2476 .channels_min = 2, 2477 .channels_max = 2, 2478}; 2479 2480static struct hda_pcm_stream alc260_pcm_analog_capture = { 2481 .substreams = 1, 2482 .channels_min = 2, 2483 .channels_max = 2, 2484}; 2485 2486static struct hda_board_config alc260_cfg_tbl[] = { 2487 { .modelname = "hp", .config = ALC260_HP }, 2488 { .pci_subvendor = 0x103c, .config = ALC260_HP }, 2489 { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702x }, 2490 { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702x }, 2491 {} 2492}; 2493 2494static int patch_alc260(struct hda_codec *codec) 2495{ 2496 struct alc_spec *spec; 2497 int board_config; 2498 2499 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 2500 if (spec == NULL) 2501 return -ENOMEM; 2502 2503 init_MUTEX(&spec->bind_mutex); 2504 codec->spec = spec; 2505 2506 board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl); 2507 if (board_config < 0 || board_config >= ALC260_MODEL_LAST) { 2508 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n"); 2509 board_config = ALC260_BASIC; 2510 } 2511 2512 switch (board_config) { 2513 case ALC260_HP: 2514 spec->mixers[spec->num_mixers] = alc260_hp_mixer; 2515 spec->num_mixers++; 2516 break; 2517 case ALC260_FUJITSU_S702x: 2518 spec->mixers[spec->num_mixers] = alc260_fujitsu_mixer; 2519 spec->num_mixers++; 2520 break; 2521 default: 2522 spec->mixers[spec->num_mixers] = alc260_base_mixer; 2523 spec->num_mixers++; 2524 break; 2525 } 2526 2527 if (board_config != ALC260_FUJITSU_S702x) { 2528 spec->init_verbs[0] = alc260_init_verbs; 2529 spec->num_init_verbs = 1; 2530 } else { 2531 spec->init_verbs[0] = alc260_fujitsu_init_verbs; 2532 spec->num_init_verbs = 1; 2533 } 2534 2535 spec->channel_mode = alc260_modes; 2536 spec->num_channel_mode = ARRAY_SIZE(alc260_modes); 2537 2538 spec->stream_name_analog = "ALC260 Analog"; 2539 spec->stream_analog_playback = &alc260_pcm_analog_playback; 2540 spec->stream_analog_capture = &alc260_pcm_analog_capture; 2541 2542 spec->multiout.max_channels = spec->channel_mode[0].channels; 2543 spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids); 2544 spec->multiout.dac_nids = alc260_dac_nids; 2545 2546 if (board_config != ALC260_FUJITSU_S702x) { 2547 spec->input_mux = &alc260_capture_source; 2548 } else { 2549 spec->input_mux = &alc260_fujitsu_capture_source; 2550 } 2551 switch (board_config) { 2552 case ALC260_HP: 2553 spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids); 2554 spec->adc_nids = alc260_hp_adc_nids; 2555 break; 2556 default: 2557 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); 2558 spec->adc_nids = alc260_adc_nids; 2559 break; 2560 } 2561 2562 codec->patch_ops = alc_patch_ops; 2563 2564 return 0; 2565} 2566 2567 2568/* 2569 * ALC882 support 2570 * 2571 * ALC882 is almost identical with ALC880 but has cleaner and more flexible 2572 * configuration. Each pin widget can choose any input DACs and a mixer. 2573 * Each ADC is connected from a mixer of all inputs. This makes possible 2574 * 6-channel independent captures. 2575 * 2576 * In addition, an independent DAC for the multi-playback (not used in this 2577 * driver yet). 2578 */ 2579 2580static struct alc_channel_mode alc882_ch_modes[1] = { 2581 { 8, NULL } 2582}; 2583 2584static hda_nid_t alc882_dac_nids[4] = { 2585 /* front, rear, clfe, rear_surr */ 2586 0x02, 0x03, 0x04, 0x05 2587}; 2588 2589static hda_nid_t alc882_adc_nids[3] = { 2590 /* ADC0-2 */ 2591 0x07, 0x08, 0x09, 2592}; 2593 2594/* input MUX */ 2595/* FIXME: should be a matrix-type input source selection */ 2596 2597static struct hda_input_mux alc882_capture_source = { 2598 .num_items = 4, 2599 .items = { 2600 { "Mic", 0x0 }, 2601 { "Front Mic", 0x1 }, 2602 { "Line", 0x2 }, 2603 { "CD", 0x4 }, 2604 }, 2605}; 2606 2607#define alc882_mux_enum_info alc_mux_enum_info 2608#define alc882_mux_enum_get alc_mux_enum_get 2609 2610static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 2611{ 2612 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2613 struct alc_spec *spec = codec->spec; 2614 const struct hda_input_mux *imux = spec->input_mux; 2615 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 2616 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; 2617 hda_nid_t nid = capture_mixers[adc_idx]; 2618 unsigned int *cur_val = &spec->cur_mux[adc_idx]; 2619 unsigned int i, idx; 2620 2621 idx = ucontrol->value.enumerated.item[0]; 2622 if (idx >= imux->num_items) 2623 idx = imux->num_items - 1; 2624 if (*cur_val == idx && ! codec->in_resume) 2625 return 0; 2626 for (i = 0; i < imux->num_items; i++) { 2627 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 2628 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 2629 v | (imux->items[i].index << 8)); 2630 } 2631 *cur_val = idx; 2632 return 1; 2633} 2634 2635/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 2636 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 2637 */ 2638static snd_kcontrol_new_t alc882_base_mixer[] = { 2639 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 2640 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), 2641 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), 2642 ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), 2643 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), 2644 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), 2645 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), 2646 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), 2647 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), 2648 ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), 2649 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 2650 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), 2651 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 2652 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 2653 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 2654 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 2655 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 2656 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 2657 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 2658 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 2659 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 2660 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), 2661 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), 2662 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), 2663 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), 2664 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), 2665 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), 2666 { 2667 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2668 /* .name = "Capture Source", */ 2669 .name = "Input Source", 2670 .count = 3, 2671 .info = alc882_mux_enum_info, 2672 .get = alc882_mux_enum_get, 2673 .put = alc882_mux_enum_put, 2674 }, 2675 { } /* end */ 2676}; 2677 2678static struct hda_verb alc882_init_verbs[] = { 2679 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 2680 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2681 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2682 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2683 /* Rear mixer */ 2684 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2685 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2686 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2687 /* CLFE mixer */ 2688 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2689 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2690 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2691 /* Side mixer */ 2692 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2693 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2694 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2695 2696 /* Front Pin: output 0 (0x0c) */ 2697 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2698 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2699 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, 2700 /* Rear Pin: output 1 (0x0d) */ 2701 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2702 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2703 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, 2704 /* CLFE Pin: output 2 (0x0e) */ 2705 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2706 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2707 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, 2708 /* Side Pin: output 3 (0x0f) */ 2709 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2710 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2711 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, 2712 /* Mic (rear) pin: input vref at 80% */ 2713 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2714 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2715 /* Front Mic pin: input vref at 80% */ 2716 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2717 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2718 /* Line In pin: input */ 2719 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2720 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2721 /* Line-2 In: Headphone output (output 0 - 0x0c) */ 2722 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2723 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2724 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 2725 /* CD pin widget for input */ 2726 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2727 2728 /* FIXME: use matrix-type input source selection */ 2729 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ 2730 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ 2731 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2732 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2733 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2734 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2735 /* Input mixer2 */ 2736 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2737 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2738 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2739 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2740 /* Input mixer3 */ 2741 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2742 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2743 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2744 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2745 /* ADC1: mute amp left and right */ 2746 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2747 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 2748 /* ADC2: mute amp left and right */ 2749 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2750 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, 2751 /* ADC3: mute amp left and right */ 2752 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2753 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, 2754 2755 { } 2756}; 2757 2758static int patch_alc882(struct hda_codec *codec) 2759{ 2760 struct alc_spec *spec; 2761 2762 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 2763 if (spec == NULL) 2764 return -ENOMEM; 2765 2766 init_MUTEX(&spec->bind_mutex); 2767 codec->spec = spec; 2768 2769 spec->mixers[spec->num_mixers] = alc882_base_mixer; 2770 spec->num_mixers++; 2771 2772 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; 2773 spec->dig_in_nid = ALC880_DIGIN_NID; 2774 spec->init_verbs[0] = alc882_init_verbs; 2775 spec->num_init_verbs = 1; 2776 2777 spec->channel_mode = alc882_ch_modes; 2778 spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes); 2779 2780 spec->stream_name_analog = "ALC882 Analog"; 2781 spec->stream_analog_playback = &alc880_pcm_analog_playback; 2782 spec->stream_analog_capture = &alc880_pcm_analog_capture; 2783 2784 spec->stream_name_digital = "ALC882 Digital"; 2785 spec->stream_digital_playback = &alc880_pcm_digital_playback; 2786 spec->stream_digital_capture = &alc880_pcm_digital_capture; 2787 2788 spec->multiout.max_channels = spec->channel_mode[0].channels; 2789 spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids); 2790 spec->multiout.dac_nids = alc882_dac_nids; 2791 2792 spec->input_mux = &alc882_capture_source; 2793 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); 2794 spec->adc_nids = alc882_adc_nids; 2795 2796 codec->patch_ops = alc_patch_ops; 2797 2798 return 0; 2799} 2800 2801/* 2802 * patch entries 2803 */ 2804struct hda_codec_preset snd_hda_preset_realtek[] = { 2805 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, 2806 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, 2807 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, 2808 {} /* terminator */ 2809}; 2810