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