aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_analog.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-07-04 09:36:56 -0400
committerTakashi Iwai <tiwai@suse.de>2013-07-04 09:36:56 -0400
commit5ccc618fee67f0f0b2122dd4b32a02fd2b6a1569 (patch)
tree4b0399154707df80db62e25035cc87e06c951030 /sound/pci/hda/patch_analog.c
parentaa95d61b43e0fcb0b2ce68e5efa37174fd9e5cd3 (diff)
ALSA: hda - Remove static quirks for AD1884/1984 & variants
Since the necessary device-specific fixups for Thinkpad and HP devices have been already ported, we can remove all static quirks for AD1884, AD1984, AD1884A and AD1984A codecs. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r--sound/pci/hda/patch_analog.c1348
1 files changed, 18 insertions, 1330 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 876d836ef742..bfa8f532841d 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3423,167 +3423,19 @@ static int patch_ad1988(struct hda_codec *codec)
3423 * 3423 *
3424 * AD1984 = AD1884 + two digital mic-ins 3424 * AD1984 = AD1884 + two digital mic-ins
3425 * 3425 *
3426 * FIXME: 3426 * AD1883 / AD1884A / AD1984A / AD1984B
3427 * For simplicity, we share the single DAC for both HP and line-outs 3427 *
3428 * right now. The inidividual playbacks could be easily implemented, 3428 * port-B (0x14) - front mic-in
3429 * but no build-up framework is given, so far. 3429 * port-E (0x1c) - rear mic-in
3430 */ 3430 * port-F (0x16) - CD / ext out
3431 3431 * port-C (0x15) - rear line-in
3432#ifdef ENABLE_AD_STATIC_QUIRKS 3432 * port-D (0x12) - rear line-out
3433static const hda_nid_t ad1884_dac_nids[1] = { 3433 * port-A (0x11) - front hp-out
3434 0x04, 3434 *
3435}; 3435 * AD1984A = AD1884A + digital-mic
3436 3436 * AD1883 = equivalent with AD1984A
3437static const hda_nid_t ad1884_adc_nids[2] = { 3437 * AD1984B = AD1984A + extra SPDIF-out
3438 0x08, 0x09,
3439};
3440
3441static const hda_nid_t ad1884_capsrc_nids[2] = {
3442 0x0c, 0x0d,
3443};
3444
3445#define AD1884_SPDIF_OUT 0x02
3446
3447static const struct hda_input_mux ad1884_capture_source = {
3448 .num_items = 4,
3449 .items = {
3450 { "Front Mic", 0x0 },
3451 { "Mic", 0x1 },
3452 { "CD", 0x2 },
3453 { "Mix", 0x3 },
3454 },
3455};
3456
3457static const struct snd_kcontrol_new ad1884_base_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("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3462 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3463 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3464 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3465 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3466 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3467 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3468 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3469 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3470 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3471 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3472 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3473 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3474 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3475 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3476 {
3477 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3478 /* The multiple "Capture Source" controls confuse alsamixer
3479 * So call somewhat different..
3480 */
3481 /* .name = "Capture Source", */
3482 .name = "Input Source",
3483 .count = 2,
3484 .info = ad198x_mux_enum_info,
3485 .get = ad198x_mux_enum_get,
3486 .put = ad198x_mux_enum_put,
3487 },
3488 /* SPDIF controls */
3489 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3490 {
3491 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3492 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3493 /* identical with ad1983 */
3494 .info = ad1983_spdif_route_info,
3495 .get = ad1983_spdif_route_get,
3496 .put = ad1983_spdif_route_put,
3497 },
3498 { } /* end */
3499};
3500
3501static const struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3502 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3503 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3504 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3505 HDA_INPUT),
3506 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3507 HDA_INPUT),
3508 { } /* end */
3509};
3510
3511/*
3512 * initialization verbs
3513 */ 3438 */
3514static const struct hda_verb ad1884_init_verbs[] = {
3515 /* DACs; mute as default */
3516 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3517 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3518 /* Port-A (HP) mixer */
3519 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3520 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3521 /* Port-A pin */
3522 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3523 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3524 /* HP selector - select DAC2 */
3525 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3526 /* Port-D (Line-out) mixer */
3527 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3528 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3529 /* Port-D pin */
3530 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3531 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3532 /* Mono-out mixer */
3533 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3534 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3535 /* Mono-out pin */
3536 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3537 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3538 /* Mono selector */
3539 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3540 /* Port-B (front mic) pin */
3541 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3542 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3543 /* Port-C (rear mic) pin */
3544 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3545 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3546 /* Analog mixer; mute as default */
3547 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3548 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3549 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3550 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3551 /* Analog Mix output amp */
3552 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3553 /* SPDIF output selector */
3554 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3555 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3556 { } /* end */
3557};
3558
3559#ifdef CONFIG_PM
3560static const struct hda_amp_list ad1884_loopbacks[] = {
3561 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3562 { 0x20, HDA_INPUT, 1 }, /* Mic */
3563 { 0x20, HDA_INPUT, 2 }, /* CD */
3564 { 0x20, HDA_INPUT, 4 }, /* Docking */
3565 { } /* end */
3566};
3567#endif
3568
3569static const char * const ad1884_slave_vols[] = {
3570 "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD",
3571 "Internal Mic", "Dock Mic", /* "Beep", */ "IEC958",
3572 NULL
3573};
3574
3575enum {
3576 AD1884_AUTO,
3577 AD1884_BASIC,
3578 AD1884_MODELS
3579};
3580
3581static const char * const ad1884_models[AD1884_MODELS] = {
3582 [AD1884_AUTO] = "auto",
3583 [AD1884_BASIC] = "basic",
3584};
3585#endif /* ENABLE_AD_STATIC_QUIRKS */
3586
3587 3439
3588/* set the upper-limit for mixer amp to 0dB for avoiding the possible 3440/* set the upper-limit for mixer amp to 0dB for avoiding the possible
3589 * damage by overloading 3441 * damage by overloading
@@ -3682,7 +3534,7 @@ static const struct snd_pci_quirk ad1884_fixup_tbl[] = {
3682}; 3534};
3683 3535
3684 3536
3685static int ad1884_parse_auto_config(struct hda_codec *codec) 3537static int patch_ad1884(struct hda_codec *codec)
3686{ 3538{
3687 struct ad198x_spec *spec; 3539 struct ad198x_spec *spec;
3688 int err; 3540 int err;
@@ -3715,1170 +3567,6 @@ static int ad1884_parse_auto_config(struct hda_codec *codec)
3715 return err; 3567 return err;
3716} 3568}
3717 3569
3718#ifdef ENABLE_AD_STATIC_QUIRKS
3719static int patch_ad1884_basic(struct hda_codec *codec)
3720{
3721 struct ad198x_spec *spec;
3722 int err;
3723
3724 err = alloc_ad_spec(codec);
3725 if (err < 0)
3726 return err;
3727 spec = codec->spec;
3728
3729 err = snd_hda_attach_beep_device(codec, 0x10);
3730 if (err < 0) {
3731 ad198x_free(codec);
3732 return err;
3733 }
3734 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3735
3736 spec->multiout.max_channels = 2;
3737 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3738 spec->multiout.dac_nids = ad1884_dac_nids;
3739 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3740 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3741 spec->adc_nids = ad1884_adc_nids;
3742 spec->capsrc_nids = ad1884_capsrc_nids;
3743 spec->input_mux = &ad1884_capture_source;
3744 spec->num_mixers = 1;
3745 spec->mixers[0] = ad1884_base_mixers;
3746 spec->num_init_verbs = 1;
3747 spec->init_verbs[0] = ad1884_init_verbs;
3748 spec->spdif_route = 0;
3749#ifdef CONFIG_PM
3750 spec->loopback.amplist = ad1884_loopbacks;
3751#endif
3752 spec->vmaster_nid = 0x04;
3753 /* we need to cover all playback volumes */
3754 spec->slave_vols = ad1884_slave_vols;
3755 /* slaves may contain input volumes, so we can't raise to 0dB blindly */
3756 spec->avoid_init_slave_vol = 1;
3757
3758 codec->patch_ops = ad198x_patch_ops;
3759
3760 codec->no_trigger_sense = 1;
3761 codec->no_sticky_stream = 1;
3762
3763 return 0;
3764}
3765
3766static int patch_ad1884(struct hda_codec *codec)
3767{
3768 int board_config;
3769
3770 board_config = snd_hda_check_board_config(codec, AD1884_MODELS,
3771 ad1884_models, NULL);
3772 if (board_config < 0) {
3773 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3774 codec->chip_name);
3775 board_config = AD1884_AUTO;
3776 }
3777
3778 if (board_config == AD1884_AUTO)
3779 return ad1884_parse_auto_config(codec);
3780 else
3781 return patch_ad1884_basic(codec);
3782}
3783#else /* ENABLE_AD_STATIC_QUIRKS */
3784#define patch_ad1884 ad1884_parse_auto_config
3785#endif /* ENABLE_AD_STATIC_QUIRKS */
3786
3787
3788#ifdef ENABLE_AD_STATIC_QUIRKS
3789/*
3790 * Lenovo Thinkpad T61/X61
3791 */
3792static const struct hda_input_mux ad1984_thinkpad_capture_source = {
3793 .num_items = 4,
3794 .items = {
3795 { "Mic", 0x0 },
3796 { "Internal Mic", 0x1 },
3797 { "Mix", 0x3 },
3798 { "Dock Mic", 0x4 },
3799 },
3800};
3801
3802
3803/*
3804 * Dell Precision T3400
3805 */
3806static const struct hda_input_mux ad1984_dell_desktop_capture_source = {
3807 .num_items = 3,
3808 .items = {
3809 { "Front Mic", 0x0 },
3810 { "Line-In", 0x1 },
3811 { "Mix", 0x3 },
3812 },
3813};
3814
3815
3816static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3817 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3818 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3819 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3820 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3821 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3822 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3823 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3824 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3825 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3826 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3827 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3828 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3829 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3830 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3831 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3832 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3833 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3834 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3835 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3836 {
3837 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3838 /* The multiple "Capture Source" controls confuse alsamixer
3839 * So call somewhat different..
3840 */
3841 /* .name = "Capture Source", */
3842 .name = "Input Source",
3843 .count = 2,
3844 .info = ad198x_mux_enum_info,
3845 .get = ad198x_mux_enum_get,
3846 .put = ad198x_mux_enum_put,
3847 },
3848 /* SPDIF controls */
3849 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3850 {
3851 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3852 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3853 /* identical with ad1983 */
3854 .info = ad1983_spdif_route_info,
3855 .get = ad1983_spdif_route_get,
3856 .put = ad1983_spdif_route_put,
3857 },
3858 { } /* end */
3859};
3860
3861/* additional verbs */
3862static const struct hda_verb ad1984_thinkpad_init_verbs[] = {
3863 /* Port-E (docking station mic) pin */
3864 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3865 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3866 /* docking mic boost */
3867 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3868 /* Analog PC Beeper - allow firmware/ACPI beeps */
3869 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a},
3870 /* Analog mixer - docking mic; mute as default */
3871 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3872 /* enable EAPD bit */
3873 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3874 { } /* end */
3875};
3876
3877/*
3878 * Dell Precision T3400
3879 */
3880static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3881 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3882 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3883 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3884 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3885 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3886 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3887 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3888 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3889 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3890 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT),
3891 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3892 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3893 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3894 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3895 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3896 {
3897 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3898 /* The multiple "Capture Source" controls confuse alsamixer
3899 * So call somewhat different..
3900 */
3901 /* .name = "Capture Source", */
3902 .name = "Input Source",
3903 .count = 2,
3904 .info = ad198x_mux_enum_info,
3905 .get = ad198x_mux_enum_get,
3906 .put = ad198x_mux_enum_put,
3907 },
3908 { } /* end */
3909};
3910
3911/* Digial MIC ADC NID 0x05 + 0x06 */
3912static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3913 struct hda_codec *codec,
3914 unsigned int stream_tag,
3915 unsigned int format,
3916 struct snd_pcm_substream *substream)
3917{
3918 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3919 stream_tag, 0, format);
3920 return 0;
3921}
3922
3923static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3924 struct hda_codec *codec,
3925 struct snd_pcm_substream *substream)
3926{
3927 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3928 return 0;
3929}
3930
3931static const struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3932 .substreams = 2,
3933 .channels_min = 2,
3934 .channels_max = 2,
3935 .nid = 0x05,
3936 .ops = {
3937 .prepare = ad1984_pcm_dmic_prepare,
3938 .cleanup = ad1984_pcm_dmic_cleanup
3939 },
3940};
3941
3942static int ad1984_build_pcms(struct hda_codec *codec)
3943{
3944 struct ad198x_spec *spec = codec->spec;
3945 struct hda_pcm *info;
3946 int err;
3947
3948 err = ad198x_build_pcms(codec);
3949 if (err < 0)
3950 return err;
3951
3952 info = spec->pcm_rec + codec->num_pcms;
3953 codec->num_pcms++;
3954 info->name = "AD1984 Digital Mic";
3955 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3956 return 0;
3957}
3958
3959/* models */
3960enum {
3961 AD1984_AUTO,
3962 AD1984_BASIC,
3963 AD1984_THINKPAD,
3964 AD1984_DELL_DESKTOP,
3965 AD1984_MODELS
3966};
3967
3968static const char * const ad1984_models[AD1984_MODELS] = {
3969 [AD1984_AUTO] = "auto",
3970 [AD1984_BASIC] = "basic",
3971 [AD1984_THINKPAD] = "thinkpad",
3972 [AD1984_DELL_DESKTOP] = "dell_desktop",
3973};
3974
3975static const struct snd_pci_quirk ad1984_cfg_tbl[] = {
3976 /* Lenovo Thinkpad T61/X61 */
3977 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3978 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3979 SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
3980 {}
3981};
3982
3983static int patch_ad1984(struct hda_codec *codec)
3984{
3985 struct ad198x_spec *spec;
3986 int board_config, err;
3987
3988 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3989 ad1984_models, ad1984_cfg_tbl);
3990 if (board_config < 0) {
3991 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3992 codec->chip_name);
3993 board_config = AD1984_AUTO;
3994 }
3995
3996 if (board_config == AD1984_AUTO)
3997 return ad1884_parse_auto_config(codec);
3998
3999 err = patch_ad1884_basic(codec);
4000 if (err < 0)
4001 return err;
4002 spec = codec->spec;
4003
4004 switch (board_config) {
4005 case AD1984_BASIC:
4006 /* additional digital mics */
4007 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
4008 codec->patch_ops.build_pcms = ad1984_build_pcms;
4009 break;
4010 case AD1984_THINKPAD:
4011 if (codec->subsystem_id == 0x17aa20fb) {
4012 /* Thinpad X300 does not have the ability to do SPDIF,
4013 or attach to docking station to use SPDIF */
4014 spec->multiout.dig_out_nid = 0;
4015 } else
4016 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
4017 spec->input_mux = &ad1984_thinkpad_capture_source;
4018 spec->mixers[0] = ad1984_thinkpad_mixers;
4019 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
4020 spec->analog_beep = 1;
4021 break;
4022 case AD1984_DELL_DESKTOP:
4023 spec->multiout.dig_out_nid = 0;
4024 spec->input_mux = &ad1984_dell_desktop_capture_source;
4025 spec->mixers[0] = ad1984_dell_desktop_mixers;
4026 break;
4027 }
4028 return 0;
4029}
4030#else /* ENABLE_AD_STATIC_QUIRKS */
4031#define patch_ad1984 ad1884_parse_auto_config
4032#endif /* ENABLE_AD_STATIC_QUIRKS */
4033
4034
4035/*
4036 * AD1883 / AD1884A / AD1984A / AD1984B
4037 *
4038 * port-B (0x14) - front mic-in
4039 * port-E (0x1c) - rear mic-in
4040 * port-F (0x16) - CD / ext out
4041 * port-C (0x15) - rear line-in
4042 * port-D (0x12) - rear line-out
4043 * port-A (0x11) - front hp-out
4044 *
4045 * AD1984A = AD1884A + digital-mic
4046 * AD1883 = equivalent with AD1984A
4047 * AD1984B = AD1984A + extra SPDIF-out
4048 *
4049 * FIXME:
4050 * We share the single DAC for both HP and line-outs (see AD1884/1984).
4051 */
4052
4053#ifdef ENABLE_AD_STATIC_QUIRKS
4054static const hda_nid_t ad1884a_dac_nids[1] = {
4055 0x03,
4056};
4057
4058#define ad1884a_adc_nids ad1884_adc_nids
4059#define ad1884a_capsrc_nids ad1884_capsrc_nids
4060
4061#define AD1884A_SPDIF_OUT 0x02
4062
4063static const struct hda_input_mux ad1884a_capture_source = {
4064 .num_items = 5,
4065 .items = {
4066 { "Front Mic", 0x0 },
4067 { "Mic", 0x4 },
4068 { "Line", 0x1 },
4069 { "CD", 0x2 },
4070 { "Mix", 0x3 },
4071 },
4072};
4073
4074static const struct snd_kcontrol_new ad1884a_base_mixers[] = {
4075 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4076 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4077 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4078 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4079 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4080 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4081 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4082 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4083 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4084 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4085 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4086 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4087 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4088 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4089 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
4090 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
4091 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4092 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT),
4093 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4094 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4095 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4096 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4097 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4098 {
4099 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4100 /* The multiple "Capture Source" controls confuse alsamixer
4101 * So call somewhat different..
4102 */
4103 /* .name = "Capture Source", */
4104 .name = "Input Source",
4105 .count = 2,
4106 .info = ad198x_mux_enum_info,
4107 .get = ad198x_mux_enum_get,
4108 .put = ad198x_mux_enum_put,
4109 },
4110 /* SPDIF controls */
4111 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4112 {
4113 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4114 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4115 /* identical with ad1983 */
4116 .info = ad1983_spdif_route_info,
4117 .get = ad1983_spdif_route_get,
4118 .put = ad1983_spdif_route_put,
4119 },
4120 { } /* end */
4121};
4122
4123/*
4124 * initialization verbs
4125 */
4126static const struct hda_verb ad1884a_init_verbs[] = {
4127 /* DACs; unmute as default */
4128 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4129 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4130 /* Port-A (HP) mixer - route only from analog mixer */
4131 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4132 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4133 /* Port-A pin */
4134 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4135 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4136 /* Port-D (Line-out) mixer - route only from analog mixer */
4137 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4138 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4139 /* Port-D pin */
4140 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4141 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4142 /* Mono-out mixer - route only from analog mixer */
4143 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4144 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4145 /* Mono-out pin */
4146 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4147 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4148 /* Port-B (front mic) pin */
4149 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4150 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4151 /* Port-C (rear line-in) pin */
4152 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4153 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4154 /* Port-E (rear mic) pin */
4155 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4156 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4157 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
4158 /* Port-F (CD) pin */
4159 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4160 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4161 /* Analog mixer; mute as default */
4162 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4163 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4164 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4165 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4166 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
4167 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4168 /* Analog Mix output amp */
4169 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4170 /* capture sources */
4171 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
4172 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4173 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4174 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4175 /* SPDIF output amp */
4176 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4177 { } /* end */
4178};
4179
4180#ifdef CONFIG_PM
4181static const struct hda_amp_list ad1884a_loopbacks[] = {
4182 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4183 { 0x20, HDA_INPUT, 1 }, /* Mic */
4184 { 0x20, HDA_INPUT, 2 }, /* CD */
4185 { 0x20, HDA_INPUT, 4 }, /* Docking */
4186 { } /* end */
4187};
4188#endif
4189
4190/*
4191 * Laptop model
4192 *
4193 * Port A: Headphone jack
4194 * Port B: MIC jack
4195 * Port C: Internal MIC
4196 * Port D: Dock Line Out (if enabled)
4197 * Port E: Dock Line In (if enabled)
4198 * Port F: Internal speakers
4199 */
4200
4201static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
4202 struct snd_ctl_elem_value *ucontrol)
4203{
4204 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4205 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
4206 int mute = (!ucontrol->value.integer.value[0] &&
4207 !ucontrol->value.integer.value[1]);
4208 /* toggle GPIO1 according to the mute state */
4209 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
4210 mute ? 0x02 : 0x0);
4211 return ret;
4212}
4213
4214static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
4215 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4216 {
4217 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4218 .name = "Master Playback Switch",
4219 .subdevice = HDA_SUBDEV_AMP_FLAG,
4220 .info = snd_hda_mixer_amp_switch_info,
4221 .get = snd_hda_mixer_amp_switch_get,
4222 .put = ad1884a_mobile_master_sw_put,
4223 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4224 },
4225 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4226 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4227 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4228 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4229 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4230 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4231 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4232 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4233 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4234 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4235 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
4236 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4237 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4238 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4239 { } /* end */
4240};
4241
4242static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
4243 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4244 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4245 {
4246 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4247 .name = "Master Playback Switch",
4248 .subdevice = HDA_SUBDEV_AMP_FLAG,
4249 .info = snd_hda_mixer_amp_switch_info,
4250 .get = snd_hda_mixer_amp_switch_get,
4251 .put = ad1884a_mobile_master_sw_put,
4252 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4253 },
4254 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4255 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4256 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
4257 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
4258 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4259 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4260 { } /* end */
4261};
4262
4263/* mute internal speaker if HP is plugged */
4264static void ad1884a_hp_automute(struct hda_codec *codec)
4265{
4266 unsigned int present;
4267
4268 present = snd_hda_jack_detect(codec, 0x11);
4269 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4270 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4271 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4272 present ? 0x00 : 0x02);
4273}
4274
4275/* switch to external mic if plugged */
4276static void ad1884a_hp_automic(struct hda_codec *codec)
4277{
4278 unsigned int present;
4279
4280 present = snd_hda_jack_detect(codec, 0x14);
4281 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
4282 present ? 0 : 1);
4283}
4284
4285#define AD1884A_HP_EVENT 0x37
4286#define AD1884A_MIC_EVENT 0x36
4287
4288/* unsolicited event for HP jack sensing */
4289static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
4290{
4291 switch (res >> 26) {
4292 case AD1884A_HP_EVENT:
4293 ad1884a_hp_automute(codec);
4294 break;
4295 case AD1884A_MIC_EVENT:
4296 ad1884a_hp_automic(codec);
4297 break;
4298 }
4299}
4300
4301/* initialize jack-sensing, too */
4302static int ad1884a_hp_init(struct hda_codec *codec)
4303{
4304 ad198x_init(codec);
4305 ad1884a_hp_automute(codec);
4306 ad1884a_hp_automic(codec);
4307 return 0;
4308}
4309
4310/* mute internal speaker if HP or docking HP is plugged */
4311static void ad1884a_laptop_automute(struct hda_codec *codec)
4312{
4313 unsigned int present;
4314
4315 present = snd_hda_jack_detect(codec, 0x11);
4316 if (!present)
4317 present = snd_hda_jack_detect(codec, 0x12);
4318 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4319 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4320 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4321 present ? 0x00 : 0x02);
4322}
4323
4324/* switch to external mic if plugged */
4325static void ad1884a_laptop_automic(struct hda_codec *codec)
4326{
4327 unsigned int idx;
4328
4329 if (snd_hda_jack_detect(codec, 0x14))
4330 idx = 0;
4331 else if (snd_hda_jack_detect(codec, 0x1c))
4332 idx = 4;
4333 else
4334 idx = 1;
4335 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
4336}
4337
4338/* unsolicited event for HP jack sensing */
4339static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
4340 unsigned int res)
4341{
4342 switch (res >> 26) {
4343 case AD1884A_HP_EVENT:
4344 ad1884a_laptop_automute(codec);
4345 break;
4346 case AD1884A_MIC_EVENT:
4347 ad1884a_laptop_automic(codec);
4348 break;
4349 }
4350}
4351
4352/* initialize jack-sensing, too */
4353static int ad1884a_laptop_init(struct hda_codec *codec)
4354{
4355 ad198x_init(codec);
4356 ad1884a_laptop_automute(codec);
4357 ad1884a_laptop_automic(codec);
4358 return 0;
4359}
4360
4361/* additional verbs for laptop model */
4362static const struct hda_verb ad1884a_laptop_verbs[] = {
4363 /* Port-A (HP) pin - always unmuted */
4364 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4365 /* Port-F (int speaker) mixer - route only from analog mixer */
4366 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4367 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4368 /* Port-F (int speaker) pin */
4369 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4370 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4371 /* required for compaq 6530s/6531s speaker output */
4372 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4373 /* Port-C pin - internal mic-in */
4374 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4375 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4376 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4377 /* Port-D (docking line-out) pin - default unmuted */
4378 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4379 /* analog mix */
4380 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4381 /* unsolicited event for pin-sense */
4382 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4383 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4384 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4385 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4386 /* allow to touch GPIO1 (for mute control) */
4387 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4388 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4389 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4390 { } /* end */
4391};
4392
4393static const struct hda_verb ad1884a_mobile_verbs[] = {
4394 /* DACs; unmute as default */
4395 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4396 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4397 /* Port-A (HP) mixer - route only from analog mixer */
4398 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4399 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4400 /* Port-A pin */
4401 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4402 /* Port-A (HP) pin - always unmuted */
4403 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4404 /* Port-B (mic jack) pin */
4405 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4406 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4407 /* Port-C (int mic) pin */
4408 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4409 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4410 /* Port-F (int speaker) mixer - route only from analog mixer */
4411 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4412 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4413 /* Port-F pin */
4414 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4415 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4416 /* Analog mixer; mute as default */
4417 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4418 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4419 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4420 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4421 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4422 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4423 /* Analog Mix output amp */
4424 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4425 /* capture sources */
4426 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4427 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4428 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4429 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4430 /* unsolicited event for pin-sense */
4431 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4432 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4433 /* allow to touch GPIO1 (for mute control) */
4434 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4435 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4436 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4437 { } /* end */
4438};
4439
4440/*
4441 * Thinkpad X300
4442 * 0x11 - HP
4443 * 0x12 - speaker
4444 * 0x14 - mic-in
4445 * 0x17 - built-in mic
4446 */
4447
4448static const struct hda_verb ad1984a_thinkpad_verbs[] = {
4449 /* HP unmute */
4450 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4451 /* analog mix */
4452 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4453 /* turn on EAPD */
4454 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4455 /* unsolicited event for pin-sense */
4456 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4457 /* internal mic - dmic */
4458 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4459 /* set magic COEFs for dmic */
4460 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4461 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4462 { } /* end */
4463};
4464
4465static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4466 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4467 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4468 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4469 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4470 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4471 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4472 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4473 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4474 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4475 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4476 {
4477 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4478 .name = "Capture Source",
4479 .info = ad198x_mux_enum_info,
4480 .get = ad198x_mux_enum_get,
4481 .put = ad198x_mux_enum_put,
4482 },
4483 { } /* end */
4484};
4485
4486static const struct hda_input_mux ad1984a_thinkpad_capture_source = {
4487 .num_items = 3,
4488 .items = {
4489 { "Mic", 0x0 },
4490 { "Internal Mic", 0x5 },
4491 { "Mix", 0x3 },
4492 },
4493};
4494
4495/* mute internal speaker if HP is plugged */
4496static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4497{
4498 unsigned int present;
4499
4500 present = snd_hda_jack_detect(codec, 0x11);
4501 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4502 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4503}
4504
4505/* unsolicited event for HP jack sensing */
4506static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4507 unsigned int res)
4508{
4509 if ((res >> 26) != AD1884A_HP_EVENT)
4510 return;
4511 ad1984a_thinkpad_automute(codec);
4512}
4513
4514/* initialize jack-sensing, too */
4515static int ad1984a_thinkpad_init(struct hda_codec *codec)
4516{
4517 ad198x_init(codec);
4518 ad1984a_thinkpad_automute(codec);
4519 return 0;
4520}
4521
4522/*
4523 * Precision R5500
4524 * 0x12 - HP/line-out
4525 * 0x13 - speaker (mono)
4526 * 0x15 - mic-in
4527 */
4528
4529static const struct hda_verb ad1984a_precision_verbs[] = {
4530 /* Unmute main output path */
4531 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4532 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
4533 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
4534 /* Analog mixer; mute as default */
4535 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4536 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4537 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4538 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4539 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4540 /* Select mic as input */
4541 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
4542 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */
4543 /* Configure as mic */
4544 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4545 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4546 /* HP unmute */
4547 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4548 /* turn on EAPD */
4549 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4550 /* unsolicited event for pin-sense */
4551 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4552 { } /* end */
4553};
4554
4555static const struct snd_kcontrol_new ad1984a_precision_mixers[] = {
4556 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4557 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4558 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4559 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4560 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4561 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4562 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
4563 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4564 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT),
4565 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4566 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4567 { } /* end */
4568};
4569
4570
4571/* mute internal speaker if HP is plugged */
4572static void ad1984a_precision_automute(struct hda_codec *codec)
4573{
4574 unsigned int present;
4575
4576 present = snd_hda_jack_detect(codec, 0x12);
4577 snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
4578 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4579}
4580
4581
4582/* unsolicited event for HP jack sensing */
4583static void ad1984a_precision_unsol_event(struct hda_codec *codec,
4584 unsigned int res)
4585{
4586 if ((res >> 26) != AD1884A_HP_EVENT)
4587 return;
4588 ad1984a_precision_automute(codec);
4589}
4590
4591/* initialize jack-sensing, too */
4592static int ad1984a_precision_init(struct hda_codec *codec)
4593{
4594 ad198x_init(codec);
4595 ad1984a_precision_automute(codec);
4596 return 0;
4597}
4598
4599
4600/*
4601 * HP Touchsmart
4602 * port-A (0x11) - front hp-out
4603 * port-B (0x14) - unused
4604 * port-C (0x15) - unused
4605 * port-D (0x12) - rear line out
4606 * port-E (0x1c) - front mic-in
4607 * port-F (0x16) - Internal speakers
4608 * digital-mic (0x17) - Internal mic
4609 */
4610
4611static const struct hda_verb ad1984a_touchsmart_verbs[] = {
4612 /* DACs; unmute as default */
4613 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4614 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4615 /* Port-A (HP) mixer - route only from analog mixer */
4616 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4617 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4618 /* Port-A pin */
4619 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4620 /* Port-A (HP) pin - always unmuted */
4621 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4622 /* Port-E (int speaker) mixer - route only from analog mixer */
4623 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4624 /* Port-E pin */
4625 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4626 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4627 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4628 /* Port-F (int speaker) mixer - route only from analog mixer */
4629 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4630 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4631 /* Port-F pin */
4632 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4633 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4634 /* Analog mixer; mute as default */
4635 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4636 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4637 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4638 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4639 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4640 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4641 /* Analog Mix output amp */
4642 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4643 /* capture sources */
4644 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4645 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4646 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4647 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4648 /* unsolicited event for pin-sense */
4649 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4650 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4651 /* allow to touch GPIO1 (for mute control) */
4652 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4653 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4654 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4655 /* internal mic - dmic */
4656 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4657 /* set magic COEFs for dmic */
4658 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4659 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4660 { } /* end */
4661};
4662
4663static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4664 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4665/* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4666 {
4667 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4668 .subdevice = HDA_SUBDEV_AMP_FLAG,
4669 .name = "Master Playback Switch",
4670 .info = snd_hda_mixer_amp_switch_info,
4671 .get = snd_hda_mixer_amp_switch_get,
4672 .put = ad1884a_mobile_master_sw_put,
4673 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4674 },
4675 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4676 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4677 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4678 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4679 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4680 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4681 { } /* end */
4682};
4683
4684/* switch to external mic if plugged */
4685static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4686{
4687 if (snd_hda_jack_detect(codec, 0x1c))
4688 snd_hda_codec_write(codec, 0x0c, 0,
4689 AC_VERB_SET_CONNECT_SEL, 0x4);
4690 else
4691 snd_hda_codec_write(codec, 0x0c, 0,
4692 AC_VERB_SET_CONNECT_SEL, 0x5);
4693}
4694
4695
4696/* unsolicited event for HP jack sensing */
4697static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4698 unsigned int res)
4699{
4700 switch (res >> 26) {
4701 case AD1884A_HP_EVENT:
4702 ad1884a_hp_automute(codec);
4703 break;
4704 case AD1884A_MIC_EVENT:
4705 ad1984a_touchsmart_automic(codec);
4706 break;
4707 }
4708}
4709
4710/* initialize jack-sensing, too */
4711static int ad1984a_touchsmart_init(struct hda_codec *codec)
4712{
4713 ad198x_init(codec);
4714 ad1884a_hp_automute(codec);
4715 ad1984a_touchsmart_automic(codec);
4716 return 0;
4717}
4718
4719
4720/*
4721 */
4722
4723enum {
4724 AD1884A_AUTO,
4725 AD1884A_DESKTOP,
4726 AD1884A_LAPTOP,
4727 AD1884A_MOBILE,
4728 AD1884A_THINKPAD,
4729 AD1984A_TOUCHSMART,
4730 AD1984A_PRECISION,
4731 AD1884A_MODELS
4732};
4733
4734static const char * const ad1884a_models[AD1884A_MODELS] = {
4735 [AD1884A_AUTO] = "auto",
4736 [AD1884A_DESKTOP] = "desktop",
4737 [AD1884A_LAPTOP] = "laptop",
4738 [AD1884A_MOBILE] = "mobile",
4739 [AD1884A_THINKPAD] = "thinkpad",
4740 [AD1984A_TOUCHSMART] = "touchsmart",
4741 [AD1984A_PRECISION] = "precision",
4742};
4743
4744static const struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4745 SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
4746 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4747 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4748 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4749 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4750 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4751 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4752 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4753 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4754 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4755 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4756 {}
4757};
4758
4759static int patch_ad1884a(struct hda_codec *codec)
4760{
4761 struct ad198x_spec *spec;
4762 int err, board_config;
4763
4764 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4765 ad1884a_models,
4766 ad1884a_cfg_tbl);
4767 if (board_config < 0) {
4768 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4769 codec->chip_name);
4770 board_config = AD1884A_AUTO;
4771 }
4772
4773 if (board_config == AD1884A_AUTO)
4774 return ad1884_parse_auto_config(codec);
4775
4776 err = alloc_ad_spec(codec);
4777 if (err < 0)
4778 return err;
4779 spec = codec->spec;
4780
4781 err = snd_hda_attach_beep_device(codec, 0x10);
4782 if (err < 0) {
4783 ad198x_free(codec);
4784 return err;
4785 }
4786 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4787
4788 spec->multiout.max_channels = 2;
4789 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4790 spec->multiout.dac_nids = ad1884a_dac_nids;
4791 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4792 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4793 spec->adc_nids = ad1884a_adc_nids;
4794 spec->capsrc_nids = ad1884a_capsrc_nids;
4795 spec->input_mux = &ad1884a_capture_source;
4796 spec->num_mixers = 1;
4797 spec->mixers[0] = ad1884a_base_mixers;
4798 spec->num_init_verbs = 1;
4799 spec->init_verbs[0] = ad1884a_init_verbs;
4800 spec->spdif_route = 0;
4801#ifdef CONFIG_PM
4802 spec->loopback.amplist = ad1884a_loopbacks;
4803#endif
4804 codec->patch_ops = ad198x_patch_ops;
4805
4806 /* override some parameters */
4807 switch (board_config) {
4808 case AD1884A_LAPTOP:
4809 spec->mixers[0] = ad1884a_laptop_mixers;
4810 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4811 spec->multiout.dig_out_nid = 0;
4812 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4813 codec->patch_ops.init = ad1884a_laptop_init;
4814 /* set the upper-limit for mixer amp to 0dB for avoiding the
4815 * possible damage by overloading
4816 */
4817 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4818 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4819 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4820 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4821 (1 << AC_AMPCAP_MUTE_SHIFT));
4822 break;
4823 case AD1884A_MOBILE:
4824 spec->mixers[0] = ad1884a_mobile_mixers;
4825 spec->init_verbs[0] = ad1884a_mobile_verbs;
4826 spec->multiout.dig_out_nid = 0;
4827 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4828 codec->patch_ops.init = ad1884a_hp_init;
4829 /* set the upper-limit for mixer amp to 0dB for avoiding the
4830 * possible damage by overloading
4831 */
4832 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4833 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4834 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4835 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4836 (1 << AC_AMPCAP_MUTE_SHIFT));
4837 break;
4838 case AD1884A_THINKPAD:
4839 spec->mixers[0] = ad1984a_thinkpad_mixers;
4840 spec->init_verbs[spec->num_init_verbs++] =
4841 ad1984a_thinkpad_verbs;
4842 spec->multiout.dig_out_nid = 0;
4843 spec->input_mux = &ad1984a_thinkpad_capture_source;
4844 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4845 codec->patch_ops.init = ad1984a_thinkpad_init;
4846 break;
4847 case AD1984A_PRECISION:
4848 spec->mixers[0] = ad1984a_precision_mixers;
4849 spec->init_verbs[spec->num_init_verbs++] =
4850 ad1984a_precision_verbs;
4851 spec->multiout.dig_out_nid = 0;
4852 codec->patch_ops.unsol_event = ad1984a_precision_unsol_event;
4853 codec->patch_ops.init = ad1984a_precision_init;
4854 break;
4855 case AD1984A_TOUCHSMART:
4856 spec->mixers[0] = ad1984a_touchsmart_mixers;
4857 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4858 spec->multiout.dig_out_nid = 0;
4859 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4860 codec->patch_ops.init = ad1984a_touchsmart_init;
4861 /* set the upper-limit for mixer amp to 0dB for avoiding the
4862 * possible damage by overloading
4863 */
4864 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4865 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4866 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4867 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4868 (1 << AC_AMPCAP_MUTE_SHIFT));
4869 break;
4870 }
4871
4872 codec->no_trigger_sense = 1;
4873 codec->no_sticky_stream = 1;
4874
4875 return 0;
4876}
4877#else /* ENABLE_AD_STATIC_QUIRKS */
4878#define patch_ad1884a ad1884_parse_auto_config
4879#endif /* ENABLE_AD_STATIC_QUIRKS */
4880
4881
4882/* 3570/*
4883 * AD1882 / AD1882A 3571 * AD1882 / AD1882A
4884 * 3572 *
@@ -4923,15 +3611,15 @@ static int patch_ad1882(struct hda_codec *codec)
4923 * patch entries 3611 * patch entries
4924 */ 3612 */
4925static const struct hda_codec_preset snd_hda_preset_analog[] = { 3613static const struct hda_codec_preset snd_hda_preset_analog[] = {
4926 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a }, 3614 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884 },
4927 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 }, 3615 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4928 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a }, 3616 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884 },
4929 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 }, 3617 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4930 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a }, 3618 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884 },
4931 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a }, 3619 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884 },
4932 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, 3620 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4933 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, 3621 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4934 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 }, 3622 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1884 },
4935 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, 3623 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4936 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, 3624 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4937 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, 3625 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },