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