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