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