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 info->name = "AD198x Digital"; 549 info->pcm_type = HDA_PCM_TYPE_SPDIF; 550 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; 551 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; 552 if (spec->dig_in_nid) { 553 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture; 554 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; 555 } 556 } 557 558 if (spec->alt_dac_nid && spec->stream_analog_alt_playback) { 559 codec->num_pcms++; 560 info = spec->pcm_rec + 2; 561 info->name = "AD198x Headphone"; 562 info->pcm_type = HDA_PCM_TYPE_AUDIO; 563 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = 564 *spec->stream_analog_alt_playback; 565 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 566 spec->alt_dac_nid[0]; 567 } 568 569 return 0; 570 } 571 572 static void ad198x_free_kctls(struct hda_codec *codec) 573 { 574 struct ad198x_spec *spec = codec->spec; 575 576 if (spec->kctls.list) { 577 struct snd_kcontrol_new *kctl = spec->kctls.list; 578 int i; 579 for (i = 0; i < spec->kctls.used; i++) 580 kfree(kctl[i].name); 581 } 582 snd_array_free(&spec->kctls); 583 } 584 585 static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front, 586 hda_nid_t hp) 587 { 588 struct ad198x_spec *spec = codec->spec; 589 if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD) 590 snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE, 591 !spec->inv_eapd ? 0x00 : 0x02); 592 if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD) 593 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE, 594 !spec->inv_eapd ? 0x00 : 0x02); 595 } 596 597 static void ad198x_power_eapd(struct hda_codec *codec) 598 { 599 /* We currently only handle front, HP */ 600 switch (codec->vendor_id) { 601 case 0x11d41882: 602 case 0x11d4882a: 603 case 0x11d41884: 604 case 0x11d41984: 605 case 0x11d41883: 606 case 0x11d4184a: 607 case 0x11d4194a: 608 case 0x11d4194b: 609 case 0x11d41988: 610 case 0x11d4198b: 611 case 0x11d4989a: 612 case 0x11d4989b: 613 ad198x_power_eapd_write(codec, 0x12, 0x11); 614 break; 615 case 0x11d41981: 616 case 0x11d41983: 617 ad198x_power_eapd_write(codec, 0x05, 0x06); 618 break; 619 case 0x11d41986: 620 ad198x_power_eapd_write(codec, 0x1b, 0x1a); 621 break; 622 } 623 } 624 625 static void ad198x_shutup(struct hda_codec *codec) 626 { 627 snd_hda_shutup_pins(codec); 628 ad198x_power_eapd(codec); 629 } 630 631 static void ad198x_free(struct hda_codec *codec) 632 { 633 struct ad198x_spec *spec = codec->spec; 634 635 if (!spec) 636 return; 637 638 ad198x_shutup(codec); 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 patch_ad1986a(struct hda_codec *codec) 1250 { 1251 struct ad198x_spec *spec; 1252 int err, board_config; 1253 1254 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1255 if (spec == NULL) 1256 return -ENOMEM; 1257 1258 codec->spec = spec; 1259 1260 err = snd_hda_attach_beep_device(codec, 0x19); 1261 if (err < 0) { 1262 ad198x_free(codec); 1263 return err; 1264 } 1265 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT); 1266 1267 spec->multiout.max_channels = 6; 1268 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); 1269 spec->multiout.dac_nids = ad1986a_dac_nids; 1270 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; 1271 spec->num_adc_nids = 1; 1272 spec->adc_nids = ad1986a_adc_nids; 1273 spec->capsrc_nids = ad1986a_capsrc_nids; 1274 spec->input_mux = &ad1986a_capture_source; 1275 spec->num_mixers = 1; 1276 spec->mixers[0] = ad1986a_mixers; 1277 spec->num_init_verbs = 1; 1278 spec->init_verbs[0] = ad1986a_init_verbs; 1279 #ifdef CONFIG_PM 1280 spec->loopback.amplist = ad1986a_loopbacks; 1281 #endif 1282 spec->vmaster_nid = 0x1b; 1283 spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */ 1284 1285 codec->patch_ops = ad198x_patch_ops; 1286 1287 /* override some parameters */ 1288 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS, 1289 ad1986a_models, 1290 ad1986a_cfg_tbl); 1291 switch (board_config) { 1292 case AD1986A_3STACK: 1293 spec->num_mixers = 2; 1294 spec->mixers[1] = ad1986a_3st_mixers; 1295 spec->num_init_verbs = 2; 1296 spec->init_verbs[1] = ad1986a_ch2_init; 1297 spec->channel_mode = ad1986a_modes; 1298 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); 1299 spec->need_dac_fix = 1; 1300 spec->multiout.max_channels = 2; 1301 spec->multiout.num_dacs = 1; 1302 break; 1303 case AD1986A_LAPTOP: 1304 spec->mixers[0] = ad1986a_laptop_mixers; 1305 spec->multiout.max_channels = 2; 1306 spec->multiout.num_dacs = 1; 1307 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1308 break; 1309 case AD1986A_LAPTOP_EAPD: 1310 spec->num_mixers = 3; 1311 spec->mixers[0] = ad1986a_laptop_master_mixers; 1312 spec->mixers[1] = ad1986a_laptop_eapd_mixers; 1313 spec->mixers[2] = ad1986a_laptop_intmic_mixers; 1314 spec->num_init_verbs = 2; 1315 spec->init_verbs[1] = ad1986a_eapd_init_verbs; 1316 spec->multiout.max_channels = 2; 1317 spec->multiout.num_dacs = 1; 1318 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1319 if (!is_jack_available(codec, 0x25)) 1320 spec->multiout.dig_out_nid = 0; 1321 spec->input_mux = &ad1986a_laptop_eapd_capture_source; 1322 break; 1323 case AD1986A_SAMSUNG: 1324 spec->num_mixers = 2; 1325 spec->mixers[0] = ad1986a_laptop_master_mixers; 1326 spec->mixers[1] = ad1986a_laptop_eapd_mixers; 1327 spec->num_init_verbs = 3; 1328 spec->init_verbs[1] = ad1986a_eapd_init_verbs; 1329 spec->init_verbs[2] = ad1986a_automic_verbs; 1330 spec->multiout.max_channels = 2; 1331 spec->multiout.num_dacs = 1; 1332 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1333 if (!is_jack_available(codec, 0x25)) 1334 spec->multiout.dig_out_nid = 0; 1335 spec->input_mux = &ad1986a_automic_capture_source; 1336 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event; 1337 codec->patch_ops.init = ad1986a_automic_init; 1338 break; 1339 case AD1986A_SAMSUNG_P50: 1340 spec->num_mixers = 2; 1341 spec->mixers[0] = ad1986a_automute_master_mixers; 1342 spec->mixers[1] = ad1986a_laptop_eapd_mixers; 1343 spec->num_init_verbs = 4; 1344 spec->init_verbs[1] = ad1986a_eapd_init_verbs; 1345 spec->init_verbs[2] = ad1986a_automic_verbs; 1346 spec->init_verbs[3] = ad1986a_hp_init_verbs; 1347 spec->multiout.max_channels = 2; 1348 spec->multiout.num_dacs = 1; 1349 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1350 if (!is_jack_available(codec, 0x25)) 1351 spec->multiout.dig_out_nid = 0; 1352 spec->input_mux = &ad1986a_automic_capture_source; 1353 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event; 1354 codec->patch_ops.init = ad1986a_samsung_p50_init; 1355 break; 1356 case AD1986A_LAPTOP_AUTOMUTE: 1357 spec->num_mixers = 3; 1358 spec->mixers[0] = ad1986a_automute_master_mixers; 1359 spec->mixers[1] = ad1986a_laptop_eapd_mixers; 1360 spec->mixers[2] = ad1986a_laptop_intmic_mixers; 1361 spec->num_init_verbs = 3; 1362 spec->init_verbs[1] = ad1986a_eapd_init_verbs; 1363 spec->init_verbs[2] = ad1986a_hp_init_verbs; 1364 spec->multiout.max_channels = 2; 1365 spec->multiout.num_dacs = 1; 1366 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1367 if (!is_jack_available(codec, 0x25)) 1368 spec->multiout.dig_out_nid = 0; 1369 spec->input_mux = &ad1986a_laptop_eapd_capture_source; 1370 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event; 1371 codec->patch_ops.init = ad1986a_hp_init; 1372 /* Lenovo N100 seems to report the reversed bit 1373 * for HP jack-sensing 1374 */ 1375 spec->inv_jack_detect = 1; 1376 break; 1377 case AD1986A_ULTRA: 1378 spec->mixers[0] = ad1986a_laptop_eapd_mixers; 1379 spec->num_init_verbs = 2; 1380 spec->init_verbs[1] = ad1986a_ultra_init; 1381 spec->multiout.max_channels = 2; 1382 spec->multiout.num_dacs = 1; 1383 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 1384 spec->multiout.dig_out_nid = 0; 1385 break; 1386 } 1387 1388 /* AD1986A has a hardware problem that it can't share a stream 1389 * with multiple output pins. The copy of front to surrounds 1390 * causes noisy or silent outputs at a certain timing, e.g. 1391 * changing the volume. 1392 * So, let's disable the shared stream. 1393 */ 1394 spec->multiout.no_share_stream = 1; 1395 1396 codec->no_trigger_sense = 1; 1397 codec->no_sticky_stream = 1; 1398 1399 return 0; 1400 } 1401 1402 /* 1403 * AD1983 specific 1404 */ 1405 1406 #define AD1983_SPDIF_OUT 0x02 1407 #define AD1983_DAC 0x03 1408 #define AD1983_ADC 0x04 1409 1410 static const hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; 1411 static const hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC }; 1412 static const hda_nid_t ad1983_capsrc_nids[1] = { 0x15 }; 1413 1414 static const struct hda_input_mux ad1983_capture_source = { 1415 .num_items = 4, 1416 .items = { 1417 { "Mic", 0x0 }, 1418 { "Line", 0x1 }, 1419 { "Mix", 0x2 }, 1420 { "Mix Mono", 0x3 }, 1421 }, 1422 }; 1423 1424 /* 1425 * SPDIF playback route 1426 */ 1427 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1428 { 1429 static const char * const texts[] = { "PCM", "ADC" }; 1430 1431 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1432 uinfo->count = 1; 1433 uinfo->value.enumerated.items = 2; 1434 if (uinfo->value.enumerated.item > 1) 1435 uinfo->value.enumerated.item = 1; 1436 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 1437 return 0; 1438 } 1439 1440 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1441 { 1442 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1443 struct ad198x_spec *spec = codec->spec; 1444 1445 ucontrol->value.enumerated.item[0] = spec->spdif_route; 1446 return 0; 1447 } 1448 1449 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1450 { 1451 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1452 struct ad198x_spec *spec = codec->spec; 1453 1454 if (ucontrol->value.enumerated.item[0] > 1) 1455 return -EINVAL; 1456 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { 1457 spec->spdif_route = ucontrol->value.enumerated.item[0]; 1458 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0, 1459 AC_VERB_SET_CONNECT_SEL, 1460 spec->spdif_route); 1461 return 1; 1462 } 1463 return 0; 1464 } 1465 1466 static const struct snd_kcontrol_new ad1983_mixers[] = { 1467 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), 1468 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), 1469 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), 1470 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), 1471 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), 1472 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), 1473 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1474 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1475 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1476 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1477 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), 1478 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), 1479 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT), 1480 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 1481 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 1482 { 1483 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1484 .name = "Capture Source", 1485 .info = ad198x_mux_enum_info, 1486 .get = ad198x_mux_enum_get, 1487 .put = ad198x_mux_enum_put, 1488 }, 1489 { 1490 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1491 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 1492 .info = ad1983_spdif_route_info, 1493 .get = ad1983_spdif_route_get, 1494 .put = ad1983_spdif_route_put, 1495 }, 1496 { } /* end */ 1497 }; 1498 1499 static const struct hda_verb ad1983_init_verbs[] = { 1500 /* Front, HP, Mono; mute as default */ 1501 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1502 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1503 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1504 /* Beep, PCM, Mic, Line-In: mute */ 1505 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1506 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1507 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1508 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1509 /* Front, HP selectors; from Mix */ 1510 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, 1511 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, 1512 /* Mono selector; from Mix */ 1513 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, 1514 /* Mic selector; Mic */ 1515 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, 1516 /* Line-in selector: Line-in */ 1517 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 1518 /* Mic boost: 0dB */ 1519 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1520 /* Record selector: mic */ 1521 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, 1522 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1523 /* SPDIF route: PCM */ 1524 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, 1525 /* Front Pin */ 1526 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1527 /* HP Pin */ 1528 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 1529 /* Mono Pin */ 1530 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1531 /* Mic Pin */ 1532 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1533 /* Line Pin */ 1534 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1535 { } /* end */ 1536 }; 1537 1538 #ifdef CONFIG_PM 1539 static const struct hda_amp_list ad1983_loopbacks[] = { 1540 { 0x12, HDA_OUTPUT, 0 }, /* Mic */ 1541 { 0x13, HDA_OUTPUT, 0 }, /* Line */ 1542 { } /* end */ 1543 }; 1544 #endif 1545 1546 static int patch_ad1983(struct hda_codec *codec) 1547 { 1548 struct ad198x_spec *spec; 1549 int err; 1550 1551 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1552 if (spec == NULL) 1553 return -ENOMEM; 1554 1555 codec->spec = spec; 1556 1557 err = snd_hda_attach_beep_device(codec, 0x10); 1558 if (err < 0) { 1559 ad198x_free(codec); 1560 return err; 1561 } 1562 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 1563 1564 spec->multiout.max_channels = 2; 1565 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); 1566 spec->multiout.dac_nids = ad1983_dac_nids; 1567 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; 1568 spec->num_adc_nids = 1; 1569 spec->adc_nids = ad1983_adc_nids; 1570 spec->capsrc_nids = ad1983_capsrc_nids; 1571 spec->input_mux = &ad1983_capture_source; 1572 spec->num_mixers = 1; 1573 spec->mixers[0] = ad1983_mixers; 1574 spec->num_init_verbs = 1; 1575 spec->init_verbs[0] = ad1983_init_verbs; 1576 spec->spdif_route = 0; 1577 #ifdef CONFIG_PM 1578 spec->loopback.amplist = ad1983_loopbacks; 1579 #endif 1580 spec->vmaster_nid = 0x05; 1581 1582 codec->patch_ops = ad198x_patch_ops; 1583 1584 codec->no_trigger_sense = 1; 1585 codec->no_sticky_stream = 1; 1586 1587 return 0; 1588 } 1589 1590 1591 /* 1592 * AD1981 HD specific 1593 */ 1594 1595 #define AD1981_SPDIF_OUT 0x02 1596 #define AD1981_DAC 0x03 1597 #define AD1981_ADC 0x04 1598 1599 static const hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; 1600 static const hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC }; 1601 static const hda_nid_t ad1981_capsrc_nids[1] = { 0x15 }; 1602 1603 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ 1604 static const struct hda_input_mux ad1981_capture_source = { 1605 .num_items = 7, 1606 .items = { 1607 { "Front Mic", 0x0 }, 1608 { "Line", 0x1 }, 1609 { "Mix", 0x2 }, 1610 { "Mix Mono", 0x3 }, 1611 { "CD", 0x4 }, 1612 { "Mic", 0x6 }, 1613 { "Aux", 0x7 }, 1614 }, 1615 }; 1616 1617 static const struct snd_kcontrol_new ad1981_mixers[] = { 1618 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), 1619 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), 1620 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), 1621 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), 1622 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), 1623 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), 1624 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1625 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1626 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1627 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1628 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), 1629 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), 1630 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 1631 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 1632 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), 1633 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), 1634 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 1635 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), 1636 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT), 1637 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT), 1638 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 1639 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 1640 { 1641 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1642 .name = "Capture Source", 1643 .info = ad198x_mux_enum_info, 1644 .get = ad198x_mux_enum_get, 1645 .put = ad198x_mux_enum_put, 1646 }, 1647 /* identical with AD1983 */ 1648 { 1649 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1650 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 1651 .info = ad1983_spdif_route_info, 1652 .get = ad1983_spdif_route_get, 1653 .put = ad1983_spdif_route_put, 1654 }, 1655 { } /* end */ 1656 }; 1657 1658 static const struct hda_verb ad1981_init_verbs[] = { 1659 /* Front, HP, Mono; mute as default */ 1660 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1661 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1662 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1663 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */ 1664 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1665 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1666 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1667 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1668 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1669 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1670 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1671 /* Front, HP selectors; from Mix */ 1672 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, 1673 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, 1674 /* Mono selector; from Mix */ 1675 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, 1676 /* Mic Mixer; select Front Mic */ 1677 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1678 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1679 /* Mic boost: 0dB */ 1680 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1681 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1682 /* Record selector: Front mic */ 1683 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, 1684 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1685 /* SPDIF route: PCM */ 1686 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, 1687 /* Front Pin */ 1688 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1689 /* HP Pin */ 1690 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 1691 /* Mono Pin */ 1692 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1693 /* Front & Rear Mic Pins */ 1694 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1695 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1696 /* Line Pin */ 1697 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1698 /* Digital Beep */ 1699 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, 1700 /* Line-Out as Input: disabled */ 1701 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1702 { } /* end */ 1703 }; 1704 1705 #ifdef CONFIG_PM 1706 static const struct hda_amp_list ad1981_loopbacks[] = { 1707 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */ 1708 { 0x13, HDA_OUTPUT, 0 }, /* Line */ 1709 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */ 1710 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */ 1711 { 0x1d, HDA_OUTPUT, 0 }, /* CD */ 1712 { } /* end */ 1713 }; 1714 #endif 1715 1716 /* 1717 * Patch for HP nx6320 1718 * 1719 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal 1720 * speaker output enabled _and_ mute-LED off. 1721 */ 1722 1723 #define AD1981_HP_EVENT 0x37 1724 #define AD1981_MIC_EVENT 0x38 1725 1726 static const struct hda_verb ad1981_hp_init_verbs[] = { 1727 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */ 1728 /* pin sensing on HP and Mic jacks */ 1729 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT}, 1730 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT}, 1731 {} 1732 }; 1733 1734 /* turn on/off EAPD (+ mute HP) as a master switch */ 1735 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol, 1736 struct snd_ctl_elem_value *ucontrol) 1737 { 1738 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1739 struct ad198x_spec *spec = codec->spec; 1740 1741 if (! ad198x_eapd_put(kcontrol, ucontrol)) 1742 return 0; 1743 /* change speaker pin appropriately */ 1744 snd_hda_set_pin_ctl(codec, 0x05, spec->cur_eapd ? PIN_OUT : 0); 1745 /* toggle HP mute appropriately */ 1746 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0, 1747 HDA_AMP_MUTE, 1748 spec->cur_eapd ? 0 : HDA_AMP_MUTE); 1749 return 1; 1750 } 1751 1752 /* bind volumes of both NID 0x05 and 0x06 */ 1753 static const struct hda_bind_ctls ad1981_hp_bind_master_vol = { 1754 .ops = &snd_hda_bind_vol, 1755 .values = { 1756 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), 1757 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT), 1758 0 1759 }, 1760 }; 1761 1762 /* mute internal speaker if HP is plugged */ 1763 static void ad1981_hp_automute(struct hda_codec *codec) 1764 { 1765 unsigned int present; 1766 1767 present = snd_hda_jack_detect(codec, 0x06); 1768 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0, 1769 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 1770 } 1771 1772 /* toggle input of built-in and mic jack appropriately */ 1773 static void ad1981_hp_automic(struct hda_codec *codec) 1774 { 1775 static const struct hda_verb mic_jack_on[] = { 1776 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1777 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1778 {} 1779 }; 1780 static const struct hda_verb mic_jack_off[] = { 1781 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1782 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1783 {} 1784 }; 1785 unsigned int present; 1786 1787 present = snd_hda_jack_detect(codec, 0x08); 1788 if (present) 1789 snd_hda_sequence_write(codec, mic_jack_on); 1790 else 1791 snd_hda_sequence_write(codec, mic_jack_off); 1792 } 1793 1794 /* unsolicited event for HP jack sensing */ 1795 static void ad1981_hp_unsol_event(struct hda_codec *codec, 1796 unsigned int res) 1797 { 1798 res >>= 26; 1799 switch (res) { 1800 case AD1981_HP_EVENT: 1801 ad1981_hp_automute(codec); 1802 break; 1803 case AD1981_MIC_EVENT: 1804 ad1981_hp_automic(codec); 1805 break; 1806 } 1807 } 1808 1809 static const struct hda_input_mux ad1981_hp_capture_source = { 1810 .num_items = 3, 1811 .items = { 1812 { "Mic", 0x0 }, 1813 { "Dock Mic", 0x1 }, 1814 { "Mix", 0x2 }, 1815 }, 1816 }; 1817 1818 static const struct snd_kcontrol_new ad1981_hp_mixers[] = { 1819 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol), 1820 { 1821 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1822 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05, 1823 .name = "Master Playback Switch", 1824 .info = ad198x_eapd_info, 1825 .get = ad198x_eapd_get, 1826 .put = ad1981_hp_master_sw_put, 1827 .private_value = 0x05, 1828 }, 1829 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1830 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1831 #if 0 1832 /* FIXME: analog mic/line loopback doesn't work with my tests... 1833 * (although recording is OK) 1834 */ 1835 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1836 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1837 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), 1838 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), 1839 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), 1840 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), 1841 /* FIXME: does this laptop have analog CD connection? */ 1842 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 1843 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), 1844 #endif 1845 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT), 1846 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT), 1847 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 1848 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 1849 { 1850 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1851 .name = "Capture Source", 1852 .info = ad198x_mux_enum_info, 1853 .get = ad198x_mux_enum_get, 1854 .put = ad198x_mux_enum_put, 1855 }, 1856 { } /* end */ 1857 }; 1858 1859 /* initialize jack-sensing, too */ 1860 static int ad1981_hp_init(struct hda_codec *codec) 1861 { 1862 ad198x_init(codec); 1863 ad1981_hp_automute(codec); 1864 ad1981_hp_automic(codec); 1865 return 0; 1866 } 1867 1868 /* configuration for Toshiba Laptops */ 1869 static const struct hda_verb ad1981_toshiba_init_verbs[] = { 1870 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */ 1871 /* pin sensing on HP and Mic jacks */ 1872 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT}, 1873 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT}, 1874 {} 1875 }; 1876 1877 static const struct snd_kcontrol_new ad1981_toshiba_mixers[] = { 1878 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT), 1879 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT), 1880 { } 1881 }; 1882 1883 /* configuration for Lenovo Thinkpad T60 */ 1884 static const struct snd_kcontrol_new ad1981_thinkpad_mixers[] = { 1885 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT), 1886 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT), 1887 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1888 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1889 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1890 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1891 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 1892 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), 1893 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT), 1894 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 1895 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 1896 { 1897 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1898 .name = "Capture Source", 1899 .info = ad198x_mux_enum_info, 1900 .get = ad198x_mux_enum_get, 1901 .put = ad198x_mux_enum_put, 1902 }, 1903 /* identical with AD1983 */ 1904 { 1905 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1906 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 1907 .info = ad1983_spdif_route_info, 1908 .get = ad1983_spdif_route_get, 1909 .put = ad1983_spdif_route_put, 1910 }, 1911 { } /* end */ 1912 }; 1913 1914 static const struct hda_input_mux ad1981_thinkpad_capture_source = { 1915 .num_items = 3, 1916 .items = { 1917 { "Mic", 0x0 }, 1918 { "Mix", 0x2 }, 1919 { "CD", 0x4 }, 1920 }, 1921 }; 1922 1923 /* models */ 1924 enum { 1925 AD1981_BASIC, 1926 AD1981_HP, 1927 AD1981_THINKPAD, 1928 AD1981_TOSHIBA, 1929 AD1981_MODELS 1930 }; 1931 1932 static const char * const ad1981_models[AD1981_MODELS] = { 1933 [AD1981_HP] = "hp", 1934 [AD1981_THINKPAD] = "thinkpad", 1935 [AD1981_BASIC] = "basic", 1936 [AD1981_TOSHIBA] = "toshiba" 1937 }; 1938 1939 static const struct snd_pci_quirk ad1981_cfg_tbl[] = { 1940 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD), 1941 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD), 1942 /* All HP models */ 1943 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP), 1944 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA), 1945 /* Lenovo Thinkpad T60/X60/Z6xx */ 1946 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD), 1947 /* HP nx6320 (reversed SSID, H/W bug) */ 1948 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP), 1949 {} 1950 }; 1951 1952 static int patch_ad1981(struct hda_codec *codec) 1953 { 1954 struct ad198x_spec *spec; 1955 int err, board_config; 1956 1957 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1958 if (spec == NULL) 1959 return -ENOMEM; 1960 1961 codec->spec = spec; 1962 1963 err = snd_hda_attach_beep_device(codec, 0x10); 1964 if (err < 0) { 1965 ad198x_free(codec); 1966 return err; 1967 } 1968 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); 1969 1970 spec->multiout.max_channels = 2; 1971 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); 1972 spec->multiout.dac_nids = ad1981_dac_nids; 1973 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; 1974 spec->num_adc_nids = 1; 1975 spec->adc_nids = ad1981_adc_nids; 1976 spec->capsrc_nids = ad1981_capsrc_nids; 1977 spec->input_mux = &ad1981_capture_source; 1978 spec->num_mixers = 1; 1979 spec->mixers[0] = ad1981_mixers; 1980 spec->num_init_verbs = 1; 1981 spec->init_verbs[0] = ad1981_init_verbs; 1982 spec->spdif_route = 0; 1983 #ifdef CONFIG_PM 1984 spec->loopback.amplist = ad1981_loopbacks; 1985 #endif 1986 spec->vmaster_nid = 0x05; 1987 1988 codec->patch_ops = ad198x_patch_ops; 1989 1990 /* override some parameters */ 1991 board_config = snd_hda_check_board_config(codec, AD1981_MODELS, 1992 ad1981_models, 1993 ad1981_cfg_tbl); 1994 switch (board_config) { 1995 case AD1981_HP: 1996 spec->mixers[0] = ad1981_hp_mixers; 1997 spec->num_init_verbs = 2; 1998 spec->init_verbs[1] = ad1981_hp_init_verbs; 1999 if (!is_jack_available(codec, 0x0a)) 2000 spec->multiout.dig_out_nid = 0; 2001 spec->input_mux = &ad1981_hp_capture_source; 2002 2003 codec->patch_ops.init = ad1981_hp_init; 2004 codec->patch_ops.unsol_event = ad1981_hp_unsol_event; 2005 /* set the upper-limit for mixer amp to 0dB for avoiding the 2006 * possible damage by overloading 2007 */ 2008 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, 2009 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 2010 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 2011 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 2012 (1 << AC_AMPCAP_MUTE_SHIFT)); 2013 break; 2014 case AD1981_THINKPAD: 2015 spec->mixers[0] = ad1981_thinkpad_mixers; 2016 spec->input_mux = &ad1981_thinkpad_capture_source; 2017 /* set the upper-limit for mixer amp to 0dB for avoiding the 2018 * possible damage by overloading 2019 */ 2020 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, 2021 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 2022 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 2023 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 2024 (1 << AC_AMPCAP_MUTE_SHIFT)); 2025 break; 2026 case AD1981_TOSHIBA: 2027 spec->mixers[0] = ad1981_hp_mixers; 2028 spec->mixers[1] = ad1981_toshiba_mixers; 2029 spec->num_init_verbs = 2; 2030 spec->init_verbs[1] = ad1981_toshiba_init_verbs; 2031 spec->multiout.dig_out_nid = 0; 2032 spec->input_mux = &ad1981_hp_capture_source; 2033 codec->patch_ops.init = ad1981_hp_init; 2034 codec->patch_ops.unsol_event = ad1981_hp_unsol_event; 2035 break; 2036 } 2037 2038 codec->no_trigger_sense = 1; 2039 codec->no_sticky_stream = 1; 2040 2041 return 0; 2042 } 2043 2044 2045 /* 2046 * AD1988 2047 * 2048 * Output pins and routes 2049 * 2050 * Pin Mix Sel DAC (*) 2051 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06 2052 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06 2053 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a 2054 * port-D 0x12 (mute/hp) <- 0x29 <- 04 2055 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a 2056 * port-F 0x16 (mute) <- 0x2a <- 06 2057 * port-G 0x24 (mute) <- 0x27 <- 05 2058 * port-H 0x25 (mute) <- 0x28 <- 0a 2059 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06 2060 * 2061 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah 2062 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug. 2063 * 2064 * Input pins and routes 2065 * 2066 * pin boost mix input # / adc input # 2067 * port-A 0x11 -> 0x38 -> mix 2, ADC 0 2068 * port-B 0x14 -> 0x39 -> mix 0, ADC 1 2069 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2 2070 * port-D 0x12 -> 0x3d -> mix 3, ADC 8 2071 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4 2072 * port-F 0x16 -> 0x3b -> mix 5, ADC 3 2073 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6 2074 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7 2075 * 2076 * 2077 * DAC assignment 2078 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03 2079 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03 2080 * 2081 * Inputs of Analog Mix (0x20) 2082 * 0:Port-B (front mic) 2083 * 1:Port-C/G/H (line-in) 2084 * 2:Port-A 2085 * 3:Port-D (line-in/2) 2086 * 4:Port-E/G/H (mic-in) 2087 * 5:Port-F (mic2-in) 2088 * 6:CD 2089 * 7:Beep 2090 * 2091 * ADC selection 2092 * 0:Port-A 2093 * 1:Port-B (front mic-in) 2094 * 2:Port-C (line-in) 2095 * 3:Port-F (mic2-in) 2096 * 4:Port-E (mic-in) 2097 * 5:CD 2098 * 6:Port-G 2099 * 7:Port-H 2100 * 8:Port-D (line-in/2) 2101 * 9:Mix 2102 * 2103 * Proposed pin assignments by the datasheet 2104 * 2105 * 6-stack 2106 * Port-A front headphone 2107 * B front mic-in 2108 * C rear line-in 2109 * D rear front-out 2110 * E rear mic-in 2111 * F rear surround 2112 * G rear CLFE 2113 * H rear side 2114 * 2115 * 3-stack 2116 * Port-A front headphone 2117 * B front mic 2118 * C rear line-in/surround 2119 * D rear front-out 2120 * E rear mic-in/CLFE 2121 * 2122 * laptop 2123 * Port-A headphone 2124 * B mic-in 2125 * C docking station 2126 * D internal speaker (with EAPD) 2127 * E/F quad mic array 2128 */ 2129 2130 2131 /* models */ 2132 enum { 2133 AD1988_6STACK, 2134 AD1988_6STACK_DIG, 2135 AD1988_3STACK, 2136 AD1988_3STACK_DIG, 2137 AD1988_LAPTOP, 2138 AD1988_LAPTOP_DIG, 2139 AD1988_AUTO, 2140 AD1988_MODEL_LAST, 2141 }; 2142 2143 /* reivision id to check workarounds */ 2144 #define AD1988A_REV2 0x100200 2145 2146 #define is_rev2(codec) \ 2147 ((codec)->vendor_id == 0x11d41988 && \ 2148 (codec)->revision_id == AD1988A_REV2) 2149 2150 /* 2151 * mixers 2152 */ 2153 2154 static const hda_nid_t ad1988_6stack_dac_nids[4] = { 2155 0x04, 0x06, 0x05, 0x0a 2156 }; 2157 2158 static const hda_nid_t ad1988_3stack_dac_nids[3] = { 2159 0x04, 0x05, 0x0a 2160 }; 2161 2162 /* for AD1988A revision-2, DAC2-4 are swapped */ 2163 static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = { 2164 0x04, 0x05, 0x0a, 0x06 2165 }; 2166 2167 static const hda_nid_t ad1988_alt_dac_nid[1] = { 2168 0x03 2169 }; 2170 2171 static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = { 2172 0x04, 0x0a, 0x06 2173 }; 2174 2175 static const hda_nid_t ad1988_adc_nids[3] = { 2176 0x08, 0x09, 0x0f 2177 }; 2178 2179 static const hda_nid_t ad1988_capsrc_nids[3] = { 2180 0x0c, 0x0d, 0x0e 2181 }; 2182 2183 #define AD1988_SPDIF_OUT 0x02 2184 #define AD1988_SPDIF_OUT_HDMI 0x0b 2185 #define AD1988_SPDIF_IN 0x07 2186 2187 static const hda_nid_t ad1989b_slave_dig_outs[] = { 2188 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0 2189 }; 2190 2191 static const struct hda_input_mux ad1988_6stack_capture_source = { 2192 .num_items = 5, 2193 .items = { 2194 { "Front Mic", 0x1 }, /* port-B */ 2195 { "Line", 0x2 }, /* port-C */ 2196 { "Mic", 0x4 }, /* port-E */ 2197 { "CD", 0x5 }, 2198 { "Mix", 0x9 }, 2199 }, 2200 }; 2201 2202 static const struct hda_input_mux ad1988_laptop_capture_source = { 2203 .num_items = 3, 2204 .items = { 2205 { "Mic/Line", 0x1 }, /* port-B */ 2206 { "CD", 0x5 }, 2207 { "Mix", 0x9 }, 2208 }, 2209 }; 2210 2211 /* 2212 */ 2213 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, 2214 struct snd_ctl_elem_info *uinfo) 2215 { 2216 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2217 struct ad198x_spec *spec = codec->spec; 2218 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, 2219 spec->num_channel_mode); 2220 } 2221 2222 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, 2223 struct snd_ctl_elem_value *ucontrol) 2224 { 2225 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2226 struct ad198x_spec *spec = codec->spec; 2227 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, 2228 spec->num_channel_mode, spec->multiout.max_channels); 2229 } 2230 2231 static int ad198x_ch_mode_put(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 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, 2237 spec->num_channel_mode, 2238 &spec->multiout.max_channels); 2239 if (err >= 0 && spec->need_dac_fix) 2240 spec->multiout.num_dacs = spec->multiout.max_channels / 2; 2241 return err; 2242 } 2243 2244 static const struct snd_kcontrol_new ad1988_hp_mixers[] = { 2245 { 2246 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2247 .name = "Independent HP", 2248 .info = ad1988_independent_hp_info, 2249 .get = ad1988_independent_hp_get, 2250 .put = ad1988_independent_hp_put, 2251 }, 2252 { } /* end */ 2253 }; 2254 2255 /* 6-stack mode */ 2256 static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = { 2257 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2258 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT), 2259 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 2260 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 2261 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 2262 { } /* end */ 2263 }; 2264 2265 static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = { 2266 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2267 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT), 2268 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 2269 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT), 2270 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT), 2271 { } /* end */ 2272 }; 2273 2274 static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = { 2275 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 2276 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), 2277 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT), 2278 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT), 2279 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT), 2280 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT), 2281 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), 2282 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 2283 2284 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 2285 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 2286 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 2287 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 2288 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 2289 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 2290 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), 2291 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), 2292 2293 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 2294 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 2295 2296 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 2297 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), 2298 { } /* end */ 2299 }; 2300 2301 /* 3-stack mode */ 2302 static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = { 2303 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2304 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 2305 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 2306 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 2307 { } /* end */ 2308 }; 2309 2310 static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = { 2311 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2312 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 2313 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT), 2314 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT), 2315 { } /* end */ 2316 }; 2317 2318 static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = { 2319 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 2320 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), 2321 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT), 2322 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT), 2323 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT), 2324 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), 2325 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 2326 2327 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 2328 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 2329 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 2330 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 2331 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 2332 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 2333 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), 2334 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), 2335 2336 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 2337 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 2338 2339 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 2340 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), 2341 { 2342 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2343 .name = "Channel Mode", 2344 .info = ad198x_ch_mode_info, 2345 .get = ad198x_ch_mode_get, 2346 .put = ad198x_ch_mode_put, 2347 }, 2348 2349 { } /* end */ 2350 }; 2351 2352 /* laptop mode */ 2353 static const struct snd_kcontrol_new ad1988_laptop_mixers[] = { 2354 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), 2355 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2356 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT), 2357 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 2358 2359 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 2360 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 2361 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 2362 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 2363 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 2364 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 2365 2366 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 2367 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 2368 2369 HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 2370 2371 { 2372 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2373 .name = "External Amplifier", 2374 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12, 2375 .info = ad198x_eapd_info, 2376 .get = ad198x_eapd_get, 2377 .put = ad198x_eapd_put, 2378 .private_value = 0x12, /* port-D */ 2379 }, 2380 2381 { } /* end */ 2382 }; 2383 2384 /* capture */ 2385 static const struct snd_kcontrol_new ad1988_capture_mixers[] = { 2386 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 2387 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 2388 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 2389 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 2390 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT), 2391 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT), 2392 { 2393 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2394 /* The multiple "Capture Source" controls confuse alsamixer 2395 * So call somewhat different.. 2396 */ 2397 /* .name = "Capture Source", */ 2398 .name = "Input Source", 2399 .count = 3, 2400 .info = ad198x_mux_enum_info, 2401 .get = ad198x_mux_enum_get, 2402 .put = ad198x_mux_enum_put, 2403 }, 2404 { } /* end */ 2405 }; 2406 2407 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol, 2408 struct snd_ctl_elem_info *uinfo) 2409 { 2410 static const char * const texts[] = { 2411 "PCM", "ADC1", "ADC2", "ADC3" 2412 }; 2413 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2414 uinfo->count = 1; 2415 uinfo->value.enumerated.items = 4; 2416 if (uinfo->value.enumerated.item >= 4) 2417 uinfo->value.enumerated.item = 3; 2418 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2419 return 0; 2420 } 2421 2422 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol, 2423 struct snd_ctl_elem_value *ucontrol) 2424 { 2425 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2426 unsigned int sel; 2427 2428 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE, 2429 AC_AMP_GET_INPUT); 2430 if (!(sel & 0x80)) 2431 ucontrol->value.enumerated.item[0] = 0; 2432 else { 2433 sel = snd_hda_codec_read(codec, 0x0b, 0, 2434 AC_VERB_GET_CONNECT_SEL, 0); 2435 if (sel < 3) 2436 sel++; 2437 else 2438 sel = 0; 2439 ucontrol->value.enumerated.item[0] = sel; 2440 } 2441 return 0; 2442 } 2443 2444 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol, 2445 struct snd_ctl_elem_value *ucontrol) 2446 { 2447 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2448 unsigned int val, sel; 2449 int change; 2450 2451 val = ucontrol->value.enumerated.item[0]; 2452 if (val > 3) 2453 return -EINVAL; 2454 if (!val) { 2455 sel = snd_hda_codec_read(codec, 0x1d, 0, 2456 AC_VERB_GET_AMP_GAIN_MUTE, 2457 AC_AMP_GET_INPUT); 2458 change = sel & 0x80; 2459 if (change) { 2460 snd_hda_codec_write_cache(codec, 0x1d, 0, 2461 AC_VERB_SET_AMP_GAIN_MUTE, 2462 AMP_IN_UNMUTE(0)); 2463 snd_hda_codec_write_cache(codec, 0x1d, 0, 2464 AC_VERB_SET_AMP_GAIN_MUTE, 2465 AMP_IN_MUTE(1)); 2466 } 2467 } else { 2468 sel = snd_hda_codec_read(codec, 0x1d, 0, 2469 AC_VERB_GET_AMP_GAIN_MUTE, 2470 AC_AMP_GET_INPUT | 0x01); 2471 change = sel & 0x80; 2472 if (change) { 2473 snd_hda_codec_write_cache(codec, 0x1d, 0, 2474 AC_VERB_SET_AMP_GAIN_MUTE, 2475 AMP_IN_MUTE(0)); 2476 snd_hda_codec_write_cache(codec, 0x1d, 0, 2477 AC_VERB_SET_AMP_GAIN_MUTE, 2478 AMP_IN_UNMUTE(1)); 2479 } 2480 sel = snd_hda_codec_read(codec, 0x0b, 0, 2481 AC_VERB_GET_CONNECT_SEL, 0) + 1; 2482 change |= sel != val; 2483 if (change) 2484 snd_hda_codec_write_cache(codec, 0x0b, 0, 2485 AC_VERB_SET_CONNECT_SEL, 2486 val - 1); 2487 } 2488 return change; 2489 } 2490 2491 static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = { 2492 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 2493 { 2494 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2495 .name = "IEC958 Playback Source", 2496 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b, 2497 .info = ad1988_spdif_playback_source_info, 2498 .get = ad1988_spdif_playback_source_get, 2499 .put = ad1988_spdif_playback_source_put, 2500 }, 2501 { } /* end */ 2502 }; 2503 2504 static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = { 2505 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT), 2506 { } /* end */ 2507 }; 2508 2509 static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = { 2510 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 2511 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 2512 { } /* end */ 2513 }; 2514 2515 /* 2516 * initialization verbs 2517 */ 2518 2519 /* 2520 * for 6-stack (+dig) 2521 */ 2522 static const struct hda_verb ad1988_6stack_init_verbs[] = { 2523 /* Front, Surround, CLFE, side DAC; unmute as default */ 2524 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2525 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2526 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2527 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2528 /* Port-A front headphon path */ 2529 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 2530 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2531 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2532 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2533 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2534 /* Port-D line-out path */ 2535 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2536 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2537 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2538 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2539 /* Port-F surround path */ 2540 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2541 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2542 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2543 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2544 /* Port-G CLFE path */ 2545 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2546 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2547 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2548 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2549 /* Port-H side path */ 2550 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2551 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2552 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2553 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2554 /* Mono out path */ 2555 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 2556 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2557 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2558 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2559 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 2560 /* Port-B front mic-in path */ 2561 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2562 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2563 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2564 /* Port-C line-in path */ 2565 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2566 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2567 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2568 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 2569 /* Port-E mic-in path */ 2570 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2571 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2572 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2573 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, 2574 /* Analog CD Input */ 2575 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2576 /* Analog Mix output amp */ 2577 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 2578 2579 { } 2580 }; 2581 2582 static const struct hda_verb ad1988_6stack_fp_init_verbs[] = { 2583 /* Headphone; unmute as default */ 2584 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2585 /* Port-A front headphon path */ 2586 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 2587 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2588 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2589 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2590 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2591 2592 { } 2593 }; 2594 2595 static const struct hda_verb ad1988_capture_init_verbs[] = { 2596 /* mute analog mix */ 2597 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2598 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2599 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2600 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2601 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2602 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 2603 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 2604 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 2605 /* select ADCs - front-mic */ 2606 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 2607 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 2608 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2609 2610 { } 2611 }; 2612 2613 static const struct hda_verb ad1988_spdif_init_verbs[] = { 2614 /* SPDIF out sel */ 2615 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 2616 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */ 2617 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2618 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2619 /* SPDIF out pin */ 2620 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2621 2622 { } 2623 }; 2624 2625 static const struct hda_verb ad1988_spdif_in_init_verbs[] = { 2626 /* unmute SPDIF input pin */ 2627 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2628 { } 2629 }; 2630 2631 /* AD1989 has no ADC -> SPDIF route */ 2632 static const struct hda_verb ad1989_spdif_init_verbs[] = { 2633 /* SPDIF-1 out pin */ 2634 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2635 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2636 /* SPDIF-2/HDMI out pin */ 2637 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2638 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2639 { } 2640 }; 2641 2642 /* 2643 * verbs for 3stack (+dig) 2644 */ 2645 static const struct hda_verb ad1988_3stack_ch2_init[] = { 2646 /* set port-C to line-in */ 2647 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2648 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 2649 /* set port-E to mic-in */ 2650 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2651 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 2652 { } /* end */ 2653 }; 2654 2655 static const struct hda_verb ad1988_3stack_ch6_init[] = { 2656 /* set port-C to surround out */ 2657 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2658 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2659 /* set port-E to CLFE out */ 2660 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2661 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2662 { } /* end */ 2663 }; 2664 2665 static const struct hda_channel_mode ad1988_3stack_modes[2] = { 2666 { 2, ad1988_3stack_ch2_init }, 2667 { 6, ad1988_3stack_ch6_init }, 2668 }; 2669 2670 static const struct hda_verb ad1988_3stack_init_verbs[] = { 2671 /* Front, Surround, CLFE, side DAC; unmute as default */ 2672 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2673 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2674 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2675 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2676 /* Port-A front headphon path */ 2677 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 2678 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2679 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2680 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2681 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2682 /* Port-D line-out path */ 2683 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2684 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2685 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2686 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2687 /* Mono out path */ 2688 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 2689 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2690 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2691 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2692 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 2693 /* Port-B front mic-in path */ 2694 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2695 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2696 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2697 /* Port-C line-in/surround path - 6ch mode as default */ 2698 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2699 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2700 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2701 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */ 2702 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 2703 /* Port-E mic-in/CLFE path - 6ch mode as default */ 2704 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2705 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2706 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2707 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */ 2708 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, 2709 /* mute analog mix */ 2710 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2711 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2712 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2713 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2714 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2715 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 2716 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 2717 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 2718 /* select ADCs - front-mic */ 2719 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 2720 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 2721 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2722 /* Analog Mix output amp */ 2723 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 2724 { } 2725 }; 2726 2727 /* 2728 * verbs for laptop mode (+dig) 2729 */ 2730 static const struct hda_verb ad1988_laptop_hp_on[] = { 2731 /* unmute port-A and mute port-D */ 2732 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2733 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2734 { } /* end */ 2735 }; 2736 static const struct hda_verb ad1988_laptop_hp_off[] = { 2737 /* mute port-A and unmute port-D */ 2738 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2739 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2740 { } /* end */ 2741 }; 2742 2743 #define AD1988_HP_EVENT 0x01 2744 2745 static const struct hda_verb ad1988_laptop_init_verbs[] = { 2746 /* Front, Surround, CLFE, side DAC; unmute as default */ 2747 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2748 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2749 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2750 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2751 /* Port-A front headphon path */ 2752 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ 2753 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2754 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2755 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2756 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2757 /* unsolicited event for pin-sense */ 2758 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT }, 2759 /* Port-D line-out path + EAPD */ 2760 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2761 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2762 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2763 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2764 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */ 2765 /* Mono out path */ 2766 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 2767 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2768 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2769 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2770 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 2771 /* Port-B mic-in path */ 2772 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2773 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2774 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2775 /* Port-C docking station - try to output */ 2776 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2777 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2778 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2779 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 2780 /* mute analog mix */ 2781 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2782 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2783 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2784 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2785 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2786 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 2787 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 2788 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 2789 /* select ADCs - mic */ 2790 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 2791 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 2792 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2793 /* Analog Mix output amp */ 2794 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 2795 { } 2796 }; 2797 2798 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) 2799 { 2800 if ((res >> 26) != AD1988_HP_EVENT) 2801 return; 2802 if (snd_hda_jack_detect(codec, 0x11)) 2803 snd_hda_sequence_write(codec, ad1988_laptop_hp_on); 2804 else 2805 snd_hda_sequence_write(codec, ad1988_laptop_hp_off); 2806 } 2807 2808 #ifdef CONFIG_PM 2809 static const struct hda_amp_list ad1988_loopbacks[] = { 2810 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 2811 { 0x20, HDA_INPUT, 1 }, /* Line */ 2812 { 0x20, HDA_INPUT, 4 }, /* Mic */ 2813 { 0x20, HDA_INPUT, 6 }, /* CD */ 2814 { } /* end */ 2815 }; 2816 #endif 2817 2818 /* 2819 * Automatic parse of I/O pins from the BIOS configuration 2820 */ 2821 2822 enum { 2823 AD_CTL_WIDGET_VOL, 2824 AD_CTL_WIDGET_MUTE, 2825 AD_CTL_BIND_MUTE, 2826 }; 2827 static const struct snd_kcontrol_new ad1988_control_templates[] = { 2828 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 2829 HDA_CODEC_MUTE(NULL, 0, 0, 0), 2830 HDA_BIND_MUTE(NULL, 0, 0, 0), 2831 }; 2832 2833 /* add dynamic controls */ 2834 static int add_control(struct ad198x_spec *spec, int type, const char *name, 2835 unsigned long val) 2836 { 2837 struct snd_kcontrol_new *knew; 2838 2839 snd_array_init(&spec->kctls, sizeof(*knew), 32); 2840 knew = snd_array_new(&spec->kctls); 2841 if (!knew) 2842 return -ENOMEM; 2843 *knew = ad1988_control_templates[type]; 2844 knew->name = kstrdup(name, GFP_KERNEL); 2845 if (! knew->name) 2846 return -ENOMEM; 2847 if (get_amp_nid_(val)) 2848 knew->subdevice = HDA_SUBDEV_AMP_FLAG; 2849 knew->private_value = val; 2850 return 0; 2851 } 2852 2853 #define AD1988_PIN_CD_NID 0x18 2854 #define AD1988_PIN_BEEP_NID 0x10 2855 2856 static const hda_nid_t ad1988_mixer_nids[8] = { 2857 /* A B C D E F G H */ 2858 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28 2859 }; 2860 2861 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx) 2862 { 2863 static const hda_nid_t idx_to_dac[8] = { 2864 /* A B C D E F G H */ 2865 0x03, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a 2866 }; 2867 static const hda_nid_t idx_to_dac_rev2[8] = { 2868 /* A B C D E F G H */ 2869 0x03, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06 2870 }; 2871 if (is_rev2(codec)) 2872 return idx_to_dac_rev2[idx]; 2873 else 2874 return idx_to_dac[idx]; 2875 } 2876 2877 static const hda_nid_t ad1988_boost_nids[8] = { 2878 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0 2879 }; 2880 2881 static int ad1988_pin_idx(hda_nid_t nid) 2882 { 2883 static const hda_nid_t ad1988_io_pins[8] = { 2884 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25 2885 }; 2886 int i; 2887 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++) 2888 if (ad1988_io_pins[i] == nid) 2889 return i; 2890 return 0; /* should be -1 */ 2891 } 2892 2893 static int ad1988_pin_to_loopback_idx(hda_nid_t nid) 2894 { 2895 static const int loopback_idx[8] = { 2896 2, 0, 1, 3, 4, 5, 1, 4 2897 }; 2898 switch (nid) { 2899 case AD1988_PIN_CD_NID: 2900 return 6; 2901 default: 2902 return loopback_idx[ad1988_pin_idx(nid)]; 2903 } 2904 } 2905 2906 static int ad1988_pin_to_adc_idx(hda_nid_t nid) 2907 { 2908 static const int adc_idx[8] = { 2909 0, 1, 2, 8, 4, 3, 6, 7 2910 }; 2911 switch (nid) { 2912 case AD1988_PIN_CD_NID: 2913 return 5; 2914 default: 2915 return adc_idx[ad1988_pin_idx(nid)]; 2916 } 2917 } 2918 2919 /* fill in the dac_nids table from the parsed pin configuration */ 2920 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec, 2921 const struct auto_pin_cfg *cfg) 2922 { 2923 struct ad198x_spec *spec = codec->spec; 2924 int i, idx; 2925 2926 spec->multiout.dac_nids = spec->private_dac_nids; 2927 2928 /* check the pins hardwired to audio widget */ 2929 for (i = 0; i < cfg->line_outs; i++) { 2930 idx = ad1988_pin_idx(cfg->line_out_pins[i]); 2931 spec->private_dac_nids[i] = ad1988_idx_to_dac(codec, idx); 2932 } 2933 spec->multiout.num_dacs = cfg->line_outs; 2934 return 0; 2935 } 2936 2937 /* add playback controls from the parsed DAC table */ 2938 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec, 2939 const struct auto_pin_cfg *cfg) 2940 { 2941 char name[32]; 2942 static const char * const chname[4] = { 2943 "Front", "Surround", NULL /*CLFE*/, "Side" 2944 }; 2945 hda_nid_t nid; 2946 int i, err; 2947 2948 for (i = 0; i < cfg->line_outs; i++) { 2949 hda_nid_t dac = spec->multiout.dac_nids[i]; 2950 if (! dac) 2951 continue; 2952 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])]; 2953 if (i == 2) { 2954 /* Center/LFE */ 2955 err = add_control(spec, AD_CTL_WIDGET_VOL, 2956 "Center Playback Volume", 2957 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT)); 2958 if (err < 0) 2959 return err; 2960 err = add_control(spec, AD_CTL_WIDGET_VOL, 2961 "LFE Playback Volume", 2962 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT)); 2963 if (err < 0) 2964 return err; 2965 err = add_control(spec, AD_CTL_BIND_MUTE, 2966 "Center Playback Switch", 2967 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT)); 2968 if (err < 0) 2969 return err; 2970 err = add_control(spec, AD_CTL_BIND_MUTE, 2971 "LFE Playback Switch", 2972 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT)); 2973 if (err < 0) 2974 return err; 2975 } else { 2976 sprintf(name, "%s Playback Volume", chname[i]); 2977 err = add_control(spec, AD_CTL_WIDGET_VOL, name, 2978 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT)); 2979 if (err < 0) 2980 return err; 2981 sprintf(name, "%s Playback Switch", chname[i]); 2982 err = add_control(spec, AD_CTL_BIND_MUTE, name, 2983 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); 2984 if (err < 0) 2985 return err; 2986 } 2987 } 2988 return 0; 2989 } 2990 2991 /* add playback controls for speaker and HP outputs */ 2992 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, 2993 const char *pfx) 2994 { 2995 struct ad198x_spec *spec = codec->spec; 2996 hda_nid_t nid; 2997 int i, idx, err; 2998 char name[32]; 2999 3000 if (! pin) 3001 return 0; 3002 3003 idx = ad1988_pin_idx(pin); 3004 nid = ad1988_idx_to_dac(codec, idx); 3005 /* check whether the corresponding DAC was already taken */ 3006 for (i = 0; i < spec->autocfg.line_outs; i++) { 3007 hda_nid_t pin = spec->autocfg.line_out_pins[i]; 3008 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin)); 3009 if (dac == nid) 3010 break; 3011 } 3012 if (i >= spec->autocfg.line_outs) { 3013 /* specify the DAC as the extra output */ 3014 if (!spec->multiout.hp_nid) 3015 spec->multiout.hp_nid = nid; 3016 else 3017 spec->multiout.extra_out_nid[0] = nid; 3018 /* control HP volume/switch on the output mixer amp */ 3019 sprintf(name, "%s Playback Volume", pfx); 3020 err = add_control(spec, AD_CTL_WIDGET_VOL, name, 3021 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 3022 if (err < 0) 3023 return err; 3024 } 3025 nid = ad1988_mixer_nids[idx]; 3026 sprintf(name, "%s Playback Switch", pfx); 3027 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name, 3028 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) 3029 return err; 3030 return 0; 3031 } 3032 3033 /* create input playback/capture controls for the given pin */ 3034 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, 3035 const char *ctlname, int ctlidx, int boost) 3036 { 3037 char name[32]; 3038 int err, idx; 3039 3040 sprintf(name, "%s Playback Volume", ctlname); 3041 idx = ad1988_pin_to_loopback_idx(pin); 3042 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name, 3043 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0) 3044 return err; 3045 sprintf(name, "%s Playback Switch", ctlname); 3046 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name, 3047 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0) 3048 return err; 3049 if (boost) { 3050 hda_nid_t bnid; 3051 idx = ad1988_pin_idx(pin); 3052 bnid = ad1988_boost_nids[idx]; 3053 if (bnid) { 3054 sprintf(name, "%s Boost Volume", ctlname); 3055 return add_control(spec, AD_CTL_WIDGET_VOL, name, 3056 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT)); 3057 3058 } 3059 } 3060 return 0; 3061 } 3062 3063 /* create playback/capture controls for input pins */ 3064 static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec, 3065 const struct auto_pin_cfg *cfg) 3066 { 3067 struct ad198x_spec *spec = codec->spec; 3068 struct hda_input_mux *imux = &spec->private_imux; 3069 int i, err, type, type_idx; 3070 3071 for (i = 0; i < cfg->num_inputs; i++) { 3072 const char *label; 3073 type = cfg->inputs[i].type; 3074 label = hda_get_autocfg_input_label(codec, cfg, i); 3075 snd_hda_add_imux_item(imux, label, 3076 ad1988_pin_to_adc_idx(cfg->inputs[i].pin), 3077 &type_idx); 3078 err = new_analog_input(spec, cfg->inputs[i].pin, 3079 label, type_idx, 3080 type == AUTO_PIN_MIC); 3081 if (err < 0) 3082 return err; 3083 } 3084 snd_hda_add_imux_item(imux, "Mix", 9, NULL); 3085 3086 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, 3087 "Analog Mix Playback Volume", 3088 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0) 3089 return err; 3090 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, 3091 "Analog Mix Playback Switch", 3092 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0) 3093 return err; 3094 3095 return 0; 3096 } 3097 3098 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec, 3099 hda_nid_t nid, int pin_type, 3100 int dac_idx) 3101 { 3102 /* set as output */ 3103 snd_hda_set_pin_ctl(codec, nid, pin_type); 3104 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 3105 switch (nid) { 3106 case 0x11: /* port-A - DAC 03 */ 3107 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x00); 3108 break; 3109 case 0x14: /* port-B - DAC 06 */ 3110 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02); 3111 break; 3112 case 0x15: /* port-C - DAC 05 */ 3113 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00); 3114 break; 3115 case 0x17: /* port-E - DAC 0a */ 3116 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01); 3117 break; 3118 case 0x13: /* mono - DAC 04 */ 3119 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01); 3120 break; 3121 } 3122 } 3123 3124 static void ad1988_auto_init_multi_out(struct hda_codec *codec) 3125 { 3126 struct ad198x_spec *spec = codec->spec; 3127 int i; 3128 3129 for (i = 0; i < spec->autocfg.line_outs; i++) { 3130 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 3131 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); 3132 } 3133 } 3134 3135 static void ad1988_auto_init_extra_out(struct hda_codec *codec) 3136 { 3137 struct ad198x_spec *spec = codec->spec; 3138 hda_nid_t pin; 3139 3140 pin = spec->autocfg.speaker_pins[0]; 3141 if (pin) /* connect to front */ 3142 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); 3143 pin = spec->autocfg.hp_pins[0]; 3144 if (pin) /* connect to front */ 3145 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 3146 } 3147 3148 static void ad1988_auto_init_analog_input(struct hda_codec *codec) 3149 { 3150 struct ad198x_spec *spec = codec->spec; 3151 const struct auto_pin_cfg *cfg = &spec->autocfg; 3152 int i, idx; 3153 3154 for (i = 0; i < cfg->num_inputs; i++) { 3155 hda_nid_t nid = cfg->inputs[i].pin; 3156 int type = cfg->inputs[i].type; 3157 int val; 3158 switch (nid) { 3159 case 0x15: /* port-C */ 3160 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); 3161 break; 3162 case 0x17: /* port-E */ 3163 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0); 3164 break; 3165 } 3166 val = PIN_IN; 3167 if (type == AUTO_PIN_MIC) 3168 val |= snd_hda_get_default_vref(codec, nid); 3169 snd_hda_set_pin_ctl(codec, nid, val); 3170 if (nid != AD1988_PIN_CD_NID) 3171 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 3172 AMP_OUT_MUTE); 3173 idx = ad1988_pin_idx(nid); 3174 if (ad1988_boost_nids[idx]) 3175 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0, 3176 AC_VERB_SET_AMP_GAIN_MUTE, 3177 AMP_OUT_ZERO); 3178 } 3179 } 3180 3181 /* parse the BIOS configuration and set up the alc_spec */ 3182 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */ 3183 static int ad1988_parse_auto_config(struct hda_codec *codec) 3184 { 3185 struct ad198x_spec *spec = codec->spec; 3186 int err; 3187 3188 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) 3189 return err; 3190 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) 3191 return err; 3192 if (! spec->autocfg.line_outs) 3193 return 0; /* can't find valid BIOS pin config */ 3194 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || 3195 (err = ad1988_auto_create_extra_out(codec, 3196 spec->autocfg.speaker_pins[0], 3197 "Speaker")) < 0 || 3198 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], 3199 "Headphone")) < 0 || 3200 (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) 3201 return err; 3202 3203 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 3204 3205 if (spec->autocfg.dig_outs) 3206 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 3207 if (spec->autocfg.dig_in_pin) 3208 spec->dig_in_nid = AD1988_SPDIF_IN; 3209 3210 if (spec->kctls.list) 3211 spec->mixers[spec->num_mixers++] = spec->kctls.list; 3212 3213 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; 3214 3215 spec->input_mux = &spec->private_imux; 3216 3217 return 1; 3218 } 3219 3220 /* init callback for auto-configuration model -- overriding the default init */ 3221 static int ad1988_auto_init(struct hda_codec *codec) 3222 { 3223 ad198x_init(codec); 3224 ad1988_auto_init_multi_out(codec); 3225 ad1988_auto_init_extra_out(codec); 3226 ad1988_auto_init_analog_input(codec); 3227 return 0; 3228 } 3229 3230 /* 3231 */ 3232 3233 static const char * const ad1988_models[AD1988_MODEL_LAST] = { 3234 [AD1988_6STACK] = "6stack", 3235 [AD1988_6STACK_DIG] = "6stack-dig", 3236 [AD1988_3STACK] = "3stack", 3237 [AD1988_3STACK_DIG] = "3stack-dig", 3238 [AD1988_LAPTOP] = "laptop", 3239 [AD1988_LAPTOP_DIG] = "laptop-dig", 3240 [AD1988_AUTO] = "auto", 3241 }; 3242 3243 static const struct snd_pci_quirk ad1988_cfg_tbl[] = { 3244 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG), 3245 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG), 3246 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG), 3247 SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG), 3248 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG), 3249 {} 3250 }; 3251 3252 static int patch_ad1988(struct hda_codec *codec) 3253 { 3254 struct ad198x_spec *spec; 3255 int err, board_config; 3256 3257 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3258 if (spec == NULL) 3259 return -ENOMEM; 3260 3261 codec->spec = spec; 3262 3263 if (is_rev2(codec)) 3264 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n"); 3265 3266 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST, 3267 ad1988_models, ad1988_cfg_tbl); 3268 if (board_config < 0) { 3269 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 3270 codec->chip_name); 3271 board_config = AD1988_AUTO; 3272 } 3273 3274 if (board_config == AD1988_AUTO) { 3275 /* automatic parse from the BIOS config */ 3276 err = ad1988_parse_auto_config(codec); 3277 if (err < 0) { 3278 ad198x_free(codec); 3279 return err; 3280 } else if (! err) { 3281 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n"); 3282 board_config = AD1988_6STACK; 3283 } 3284 } 3285 3286 err = snd_hda_attach_beep_device(codec, 0x10); 3287 if (err < 0) { 3288 ad198x_free(codec); 3289 return err; 3290 } 3291 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3292 3293 if (!spec->multiout.hp_nid) 3294 spec->multiout.hp_nid = ad1988_alt_dac_nid[0]; 3295 switch (board_config) { 3296 case AD1988_6STACK: 3297 case AD1988_6STACK_DIG: 3298 spec->multiout.max_channels = 8; 3299 spec->multiout.num_dacs = 4; 3300 if (is_rev2(codec)) 3301 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2; 3302 else 3303 spec->multiout.dac_nids = ad1988_6stack_dac_nids; 3304 spec->input_mux = &ad1988_6stack_capture_source; 3305 spec->num_mixers = 2; 3306 if (is_rev2(codec)) 3307 spec->mixers[0] = ad1988_6stack_mixers1_rev2; 3308 else 3309 spec->mixers[0] = ad1988_6stack_mixers1; 3310 spec->mixers[1] = ad1988_6stack_mixers2; 3311 spec->num_init_verbs = 1; 3312 spec->init_verbs[0] = ad1988_6stack_init_verbs; 3313 if (board_config == AD1988_6STACK_DIG) { 3314 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 3315 spec->dig_in_nid = AD1988_SPDIF_IN; 3316 } 3317 break; 3318 case AD1988_3STACK: 3319 case AD1988_3STACK_DIG: 3320 spec->multiout.max_channels = 6; 3321 spec->multiout.num_dacs = 3; 3322 if (is_rev2(codec)) 3323 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2; 3324 else 3325 spec->multiout.dac_nids = ad1988_3stack_dac_nids; 3326 spec->input_mux = &ad1988_6stack_capture_source; 3327 spec->channel_mode = ad1988_3stack_modes; 3328 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes); 3329 spec->num_mixers = 2; 3330 if (is_rev2(codec)) 3331 spec->mixers[0] = ad1988_3stack_mixers1_rev2; 3332 else 3333 spec->mixers[0] = ad1988_3stack_mixers1; 3334 spec->mixers[1] = ad1988_3stack_mixers2; 3335 spec->num_init_verbs = 1; 3336 spec->init_verbs[0] = ad1988_3stack_init_verbs; 3337 if (board_config == AD1988_3STACK_DIG) 3338 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 3339 break; 3340 case AD1988_LAPTOP: 3341 case AD1988_LAPTOP_DIG: 3342 spec->multiout.max_channels = 2; 3343 spec->multiout.num_dacs = 1; 3344 spec->multiout.dac_nids = ad1988_3stack_dac_nids; 3345 spec->input_mux = &ad1988_laptop_capture_source; 3346 spec->num_mixers = 1; 3347 spec->mixers[0] = ad1988_laptop_mixers; 3348 spec->inv_eapd = 1; /* inverted EAPD */ 3349 spec->num_init_verbs = 1; 3350 spec->init_verbs[0] = ad1988_laptop_init_verbs; 3351 if (board_config == AD1988_LAPTOP_DIG) 3352 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 3353 break; 3354 } 3355 3356 if (spec->autocfg.hp_pins[0]) { 3357 spec->mixers[spec->num_mixers++] = ad1988_hp_mixers; 3358 spec->slave_vols = ad1988_6stack_fp_slave_pfxs; 3359 spec->slave_sws = ad1988_6stack_fp_slave_pfxs; 3360 spec->alt_dac_nid = ad1988_alt_dac_nid; 3361 spec->stream_analog_alt_playback = 3362 &ad198x_pcm_analog_alt_playback; 3363 } 3364 3365 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids); 3366 spec->adc_nids = ad1988_adc_nids; 3367 spec->capsrc_nids = ad1988_capsrc_nids; 3368 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers; 3369 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs; 3370 if (spec->multiout.dig_out_nid) { 3371 if (codec->vendor_id >= 0x11d4989a) { 3372 spec->mixers[spec->num_mixers++] = 3373 ad1989_spdif_out_mixers; 3374 spec->init_verbs[spec->num_init_verbs++] = 3375 ad1989_spdif_init_verbs; 3376 codec->slave_dig_outs = ad1989b_slave_dig_outs; 3377 } else { 3378 spec->mixers[spec->num_mixers++] = 3379 ad1988_spdif_out_mixers; 3380 spec->init_verbs[spec->num_init_verbs++] = 3381 ad1988_spdif_init_verbs; 3382 } 3383 } 3384 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) { 3385 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers; 3386 spec->init_verbs[spec->num_init_verbs++] = 3387 ad1988_spdif_in_init_verbs; 3388 } 3389 3390 codec->patch_ops = ad198x_patch_ops; 3391 switch (board_config) { 3392 case AD1988_AUTO: 3393 codec->patch_ops.init = ad1988_auto_init; 3394 break; 3395 case AD1988_LAPTOP: 3396 case AD1988_LAPTOP_DIG: 3397 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; 3398 break; 3399 } 3400 #ifdef CONFIG_PM 3401 spec->loopback.amplist = ad1988_loopbacks; 3402 #endif 3403 spec->vmaster_nid = 0x04; 3404 3405 codec->no_trigger_sense = 1; 3406 codec->no_sticky_stream = 1; 3407 3408 return 0; 3409 } 3410 3411 3412 /* 3413 * AD1884 / AD1984 3414 * 3415 * port-B - front line/mic-in 3416 * port-E - aux in/out 3417 * port-F - aux in/out 3418 * port-C - rear line/mic-in 3419 * port-D - rear line/hp-out 3420 * port-A - front line/hp-out 3421 * 3422 * AD1984 = AD1884 + two digital mic-ins 3423 * 3424 * FIXME: 3425 * For simplicity, we share the single DAC for both HP and line-outs 3426 * right now. The inidividual playbacks could be easily implemented, 3427 * but no build-up framework is given, so far. 3428 */ 3429 3430 static const hda_nid_t ad1884_dac_nids[1] = { 3431 0x04, 3432 }; 3433 3434 static const hda_nid_t ad1884_adc_nids[2] = { 3435 0x08, 0x09, 3436 }; 3437 3438 static const hda_nid_t ad1884_capsrc_nids[2] = { 3439 0x0c, 0x0d, 3440 }; 3441 3442 #define AD1884_SPDIF_OUT 0x02 3443 3444 static const struct hda_input_mux ad1884_capture_source = { 3445 .num_items = 4, 3446 .items = { 3447 { "Front Mic", 0x0 }, 3448 { "Mic", 0x1 }, 3449 { "CD", 0x2 }, 3450 { "Mix", 0x3 }, 3451 }, 3452 }; 3453 3454 static const struct snd_kcontrol_new ad1884_base_mixers[] = { 3455 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3456 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ 3457 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3458 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3459 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 3460 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 3461 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3462 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3463 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 3464 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 3465 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), 3466 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), 3467 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 3468 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 3469 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3470 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3471 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3472 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3473 { 3474 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3475 /* The multiple "Capture Source" controls confuse alsamixer 3476 * So call somewhat different.. 3477 */ 3478 /* .name = "Capture Source", */ 3479 .name = "Input Source", 3480 .count = 2, 3481 .info = ad198x_mux_enum_info, 3482 .get = ad198x_mux_enum_get, 3483 .put = ad198x_mux_enum_put, 3484 }, 3485 /* SPDIF controls */ 3486 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 3487 { 3488 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3489 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 3490 /* identical with ad1983 */ 3491 .info = ad1983_spdif_route_info, 3492 .get = ad1983_spdif_route_get, 3493 .put = ad1983_spdif_route_put, 3494 }, 3495 { } /* end */ 3496 }; 3497 3498 static const struct snd_kcontrol_new ad1984_dmic_mixers[] = { 3499 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT), 3500 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT), 3501 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0, 3502 HDA_INPUT), 3503 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0, 3504 HDA_INPUT), 3505 { } /* end */ 3506 }; 3507 3508 /* 3509 * initialization verbs 3510 */ 3511 static const struct hda_verb ad1884_init_verbs[] = { 3512 /* DACs; mute as default */ 3513 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3514 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3515 /* Port-A (HP) mixer */ 3516 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3517 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3518 /* Port-A pin */ 3519 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3520 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3521 /* HP selector - select DAC2 */ 3522 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1}, 3523 /* Port-D (Line-out) mixer */ 3524 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3525 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3526 /* Port-D pin */ 3527 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3528 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3529 /* Mono-out mixer */ 3530 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3531 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3532 /* Mono-out pin */ 3533 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3534 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3535 /* Mono selector */ 3536 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 3537 /* Port-B (front mic) pin */ 3538 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3539 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3540 /* Port-C (rear mic) pin */ 3541 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3542 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3543 /* Analog mixer; mute as default */ 3544 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3545 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3546 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 3547 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 3548 /* Analog Mix output amp */ 3549 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 3550 /* SPDIF output selector */ 3551 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 3552 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 3553 { } /* end */ 3554 }; 3555 3556 #ifdef CONFIG_PM 3557 static const struct hda_amp_list ad1884_loopbacks[] = { 3558 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 3559 { 0x20, HDA_INPUT, 1 }, /* Mic */ 3560 { 0x20, HDA_INPUT, 2 }, /* CD */ 3561 { 0x20, HDA_INPUT, 4 }, /* Docking */ 3562 { } /* end */ 3563 }; 3564 #endif 3565 3566 static const char * const ad1884_slave_vols[] = { 3567 "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD", 3568 "Internal Mic", "Dock Mic", /* "Beep", */ "IEC958", 3569 NULL 3570 }; 3571 3572 static int patch_ad1884(struct hda_codec *codec) 3573 { 3574 struct ad198x_spec *spec; 3575 int err; 3576 3577 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3578 if (spec == NULL) 3579 return -ENOMEM; 3580 3581 codec->spec = spec; 3582 3583 err = snd_hda_attach_beep_device(codec, 0x10); 3584 if (err < 0) { 3585 ad198x_free(codec); 3586 return err; 3587 } 3588 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3589 3590 spec->multiout.max_channels = 2; 3591 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); 3592 spec->multiout.dac_nids = ad1884_dac_nids; 3593 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; 3594 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids); 3595 spec->adc_nids = ad1884_adc_nids; 3596 spec->capsrc_nids = ad1884_capsrc_nids; 3597 spec->input_mux = &ad1884_capture_source; 3598 spec->num_mixers = 1; 3599 spec->mixers[0] = ad1884_base_mixers; 3600 spec->num_init_verbs = 1; 3601 spec->init_verbs[0] = ad1884_init_verbs; 3602 spec->spdif_route = 0; 3603 #ifdef CONFIG_PM 3604 spec->loopback.amplist = ad1884_loopbacks; 3605 #endif 3606 spec->vmaster_nid = 0x04; 3607 /* we need to cover all playback volumes */ 3608 spec->slave_vols = ad1884_slave_vols; 3609 /* slaves may contain input volumes, so we can't raise to 0dB blindly */ 3610 spec->avoid_init_slave_vol = 1; 3611 3612 codec->patch_ops = ad198x_patch_ops; 3613 3614 codec->no_trigger_sense = 1; 3615 codec->no_sticky_stream = 1; 3616 3617 return 0; 3618 } 3619 3620 /* 3621 * Lenovo Thinkpad T61/X61 3622 */ 3623 static const struct hda_input_mux ad1984_thinkpad_capture_source = { 3624 .num_items = 4, 3625 .items = { 3626 { "Mic", 0x0 }, 3627 { "Internal Mic", 0x1 }, 3628 { "Mix", 0x3 }, 3629 { "Dock Mic", 0x4 }, 3630 }, 3631 }; 3632 3633 3634 /* 3635 * Dell Precision T3400 3636 */ 3637 static const struct hda_input_mux ad1984_dell_desktop_capture_source = { 3638 .num_items = 3, 3639 .items = { 3640 { "Front Mic", 0x0 }, 3641 { "Line-In", 0x1 }, 3642 { "Mix", 0x3 }, 3643 }, 3644 }; 3645 3646 3647 static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { 3648 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3649 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ 3650 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3651 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3652 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3653 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3654 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 3655 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 3656 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), 3657 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), 3658 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 3659 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 3660 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 3661 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 3662 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 3663 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3664 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3665 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3666 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3667 { 3668 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3669 /* The multiple "Capture Source" controls confuse alsamixer 3670 * So call somewhat different.. 3671 */ 3672 /* .name = "Capture Source", */ 3673 .name = "Input Source", 3674 .count = 2, 3675 .info = ad198x_mux_enum_info, 3676 .get = ad198x_mux_enum_get, 3677 .put = ad198x_mux_enum_put, 3678 }, 3679 /* SPDIF controls */ 3680 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 3681 { 3682 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3683 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 3684 /* identical with ad1983 */ 3685 .info = ad1983_spdif_route_info, 3686 .get = ad1983_spdif_route_get, 3687 .put = ad1983_spdif_route_put, 3688 }, 3689 { } /* end */ 3690 }; 3691 3692 /* additional verbs */ 3693 static const struct hda_verb ad1984_thinkpad_init_verbs[] = { 3694 /* Port-E (docking station mic) pin */ 3695 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3696 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3697 /* docking mic boost */ 3698 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3699 /* Analog PC Beeper - allow firmware/ACPI beeps */ 3700 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a}, 3701 /* Analog mixer - docking mic; mute as default */ 3702 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3703 /* enable EAPD bit */ 3704 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 3705 { } /* end */ 3706 }; 3707 3708 /* 3709 * Dell Precision T3400 3710 */ 3711 static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = { 3712 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3713 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3714 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3715 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 3716 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 3717 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3718 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3719 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), 3720 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), 3721 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT), 3722 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 3723 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3724 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3725 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3726 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3727 { 3728 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3729 /* The multiple "Capture Source" controls confuse alsamixer 3730 * So call somewhat different.. 3731 */ 3732 /* .name = "Capture Source", */ 3733 .name = "Input Source", 3734 .count = 2, 3735 .info = ad198x_mux_enum_info, 3736 .get = ad198x_mux_enum_get, 3737 .put = ad198x_mux_enum_put, 3738 }, 3739 { } /* end */ 3740 }; 3741 3742 /* Digial MIC ADC NID 0x05 + 0x06 */ 3743 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo, 3744 struct hda_codec *codec, 3745 unsigned int stream_tag, 3746 unsigned int format, 3747 struct snd_pcm_substream *substream) 3748 { 3749 snd_hda_codec_setup_stream(codec, 0x05 + substream->number, 3750 stream_tag, 0, format); 3751 return 0; 3752 } 3753 3754 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo, 3755 struct hda_codec *codec, 3756 struct snd_pcm_substream *substream) 3757 { 3758 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number); 3759 return 0; 3760 } 3761 3762 static const struct hda_pcm_stream ad1984_pcm_dmic_capture = { 3763 .substreams = 2, 3764 .channels_min = 2, 3765 .channels_max = 2, 3766 .nid = 0x05, 3767 .ops = { 3768 .prepare = ad1984_pcm_dmic_prepare, 3769 .cleanup = ad1984_pcm_dmic_cleanup 3770 }, 3771 }; 3772 3773 static int ad1984_build_pcms(struct hda_codec *codec) 3774 { 3775 struct ad198x_spec *spec = codec->spec; 3776 struct hda_pcm *info; 3777 int err; 3778 3779 err = ad198x_build_pcms(codec); 3780 if (err < 0) 3781 return err; 3782 3783 info = spec->pcm_rec + codec->num_pcms; 3784 codec->num_pcms++; 3785 info->name = "AD1984 Digital Mic"; 3786 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture; 3787 return 0; 3788 } 3789 3790 /* models */ 3791 enum { 3792 AD1984_BASIC, 3793 AD1984_THINKPAD, 3794 AD1984_DELL_DESKTOP, 3795 AD1984_MODELS 3796 }; 3797 3798 static const char * const ad1984_models[AD1984_MODELS] = { 3799 [AD1984_BASIC] = "basic", 3800 [AD1984_THINKPAD] = "thinkpad", 3801 [AD1984_DELL_DESKTOP] = "dell_desktop", 3802 }; 3803 3804 static const struct snd_pci_quirk ad1984_cfg_tbl[] = { 3805 /* Lenovo Thinkpad T61/X61 */ 3806 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD), 3807 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), 3808 SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP), 3809 {} 3810 }; 3811 3812 static int patch_ad1984(struct hda_codec *codec) 3813 { 3814 struct ad198x_spec *spec; 3815 int board_config, err; 3816 3817 err = patch_ad1884(codec); 3818 if (err < 0) 3819 return err; 3820 spec = codec->spec; 3821 board_config = snd_hda_check_board_config(codec, AD1984_MODELS, 3822 ad1984_models, ad1984_cfg_tbl); 3823 switch (board_config) { 3824 case AD1984_BASIC: 3825 /* additional digital mics */ 3826 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers; 3827 codec->patch_ops.build_pcms = ad1984_build_pcms; 3828 break; 3829 case AD1984_THINKPAD: 3830 if (codec->subsystem_id == 0x17aa20fb) { 3831 /* Thinpad X300 does not have the ability to do SPDIF, 3832 or attach to docking station to use SPDIF */ 3833 spec->multiout.dig_out_nid = 0; 3834 } else 3835 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; 3836 spec->input_mux = &ad1984_thinkpad_capture_source; 3837 spec->mixers[0] = ad1984_thinkpad_mixers; 3838 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs; 3839 spec->analog_beep = 1; 3840 break; 3841 case AD1984_DELL_DESKTOP: 3842 spec->multiout.dig_out_nid = 0; 3843 spec->input_mux = &ad1984_dell_desktop_capture_source; 3844 spec->mixers[0] = ad1984_dell_desktop_mixers; 3845 break; 3846 } 3847 return 0; 3848 } 3849 3850 3851 /* 3852 * AD1883 / AD1884A / AD1984A / AD1984B 3853 * 3854 * port-B (0x14) - front mic-in 3855 * port-E (0x1c) - rear mic-in 3856 * port-F (0x16) - CD / ext out 3857 * port-C (0x15) - rear line-in 3858 * port-D (0x12) - rear line-out 3859 * port-A (0x11) - front hp-out 3860 * 3861 * AD1984A = AD1884A + digital-mic 3862 * AD1883 = equivalent with AD1984A 3863 * AD1984B = AD1984A + extra SPDIF-out 3864 * 3865 * FIXME: 3866 * We share the single DAC for both HP and line-outs (see AD1884/1984). 3867 */ 3868 3869 static const hda_nid_t ad1884a_dac_nids[1] = { 3870 0x03, 3871 }; 3872 3873 #define ad1884a_adc_nids ad1884_adc_nids 3874 #define ad1884a_capsrc_nids ad1884_capsrc_nids 3875 3876 #define AD1884A_SPDIF_OUT 0x02 3877 3878 static const struct hda_input_mux ad1884a_capture_source = { 3879 .num_items = 5, 3880 .items = { 3881 { "Front Mic", 0x0 }, 3882 { "Mic", 0x4 }, 3883 { "Line", 0x1 }, 3884 { "CD", 0x2 }, 3885 { "Mix", 0x3 }, 3886 }, 3887 }; 3888 3889 static const struct snd_kcontrol_new ad1884a_base_mixers[] = { 3890 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 3891 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), 3892 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3893 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3894 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 3895 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 3896 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 3897 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 3898 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3899 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3900 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT), 3901 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), 3902 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 3903 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 3904 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), 3905 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), 3906 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 3907 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT), 3908 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 3909 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3910 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3911 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3912 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3913 { 3914 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3915 /* The multiple "Capture Source" controls confuse alsamixer 3916 * So call somewhat different.. 3917 */ 3918 /* .name = "Capture Source", */ 3919 .name = "Input Source", 3920 .count = 2, 3921 .info = ad198x_mux_enum_info, 3922 .get = ad198x_mux_enum_get, 3923 .put = ad198x_mux_enum_put, 3924 }, 3925 /* SPDIF controls */ 3926 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 3927 { 3928 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3929 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 3930 /* identical with ad1983 */ 3931 .info = ad1983_spdif_route_info, 3932 .get = ad1983_spdif_route_get, 3933 .put = ad1983_spdif_route_put, 3934 }, 3935 { } /* end */ 3936 }; 3937 3938 /* 3939 * initialization verbs 3940 */ 3941 static const struct hda_verb ad1884a_init_verbs[] = { 3942 /* DACs; unmute as default */ 3943 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 3944 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 3945 /* Port-A (HP) mixer - route only from analog mixer */ 3946 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3947 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3948 /* Port-A pin */ 3949 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3950 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3951 /* Port-D (Line-out) mixer - route only from analog mixer */ 3952 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3953 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3954 /* Port-D pin */ 3955 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3956 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3957 /* Mono-out mixer - route only from analog mixer */ 3958 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3959 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3960 /* Mono-out pin */ 3961 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3962 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3963 /* Port-B (front mic) pin */ 3964 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3965 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3966 /* Port-C (rear line-in) pin */ 3967 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3968 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3969 /* Port-E (rear mic) pin */ 3970 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3971 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3972 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */ 3973 /* Port-F (CD) pin */ 3974 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3975 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3976 /* Analog mixer; mute as default */ 3977 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3978 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3979 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 3980 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 3981 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */ 3982 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 3983 /* Analog Mix output amp */ 3984 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3985 /* capture sources */ 3986 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, 3987 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3988 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 3989 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3990 /* SPDIF output amp */ 3991 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 3992 { } /* end */ 3993 }; 3994 3995 #ifdef CONFIG_PM 3996 static const struct hda_amp_list ad1884a_loopbacks[] = { 3997 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 3998 { 0x20, HDA_INPUT, 1 }, /* Mic */ 3999 { 0x20, HDA_INPUT, 2 }, /* CD */ 4000 { 0x20, HDA_INPUT, 4 }, /* Docking */ 4001 { } /* end */ 4002 }; 4003 #endif 4004 4005 /* 4006 * Laptop model 4007 * 4008 * Port A: Headphone jack 4009 * Port B: MIC jack 4010 * Port C: Internal MIC 4011 * Port D: Dock Line Out (if enabled) 4012 * Port E: Dock Line In (if enabled) 4013 * Port F: Internal speakers 4014 */ 4015 4016 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol, 4017 struct snd_ctl_elem_value *ucontrol) 4018 { 4019 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 4020 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); 4021 int mute = (!ucontrol->value.integer.value[0] && 4022 !ucontrol->value.integer.value[1]); 4023 /* toggle GPIO1 according to the mute state */ 4024 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 4025 mute ? 0x02 : 0x0); 4026 return ret; 4027 } 4028 4029 static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = { 4030 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4031 { 4032 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4033 .name = "Master Playback Switch", 4034 .subdevice = HDA_SUBDEV_AMP_FLAG, 4035 .info = snd_hda_mixer_amp_switch_info, 4036 .get = snd_hda_mixer_amp_switch_get, 4037 .put = ad1884a_mobile_master_sw_put, 4038 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), 4039 }, 4040 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4041 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4042 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4043 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4044 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4045 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 4046 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 4047 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 4048 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 4049 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 4050 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 4051 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 4052 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4053 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4054 { } /* end */ 4055 }; 4056 4057 static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = { 4058 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4059 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ 4060 { 4061 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4062 .name = "Master Playback Switch", 4063 .subdevice = HDA_SUBDEV_AMP_FLAG, 4064 .info = snd_hda_mixer_amp_switch_info, 4065 .get = snd_hda_mixer_amp_switch_get, 4066 .put = ad1884a_mobile_master_sw_put, 4067 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), 4068 }, 4069 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4070 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4071 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), 4072 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT), 4073 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4074 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4075 { } /* end */ 4076 }; 4077 4078 /* mute internal speaker if HP is plugged */ 4079 static void ad1884a_hp_automute(struct hda_codec *codec) 4080 { 4081 unsigned int present; 4082 4083 present = snd_hda_jack_detect(codec, 0x11); 4084 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 4085 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4086 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, 4087 present ? 0x00 : 0x02); 4088 } 4089 4090 /* switch to external mic if plugged */ 4091 static void ad1884a_hp_automic(struct hda_codec *codec) 4092 { 4093 unsigned int present; 4094 4095 present = snd_hda_jack_detect(codec, 0x14); 4096 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 4097 present ? 0 : 1); 4098 } 4099 4100 #define AD1884A_HP_EVENT 0x37 4101 #define AD1884A_MIC_EVENT 0x36 4102 4103 /* unsolicited event for HP jack sensing */ 4104 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res) 4105 { 4106 switch (res >> 26) { 4107 case AD1884A_HP_EVENT: 4108 ad1884a_hp_automute(codec); 4109 break; 4110 case AD1884A_MIC_EVENT: 4111 ad1884a_hp_automic(codec); 4112 break; 4113 } 4114 } 4115 4116 /* initialize jack-sensing, too */ 4117 static int ad1884a_hp_init(struct hda_codec *codec) 4118 { 4119 ad198x_init(codec); 4120 ad1884a_hp_automute(codec); 4121 ad1884a_hp_automic(codec); 4122 return 0; 4123 } 4124 4125 /* mute internal speaker if HP or docking HP is plugged */ 4126 static void ad1884a_laptop_automute(struct hda_codec *codec) 4127 { 4128 unsigned int present; 4129 4130 present = snd_hda_jack_detect(codec, 0x11); 4131 if (!present) 4132 present = snd_hda_jack_detect(codec, 0x12); 4133 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 4134 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4135 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, 4136 present ? 0x00 : 0x02); 4137 } 4138 4139 /* switch to external mic if plugged */ 4140 static void ad1884a_laptop_automic(struct hda_codec *codec) 4141 { 4142 unsigned int idx; 4143 4144 if (snd_hda_jack_detect(codec, 0x14)) 4145 idx = 0; 4146 else if (snd_hda_jack_detect(codec, 0x1c)) 4147 idx = 4; 4148 else 4149 idx = 1; 4150 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx); 4151 } 4152 4153 /* unsolicited event for HP jack sensing */ 4154 static void ad1884a_laptop_unsol_event(struct hda_codec *codec, 4155 unsigned int res) 4156 { 4157 switch (res >> 26) { 4158 case AD1884A_HP_EVENT: 4159 ad1884a_laptop_automute(codec); 4160 break; 4161 case AD1884A_MIC_EVENT: 4162 ad1884a_laptop_automic(codec); 4163 break; 4164 } 4165 } 4166 4167 /* initialize jack-sensing, too */ 4168 static int ad1884a_laptop_init(struct hda_codec *codec) 4169 { 4170 ad198x_init(codec); 4171 ad1884a_laptop_automute(codec); 4172 ad1884a_laptop_automic(codec); 4173 return 0; 4174 } 4175 4176 /* additional verbs for laptop model */ 4177 static const struct hda_verb ad1884a_laptop_verbs[] = { 4178 /* Port-A (HP) pin - always unmuted */ 4179 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4180 /* Port-F (int speaker) mixer - route only from analog mixer */ 4181 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4182 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4183 /* Port-F (int speaker) pin */ 4184 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4185 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4186 /* required for compaq 6530s/6531s speaker output */ 4187 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4188 /* Port-C pin - internal mic-in */ 4189 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4190 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4191 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4192 /* Port-D (docking line-out) pin - default unmuted */ 4193 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4194 /* analog mix */ 4195 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4196 /* unsolicited event for pin-sense */ 4197 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4198 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4199 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4200 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4201 /* allow to touch GPIO1 (for mute control) */ 4202 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 4203 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 4204 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ 4205 { } /* end */ 4206 }; 4207 4208 static const struct hda_verb ad1884a_mobile_verbs[] = { 4209 /* DACs; unmute as default */ 4210 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4211 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4212 /* Port-A (HP) mixer - route only from analog mixer */ 4213 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4214 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4215 /* Port-A pin */ 4216 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4217 /* Port-A (HP) pin - always unmuted */ 4218 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4219 /* Port-B (mic jack) pin */ 4220 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4221 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4222 /* Port-C (int mic) pin */ 4223 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4224 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4225 /* Port-F (int speaker) mixer - route only from analog mixer */ 4226 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4227 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4228 /* Port-F pin */ 4229 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4230 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4231 /* Analog mixer; mute as default */ 4232 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4233 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4234 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4235 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4236 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4237 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 4238 /* Analog Mix output amp */ 4239 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4240 /* capture sources */ 4241 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ 4242 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4243 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 4244 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4245 /* unsolicited event for pin-sense */ 4246 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4247 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4248 /* allow to touch GPIO1 (for mute control) */ 4249 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 4250 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 4251 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ 4252 { } /* end */ 4253 }; 4254 4255 /* 4256 * Thinkpad X300 4257 * 0x11 - HP 4258 * 0x12 - speaker 4259 * 0x14 - mic-in 4260 * 0x17 - built-in mic 4261 */ 4262 4263 static const struct hda_verb ad1984a_thinkpad_verbs[] = { 4264 /* HP unmute */ 4265 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4266 /* analog mix */ 4267 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4268 /* turn on EAPD */ 4269 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4270 /* unsolicited event for pin-sense */ 4271 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4272 /* internal mic - dmic */ 4273 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4274 /* set magic COEFs for dmic */ 4275 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, 4276 {0x01, AC_VERB_SET_PROC_COEF, 0x08}, 4277 { } /* end */ 4278 }; 4279 4280 static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = { 4281 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4282 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), 4283 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4284 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4285 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4286 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4287 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), 4288 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT), 4289 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4290 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4291 { 4292 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4293 .name = "Capture Source", 4294 .info = ad198x_mux_enum_info, 4295 .get = ad198x_mux_enum_get, 4296 .put = ad198x_mux_enum_put, 4297 }, 4298 { } /* end */ 4299 }; 4300 4301 static const struct hda_input_mux ad1984a_thinkpad_capture_source = { 4302 .num_items = 3, 4303 .items = { 4304 { "Mic", 0x0 }, 4305 { "Internal Mic", 0x5 }, 4306 { "Mix", 0x3 }, 4307 }, 4308 }; 4309 4310 /* mute internal speaker if HP is plugged */ 4311 static void ad1984a_thinkpad_automute(struct hda_codec *codec) 4312 { 4313 unsigned int present; 4314 4315 present = snd_hda_jack_detect(codec, 0x11); 4316 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0, 4317 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4318 } 4319 4320 /* unsolicited event for HP jack sensing */ 4321 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec, 4322 unsigned int res) 4323 { 4324 if ((res >> 26) != AD1884A_HP_EVENT) 4325 return; 4326 ad1984a_thinkpad_automute(codec); 4327 } 4328 4329 /* initialize jack-sensing, too */ 4330 static int ad1984a_thinkpad_init(struct hda_codec *codec) 4331 { 4332 ad198x_init(codec); 4333 ad1984a_thinkpad_automute(codec); 4334 return 0; 4335 } 4336 4337 /* 4338 * Precision R5500 4339 * 0x12 - HP/line-out 4340 * 0x13 - speaker (mono) 4341 * 0x15 - mic-in 4342 */ 4343 4344 static const struct hda_verb ad1984a_precision_verbs[] = { 4345 /* Unmute main output path */ 4346 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4347 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */ 4348 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */ 4349 /* Analog mixer; mute as default */ 4350 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4351 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4352 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4353 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4354 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4355 /* Select mic as input */ 4356 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 4357 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */ 4358 /* Configure as mic */ 4359 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4360 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ 4361 /* HP unmute */ 4362 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4363 /* turn on EAPD */ 4364 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 4365 /* unsolicited event for pin-sense */ 4366 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4367 { } /* end */ 4368 }; 4369 4370 static const struct snd_kcontrol_new ad1984a_precision_mixers[] = { 4371 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4372 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), 4373 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4374 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4375 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 4376 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 4377 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT), 4378 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4379 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT), 4380 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4381 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4382 { } /* end */ 4383 }; 4384 4385 4386 /* mute internal speaker if HP is plugged */ 4387 static void ad1984a_precision_automute(struct hda_codec *codec) 4388 { 4389 unsigned int present; 4390 4391 present = snd_hda_jack_detect(codec, 0x12); 4392 snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, 4393 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4394 } 4395 4396 4397 /* unsolicited event for HP jack sensing */ 4398 static void ad1984a_precision_unsol_event(struct hda_codec *codec, 4399 unsigned int res) 4400 { 4401 if ((res >> 26) != AD1884A_HP_EVENT) 4402 return; 4403 ad1984a_precision_automute(codec); 4404 } 4405 4406 /* initialize jack-sensing, too */ 4407 static int ad1984a_precision_init(struct hda_codec *codec) 4408 { 4409 ad198x_init(codec); 4410 ad1984a_precision_automute(codec); 4411 return 0; 4412 } 4413 4414 4415 /* 4416 * HP Touchsmart 4417 * port-A (0x11) - front hp-out 4418 * port-B (0x14) - unused 4419 * port-C (0x15) - unused 4420 * port-D (0x12) - rear line out 4421 * port-E (0x1c) - front mic-in 4422 * port-F (0x16) - Internal speakers 4423 * digital-mic (0x17) - Internal mic 4424 */ 4425 4426 static const struct hda_verb ad1984a_touchsmart_verbs[] = { 4427 /* DACs; unmute as default */ 4428 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4429 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ 4430 /* Port-A (HP) mixer - route only from analog mixer */ 4431 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4432 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4433 /* Port-A pin */ 4434 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4435 /* Port-A (HP) pin - always unmuted */ 4436 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4437 /* Port-E (int speaker) mixer - route only from analog mixer */ 4438 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03}, 4439 /* Port-E pin */ 4440 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4441 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 4442 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4443 /* Port-F (int speaker) mixer - route only from analog mixer */ 4444 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4445 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4446 /* Port-F pin */ 4447 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4448 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4449 /* Analog mixer; mute as default */ 4450 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4451 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4452 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4453 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4454 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4455 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 4456 /* Analog Mix output amp */ 4457 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4458 /* capture sources */ 4459 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ 4460 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4461 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 4462 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4463 /* unsolicited event for pin-sense */ 4464 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, 4465 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, 4466 /* allow to touch GPIO1 (for mute control) */ 4467 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 4468 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 4469 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ 4470 /* internal mic - dmic */ 4471 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4472 /* set magic COEFs for dmic */ 4473 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, 4474 {0x01, AC_VERB_SET_PROC_COEF, 0x08}, 4475 { } /* end */ 4476 }; 4477 4478 static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { 4479 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), 4480 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ 4481 { 4482 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4483 .subdevice = HDA_SUBDEV_AMP_FLAG, 4484 .name = "Master Playback Switch", 4485 .info = snd_hda_mixer_amp_switch_info, 4486 .get = snd_hda_mixer_amp_switch_get, 4487 .put = ad1884a_mobile_master_sw_put, 4488 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), 4489 }, 4490 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), 4491 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), 4492 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4493 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4494 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), 4495 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT), 4496 { } /* end */ 4497 }; 4498 4499 /* switch to external mic if plugged */ 4500 static void ad1984a_touchsmart_automic(struct hda_codec *codec) 4501 { 4502 if (snd_hda_jack_detect(codec, 0x1c)) 4503 snd_hda_codec_write(codec, 0x0c, 0, 4504 AC_VERB_SET_CONNECT_SEL, 0x4); 4505 else 4506 snd_hda_codec_write(codec, 0x0c, 0, 4507 AC_VERB_SET_CONNECT_SEL, 0x5); 4508 } 4509 4510 4511 /* unsolicited event for HP jack sensing */ 4512 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec, 4513 unsigned int res) 4514 { 4515 switch (res >> 26) { 4516 case AD1884A_HP_EVENT: 4517 ad1884a_hp_automute(codec); 4518 break; 4519 case AD1884A_MIC_EVENT: 4520 ad1984a_touchsmart_automic(codec); 4521 break; 4522 } 4523 } 4524 4525 /* initialize jack-sensing, too */ 4526 static int ad1984a_touchsmart_init(struct hda_codec *codec) 4527 { 4528 ad198x_init(codec); 4529 ad1884a_hp_automute(codec); 4530 ad1984a_touchsmart_automic(codec); 4531 return 0; 4532 } 4533 4534 4535 /* 4536 */ 4537 4538 enum { 4539 AD1884A_DESKTOP, 4540 AD1884A_LAPTOP, 4541 AD1884A_MOBILE, 4542 AD1884A_THINKPAD, 4543 AD1984A_TOUCHSMART, 4544 AD1984A_PRECISION, 4545 AD1884A_MODELS 4546 }; 4547 4548 static const char * const ad1884a_models[AD1884A_MODELS] = { 4549 [AD1884A_DESKTOP] = "desktop", 4550 [AD1884A_LAPTOP] = "laptop", 4551 [AD1884A_MOBILE] = "mobile", 4552 [AD1884A_THINKPAD] = "thinkpad", 4553 [AD1984A_TOUCHSMART] = "touchsmart", 4554 [AD1984A_PRECISION] = "precision", 4555 }; 4556 4557 static const struct snd_pci_quirk ad1884a_cfg_tbl[] = { 4558 SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION), 4559 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), 4560 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), 4561 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), 4562 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE), 4563 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP), 4564 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP), 4565 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), 4566 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), 4567 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), 4568 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART), 4569 {} 4570 }; 4571 4572 static int patch_ad1884a(struct hda_codec *codec) 4573 { 4574 struct ad198x_spec *spec; 4575 int err, board_config; 4576 4577 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 4578 if (spec == NULL) 4579 return -ENOMEM; 4580 4581 codec->spec = spec; 4582 4583 err = snd_hda_attach_beep_device(codec, 0x10); 4584 if (err < 0) { 4585 ad198x_free(codec); 4586 return err; 4587 } 4588 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 4589 4590 spec->multiout.max_channels = 2; 4591 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids); 4592 spec->multiout.dac_nids = ad1884a_dac_nids; 4593 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT; 4594 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids); 4595 spec->adc_nids = ad1884a_adc_nids; 4596 spec->capsrc_nids = ad1884a_capsrc_nids; 4597 spec->input_mux = &ad1884a_capture_source; 4598 spec->num_mixers = 1; 4599 spec->mixers[0] = ad1884a_base_mixers; 4600 spec->num_init_verbs = 1; 4601 spec->init_verbs[0] = ad1884a_init_verbs; 4602 spec->spdif_route = 0; 4603 #ifdef CONFIG_PM 4604 spec->loopback.amplist = ad1884a_loopbacks; 4605 #endif 4606 codec->patch_ops = ad198x_patch_ops; 4607 4608 /* override some parameters */ 4609 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS, 4610 ad1884a_models, 4611 ad1884a_cfg_tbl); 4612 switch (board_config) { 4613 case AD1884A_LAPTOP: 4614 spec->mixers[0] = ad1884a_laptop_mixers; 4615 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs; 4616 spec->multiout.dig_out_nid = 0; 4617 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event; 4618 codec->patch_ops.init = ad1884a_laptop_init; 4619 /* set the upper-limit for mixer amp to 0dB for avoiding the 4620 * possible damage by overloading 4621 */ 4622 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 4623 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 4624 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 4625 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 4626 (1 << AC_AMPCAP_MUTE_SHIFT)); 4627 break; 4628 case AD1884A_MOBILE: 4629 spec->mixers[0] = ad1884a_mobile_mixers; 4630 spec->init_verbs[0] = ad1884a_mobile_verbs; 4631 spec->multiout.dig_out_nid = 0; 4632 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; 4633 codec->patch_ops.init = ad1884a_hp_init; 4634 /* set the upper-limit for mixer amp to 0dB for avoiding the 4635 * possible damage by overloading 4636 */ 4637 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 4638 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 4639 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 4640 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 4641 (1 << AC_AMPCAP_MUTE_SHIFT)); 4642 break; 4643 case AD1884A_THINKPAD: 4644 spec->mixers[0] = ad1984a_thinkpad_mixers; 4645 spec->init_verbs[spec->num_init_verbs++] = 4646 ad1984a_thinkpad_verbs; 4647 spec->multiout.dig_out_nid = 0; 4648 spec->input_mux = &ad1984a_thinkpad_capture_source; 4649 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; 4650 codec->patch_ops.init = ad1984a_thinkpad_init; 4651 break; 4652 case AD1984A_PRECISION: 4653 spec->mixers[0] = ad1984a_precision_mixers; 4654 spec->init_verbs[spec->num_init_verbs++] = 4655 ad1984a_precision_verbs; 4656 spec->multiout.dig_out_nid = 0; 4657 codec->patch_ops.unsol_event = ad1984a_precision_unsol_event; 4658 codec->patch_ops.init = ad1984a_precision_init; 4659 break; 4660 case AD1984A_TOUCHSMART: 4661 spec->mixers[0] = ad1984a_touchsmart_mixers; 4662 spec->init_verbs[0] = ad1984a_touchsmart_verbs; 4663 spec->multiout.dig_out_nid = 0; 4664 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event; 4665 codec->patch_ops.init = ad1984a_touchsmart_init; 4666 /* set the upper-limit for mixer amp to 0dB for avoiding the 4667 * possible damage by overloading 4668 */ 4669 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, 4670 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 4671 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 4672 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 4673 (1 << AC_AMPCAP_MUTE_SHIFT)); 4674 break; 4675 } 4676 4677 codec->no_trigger_sense = 1; 4678 codec->no_sticky_stream = 1; 4679 4680 return 0; 4681 } 4682 4683 4684 /* 4685 * AD1882 / AD1882A 4686 * 4687 * port-A - front hp-out 4688 * port-B - front mic-in 4689 * port-C - rear line-in, shared surr-out (3stack) 4690 * port-D - rear line-out 4691 * port-E - rear mic-in, shared clfe-out (3stack) 4692 * port-F - rear surr-out (6stack) 4693 * port-G - rear clfe-out (6stack) 4694 */ 4695 4696 static const hda_nid_t ad1882_dac_nids[3] = { 4697 0x04, 0x03, 0x05 4698 }; 4699 4700 static const hda_nid_t ad1882_adc_nids[2] = { 4701 0x08, 0x09, 4702 }; 4703 4704 static const hda_nid_t ad1882_capsrc_nids[2] = { 4705 0x0c, 0x0d, 4706 }; 4707 4708 #define AD1882_SPDIF_OUT 0x02 4709 4710 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */ 4711 static const struct hda_input_mux ad1882_capture_source = { 4712 .num_items = 5, 4713 .items = { 4714 { "Front Mic", 0x1 }, 4715 { "Mic", 0x4 }, 4716 { "Line", 0x2 }, 4717 { "CD", 0x3 }, 4718 { "Mix", 0x7 }, 4719 }, 4720 }; 4721 4722 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */ 4723 static const struct hda_input_mux ad1882a_capture_source = { 4724 .num_items = 5, 4725 .items = { 4726 { "Front Mic", 0x1 }, 4727 { "Mic", 0x4}, 4728 { "Line", 0x2 }, 4729 { "Digital Mic", 0x06 }, 4730 { "Mix", 0x7 }, 4731 }, 4732 }; 4733 4734 static const struct snd_kcontrol_new ad1882_base_mixers[] = { 4735 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 4736 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), 4737 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 4738 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 4739 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 4740 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 4741 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 4742 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 4743 4744 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), 4745 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), 4746 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT), 4747 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 4748 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 4749 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 4750 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 4751 { 4752 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4753 /* The multiple "Capture Source" controls confuse alsamixer 4754 * So call somewhat different.. 4755 */ 4756 /* .name = "Capture Source", */ 4757 .name = "Input Source", 4758 .count = 2, 4759 .info = ad198x_mux_enum_info, 4760 .get = ad198x_mux_enum_get, 4761 .put = ad198x_mux_enum_put, 4762 }, 4763 /* SPDIF controls */ 4764 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 4765 { 4766 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4767 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 4768 /* identical with ad1983 */ 4769 .info = ad1983_spdif_route_info, 4770 .get = ad1983_spdif_route_get, 4771 .put = ad1983_spdif_route_put, 4772 }, 4773 { } /* end */ 4774 }; 4775 4776 static const struct snd_kcontrol_new ad1882_loopback_mixers[] = { 4777 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4778 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4779 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 4780 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 4781 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT), 4782 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), 4783 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), 4784 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), 4785 { } /* end */ 4786 }; 4787 4788 static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = { 4789 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 4790 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 4791 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 4792 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 4793 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT), 4794 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), 4795 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), 4796 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), 4797 HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT), 4798 { } /* end */ 4799 }; 4800 4801 static const struct snd_kcontrol_new ad1882_3stack_mixers[] = { 4802 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), 4803 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT), 4804 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT), 4805 { 4806 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 4807 .name = "Channel Mode", 4808 .info = ad198x_ch_mode_info, 4809 .get = ad198x_ch_mode_get, 4810 .put = ad198x_ch_mode_put, 4811 }, 4812 { } /* end */ 4813 }; 4814 4815 /* simple auto-mute control for AD1882 3-stack board */ 4816 #define AD1882_HP_EVENT 0x01 4817 4818 static void ad1882_3stack_automute(struct hda_codec *codec) 4819 { 4820 bool mute = snd_hda_jack_detect(codec, 0x11); 4821 snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 4822 mute ? 0 : PIN_OUT); 4823 } 4824 4825 static int ad1882_3stack_automute_init(struct hda_codec *codec) 4826 { 4827 ad198x_init(codec); 4828 ad1882_3stack_automute(codec); 4829 return 0; 4830 } 4831 4832 static void ad1882_3stack_unsol_event(struct hda_codec *codec, unsigned int res) 4833 { 4834 switch (res >> 26) { 4835 case AD1882_HP_EVENT: 4836 ad1882_3stack_automute(codec); 4837 break; 4838 } 4839 } 4840 4841 static const struct snd_kcontrol_new ad1882_6stack_mixers[] = { 4842 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT), 4843 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT), 4844 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT), 4845 { } /* end */ 4846 }; 4847 4848 static const struct hda_verb ad1882_ch2_init[] = { 4849 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4850 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4851 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4852 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4853 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4854 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4855 { } /* end */ 4856 }; 4857 4858 static const struct hda_verb ad1882_ch4_init[] = { 4859 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4860 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4861 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4862 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4863 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4864 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4865 { } /* end */ 4866 }; 4867 4868 static const struct hda_verb ad1882_ch6_init[] = { 4869 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4870 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4871 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4872 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4873 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4874 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4875 { } /* end */ 4876 }; 4877 4878 static const struct hda_channel_mode ad1882_modes[3] = { 4879 { 2, ad1882_ch2_init }, 4880 { 4, ad1882_ch4_init }, 4881 { 6, ad1882_ch6_init }, 4882 }; 4883 4884 /* 4885 * initialization verbs 4886 */ 4887 static const struct hda_verb ad1882_init_verbs[] = { 4888 /* DACs; mute as default */ 4889 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4890 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4891 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 4892 /* Port-A (HP) mixer */ 4893 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4894 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4895 /* Port-A pin */ 4896 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4897 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4898 /* HP selector - select DAC2 */ 4899 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1}, 4900 /* Port-D (Line-out) mixer */ 4901 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4902 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4903 /* Port-D pin */ 4904 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4905 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4906 /* Mono-out mixer */ 4907 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 4908 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 4909 /* Mono-out pin */ 4910 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 4911 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4912 /* Port-B (front mic) pin */ 4913 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4914 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4915 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 4916 /* Port-C (line-in) pin */ 4917 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 4918 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4919 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 4920 /* Port-C mixer - mute as input */ 4921 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4922 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4923 /* Port-E (mic-in) pin */ 4924 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 4925 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4926 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 4927 /* Port-E mixer - mute as input */ 4928 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4929 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4930 /* Port-F (surround) */ 4931 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4932 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4933 /* Port-G (CLFE) */ 4934 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 4935 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 4936 /* Analog mixer; mute as default */ 4937 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */ 4938 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 4939 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 4940 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 4941 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 4942 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 4943 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 4944 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 4945 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 4946 /* Analog Mix output amp */ 4947 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 4948 /* SPDIF output selector */ 4949 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 4950 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 4951 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 4952 { } /* end */ 4953 }; 4954 4955 static const struct hda_verb ad1882_3stack_automute_verbs[] = { 4956 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1882_HP_EVENT}, 4957 { } /* end */ 4958 }; 4959 4960 #ifdef CONFIG_PM 4961 static const struct hda_amp_list ad1882_loopbacks[] = { 4962 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 4963 { 0x20, HDA_INPUT, 1 }, /* Mic */ 4964 { 0x20, HDA_INPUT, 4 }, /* Line */ 4965 { 0x20, HDA_INPUT, 6 }, /* CD */ 4966 { } /* end */ 4967 }; 4968 #endif 4969 4970 /* models */ 4971 enum { 4972 AD1882_3STACK, 4973 AD1882_6STACK, 4974 AD1882_3STACK_AUTOMUTE, 4975 AD1882_MODELS 4976 }; 4977 4978 static const char * const ad1882_models[AD1986A_MODELS] = { 4979 [AD1882_3STACK] = "3stack", 4980 [AD1882_6STACK] = "6stack", 4981 [AD1882_3STACK_AUTOMUTE] = "3stack-automute", 4982 }; 4983 4984 4985 static int patch_ad1882(struct hda_codec *codec) 4986 { 4987 struct ad198x_spec *spec; 4988 int err, board_config; 4989 4990 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 4991 if (spec == NULL) 4992 return -ENOMEM; 4993 4994 codec->spec = spec; 4995 4996 err = snd_hda_attach_beep_device(codec, 0x10); 4997 if (err < 0) { 4998 ad198x_free(codec); 4999 return err; 5000 } 5001 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 5002 5003 spec->multiout.max_channels = 6; 5004 spec->multiout.num_dacs = 3; 5005 spec->multiout.dac_nids = ad1882_dac_nids; 5006 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT; 5007 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids); 5008 spec->adc_nids = ad1882_adc_nids; 5009 spec->capsrc_nids = ad1882_capsrc_nids; 5010 if (codec->vendor_id == 0x11d41882) 5011 spec->input_mux = &ad1882_capture_source; 5012 else 5013 spec->input_mux = &ad1882a_capture_source; 5014 spec->num_mixers = 2; 5015 spec->mixers[0] = ad1882_base_mixers; 5016 if (codec->vendor_id == 0x11d41882) 5017 spec->mixers[1] = ad1882_loopback_mixers; 5018 else 5019 spec->mixers[1] = ad1882a_loopback_mixers; 5020 spec->num_init_verbs = 1; 5021 spec->init_verbs[0] = ad1882_init_verbs; 5022 spec->spdif_route = 0; 5023 #ifdef CONFIG_PM 5024 spec->loopback.amplist = ad1882_loopbacks; 5025 #endif 5026 spec->vmaster_nid = 0x04; 5027 5028 codec->patch_ops = ad198x_patch_ops; 5029 5030 /* override some parameters */ 5031 board_config = snd_hda_check_board_config(codec, AD1882_MODELS, 5032 ad1882_models, NULL); 5033 switch (board_config) { 5034 default: 5035 case AD1882_3STACK: 5036 case AD1882_3STACK_AUTOMUTE: 5037 spec->num_mixers = 3; 5038 spec->mixers[2] = ad1882_3stack_mixers; 5039 spec->channel_mode = ad1882_modes; 5040 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes); 5041 spec->need_dac_fix = 1; 5042 spec->multiout.max_channels = 2; 5043 spec->multiout.num_dacs = 1; 5044 if (board_config != AD1882_3STACK) { 5045 spec->init_verbs[spec->num_init_verbs++] = 5046 ad1882_3stack_automute_verbs; 5047 codec->patch_ops.unsol_event = ad1882_3stack_unsol_event; 5048 codec->patch_ops.init = ad1882_3stack_automute_init; 5049 } 5050 break; 5051 case AD1882_6STACK: 5052 spec->num_mixers = 3; 5053 spec->mixers[2] = ad1882_6stack_mixers; 5054 break; 5055 } 5056 5057 codec->no_trigger_sense = 1; 5058 codec->no_sticky_stream = 1; 5059 5060 return 0; 5061 } 5062 5063 5064 /* 5065 * patch entries 5066 */ 5067 static const struct hda_codec_preset snd_hda_preset_analog[] = { 5068 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a }, 5069 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 }, 5070 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a }, 5071 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 }, 5072 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a }, 5073 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a }, 5074 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, 5075 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, 5076 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 }, 5077 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, 5078 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, 5079 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, 5080 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 }, 5081 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 }, 5082 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 }, 5083 {} /* terminator */ 5084 }; 5085 5086 MODULE_ALIAS("snd-hda-codec-id:11d4*"); 5087 5088 MODULE_LICENSE("GPL"); 5089 MODULE_DESCRIPTION("Analog Devices HD-audio codec"); 5090 5091 static struct hda_codec_preset_list analog_list = { 5092 .preset = snd_hda_preset_analog, 5093 .owner = THIS_MODULE, 5094 }; 5095 5096 static int __init patch_analog_init(void) 5097 { 5098 return snd_hda_add_codec_preset(&analog_list); 5099 } 5100 5101 static void __exit patch_analog_exit(void) 5102 { 5103 snd_hda_delete_codec_preset(&analog_list); 5104 } 5105 5106 module_init(patch_analog_init) 5107 module_exit(patch_analog_exit) 5108