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 snd_hda_codec_update_cache(codec, spec->eapd_nid, 0, 2116 AC_VERB_SET_EAPD_BTLENABLE, 2117 enabled ? 0x02 : 0x00); 2118 } 2119 2120 static void ad1981_fixup_hp_eapd(struct hda_codec *codec, 2121 const struct hda_fixup *fix, int action) 2122 { 2123 struct ad198x_spec *spec = codec->spec; 2124 2125 if (action == HDA_FIXUP_ACT_PRE_PROBE) { 2126 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook; 2127 spec->eapd_nid = 0x05; 2128 } 2129 } 2130 2131 /* set the upper-limit for mixer amp to 0dB for avoiding the possible 2132 * damage by overloading 2133 */ 2134 static void ad1981_fixup_amp_override(struct hda_codec *codec, 2135 const struct hda_fixup *fix, int action) 2136 { 2137 if (action == HDA_FIXUP_ACT_PRE_PROBE) 2138 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, 2139 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 2140 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 2141 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 2142 (1 << AC_AMPCAP_MUTE_SHIFT)); 2143 } 2144 2145 enum { 2146 AD1981_FIXUP_AMP_OVERRIDE, 2147 AD1981_FIXUP_HP_EAPD, 2148 }; 2149 2150 static const struct hda_fixup ad1981_fixups[] = { 2151 [AD1981_FIXUP_AMP_OVERRIDE] = { 2152 .type = HDA_FIXUP_FUNC, 2153 .v.func = ad1981_fixup_amp_override, 2154 }, 2155 [AD1981_FIXUP_HP_EAPD] = { 2156 .type = HDA_FIXUP_FUNC, 2157 .v.func = ad1981_fixup_hp_eapd, 2158 .chained = true, 2159 .chain_id = AD1981_FIXUP_AMP_OVERRIDE, 2160 }, 2161 }; 2162 2163 static const struct snd_pci_quirk ad1981_fixup_tbl[] = { 2164 SND_PCI_QUIRK_VENDOR(0x1014, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE), 2165 SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1981_FIXUP_HP_EAPD), 2166 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE), 2167 /* HP nx6320 (reversed SSID, H/W bug) */ 2168 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_FIXUP_HP_EAPD), 2169 {} 2170 }; 2171 2172 static int ad1981_parse_auto_config(struct hda_codec *codec) 2173 { 2174 struct ad198x_spec *spec; 2175 int err; 2176 2177 err = alloc_ad_spec(codec); 2178 if (err < 0) 2179 return -ENOMEM; 2180 spec = codec->spec; 2181 2182 spec->gen.mixer_nid = 0x0e; 2183 spec->gen.beep_nid = 0x10; 2184 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); 2185 2186 snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups); 2187 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 2188 2189 err = ad198x_parse_auto_config(codec); 2190 if (err < 0) 2191 goto error; 2192 err = ad1983_add_spdif_mux_ctl(codec); 2193 if (err < 0) 2194 goto error; 2195 2196 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); 2197 2198 return 0; 2199 2200 error: 2201 snd_hda_gen_free(codec); 2202 return err; 2203 } 2204 2205 #ifdef ENABLE_AD_STATIC_QUIRKS 2206 static int patch_ad1981(struct hda_codec *codec) 2207 { 2208 struct ad198x_spec *spec; 2209 int err, board_config; 2210 2211 board_config = snd_hda_check_board_config(codec, AD1981_MODELS, 2212 ad1981_models, 2213 ad1981_cfg_tbl); 2214 if (board_config < 0) { 2215 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 2216 codec->chip_name); 2217 board_config = AD1981_AUTO; 2218 } 2219 2220 if (board_config == AD1981_AUTO) 2221 return ad1981_parse_auto_config(codec); 2222 2223 err = alloc_ad_spec(codec); 2224 if (err < 0) 2225 return -ENOMEM; 2226 spec = codec->spec; 2227 2228 err = snd_hda_attach_beep_device(codec, 0x10); 2229 if (err < 0) { 2230 ad198x_free(codec); 2231 return err; 2232 } 2233 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); 2234 2235 spec->multiout.max_channels = 2; 2236 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); 2237 spec->multiout.dac_nids = ad1981_dac_nids; 2238 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; 2239 spec->num_adc_nids = 1; 2240 spec->adc_nids = ad1981_adc_nids; 2241 spec->capsrc_nids = ad1981_capsrc_nids; 2242 spec->input_mux = &ad1981_capture_source; 2243 spec->num_mixers = 1; 2244 spec->mixers[0] = ad1981_mixers; 2245 spec->num_init_verbs = 1; 2246 spec->init_verbs[0] = ad1981_init_verbs; 2247 spec->spdif_route = 0; 2248 #ifdef CONFIG_PM 2249 spec->loopback.amplist = ad1981_loopbacks; 2250 #endif 2251 spec->vmaster_nid = 0x05; 2252 2253 codec->patch_ops = ad198x_patch_ops; 2254 2255 /* override some parameters */ 2256 switch (board_config) { 2257 case AD1981_HP: 2258 spec->mixers[0] = ad1981_hp_mixers; 2259 spec->num_init_verbs = 2; 2260 spec->init_verbs[1] = ad1981_hp_init_verbs; 2261 if (!is_jack_available(codec, 0x0a)) 2262 spec->multiout.dig_out_nid = 0; 2263 spec->input_mux = &ad1981_hp_capture_source; 2264 2265 codec->patch_ops.init = ad1981_hp_init; 2266 codec->patch_ops.unsol_event = ad1981_hp_unsol_event; 2267 /* set the upper-limit for mixer amp to 0dB for avoiding the 2268 * possible damage by overloading 2269 */ 2270 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, 2271 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 2272 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 2273 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 2274 (1 << AC_AMPCAP_MUTE_SHIFT)); 2275 break; 2276 case AD1981_THINKPAD: 2277 spec->mixers[0] = ad1981_thinkpad_mixers; 2278 spec->input_mux = &ad1981_thinkpad_capture_source; 2279 /* set the upper-limit for mixer amp to 0dB for avoiding the 2280 * possible damage by overloading 2281 */ 2282 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, 2283 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 2284 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 2285 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 2286 (1 << AC_AMPCAP_MUTE_SHIFT)); 2287 break; 2288 case AD1981_TOSHIBA: 2289 spec->mixers[0] = ad1981_hp_mixers; 2290 spec->mixers[1] = ad1981_toshiba_mixers; 2291 spec->num_init_verbs = 2; 2292 spec->init_verbs[1] = ad1981_toshiba_init_verbs; 2293 spec->multiout.dig_out_nid = 0; 2294 spec->input_mux = &ad1981_hp_capture_source; 2295 codec->patch_ops.init = ad1981_hp_init; 2296 codec->patch_ops.unsol_event = ad1981_hp_unsol_event; 2297 break; 2298 } 2299 2300 codec->no_trigger_sense = 1; 2301 codec->no_sticky_stream = 1; 2302 2303 return 0; 2304 } 2305 #else /* ENABLE_AD_STATIC_QUIRKS */ 2306 #define patch_ad1981 ad1981_parse_auto_config 2307 #endif /* ENABLE_AD_STATIC_QUIRKS */ 2308 2309 2310 /* 2311 * AD1988 2312 * 2313 * Output pins and routes 2314 * 2315 * Pin Mix Sel DAC (*) 2316 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06 2317 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06 2318 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a 2319 * port-D 0x12 (mute/hp) <- 0x29 <- 04 2320 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a 2321 * port-F 0x16 (mute) <- 0x2a <- 06 2322 * port-G 0x24 (mute) <- 0x27 <- 05 2323 * port-H 0x25 (mute) <- 0x28 <- 0a 2324 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06 2325 * 2326 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah 2327 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug. 2328 * 2329 * Input pins and routes 2330 * 2331 * pin boost mix input # / adc input # 2332 * port-A 0x11 -> 0x38 -> mix 2, ADC 0 2333 * port-B 0x14 -> 0x39 -> mix 0, ADC 1 2334 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2 2335 * port-D 0x12 -> 0x3d -> mix 3, ADC 8 2336 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4 2337 * port-F 0x16 -> 0x3b -> mix 5, ADC 3 2338 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6 2339 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7 2340 * 2341 * 2342 * DAC assignment 2343 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03 2344 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03 2345 * 2346 * Inputs of Analog Mix (0x20) 2347 * 0:Port-B (front mic) 2348 * 1:Port-C/G/H (line-in) 2349 * 2:Port-A 2350 * 3:Port-D (line-in/2) 2351 * 4:Port-E/G/H (mic-in) 2352 * 5:Port-F (mic2-in) 2353 * 6:CD 2354 * 7:Beep 2355 * 2356 * ADC selection 2357 * 0:Port-A 2358 * 1:Port-B (front mic-in) 2359 * 2:Port-C (line-in) 2360 * 3:Port-F (mic2-in) 2361 * 4:Port-E (mic-in) 2362 * 5:CD 2363 * 6:Port-G 2364 * 7:Port-H 2365 * 8:Port-D (line-in/2) 2366 * 9:Mix 2367 * 2368 * Proposed pin assignments by the datasheet 2369 * 2370 * 6-stack 2371 * Port-A front headphone 2372 * B front mic-in 2373 * C rear line-in 2374 * D rear front-out 2375 * E rear mic-in 2376 * F rear surround 2377 * G rear CLFE 2378 * H rear side 2379 * 2380 * 3-stack 2381 * Port-A front headphone 2382 * B front mic 2383 * C rear line-in/surround 2384 * D rear front-out 2385 * E rear mic-in/CLFE 2386 * 2387 * laptop 2388 * Port-A headphone 2389 * B mic-in 2390 * C docking station 2391 * D internal speaker (with EAPD) 2392 * E/F quad mic array 2393 */ 2394 2395 2396 #ifdef ENABLE_AD_STATIC_QUIRKS 2397 /* models */ 2398 enum { 2399 AD1988_AUTO, 2400 AD1988_6STACK, 2401 AD1988_6STACK_DIG, 2402 AD1988_3STACK, 2403 AD1988_3STACK_DIG, 2404 AD1988_LAPTOP, 2405 AD1988_LAPTOP_DIG, 2406 AD1988_MODEL_LAST, 2407 }; 2408 2409 /* reivision id to check workarounds */ 2410 #define AD1988A_REV2 0x100200 2411 2412 #define is_rev2(codec) \ 2413 ((codec)->vendor_id == 0x11d41988 && \ 2414 (codec)->revision_id == AD1988A_REV2) 2415 2416 /* 2417 * mixers 2418 */ 2419 2420 static const hda_nid_t ad1988_6stack_dac_nids[4] = { 2421 0x04, 0x06, 0x05, 0x0a 2422 }; 2423 2424 static const hda_nid_t ad1988_3stack_dac_nids[3] = { 2425 0x04, 0x05, 0x0a 2426 }; 2427 2428 /* for AD1988A revision-2, DAC2-4 are swapped */ 2429 static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = { 2430 0x04, 0x05, 0x0a, 0x06 2431 }; 2432 2433 static const hda_nid_t ad1988_alt_dac_nid[1] = { 2434 0x03 2435 }; 2436 2437 static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = { 2438 0x04, 0x0a, 0x06 2439 }; 2440 2441 static const hda_nid_t ad1988_adc_nids[3] = { 2442 0x08, 0x09, 0x0f 2443 }; 2444 2445 static const hda_nid_t ad1988_capsrc_nids[3] = { 2446 0x0c, 0x0d, 0x0e 2447 }; 2448 2449 #define AD1988_SPDIF_OUT 0x02 2450 #define AD1988_SPDIF_OUT_HDMI 0x0b 2451 #define AD1988_SPDIF_IN 0x07 2452 2453 static const hda_nid_t ad1989b_slave_dig_outs[] = { 2454 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0 2455 }; 2456 2457 static const struct hda_input_mux ad1988_6stack_capture_source = { 2458 .num_items = 5, 2459 .items = { 2460 { "Front Mic", 0x1 }, /* port-B */ 2461 { "Line", 0x2 }, /* port-C */ 2462 { "Mic", 0x4 }, /* port-E */ 2463 { "CD", 0x5 }, 2464 { "Mix", 0x9 }, 2465 }, 2466 }; 2467 2468 static const struct hda_input_mux ad1988_laptop_capture_source = { 2469 .num_items = 3, 2470 .items = { 2471 { "Mic/Line", 0x1 }, /* port-B */ 2472 { "CD", 0x5 }, 2473 { "Mix", 0x9 }, 2474 }, 2475 }; 2476 2477 /* 2478 */ 2479 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, 2480 struct snd_ctl_elem_info *uinfo) 2481 { 2482 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2483 struct ad198x_spec *spec = codec->spec; 2484 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, 2485 spec->num_channel_mode); 2486 } 2487 2488 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, 2489 struct snd_ctl_elem_value *ucontrol) 2490 { 2491 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2492 struct ad198x_spec *spec = codec->spec; 2493 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, 2494 spec->num_channel_mode, spec->multiout.max_channels); 2495 } 2496 2497 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, 2498 struct snd_ctl_elem_value *ucontrol) 2499 { 2500 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2501 struct ad198x_spec *spec = codec->spec; 2502 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, 2503 spec->num_channel_mode, 2504 &spec->multiout.max_channels); 2505 if (err >= 0 && spec->need_dac_fix) 2506 spec->multiout.num_dacs = spec->multiout.max_channels / 2; 2507 return err; 2508 } 2509 2510 /* 6-stack mode */ 2511 static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = { 2512 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2513 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT), 2514 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 2515 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 2516 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 2517 { } /* end */ 2518 }; 2519 2520 static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = { 2521 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2522 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT), 2523 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 2524 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT), 2525 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT), 2526 { } /* end */ 2527 }; 2528 2529 static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = { 2530 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 2531 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), 2532 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT), 2533 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT), 2534 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT), 2535 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT), 2536 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), 2537 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 2538 2539 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 2540 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 2541 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 2542 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 2543 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 2544 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 2545 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), 2546 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), 2547 2548 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 2549 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 2550 2551 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 2552 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), 2553 { } /* end */ 2554 }; 2555 2556 /* 3-stack mode */ 2557 static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = { 2558 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2559 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 2560 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 2561 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 2562 { } /* end */ 2563 }; 2564 2565 static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = { 2566 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2567 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 2568 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT), 2569 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT), 2570 { } /* end */ 2571 }; 2572 2573 static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = { 2574 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 2575 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), 2576 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT), 2577 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT), 2578 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT), 2579 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), 2580 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 2581 2582 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 2583 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 2584 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 2585 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 2586 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 2587 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 2588 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), 2589 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), 2590 2591 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 2592 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 2593 2594 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 2595 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), 2596 { 2597 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2598 .name = "Channel Mode", 2599 .info = ad198x_ch_mode_info, 2600 .get = ad198x_ch_mode_get, 2601 .put = ad198x_ch_mode_put, 2602 }, 2603 2604 { } /* end */ 2605 }; 2606 2607 /* laptop mode */ 2608 static const struct snd_kcontrol_new ad1988_laptop_mixers[] = { 2609 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 2610 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2611 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT), 2612 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 2613 2614 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 2615 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 2616 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 2617 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 2618 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 2619 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 2620 2621 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 2622 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 2623 2624 HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 2625 2626 { 2627 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2628 .name = "External Amplifier", 2629 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12, 2630 .info = ad198x_eapd_info, 2631 .get = ad198x_eapd_get, 2632 .put = ad198x_eapd_put, 2633 .private_value = 0x12, /* port-D */ 2634 }, 2635 2636 { } /* end */ 2637 }; 2638 2639 /* capture */ 2640 static const struct snd_kcontrol_new ad1988_capture_mixers[] = { 2641 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 2642 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 2643 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 2644 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 2645 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT), 2646 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT), 2647 { 2648 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2649 /* The multiple "Capture Source" controls confuse alsamixer 2650 * So call somewhat different.. 2651 */ 2652 /* .name = "Capture Source", */ 2653 .name = "Input Source", 2654 .count = 3, 2655 .info = ad198x_mux_enum_info, 2656 .get = ad198x_mux_enum_get, 2657 .put = ad198x_mux_enum_put, 2658 }, 2659 { } /* end */ 2660 }; 2661 2662 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol, 2663 struct snd_ctl_elem_info *uinfo) 2664 { 2665 static const char * const texts[] = { 2666 "PCM", "ADC1", "ADC2", "ADC3" 2667 }; 2668 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2669 uinfo->count = 1; 2670 uinfo->value.enumerated.items = 4; 2671 if (uinfo->value.enumerated.item >= 4) 2672 uinfo->value.enumerated.item = 3; 2673 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2674 return 0; 2675 } 2676 2677 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol, 2678 struct snd_ctl_elem_value *ucontrol) 2679 { 2680 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2681 unsigned int sel; 2682 2683 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE, 2684 AC_AMP_GET_INPUT); 2685 if (!(sel & 0x80)) 2686 ucontrol->value.enumerated.item[0] = 0; 2687 else { 2688 sel = snd_hda_codec_read(codec, 0x0b, 0, 2689 AC_VERB_GET_CONNECT_SEL, 0); 2690 if (sel < 3) 2691 sel++; 2692 else 2693 sel = 0; 2694 ucontrol->value.enumerated.item[0] = sel; 2695 } 2696 return 0; 2697 } 2698 2699 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol, 2700 struct snd_ctl_elem_value *ucontrol) 2701 { 2702 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2703 unsigned int val, sel; 2704 int change; 2705 2706 val = ucontrol->value.enumerated.item[0]; 2707 if (val > 3) 2708 return -EINVAL; 2709 if (!val) { 2710 sel = snd_hda_codec_read(codec, 0x1d, 0, 2711 AC_VERB_GET_AMP_GAIN_MUTE, 2712 AC_AMP_GET_INPUT); 2713 change = sel & 0x80; 2714 if (change) { 2715 snd_hda_codec_write_cache(codec, 0x1d, 0, 2716 AC_VERB_SET_AMP_GAIN_MUTE, 2717 AMP_IN_UNMUTE(0)); 2718 snd_hda_codec_write_cache(codec, 0x1d, 0, 2719 AC_VERB_SET_AMP_GAIN_MUTE, 2720 AMP_IN_MUTE(1)); 2721 } 2722 } else { 2723 sel = snd_hda_codec_read(codec, 0x1d, 0, 2724 AC_VERB_GET_AMP_GAIN_MUTE, 2725 AC_AMP_GET_INPUT | 0x01); 2726 change = sel & 0x80; 2727 if (change) { 2728 snd_hda_codec_write_cache(codec, 0x1d, 0, 2729 AC_VERB_SET_AMP_GAIN_MUTE, 2730 AMP_IN_MUTE(0)); 2731 snd_hda_codec_write_cache(codec, 0x1d, 0, 2732 AC_VERB_SET_AMP_GAIN_MUTE, 2733 AMP_IN_UNMUTE(1)); 2734 } 2735 sel = snd_hda_codec_read(codec, 0x0b, 0, 2736 AC_VERB_GET_CONNECT_SEL, 0) + 1; 2737 change |= sel != val; 2738 if (change) 2739 snd_hda_codec_write_cache(codec, 0x0b, 0, 2740 AC_VERB_SET_CONNECT_SEL, 2741 val - 1); 2742 } 2743 return change; 2744 } 2745 2746 static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = { 2747 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 2748 { 2749 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2750 .name = "IEC958 Playback Source", 2751 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b, 2752 .info = ad1988_spdif_playback_source_info, 2753 .get = ad1988_spdif_playback_source_get, 2754 .put = ad1988_spdif_playback_source_put, 2755 }, 2756 { } /* end */ 2757 }; 2758 2759 static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = { 2760 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT), 2761 { } /* end */ 2762 }; 2763 2764 static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = { 2765 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 2766 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 2767 { } /* end */ 2768 }; 2769 2770 /* 2771 * initialization verbs 2772 */ 2773 2774 /* 2775 * for 6-stack (+dig) 2776 */ 2777 static const struct hda_verb ad1988_6stack_init_verbs[] = { 2778 /* Front, Surround, CLFE, side DAC; unmute as default */ 2779 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2780 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2781 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2782 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2783 /* Port-A front headphon path */ 2784 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 2785 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2786 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2787 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2788 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2789 /* Port-D line-out path */ 2790 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2791 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2792 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2793 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2794 /* Port-F surround path */ 2795 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2796 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2797 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2798 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2799 /* Port-G CLFE path */ 2800 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2801 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2802 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2803 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2804 /* Port-H side path */ 2805 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2806 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2807 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2808 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2809 /* Mono out path */ 2810 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 2811 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2812 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2813 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2814 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 2815 /* Port-B front mic-in path */ 2816 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2817 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2818 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2819 /* Port-C line-in path */ 2820 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2821 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2822 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2823 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 2824 /* Port-E mic-in path */ 2825 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2826 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2827 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2828 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, 2829 /* Analog CD Input */ 2830 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2831 /* Analog Mix output amp */ 2832 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 2833 2834 { } 2835 }; 2836 2837 static const struct hda_verb ad1988_6stack_fp_init_verbs[] = { 2838 /* Headphone; unmute as default */ 2839 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2840 /* Port-A front headphon path */ 2841 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 2842 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2843 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2844 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2845 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2846 2847 { } 2848 }; 2849 2850 static const struct hda_verb ad1988_capture_init_verbs[] = { 2851 /* mute analog mix */ 2852 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2853 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2854 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2855 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2856 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2857 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 2858 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 2859 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 2860 /* select ADCs - front-mic */ 2861 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 2862 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 2863 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2864 2865 { } 2866 }; 2867 2868 static const struct hda_verb ad1988_spdif_init_verbs[] = { 2869 /* SPDIF out sel */ 2870 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 2871 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */ 2872 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2873 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2874 /* SPDIF out pin */ 2875 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2876 2877 { } 2878 }; 2879 2880 static const struct hda_verb ad1988_spdif_in_init_verbs[] = { 2881 /* unmute SPDIF input pin */ 2882 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2883 { } 2884 }; 2885 2886 /* AD1989 has no ADC -> SPDIF route */ 2887 static const struct hda_verb ad1989_spdif_init_verbs[] = { 2888 /* SPDIF-1 out pin */ 2889 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2890 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2891 /* SPDIF-2/HDMI out pin */ 2892 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2893 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2894 { } 2895 }; 2896 2897 /* 2898 * verbs for 3stack (+dig) 2899 */ 2900 static const struct hda_verb ad1988_3stack_ch2_init[] = { 2901 /* set port-C to line-in */ 2902 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2903 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 2904 /* set port-E to mic-in */ 2905 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2906 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 2907 { } /* end */ 2908 }; 2909 2910 static const struct hda_verb ad1988_3stack_ch6_init[] = { 2911 /* set port-C to surround out */ 2912 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2913 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2914 /* set port-E to CLFE out */ 2915 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2916 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2917 { } /* end */ 2918 }; 2919 2920 static const struct hda_channel_mode ad1988_3stack_modes[2] = { 2921 { 2, ad1988_3stack_ch2_init }, 2922 { 6, ad1988_3stack_ch6_init }, 2923 }; 2924 2925 static const struct hda_verb ad1988_3stack_init_verbs[] = { 2926 /* Front, Surround, CLFE, side DAC; unmute as default */ 2927 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2928 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2929 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2930 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2931 /* Port-A front headphon path */ 2932 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 2933 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2934 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2935 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2936 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2937 /* Port-D line-out path */ 2938 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2939 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2940 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2941 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2942 /* Mono out path */ 2943 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 2944 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2945 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2946 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2947 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 2948 /* Port-B front mic-in path */ 2949 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2950 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2951 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2952 /* Port-C line-in/surround path - 6ch mode as default */ 2953 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2954 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2955 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2956 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */ 2957 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 2958 /* Port-E mic-in/CLFE path - 6ch mode as default */ 2959 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2960 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2961 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2962 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */ 2963 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, 2964 /* mute analog mix */ 2965 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2966 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2967 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2968 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2969 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2970 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 2971 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 2972 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 2973 /* select ADCs - front-mic */ 2974 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 2975 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 2976 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2977 /* Analog Mix output amp */ 2978 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 2979 { } 2980 }; 2981 2982 /* 2983 * verbs for laptop mode (+dig) 2984 */ 2985 static const struct hda_verb ad1988_laptop_hp_on[] = { 2986 /* unmute port-A and mute port-D */ 2987 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2988 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2989 { } /* end */ 2990 }; 2991 static const struct hda_verb ad1988_laptop_hp_off[] = { 2992 /* mute port-A and unmute port-D */ 2993 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2994 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2995 { } /* end */ 2996 }; 2997 2998 #define AD1988_HP_EVENT 0x01 2999 3000 static const struct hda_verb ad1988_laptop_init_verbs[] = { 3001 /* Front, Surround, CLFE, side DAC; unmute as default */ 3002 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3003 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3004 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3005 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3006 /* Port-A front headphon path */ 3007 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 3008 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3009 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3010 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3011 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3012 /* unsolicited event for pin-sense */ 3013 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT }, 3014 /* Port-D line-out path + EAPD */ 3015 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3016 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3017 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3018 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3019 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */ 3020 /* Mono out path */ 3021 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 3022 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3023 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3024 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3025 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 3026 /* Port-B mic-in path */ 3027 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3028 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3029 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3030 /* Port-C docking station - try to output */ 3031 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3032 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3033 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3034 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 3035 /* mute analog mix */ 3036 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3037 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3038 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 3039 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 3040 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3041 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 3042 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 3043 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 3044 /* select ADCs - mic */ 3045 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 3046 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 3047 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 3048 /* Analog Mix output amp */ 3049 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 3050 { } 3051 }; 3052 3053 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) 3054 { 3055 if ((res >> 26) != AD1988_HP_EVENT) 3056 return; 3057 if (snd_hda_jack_detect(codec, 0x11)) 3058 snd_hda_sequence_write(codec, ad1988_laptop_hp_on); 3059 else 3060 snd_hda_sequence_write(codec, ad1988_laptop_hp_off); 3061 } 3062 3063 #ifdef CONFIG_PM 3064 static const struct hda_amp_list ad1988_loopbacks[] = { 3065 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 3066 { 0x20, HDA_INPUT, 1 }, /* Line */ 3067 { 0x20, HDA_INPUT, 4 }, /* Mic */ 3068 { 0x20, HDA_INPUT, 6 }, /* CD */ 3069 { } /* end */ 3070 }; 3071 #endif 3072 #endif /* ENABLE_AD_STATIC_QUIRKS */ 3073 3074 static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol, 3075 struct snd_ctl_elem_info *uinfo) 3076 { 3077 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 3078 static const char * const texts[] = { 3079 "PCM", "ADC1", "ADC2", "ADC3", 3080 }; 3081 int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1; 3082 if (num_conns > 4) 3083 num_conns = 4; 3084 return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts); 3085 } 3086 3087 static int ad1988_auto_smux_enum_get(struct snd_kcontrol *kcontrol, 3088 struct snd_ctl_elem_value *ucontrol) 3089 { 3090 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 3091 struct ad198x_spec *spec = codec->spec; 3092 3093 ucontrol->value.enumerated.item[0] = spec->cur_smux; 3094 return 0; 3095 } 3096 3097 static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol, 3098 struct snd_ctl_elem_value *ucontrol) 3099 { 3100 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 3101 struct ad198x_spec *spec = codec->spec; 3102 unsigned int val = ucontrol->value.enumerated.item[0]; 3103 struct nid_path *path; 3104 int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1; 3105 3106 if (val >= num_conns) 3107 return -EINVAL; 3108 if (spec->cur_smux == val) 3109 return 0; 3110 3111 mutex_lock(&codec->control_mutex); 3112 codec->cached_write = 1; 3113 path = snd_hda_get_path_from_idx(codec, 3114 spec->smux_paths[spec->cur_smux]); 3115 if (path) 3116 snd_hda_activate_path(codec, path, false, true); 3117 path = snd_hda_get_path_from_idx(codec, spec->smux_paths[val]); 3118 if (path) 3119 snd_hda_activate_path(codec, path, true, true); 3120 spec->cur_smux = val; 3121 codec->cached_write = 0; 3122 mutex_unlock(&codec->control_mutex); 3123 snd_hda_codec_flush_cache(codec); /* flush the updates */ 3124 return 1; 3125 } 3126 3127 static struct snd_kcontrol_new ad1988_auto_smux_mixer = { 3128 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3129 .name = "IEC958 Playback Source", 3130 .info = ad1988_auto_smux_enum_info, 3131 .get = ad1988_auto_smux_enum_get, 3132 .put = ad1988_auto_smux_enum_put, 3133 }; 3134 3135 static int ad1988_auto_init(struct hda_codec *codec) 3136 { 3137 struct ad198x_spec *spec = codec->spec; 3138 int i, err; 3139 3140 err = snd_hda_gen_init(codec); 3141 if (err < 0) 3142 return err; 3143 if (!spec->gen.autocfg.dig_outs) 3144 return 0; 3145 3146 for (i = 0; i < 4; i++) { 3147 struct nid_path *path; 3148 path = snd_hda_get_path_from_idx(codec, spec->smux_paths[i]); 3149 if (path) 3150 snd_hda_activate_path(codec, path, path->active, false); 3151 } 3152 3153 return 0; 3154 } 3155 3156 static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec) 3157 { 3158 struct ad198x_spec *spec = codec->spec; 3159 int i, num_conns; 3160 /* we create four static faked paths, since AD codecs have odd 3161 * widget connections regarding the SPDIF out source 3162 */ 3163 static struct nid_path fake_paths[4] = { 3164 { 3165 .depth = 3, 3166 .path = { 0x02, 0x1d, 0x1b }, 3167 .idx = { 0, 0, 0 }, 3168 .multi = { 0, 0, 0 }, 3169 }, 3170 { 3171 .depth = 4, 3172 .path = { 0x08, 0x0b, 0x1d, 0x1b }, 3173 .idx = { 0, 0, 1, 0 }, 3174 .multi = { 0, 1, 0, 0 }, 3175 }, 3176 { 3177 .depth = 4, 3178 .path = { 0x09, 0x0b, 0x1d, 0x1b }, 3179 .idx = { 0, 1, 1, 0 }, 3180 .multi = { 0, 1, 0, 0 }, 3181 }, 3182 { 3183 .depth = 4, 3184 .path = { 0x0f, 0x0b, 0x1d, 0x1b }, 3185 .idx = { 0, 2, 1, 0 }, 3186 .multi = { 0, 1, 0, 0 }, 3187 }, 3188 }; 3189 3190 /* SPDIF source mux appears to be present only on AD1988A */ 3191 if (!spec->gen.autocfg.dig_outs || 3192 get_wcaps_type(get_wcaps(codec, 0x1d)) != AC_WID_AUD_MIX) 3193 return 0; 3194 3195 num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1; 3196 if (num_conns != 3 && num_conns != 4) 3197 return 0; 3198 3199 for (i = 0; i < num_conns; i++) { 3200 struct nid_path *path = snd_array_new(&spec->gen.paths); 3201 if (!path) 3202 return -ENOMEM; 3203 *path = fake_paths[i]; 3204 if (!i) 3205 path->active = 1; 3206 spec->smux_paths[i] = snd_hda_get_path_idx(codec, path); 3207 } 3208 3209 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1988_auto_smux_mixer)) 3210 return -ENOMEM; 3211 3212 codec->patch_ops.init = ad1988_auto_init; 3213 3214 return 0; 3215 } 3216 3217 /* 3218 */ 3219 3220 static int ad1988_parse_auto_config(struct hda_codec *codec) 3221 { 3222 struct ad198x_spec *spec; 3223 int err; 3224 3225 err = alloc_ad_spec(codec); 3226 if (err < 0) 3227 return err; 3228 spec = codec->spec; 3229 3230 spec->gen.mixer_nid = 0x20; 3231 spec->gen.mixer_merge_nid = 0x21; 3232 spec->gen.beep_nid = 0x10; 3233 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3234 err = ad198x_parse_auto_config(codec); 3235 if (err < 0) 3236 goto error; 3237 err = ad1988_add_spdif_mux_ctl(codec); 3238 if (err < 0) 3239 goto error; 3240 return 0; 3241 3242 error: 3243 snd_hda_gen_free(codec); 3244 return err; 3245 } 3246 3247 /* 3248 */ 3249 3250 #ifdef ENABLE_AD_STATIC_QUIRKS 3251 static const char * const ad1988_models[AD1988_MODEL_LAST] = { 3252 [AD1988_6STACK] = "6stack", 3253 [AD1988_6STACK_DIG] = "6stack-dig", 3254 [AD1988_3STACK] = "3stack", 3255 [AD1988_3STACK_DIG] = "3stack-dig", 3256 [AD1988_LAPTOP] = "laptop", 3257 [AD1988_LAPTOP_DIG] = "laptop-dig", 3258 [AD1988_AUTO] = "auto", 3259 }; 3260 3261 static const struct snd_pci_quirk ad1988_cfg_tbl[] = { 3262 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG), 3263 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG), 3264 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG), 3265 SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG), 3266 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG), 3267 {} 3268 }; 3269 3270 static int patch_ad1988(struct hda_codec *codec) 3271 { 3272 struct ad198x_spec *spec; 3273 int err, board_config; 3274 3275 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST, 3276 ad1988_models, ad1988_cfg_tbl); 3277 if (board_config < 0) { 3278 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 3279 codec->chip_name); 3280 board_config = AD1988_AUTO; 3281 } 3282 3283 if (board_config == AD1988_AUTO) 3284 return ad1988_parse_auto_config(codec); 3285 3286 err = alloc_ad_spec(codec); 3287 if (err < 0) 3288 return err; 3289 spec = codec->spec; 3290 3291 if (is_rev2(codec)) 3292 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n"); 3293 3294 err = snd_hda_attach_beep_device(codec, 0x10); 3295 if (err < 0) { 3296 ad198x_free(codec); 3297 return err; 3298 } 3299 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3300 3301 if (!spec->multiout.hp_nid) 3302 spec->multiout.hp_nid = ad1988_alt_dac_nid[0]; 3303 switch (board_config) { 3304 case AD1988_6STACK: 3305 case AD1988_6STACK_DIG: 3306 spec->multiout.max_channels = 8; 3307 spec->multiout.num_dacs = 4; 3308 if (is_rev2(codec)) 3309 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2; 3310 else 3311 spec->multiout.dac_nids = ad1988_6stack_dac_nids; 3312 spec->input_mux = &ad1988_6stack_capture_source; 3313 spec->num_mixers = 2; 3314 if (is_rev2(codec)) 3315 spec->mixers[0] = ad1988_6stack_mixers1_rev2; 3316 else 3317 spec->mixers[0] = ad1988_6stack_mixers1; 3318 spec->mixers[1] = ad1988_6stack_mixers2; 3319 spec->num_init_verbs = 1; 3320 spec->init_verbs[0] = ad1988_6stack_init_verbs; 3321 if (board_config == AD1988_6STACK_DIG) { 3322 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 3323 spec->dig_in_nid = AD1988_SPDIF_IN; 3324 } 3325 break; 3326 case AD1988_3STACK: 3327 case AD1988_3STACK_DIG: 3328 spec->multiout.max_channels = 6; 3329 spec->multiout.num_dacs = 3; 3330 if (is_rev2(codec)) 3331 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2; 3332 else 3333 spec->multiout.dac_nids = ad1988_3stack_dac_nids; 3334 spec->input_mux = &ad1988_6stack_capture_source; 3335 spec->channel_mode = ad1988_3stack_modes; 3336 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes); 3337 spec->num_mixers = 2; 3338 if (is_rev2(codec)) 3339 spec->mixers[0] = ad1988_3stack_mixers1_rev2; 3340 else 3341 spec->mixers[0] = ad1988_3stack_mixers1; 3342 spec->mixers[1] = ad1988_3stack_mixers2; 3343 spec->num_init_verbs = 1; 3344 spec->init_verbs[0] = ad1988_3stack_init_verbs; 3345 if (board_config == AD1988_3STACK_DIG) 3346 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 3347 break; 3348 case AD1988_LAPTOP: 3349 case AD1988_LAPTOP_DIG: 3350 spec->multiout.max_channels = 2; 3351 spec->multiout.num_dacs = 1; 3352 spec->multiout.dac_nids = ad1988_3stack_dac_nids; 3353 spec->input_mux = &ad1988_laptop_capture_source; 3354 spec->num_mixers = 1; 3355 spec->mixers[0] = ad1988_laptop_mixers; 3356 codec->inv_eapd = 1; /* inverted EAPD */ 3357 spec->num_init_verbs = 1; 3358 spec->init_verbs[0] = ad1988_laptop_init_verbs; 3359 if (board_config == AD1988_LAPTOP_DIG) 3360 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 3361 break; 3362 } 3363 3364 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids); 3365 spec->adc_nids = ad1988_adc_nids; 3366 spec->capsrc_nids = ad1988_capsrc_nids; 3367 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers; 3368 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs; 3369 if (spec->multiout.dig_out_nid) { 3370 if (codec->vendor_id >= 0x11d4989a) { 3371 spec->mixers[spec->num_mixers++] = 3372 ad1989_spdif_out_mixers; 3373 spec->init_verbs[spec->num_init_verbs++] = 3374 ad1989_spdif_init_verbs; 3375 codec->slave_dig_outs = ad1989b_slave_dig_outs; 3376 } else { 3377 spec->mixers[spec->num_mixers++] = 3378 ad1988_spdif_out_mixers; 3379 spec->init_verbs[spec->num_init_verbs++] = 3380 ad1988_spdif_init_verbs; 3381 } 3382 } 3383 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) { 3384 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers; 3385 spec->init_verbs[spec->num_init_verbs++] = 3386 ad1988_spdif_in_init_verbs; 3387 } 3388 3389 codec->patch_ops = ad198x_patch_ops; 3390 switch (board_config) { 3391 case AD1988_LAPTOP: 3392 case AD1988_LAPTOP_DIG: 3393 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; 3394 break; 3395 } 3396 #ifdef CONFIG_PM 3397 spec->loopback.amplist = ad1988_loopbacks; 3398 #endif 3399 spec->vmaster_nid = 0x04; 3400 3401 codec->no_trigger_sense = 1; 3402 codec->no_sticky_stream = 1; 3403 3404 return 0; 3405 } 3406 #else /* ENABLE_AD_STATIC_QUIRKS */ 3407 #define patch_ad1988 ad1988_parse_auto_config 3408 #endif /* ENABLE_AD_STATIC_QUIRKS */ 3409 3410 3411 /* 3412 * AD1884 / AD1984 3413 * 3414 * port-B - front line/mic-in 3415 * port-E - aux in/out 3416 * port-F - aux in/out 3417 * port-C - rear line/mic-in 3418 * port-D - rear line/hp-out 3419 * port-A - front line/hp-out 3420 * 3421 * AD1984 = AD1884 + two digital mic-ins 3422 * 3423 * FIXME: 3424 * For simplicity, we share the single DAC for both HP and line-outs 3425 * right now. The inidividual playbacks could be easily implemented, 3426 * but no build-up framework is given, so far. 3427 */ 3428 3429 #ifdef ENABLE_AD_STATIC_QUIRKS 3430 static const hda_nid_t ad1884_dac_nids[1] = { 3431 0x04, 3432 }; 3433 3434 static const hda_nid_t ad1884_adc_nids[2] = { 3435 0x08, 0x09, 3436 }; 3437 3438 static const hda_nid_t ad1884_capsrc_nids[2] = { 3439 0x0c, 0x0d, 3440 }; 3441 3442 #define AD1884_SPDIF_OUT 0x02 3443 3444 static const struct hda_input_mux ad1884_capture_source = { 3445 .num_items = 4, 3446 .items = { 3447 { "Front Mic", 0x0 }, 3448 { "Mic", 0x1 }, 3449 { "CD", 0x2 }, 3450 { "Mix", 0x3 }, 3451 }, 3452 }; 3453 3454 static const struct snd_kcontrol_new ad1884_base_mixers[] = { 3455 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3456 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ 3457 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3458 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3459 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 3460 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 3461 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3462 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3463 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 3464 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 3465 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), 3466 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), 3467 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 3468 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 3469 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3470 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3471 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3472 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3473 { 3474 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3475 /* The multiple "Capture Source" controls confuse alsamixer 3476 * So call somewhat different.. 3477 */ 3478 /* .name = "Capture Source", */ 3479 .name = "Input Source", 3480 .count = 2, 3481 .info = ad198x_mux_enum_info, 3482 .get = ad198x_mux_enum_get, 3483 .put = ad198x_mux_enum_put, 3484 }, 3485 /* SPDIF controls */ 3486 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 3487 { 3488 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3489 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 3490 /* identical with ad1983 */ 3491 .info = ad1983_spdif_route_info, 3492 .get = ad1983_spdif_route_get, 3493 .put = ad1983_spdif_route_put, 3494 }, 3495 { } /* end */ 3496 }; 3497 3498 static const struct snd_kcontrol_new ad1984_dmic_mixers[] = { 3499 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT), 3500 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT), 3501 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0, 3502 HDA_INPUT), 3503 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0, 3504 HDA_INPUT), 3505 { } /* end */ 3506 }; 3507 3508 /* 3509 * initialization verbs 3510 */ 3511 static const struct hda_verb ad1884_init_verbs[] = { 3512 /* DACs; mute as default */ 3513 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3514 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3515 /* Port-A (HP) mixer */ 3516 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3517 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3518 /* Port-A pin */ 3519 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3520 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3521 /* HP selector - select DAC2 */ 3522 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1}, 3523 /* Port-D (Line-out) mixer */ 3524 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3525 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3526 /* Port-D pin */ 3527 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3528 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3529 /* Mono-out mixer */ 3530 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3531 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3532 /* Mono-out pin */ 3533 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3534 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3535 /* Mono selector */ 3536 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 3537 /* Port-B (front mic) pin */ 3538 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3539 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3540 /* Port-C (rear mic) pin */ 3541 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3542 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3543 /* Analog mixer; mute as default */ 3544 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3545 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3546 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 3547 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 3548 /* Analog Mix output amp */ 3549 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 3550 /* SPDIF output selector */ 3551 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 3552 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 3553 { } /* end */ 3554 }; 3555 3556 #ifdef CONFIG_PM 3557 static const struct hda_amp_list ad1884_loopbacks[] = { 3558 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 3559 { 0x20, HDA_INPUT, 1 }, /* Mic */ 3560 { 0x20, HDA_INPUT, 2 }, /* CD */ 3561 { 0x20, HDA_INPUT, 4 }, /* Docking */ 3562 { } /* end */ 3563 }; 3564 #endif 3565 3566 static const char * const ad1884_slave_vols[] = { 3567 "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD", 3568 "Internal Mic", "Dock Mic", /* "Beep", */ "IEC958", 3569 NULL 3570 }; 3571 3572 enum { 3573 AD1884_AUTO, 3574 AD1884_BASIC, 3575 AD1884_MODELS 3576 }; 3577 3578 static const char * const ad1884_models[AD1884_MODELS] = { 3579 [AD1884_AUTO] = "auto", 3580 [AD1884_BASIC] = "basic", 3581 }; 3582 #endif /* ENABLE_AD_STATIC_QUIRKS */ 3583 3584 3585 /* set the upper-limit for mixer amp to 0dB for avoiding the possible 3586 * damage by overloading 3587 */ 3588 static void ad1884_fixup_amp_override(struct hda_codec *codec, 3589 const struct hda_fixup *fix, int action) 3590 { 3591 if (action == HDA_FIXUP_ACT_PRE_PROBE) 3592 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 3593 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 3594 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 3595 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 3596 (1 << AC_AMPCAP_MUTE_SHIFT)); 3597 } 3598 3599 static void ad1884_fixup_hp_eapd(struct hda_codec *codec, 3600 const struct hda_fixup *fix, int action) 3601 { 3602 struct ad198x_spec *spec = codec->spec; 3603 3604 if (action == HDA_FIXUP_ACT_PRE_PROBE) { 3605 if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) 3606 spec->eapd_nid = spec->gen.autocfg.line_out_pins[0]; 3607 else 3608 spec->eapd_nid = spec->gen.autocfg.speaker_pins[0]; 3609 if (spec->eapd_nid) 3610 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook; 3611 } 3612 } 3613 3614 enum { 3615 AD1884_FIXUP_AMP_OVERRIDE, 3616 AD1884_FIXUP_HP_EAPD, 3617 }; 3618 3619 static const struct hda_fixup ad1884_fixups[] = { 3620 [AD1884_FIXUP_AMP_OVERRIDE] = { 3621 .type = HDA_FIXUP_FUNC, 3622 .v.func = ad1884_fixup_amp_override, 3623 }, 3624 [AD1884_FIXUP_HP_EAPD] = { 3625 .type = HDA_FIXUP_FUNC, 3626 .v.func = ad1884_fixup_hp_eapd, 3627 .chained = true, 3628 .chain_id = AD1884_FIXUP_AMP_OVERRIDE, 3629 }, 3630 }; 3631 3632 static const struct snd_pci_quirk ad1884_fixup_tbl[] = { 3633 SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD), 3634 {} 3635 }; 3636 3637 3638 static int ad1884_parse_auto_config(struct hda_codec *codec) 3639 { 3640 struct ad198x_spec *spec; 3641 int err; 3642 3643 err = alloc_ad_spec(codec); 3644 if (err < 0) 3645 return err; 3646 spec = codec->spec; 3647 3648 spec->gen.mixer_nid = 0x20; 3649 spec->gen.beep_nid = 0x10; 3650 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3651 3652 snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups); 3653 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 3654 3655 err = ad198x_parse_auto_config(codec); 3656 if (err < 0) 3657 goto error; 3658 err = ad1983_add_spdif_mux_ctl(codec); 3659 if (err < 0) 3660 goto error; 3661 3662 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); 3663 3664 return 0; 3665 3666 error: 3667 snd_hda_gen_free(codec); 3668 return err; 3669 } 3670 3671 #ifdef ENABLE_AD_STATIC_QUIRKS 3672 static int patch_ad1884_basic(struct hda_codec *codec) 3673 { 3674 struct ad198x_spec *spec; 3675 int err; 3676 3677 err = alloc_ad_spec(codec); 3678 if (err < 0) 3679 return err; 3680 spec = codec->spec; 3681 3682 err = snd_hda_attach_beep_device(codec, 0x10); 3683 if (err < 0) { 3684 ad198x_free(codec); 3685 return err; 3686 } 3687 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3688 3689 spec->multiout.max_channels = 2; 3690 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); 3691 spec->multiout.dac_nids = ad1884_dac_nids; 3692 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; 3693 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids); 3694 spec->adc_nids = ad1884_adc_nids; 3695 spec->capsrc_nids = ad1884_capsrc_nids; 3696 spec->input_mux = &ad1884_capture_source; 3697 spec->num_mixers = 1; 3698 spec->mixers[0] = ad1884_base_mixers; 3699 spec->num_init_verbs = 1; 3700 spec->init_verbs[0] = ad1884_init_verbs; 3701 spec->spdif_route = 0; 3702 #ifdef CONFIG_PM 3703 spec->loopback.amplist = ad1884_loopbacks; 3704 #endif 3705 spec->vmaster_nid = 0x04; 3706 /* we need to cover all playback volumes */ 3707 spec->slave_vols = ad1884_slave_vols; 3708 /* slaves may contain input volumes, so we can't raise to 0dB blindly */ 3709 spec->avoid_init_slave_vol = 1; 3710 3711 codec->patch_ops = ad198x_patch_ops; 3712 3713 codec->no_trigger_sense = 1; 3714 codec->no_sticky_stream = 1; 3715 3716 return 0; 3717 } 3718 3719 static int patch_ad1884(struct hda_codec *codec) 3720 { 3721 int board_config; 3722 3723 board_config = snd_hda_check_board_config(codec, AD1884_MODELS, 3724 ad1884_models, NULL); 3725 if (board_config < 0) { 3726 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 3727 codec->chip_name); 3728 board_config = AD1884_AUTO; 3729 } 3730 3731 if (board_config == AD1884_AUTO) 3732 return ad1884_parse_auto_config(codec); 3733 else 3734 return patch_ad1884_basic(codec); 3735 } 3736 #else /* ENABLE_AD_STATIC_QUIRKS */ 3737 #define patch_ad1884 ad1884_parse_auto_config 3738 #endif /* ENABLE_AD_STATIC_QUIRKS */ 3739 3740 3741 #ifdef ENABLE_AD_STATIC_QUIRKS 3742 /* 3743 * Lenovo Thinkpad T61/X61 3744 */ 3745 static const struct hda_input_mux ad1984_thinkpad_capture_source = { 3746 .num_items = 4, 3747 .items = { 3748 { "Mic", 0x0 }, 3749 { "Internal Mic", 0x1 }, 3750 { "Mix", 0x3 }, 3751 { "Dock Mic", 0x4 }, 3752 }, 3753 }; 3754 3755 3756 /* 3757 * Dell Precision T3400 3758 */ 3759 static const struct hda_input_mux ad1984_dell_desktop_capture_source = { 3760 .num_items = 3, 3761 .items = { 3762 { "Front Mic", 0x0 }, 3763 { "Line-In", 0x1 }, 3764 { "Mix", 0x3 }, 3765 }, 3766 }; 3767 3768 3769 static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { 3770 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3771 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ 3772 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3773 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3774 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3775 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3776 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 3777 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 3778 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), 3779 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), 3780 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 3781 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 3782 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 3783 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 3784 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 3785 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3786 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3787 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3788 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3789 { 3790 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3791 /* The multiple "Capture Source" controls confuse alsamixer 3792 * So call somewhat different.. 3793 */ 3794 /* .name = "Capture Source", */ 3795 .name = "Input Source", 3796 .count = 2, 3797 .info = ad198x_mux_enum_info, 3798 .get = ad198x_mux_enum_get, 3799 .put = ad198x_mux_enum_put, 3800 }, 3801 /* SPDIF controls */ 3802 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 3803 { 3804 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3805 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 3806 /* identical with ad1983 */ 3807 .info = ad1983_spdif_route_info, 3808 .get = ad1983_spdif_route_get, 3809 .put = ad1983_spdif_route_put, 3810 }, 3811 { } /* end */ 3812 }; 3813 3814 /* additional verbs */ 3815 static const struct hda_verb ad1984_thinkpad_init_verbs[] = { 3816 /* Port-E (docking station mic) pin */ 3817 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3818 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3819 /* docking mic boost */ 3820 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3821 /* Analog PC Beeper - allow firmware/ACPI beeps */ 3822 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a}, 3823 /* Analog mixer - docking mic; mute as default */ 3824 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3825 /* enable EAPD bit */ 3826 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 3827 { } /* end */ 3828 }; 3829 3830 /* 3831 * Dell Precision T3400 3832 */ 3833 static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = { 3834 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3835 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3836 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3837 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 3838 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 3839 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3840 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3841 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), 3842 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), 3843 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT), 3844 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 3845 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3846 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3847 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3848 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3849 { 3850 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3851 /* The multiple "Capture Source" controls confuse alsamixer 3852 * So call somewhat different.. 3853 */ 3854 /* .name = "Capture Source", */ 3855 .name = "Input Source", 3856 .count = 2, 3857 .info = ad198x_mux_enum_info, 3858 .get = ad198x_mux_enum_get, 3859 .put = ad198x_mux_enum_put, 3860 }, 3861 { } /* end */ 3862 }; 3863 3864 /* Digial MIC ADC NID 0x05 + 0x06 */ 3865 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo, 3866 struct hda_codec *codec, 3867 unsigned int stream_tag, 3868 unsigned int format, 3869 struct snd_pcm_substream *substream) 3870 { 3871 snd_hda_codec_setup_stream(codec, 0x05 + substream->number, 3872 stream_tag, 0, format); 3873 return 0; 3874 } 3875 3876 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo, 3877 struct hda_codec *codec, 3878 struct snd_pcm_substream *substream) 3879 { 3880 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number); 3881 return 0; 3882 } 3883 3884 static const struct hda_pcm_stream ad1984_pcm_dmic_capture = { 3885 .substreams = 2, 3886 .channels_min = 2, 3887 .channels_max = 2, 3888 .nid = 0x05, 3889 .ops = { 3890 .prepare = ad1984_pcm_dmic_prepare, 3891 .cleanup = ad1984_pcm_dmic_cleanup 3892 }, 3893 }; 3894 3895 static int ad1984_build_pcms(struct hda_codec *codec) 3896 { 3897 struct ad198x_spec *spec = codec->spec; 3898 struct hda_pcm *info; 3899 int err; 3900 3901 err = ad198x_build_pcms(codec); 3902 if (err < 0) 3903 return err; 3904 3905 info = spec->pcm_rec + codec->num_pcms; 3906 codec->num_pcms++; 3907 info->name = "AD1984 Digital Mic"; 3908 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture; 3909 return 0; 3910 } 3911 3912 /* models */ 3913 enum { 3914 AD1984_AUTO, 3915 AD1984_BASIC, 3916 AD1984_THINKPAD, 3917 AD1984_DELL_DESKTOP, 3918 AD1984_MODELS 3919 }; 3920 3921 static const char * const ad1984_models[AD1984_MODELS] = { 3922 [AD1984_AUTO] = "auto", 3923 [AD1984_BASIC] = "basic", 3924 [AD1984_THINKPAD] = "thinkpad", 3925 [AD1984_DELL_DESKTOP] = "dell_desktop", 3926 }; 3927 3928 static const struct snd_pci_quirk ad1984_cfg_tbl[] = { 3929 /* Lenovo Thinkpad T61/X61 */ 3930 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD), 3931 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), 3932 SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP), 3933 {} 3934 }; 3935 3936 static int patch_ad1984(struct hda_codec *codec) 3937 { 3938 struct ad198x_spec *spec; 3939 int board_config, err; 3940 3941 board_config = snd_hda_check_board_config(codec, AD1984_MODELS, 3942 ad1984_models, ad1984_cfg_tbl); 3943 if (board_config < 0) { 3944 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 3945 codec->chip_name); 3946 board_config = AD1984_AUTO; 3947 } 3948 3949 if (board_config == AD1984_AUTO) 3950 return ad1884_parse_auto_config(codec); 3951 3952 err = patch_ad1884_basic(codec); 3953 if (err < 0) 3954 return err; 3955 spec = codec->spec; 3956 3957 switch (board_config) { 3958 case AD1984_BASIC: 3959 /* additional digital mics */ 3960 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers; 3961 codec->patch_ops.build_pcms = ad1984_build_pcms; 3962 break; 3963 case AD1984_THINKPAD: 3964 if (codec->subsystem_id == 0x17aa20fb) { 3965 /* Thinpad X300 does not have the ability to do SPDIF, 3966 or attach to docking station to use SPDIF */ 3967 spec->multiout.dig_out_nid = 0; 3968 } else 3969 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; 3970 spec->input_mux = &ad1984_thinkpad_capture_source; 3971 spec->mixers[0] = ad1984_thinkpad_mixers; 3972 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs; 3973 spec->analog_beep = 1; 3974 break; 3975 case AD1984_DELL_DESKTOP: 3976 spec->multiout.dig_out_nid = 0; 3977 spec->input_mux = &ad1984_dell_desktop_capture_source; 3978 spec->mixers[0] = ad1984_dell_desktop_mixers; 3979 break; 3980 } 3981 return 0; 3982 } 3983 #else /* ENABLE_AD_STATIC_QUIRKS */ 3984 #define patch_ad1984 ad1884_parse_auto_config 3985 #endif /* ENABLE_AD_STATIC_QUIRKS */ 3986 3987 3988 /* 3989 * AD1883 / AD1884A / AD1984A / AD1984B 3990 * 3991 * port-B (0x14) - front mic-in 3992 * port-E (0x1c) - rear mic-in 3993 * port-F (0x16) - CD / ext out 3994 * port-C (0x15) - rear line-in 3995 * port-D (0x12) - rear line-out 3996 * port-A (0x11) - front hp-out 3997 * 3998 * AD1984A = AD1884A + digital-mic 3999 * AD1883 = equivalent with AD1984A 4000 * AD1984B = AD1984A + extra SPDIF-out 4001 * 4002 * FIXME: 4003 * We share the single DAC for both HP and line-outs (see AD1884/1984). 4004 */ 4005 4006 #ifdef ENABLE_AD_STATIC_QUIRKS 4007 static const hda_nid_t ad1884a_dac_nids[1] = { 4008 0x03, 4009 }; 4010 4011 #define ad1884a_adc_nids ad1884_adc_nids 4012 #define ad1884a_capsrc_nids ad1884_capsrc_nids 4013 4014 #define AD1884A_SPDIF_OUT 0x02 4015 4016 static const struct hda_input_mux ad1884a_capture_source = { 4017 .num_items = 5, 4018 .items = { 4019 { "Front Mic", 0x0 }, 4020 { "Mic", 0x4 }, 4021 { "Line", 0x1 }, 4022 { "CD", 0x2 }, 4023 { "Mix", 0x3 }, 4024 }, 4025 }; 4026 4027 static const struct snd_kcontrol_new ad1884a_base_mixers[] = { 4028 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4029 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), 4030 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 4031 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4032 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 4033 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 4034 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4035 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4036 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4037 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4038 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT), 4039 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), 4040 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 4041 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 4042 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), 4043 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), 4044 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 4045 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT), 4046 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 4047 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4048 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4049 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 4050 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 4051 { 4052 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4053 /* The multiple "Capture Source" controls confuse alsamixer 4054 * So call somewhat different.. 4055 */ 4056 /* .name = "Capture Source", */ 4057 .name = "Input Source", 4058 .count = 2, 4059 .info = ad198x_mux_enum_info, 4060 .get = ad198x_mux_enum_get, 4061 .put = ad198x_mux_enum_put, 4062 }, 4063 /* SPDIF controls */ 4064 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 4065 { 4066 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4067 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 4068 /* identical with ad1983 */ 4069 .info = ad1983_spdif_route_info, 4070 .get = ad1983_spdif_route_get, 4071 .put = ad1983_spdif_route_put, 4072 }, 4073 { } /* end */ 4074 }; 4075 4076 /* 4077 * initialization verbs 4078 */ 4079 static const struct hda_verb ad1884a_init_verbs[] = { 4080 /* DACs; unmute as default */ 4081 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4082 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4083 /* Port-A (HP) mixer - route only from analog mixer */ 4084 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4085 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4086 /* Port-A pin */ 4087 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4088 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4089 /* Port-D (Line-out) mixer - route only from analog mixer */ 4090 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4091 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4092 /* Port-D pin */ 4093 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4094 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4095 /* Mono-out mixer - route only from analog mixer */ 4096 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4097 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4098 /* Mono-out pin */ 4099 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4100 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4101 /* Port-B (front mic) pin */ 4102 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4103 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4104 /* Port-C (rear line-in) pin */ 4105 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4106 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4107 /* Port-E (rear mic) pin */ 4108 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4109 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4110 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */ 4111 /* Port-F (CD) pin */ 4112 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4113 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4114 /* Analog mixer; mute as default */ 4115 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4116 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4117 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4118 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4119 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */ 4120 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 4121 /* Analog Mix output amp */ 4122 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4123 /* capture sources */ 4124 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, 4125 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4126 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 4127 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4128 /* SPDIF output amp */ 4129 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 4130 { } /* end */ 4131 }; 4132 4133 #ifdef CONFIG_PM 4134 static const struct hda_amp_list ad1884a_loopbacks[] = { 4135 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 4136 { 0x20, HDA_INPUT, 1 }, /* Mic */ 4137 { 0x20, HDA_INPUT, 2 }, /* CD */ 4138 { 0x20, HDA_INPUT, 4 }, /* Docking */ 4139 { } /* end */ 4140 }; 4141 #endif 4142 4143 /* 4144 * Laptop model 4145 * 4146 * Port A: Headphone jack 4147 * Port B: MIC jack 4148 * Port C: Internal MIC 4149 * Port D: Dock Line Out (if enabled) 4150 * Port E: Dock Line In (if enabled) 4151 * Port F: Internal speakers 4152 */ 4153 4154 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol, 4155 struct snd_ctl_elem_value *ucontrol) 4156 { 4157 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 4158 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); 4159 int mute = (!ucontrol->value.integer.value[0] && 4160 !ucontrol->value.integer.value[1]); 4161 /* toggle GPIO1 according to the mute state */ 4162 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 4163 mute ? 0x02 : 0x0); 4164 return ret; 4165 } 4166 4167 static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = { 4168 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4169 { 4170 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4171 .name = "Master Playback Switch", 4172 .subdevice = HDA_SUBDEV_AMP_FLAG, 4173 .info = snd_hda_mixer_amp_switch_info, 4174 .get = snd_hda_mixer_amp_switch_get, 4175 .put = ad1884a_mobile_master_sw_put, 4176 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), 4177 }, 4178 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4179 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4180 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4181 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4182 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4183 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 4184 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 4185 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 4186 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 4187 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 4188 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 4189 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 4190 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4191 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4192 { } /* end */ 4193 }; 4194 4195 static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = { 4196 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4197 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ 4198 { 4199 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4200 .name = "Master Playback Switch", 4201 .subdevice = HDA_SUBDEV_AMP_FLAG, 4202 .info = snd_hda_mixer_amp_switch_info, 4203 .get = snd_hda_mixer_amp_switch_get, 4204 .put = ad1884a_mobile_master_sw_put, 4205 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), 4206 }, 4207 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4208 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4209 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), 4210 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT), 4211 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4212 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4213 { } /* end */ 4214 }; 4215 4216 /* mute internal speaker if HP is plugged */ 4217 static void ad1884a_hp_automute(struct hda_codec *codec) 4218 { 4219 unsigned int present; 4220 4221 present = snd_hda_jack_detect(codec, 0x11); 4222 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 4223 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4224 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, 4225 present ? 0x00 : 0x02); 4226 } 4227 4228 /* switch to external mic if plugged */ 4229 static void ad1884a_hp_automic(struct hda_codec *codec) 4230 { 4231 unsigned int present; 4232 4233 present = snd_hda_jack_detect(codec, 0x14); 4234 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 4235 present ? 0 : 1); 4236 } 4237 4238 #define AD1884A_HP_EVENT 0x37 4239 #define AD1884A_MIC_EVENT 0x36 4240 4241 /* unsolicited event for HP jack sensing */ 4242 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res) 4243 { 4244 switch (res >> 26) { 4245 case AD1884A_HP_EVENT: 4246 ad1884a_hp_automute(codec); 4247 break; 4248 case AD1884A_MIC_EVENT: 4249 ad1884a_hp_automic(codec); 4250 break; 4251 } 4252 } 4253 4254 /* initialize jack-sensing, too */ 4255 static int ad1884a_hp_init(struct hda_codec *codec) 4256 { 4257 ad198x_init(codec); 4258 ad1884a_hp_automute(codec); 4259 ad1884a_hp_automic(codec); 4260 return 0; 4261 } 4262 4263 /* mute internal speaker if HP or docking HP is plugged */ 4264 static void ad1884a_laptop_automute(struct hda_codec *codec) 4265 { 4266 unsigned int present; 4267 4268 present = snd_hda_jack_detect(codec, 0x11); 4269 if (!present) 4270 present = snd_hda_jack_detect(codec, 0x12); 4271 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 4272 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4273 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, 4274 present ? 0x00 : 0x02); 4275 } 4276 4277 /* switch to external mic if plugged */ 4278 static void ad1884a_laptop_automic(struct hda_codec *codec) 4279 { 4280 unsigned int idx; 4281 4282 if (snd_hda_jack_detect(codec, 0x14)) 4283 idx = 0; 4284 else if (snd_hda_jack_detect(codec, 0x1c)) 4285 idx = 4; 4286 else 4287 idx = 1; 4288 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx); 4289 } 4290 4291 /* unsolicited event for HP jack sensing */ 4292 static void ad1884a_laptop_unsol_event(struct hda_codec *codec, 4293 unsigned int res) 4294 { 4295 switch (res >> 26) { 4296 case AD1884A_HP_EVENT: 4297 ad1884a_laptop_automute(codec); 4298 break; 4299 case AD1884A_MIC_EVENT: 4300 ad1884a_laptop_automic(codec); 4301 break; 4302 } 4303 } 4304 4305 /* initialize jack-sensing, too */ 4306 static int ad1884a_laptop_init(struct hda_codec *codec) 4307 { 4308 ad198x_init(codec); 4309 ad1884a_laptop_automute(codec); 4310 ad1884a_laptop_automic(codec); 4311 return 0; 4312 } 4313 4314 /* additional verbs for laptop model */ 4315 static const struct hda_verb ad1884a_laptop_verbs[] = { 4316 /* Port-A (HP) pin - always unmuted */ 4317 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4318 /* Port-F (int speaker) mixer - route only from analog mixer */ 4319 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4320 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4321 /* Port-F (int speaker) pin */ 4322 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4323 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4324 /* required for compaq 6530s/6531s speaker output */ 4325 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4326 /* Port-C pin - internal mic-in */ 4327 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4328 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4329 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4330 /* Port-D (docking line-out) pin - default unmuted */ 4331 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4332 /* analog mix */ 4333 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4334 /* unsolicited event for pin-sense */ 4335 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4336 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4337 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4338 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4339 /* allow to touch GPIO1 (for mute control) */ 4340 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 4341 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 4342 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ 4343 { } /* end */ 4344 }; 4345 4346 static const struct hda_verb ad1884a_mobile_verbs[] = { 4347 /* DACs; unmute as default */ 4348 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4349 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4350 /* Port-A (HP) mixer - route only from analog mixer */ 4351 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4352 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4353 /* Port-A pin */ 4354 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4355 /* Port-A (HP) pin - always unmuted */ 4356 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4357 /* Port-B (mic jack) pin */ 4358 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4359 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4360 /* Port-C (int mic) pin */ 4361 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4362 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4363 /* Port-F (int speaker) mixer - route only from analog mixer */ 4364 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4365 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4366 /* Port-F pin */ 4367 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4368 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4369 /* Analog mixer; mute as default */ 4370 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4371 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4372 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4373 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4374 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4375 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 4376 /* Analog Mix output amp */ 4377 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4378 /* capture sources */ 4379 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ 4380 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4381 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 4382 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4383 /* unsolicited event for pin-sense */ 4384 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4385 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4386 /* allow to touch GPIO1 (for mute control) */ 4387 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 4388 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 4389 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ 4390 { } /* end */ 4391 }; 4392 4393 /* 4394 * Thinkpad X300 4395 * 0x11 - HP 4396 * 0x12 - speaker 4397 * 0x14 - mic-in 4398 * 0x17 - built-in mic 4399 */ 4400 4401 static const struct hda_verb ad1984a_thinkpad_verbs[] = { 4402 /* HP unmute */ 4403 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4404 /* analog mix */ 4405 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4406 /* turn on EAPD */ 4407 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4408 /* unsolicited event for pin-sense */ 4409 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4410 /* internal mic - dmic */ 4411 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4412 /* set magic COEFs for dmic */ 4413 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, 4414 {0x01, AC_VERB_SET_PROC_COEF, 0x08}, 4415 { } /* end */ 4416 }; 4417 4418 static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = { 4419 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4420 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), 4421 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4422 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4423 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4424 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4425 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 4426 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT), 4427 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4428 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4429 { 4430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4431 .name = "Capture Source", 4432 .info = ad198x_mux_enum_info, 4433 .get = ad198x_mux_enum_get, 4434 .put = ad198x_mux_enum_put, 4435 }, 4436 { } /* end */ 4437 }; 4438 4439 static const struct hda_input_mux ad1984a_thinkpad_capture_source = { 4440 .num_items = 3, 4441 .items = { 4442 { "Mic", 0x0 }, 4443 { "Internal Mic", 0x5 }, 4444 { "Mix", 0x3 }, 4445 }, 4446 }; 4447 4448 /* mute internal speaker if HP is plugged */ 4449 static void ad1984a_thinkpad_automute(struct hda_codec *codec) 4450 { 4451 unsigned int present; 4452 4453 present = snd_hda_jack_detect(codec, 0x11); 4454 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0, 4455 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4456 } 4457 4458 /* unsolicited event for HP jack sensing */ 4459 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec, 4460 unsigned int res) 4461 { 4462 if ((res >> 26) != AD1884A_HP_EVENT) 4463 return; 4464 ad1984a_thinkpad_automute(codec); 4465 } 4466 4467 /* initialize jack-sensing, too */ 4468 static int ad1984a_thinkpad_init(struct hda_codec *codec) 4469 { 4470 ad198x_init(codec); 4471 ad1984a_thinkpad_automute(codec); 4472 return 0; 4473 } 4474 4475 /* 4476 * Precision R5500 4477 * 0x12 - HP/line-out 4478 * 0x13 - speaker (mono) 4479 * 0x15 - mic-in 4480 */ 4481 4482 static const struct hda_verb ad1984a_precision_verbs[] = { 4483 /* Unmute main output path */ 4484 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4485 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */ 4486 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */ 4487 /* Analog mixer; mute as default */ 4488 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4489 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4490 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4491 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4492 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4493 /* Select mic as input */ 4494 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 4495 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */ 4496 /* Configure as mic */ 4497 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4498 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4499 /* HP unmute */ 4500 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4501 /* turn on EAPD */ 4502 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4503 /* unsolicited event for pin-sense */ 4504 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4505 { } /* end */ 4506 }; 4507 4508 static const struct snd_kcontrol_new ad1984a_precision_mixers[] = { 4509 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4510 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), 4511 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4512 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4513 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 4514 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 4515 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 4516 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4517 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT), 4518 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4519 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4520 { } /* end */ 4521 }; 4522 4523 4524 /* mute internal speaker if HP is plugged */ 4525 static void ad1984a_precision_automute(struct hda_codec *codec) 4526 { 4527 unsigned int present; 4528 4529 present = snd_hda_jack_detect(codec, 0x12); 4530 snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, 4531 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4532 } 4533 4534 4535 /* unsolicited event for HP jack sensing */ 4536 static void ad1984a_precision_unsol_event(struct hda_codec *codec, 4537 unsigned int res) 4538 { 4539 if ((res >> 26) != AD1884A_HP_EVENT) 4540 return; 4541 ad1984a_precision_automute(codec); 4542 } 4543 4544 /* initialize jack-sensing, too */ 4545 static int ad1984a_precision_init(struct hda_codec *codec) 4546 { 4547 ad198x_init(codec); 4548 ad1984a_precision_automute(codec); 4549 return 0; 4550 } 4551 4552 4553 /* 4554 * HP Touchsmart 4555 * port-A (0x11) - front hp-out 4556 * port-B (0x14) - unused 4557 * port-C (0x15) - unused 4558 * port-D (0x12) - rear line out 4559 * port-E (0x1c) - front mic-in 4560 * port-F (0x16) - Internal speakers 4561 * digital-mic (0x17) - Internal mic 4562 */ 4563 4564 static const struct hda_verb ad1984a_touchsmart_verbs[] = { 4565 /* DACs; unmute as default */ 4566 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4567 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4568 /* Port-A (HP) mixer - route only from analog mixer */ 4569 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4570 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4571 /* Port-A pin */ 4572 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4573 /* Port-A (HP) pin - always unmuted */ 4574 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4575 /* Port-E (int speaker) mixer - route only from analog mixer */ 4576 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03}, 4577 /* Port-E pin */ 4578 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4579 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4580 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4581 /* Port-F (int speaker) mixer - route only from analog mixer */ 4582 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4583 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4584 /* Port-F pin */ 4585 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4586 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4587 /* Analog mixer; mute as default */ 4588 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4589 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4590 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4591 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4592 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4593 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 4594 /* Analog Mix output amp */ 4595 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4596 /* capture sources */ 4597 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ 4598 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4599 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 4600 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4601 /* unsolicited event for pin-sense */ 4602 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4603 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4604 /* allow to touch GPIO1 (for mute control) */ 4605 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 4606 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 4607 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ 4608 /* internal mic - dmic */ 4609 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4610 /* set magic COEFs for dmic */ 4611 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, 4612 {0x01, AC_VERB_SET_PROC_COEF, 0x08}, 4613 { } /* end */ 4614 }; 4615 4616 static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { 4617 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4618 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ 4619 { 4620 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4621 .subdevice = HDA_SUBDEV_AMP_FLAG, 4622 .name = "Master Playback Switch", 4623 .info = snd_hda_mixer_amp_switch_info, 4624 .get = snd_hda_mixer_amp_switch_get, 4625 .put = ad1884a_mobile_master_sw_put, 4626 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), 4627 }, 4628 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4629 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4630 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4631 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4632 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 4633 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT), 4634 { } /* end */ 4635 }; 4636 4637 /* switch to external mic if plugged */ 4638 static void ad1984a_touchsmart_automic(struct hda_codec *codec) 4639 { 4640 if (snd_hda_jack_detect(codec, 0x1c)) 4641 snd_hda_codec_write(codec, 0x0c, 0, 4642 AC_VERB_SET_CONNECT_SEL, 0x4); 4643 else 4644 snd_hda_codec_write(codec, 0x0c, 0, 4645 AC_VERB_SET_CONNECT_SEL, 0x5); 4646 } 4647 4648 4649 /* unsolicited event for HP jack sensing */ 4650 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec, 4651 unsigned int res) 4652 { 4653 switch (res >> 26) { 4654 case AD1884A_HP_EVENT: 4655 ad1884a_hp_automute(codec); 4656 break; 4657 case AD1884A_MIC_EVENT: 4658 ad1984a_touchsmart_automic(codec); 4659 break; 4660 } 4661 } 4662 4663 /* initialize jack-sensing, too */ 4664 static int ad1984a_touchsmart_init(struct hda_codec *codec) 4665 { 4666 ad198x_init(codec); 4667 ad1884a_hp_automute(codec); 4668 ad1984a_touchsmart_automic(codec); 4669 return 0; 4670 } 4671 4672 4673 /* 4674 */ 4675 4676 enum { 4677 AD1884A_AUTO, 4678 AD1884A_DESKTOP, 4679 AD1884A_LAPTOP, 4680 AD1884A_MOBILE, 4681 AD1884A_THINKPAD, 4682 AD1984A_TOUCHSMART, 4683 AD1984A_PRECISION, 4684 AD1884A_MODELS 4685 }; 4686 4687 static const char * const ad1884a_models[AD1884A_MODELS] = { 4688 [AD1884A_AUTO] = "auto", 4689 [AD1884A_DESKTOP] = "desktop", 4690 [AD1884A_LAPTOP] = "laptop", 4691 [AD1884A_MOBILE] = "mobile", 4692 [AD1884A_THINKPAD] = "thinkpad", 4693 [AD1984A_TOUCHSMART] = "touchsmart", 4694 [AD1984A_PRECISION] = "precision", 4695 }; 4696 4697 static const struct snd_pci_quirk ad1884a_cfg_tbl[] = { 4698 SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION), 4699 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), 4700 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), 4701 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), 4702 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE), 4703 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP), 4704 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP), 4705 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), 4706 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), 4707 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), 4708 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART), 4709 {} 4710 }; 4711 4712 static int patch_ad1884a(struct hda_codec *codec) 4713 { 4714 struct ad198x_spec *spec; 4715 int err, board_config; 4716 4717 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS, 4718 ad1884a_models, 4719 ad1884a_cfg_tbl); 4720 if (board_config < 0) { 4721 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 4722 codec->chip_name); 4723 board_config = AD1884A_AUTO; 4724 } 4725 4726 if (board_config == AD1884A_AUTO) 4727 return ad1884_parse_auto_config(codec); 4728 4729 err = alloc_ad_spec(codec); 4730 if (err < 0) 4731 return err; 4732 spec = codec->spec; 4733 4734 err = snd_hda_attach_beep_device(codec, 0x10); 4735 if (err < 0) { 4736 ad198x_free(codec); 4737 return err; 4738 } 4739 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 4740 4741 spec->multiout.max_channels = 2; 4742 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids); 4743 spec->multiout.dac_nids = ad1884a_dac_nids; 4744 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT; 4745 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids); 4746 spec->adc_nids = ad1884a_adc_nids; 4747 spec->capsrc_nids = ad1884a_capsrc_nids; 4748 spec->input_mux = &ad1884a_capture_source; 4749 spec->num_mixers = 1; 4750 spec->mixers[0] = ad1884a_base_mixers; 4751 spec->num_init_verbs = 1; 4752 spec->init_verbs[0] = ad1884a_init_verbs; 4753 spec->spdif_route = 0; 4754 #ifdef CONFIG_PM 4755 spec->loopback.amplist = ad1884a_loopbacks; 4756 #endif 4757 codec->patch_ops = ad198x_patch_ops; 4758 4759 /* override some parameters */ 4760 switch (board_config) { 4761 case AD1884A_LAPTOP: 4762 spec->mixers[0] = ad1884a_laptop_mixers; 4763 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs; 4764 spec->multiout.dig_out_nid = 0; 4765 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event; 4766 codec->patch_ops.init = ad1884a_laptop_init; 4767 /* set the upper-limit for mixer amp to 0dB for avoiding the 4768 * possible damage by overloading 4769 */ 4770 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 4771 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 4772 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 4773 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 4774 (1 << AC_AMPCAP_MUTE_SHIFT)); 4775 break; 4776 case AD1884A_MOBILE: 4777 spec->mixers[0] = ad1884a_mobile_mixers; 4778 spec->init_verbs[0] = ad1884a_mobile_verbs; 4779 spec->multiout.dig_out_nid = 0; 4780 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; 4781 codec->patch_ops.init = ad1884a_hp_init; 4782 /* set the upper-limit for mixer amp to 0dB for avoiding the 4783 * possible damage by overloading 4784 */ 4785 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 4786 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 4787 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 4788 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 4789 (1 << AC_AMPCAP_MUTE_SHIFT)); 4790 break; 4791 case AD1884A_THINKPAD: 4792 spec->mixers[0] = ad1984a_thinkpad_mixers; 4793 spec->init_verbs[spec->num_init_verbs++] = 4794 ad1984a_thinkpad_verbs; 4795 spec->multiout.dig_out_nid = 0; 4796 spec->input_mux = &ad1984a_thinkpad_capture_source; 4797 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; 4798 codec->patch_ops.init = ad1984a_thinkpad_init; 4799 break; 4800 case AD1984A_PRECISION: 4801 spec->mixers[0] = ad1984a_precision_mixers; 4802 spec->init_verbs[spec->num_init_verbs++] = 4803 ad1984a_precision_verbs; 4804 spec->multiout.dig_out_nid = 0; 4805 codec->patch_ops.unsol_event = ad1984a_precision_unsol_event; 4806 codec->patch_ops.init = ad1984a_precision_init; 4807 break; 4808 case AD1984A_TOUCHSMART: 4809 spec->mixers[0] = ad1984a_touchsmart_mixers; 4810 spec->init_verbs[0] = ad1984a_touchsmart_verbs; 4811 spec->multiout.dig_out_nid = 0; 4812 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event; 4813 codec->patch_ops.init = ad1984a_touchsmart_init; 4814 /* set the upper-limit for mixer amp to 0dB for avoiding the 4815 * possible damage by overloading 4816 */ 4817 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 4818 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 4819 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 4820 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 4821 (1 << AC_AMPCAP_MUTE_SHIFT)); 4822 break; 4823 } 4824 4825 codec->no_trigger_sense = 1; 4826 codec->no_sticky_stream = 1; 4827 4828 return 0; 4829 } 4830 #else /* ENABLE_AD_STATIC_QUIRKS */ 4831 #define patch_ad1884a ad1884_parse_auto_config 4832 #endif /* ENABLE_AD_STATIC_QUIRKS */ 4833 4834 4835 /* 4836 * AD1882 / AD1882A 4837 * 4838 * port-A - front hp-out 4839 * port-B - front mic-in 4840 * port-C - rear line-in, shared surr-out (3stack) 4841 * port-D - rear line-out 4842 * port-E - rear mic-in, shared clfe-out (3stack) 4843 * port-F - rear surr-out (6stack) 4844 * port-G - rear clfe-out (6stack) 4845 */ 4846 4847 #ifdef ENABLE_AD_STATIC_QUIRKS 4848 static const hda_nid_t ad1882_dac_nids[3] = { 4849 0x04, 0x03, 0x05 4850 }; 4851 4852 static const hda_nid_t ad1882_adc_nids[2] = { 4853 0x08, 0x09, 4854 }; 4855 4856 static const hda_nid_t ad1882_capsrc_nids[2] = { 4857 0x0c, 0x0d, 4858 }; 4859 4860 #define AD1882_SPDIF_OUT 0x02 4861 4862 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */ 4863 static const struct hda_input_mux ad1882_capture_source = { 4864 .num_items = 5, 4865 .items = { 4866 { "Front Mic", 0x1 }, 4867 { "Mic", 0x4 }, 4868 { "Line", 0x2 }, 4869 { "CD", 0x3 }, 4870 { "Mix", 0x7 }, 4871 }, 4872 }; 4873 4874 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */ 4875 static const struct hda_input_mux ad1882a_capture_source = { 4876 .num_items = 5, 4877 .items = { 4878 { "Front Mic", 0x1 }, 4879 { "Mic", 0x4}, 4880 { "Line", 0x2 }, 4881 { "Digital Mic", 0x06 }, 4882 { "Mix", 0x7 }, 4883 }, 4884 }; 4885 4886 static const struct snd_kcontrol_new ad1882_base_mixers[] = { 4887 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 4888 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), 4889 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 4890 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 4891 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 4892 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4893 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 4894 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 4895 4896 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), 4897 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 4898 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT), 4899 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4900 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4901 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 4902 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 4903 { 4904 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4905 /* The multiple "Capture Source" controls confuse alsamixer 4906 * So call somewhat different.. 4907 */ 4908 /* .name = "Capture Source", */ 4909 .name = "Input Source", 4910 .count = 2, 4911 .info = ad198x_mux_enum_info, 4912 .get = ad198x_mux_enum_get, 4913 .put = ad198x_mux_enum_put, 4914 }, 4915 /* SPDIF controls */ 4916 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 4917 { 4918 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4919 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 4920 /* identical with ad1983 */ 4921 .info = ad1983_spdif_route_info, 4922 .get = ad1983_spdif_route_get, 4923 .put = ad1983_spdif_route_put, 4924 }, 4925 { } /* end */ 4926 }; 4927 4928 static const struct snd_kcontrol_new ad1882_loopback_mixers[] = { 4929 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4930 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4931 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 4932 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 4933 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT), 4934 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), 4935 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), 4936 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), 4937 { } /* end */ 4938 }; 4939 4940 static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = { 4941 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4942 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4943 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 4944 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 4945 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT), 4946 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), 4947 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), 4948 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), 4949 HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT), 4950 { } /* end */ 4951 }; 4952 4953 static const struct snd_kcontrol_new ad1882_3stack_mixers[] = { 4954 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), 4955 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT), 4956 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT), 4957 { 4958 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4959 .name = "Channel Mode", 4960 .info = ad198x_ch_mode_info, 4961 .get = ad198x_ch_mode_get, 4962 .put = ad198x_ch_mode_put, 4963 }, 4964 { } /* end */ 4965 }; 4966 4967 /* simple auto-mute control for AD1882 3-stack board */ 4968 #define AD1882_HP_EVENT 0x01 4969 4970 static void ad1882_3stack_automute(struct hda_codec *codec) 4971 { 4972 bool mute = snd_hda_jack_detect(codec, 0x11); 4973 snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 4974 mute ? 0 : PIN_OUT); 4975 } 4976 4977 static int ad1882_3stack_automute_init(struct hda_codec *codec) 4978 { 4979 ad198x_init(codec); 4980 ad1882_3stack_automute(codec); 4981 return 0; 4982 } 4983 4984 static void ad1882_3stack_unsol_event(struct hda_codec *codec, unsigned int res) 4985 { 4986 switch (res >> 26) { 4987 case AD1882_HP_EVENT: 4988 ad1882_3stack_automute(codec); 4989 break; 4990 } 4991 } 4992 4993 static const struct snd_kcontrol_new ad1882_6stack_mixers[] = { 4994 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT), 4995 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT), 4996 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT), 4997 { } /* end */ 4998 }; 4999 5000 static const struct hda_verb ad1882_ch2_init[] = { 5001 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 5002 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5003 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5004 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5005 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5006 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5007 { } /* end */ 5008 }; 5009 5010 static const struct hda_verb ad1882_ch4_init[] = { 5011 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5012 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5013 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5014 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5015 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5016 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5017 { } /* end */ 5018 }; 5019 5020 static const struct hda_verb ad1882_ch6_init[] = { 5021 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5022 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5023 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5024 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5025 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5026 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5027 { } /* end */ 5028 }; 5029 5030 static const struct hda_channel_mode ad1882_modes[3] = { 5031 { 2, ad1882_ch2_init }, 5032 { 4, ad1882_ch4_init }, 5033 { 6, ad1882_ch6_init }, 5034 }; 5035 5036 /* 5037 * initialization verbs 5038 */ 5039 static const struct hda_verb ad1882_init_verbs[] = { 5040 /* DACs; mute as default */ 5041 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5042 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5043 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 5044 /* Port-A (HP) mixer */ 5045 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5046 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5047 /* Port-A pin */ 5048 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5049 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5050 /* HP selector - select DAC2 */ 5051 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1}, 5052 /* Port-D (Line-out) mixer */ 5053 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5054 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5055 /* Port-D pin */ 5056 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5057 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5058 /* Mono-out mixer */ 5059 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 5060 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 5061 /* Mono-out pin */ 5062 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 5063 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5064 /* Port-B (front mic) pin */ 5065 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5066 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5067 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 5068 /* Port-C (line-in) pin */ 5069 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 5070 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5071 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 5072 /* Port-C mixer - mute as input */ 5073 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5074 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5075 /* Port-E (mic-in) pin */ 5076 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 5077 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5078 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 5079 /* Port-E mixer - mute as input */ 5080 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5081 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5082 /* Port-F (surround) */ 5083 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5084 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5085 /* Port-G (CLFE) */ 5086 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 5087 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 5088 /* Analog mixer; mute as default */ 5089 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */ 5090 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 5091 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 5092 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 5093 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 5094 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 5095 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 5096 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 5097 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 5098 /* Analog Mix output amp */ 5099 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 5100 /* SPDIF output selector */ 5101 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 5102 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 5103 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 5104 { } /* end */ 5105 }; 5106 5107 static const struct hda_verb ad1882_3stack_automute_verbs[] = { 5108 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1882_HP_EVENT}, 5109 { } /* end */ 5110 }; 5111 5112 #ifdef CONFIG_PM 5113 static const struct hda_amp_list ad1882_loopbacks[] = { 5114 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 5115 { 0x20, HDA_INPUT, 1 }, /* Mic */ 5116 { 0x20, HDA_INPUT, 4 }, /* Line */ 5117 { 0x20, HDA_INPUT, 6 }, /* CD */ 5118 { } /* end */ 5119 }; 5120 #endif 5121 5122 /* models */ 5123 enum { 5124 AD1882_AUTO, 5125 AD1882_3STACK, 5126 AD1882_6STACK, 5127 AD1882_3STACK_AUTOMUTE, 5128 AD1882_MODELS 5129 }; 5130 5131 static const char * const ad1882_models[AD1986A_MODELS] = { 5132 [AD1882_AUTO] = "auto", 5133 [AD1882_3STACK] = "3stack", 5134 [AD1882_6STACK] = "6stack", 5135 [AD1882_3STACK_AUTOMUTE] = "3stack-automute", 5136 }; 5137 #endif /* ENABLE_AD_STATIC_QUIRKS */ 5138 5139 static int ad1882_parse_auto_config(struct hda_codec *codec) 5140 { 5141 struct ad198x_spec *spec; 5142 int err; 5143 5144 err = alloc_ad_spec(codec); 5145 if (err < 0) 5146 return err; 5147 spec = codec->spec; 5148 5149 spec->gen.mixer_nid = 0x20; 5150 spec->gen.mixer_merge_nid = 0x21; 5151 spec->gen.beep_nid = 0x10; 5152 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 5153 err = ad198x_parse_auto_config(codec); 5154 if (err < 0) 5155 goto error; 5156 err = ad1988_add_spdif_mux_ctl(codec); 5157 if (err < 0) 5158 goto error; 5159 return 0; 5160 5161 error: 5162 snd_hda_gen_free(codec); 5163 return err; 5164 } 5165 5166 #ifdef ENABLE_AD_STATIC_QUIRKS 5167 static int patch_ad1882(struct hda_codec *codec) 5168 { 5169 struct ad198x_spec *spec; 5170 int err, board_config; 5171 5172 board_config = snd_hda_check_board_config(codec, AD1882_MODELS, 5173 ad1882_models, NULL); 5174 if (board_config < 0) { 5175 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 5176 codec->chip_name); 5177 board_config = AD1882_AUTO; 5178 } 5179 5180 if (board_config == AD1882_AUTO) 5181 return ad1882_parse_auto_config(codec); 5182 5183 err = alloc_ad_spec(codec); 5184 if (err < 0) 5185 return err; 5186 spec = codec->spec; 5187 5188 err = snd_hda_attach_beep_device(codec, 0x10); 5189 if (err < 0) { 5190 ad198x_free(codec); 5191 return err; 5192 } 5193 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 5194 5195 spec->multiout.max_channels = 6; 5196 spec->multiout.num_dacs = 3; 5197 spec->multiout.dac_nids = ad1882_dac_nids; 5198 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT; 5199 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids); 5200 spec->adc_nids = ad1882_adc_nids; 5201 spec->capsrc_nids = ad1882_capsrc_nids; 5202 if (codec->vendor_id == 0x11d41882) 5203 spec->input_mux = &ad1882_capture_source; 5204 else 5205 spec->input_mux = &ad1882a_capture_source; 5206 spec->num_mixers = 2; 5207 spec->mixers[0] = ad1882_base_mixers; 5208 if (codec->vendor_id == 0x11d41882) 5209 spec->mixers[1] = ad1882_loopback_mixers; 5210 else 5211 spec->mixers[1] = ad1882a_loopback_mixers; 5212 spec->num_init_verbs = 1; 5213 spec->init_verbs[0] = ad1882_init_verbs; 5214 spec->spdif_route = 0; 5215 #ifdef CONFIG_PM 5216 spec->loopback.amplist = ad1882_loopbacks; 5217 #endif 5218 spec->vmaster_nid = 0x04; 5219 5220 codec->patch_ops = ad198x_patch_ops; 5221 5222 /* override some parameters */ 5223 switch (board_config) { 5224 default: 5225 case AD1882_3STACK: 5226 case AD1882_3STACK_AUTOMUTE: 5227 spec->num_mixers = 3; 5228 spec->mixers[2] = ad1882_3stack_mixers; 5229 spec->channel_mode = ad1882_modes; 5230 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes); 5231 spec->need_dac_fix = 1; 5232 spec->multiout.max_channels = 2; 5233 spec->multiout.num_dacs = 1; 5234 if (board_config != AD1882_3STACK) { 5235 spec->init_verbs[spec->num_init_verbs++] = 5236 ad1882_3stack_automute_verbs; 5237 codec->patch_ops.unsol_event = ad1882_3stack_unsol_event; 5238 codec->patch_ops.init = ad1882_3stack_automute_init; 5239 } 5240 break; 5241 case AD1882_6STACK: 5242 spec->num_mixers = 3; 5243 spec->mixers[2] = ad1882_6stack_mixers; 5244 break; 5245 } 5246 5247 codec->no_trigger_sense = 1; 5248 codec->no_sticky_stream = 1; 5249 5250 return 0; 5251 } 5252 #else /* ENABLE_AD_STATIC_QUIRKS */ 5253 #define patch_ad1882 ad1882_parse_auto_config 5254 #endif /* ENABLE_AD_STATIC_QUIRKS */ 5255 5256 5257 /* 5258 * patch entries 5259 */ 5260 static const struct hda_codec_preset snd_hda_preset_analog[] = { 5261 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a }, 5262 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 }, 5263 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a }, 5264 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 }, 5265 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a }, 5266 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a }, 5267 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, 5268 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, 5269 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 }, 5270 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, 5271 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, 5272 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, 5273 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 }, 5274 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 }, 5275 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 }, 5276 {} /* terminator */ 5277 }; 5278 5279 MODULE_ALIAS("snd-hda-codec-id:11d4*"); 5280 5281 MODULE_LICENSE("GPL"); 5282 MODULE_DESCRIPTION("Analog Devices HD-audio codec"); 5283 5284 static struct hda_codec_preset_list analog_list = { 5285 .preset = snd_hda_preset_analog, 5286 .owner = THIS_MODULE, 5287 }; 5288 5289 static int __init patch_analog_init(void) 5290 { 5291 return snd_hda_add_codec_preset(&analog_list); 5292 } 5293 5294 static void __exit patch_analog_exit(void) 5295 { 5296 snd_hda_delete_codec_preset(&analog_list); 5297 } 5298 5299 module_init(patch_analog_init) 5300 module_exit(patch_analog_exit) 5301