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