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