1 /* 2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984, 3 * AD1986A, AD1988 4 * 5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de> 6 * 7 * This driver is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This driver is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 #include <linux/init.h> 23 #include <linux/slab.h> 24 #include <linux/pci.h> 25 #include <linux/module.h> 26 27 #include <sound/core.h> 28 #include "hda_codec.h" 29 #include "hda_local.h" 30 #include "hda_auto_parser.h" 31 #include "hda_beep.h" 32 #include "hda_jack.h" 33 #include "hda_generic.h" 34 35 #define ENABLE_AD_STATIC_QUIRKS 36 37 struct ad198x_spec { 38 struct hda_gen_spec gen; 39 40 /* for auto parser */ 41 int smux_paths[4]; 42 unsigned int cur_smux; 43 hda_nid_t eapd_nid; 44 45 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ 46 47 #ifdef ENABLE_AD_STATIC_QUIRKS 48 const struct snd_kcontrol_new *mixers[6]; 49 int num_mixers; 50 const struct hda_verb *init_verbs[6]; /* initialization verbs 51 * don't forget NULL termination! 52 */ 53 unsigned int num_init_verbs; 54 55 /* playback */ 56 struct hda_multi_out multiout; /* playback set-up 57 * max_channels, dacs must be set 58 * dig_out_nid and hp_nid are optional 59 */ 60 unsigned int cur_eapd; 61 unsigned int need_dac_fix; 62 63 /* capture */ 64 unsigned int num_adc_nids; 65 const hda_nid_t *adc_nids; 66 hda_nid_t dig_in_nid; /* digital-in NID; optional */ 67 68 /* capture source */ 69 const struct hda_input_mux *input_mux; 70 const hda_nid_t *capsrc_nids; 71 unsigned int cur_mux[3]; 72 73 /* channel model */ 74 const struct hda_channel_mode *channel_mode; 75 int num_channel_mode; 76 77 /* PCM information */ 78 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ 79 80 unsigned int spdif_route; 81 82 unsigned int jack_present: 1; 83 unsigned int inv_jack_detect: 1;/* inverted jack-detection */ 84 unsigned int analog_beep: 1; /* analog beep input present */ 85 unsigned int avoid_init_slave_vol:1; 86 87 #ifdef CONFIG_PM 88 struct hda_loopback_check loopback; 89 #endif 90 /* for virtual master */ 91 hda_nid_t vmaster_nid; 92 const char * const *slave_vols; 93 const char * const *slave_sws; 94 #endif /* ENABLE_AD_STATIC_QUIRKS */ 95 }; 96 97 #ifdef ENABLE_AD_STATIC_QUIRKS 98 /* 99 * input MUX handling (common part) 100 */ 101 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 102 { 103 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 104 struct ad198x_spec *spec = codec->spec; 105 106 return snd_hda_input_mux_info(spec->input_mux, uinfo); 107 } 108 109 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 110 { 111 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 112 struct ad198x_spec *spec = codec->spec; 113 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 114 115 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; 116 return 0; 117 } 118 119 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 120 { 121 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 122 struct ad198x_spec *spec = codec->spec; 123 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 124 125 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, 126 spec->capsrc_nids[adc_idx], 127 &spec->cur_mux[adc_idx]); 128 } 129 130 /* 131 * initialization (common callbacks) 132 */ 133 static int ad198x_init(struct hda_codec *codec) 134 { 135 struct ad198x_spec *spec = codec->spec; 136 int i; 137 138 for (i = 0; i < spec->num_init_verbs; i++) 139 snd_hda_sequence_write(codec, spec->init_verbs[i]); 140 return 0; 141 } 142 143 static const char * const ad_slave_pfxs[] = { 144 "Front", "Surround", "Center", "LFE", "Side", 145 "Headphone", "Mono", "Speaker", "IEC958", 146 NULL 147 }; 148 149 static const char * const ad1988_6stack_fp_slave_pfxs[] = { 150 "Front", "Surround", "Center", "LFE", "Side", "IEC958", 151 NULL 152 }; 153 #endif /* ENABLE_AD_STATIC_QUIRKS */ 154 155 #ifdef CONFIG_SND_HDA_INPUT_BEEP 156 /* additional beep mixers; the actual parameters are overwritten at build */ 157 static const struct snd_kcontrol_new ad_beep_mixer[] = { 158 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT), 159 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT), 160 { } /* end */ 161 }; 162 163 static const struct snd_kcontrol_new ad_beep2_mixer[] = { 164 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT), 165 HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT), 166 { } /* end */ 167 }; 168 169 #define set_beep_amp(spec, nid, idx, dir) \ 170 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ 171 #else 172 #define set_beep_amp(spec, nid, idx, dir) /* NOP */ 173 #endif 174 175 #ifdef CONFIG_SND_HDA_INPUT_BEEP 176 static int create_beep_ctls(struct hda_codec *codec) 177 { 178 struct ad198x_spec *spec = codec->spec; 179 const struct snd_kcontrol_new *knew; 180 181 if (!spec->beep_amp) 182 return 0; 183 184 knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer; 185 for ( ; knew->name; knew++) { 186 int err; 187 struct snd_kcontrol *kctl; 188 kctl = snd_ctl_new1(knew, codec); 189 if (!kctl) 190 return -ENOMEM; 191 kctl->private_value = spec->beep_amp; 192 err = snd_hda_ctl_add(codec, 0, kctl); 193 if (err < 0) 194 return err; 195 } 196 return 0; 197 } 198 #else 199 #define create_beep_ctls(codec) 0 200 #endif 201 202 #ifdef ENABLE_AD_STATIC_QUIRKS 203 static int ad198x_build_controls(struct hda_codec *codec) 204 { 205 struct ad198x_spec *spec = codec->spec; 206 struct snd_kcontrol *kctl; 207 unsigned int i; 208 int err; 209 210 for (i = 0; i < spec->num_mixers; i++) { 211 err = snd_hda_add_new_ctls(codec, spec->mixers[i]); 212 if (err < 0) 213 return err; 214 } 215 if (spec->multiout.dig_out_nid) { 216 err = snd_hda_create_spdif_out_ctls(codec, 217 spec->multiout.dig_out_nid, 218 spec->multiout.dig_out_nid); 219 if (err < 0) 220 return err; 221 err = snd_hda_create_spdif_share_sw(codec, 222 &spec->multiout); 223 if (err < 0) 224 return err; 225 spec->multiout.share_spdif = 1; 226 } 227 if (spec->dig_in_nid) { 228 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 229 if (err < 0) 230 return err; 231 } 232 233 /* create beep controls if needed */ 234 err = create_beep_ctls(codec); 235 if (err < 0) 236 return err; 237 238 /* if we have no master control, let's create it */ 239 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { 240 unsigned int vmaster_tlv[4]; 241 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, 242 HDA_OUTPUT, vmaster_tlv); 243 err = __snd_hda_add_vmaster(codec, "Master Playback Volume", 244 vmaster_tlv, 245 (spec->slave_vols ? 246 spec->slave_vols : ad_slave_pfxs), 247 "Playback Volume", 248 !spec->avoid_init_slave_vol, NULL); 249 if (err < 0) 250 return err; 251 } 252 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { 253 err = snd_hda_add_vmaster(codec, "Master Playback Switch", 254 NULL, 255 (spec->slave_sws ? 256 spec->slave_sws : ad_slave_pfxs), 257 "Playback Switch"); 258 if (err < 0) 259 return err; 260 } 261 262 /* assign Capture Source enums to NID */ 263 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); 264 if (!kctl) 265 kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); 266 for (i = 0; kctl && i < kctl->count; i++) { 267 err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]); 268 if (err < 0) 269 return err; 270 } 271 272 /* assign IEC958 enums to NID */ 273 kctl = snd_hda_find_mixer_ctl(codec, 274 SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source"); 275 if (kctl) { 276 err = snd_hda_add_nid(codec, kctl, 0, 277 spec->multiout.dig_out_nid); 278 if (err < 0) 279 return err; 280 } 281 282 return 0; 283 } 284 285 #ifdef CONFIG_PM 286 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid) 287 { 288 struct ad198x_spec *spec = codec->spec; 289 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); 290 } 291 #endif 292 293 /* 294 * Analog playback callbacks 295 */ 296 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo, 297 struct hda_codec *codec, 298 struct snd_pcm_substream *substream) 299 { 300 struct ad198x_spec *spec = codec->spec; 301 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, 302 hinfo); 303 } 304 305 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 306 struct hda_codec *codec, 307 unsigned int stream_tag, 308 unsigned int format, 309 struct snd_pcm_substream *substream) 310 { 311 struct ad198x_spec *spec = codec->spec; 312 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, 313 format, substream); 314 } 315 316 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, 317 struct hda_codec *codec, 318 struct snd_pcm_substream *substream) 319 { 320 struct ad198x_spec *spec = codec->spec; 321 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); 322 } 323 324 /* 325 * Digital out 326 */ 327 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, 328 struct hda_codec *codec, 329 struct snd_pcm_substream *substream) 330 { 331 struct ad198x_spec *spec = codec->spec; 332 return snd_hda_multi_out_dig_open(codec, &spec->multiout); 333 } 334 335 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, 336 struct hda_codec *codec, 337 struct snd_pcm_substream *substream) 338 { 339 struct ad198x_spec *spec = codec->spec; 340 return snd_hda_multi_out_dig_close(codec, &spec->multiout); 341 } 342 343 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 344 struct hda_codec *codec, 345 unsigned int stream_tag, 346 unsigned int format, 347 struct snd_pcm_substream *substream) 348 { 349 struct ad198x_spec *spec = codec->spec; 350 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, 351 format, substream); 352 } 353 354 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, 355 struct hda_codec *codec, 356 struct snd_pcm_substream *substream) 357 { 358 struct ad198x_spec *spec = codec->spec; 359 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); 360 } 361 362 /* 363 * Analog capture 364 */ 365 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo, 366 struct hda_codec *codec, 367 unsigned int stream_tag, 368 unsigned int format, 369 struct snd_pcm_substream *substream) 370 { 371 struct ad198x_spec *spec = codec->spec; 372 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 373 stream_tag, 0, format); 374 return 0; 375 } 376 377 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, 378 struct hda_codec *codec, 379 struct snd_pcm_substream *substream) 380 { 381 struct ad198x_spec *spec = codec->spec; 382 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); 383 return 0; 384 } 385 386 /* 387 */ 388 static const struct hda_pcm_stream ad198x_pcm_analog_playback = { 389 .substreams = 1, 390 .channels_min = 2, 391 .channels_max = 6, /* changed later */ 392 .nid = 0, /* fill later */ 393 .ops = { 394 .open = ad198x_playback_pcm_open, 395 .prepare = ad198x_playback_pcm_prepare, 396 .cleanup = ad198x_playback_pcm_cleanup, 397 }, 398 }; 399 400 static const struct hda_pcm_stream ad198x_pcm_analog_capture = { 401 .substreams = 1, 402 .channels_min = 2, 403 .channels_max = 2, 404 .nid = 0, /* fill later */ 405 .ops = { 406 .prepare = ad198x_capture_pcm_prepare, 407 .cleanup = ad198x_capture_pcm_cleanup 408 }, 409 }; 410 411 static const struct hda_pcm_stream ad198x_pcm_digital_playback = { 412 .substreams = 1, 413 .channels_min = 2, 414 .channels_max = 2, 415 .nid = 0, /* fill later */ 416 .ops = { 417 .open = ad198x_dig_playback_pcm_open, 418 .close = ad198x_dig_playback_pcm_close, 419 .prepare = ad198x_dig_playback_pcm_prepare, 420 .cleanup = ad198x_dig_playback_pcm_cleanup 421 }, 422 }; 423 424 static const struct hda_pcm_stream ad198x_pcm_digital_capture = { 425 .substreams = 1, 426 .channels_min = 2, 427 .channels_max = 2, 428 /* NID is set in alc_build_pcms */ 429 }; 430 431 static int ad198x_build_pcms(struct hda_codec *codec) 432 { 433 struct ad198x_spec *spec = codec->spec; 434 struct hda_pcm *info = spec->pcm_rec; 435 436 codec->num_pcms = 1; 437 codec->pcm_info = info; 438 439 info->name = "AD198x Analog"; 440 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback; 441 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; 442 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; 443 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture; 444 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids; 445 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; 446 447 if (spec->multiout.dig_out_nid) { 448 info++; 449 codec->num_pcms++; 450 codec->spdif_status_reset = 1; 451 info->name = "AD198x Digital"; 452 info->pcm_type = HDA_PCM_TYPE_SPDIF; 453 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; 454 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; 455 if (spec->dig_in_nid) { 456 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture; 457 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; 458 } 459 } 460 461 return 0; 462 } 463 #endif /* ENABLE_AD_STATIC_QUIRKS */ 464 465 static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front, 466 hda_nid_t hp) 467 { 468 if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD) 469 snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE, 470 !codec->inv_eapd ? 0x00 : 0x02); 471 if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD) 472 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE, 473 !codec->inv_eapd ? 0x00 : 0x02); 474 } 475 476 static void ad198x_power_eapd(struct hda_codec *codec) 477 { 478 /* We currently only handle front, HP */ 479 switch (codec->vendor_id) { 480 case 0x11d41882: 481 case 0x11d4882a: 482 case 0x11d41884: 483 case 0x11d41984: 484 case 0x11d41883: 485 case 0x11d4184a: 486 case 0x11d4194a: 487 case 0x11d4194b: 488 case 0x11d41988: 489 case 0x11d4198b: 490 case 0x11d4989a: 491 case 0x11d4989b: 492 ad198x_power_eapd_write(codec, 0x12, 0x11); 493 break; 494 case 0x11d41981: 495 case 0x11d41983: 496 ad198x_power_eapd_write(codec, 0x05, 0x06); 497 break; 498 case 0x11d41986: 499 ad198x_power_eapd_write(codec, 0x1b, 0x1a); 500 break; 501 } 502 } 503 504 static void ad198x_shutup(struct hda_codec *codec) 505 { 506 snd_hda_shutup_pins(codec); 507 ad198x_power_eapd(codec); 508 } 509 510 static void ad198x_free(struct hda_codec *codec) 511 { 512 struct ad198x_spec *spec = codec->spec; 513 514 if (!spec) 515 return; 516 517 snd_hda_gen_spec_free(&spec->gen); 518 kfree(spec); 519 snd_hda_detach_beep_device(codec); 520 } 521 522 #ifdef CONFIG_PM 523 static int ad198x_suspend(struct hda_codec *codec) 524 { 525 ad198x_shutup(codec); 526 return 0; 527 } 528 #endif 529 530 #ifdef ENABLE_AD_STATIC_QUIRKS 531 static const struct hda_codec_ops ad198x_patch_ops = { 532 .build_controls = ad198x_build_controls, 533 .build_pcms = ad198x_build_pcms, 534 .init = ad198x_init, 535 .free = ad198x_free, 536 #ifdef CONFIG_PM 537 .check_power_status = ad198x_check_power_status, 538 .suspend = ad198x_suspend, 539 #endif 540 .reboot_notify = ad198x_shutup, 541 }; 542 543 544 /* 545 * EAPD control 546 * the private value = nid 547 */ 548 #define ad198x_eapd_info snd_ctl_boolean_mono_info 549 550 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol, 551 struct snd_ctl_elem_value *ucontrol) 552 { 553 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 554 struct ad198x_spec *spec = codec->spec; 555 if (codec->inv_eapd) 556 ucontrol->value.integer.value[0] = ! spec->cur_eapd; 557 else 558 ucontrol->value.integer.value[0] = spec->cur_eapd; 559 return 0; 560 } 561 562 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol, 563 struct snd_ctl_elem_value *ucontrol) 564 { 565 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 566 struct ad198x_spec *spec = codec->spec; 567 hda_nid_t nid = kcontrol->private_value & 0xff; 568 unsigned int eapd; 569 eapd = !!ucontrol->value.integer.value[0]; 570 if (codec->inv_eapd) 571 eapd = !eapd; 572 if (eapd == spec->cur_eapd) 573 return 0; 574 spec->cur_eapd = eapd; 575 snd_hda_codec_write_cache(codec, nid, 576 0, AC_VERB_SET_EAPD_BTLENABLE, 577 eapd ? 0x02 : 0x00); 578 return 1; 579 } 580 581 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, 582 struct snd_ctl_elem_info *uinfo); 583 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, 584 struct snd_ctl_elem_value *ucontrol); 585 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, 586 struct snd_ctl_elem_value *ucontrol); 587 #endif /* ENABLE_AD_STATIC_QUIRKS */ 588 589 590 /* 591 * Automatic parse of I/O pins from the BIOS configuration 592 */ 593 594 static int ad198x_auto_build_controls(struct hda_codec *codec) 595 { 596 int err; 597 598 err = snd_hda_gen_build_controls(codec); 599 if (err < 0) 600 return err; 601 err = create_beep_ctls(codec); 602 if (err < 0) 603 return err; 604 return 0; 605 } 606 607 static const struct hda_codec_ops ad198x_auto_patch_ops = { 608 .build_controls = ad198x_auto_build_controls, 609 .build_pcms = snd_hda_gen_build_pcms, 610 .init = snd_hda_gen_init, 611 .free = snd_hda_gen_free, 612 .unsol_event = snd_hda_jack_unsol_event, 613 #ifdef CONFIG_PM 614 .check_power_status = snd_hda_gen_check_power_status, 615 .suspend = ad198x_suspend, 616 #endif 617 .reboot_notify = ad198x_shutup, 618 }; 619 620 621 static int ad198x_parse_auto_config(struct hda_codec *codec) 622 { 623 struct ad198x_spec *spec = codec->spec; 624 struct auto_pin_cfg *cfg = &spec->gen.autocfg; 625 int err; 626 627 codec->spdif_status_reset = 1; 628 codec->no_trigger_sense = 1; 629 codec->no_sticky_stream = 1; 630 631 spec->gen.indep_hp = 1; 632 633 err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); 634 if (err < 0) 635 return err; 636 err = snd_hda_gen_parse_auto_config(codec, cfg); 637 if (err < 0) 638 return err; 639 640 codec->patch_ops = ad198x_auto_patch_ops; 641 642 return 0; 643 } 644 645 /* 646 * AD1986A specific 647 */ 648 649 #ifdef ENABLE_AD_STATIC_QUIRKS 650 #define AD1986A_SPDIF_OUT 0x02 651 #define AD1986A_FRONT_DAC 0x03 652 #define AD1986A_SURR_DAC 0x04 653 #define AD1986A_CLFE_DAC 0x05 654 #define AD1986A_ADC 0x06 655 656 static const hda_nid_t ad1986a_dac_nids[3] = { 657 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC 658 }; 659 static const hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC }; 660 static const hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 }; 661 662 static const struct hda_input_mux ad1986a_capture_source = { 663 .num_items = 7, 664 .items = { 665 { "Mic", 0x0 }, 666 { "CD", 0x1 }, 667 { "Aux", 0x3 }, 668 { "Line", 0x4 }, 669 { "Mix", 0x5 }, 670 { "Mono", 0x6 }, 671 { "Phone", 0x7 }, 672 }, 673 }; 674 675 676 static const struct hda_bind_ctls ad1986a_bind_pcm_vol = { 677 .ops = &snd_hda_bind_vol, 678 .values = { 679 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT), 680 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT), 681 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT), 682 0 683 }, 684 }; 685 686 static const struct hda_bind_ctls ad1986a_bind_pcm_sw = { 687 .ops = &snd_hda_bind_sw, 688 .values = { 689 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT), 690 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT), 691 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT), 692 0 693 }, 694 }; 695 696 /* 697 * mixers 698 */ 699 static const struct snd_kcontrol_new ad1986a_mixers[] = { 700 /* 701 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity 702 */ 703 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol), 704 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw), 705 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 706 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 707 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT), 708 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT), 709 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT), 710 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT), 711 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT), 712 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT), 713 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT), 714 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), 715 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), 716 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), 717 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), 718 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT), 719 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT), 720 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), 721 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), 722 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), 723 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT), 724 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), 725 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), 726 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), 727 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), 728 { 729 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 730 .name = "Capture Source", 731 .info = ad198x_mux_enum_info, 732 .get = ad198x_mux_enum_get, 733 .put = ad198x_mux_enum_put, 734 }, 735 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT), 736 { } /* end */ 737 }; 738 739 /* additional mixers for 3stack mode */ 740 static const struct snd_kcontrol_new ad1986a_3st_mixers[] = { 741 { 742 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 743 .name = "Channel Mode", 744 .info = ad198x_ch_mode_info, 745 .get = ad198x_ch_mode_get, 746 .put = ad198x_ch_mode_put, 747 }, 748 { } /* end */ 749 }; 750 751 /* laptop model - 2ch only */ 752 static const hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC }; 753 754 /* master controls both pins 0x1a and 0x1b */ 755 static const struct hda_bind_ctls ad1986a_laptop_master_vol = { 756 .ops = &snd_hda_bind_vol, 757 .values = { 758 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), 759 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), 760 0, 761 }, 762 }; 763 764 static const struct hda_bind_ctls ad1986a_laptop_master_sw = { 765 .ops = &snd_hda_bind_sw, 766 .values = { 767 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), 768 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), 769 0, 770 }, 771 }; 772 773 static const struct snd_kcontrol_new ad1986a_laptop_mixers[] = { 774 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), 775 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), 776 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), 777 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), 778 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), 779 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), 780 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), 781 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT), 782 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT), 783 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), 784 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), 785 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), 786 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT), 787 /* 788 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), 789 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ 790 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), 791 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), 792 { 793 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 794 .name = "Capture Source", 795 .info = ad198x_mux_enum_info, 796 .get = ad198x_mux_enum_get, 797 .put = ad198x_mux_enum_put, 798 }, 799 { } /* end */ 800 }; 801 802 /* laptop-eapd model - 2ch only */ 803 804 static const struct hda_input_mux ad1986a_laptop_eapd_capture_source = { 805 .num_items = 3, 806 .items = { 807 { "Mic", 0x0 }, 808 { "Internal Mic", 0x4 }, 809 { "Mix", 0x5 }, 810 }, 811 }; 812 813 static const struct hda_input_mux ad1986a_automic_capture_source = { 814 .num_items = 2, 815 .items = { 816 { "Mic", 0x0 }, 817 { "Mix", 0x5 }, 818 }, 819 }; 820 821 static const struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = { 822 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), 823 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), 824 { } /* end */ 825 }; 826 827 static const struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { 828 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), 829 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), 830 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), 831 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), 832 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT), 833 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), 834 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), 835 { 836 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 837 .name = "Capture Source", 838 .info = ad198x_mux_enum_info, 839 .get = ad198x_mux_enum_get, 840 .put = ad198x_mux_enum_put, 841 }, 842 { 843 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 844 .name = "External Amplifier", 845 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b, 846 .info = ad198x_eapd_info, 847 .get = ad198x_eapd_get, 848 .put = ad198x_eapd_put, 849 .private_value = 0x1b, /* port-D */ 850 }, 851 { } /* end */ 852 }; 853 854 static const struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = { 855 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT), 856 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT), 857 { } /* end */ 858 }; 859 860 /* re-connect the mic boost input according to the jack sensing */ 861 static void ad1986a_automic(struct hda_codec *codec) 862 { 863 unsigned int present; 864 present = snd_hda_jack_detect(codec, 0x1f); 865 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */ 866 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL, 867 present ? 0 : 2); 868 } 869 870 #define AD1986A_MIC_EVENT 0x36 871 872 static void ad1986a_automic_unsol_event(struct hda_codec *codec, 873 unsigned int res) 874 { 875 if ((res >> 26) != AD1986A_MIC_EVENT) 876 return; 877 ad1986a_automic(codec); 878 } 879 880 static int ad1986a_automic_init(struct hda_codec *codec) 881 { 882 ad198x_init(codec); 883 ad1986a_automic(codec); 884 return 0; 885 } 886 887 /* laptop-automute - 2ch only */ 888 889 static void ad1986a_update_hp(struct hda_codec *codec) 890 { 891 struct ad198x_spec *spec = codec->spec; 892 unsigned int mute; 893 894 if (spec->jack_present) 895 mute = HDA_AMP_MUTE; /* mute internal speaker */ 896 else 897 /* unmute internal speaker if necessary */ 898 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0); 899 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, 900 HDA_AMP_MUTE, mute); 901 } 902 903 static void ad1986a_hp_automute(struct hda_codec *codec) 904 { 905 struct ad198x_spec *spec = codec->spec; 906 907 spec->jack_present = snd_hda_jack_detect(codec, 0x1a); 908 if (spec->inv_jack_detect) 909 spec->jack_present = !spec->jack_present; 910 ad1986a_update_hp(codec); 911 } 912 913 #define AD1986A_HP_EVENT 0x37 914 915 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res) 916 { 917 if ((res >> 26) != AD1986A_HP_EVENT) 918 return; 919 ad1986a_hp_automute(codec); 920 } 921 922 static int ad1986a_hp_init(struct hda_codec *codec) 923 { 924 ad198x_init(codec); 925 ad1986a_hp_automute(codec); 926 return 0; 927 } 928 929 /* bind hp and internal speaker mute (with plug check) */ 930 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol, 931 struct snd_ctl_elem_value *ucontrol) 932 { 933 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 934 int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); 935 if (change) 936 ad1986a_update_hp(codec); 937 return change; 938 } 939 940 static const struct snd_kcontrol_new ad1986a_automute_master_mixers[] = { 941 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), 942 { 943 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 944 .name = "Master Playback Switch", 945 .subdevice = HDA_SUBDEV_AMP_FLAG, 946 .info = snd_hda_mixer_amp_switch_info, 947 .get = snd_hda_mixer_amp_switch_get, 948 .put = ad1986a_hp_master_sw_put, 949 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), 950 }, 951 { } /* end */ 952 }; 953 954 955 /* 956 * initialization verbs 957 */ 958 static const struct hda_verb ad1986a_init_verbs[] = { 959 /* Front, Surround, CLFE DAC; mute as default */ 960 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 961 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 962 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 963 /* Downmix - off */ 964 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 965 /* HP, Line-Out, Surround, CLFE selectors */ 966 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0}, 967 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, 968 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, 969 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 970 /* Mono selector */ 971 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0}, 972 /* Mic selector: Mic 1/2 pin */ 973 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0}, 974 /* Line-in selector: Line-in */ 975 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0}, 976 /* Mic 1/2 swap */ 977 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0}, 978 /* Record selector: mic */ 979 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0}, 980 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */ 981 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 982 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 983 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 984 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 985 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 986 /* PC beep */ 987 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0}, 988 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */ 989 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 990 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 991 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 992 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 993 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 994 /* HP Pin */ 995 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 996 /* Front, Surround, CLFE Pins */ 997 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 998 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 999 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1000 /* Mono Pin */ 1001 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1002 /* Mic Pin */ 1003 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1004 /* Line, Aux, CD, Beep-In Pin */ 1005 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1006 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1007 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1008 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1009 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1010 { } /* end */ 1011 }; 1012 1013 static const struct hda_verb ad1986a_ch2_init[] = { 1014 /* Surround out -> Line In */ 1015 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 1016 /* Line-in selectors */ 1017 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 }, 1018 /* CLFE -> Mic in */ 1019 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 1020 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */ 1021 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, 1022 { } /* end */ 1023 }; 1024 1025 static const struct hda_verb ad1986a_ch4_init[] = { 1026 /* Surround out -> Surround */ 1027 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 1028 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, 1029 /* CLFE -> Mic in */ 1030 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 1031 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, 1032 { } /* end */ 1033 }; 1034 1035 static const struct hda_verb ad1986a_ch6_init[] = { 1036 /* Surround out -> Surround out */ 1037 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 1038 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, 1039 /* CLFE -> CLFE */ 1040 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 1041 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 }, 1042 { } /* end */ 1043 }; 1044 1045 static const struct hda_channel_mode ad1986a_modes[3] = { 1046 { 2, ad1986a_ch2_init }, 1047 { 4, ad1986a_ch4_init }, 1048 { 6, ad1986a_ch6_init }, 1049 }; 1050 1051 /* eapd initialization */ 1052 static const struct hda_verb ad1986a_eapd_init_verbs[] = { 1053 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, 1054 {} 1055 }; 1056 1057 static const struct hda_verb ad1986a_automic_verbs[] = { 1058 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1059 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1060 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/ 1061 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0}, 1062 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT}, 1063 {} 1064 }; 1065 1066 /* Ultra initialization */ 1067 static const struct hda_verb ad1986a_ultra_init[] = { 1068 /* eapd initialization */ 1069 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, 1070 /* CLFE -> Mic in */ 1071 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 }, 1072 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1073 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, 1074 { } /* end */ 1075 }; 1076 1077 /* pin sensing on HP jack */ 1078 static const struct hda_verb ad1986a_hp_init_verbs[] = { 1079 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT}, 1080 {} 1081 }; 1082 1083 static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec, 1084 unsigned int res) 1085 { 1086 switch (res >> 26) { 1087 case AD1986A_HP_EVENT: 1088 ad1986a_hp_automute(codec); 1089 break; 1090 case AD1986A_MIC_EVENT: 1091 ad1986a_automic(codec); 1092 break; 1093 } 1094 } 1095 1096 static int ad1986a_samsung_p50_init(struct hda_codec *codec) 1097 { 1098 ad198x_init(codec); 1099 ad1986a_hp_automute(codec); 1100 ad1986a_automic(codec); 1101 return 0; 1102 } 1103 1104 1105 /* models */ 1106 enum { 1107 AD1986A_AUTO, 1108 AD1986A_6STACK, 1109 AD1986A_3STACK, 1110 AD1986A_LAPTOP, 1111 AD1986A_LAPTOP_EAPD, 1112 AD1986A_LAPTOP_AUTOMUTE, 1113 AD1986A_ULTRA, 1114 AD1986A_SAMSUNG, 1115 AD1986A_SAMSUNG_P50, 1116 AD1986A_MODELS 1117 }; 1118 1119 static const char * const ad1986a_models[AD1986A_MODELS] = { 1120 [AD1986A_AUTO] = "auto", 1121 [AD1986A_6STACK] = "6stack", 1122 [AD1986A_3STACK] = "3stack", 1123 [AD1986A_LAPTOP] = "laptop", 1124 [AD1986A_LAPTOP_EAPD] = "laptop-eapd", 1125 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute", 1126 [AD1986A_ULTRA] = "ultra", 1127 [AD1986A_SAMSUNG] = "samsung", 1128 [AD1986A_SAMSUNG_P50] = "samsung-p50", 1129 }; 1130 1131 static const struct snd_pci_quirk ad1986a_cfg_tbl[] = { 1132 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD), 1133 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD), 1134 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD), 1135 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD), 1136 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD), 1137 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD), 1138 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD), 1139 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD), 1140 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP), 1141 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK), 1142 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK), 1143 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP), 1144 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK), 1145 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK), 1146 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK), 1147 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK), 1148 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK), 1149 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), 1150 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), 1151 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50), 1152 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), 1153 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG), 1154 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), 1155 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), 1156 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), 1157 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE), 1158 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP), 1159 {} 1160 }; 1161 1162 #ifdef CONFIG_PM 1163 static const struct hda_amp_list ad1986a_loopbacks[] = { 1164 { 0x13, HDA_OUTPUT, 0 }, /* Mic */ 1165 { 0x14, HDA_OUTPUT, 0 }, /* Phone */ 1166 { 0x15, HDA_OUTPUT, 0 }, /* CD */ 1167 { 0x16, HDA_OUTPUT, 0 }, /* Aux */ 1168 { 0x17, HDA_OUTPUT, 0 }, /* Line */ 1169 { } /* end */ 1170 }; 1171 #endif 1172 1173 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) 1174 { 1175 unsigned int conf = snd_hda_codec_get_pincfg(codec, nid); 1176 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE; 1177 } 1178 #endif /* ENABLE_AD_STATIC_QUIRKS */ 1179 1180 static int alloc_ad_spec(struct hda_codec *codec) 1181 { 1182 struct ad198x_spec *spec; 1183 1184 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1185 if (!spec) 1186 return -ENOMEM; 1187 codec->spec = spec; 1188 snd_hda_gen_spec_init(&spec->gen); 1189 return 0; 1190 } 1191 1192 /* 1193 * AD1986A fixup codes 1194 */ 1195 1196 /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */ 1197 static void ad_fixup_inv_jack_detect(struct hda_codec *codec, 1198 const struct hda_fixup *fix, int action) 1199 { 1200 if (action == HDA_FIXUP_ACT_PRE_PROBE) 1201 codec->inv_jack_detect = 1; 1202 } 1203 1204 enum { 1205 AD1986A_FIXUP_INV_JACK_DETECT, 1206 }; 1207 1208 static const struct hda_fixup ad1986a_fixups[] = { 1209 [AD1986A_FIXUP_INV_JACK_DETECT] = { 1210 .type = HDA_FIXUP_FUNC, 1211 .v.func = ad_fixup_inv_jack_detect, 1212 }, 1213 }; 1214 1215 static const struct snd_pci_quirk ad1986a_fixup_tbl[] = { 1216 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_FIXUP_INV_JACK_DETECT), 1217 {} 1218 }; 1219 1220 /* 1221 */ 1222 static int ad1986a_parse_auto_config(struct hda_codec *codec) 1223 { 1224 int err; 1225 struct ad198x_spec *spec; 1226 1227 err = alloc_ad_spec(codec); 1228 if (err < 0) 1229 return err; 1230 spec = codec->spec; 1231 1232 /* AD1986A has the inverted EAPD implementation */ 1233 codec->inv_eapd = 1; 1234 1235 spec->gen.mixer_nid = 0x07; 1236 spec->gen.beep_nid = 0x19; 1237 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT); 1238 1239 /* AD1986A has a hardware problem that it can't share a stream 1240 * with multiple output pins. The copy of front to surrounds 1241 * causes noisy or silent outputs at a certain timing, e.g. 1242 * changing the volume. 1243 * So, let's disable the shared stream. 1244 */ 1245 spec->gen.multiout.no_share_stream = 1; 1246 1247 snd_hda_pick_fixup(codec, NULL, ad1986a_fixup_tbl, ad1986a_fixups); 1248 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 1249 1250 err = ad198x_parse_auto_config(codec); 1251 if (err < 0) { 1252 snd_hda_gen_free(codec); 1253 return err; 1254 } 1255 1256 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); 1257 1258 return 0; 1259 } 1260 1261 #ifdef ENABLE_AD_STATIC_QUIRKS 1262 static int patch_ad1986a(struct hda_codec *codec) 1263 { 1264 struct ad198x_spec *spec; 1265 int err, board_config; 1266 1267 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS, 1268 ad1986a_models, 1269 ad1986a_cfg_tbl); 1270 if (board_config < 0) { 1271 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 1272 codec->chip_name); 1273 board_config = AD1986A_AUTO; 1274 } 1275 1276 if (board_config == AD1986A_AUTO) 1277 return ad1986a_parse_auto_config(codec); 1278 1279 err = alloc_ad_spec(codec); 1280 if (err < 0) 1281 return err; 1282 spec = codec->spec; 1283 1284 err = snd_hda_attach_beep_device(codec, 0x19); 1285 if (err < 0) { 1286 ad198x_free(codec); 1287 return err; 1288 } 1289 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT); 1290 1291 spec->multiout.max_channels = 6; 1292 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); 1293 spec->multiout.dac_nids = ad1986a_dac_nids; 1294 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; 1295 spec->num_adc_nids = 1; 1296 spec->adc_nids = ad1986a_adc_nids; 1297 spec->capsrc_nids = ad1986a_capsrc_nids; 1298 spec->input_mux = &ad1986a_capture_source; 1299 spec->num_mixers = 1; 1300 spec->mixers[0] = ad1986a_mixers; 1301 spec->num_init_verbs = 1; 1302 spec->init_verbs[0] = ad1986a_init_verbs; 1303 #ifdef CONFIG_PM 1304 spec->loopback.amplist = ad1986a_loopbacks; 1305 #endif 1306 spec->vmaster_nid = 0x1b; 1307 codec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */ 1308 1309 codec->patch_ops = ad198x_patch_ops; 1310 1311 /* override some parameters */ 1312 switch (board_config) { 1313 case AD1986A_3STACK: 1314 spec->num_mixers = 2; 1315 spec->mixers[1] = ad1986a_3st_mixers; 1316 spec->num_init_verbs = 2; 1317 spec->init_verbs[1] = ad1986a_ch2_init; 1318 spec->channel_mode = ad1986a_modes; 1319 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); 1320 spec->need_dac_fix = 1; 1321 spec->multiout.max_channels = 2; 1322 spec->multiout.num_dacs = 1; 1323 break; 1324 case AD1986A_LAPTOP: 1325 spec->mixers[0] = ad1986a_laptop_mixers; 1326 spec->multiout.max_channels = 2; 1327 spec->multiout.num_dacs = 1; 1328 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1329 break; 1330 case AD1986A_LAPTOP_EAPD: 1331 spec->num_mixers = 3; 1332 spec->mixers[0] = ad1986a_laptop_master_mixers; 1333 spec->mixers[1] = ad1986a_laptop_eapd_mixers; 1334 spec->mixers[2] = ad1986a_laptop_intmic_mixers; 1335 spec->num_init_verbs = 2; 1336 spec->init_verbs[1] = ad1986a_eapd_init_verbs; 1337 spec->multiout.max_channels = 2; 1338 spec->multiout.num_dacs = 1; 1339 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1340 if (!is_jack_available(codec, 0x25)) 1341 spec->multiout.dig_out_nid = 0; 1342 spec->input_mux = &ad1986a_laptop_eapd_capture_source; 1343 break; 1344 case AD1986A_SAMSUNG: 1345 spec->num_mixers = 2; 1346 spec->mixers[0] = ad1986a_laptop_master_mixers; 1347 spec->mixers[1] = ad1986a_laptop_eapd_mixers; 1348 spec->num_init_verbs = 3; 1349 spec->init_verbs[1] = ad1986a_eapd_init_verbs; 1350 spec->init_verbs[2] = ad1986a_automic_verbs; 1351 spec->multiout.max_channels = 2; 1352 spec->multiout.num_dacs = 1; 1353 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1354 if (!is_jack_available(codec, 0x25)) 1355 spec->multiout.dig_out_nid = 0; 1356 spec->input_mux = &ad1986a_automic_capture_source; 1357 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event; 1358 codec->patch_ops.init = ad1986a_automic_init; 1359 break; 1360 case AD1986A_SAMSUNG_P50: 1361 spec->num_mixers = 2; 1362 spec->mixers[0] = ad1986a_automute_master_mixers; 1363 spec->mixers[1] = ad1986a_laptop_eapd_mixers; 1364 spec->num_init_verbs = 4; 1365 spec->init_verbs[1] = ad1986a_eapd_init_verbs; 1366 spec->init_verbs[2] = ad1986a_automic_verbs; 1367 spec->init_verbs[3] = ad1986a_hp_init_verbs; 1368 spec->multiout.max_channels = 2; 1369 spec->multiout.num_dacs = 1; 1370 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1371 if (!is_jack_available(codec, 0x25)) 1372 spec->multiout.dig_out_nid = 0; 1373 spec->input_mux = &ad1986a_automic_capture_source; 1374 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event; 1375 codec->patch_ops.init = ad1986a_samsung_p50_init; 1376 break; 1377 case AD1986A_LAPTOP_AUTOMUTE: 1378 spec->num_mixers = 3; 1379 spec->mixers[0] = ad1986a_automute_master_mixers; 1380 spec->mixers[1] = ad1986a_laptop_eapd_mixers; 1381 spec->mixers[2] = ad1986a_laptop_intmic_mixers; 1382 spec->num_init_verbs = 3; 1383 spec->init_verbs[1] = ad1986a_eapd_init_verbs; 1384 spec->init_verbs[2] = ad1986a_hp_init_verbs; 1385 spec->multiout.max_channels = 2; 1386 spec->multiout.num_dacs = 1; 1387 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1388 if (!is_jack_available(codec, 0x25)) 1389 spec->multiout.dig_out_nid = 0; 1390 spec->input_mux = &ad1986a_laptop_eapd_capture_source; 1391 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event; 1392 codec->patch_ops.init = ad1986a_hp_init; 1393 /* Lenovo N100 seems to report the reversed bit 1394 * for HP jack-sensing 1395 */ 1396 spec->inv_jack_detect = 1; 1397 break; 1398 case AD1986A_ULTRA: 1399 spec->mixers[0] = ad1986a_laptop_eapd_mixers; 1400 spec->num_init_verbs = 2; 1401 spec->init_verbs[1] = ad1986a_ultra_init; 1402 spec->multiout.max_channels = 2; 1403 spec->multiout.num_dacs = 1; 1404 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1405 spec->multiout.dig_out_nid = 0; 1406 break; 1407 } 1408 1409 /* AD1986A has a hardware problem that it can't share a stream 1410 * with multiple output pins. The copy of front to surrounds 1411 * causes noisy or silent outputs at a certain timing, e.g. 1412 * changing the volume. 1413 * So, let's disable the shared stream. 1414 */ 1415 spec->multiout.no_share_stream = 1; 1416 1417 codec->no_trigger_sense = 1; 1418 codec->no_sticky_stream = 1; 1419 1420 return 0; 1421 } 1422 #else /* ENABLE_AD_STATIC_QUIRKS */ 1423 #define patch_ad1986a ad1986a_parse_auto_config 1424 #endif /* ENABLE_AD_STATIC_QUIRKS */ 1425 1426 /* 1427 * AD1983 specific 1428 */ 1429 1430 #ifdef ENABLE_AD_STATIC_QUIRKS 1431 #define AD1983_SPDIF_OUT 0x02 1432 #define AD1983_DAC 0x03 1433 #define AD1983_ADC 0x04 1434 1435 static const hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; 1436 static const hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC }; 1437 static const hda_nid_t ad1983_capsrc_nids[1] = { 0x15 }; 1438 1439 static const struct hda_input_mux ad1983_capture_source = { 1440 .num_items = 4, 1441 .items = { 1442 { "Mic", 0x0 }, 1443 { "Line", 0x1 }, 1444 { "Mix", 0x2 }, 1445 { "Mix Mono", 0x3 }, 1446 }, 1447 }; 1448 1449 /* 1450 * SPDIF playback route 1451 */ 1452 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1453 { 1454 static const char * const texts[] = { "PCM", "ADC" }; 1455 1456 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1457 uinfo->count = 1; 1458 uinfo->value.enumerated.items = 2; 1459 if (uinfo->value.enumerated.item > 1) 1460 uinfo->value.enumerated.item = 1; 1461 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 1462 return 0; 1463 } 1464 1465 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1466 { 1467 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1468 struct ad198x_spec *spec = codec->spec; 1469 1470 ucontrol->value.enumerated.item[0] = spec->spdif_route; 1471 return 0; 1472 } 1473 1474 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1475 { 1476 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1477 struct ad198x_spec *spec = codec->spec; 1478 1479 if (ucontrol->value.enumerated.item[0] > 1) 1480 return -EINVAL; 1481 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { 1482 spec->spdif_route = ucontrol->value.enumerated.item[0]; 1483 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0, 1484 AC_VERB_SET_CONNECT_SEL, 1485 spec->spdif_route); 1486 return 1; 1487 } 1488 return 0; 1489 } 1490 1491 static const struct snd_kcontrol_new ad1983_mixers[] = { 1492 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), 1493 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), 1494 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), 1495 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), 1496 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), 1497 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), 1498 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1499 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1500 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1501 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1502 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), 1503 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), 1504 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT), 1505 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 1506 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 1507 { 1508 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1509 .name = "Capture Source", 1510 .info = ad198x_mux_enum_info, 1511 .get = ad198x_mux_enum_get, 1512 .put = ad198x_mux_enum_put, 1513 }, 1514 { 1515 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1516 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 1517 .info = ad1983_spdif_route_info, 1518 .get = ad1983_spdif_route_get, 1519 .put = ad1983_spdif_route_put, 1520 }, 1521 { } /* end */ 1522 }; 1523 1524 static const struct hda_verb ad1983_init_verbs[] = { 1525 /* Front, HP, Mono; mute as default */ 1526 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1527 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1528 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1529 /* Beep, PCM, Mic, Line-In: mute */ 1530 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1531 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1532 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1533 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1534 /* Front, HP selectors; from Mix */ 1535 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, 1536 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, 1537 /* Mono selector; from Mix */ 1538 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, 1539 /* Mic selector; Mic */ 1540 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, 1541 /* Line-in selector: Line-in */ 1542 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 1543 /* Mic boost: 0dB */ 1544 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1545 /* Record selector: mic */ 1546 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, 1547 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1548 /* SPDIF route: PCM */ 1549 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, 1550 /* Front Pin */ 1551 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1552 /* HP Pin */ 1553 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 1554 /* Mono Pin */ 1555 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1556 /* Mic Pin */ 1557 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1558 /* Line Pin */ 1559 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1560 { } /* end */ 1561 }; 1562 1563 #ifdef CONFIG_PM 1564 static const struct hda_amp_list ad1983_loopbacks[] = { 1565 { 0x12, HDA_OUTPUT, 0 }, /* Mic */ 1566 { 0x13, HDA_OUTPUT, 0 }, /* Line */ 1567 { } /* end */ 1568 }; 1569 #endif 1570 1571 /* models */ 1572 enum { 1573 AD1983_AUTO, 1574 AD1983_BASIC, 1575 AD1983_MODELS 1576 }; 1577 1578 static const char * const ad1983_models[AD1983_MODELS] = { 1579 [AD1983_AUTO] = "auto", 1580 [AD1983_BASIC] = "basic", 1581 }; 1582 #endif /* ENABLE_AD_STATIC_QUIRKS */ 1583 1584 1585 /* 1586 * SPDIF mux control for AD1983 auto-parser 1587 */ 1588 static int ad1983_auto_smux_enum_info(struct snd_kcontrol *kcontrol, 1589 struct snd_ctl_elem_info *uinfo) 1590 { 1591 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1592 struct ad198x_spec *spec = codec->spec; 1593 static const char * const texts2[] = { "PCM", "ADC" }; 1594 static const char * const texts3[] = { "PCM", "ADC1", "ADC2" }; 1595 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid; 1596 int num_conns = snd_hda_get_num_conns(codec, dig_out); 1597 1598 if (num_conns == 2) 1599 return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts2); 1600 else if (num_conns == 3) 1601 return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3); 1602 else 1603 return -EINVAL; 1604 } 1605 1606 static int ad1983_auto_smux_enum_get(struct snd_kcontrol *kcontrol, 1607 struct snd_ctl_elem_value *ucontrol) 1608 { 1609 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1610 struct ad198x_spec *spec = codec->spec; 1611 1612 ucontrol->value.enumerated.item[0] = spec->cur_smux; 1613 return 0; 1614 } 1615 1616 static int ad1983_auto_smux_enum_put(struct snd_kcontrol *kcontrol, 1617 struct snd_ctl_elem_value *ucontrol) 1618 { 1619 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1620 struct ad198x_spec *spec = codec->spec; 1621 unsigned int val = ucontrol->value.enumerated.item[0]; 1622 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid; 1623 int num_conns = snd_hda_get_num_conns(codec, dig_out); 1624 1625 if (val >= num_conns) 1626 return -EINVAL; 1627 if (spec->cur_smux == val) 1628 return 0; 1629 spec->cur_smux = val; 1630 snd_hda_codec_write_cache(codec, dig_out, 0, 1631 AC_VERB_SET_CONNECT_SEL, val); 1632 return 1; 1633 } 1634 1635 static struct snd_kcontrol_new ad1983_auto_smux_mixer = { 1636 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1637 .name = "IEC958 Playback Source", 1638 .info = ad1983_auto_smux_enum_info, 1639 .get = ad1983_auto_smux_enum_get, 1640 .put = ad1983_auto_smux_enum_put, 1641 }; 1642 1643 static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec) 1644 { 1645 struct ad198x_spec *spec = codec->spec; 1646 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid; 1647 int num_conns; 1648 1649 if (!dig_out) 1650 return 0; 1651 num_conns = snd_hda_get_num_conns(codec, dig_out); 1652 if (num_conns != 2 && num_conns != 3) 1653 return 0; 1654 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1983_auto_smux_mixer)) 1655 return -ENOMEM; 1656 return 0; 1657 } 1658 1659 static int ad1983_parse_auto_config(struct hda_codec *codec) 1660 { 1661 struct ad198x_spec *spec; 1662 int err; 1663 1664 err = alloc_ad_spec(codec); 1665 if (err < 0) 1666 return err; 1667 spec = codec->spec; 1668 1669 spec->gen.beep_nid = 0x10; 1670 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 1671 err = ad198x_parse_auto_config(codec); 1672 if (err < 0) 1673 goto error; 1674 err = ad1983_add_spdif_mux_ctl(codec); 1675 if (err < 0) 1676 goto error; 1677 return 0; 1678 1679 error: 1680 snd_hda_gen_free(codec); 1681 return err; 1682 } 1683 1684 #ifdef ENABLE_AD_STATIC_QUIRKS 1685 static int patch_ad1983(struct hda_codec *codec) 1686 { 1687 struct ad198x_spec *spec; 1688 int board_config; 1689 int err; 1690 1691 board_config = snd_hda_check_board_config(codec, AD1983_MODELS, 1692 ad1983_models, NULL); 1693 if (board_config < 0) { 1694 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 1695 codec->chip_name); 1696 board_config = AD1983_AUTO; 1697 } 1698 1699 if (board_config == AD1983_AUTO) 1700 return ad1983_parse_auto_config(codec); 1701 1702 err = alloc_ad_spec(codec); 1703 if (err < 0) 1704 return err; 1705 spec = codec->spec; 1706 1707 err = snd_hda_attach_beep_device(codec, 0x10); 1708 if (err < 0) { 1709 ad198x_free(codec); 1710 return err; 1711 } 1712 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 1713 1714 spec->multiout.max_channels = 2; 1715 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); 1716 spec->multiout.dac_nids = ad1983_dac_nids; 1717 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; 1718 spec->num_adc_nids = 1; 1719 spec->adc_nids = ad1983_adc_nids; 1720 spec->capsrc_nids = ad1983_capsrc_nids; 1721 spec->input_mux = &ad1983_capture_source; 1722 spec->num_mixers = 1; 1723 spec->mixers[0] = ad1983_mixers; 1724 spec->num_init_verbs = 1; 1725 spec->init_verbs[0] = ad1983_init_verbs; 1726 spec->spdif_route = 0; 1727 #ifdef CONFIG_PM 1728 spec->loopback.amplist = ad1983_loopbacks; 1729 #endif 1730 spec->vmaster_nid = 0x05; 1731 1732 codec->patch_ops = ad198x_patch_ops; 1733 1734 codec->no_trigger_sense = 1; 1735 codec->no_sticky_stream = 1; 1736 1737 return 0; 1738 } 1739 #else /* ENABLE_AD_STATIC_QUIRKS */ 1740 #define patch_ad1983 ad1983_parse_auto_config 1741 #endif /* ENABLE_AD_STATIC_QUIRKS */ 1742 1743 1744 /* 1745 * AD1981 HD specific 1746 */ 1747 1748 #ifdef ENABLE_AD_STATIC_QUIRKS 1749 #define AD1981_SPDIF_OUT 0x02 1750 #define AD1981_DAC 0x03 1751 #define AD1981_ADC 0x04 1752 1753 static const hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; 1754 static const hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC }; 1755 static const hda_nid_t ad1981_capsrc_nids[1] = { 0x15 }; 1756 1757 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ 1758 static const struct hda_input_mux ad1981_capture_source = { 1759 .num_items = 7, 1760 .items = { 1761 { "Front Mic", 0x0 }, 1762 { "Line", 0x1 }, 1763 { "Mix", 0x2 }, 1764 { "Mix Mono", 0x3 }, 1765 { "CD", 0x4 }, 1766 { "Mic", 0x6 }, 1767 { "Aux", 0x7 }, 1768 }, 1769 }; 1770 1771 static const struct snd_kcontrol_new ad1981_mixers[] = { 1772 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), 1773 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), 1774 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), 1775 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), 1776 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), 1777 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), 1778 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1779 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1780 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1781 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1782 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), 1783 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), 1784 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 1785 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 1786 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), 1787 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), 1788 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 1789 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), 1790 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT), 1791 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT), 1792 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 1793 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 1794 { 1795 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1796 .name = "Capture Source", 1797 .info = ad198x_mux_enum_info, 1798 .get = ad198x_mux_enum_get, 1799 .put = ad198x_mux_enum_put, 1800 }, 1801 /* identical with AD1983 */ 1802 { 1803 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1804 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 1805 .info = ad1983_spdif_route_info, 1806 .get = ad1983_spdif_route_get, 1807 .put = ad1983_spdif_route_put, 1808 }, 1809 { } /* end */ 1810 }; 1811 1812 static const struct hda_verb ad1981_init_verbs[] = { 1813 /* Front, HP, Mono; mute as default */ 1814 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1815 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1816 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1817 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */ 1818 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1819 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1820 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1821 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1822 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1823 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1824 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1825 /* Front, HP selectors; from Mix */ 1826 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, 1827 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, 1828 /* Mono selector; from Mix */ 1829 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, 1830 /* Mic Mixer; select Front Mic */ 1831 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1832 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1833 /* Mic boost: 0dB */ 1834 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1835 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1836 /* Record selector: Front mic */ 1837 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, 1838 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1839 /* SPDIF route: PCM */ 1840 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, 1841 /* Front Pin */ 1842 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1843 /* HP Pin */ 1844 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 1845 /* Mono Pin */ 1846 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1847 /* Front & Rear Mic Pins */ 1848 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1849 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1850 /* Line Pin */ 1851 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1852 /* Digital Beep */ 1853 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, 1854 /* Line-Out as Input: disabled */ 1855 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1856 { } /* end */ 1857 }; 1858 1859 #ifdef CONFIG_PM 1860 static const struct hda_amp_list ad1981_loopbacks[] = { 1861 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */ 1862 { 0x13, HDA_OUTPUT, 0 }, /* Line */ 1863 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */ 1864 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */ 1865 { 0x1d, HDA_OUTPUT, 0 }, /* CD */ 1866 { } /* end */ 1867 }; 1868 #endif 1869 1870 /* 1871 * Patch for HP nx6320 1872 * 1873 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal 1874 * speaker output enabled _and_ mute-LED off. 1875 */ 1876 1877 #define AD1981_HP_EVENT 0x37 1878 #define AD1981_MIC_EVENT 0x38 1879 1880 static const struct hda_verb ad1981_hp_init_verbs[] = { 1881 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */ 1882 /* pin sensing on HP and Mic jacks */ 1883 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT}, 1884 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT}, 1885 {} 1886 }; 1887 1888 /* turn on/off EAPD (+ mute HP) as a master switch */ 1889 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol, 1890 struct snd_ctl_elem_value *ucontrol) 1891 { 1892 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1893 struct ad198x_spec *spec = codec->spec; 1894 1895 if (! ad198x_eapd_put(kcontrol, ucontrol)) 1896 return 0; 1897 /* change speaker pin appropriately */ 1898 snd_hda_set_pin_ctl(codec, 0x05, spec->cur_eapd ? PIN_OUT : 0); 1899 /* toggle HP mute appropriately */ 1900 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0, 1901 HDA_AMP_MUTE, 1902 spec->cur_eapd ? 0 : HDA_AMP_MUTE); 1903 return 1; 1904 } 1905 1906 /* bind volumes of both NID 0x05 and 0x06 */ 1907 static const struct hda_bind_ctls ad1981_hp_bind_master_vol = { 1908 .ops = &snd_hda_bind_vol, 1909 .values = { 1910 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), 1911 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT), 1912 0 1913 }, 1914 }; 1915 1916 /* mute internal speaker if HP is plugged */ 1917 static void ad1981_hp_automute(struct hda_codec *codec) 1918 { 1919 unsigned int present; 1920 1921 present = snd_hda_jack_detect(codec, 0x06); 1922 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0, 1923 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 1924 } 1925 1926 /* toggle input of built-in and mic jack appropriately */ 1927 static void ad1981_hp_automic(struct hda_codec *codec) 1928 { 1929 static const struct hda_verb mic_jack_on[] = { 1930 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1931 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1932 {} 1933 }; 1934 static const struct hda_verb mic_jack_off[] = { 1935 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1936 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1937 {} 1938 }; 1939 unsigned int present; 1940 1941 present = snd_hda_jack_detect(codec, 0x08); 1942 if (present) 1943 snd_hda_sequence_write(codec, mic_jack_on); 1944 else 1945 snd_hda_sequence_write(codec, mic_jack_off); 1946 } 1947 1948 /* unsolicited event for HP jack sensing */ 1949 static void ad1981_hp_unsol_event(struct hda_codec *codec, 1950 unsigned int res) 1951 { 1952 res >>= 26; 1953 switch (res) { 1954 case AD1981_HP_EVENT: 1955 ad1981_hp_automute(codec); 1956 break; 1957 case AD1981_MIC_EVENT: 1958 ad1981_hp_automic(codec); 1959 break; 1960 } 1961 } 1962 1963 static const struct hda_input_mux ad1981_hp_capture_source = { 1964 .num_items = 3, 1965 .items = { 1966 { "Mic", 0x0 }, 1967 { "Dock Mic", 0x1 }, 1968 { "Mix", 0x2 }, 1969 }, 1970 }; 1971 1972 static const struct snd_kcontrol_new ad1981_hp_mixers[] = { 1973 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol), 1974 { 1975 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1976 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05, 1977 .name = "Master Playback Switch", 1978 .info = ad198x_eapd_info, 1979 .get = ad198x_eapd_get, 1980 .put = ad1981_hp_master_sw_put, 1981 .private_value = 0x05, 1982 }, 1983 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1984 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1985 #if 0 1986 /* FIXME: analog mic/line loopback doesn't work with my tests... 1987 * (although recording is OK) 1988 */ 1989 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1990 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1991 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), 1992 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), 1993 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), 1994 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), 1995 /* FIXME: does this laptop have analog CD connection? */ 1996 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 1997 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), 1998 #endif 1999 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT), 2000 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT), 2001 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 2002 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 2003 { 2004 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2005 .name = "Capture Source", 2006 .info = ad198x_mux_enum_info, 2007 .get = ad198x_mux_enum_get, 2008 .put = ad198x_mux_enum_put, 2009 }, 2010 { } /* end */ 2011 }; 2012 2013 /* initialize jack-sensing, too */ 2014 static int ad1981_hp_init(struct hda_codec *codec) 2015 { 2016 ad198x_init(codec); 2017 ad1981_hp_automute(codec); 2018 ad1981_hp_automic(codec); 2019 return 0; 2020 } 2021 2022 /* configuration for Toshiba Laptops */ 2023 static const struct hda_verb ad1981_toshiba_init_verbs[] = { 2024 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */ 2025 /* pin sensing on HP and Mic jacks */ 2026 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT}, 2027 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT}, 2028 {} 2029 }; 2030 2031 static const struct snd_kcontrol_new ad1981_toshiba_mixers[] = { 2032 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT), 2033 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT), 2034 { } 2035 }; 2036 2037 /* configuration for Lenovo Thinkpad T60 */ 2038 static const struct snd_kcontrol_new ad1981_thinkpad_mixers[] = { 2039 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT), 2040 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT), 2041 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 2042 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 2043 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 2044 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 2045 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 2046 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), 2047 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT), 2048 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 2049 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 2050 { 2051 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2052 .name = "Capture Source", 2053 .info = ad198x_mux_enum_info, 2054 .get = ad198x_mux_enum_get, 2055 .put = ad198x_mux_enum_put, 2056 }, 2057 /* identical with AD1983 */ 2058 { 2059 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2060 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 2061 .info = ad1983_spdif_route_info, 2062 .get = ad1983_spdif_route_get, 2063 .put = ad1983_spdif_route_put, 2064 }, 2065 { } /* end */ 2066 }; 2067 2068 static const struct hda_input_mux ad1981_thinkpad_capture_source = { 2069 .num_items = 3, 2070 .items = { 2071 { "Mic", 0x0 }, 2072 { "Mix", 0x2 }, 2073 { "CD", 0x4 }, 2074 }, 2075 }; 2076 2077 /* models */ 2078 enum { 2079 AD1981_AUTO, 2080 AD1981_BASIC, 2081 AD1981_HP, 2082 AD1981_THINKPAD, 2083 AD1981_TOSHIBA, 2084 AD1981_MODELS 2085 }; 2086 2087 static const char * const ad1981_models[AD1981_MODELS] = { 2088 [AD1981_AUTO] = "auto", 2089 [AD1981_HP] = "hp", 2090 [AD1981_THINKPAD] = "thinkpad", 2091 [AD1981_BASIC] = "basic", 2092 [AD1981_TOSHIBA] = "toshiba" 2093 }; 2094 2095 static const struct snd_pci_quirk ad1981_cfg_tbl[] = { 2096 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD), 2097 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD), 2098 /* All HP models */ 2099 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP), 2100 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA), 2101 /* Lenovo Thinkpad T60/X60/Z6xx */ 2102 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD), 2103 /* HP nx6320 (reversed SSID, H/W bug) */ 2104 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP), 2105 {} 2106 }; 2107 #endif /* ENABLE_AD_STATIC_QUIRKS */ 2108 2109 2110 /* follow EAPD via vmaster hook */ 2111 static void ad_vmaster_eapd_hook(void *private_data, int enabled) 2112 { 2113 struct hda_codec *codec = private_data; 2114 struct ad198x_spec *spec = codec->spec; 2115 2116 if (!spec->eapd_nid) 2117 return; 2118 snd_hda_codec_update_cache(codec, spec->eapd_nid, 0, 2119 AC_VERB_SET_EAPD_BTLENABLE, 2120 enabled ? 0x02 : 0x00); 2121 } 2122 2123 static void ad1981_fixup_hp_eapd(struct hda_codec *codec, 2124 const struct hda_fixup *fix, int action) 2125 { 2126 struct ad198x_spec *spec = codec->spec; 2127 2128 if (action == HDA_FIXUP_ACT_PRE_PROBE) { 2129 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook; 2130 spec->eapd_nid = 0x05; 2131 } 2132 } 2133 2134 /* set the upper-limit for mixer amp to 0dB for avoiding the possible 2135 * damage by overloading 2136 */ 2137 static void ad1981_fixup_amp_override(struct hda_codec *codec, 2138 const struct hda_fixup *fix, int action) 2139 { 2140 if (action == HDA_FIXUP_ACT_PRE_PROBE) 2141 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, 2142 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 2143 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 2144 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 2145 (1 << AC_AMPCAP_MUTE_SHIFT)); 2146 } 2147 2148 enum { 2149 AD1981_FIXUP_AMP_OVERRIDE, 2150 AD1981_FIXUP_HP_EAPD, 2151 }; 2152 2153 static const struct hda_fixup ad1981_fixups[] = { 2154 [AD1981_FIXUP_AMP_OVERRIDE] = { 2155 .type = HDA_FIXUP_FUNC, 2156 .v.func = ad1981_fixup_amp_override, 2157 }, 2158 [AD1981_FIXUP_HP_EAPD] = { 2159 .type = HDA_FIXUP_FUNC, 2160 .v.func = ad1981_fixup_hp_eapd, 2161 .chained = true, 2162 .chain_id = AD1981_FIXUP_AMP_OVERRIDE, 2163 }, 2164 }; 2165 2166 static const struct snd_pci_quirk ad1981_fixup_tbl[] = { 2167 SND_PCI_QUIRK_VENDOR(0x1014, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE), 2168 SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1981_FIXUP_HP_EAPD), 2169 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE), 2170 /* HP nx6320 (reversed SSID, H/W bug) */ 2171 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_FIXUP_HP_EAPD), 2172 {} 2173 }; 2174 2175 static int ad1981_parse_auto_config(struct hda_codec *codec) 2176 { 2177 struct ad198x_spec *spec; 2178 int err; 2179 2180 err = alloc_ad_spec(codec); 2181 if (err < 0) 2182 return -ENOMEM; 2183 spec = codec->spec; 2184 2185 spec->gen.mixer_nid = 0x0e; 2186 spec->gen.beep_nid = 0x10; 2187 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); 2188 2189 snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups); 2190 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 2191 2192 err = ad198x_parse_auto_config(codec); 2193 if (err < 0) 2194 goto error; 2195 err = ad1983_add_spdif_mux_ctl(codec); 2196 if (err < 0) 2197 goto error; 2198 2199 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); 2200 2201 return 0; 2202 2203 error: 2204 snd_hda_gen_free(codec); 2205 return err; 2206 } 2207 2208 #ifdef ENABLE_AD_STATIC_QUIRKS 2209 static int patch_ad1981(struct hda_codec *codec) 2210 { 2211 struct ad198x_spec *spec; 2212 int err, board_config; 2213 2214 board_config = snd_hda_check_board_config(codec, AD1981_MODELS, 2215 ad1981_models, 2216 ad1981_cfg_tbl); 2217 if (board_config < 0) { 2218 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 2219 codec->chip_name); 2220 board_config = AD1981_AUTO; 2221 } 2222 2223 if (board_config == AD1981_AUTO) 2224 return ad1981_parse_auto_config(codec); 2225 2226 err = alloc_ad_spec(codec); 2227 if (err < 0) 2228 return -ENOMEM; 2229 spec = codec->spec; 2230 2231 err = snd_hda_attach_beep_device(codec, 0x10); 2232 if (err < 0) { 2233 ad198x_free(codec); 2234 return err; 2235 } 2236 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); 2237 2238 spec->multiout.max_channels = 2; 2239 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); 2240 spec->multiout.dac_nids = ad1981_dac_nids; 2241 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; 2242 spec->num_adc_nids = 1; 2243 spec->adc_nids = ad1981_adc_nids; 2244 spec->capsrc_nids = ad1981_capsrc_nids; 2245 spec->input_mux = &ad1981_capture_source; 2246 spec->num_mixers = 1; 2247 spec->mixers[0] = ad1981_mixers; 2248 spec->num_init_verbs = 1; 2249 spec->init_verbs[0] = ad1981_init_verbs; 2250 spec->spdif_route = 0; 2251 #ifdef CONFIG_PM 2252 spec->loopback.amplist = ad1981_loopbacks; 2253 #endif 2254 spec->vmaster_nid = 0x05; 2255 2256 codec->patch_ops = ad198x_patch_ops; 2257 2258 /* override some parameters */ 2259 switch (board_config) { 2260 case AD1981_HP: 2261 spec->mixers[0] = ad1981_hp_mixers; 2262 spec->num_init_verbs = 2; 2263 spec->init_verbs[1] = ad1981_hp_init_verbs; 2264 if (!is_jack_available(codec, 0x0a)) 2265 spec->multiout.dig_out_nid = 0; 2266 spec->input_mux = &ad1981_hp_capture_source; 2267 2268 codec->patch_ops.init = ad1981_hp_init; 2269 codec->patch_ops.unsol_event = ad1981_hp_unsol_event; 2270 /* set the upper-limit for mixer amp to 0dB for avoiding the 2271 * possible damage by overloading 2272 */ 2273 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, 2274 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 2275 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 2276 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 2277 (1 << AC_AMPCAP_MUTE_SHIFT)); 2278 break; 2279 case AD1981_THINKPAD: 2280 spec->mixers[0] = ad1981_thinkpad_mixers; 2281 spec->input_mux = &ad1981_thinkpad_capture_source; 2282 /* set the upper-limit for mixer amp to 0dB for avoiding the 2283 * possible damage by overloading 2284 */ 2285 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, 2286 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 2287 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 2288 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 2289 (1 << AC_AMPCAP_MUTE_SHIFT)); 2290 break; 2291 case AD1981_TOSHIBA: 2292 spec->mixers[0] = ad1981_hp_mixers; 2293 spec->mixers[1] = ad1981_toshiba_mixers; 2294 spec->num_init_verbs = 2; 2295 spec->init_verbs[1] = ad1981_toshiba_init_verbs; 2296 spec->multiout.dig_out_nid = 0; 2297 spec->input_mux = &ad1981_hp_capture_source; 2298 codec->patch_ops.init = ad1981_hp_init; 2299 codec->patch_ops.unsol_event = ad1981_hp_unsol_event; 2300 break; 2301 } 2302 2303 codec->no_trigger_sense = 1; 2304 codec->no_sticky_stream = 1; 2305 2306 return 0; 2307 } 2308 #else /* ENABLE_AD_STATIC_QUIRKS */ 2309 #define patch_ad1981 ad1981_parse_auto_config 2310 #endif /* ENABLE_AD_STATIC_QUIRKS */ 2311 2312 2313 /* 2314 * AD1988 2315 * 2316 * Output pins and routes 2317 * 2318 * Pin Mix Sel DAC (*) 2319 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06 2320 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06 2321 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a 2322 * port-D 0x12 (mute/hp) <- 0x29 <- 04 2323 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a 2324 * port-F 0x16 (mute) <- 0x2a <- 06 2325 * port-G 0x24 (mute) <- 0x27 <- 05 2326 * port-H 0x25 (mute) <- 0x28 <- 0a 2327 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06 2328 * 2329 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah 2330 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug. 2331 * 2332 * Input pins and routes 2333 * 2334 * pin boost mix input # / adc input # 2335 * port-A 0x11 -> 0x38 -> mix 2, ADC 0 2336 * port-B 0x14 -> 0x39 -> mix 0, ADC 1 2337 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2 2338 * port-D 0x12 -> 0x3d -> mix 3, ADC 8 2339 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4 2340 * port-F 0x16 -> 0x3b -> mix 5, ADC 3 2341 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6 2342 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7 2343 * 2344 * 2345 * DAC assignment 2346 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03 2347 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03 2348 * 2349 * Inputs of Analog Mix (0x20) 2350 * 0:Port-B (front mic) 2351 * 1:Port-C/G/H (line-in) 2352 * 2:Port-A 2353 * 3:Port-D (line-in/2) 2354 * 4:Port-E/G/H (mic-in) 2355 * 5:Port-F (mic2-in) 2356 * 6:CD 2357 * 7:Beep 2358 * 2359 * ADC selection 2360 * 0:Port-A 2361 * 1:Port-B (front mic-in) 2362 * 2:Port-C (line-in) 2363 * 3:Port-F (mic2-in) 2364 * 4:Port-E (mic-in) 2365 * 5:CD 2366 * 6:Port-G 2367 * 7:Port-H 2368 * 8:Port-D (line-in/2) 2369 * 9:Mix 2370 * 2371 * Proposed pin assignments by the datasheet 2372 * 2373 * 6-stack 2374 * Port-A front headphone 2375 * B front mic-in 2376 * C rear line-in 2377 * D rear front-out 2378 * E rear mic-in 2379 * F rear surround 2380 * G rear CLFE 2381 * H rear side 2382 * 2383 * 3-stack 2384 * Port-A front headphone 2385 * B front mic 2386 * C rear line-in/surround 2387 * D rear front-out 2388 * E rear mic-in/CLFE 2389 * 2390 * laptop 2391 * Port-A headphone 2392 * B mic-in 2393 * C docking station 2394 * D internal speaker (with EAPD) 2395 * E/F quad mic array 2396 */ 2397 2398 2399 #ifdef ENABLE_AD_STATIC_QUIRKS 2400 /* models */ 2401 enum { 2402 AD1988_AUTO, 2403 AD1988_6STACK, 2404 AD1988_6STACK_DIG, 2405 AD1988_3STACK, 2406 AD1988_3STACK_DIG, 2407 AD1988_LAPTOP, 2408 AD1988_LAPTOP_DIG, 2409 AD1988_MODEL_LAST, 2410 }; 2411 2412 /* reivision id to check workarounds */ 2413 #define AD1988A_REV2 0x100200 2414 2415 #define is_rev2(codec) \ 2416 ((codec)->vendor_id == 0x11d41988 && \ 2417 (codec)->revision_id == AD1988A_REV2) 2418 2419 /* 2420 * mixers 2421 */ 2422 2423 static const hda_nid_t ad1988_6stack_dac_nids[4] = { 2424 0x04, 0x06, 0x05, 0x0a 2425 }; 2426 2427 static const hda_nid_t ad1988_3stack_dac_nids[3] = { 2428 0x04, 0x05, 0x0a 2429 }; 2430 2431 /* for AD1988A revision-2, DAC2-4 are swapped */ 2432 static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = { 2433 0x04, 0x05, 0x0a, 0x06 2434 }; 2435 2436 static const hda_nid_t ad1988_alt_dac_nid[1] = { 2437 0x03 2438 }; 2439 2440 static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = { 2441 0x04, 0x0a, 0x06 2442 }; 2443 2444 static const hda_nid_t ad1988_adc_nids[3] = { 2445 0x08, 0x09, 0x0f 2446 }; 2447 2448 static const hda_nid_t ad1988_capsrc_nids[3] = { 2449 0x0c, 0x0d, 0x0e 2450 }; 2451 2452 #define AD1988_SPDIF_OUT 0x02 2453 #define AD1988_SPDIF_OUT_HDMI 0x0b 2454 #define AD1988_SPDIF_IN 0x07 2455 2456 static const hda_nid_t ad1989b_slave_dig_outs[] = { 2457 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0 2458 }; 2459 2460 static const struct hda_input_mux ad1988_6stack_capture_source = { 2461 .num_items = 5, 2462 .items = { 2463 { "Front Mic", 0x1 }, /* port-B */ 2464 { "Line", 0x2 }, /* port-C */ 2465 { "Mic", 0x4 }, /* port-E */ 2466 { "CD", 0x5 }, 2467 { "Mix", 0x9 }, 2468 }, 2469 }; 2470 2471 static const struct hda_input_mux ad1988_laptop_capture_source = { 2472 .num_items = 3, 2473 .items = { 2474 { "Mic/Line", 0x1 }, /* port-B */ 2475 { "CD", 0x5 }, 2476 { "Mix", 0x9 }, 2477 }, 2478 }; 2479 2480 /* 2481 */ 2482 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, 2483 struct snd_ctl_elem_info *uinfo) 2484 { 2485 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2486 struct ad198x_spec *spec = codec->spec; 2487 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, 2488 spec->num_channel_mode); 2489 } 2490 2491 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, 2492 struct snd_ctl_elem_value *ucontrol) 2493 { 2494 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2495 struct ad198x_spec *spec = codec->spec; 2496 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, 2497 spec->num_channel_mode, spec->multiout.max_channels); 2498 } 2499 2500 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, 2501 struct snd_ctl_elem_value *ucontrol) 2502 { 2503 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2504 struct ad198x_spec *spec = codec->spec; 2505 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, 2506 spec->num_channel_mode, 2507 &spec->multiout.max_channels); 2508 if (err >= 0 && spec->need_dac_fix) 2509 spec->multiout.num_dacs = spec->multiout.max_channels / 2; 2510 return err; 2511 } 2512 2513 /* 6-stack mode */ 2514 static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = { 2515 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2516 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT), 2517 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 2518 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 2519 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 2520 { } /* end */ 2521 }; 2522 2523 static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = { 2524 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2525 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT), 2526 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 2527 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT), 2528 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT), 2529 { } /* end */ 2530 }; 2531 2532 static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = { 2533 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 2534 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), 2535 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT), 2536 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT), 2537 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT), 2538 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT), 2539 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), 2540 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 2541 2542 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 2543 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 2544 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 2545 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 2546 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 2547 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 2548 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), 2549 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), 2550 2551 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 2552 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 2553 2554 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 2555 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), 2556 { } /* end */ 2557 }; 2558 2559 /* 3-stack mode */ 2560 static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = { 2561 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2562 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 2563 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 2564 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 2565 { } /* end */ 2566 }; 2567 2568 static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = { 2569 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2570 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 2571 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT), 2572 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT), 2573 { } /* end */ 2574 }; 2575 2576 static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = { 2577 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 2578 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), 2579 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT), 2580 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT), 2581 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT), 2582 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), 2583 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 2584 2585 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 2586 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 2587 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 2588 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 2589 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 2590 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 2591 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), 2592 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), 2593 2594 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 2595 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 2596 2597 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 2598 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), 2599 { 2600 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2601 .name = "Channel Mode", 2602 .info = ad198x_ch_mode_info, 2603 .get = ad198x_ch_mode_get, 2604 .put = ad198x_ch_mode_put, 2605 }, 2606 2607 { } /* end */ 2608 }; 2609 2610 /* laptop mode */ 2611 static const struct snd_kcontrol_new ad1988_laptop_mixers[] = { 2612 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 2613 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2614 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT), 2615 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 2616 2617 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 2618 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 2619 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 2620 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 2621 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 2622 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 2623 2624 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 2625 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 2626 2627 HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 2628 2629 { 2630 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2631 .name = "External Amplifier", 2632 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12, 2633 .info = ad198x_eapd_info, 2634 .get = ad198x_eapd_get, 2635 .put = ad198x_eapd_put, 2636 .private_value = 0x12, /* port-D */ 2637 }, 2638 2639 { } /* end */ 2640 }; 2641 2642 /* capture */ 2643 static const struct snd_kcontrol_new ad1988_capture_mixers[] = { 2644 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 2645 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 2646 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 2647 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 2648 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT), 2649 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT), 2650 { 2651 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2652 /* The multiple "Capture Source" controls confuse alsamixer 2653 * So call somewhat different.. 2654 */ 2655 /* .name = "Capture Source", */ 2656 .name = "Input Source", 2657 .count = 3, 2658 .info = ad198x_mux_enum_info, 2659 .get = ad198x_mux_enum_get, 2660 .put = ad198x_mux_enum_put, 2661 }, 2662 { } /* end */ 2663 }; 2664 2665 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol, 2666 struct snd_ctl_elem_info *uinfo) 2667 { 2668 static const char * const texts[] = { 2669 "PCM", "ADC1", "ADC2", "ADC3" 2670 }; 2671 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2672 uinfo->count = 1; 2673 uinfo->value.enumerated.items = 4; 2674 if (uinfo->value.enumerated.item >= 4) 2675 uinfo->value.enumerated.item = 3; 2676 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2677 return 0; 2678 } 2679 2680 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol, 2681 struct snd_ctl_elem_value *ucontrol) 2682 { 2683 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2684 unsigned int sel; 2685 2686 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE, 2687 AC_AMP_GET_INPUT); 2688 if (!(sel & 0x80)) 2689 ucontrol->value.enumerated.item[0] = 0; 2690 else { 2691 sel = snd_hda_codec_read(codec, 0x0b, 0, 2692 AC_VERB_GET_CONNECT_SEL, 0); 2693 if (sel < 3) 2694 sel++; 2695 else 2696 sel = 0; 2697 ucontrol->value.enumerated.item[0] = sel; 2698 } 2699 return 0; 2700 } 2701 2702 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol, 2703 struct snd_ctl_elem_value *ucontrol) 2704 { 2705 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2706 unsigned int val, sel; 2707 int change; 2708 2709 val = ucontrol->value.enumerated.item[0]; 2710 if (val > 3) 2711 return -EINVAL; 2712 if (!val) { 2713 sel = snd_hda_codec_read(codec, 0x1d, 0, 2714 AC_VERB_GET_AMP_GAIN_MUTE, 2715 AC_AMP_GET_INPUT); 2716 change = sel & 0x80; 2717 if (change) { 2718 snd_hda_codec_write_cache(codec, 0x1d, 0, 2719 AC_VERB_SET_AMP_GAIN_MUTE, 2720 AMP_IN_UNMUTE(0)); 2721 snd_hda_codec_write_cache(codec, 0x1d, 0, 2722 AC_VERB_SET_AMP_GAIN_MUTE, 2723 AMP_IN_MUTE(1)); 2724 } 2725 } else { 2726 sel = snd_hda_codec_read(codec, 0x1d, 0, 2727 AC_VERB_GET_AMP_GAIN_MUTE, 2728 AC_AMP_GET_INPUT | 0x01); 2729 change = sel & 0x80; 2730 if (change) { 2731 snd_hda_codec_write_cache(codec, 0x1d, 0, 2732 AC_VERB_SET_AMP_GAIN_MUTE, 2733 AMP_IN_MUTE(0)); 2734 snd_hda_codec_write_cache(codec, 0x1d, 0, 2735 AC_VERB_SET_AMP_GAIN_MUTE, 2736 AMP_IN_UNMUTE(1)); 2737 } 2738 sel = snd_hda_codec_read(codec, 0x0b, 0, 2739 AC_VERB_GET_CONNECT_SEL, 0) + 1; 2740 change |= sel != val; 2741 if (change) 2742 snd_hda_codec_write_cache(codec, 0x0b, 0, 2743 AC_VERB_SET_CONNECT_SEL, 2744 val - 1); 2745 } 2746 return change; 2747 } 2748 2749 static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = { 2750 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 2751 { 2752 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2753 .name = "IEC958 Playback Source", 2754 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b, 2755 .info = ad1988_spdif_playback_source_info, 2756 .get = ad1988_spdif_playback_source_get, 2757 .put = ad1988_spdif_playback_source_put, 2758 }, 2759 { } /* end */ 2760 }; 2761 2762 static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = { 2763 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT), 2764 { } /* end */ 2765 }; 2766 2767 static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = { 2768 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 2769 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 2770 { } /* end */ 2771 }; 2772 2773 /* 2774 * initialization verbs 2775 */ 2776 2777 /* 2778 * for 6-stack (+dig) 2779 */ 2780 static const struct hda_verb ad1988_6stack_init_verbs[] = { 2781 /* Front, Surround, CLFE, side DAC; unmute as default */ 2782 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2783 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2784 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2785 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2786 /* Port-A front headphon path */ 2787 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 2788 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2789 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2790 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2791 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2792 /* Port-D line-out path */ 2793 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2794 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2795 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2796 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2797 /* Port-F surround path */ 2798 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2799 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2800 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2801 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2802 /* Port-G CLFE path */ 2803 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2804 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2805 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2806 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2807 /* Port-H side path */ 2808 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2809 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2810 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2811 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2812 /* Mono out path */ 2813 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 2814 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2815 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2816 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2817 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 2818 /* Port-B front mic-in path */ 2819 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2820 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2821 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2822 /* Port-C line-in path */ 2823 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2824 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2825 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2826 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 2827 /* Port-E mic-in path */ 2828 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2829 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2830 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2831 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, 2832 /* Analog CD Input */ 2833 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2834 /* Analog Mix output amp */ 2835 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 2836 2837 { } 2838 }; 2839 2840 static const struct hda_verb ad1988_6stack_fp_init_verbs[] = { 2841 /* Headphone; unmute as default */ 2842 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2843 /* Port-A front headphon path */ 2844 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 2845 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2846 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2847 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2848 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2849 2850 { } 2851 }; 2852 2853 static const struct hda_verb ad1988_capture_init_verbs[] = { 2854 /* mute analog mix */ 2855 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2856 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2857 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2858 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2859 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2860 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 2861 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 2862 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 2863 /* select ADCs - front-mic */ 2864 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 2865 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 2866 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2867 2868 { } 2869 }; 2870 2871 static const struct hda_verb ad1988_spdif_init_verbs[] = { 2872 /* SPDIF out sel */ 2873 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 2874 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */ 2875 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2876 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2877 /* SPDIF out pin */ 2878 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2879 2880 { } 2881 }; 2882 2883 static const struct hda_verb ad1988_spdif_in_init_verbs[] = { 2884 /* unmute SPDIF input pin */ 2885 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2886 { } 2887 }; 2888 2889 /* AD1989 has no ADC -> SPDIF route */ 2890 static const struct hda_verb ad1989_spdif_init_verbs[] = { 2891 /* SPDIF-1 out pin */ 2892 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2893 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2894 /* SPDIF-2/HDMI out pin */ 2895 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2896 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2897 { } 2898 }; 2899 2900 /* 2901 * verbs for 3stack (+dig) 2902 */ 2903 static const struct hda_verb ad1988_3stack_ch2_init[] = { 2904 /* set port-C to line-in */ 2905 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2906 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 2907 /* set port-E to mic-in */ 2908 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2909 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 2910 { } /* end */ 2911 }; 2912 2913 static const struct hda_verb ad1988_3stack_ch6_init[] = { 2914 /* set port-C to surround out */ 2915 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2916 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2917 /* set port-E to CLFE out */ 2918 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2919 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2920 { } /* end */ 2921 }; 2922 2923 static const struct hda_channel_mode ad1988_3stack_modes[2] = { 2924 { 2, ad1988_3stack_ch2_init }, 2925 { 6, ad1988_3stack_ch6_init }, 2926 }; 2927 2928 static const struct hda_verb ad1988_3stack_init_verbs[] = { 2929 /* Front, Surround, CLFE, side DAC; unmute as default */ 2930 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2931 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2932 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2933 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2934 /* Port-A front headphon path */ 2935 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 2936 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2937 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2938 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2939 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2940 /* Port-D line-out path */ 2941 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2942 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2943 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2944 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2945 /* Mono out path */ 2946 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 2947 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2948 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2949 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2950 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 2951 /* Port-B front mic-in path */ 2952 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2953 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2954 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2955 /* Port-C line-in/surround path - 6ch mode as default */ 2956 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2957 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2958 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2959 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */ 2960 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 2961 /* Port-E mic-in/CLFE path - 6ch mode as default */ 2962 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2963 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2964 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2965 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */ 2966 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, 2967 /* mute analog mix */ 2968 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2969 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2970 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2971 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2972 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2973 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 2974 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 2975 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 2976 /* select ADCs - front-mic */ 2977 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 2978 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 2979 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2980 /* Analog Mix output amp */ 2981 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 2982 { } 2983 }; 2984 2985 /* 2986 * verbs for laptop mode (+dig) 2987 */ 2988 static const struct hda_verb ad1988_laptop_hp_on[] = { 2989 /* unmute port-A and mute port-D */ 2990 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2991 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2992 { } /* end */ 2993 }; 2994 static const struct hda_verb ad1988_laptop_hp_off[] = { 2995 /* mute port-A and unmute port-D */ 2996 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2997 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2998 { } /* end */ 2999 }; 3000 3001 #define AD1988_HP_EVENT 0x01 3002 3003 static const struct hda_verb ad1988_laptop_init_verbs[] = { 3004 /* Front, Surround, CLFE, side DAC; unmute as default */ 3005 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3006 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3007 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3008 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3009 /* Port-A front headphon path */ 3010 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 3011 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3012 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3013 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3014 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3015 /* unsolicited event for pin-sense */ 3016 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT }, 3017 /* Port-D line-out path + EAPD */ 3018 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3019 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3020 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3021 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3022 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */ 3023 /* Mono out path */ 3024 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 3025 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3026 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3027 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3028 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 3029 /* Port-B mic-in path */ 3030 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3031 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3032 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3033 /* Port-C docking station - try to output */ 3034 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3035 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3036 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3037 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 3038 /* mute analog mix */ 3039 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3040 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3041 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 3042 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 3043 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3044 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 3045 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 3046 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 3047 /* select ADCs - mic */ 3048 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 3049 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 3050 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 3051 /* Analog Mix output amp */ 3052 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 3053 { } 3054 }; 3055 3056 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) 3057 { 3058 if ((res >> 26) != AD1988_HP_EVENT) 3059 return; 3060 if (snd_hda_jack_detect(codec, 0x11)) 3061 snd_hda_sequence_write(codec, ad1988_laptop_hp_on); 3062 else 3063 snd_hda_sequence_write(codec, ad1988_laptop_hp_off); 3064 } 3065 3066 #ifdef CONFIG_PM 3067 static const struct hda_amp_list ad1988_loopbacks[] = { 3068 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 3069 { 0x20, HDA_INPUT, 1 }, /* Line */ 3070 { 0x20, HDA_INPUT, 4 }, /* Mic */ 3071 { 0x20, HDA_INPUT, 6 }, /* CD */ 3072 { } /* end */ 3073 }; 3074 #endif 3075 #endif /* ENABLE_AD_STATIC_QUIRKS */ 3076 3077 static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol, 3078 struct snd_ctl_elem_info *uinfo) 3079 { 3080 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 3081 static const char * const texts[] = { 3082 "PCM", "ADC1", "ADC2", "ADC3", 3083 }; 3084 int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1; 3085 if (num_conns > 4) 3086 num_conns = 4; 3087 return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts); 3088 } 3089 3090 static int ad1988_auto_smux_enum_get(struct snd_kcontrol *kcontrol, 3091 struct snd_ctl_elem_value *ucontrol) 3092 { 3093 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 3094 struct ad198x_spec *spec = codec->spec; 3095 3096 ucontrol->value.enumerated.item[0] = spec->cur_smux; 3097 return 0; 3098 } 3099 3100 static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol, 3101 struct snd_ctl_elem_value *ucontrol) 3102 { 3103 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 3104 struct ad198x_spec *spec = codec->spec; 3105 unsigned int val = ucontrol->value.enumerated.item[0]; 3106 struct nid_path *path; 3107 int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1; 3108 3109 if (val >= num_conns) 3110 return -EINVAL; 3111 if (spec->cur_smux == val) 3112 return 0; 3113 3114 mutex_lock(&codec->control_mutex); 3115 codec->cached_write = 1; 3116 path = snd_hda_get_path_from_idx(codec, 3117 spec->smux_paths[spec->cur_smux]); 3118 if (path) 3119 snd_hda_activate_path(codec, path, false, true); 3120 path = snd_hda_get_path_from_idx(codec, spec->smux_paths[val]); 3121 if (path) 3122 snd_hda_activate_path(codec, path, true, true); 3123 spec->cur_smux = val; 3124 codec->cached_write = 0; 3125 mutex_unlock(&codec->control_mutex); 3126 snd_hda_codec_flush_cache(codec); /* flush the updates */ 3127 return 1; 3128 } 3129 3130 static struct snd_kcontrol_new ad1988_auto_smux_mixer = { 3131 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3132 .name = "IEC958 Playback Source", 3133 .info = ad1988_auto_smux_enum_info, 3134 .get = ad1988_auto_smux_enum_get, 3135 .put = ad1988_auto_smux_enum_put, 3136 }; 3137 3138 static int ad1988_auto_init(struct hda_codec *codec) 3139 { 3140 struct ad198x_spec *spec = codec->spec; 3141 int i, err; 3142 3143 err = snd_hda_gen_init(codec); 3144 if (err < 0) 3145 return err; 3146 if (!spec->gen.autocfg.dig_outs) 3147 return 0; 3148 3149 for (i = 0; i < 4; i++) { 3150 struct nid_path *path; 3151 path = snd_hda_get_path_from_idx(codec, spec->smux_paths[i]); 3152 if (path) 3153 snd_hda_activate_path(codec, path, path->active, false); 3154 } 3155 3156 return 0; 3157 } 3158 3159 static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec) 3160 { 3161 struct ad198x_spec *spec = codec->spec; 3162 int i, num_conns; 3163 /* we create four static faked paths, since AD codecs have odd 3164 * widget connections regarding the SPDIF out source 3165 */ 3166 static struct nid_path fake_paths[4] = { 3167 { 3168 .depth = 3, 3169 .path = { 0x02, 0x1d, 0x1b }, 3170 .idx = { 0, 0, 0 }, 3171 .multi = { 0, 0, 0 }, 3172 }, 3173 { 3174 .depth = 4, 3175 .path = { 0x08, 0x0b, 0x1d, 0x1b }, 3176 .idx = { 0, 0, 1, 0 }, 3177 .multi = { 0, 1, 0, 0 }, 3178 }, 3179 { 3180 .depth = 4, 3181 .path = { 0x09, 0x0b, 0x1d, 0x1b }, 3182 .idx = { 0, 1, 1, 0 }, 3183 .multi = { 0, 1, 0, 0 }, 3184 }, 3185 { 3186 .depth = 4, 3187 .path = { 0x0f, 0x0b, 0x1d, 0x1b }, 3188 .idx = { 0, 2, 1, 0 }, 3189 .multi = { 0, 1, 0, 0 }, 3190 }, 3191 }; 3192 3193 /* SPDIF source mux appears to be present only on AD1988A */ 3194 if (!spec->gen.autocfg.dig_outs || 3195 get_wcaps_type(get_wcaps(codec, 0x1d)) != AC_WID_AUD_MIX) 3196 return 0; 3197 3198 num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1; 3199 if (num_conns != 3 && num_conns != 4) 3200 return 0; 3201 3202 for (i = 0; i < num_conns; i++) { 3203 struct nid_path *path = snd_array_new(&spec->gen.paths); 3204 if (!path) 3205 return -ENOMEM; 3206 *path = fake_paths[i]; 3207 if (!i) 3208 path->active = 1; 3209 spec->smux_paths[i] = snd_hda_get_path_idx(codec, path); 3210 } 3211 3212 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1988_auto_smux_mixer)) 3213 return -ENOMEM; 3214 3215 codec->patch_ops.init = ad1988_auto_init; 3216 3217 return 0; 3218 } 3219 3220 /* 3221 */ 3222 3223 static int ad1988_parse_auto_config(struct hda_codec *codec) 3224 { 3225 struct ad198x_spec *spec; 3226 int err; 3227 3228 err = alloc_ad_spec(codec); 3229 if (err < 0) 3230 return err; 3231 spec = codec->spec; 3232 3233 spec->gen.mixer_nid = 0x20; 3234 spec->gen.mixer_merge_nid = 0x21; 3235 spec->gen.beep_nid = 0x10; 3236 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3237 err = ad198x_parse_auto_config(codec); 3238 if (err < 0) 3239 goto error; 3240 err = ad1988_add_spdif_mux_ctl(codec); 3241 if (err < 0) 3242 goto error; 3243 return 0; 3244 3245 error: 3246 snd_hda_gen_free(codec); 3247 return err; 3248 } 3249 3250 /* 3251 */ 3252 3253 #ifdef ENABLE_AD_STATIC_QUIRKS 3254 static const char * const ad1988_models[AD1988_MODEL_LAST] = { 3255 [AD1988_6STACK] = "6stack", 3256 [AD1988_6STACK_DIG] = "6stack-dig", 3257 [AD1988_3STACK] = "3stack", 3258 [AD1988_3STACK_DIG] = "3stack-dig", 3259 [AD1988_LAPTOP] = "laptop", 3260 [AD1988_LAPTOP_DIG] = "laptop-dig", 3261 [AD1988_AUTO] = "auto", 3262 }; 3263 3264 static const struct snd_pci_quirk ad1988_cfg_tbl[] = { 3265 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG), 3266 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG), 3267 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG), 3268 SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG), 3269 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG), 3270 {} 3271 }; 3272 3273 static int patch_ad1988(struct hda_codec *codec) 3274 { 3275 struct ad198x_spec *spec; 3276 int err, board_config; 3277 3278 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST, 3279 ad1988_models, ad1988_cfg_tbl); 3280 if (board_config < 0) { 3281 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 3282 codec->chip_name); 3283 board_config = AD1988_AUTO; 3284 } 3285 3286 if (board_config == AD1988_AUTO) 3287 return ad1988_parse_auto_config(codec); 3288 3289 err = alloc_ad_spec(codec); 3290 if (err < 0) 3291 return err; 3292 spec = codec->spec; 3293 3294 if (is_rev2(codec)) 3295 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n"); 3296 3297 err = snd_hda_attach_beep_device(codec, 0x10); 3298 if (err < 0) { 3299 ad198x_free(codec); 3300 return err; 3301 } 3302 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3303 3304 if (!spec->multiout.hp_nid) 3305 spec->multiout.hp_nid = ad1988_alt_dac_nid[0]; 3306 switch (board_config) { 3307 case AD1988_6STACK: 3308 case AD1988_6STACK_DIG: 3309 spec->multiout.max_channels = 8; 3310 spec->multiout.num_dacs = 4; 3311 if (is_rev2(codec)) 3312 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2; 3313 else 3314 spec->multiout.dac_nids = ad1988_6stack_dac_nids; 3315 spec->input_mux = &ad1988_6stack_capture_source; 3316 spec->num_mixers = 2; 3317 if (is_rev2(codec)) 3318 spec->mixers[0] = ad1988_6stack_mixers1_rev2; 3319 else 3320 spec->mixers[0] = ad1988_6stack_mixers1; 3321 spec->mixers[1] = ad1988_6stack_mixers2; 3322 spec->num_init_verbs = 1; 3323 spec->init_verbs[0] = ad1988_6stack_init_verbs; 3324 if (board_config == AD1988_6STACK_DIG) { 3325 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 3326 spec->dig_in_nid = AD1988_SPDIF_IN; 3327 } 3328 break; 3329 case AD1988_3STACK: 3330 case AD1988_3STACK_DIG: 3331 spec->multiout.max_channels = 6; 3332 spec->multiout.num_dacs = 3; 3333 if (is_rev2(codec)) 3334 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2; 3335 else 3336 spec->multiout.dac_nids = ad1988_3stack_dac_nids; 3337 spec->input_mux = &ad1988_6stack_capture_source; 3338 spec->channel_mode = ad1988_3stack_modes; 3339 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes); 3340 spec->num_mixers = 2; 3341 if (is_rev2(codec)) 3342 spec->mixers[0] = ad1988_3stack_mixers1_rev2; 3343 else 3344 spec->mixers[0] = ad1988_3stack_mixers1; 3345 spec->mixers[1] = ad1988_3stack_mixers2; 3346 spec->num_init_verbs = 1; 3347 spec->init_verbs[0] = ad1988_3stack_init_verbs; 3348 if (board_config == AD1988_3STACK_DIG) 3349 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 3350 break; 3351 case AD1988_LAPTOP: 3352 case AD1988_LAPTOP_DIG: 3353 spec->multiout.max_channels = 2; 3354 spec->multiout.num_dacs = 1; 3355 spec->multiout.dac_nids = ad1988_3stack_dac_nids; 3356 spec->input_mux = &ad1988_laptop_capture_source; 3357 spec->num_mixers = 1; 3358 spec->mixers[0] = ad1988_laptop_mixers; 3359 codec->inv_eapd = 1; /* inverted EAPD */ 3360 spec->num_init_verbs = 1; 3361 spec->init_verbs[0] = ad1988_laptop_init_verbs; 3362 if (board_config == AD1988_LAPTOP_DIG) 3363 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 3364 break; 3365 } 3366 3367 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids); 3368 spec->adc_nids = ad1988_adc_nids; 3369 spec->capsrc_nids = ad1988_capsrc_nids; 3370 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers; 3371 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs; 3372 if (spec->multiout.dig_out_nid) { 3373 if (codec->vendor_id >= 0x11d4989a) { 3374 spec->mixers[spec->num_mixers++] = 3375 ad1989_spdif_out_mixers; 3376 spec->init_verbs[spec->num_init_verbs++] = 3377 ad1989_spdif_init_verbs; 3378 codec->slave_dig_outs = ad1989b_slave_dig_outs; 3379 } else { 3380 spec->mixers[spec->num_mixers++] = 3381 ad1988_spdif_out_mixers; 3382 spec->init_verbs[spec->num_init_verbs++] = 3383 ad1988_spdif_init_verbs; 3384 } 3385 } 3386 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) { 3387 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers; 3388 spec->init_verbs[spec->num_init_verbs++] = 3389 ad1988_spdif_in_init_verbs; 3390 } 3391 3392 codec->patch_ops = ad198x_patch_ops; 3393 switch (board_config) { 3394 case AD1988_LAPTOP: 3395 case AD1988_LAPTOP_DIG: 3396 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; 3397 break; 3398 } 3399 #ifdef CONFIG_PM 3400 spec->loopback.amplist = ad1988_loopbacks; 3401 #endif 3402 spec->vmaster_nid = 0x04; 3403 3404 codec->no_trigger_sense = 1; 3405 codec->no_sticky_stream = 1; 3406 3407 return 0; 3408 } 3409 #else /* ENABLE_AD_STATIC_QUIRKS */ 3410 #define patch_ad1988 ad1988_parse_auto_config 3411 #endif /* ENABLE_AD_STATIC_QUIRKS */ 3412 3413 3414 /* 3415 * AD1884 / AD1984 3416 * 3417 * port-B - front line/mic-in 3418 * port-E - aux in/out 3419 * port-F - aux in/out 3420 * port-C - rear line/mic-in 3421 * port-D - rear line/hp-out 3422 * port-A - front line/hp-out 3423 * 3424 * AD1984 = AD1884 + two digital mic-ins 3425 * 3426 * FIXME: 3427 * For simplicity, we share the single DAC for both HP and line-outs 3428 * right now. The inidividual playbacks could be easily implemented, 3429 * but no build-up framework is given, so far. 3430 */ 3431 3432 #ifdef ENABLE_AD_STATIC_QUIRKS 3433 static const hda_nid_t ad1884_dac_nids[1] = { 3434 0x04, 3435 }; 3436 3437 static const hda_nid_t ad1884_adc_nids[2] = { 3438 0x08, 0x09, 3439 }; 3440 3441 static const hda_nid_t ad1884_capsrc_nids[2] = { 3442 0x0c, 0x0d, 3443 }; 3444 3445 #define AD1884_SPDIF_OUT 0x02 3446 3447 static const struct hda_input_mux ad1884_capture_source = { 3448 .num_items = 4, 3449 .items = { 3450 { "Front Mic", 0x0 }, 3451 { "Mic", 0x1 }, 3452 { "CD", 0x2 }, 3453 { "Mix", 0x3 }, 3454 }, 3455 }; 3456 3457 static const struct snd_kcontrol_new ad1884_base_mixers[] = { 3458 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3459 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ 3460 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3461 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3462 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 3463 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 3464 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3465 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3466 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 3467 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 3468 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), 3469 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), 3470 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 3471 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 3472 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3473 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3474 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3475 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3476 { 3477 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3478 /* The multiple "Capture Source" controls confuse alsamixer 3479 * So call somewhat different.. 3480 */ 3481 /* .name = "Capture Source", */ 3482 .name = "Input Source", 3483 .count = 2, 3484 .info = ad198x_mux_enum_info, 3485 .get = ad198x_mux_enum_get, 3486 .put = ad198x_mux_enum_put, 3487 }, 3488 /* SPDIF controls */ 3489 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 3490 { 3491 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3492 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 3493 /* identical with ad1983 */ 3494 .info = ad1983_spdif_route_info, 3495 .get = ad1983_spdif_route_get, 3496 .put = ad1983_spdif_route_put, 3497 }, 3498 { } /* end */ 3499 }; 3500 3501 static const struct snd_kcontrol_new ad1984_dmic_mixers[] = { 3502 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT), 3503 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT), 3504 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0, 3505 HDA_INPUT), 3506 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0, 3507 HDA_INPUT), 3508 { } /* end */ 3509 }; 3510 3511 /* 3512 * initialization verbs 3513 */ 3514 static const struct hda_verb ad1884_init_verbs[] = { 3515 /* DACs; mute as default */ 3516 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3517 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3518 /* Port-A (HP) mixer */ 3519 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3520 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3521 /* Port-A pin */ 3522 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3523 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3524 /* HP selector - select DAC2 */ 3525 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1}, 3526 /* Port-D (Line-out) mixer */ 3527 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3528 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3529 /* Port-D pin */ 3530 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3531 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3532 /* Mono-out mixer */ 3533 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3534 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3535 /* Mono-out pin */ 3536 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3537 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3538 /* Mono selector */ 3539 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 3540 /* Port-B (front mic) pin */ 3541 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3542 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3543 /* Port-C (rear mic) pin */ 3544 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3545 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3546 /* Analog mixer; mute as default */ 3547 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3548 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3549 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 3550 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 3551 /* Analog Mix output amp */ 3552 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 3553 /* SPDIF output selector */ 3554 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 3555 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 3556 { } /* end */ 3557 }; 3558 3559 #ifdef CONFIG_PM 3560 static const struct hda_amp_list ad1884_loopbacks[] = { 3561 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 3562 { 0x20, HDA_INPUT, 1 }, /* Mic */ 3563 { 0x20, HDA_INPUT, 2 }, /* CD */ 3564 { 0x20, HDA_INPUT, 4 }, /* Docking */ 3565 { } /* end */ 3566 }; 3567 #endif 3568 3569 static const char * const ad1884_slave_vols[] = { 3570 "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD", 3571 "Internal Mic", "Dock Mic", /* "Beep", */ "IEC958", 3572 NULL 3573 }; 3574 3575 enum { 3576 AD1884_AUTO, 3577 AD1884_BASIC, 3578 AD1884_MODELS 3579 }; 3580 3581 static const char * const ad1884_models[AD1884_MODELS] = { 3582 [AD1884_AUTO] = "auto", 3583 [AD1884_BASIC] = "basic", 3584 }; 3585 #endif /* ENABLE_AD_STATIC_QUIRKS */ 3586 3587 3588 /* set the upper-limit for mixer amp to 0dB for avoiding the possible 3589 * damage by overloading 3590 */ 3591 static void ad1884_fixup_amp_override(struct hda_codec *codec, 3592 const struct hda_fixup *fix, int action) 3593 { 3594 if (action == HDA_FIXUP_ACT_PRE_PROBE) 3595 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 3596 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 3597 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 3598 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 3599 (1 << AC_AMPCAP_MUTE_SHIFT)); 3600 } 3601 3602 static void ad1884_fixup_hp_eapd(struct hda_codec *codec, 3603 const struct hda_fixup *fix, int action) 3604 { 3605 struct ad198x_spec *spec = codec->spec; 3606 3607 switch (action) { 3608 case HDA_FIXUP_ACT_PRE_PROBE: 3609 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook; 3610 break; 3611 case HDA_FIXUP_ACT_PROBE: 3612 if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) 3613 spec->eapd_nid = spec->gen.autocfg.line_out_pins[0]; 3614 else 3615 spec->eapd_nid = spec->gen.autocfg.speaker_pins[0]; 3616 break; 3617 } 3618 } 3619 3620 enum { 3621 AD1884_FIXUP_AMP_OVERRIDE, 3622 AD1884_FIXUP_HP_EAPD, 3623 }; 3624 3625 static const struct hda_fixup ad1884_fixups[] = { 3626 [AD1884_FIXUP_AMP_OVERRIDE] = { 3627 .type = HDA_FIXUP_FUNC, 3628 .v.func = ad1884_fixup_amp_override, 3629 }, 3630 [AD1884_FIXUP_HP_EAPD] = { 3631 .type = HDA_FIXUP_FUNC, 3632 .v.func = ad1884_fixup_hp_eapd, 3633 .chained = true, 3634 .chain_id = AD1884_FIXUP_AMP_OVERRIDE, 3635 }, 3636 }; 3637 3638 static const struct snd_pci_quirk ad1884_fixup_tbl[] = { 3639 SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD), 3640 {} 3641 }; 3642 3643 3644 static int ad1884_parse_auto_config(struct hda_codec *codec) 3645 { 3646 struct ad198x_spec *spec; 3647 int err; 3648 3649 err = alloc_ad_spec(codec); 3650 if (err < 0) 3651 return err; 3652 spec = codec->spec; 3653 3654 spec->gen.mixer_nid = 0x20; 3655 spec->gen.beep_nid = 0x10; 3656 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3657 3658 snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups); 3659 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 3660 3661 err = ad198x_parse_auto_config(codec); 3662 if (err < 0) 3663 goto error; 3664 err = ad1983_add_spdif_mux_ctl(codec); 3665 if (err < 0) 3666 goto error; 3667 3668 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); 3669 3670 return 0; 3671 3672 error: 3673 snd_hda_gen_free(codec); 3674 return err; 3675 } 3676 3677 #ifdef ENABLE_AD_STATIC_QUIRKS 3678 static int patch_ad1884_basic(struct hda_codec *codec) 3679 { 3680 struct ad198x_spec *spec; 3681 int err; 3682 3683 err = alloc_ad_spec(codec); 3684 if (err < 0) 3685 return err; 3686 spec = codec->spec; 3687 3688 err = snd_hda_attach_beep_device(codec, 0x10); 3689 if (err < 0) { 3690 ad198x_free(codec); 3691 return err; 3692 } 3693 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3694 3695 spec->multiout.max_channels = 2; 3696 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); 3697 spec->multiout.dac_nids = ad1884_dac_nids; 3698 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; 3699 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids); 3700 spec->adc_nids = ad1884_adc_nids; 3701 spec->capsrc_nids = ad1884_capsrc_nids; 3702 spec->input_mux = &ad1884_capture_source; 3703 spec->num_mixers = 1; 3704 spec->mixers[0] = ad1884_base_mixers; 3705 spec->num_init_verbs = 1; 3706 spec->init_verbs[0] = ad1884_init_verbs; 3707 spec->spdif_route = 0; 3708 #ifdef CONFIG_PM 3709 spec->loopback.amplist = ad1884_loopbacks; 3710 #endif 3711 spec->vmaster_nid = 0x04; 3712 /* we need to cover all playback volumes */ 3713 spec->slave_vols = ad1884_slave_vols; 3714 /* slaves may contain input volumes, so we can't raise to 0dB blindly */ 3715 spec->avoid_init_slave_vol = 1; 3716 3717 codec->patch_ops = ad198x_patch_ops; 3718 3719 codec->no_trigger_sense = 1; 3720 codec->no_sticky_stream = 1; 3721 3722 return 0; 3723 } 3724 3725 static int patch_ad1884(struct hda_codec *codec) 3726 { 3727 int board_config; 3728 3729 board_config = snd_hda_check_board_config(codec, AD1884_MODELS, 3730 ad1884_models, NULL); 3731 if (board_config < 0) { 3732 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 3733 codec->chip_name); 3734 board_config = AD1884_AUTO; 3735 } 3736 3737 if (board_config == AD1884_AUTO) 3738 return ad1884_parse_auto_config(codec); 3739 else 3740 return patch_ad1884_basic(codec); 3741 } 3742 #else /* ENABLE_AD_STATIC_QUIRKS */ 3743 #define patch_ad1884 ad1884_parse_auto_config 3744 #endif /* ENABLE_AD_STATIC_QUIRKS */ 3745 3746 3747 #ifdef ENABLE_AD_STATIC_QUIRKS 3748 /* 3749 * Lenovo Thinkpad T61/X61 3750 */ 3751 static const struct hda_input_mux ad1984_thinkpad_capture_source = { 3752 .num_items = 4, 3753 .items = { 3754 { "Mic", 0x0 }, 3755 { "Internal Mic", 0x1 }, 3756 { "Mix", 0x3 }, 3757 { "Dock Mic", 0x4 }, 3758 }, 3759 }; 3760 3761 3762 /* 3763 * Dell Precision T3400 3764 */ 3765 static const struct hda_input_mux ad1984_dell_desktop_capture_source = { 3766 .num_items = 3, 3767 .items = { 3768 { "Front Mic", 0x0 }, 3769 { "Line-In", 0x1 }, 3770 { "Mix", 0x3 }, 3771 }, 3772 }; 3773 3774 3775 static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { 3776 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3777 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ 3778 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3779 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3780 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3781 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3782 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 3783 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 3784 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), 3785 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), 3786 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 3787 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 3788 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 3789 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 3790 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 3791 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3792 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3793 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3794 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3795 { 3796 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3797 /* The multiple "Capture Source" controls confuse alsamixer 3798 * So call somewhat different.. 3799 */ 3800 /* .name = "Capture Source", */ 3801 .name = "Input Source", 3802 .count = 2, 3803 .info = ad198x_mux_enum_info, 3804 .get = ad198x_mux_enum_get, 3805 .put = ad198x_mux_enum_put, 3806 }, 3807 /* SPDIF controls */ 3808 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 3809 { 3810 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3811 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 3812 /* identical with ad1983 */ 3813 .info = ad1983_spdif_route_info, 3814 .get = ad1983_spdif_route_get, 3815 .put = ad1983_spdif_route_put, 3816 }, 3817 { } /* end */ 3818 }; 3819 3820 /* additional verbs */ 3821 static const struct hda_verb ad1984_thinkpad_init_verbs[] = { 3822 /* Port-E (docking station mic) pin */ 3823 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3824 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3825 /* docking mic boost */ 3826 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3827 /* Analog PC Beeper - allow firmware/ACPI beeps */ 3828 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a}, 3829 /* Analog mixer - docking mic; mute as default */ 3830 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3831 /* enable EAPD bit */ 3832 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 3833 { } /* end */ 3834 }; 3835 3836 /* 3837 * Dell Precision T3400 3838 */ 3839 static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = { 3840 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3841 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3842 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3843 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 3844 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 3845 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3846 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3847 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), 3848 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), 3849 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT), 3850 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 3851 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3852 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3853 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3854 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3855 { 3856 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3857 /* The multiple "Capture Source" controls confuse alsamixer 3858 * So call somewhat different.. 3859 */ 3860 /* .name = "Capture Source", */ 3861 .name = "Input Source", 3862 .count = 2, 3863 .info = ad198x_mux_enum_info, 3864 .get = ad198x_mux_enum_get, 3865 .put = ad198x_mux_enum_put, 3866 }, 3867 { } /* end */ 3868 }; 3869 3870 /* Digial MIC ADC NID 0x05 + 0x06 */ 3871 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo, 3872 struct hda_codec *codec, 3873 unsigned int stream_tag, 3874 unsigned int format, 3875 struct snd_pcm_substream *substream) 3876 { 3877 snd_hda_codec_setup_stream(codec, 0x05 + substream->number, 3878 stream_tag, 0, format); 3879 return 0; 3880 } 3881 3882 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo, 3883 struct hda_codec *codec, 3884 struct snd_pcm_substream *substream) 3885 { 3886 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number); 3887 return 0; 3888 } 3889 3890 static const struct hda_pcm_stream ad1984_pcm_dmic_capture = { 3891 .substreams = 2, 3892 .channels_min = 2, 3893 .channels_max = 2, 3894 .nid = 0x05, 3895 .ops = { 3896 .prepare = ad1984_pcm_dmic_prepare, 3897 .cleanup = ad1984_pcm_dmic_cleanup 3898 }, 3899 }; 3900 3901 static int ad1984_build_pcms(struct hda_codec *codec) 3902 { 3903 struct ad198x_spec *spec = codec->spec; 3904 struct hda_pcm *info; 3905 int err; 3906 3907 err = ad198x_build_pcms(codec); 3908 if (err < 0) 3909 return err; 3910 3911 info = spec->pcm_rec + codec->num_pcms; 3912 codec->num_pcms++; 3913 info->name = "AD1984 Digital Mic"; 3914 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture; 3915 return 0; 3916 } 3917 3918 /* models */ 3919 enum { 3920 AD1984_AUTO, 3921 AD1984_BASIC, 3922 AD1984_THINKPAD, 3923 AD1984_DELL_DESKTOP, 3924 AD1984_MODELS 3925 }; 3926 3927 static const char * const ad1984_models[AD1984_MODELS] = { 3928 [AD1984_AUTO] = "auto", 3929 [AD1984_BASIC] = "basic", 3930 [AD1984_THINKPAD] = "thinkpad", 3931 [AD1984_DELL_DESKTOP] = "dell_desktop", 3932 }; 3933 3934 static const struct snd_pci_quirk ad1984_cfg_tbl[] = { 3935 /* Lenovo Thinkpad T61/X61 */ 3936 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD), 3937 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), 3938 SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP), 3939 {} 3940 }; 3941 3942 static int patch_ad1984(struct hda_codec *codec) 3943 { 3944 struct ad198x_spec *spec; 3945 int board_config, err; 3946 3947 board_config = snd_hda_check_board_config(codec, AD1984_MODELS, 3948 ad1984_models, ad1984_cfg_tbl); 3949 if (board_config < 0) { 3950 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 3951 codec->chip_name); 3952 board_config = AD1984_AUTO; 3953 } 3954 3955 if (board_config == AD1984_AUTO) 3956 return ad1884_parse_auto_config(codec); 3957 3958 err = patch_ad1884_basic(codec); 3959 if (err < 0) 3960 return err; 3961 spec = codec->spec; 3962 3963 switch (board_config) { 3964 case AD1984_BASIC: 3965 /* additional digital mics */ 3966 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers; 3967 codec->patch_ops.build_pcms = ad1984_build_pcms; 3968 break; 3969 case AD1984_THINKPAD: 3970 if (codec->subsystem_id == 0x17aa20fb) { 3971 /* Thinpad X300 does not have the ability to do SPDIF, 3972 or attach to docking station to use SPDIF */ 3973 spec->multiout.dig_out_nid = 0; 3974 } else 3975 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; 3976 spec->input_mux = &ad1984_thinkpad_capture_source; 3977 spec->mixers[0] = ad1984_thinkpad_mixers; 3978 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs; 3979 spec->analog_beep = 1; 3980 break; 3981 case AD1984_DELL_DESKTOP: 3982 spec->multiout.dig_out_nid = 0; 3983 spec->input_mux = &ad1984_dell_desktop_capture_source; 3984 spec->mixers[0] = ad1984_dell_desktop_mixers; 3985 break; 3986 } 3987 return 0; 3988 } 3989 #else /* ENABLE_AD_STATIC_QUIRKS */ 3990 #define patch_ad1984 ad1884_parse_auto_config 3991 #endif /* ENABLE_AD_STATIC_QUIRKS */ 3992 3993 3994 /* 3995 * AD1883 / AD1884A / AD1984A / AD1984B 3996 * 3997 * port-B (0x14) - front mic-in 3998 * port-E (0x1c) - rear mic-in 3999 * port-F (0x16) - CD / ext out 4000 * port-C (0x15) - rear line-in 4001 * port-D (0x12) - rear line-out 4002 * port-A (0x11) - front hp-out 4003 * 4004 * AD1984A = AD1884A + digital-mic 4005 * AD1883 = equivalent with AD1984A 4006 * AD1984B = AD1984A + extra SPDIF-out 4007 * 4008 * FIXME: 4009 * We share the single DAC for both HP and line-outs (see AD1884/1984). 4010 */ 4011 4012 #ifdef ENABLE_AD_STATIC_QUIRKS 4013 static const hda_nid_t ad1884a_dac_nids[1] = { 4014 0x03, 4015 }; 4016 4017 #define ad1884a_adc_nids ad1884_adc_nids 4018 #define ad1884a_capsrc_nids ad1884_capsrc_nids 4019 4020 #define AD1884A_SPDIF_OUT 0x02 4021 4022 static const struct hda_input_mux ad1884a_capture_source = { 4023 .num_items = 5, 4024 .items = { 4025 { "Front Mic", 0x0 }, 4026 { "Mic", 0x4 }, 4027 { "Line", 0x1 }, 4028 { "CD", 0x2 }, 4029 { "Mix", 0x3 }, 4030 }, 4031 }; 4032 4033 static const struct snd_kcontrol_new ad1884a_base_mixers[] = { 4034 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4035 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), 4036 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 4037 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4038 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 4039 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 4040 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4041 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4042 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4043 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4044 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT), 4045 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), 4046 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 4047 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 4048 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), 4049 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), 4050 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 4051 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT), 4052 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 4053 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4054 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4055 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 4056 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 4057 { 4058 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4059 /* The multiple "Capture Source" controls confuse alsamixer 4060 * So call somewhat different.. 4061 */ 4062 /* .name = "Capture Source", */ 4063 .name = "Input Source", 4064 .count = 2, 4065 .info = ad198x_mux_enum_info, 4066 .get = ad198x_mux_enum_get, 4067 .put = ad198x_mux_enum_put, 4068 }, 4069 /* SPDIF controls */ 4070 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 4071 { 4072 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4073 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 4074 /* identical with ad1983 */ 4075 .info = ad1983_spdif_route_info, 4076 .get = ad1983_spdif_route_get, 4077 .put = ad1983_spdif_route_put, 4078 }, 4079 { } /* end */ 4080 }; 4081 4082 /* 4083 * initialization verbs 4084 */ 4085 static const struct hda_verb ad1884a_init_verbs[] = { 4086 /* DACs; unmute as default */ 4087 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4088 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4089 /* Port-A (HP) mixer - route only from analog mixer */ 4090 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4091 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4092 /* Port-A pin */ 4093 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4094 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4095 /* Port-D (Line-out) mixer - route only from analog mixer */ 4096 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4097 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4098 /* Port-D pin */ 4099 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4100 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4101 /* Mono-out mixer - route only from analog mixer */ 4102 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4103 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4104 /* Mono-out pin */ 4105 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4106 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4107 /* Port-B (front mic) pin */ 4108 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4109 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4110 /* Port-C (rear line-in) pin */ 4111 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4112 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4113 /* Port-E (rear mic) pin */ 4114 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4115 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4116 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */ 4117 /* Port-F (CD) pin */ 4118 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4119 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4120 /* Analog mixer; mute as default */ 4121 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4122 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4123 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4124 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4125 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */ 4126 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 4127 /* Analog Mix output amp */ 4128 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4129 /* capture sources */ 4130 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, 4131 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4132 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 4133 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4134 /* SPDIF output amp */ 4135 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 4136 { } /* end */ 4137 }; 4138 4139 #ifdef CONFIG_PM 4140 static const struct hda_amp_list ad1884a_loopbacks[] = { 4141 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 4142 { 0x20, HDA_INPUT, 1 }, /* Mic */ 4143 { 0x20, HDA_INPUT, 2 }, /* CD */ 4144 { 0x20, HDA_INPUT, 4 }, /* Docking */ 4145 { } /* end */ 4146 }; 4147 #endif 4148 4149 /* 4150 * Laptop model 4151 * 4152 * Port A: Headphone jack 4153 * Port B: MIC jack 4154 * Port C: Internal MIC 4155 * Port D: Dock Line Out (if enabled) 4156 * Port E: Dock Line In (if enabled) 4157 * Port F: Internal speakers 4158 */ 4159 4160 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol, 4161 struct snd_ctl_elem_value *ucontrol) 4162 { 4163 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 4164 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); 4165 int mute = (!ucontrol->value.integer.value[0] && 4166 !ucontrol->value.integer.value[1]); 4167 /* toggle GPIO1 according to the mute state */ 4168 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 4169 mute ? 0x02 : 0x0); 4170 return ret; 4171 } 4172 4173 static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = { 4174 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4175 { 4176 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4177 .name = "Master Playback Switch", 4178 .subdevice = HDA_SUBDEV_AMP_FLAG, 4179 .info = snd_hda_mixer_amp_switch_info, 4180 .get = snd_hda_mixer_amp_switch_get, 4181 .put = ad1884a_mobile_master_sw_put, 4182 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), 4183 }, 4184 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4185 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4186 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4187 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4188 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4189 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 4190 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 4191 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 4192 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 4193 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 4194 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 4195 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 4196 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4197 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4198 { } /* end */ 4199 }; 4200 4201 static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = { 4202 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4203 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ 4204 { 4205 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4206 .name = "Master Playback Switch", 4207 .subdevice = HDA_SUBDEV_AMP_FLAG, 4208 .info = snd_hda_mixer_amp_switch_info, 4209 .get = snd_hda_mixer_amp_switch_get, 4210 .put = ad1884a_mobile_master_sw_put, 4211 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), 4212 }, 4213 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4214 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4215 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), 4216 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT), 4217 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4218 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4219 { } /* end */ 4220 }; 4221 4222 /* mute internal speaker if HP is plugged */ 4223 static void ad1884a_hp_automute(struct hda_codec *codec) 4224 { 4225 unsigned int present; 4226 4227 present = snd_hda_jack_detect(codec, 0x11); 4228 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 4229 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4230 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, 4231 present ? 0x00 : 0x02); 4232 } 4233 4234 /* switch to external mic if plugged */ 4235 static void ad1884a_hp_automic(struct hda_codec *codec) 4236 { 4237 unsigned int present; 4238 4239 present = snd_hda_jack_detect(codec, 0x14); 4240 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 4241 present ? 0 : 1); 4242 } 4243 4244 #define AD1884A_HP_EVENT 0x37 4245 #define AD1884A_MIC_EVENT 0x36 4246 4247 /* unsolicited event for HP jack sensing */ 4248 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res) 4249 { 4250 switch (res >> 26) { 4251 case AD1884A_HP_EVENT: 4252 ad1884a_hp_automute(codec); 4253 break; 4254 case AD1884A_MIC_EVENT: 4255 ad1884a_hp_automic(codec); 4256 break; 4257 } 4258 } 4259 4260 /* initialize jack-sensing, too */ 4261 static int ad1884a_hp_init(struct hda_codec *codec) 4262 { 4263 ad198x_init(codec); 4264 ad1884a_hp_automute(codec); 4265 ad1884a_hp_automic(codec); 4266 return 0; 4267 } 4268 4269 /* mute internal speaker if HP or docking HP is plugged */ 4270 static void ad1884a_laptop_automute(struct hda_codec *codec) 4271 { 4272 unsigned int present; 4273 4274 present = snd_hda_jack_detect(codec, 0x11); 4275 if (!present) 4276 present = snd_hda_jack_detect(codec, 0x12); 4277 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 4278 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4279 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, 4280 present ? 0x00 : 0x02); 4281 } 4282 4283 /* switch to external mic if plugged */ 4284 static void ad1884a_laptop_automic(struct hda_codec *codec) 4285 { 4286 unsigned int idx; 4287 4288 if (snd_hda_jack_detect(codec, 0x14)) 4289 idx = 0; 4290 else if (snd_hda_jack_detect(codec, 0x1c)) 4291 idx = 4; 4292 else 4293 idx = 1; 4294 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx); 4295 } 4296 4297 /* unsolicited event for HP jack sensing */ 4298 static void ad1884a_laptop_unsol_event(struct hda_codec *codec, 4299 unsigned int res) 4300 { 4301 switch (res >> 26) { 4302 case AD1884A_HP_EVENT: 4303 ad1884a_laptop_automute(codec); 4304 break; 4305 case AD1884A_MIC_EVENT: 4306 ad1884a_laptop_automic(codec); 4307 break; 4308 } 4309 } 4310 4311 /* initialize jack-sensing, too */ 4312 static int ad1884a_laptop_init(struct hda_codec *codec) 4313 { 4314 ad198x_init(codec); 4315 ad1884a_laptop_automute(codec); 4316 ad1884a_laptop_automic(codec); 4317 return 0; 4318 } 4319 4320 /* additional verbs for laptop model */ 4321 static const struct hda_verb ad1884a_laptop_verbs[] = { 4322 /* Port-A (HP) pin - always unmuted */ 4323 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4324 /* Port-F (int speaker) mixer - route only from analog mixer */ 4325 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4326 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4327 /* Port-F (int speaker) pin */ 4328 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4329 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4330 /* required for compaq 6530s/6531s speaker output */ 4331 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4332 /* Port-C pin - internal mic-in */ 4333 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4334 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4335 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4336 /* Port-D (docking line-out) pin - default unmuted */ 4337 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4338 /* analog mix */ 4339 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4340 /* unsolicited event for pin-sense */ 4341 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4342 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4343 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4344 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4345 /* allow to touch GPIO1 (for mute control) */ 4346 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 4347 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 4348 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ 4349 { } /* end */ 4350 }; 4351 4352 static const struct hda_verb ad1884a_mobile_verbs[] = { 4353 /* DACs; unmute as default */ 4354 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4355 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4356 /* Port-A (HP) mixer - route only from analog mixer */ 4357 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4358 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4359 /* Port-A pin */ 4360 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4361 /* Port-A (HP) pin - always unmuted */ 4362 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4363 /* Port-B (mic jack) pin */ 4364 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4365 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4366 /* Port-C (int mic) pin */ 4367 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4368 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4369 /* Port-F (int speaker) mixer - route only from analog mixer */ 4370 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4371 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4372 /* Port-F pin */ 4373 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4374 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4375 /* Analog mixer; mute as default */ 4376 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4377 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4378 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4379 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4380 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4381 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 4382 /* Analog Mix output amp */ 4383 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4384 /* capture sources */ 4385 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ 4386 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4387 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 4388 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4389 /* unsolicited event for pin-sense */ 4390 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4391 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4392 /* allow to touch GPIO1 (for mute control) */ 4393 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 4394 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 4395 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ 4396 { } /* end */ 4397 }; 4398 4399 /* 4400 * Thinkpad X300 4401 * 0x11 - HP 4402 * 0x12 - speaker 4403 * 0x14 - mic-in 4404 * 0x17 - built-in mic 4405 */ 4406 4407 static const struct hda_verb ad1984a_thinkpad_verbs[] = { 4408 /* HP unmute */ 4409 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4410 /* analog mix */ 4411 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4412 /* turn on EAPD */ 4413 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4414 /* unsolicited event for pin-sense */ 4415 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4416 /* internal mic - dmic */ 4417 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4418 /* set magic COEFs for dmic */ 4419 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, 4420 {0x01, AC_VERB_SET_PROC_COEF, 0x08}, 4421 { } /* end */ 4422 }; 4423 4424 static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = { 4425 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4426 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), 4427 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4428 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4429 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4430 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4431 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 4432 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT), 4433 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4434 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4435 { 4436 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4437 .name = "Capture Source", 4438 .info = ad198x_mux_enum_info, 4439 .get = ad198x_mux_enum_get, 4440 .put = ad198x_mux_enum_put, 4441 }, 4442 { } /* end */ 4443 }; 4444 4445 static const struct hda_input_mux ad1984a_thinkpad_capture_source = { 4446 .num_items = 3, 4447 .items = { 4448 { "Mic", 0x0 }, 4449 { "Internal Mic", 0x5 }, 4450 { "Mix", 0x3 }, 4451 }, 4452 }; 4453 4454 /* mute internal speaker if HP is plugged */ 4455 static void ad1984a_thinkpad_automute(struct hda_codec *codec) 4456 { 4457 unsigned int present; 4458 4459 present = snd_hda_jack_detect(codec, 0x11); 4460 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0, 4461 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4462 } 4463 4464 /* unsolicited event for HP jack sensing */ 4465 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec, 4466 unsigned int res) 4467 { 4468 if ((res >> 26) != AD1884A_HP_EVENT) 4469 return; 4470 ad1984a_thinkpad_automute(codec); 4471 } 4472 4473 /* initialize jack-sensing, too */ 4474 static int ad1984a_thinkpad_init(struct hda_codec *codec) 4475 { 4476 ad198x_init(codec); 4477 ad1984a_thinkpad_automute(codec); 4478 return 0; 4479 } 4480 4481 /* 4482 * Precision R5500 4483 * 0x12 - HP/line-out 4484 * 0x13 - speaker (mono) 4485 * 0x15 - mic-in 4486 */ 4487 4488 static const struct hda_verb ad1984a_precision_verbs[] = { 4489 /* Unmute main output path */ 4490 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4491 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */ 4492 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */ 4493 /* Analog mixer; mute as default */ 4494 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4495 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4496 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4497 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4498 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4499 /* Select mic as input */ 4500 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 4501 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */ 4502 /* Configure as mic */ 4503 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4504 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4505 /* HP unmute */ 4506 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4507 /* turn on EAPD */ 4508 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4509 /* unsolicited event for pin-sense */ 4510 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4511 { } /* end */ 4512 }; 4513 4514 static const struct snd_kcontrol_new ad1984a_precision_mixers[] = { 4515 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4516 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), 4517 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4518 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4519 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 4520 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 4521 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 4522 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4523 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT), 4524 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4525 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4526 { } /* end */ 4527 }; 4528 4529 4530 /* mute internal speaker if HP is plugged */ 4531 static void ad1984a_precision_automute(struct hda_codec *codec) 4532 { 4533 unsigned int present; 4534 4535 present = snd_hda_jack_detect(codec, 0x12); 4536 snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, 4537 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4538 } 4539 4540 4541 /* unsolicited event for HP jack sensing */ 4542 static void ad1984a_precision_unsol_event(struct hda_codec *codec, 4543 unsigned int res) 4544 { 4545 if ((res >> 26) != AD1884A_HP_EVENT) 4546 return; 4547 ad1984a_precision_automute(codec); 4548 } 4549 4550 /* initialize jack-sensing, too */ 4551 static int ad1984a_precision_init(struct hda_codec *codec) 4552 { 4553 ad198x_init(codec); 4554 ad1984a_precision_automute(codec); 4555 return 0; 4556 } 4557 4558 4559 /* 4560 * HP Touchsmart 4561 * port-A (0x11) - front hp-out 4562 * port-B (0x14) - unused 4563 * port-C (0x15) - unused 4564 * port-D (0x12) - rear line out 4565 * port-E (0x1c) - front mic-in 4566 * port-F (0x16) - Internal speakers 4567 * digital-mic (0x17) - Internal mic 4568 */ 4569 4570 static const struct hda_verb ad1984a_touchsmart_verbs[] = { 4571 /* DACs; unmute as default */ 4572 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4573 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4574 /* Port-A (HP) mixer - route only from analog mixer */ 4575 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4576 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4577 /* Port-A pin */ 4578 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4579 /* Port-A (HP) pin - always unmuted */ 4580 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4581 /* Port-E (int speaker) mixer - route only from analog mixer */ 4582 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03}, 4583 /* Port-E pin */ 4584 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4585 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4586 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4587 /* Port-F (int speaker) mixer - route only from analog mixer */ 4588 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4589 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4590 /* Port-F pin */ 4591 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4592 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4593 /* Analog mixer; mute as default */ 4594 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4595 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4596 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4597 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4598 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4599 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 4600 /* Analog Mix output amp */ 4601 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4602 /* capture sources */ 4603 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ 4604 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4605 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 4606 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4607 /* unsolicited event for pin-sense */ 4608 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4609 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4610 /* allow to touch GPIO1 (for mute control) */ 4611 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 4612 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 4613 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ 4614 /* internal mic - dmic */ 4615 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4616 /* set magic COEFs for dmic */ 4617 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, 4618 {0x01, AC_VERB_SET_PROC_COEF, 0x08}, 4619 { } /* end */ 4620 }; 4621 4622 static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { 4623 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4624 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ 4625 { 4626 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4627 .subdevice = HDA_SUBDEV_AMP_FLAG, 4628 .name = "Master Playback Switch", 4629 .info = snd_hda_mixer_amp_switch_info, 4630 .get = snd_hda_mixer_amp_switch_get, 4631 .put = ad1884a_mobile_master_sw_put, 4632 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), 4633 }, 4634 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4635 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4636 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4637 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4638 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 4639 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT), 4640 { } /* end */ 4641 }; 4642 4643 /* switch to external mic if plugged */ 4644 static void ad1984a_touchsmart_automic(struct hda_codec *codec) 4645 { 4646 if (snd_hda_jack_detect(codec, 0x1c)) 4647 snd_hda_codec_write(codec, 0x0c, 0, 4648 AC_VERB_SET_CONNECT_SEL, 0x4); 4649 else 4650 snd_hda_codec_write(codec, 0x0c, 0, 4651 AC_VERB_SET_CONNECT_SEL, 0x5); 4652 } 4653 4654 4655 /* unsolicited event for HP jack sensing */ 4656 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec, 4657 unsigned int res) 4658 { 4659 switch (res >> 26) { 4660 case AD1884A_HP_EVENT: 4661 ad1884a_hp_automute(codec); 4662 break; 4663 case AD1884A_MIC_EVENT: 4664 ad1984a_touchsmart_automic(codec); 4665 break; 4666 } 4667 } 4668 4669 /* initialize jack-sensing, too */ 4670 static int ad1984a_touchsmart_init(struct hda_codec *codec) 4671 { 4672 ad198x_init(codec); 4673 ad1884a_hp_automute(codec); 4674 ad1984a_touchsmart_automic(codec); 4675 return 0; 4676 } 4677 4678 4679 /* 4680 */ 4681 4682 enum { 4683 AD1884A_AUTO, 4684 AD1884A_DESKTOP, 4685 AD1884A_LAPTOP, 4686 AD1884A_MOBILE, 4687 AD1884A_THINKPAD, 4688 AD1984A_TOUCHSMART, 4689 AD1984A_PRECISION, 4690 AD1884A_MODELS 4691 }; 4692 4693 static const char * const ad1884a_models[AD1884A_MODELS] = { 4694 [AD1884A_AUTO] = "auto", 4695 [AD1884A_DESKTOP] = "desktop", 4696 [AD1884A_LAPTOP] = "laptop", 4697 [AD1884A_MOBILE] = "mobile", 4698 [AD1884A_THINKPAD] = "thinkpad", 4699 [AD1984A_TOUCHSMART] = "touchsmart", 4700 [AD1984A_PRECISION] = "precision", 4701 }; 4702 4703 static const struct snd_pci_quirk ad1884a_cfg_tbl[] = { 4704 SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION), 4705 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), 4706 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), 4707 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), 4708 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE), 4709 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP), 4710 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP), 4711 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), 4712 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), 4713 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), 4714 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART), 4715 {} 4716 }; 4717 4718 static int patch_ad1884a(struct hda_codec *codec) 4719 { 4720 struct ad198x_spec *spec; 4721 int err, board_config; 4722 4723 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS, 4724 ad1884a_models, 4725 ad1884a_cfg_tbl); 4726 if (board_config < 0) { 4727 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 4728 codec->chip_name); 4729 board_config = AD1884A_AUTO; 4730 } 4731 4732 if (board_config == AD1884A_AUTO) 4733 return ad1884_parse_auto_config(codec); 4734 4735 err = alloc_ad_spec(codec); 4736 if (err < 0) 4737 return err; 4738 spec = codec->spec; 4739 4740 err = snd_hda_attach_beep_device(codec, 0x10); 4741 if (err < 0) { 4742 ad198x_free(codec); 4743 return err; 4744 } 4745 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 4746 4747 spec->multiout.max_channels = 2; 4748 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids); 4749 spec->multiout.dac_nids = ad1884a_dac_nids; 4750 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT; 4751 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids); 4752 spec->adc_nids = ad1884a_adc_nids; 4753 spec->capsrc_nids = ad1884a_capsrc_nids; 4754 spec->input_mux = &ad1884a_capture_source; 4755 spec->num_mixers = 1; 4756 spec->mixers[0] = ad1884a_base_mixers; 4757 spec->num_init_verbs = 1; 4758 spec->init_verbs[0] = ad1884a_init_verbs; 4759 spec->spdif_route = 0; 4760 #ifdef CONFIG_PM 4761 spec->loopback.amplist = ad1884a_loopbacks; 4762 #endif 4763 codec->patch_ops = ad198x_patch_ops; 4764 4765 /* override some parameters */ 4766 switch (board_config) { 4767 case AD1884A_LAPTOP: 4768 spec->mixers[0] = ad1884a_laptop_mixers; 4769 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs; 4770 spec->multiout.dig_out_nid = 0; 4771 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event; 4772 codec->patch_ops.init = ad1884a_laptop_init; 4773 /* set the upper-limit for mixer amp to 0dB for avoiding the 4774 * possible damage by overloading 4775 */ 4776 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 4777 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 4778 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 4779 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 4780 (1 << AC_AMPCAP_MUTE_SHIFT)); 4781 break; 4782 case AD1884A_MOBILE: 4783 spec->mixers[0] = ad1884a_mobile_mixers; 4784 spec->init_verbs[0] = ad1884a_mobile_verbs; 4785 spec->multiout.dig_out_nid = 0; 4786 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; 4787 codec->patch_ops.init = ad1884a_hp_init; 4788 /* set the upper-limit for mixer amp to 0dB for avoiding the 4789 * possible damage by overloading 4790 */ 4791 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 4792 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 4793 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 4794 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 4795 (1 << AC_AMPCAP_MUTE_SHIFT)); 4796 break; 4797 case AD1884A_THINKPAD: 4798 spec->mixers[0] = ad1984a_thinkpad_mixers; 4799 spec->init_verbs[spec->num_init_verbs++] = 4800 ad1984a_thinkpad_verbs; 4801 spec->multiout.dig_out_nid = 0; 4802 spec->input_mux = &ad1984a_thinkpad_capture_source; 4803 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; 4804 codec->patch_ops.init = ad1984a_thinkpad_init; 4805 break; 4806 case AD1984A_PRECISION: 4807 spec->mixers[0] = ad1984a_precision_mixers; 4808 spec->init_verbs[spec->num_init_verbs++] = 4809 ad1984a_precision_verbs; 4810 spec->multiout.dig_out_nid = 0; 4811 codec->patch_ops.unsol_event = ad1984a_precision_unsol_event; 4812 codec->patch_ops.init = ad1984a_precision_init; 4813 break; 4814 case AD1984A_TOUCHSMART: 4815 spec->mixers[0] = ad1984a_touchsmart_mixers; 4816 spec->init_verbs[0] = ad1984a_touchsmart_verbs; 4817 spec->multiout.dig_out_nid = 0; 4818 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event; 4819 codec->patch_ops.init = ad1984a_touchsmart_init; 4820 /* set the upper-limit for mixer amp to 0dB for avoiding the 4821 * possible damage by overloading 4822 */ 4823 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 4824 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 4825 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 4826 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 4827 (1 << AC_AMPCAP_MUTE_SHIFT)); 4828 break; 4829 } 4830 4831 codec->no_trigger_sense = 1; 4832 codec->no_sticky_stream = 1; 4833 4834 return 0; 4835 } 4836 #else /* ENABLE_AD_STATIC_QUIRKS */ 4837 #define patch_ad1884a ad1884_parse_auto_config 4838 #endif /* ENABLE_AD_STATIC_QUIRKS */ 4839 4840 4841 /* 4842 * AD1882 / AD1882A 4843 * 4844 * port-A - front hp-out 4845 * port-B - front mic-in 4846 * port-C - rear line-in, shared surr-out (3stack) 4847 * port-D - rear line-out 4848 * port-E - rear mic-in, shared clfe-out (3stack) 4849 * port-F - rear surr-out (6stack) 4850 * port-G - rear clfe-out (6stack) 4851 */ 4852 4853 #ifdef ENABLE_AD_STATIC_QUIRKS 4854 static const hda_nid_t ad1882_dac_nids[3] = { 4855 0x04, 0x03, 0x05 4856 }; 4857 4858 static const hda_nid_t ad1882_adc_nids[2] = { 4859 0x08, 0x09, 4860 }; 4861 4862 static const hda_nid_t ad1882_capsrc_nids[2] = { 4863 0x0c, 0x0d, 4864 }; 4865 4866 #define AD1882_SPDIF_OUT 0x02 4867 4868 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */ 4869 static const struct hda_input_mux ad1882_capture_source = { 4870 .num_items = 5, 4871 .items = { 4872 { "Front Mic", 0x1 }, 4873 { "Mic", 0x4 }, 4874 { "Line", 0x2 }, 4875 { "CD", 0x3 }, 4876 { "Mix", 0x7 }, 4877 }, 4878 }; 4879 4880 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */ 4881 static const struct hda_input_mux ad1882a_capture_source = { 4882 .num_items = 5, 4883 .items = { 4884 { "Front Mic", 0x1 }, 4885 { "Mic", 0x4}, 4886 { "Line", 0x2 }, 4887 { "Digital Mic", 0x06 }, 4888 { "Mix", 0x7 }, 4889 }, 4890 }; 4891 4892 static const struct snd_kcontrol_new ad1882_base_mixers[] = { 4893 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 4894 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), 4895 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 4896 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 4897 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 4898 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4899 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 4900 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 4901 4902 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), 4903 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 4904 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT), 4905 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4906 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4907 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 4908 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 4909 { 4910 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4911 /* The multiple "Capture Source" controls confuse alsamixer 4912 * So call somewhat different.. 4913 */ 4914 /* .name = "Capture Source", */ 4915 .name = "Input Source", 4916 .count = 2, 4917 .info = ad198x_mux_enum_info, 4918 .get = ad198x_mux_enum_get, 4919 .put = ad198x_mux_enum_put, 4920 }, 4921 /* SPDIF controls */ 4922 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 4923 { 4924 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4925 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 4926 /* identical with ad1983 */ 4927 .info = ad1983_spdif_route_info, 4928 .get = ad1983_spdif_route_get, 4929 .put = ad1983_spdif_route_put, 4930 }, 4931 { } /* end */ 4932 }; 4933 4934 static const struct snd_kcontrol_new ad1882_loopback_mixers[] = { 4935 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4936 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4937 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 4938 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 4939 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT), 4940 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), 4941 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), 4942 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), 4943 { } /* end */ 4944 }; 4945 4946 static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = { 4947 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4948 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4949 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 4950 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 4951 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT), 4952 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), 4953 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), 4954 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), 4955 HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT), 4956 { } /* end */ 4957 }; 4958 4959 static const struct snd_kcontrol_new ad1882_3stack_mixers[] = { 4960 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), 4961 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT), 4962 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT), 4963 { 4964 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4965 .name = "Channel Mode", 4966 .info = ad198x_ch_mode_info, 4967 .get = ad198x_ch_mode_get, 4968 .put = ad198x_ch_mode_put, 4969 }, 4970 { } /* end */ 4971 }; 4972 4973 /* simple auto-mute control for AD1882 3-stack board */ 4974 #define AD1882_HP_EVENT 0x01 4975 4976 static void ad1882_3stack_automute(struct hda_codec *codec) 4977 { 4978 bool mute = snd_hda_jack_detect(codec, 0x11); 4979 snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 4980 mute ? 0 : PIN_OUT); 4981 } 4982 4983 static int ad1882_3stack_automute_init(struct hda_codec *codec) 4984 { 4985 ad198x_init(codec); 4986 ad1882_3stack_automute(codec); 4987 return 0; 4988 } 4989 4990 static void ad1882_3stack_unsol_event(struct hda_codec *codec, unsigned int res) 4991 { 4992 switch (res >> 26) { 4993 case AD1882_HP_EVENT: 4994 ad1882_3stack_automute(codec); 4995 break; 4996 } 4997 } 4998 4999 static const struct snd_kcontrol_new ad1882_6stack_mixers[] = { 5000 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT), 5001 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT), 5002 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT), 5003 { } /* end */ 5004 }; 5005 5006 static const struct hda_verb ad1882_ch2_init[] = { 5007 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 5008 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5009 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5010 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5011 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5012 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5013 { } /* end */ 5014 }; 5015 5016 static const struct hda_verb ad1882_ch4_init[] = { 5017 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5018 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5019 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5020 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5021 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5022 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5023 { } /* end */ 5024 }; 5025 5026 static const struct hda_verb ad1882_ch6_init[] = { 5027 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5028 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5029 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5030 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5031 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5032 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5033 { } /* end */ 5034 }; 5035 5036 static const struct hda_channel_mode ad1882_modes[3] = { 5037 { 2, ad1882_ch2_init }, 5038 { 4, ad1882_ch4_init }, 5039 { 6, ad1882_ch6_init }, 5040 }; 5041 5042 /* 5043 * initialization verbs 5044 */ 5045 static const struct hda_verb ad1882_init_verbs[] = { 5046 /* DACs; mute as default */ 5047 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5048 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5049 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5050 /* Port-A (HP) mixer */ 5051 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5052 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5053 /* Port-A pin */ 5054 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5055 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5056 /* HP selector - select DAC2 */ 5057 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1}, 5058 /* Port-D (Line-out) mixer */ 5059 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5060 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5061 /* Port-D pin */ 5062 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5063 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5064 /* Mono-out mixer */ 5065 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5066 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5067 /* Mono-out pin */ 5068 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5069 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5070 /* Port-B (front mic) pin */ 5071 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5072 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5073 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 5074 /* Port-C (line-in) pin */ 5075 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 5076 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5077 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 5078 /* Port-C mixer - mute as input */ 5079 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5080 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5081 /* Port-E (mic-in) pin */ 5082 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5083 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5084 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 5085 /* Port-E mixer - mute as input */ 5086 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5087 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5088 /* Port-F (surround) */ 5089 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5090 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5091 /* Port-G (CLFE) */ 5092 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5093 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5094 /* Analog mixer; mute as default */ 5095 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */ 5096 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5097 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5098 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5099 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5100 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5101 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 5102 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 5103 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 5104 /* Analog Mix output amp */ 5105 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 5106 /* SPDIF output selector */ 5107 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 5108 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 5109 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 5110 { } /* end */ 5111 }; 5112 5113 static const struct hda_verb ad1882_3stack_automute_verbs[] = { 5114 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1882_HP_EVENT}, 5115 { } /* end */ 5116 }; 5117 5118 #ifdef CONFIG_PM 5119 static const struct hda_amp_list ad1882_loopbacks[] = { 5120 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 5121 { 0x20, HDA_INPUT, 1 }, /* Mic */ 5122 { 0x20, HDA_INPUT, 4 }, /* Line */ 5123 { 0x20, HDA_INPUT, 6 }, /* CD */ 5124 { } /* end */ 5125 }; 5126 #endif 5127 5128 /* models */ 5129 enum { 5130 AD1882_AUTO, 5131 AD1882_3STACK, 5132 AD1882_6STACK, 5133 AD1882_3STACK_AUTOMUTE, 5134 AD1882_MODELS 5135 }; 5136 5137 static const char * const ad1882_models[AD1986A_MODELS] = { 5138 [AD1882_AUTO] = "auto", 5139 [AD1882_3STACK] = "3stack", 5140 [AD1882_6STACK] = "6stack", 5141 [AD1882_3STACK_AUTOMUTE] = "3stack-automute", 5142 }; 5143 #endif /* ENABLE_AD_STATIC_QUIRKS */ 5144 5145 static int ad1882_parse_auto_config(struct hda_codec *codec) 5146 { 5147 struct ad198x_spec *spec; 5148 int err; 5149 5150 err = alloc_ad_spec(codec); 5151 if (err < 0) 5152 return err; 5153 spec = codec->spec; 5154 5155 spec->gen.mixer_nid = 0x20; 5156 spec->gen.mixer_merge_nid = 0x21; 5157 spec->gen.beep_nid = 0x10; 5158 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 5159 err = ad198x_parse_auto_config(codec); 5160 if (err < 0) 5161 goto error; 5162 err = ad1988_add_spdif_mux_ctl(codec); 5163 if (err < 0) 5164 goto error; 5165 return 0; 5166 5167 error: 5168 snd_hda_gen_free(codec); 5169 return err; 5170 } 5171 5172 #ifdef ENABLE_AD_STATIC_QUIRKS 5173 static int patch_ad1882(struct hda_codec *codec) 5174 { 5175 struct ad198x_spec *spec; 5176 int err, board_config; 5177 5178 board_config = snd_hda_check_board_config(codec, AD1882_MODELS, 5179 ad1882_models, NULL); 5180 if (board_config < 0) { 5181 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 5182 codec->chip_name); 5183 board_config = AD1882_AUTO; 5184 } 5185 5186 if (board_config == AD1882_AUTO) 5187 return ad1882_parse_auto_config(codec); 5188 5189 err = alloc_ad_spec(codec); 5190 if (err < 0) 5191 return err; 5192 spec = codec->spec; 5193 5194 err = snd_hda_attach_beep_device(codec, 0x10); 5195 if (err < 0) { 5196 ad198x_free(codec); 5197 return err; 5198 } 5199 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 5200 5201 spec->multiout.max_channels = 6; 5202 spec->multiout.num_dacs = 3; 5203 spec->multiout.dac_nids = ad1882_dac_nids; 5204 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT; 5205 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids); 5206 spec->adc_nids = ad1882_adc_nids; 5207 spec->capsrc_nids = ad1882_capsrc_nids; 5208 if (codec->vendor_id == 0x11d41882) 5209 spec->input_mux = &ad1882_capture_source; 5210 else 5211 spec->input_mux = &ad1882a_capture_source; 5212 spec->num_mixers = 2; 5213 spec->mixers[0] = ad1882_base_mixers; 5214 if (codec->vendor_id == 0x11d41882) 5215 spec->mixers[1] = ad1882_loopback_mixers; 5216 else 5217 spec->mixers[1] = ad1882a_loopback_mixers; 5218 spec->num_init_verbs = 1; 5219 spec->init_verbs[0] = ad1882_init_verbs; 5220 spec->spdif_route = 0; 5221 #ifdef CONFIG_PM 5222 spec->loopback.amplist = ad1882_loopbacks; 5223 #endif 5224 spec->vmaster_nid = 0x04; 5225 5226 codec->patch_ops = ad198x_patch_ops; 5227 5228 /* override some parameters */ 5229 switch (board_config) { 5230 default: 5231 case AD1882_3STACK: 5232 case AD1882_3STACK_AUTOMUTE: 5233 spec->num_mixers = 3; 5234 spec->mixers[2] = ad1882_3stack_mixers; 5235 spec->channel_mode = ad1882_modes; 5236 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes); 5237 spec->need_dac_fix = 1; 5238 spec->multiout.max_channels = 2; 5239 spec->multiout.num_dacs = 1; 5240 if (board_config != AD1882_3STACK) { 5241 spec->init_verbs[spec->num_init_verbs++] = 5242 ad1882_3stack_automute_verbs; 5243 codec->patch_ops.unsol_event = ad1882_3stack_unsol_event; 5244 codec->patch_ops.init = ad1882_3stack_automute_init; 5245 } 5246 break; 5247 case AD1882_6STACK: 5248 spec->num_mixers = 3; 5249 spec->mixers[2] = ad1882_6stack_mixers; 5250 break; 5251 } 5252 5253 codec->no_trigger_sense = 1; 5254 codec->no_sticky_stream = 1; 5255 5256 return 0; 5257 } 5258 #else /* ENABLE_AD_STATIC_QUIRKS */ 5259 #define patch_ad1882 ad1882_parse_auto_config 5260 #endif /* ENABLE_AD_STATIC_QUIRKS */ 5261 5262 5263 /* 5264 * patch entries 5265 */ 5266 static const struct hda_codec_preset snd_hda_preset_analog[] = { 5267 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a }, 5268 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 }, 5269 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a }, 5270 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 }, 5271 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a }, 5272 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a }, 5273 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, 5274 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, 5275 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 }, 5276 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, 5277 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, 5278 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, 5279 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 }, 5280 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 }, 5281 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 }, 5282 {} /* terminator */ 5283 }; 5284 5285 MODULE_ALIAS("snd-hda-codec-id:11d4*"); 5286 5287 MODULE_LICENSE("GPL"); 5288 MODULE_DESCRIPTION("Analog Devices HD-audio codec"); 5289 5290 static struct hda_codec_preset_list analog_list = { 5291 .preset = snd_hda_preset_analog, 5292 .owner = THIS_MODULE, 5293 }; 5294 5295 static int __init patch_analog_init(void) 5296 { 5297 return snd_hda_add_codec_preset(&analog_list); 5298 } 5299 5300 static void __exit patch_analog_exit(void) 5301 { 5302 snd_hda_delete_codec_preset(&analog_list); 5303 } 5304 5305 module_init(patch_analog_init) 5306 module_exit(patch_analog_exit) 5307