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