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