diff options
-rw-r--r-- | Documentation/sound/alsa/ALSA-Configuration.txt | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 94 |
2 files changed, 95 insertions, 0 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index b02404395e52..42dd8f5855da 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt | |||
@@ -923,6 +923,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
923 | desktop 3-stack desktop (default) | 923 | desktop 3-stack desktop (default) |
924 | laptop laptop with HP jack sensing | 924 | laptop laptop with HP jack sensing |
925 | mobile mobile devices with HP jack sensing | 925 | mobile mobile devices with HP jack sensing |
926 | thinkpad Lenovo Thinkpad X300 | ||
926 | 927 | ||
927 | AD1884 | 928 | AD1884 |
928 | N/A | 929 | N/A |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 220784bb76a7..2befeebd909e 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -3702,12 +3702,95 @@ static struct hda_verb ad1884a_laptop_verbs[] = { | |||
3702 | }; | 3702 | }; |
3703 | 3703 | ||
3704 | /* | 3704 | /* |
3705 | * Thinkpad X300 | ||
3706 | * 0x11 - HP | ||
3707 | * 0x12 - speaker | ||
3708 | * 0x14 - mic-in | ||
3709 | * 0x17 - built-in mic | ||
3710 | */ | ||
3711 | |||
3712 | static struct hda_verb ad1984a_thinkpad_verbs[] = { | ||
3713 | /* HP unmute */ | ||
3714 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3715 | /* analog mix */ | ||
3716 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
3717 | /* turn on EAPD */ | ||
3718 | {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | ||
3719 | /* unsolicited event for pin-sense */ | ||
3720 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, | ||
3721 | /* internal mic - dmic */ | ||
3722 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
3723 | { } /* end */ | ||
3724 | }; | ||
3725 | |||
3726 | static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = { | ||
3727 | HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), | ||
3728 | HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), | ||
3729 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), | ||
3730 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | ||
3731 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), | ||
3732 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | ||
3733 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3734 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3735 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | ||
3736 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), | ||
3737 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
3738 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | ||
3739 | { | ||
3740 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3741 | .name = "Capture Source", | ||
3742 | .info = ad198x_mux_enum_info, | ||
3743 | .get = ad198x_mux_enum_get, | ||
3744 | .put = ad198x_mux_enum_put, | ||
3745 | }, | ||
3746 | { } /* end */ | ||
3747 | }; | ||
3748 | |||
3749 | static struct hda_input_mux ad1984a_thinkpad_capture_source = { | ||
3750 | .num_items = 3, | ||
3751 | .items = { | ||
3752 | { "Mic", 0x0 }, | ||
3753 | { "Internal Mic", 0x5 }, | ||
3754 | { "Mix", 0x3 }, | ||
3755 | }, | ||
3756 | }; | ||
3757 | |||
3758 | /* mute internal speaker if HP is plugged */ | ||
3759 | static void ad1984a_thinkpad_automute(struct hda_codec *codec) | ||
3760 | { | ||
3761 | unsigned int present; | ||
3762 | |||
3763 | present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) | ||
3764 | & AC_PINSENSE_PRESENCE; | ||
3765 | snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0, | ||
3766 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
3767 | } | ||
3768 | |||
3769 | /* unsolicited event for HP jack sensing */ | ||
3770 | static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec, | ||
3771 | unsigned int res) | ||
3772 | { | ||
3773 | if ((res >> 26) != AD1884A_HP_EVENT) | ||
3774 | return; | ||
3775 | ad1984a_thinkpad_automute(codec); | ||
3776 | } | ||
3777 | |||
3778 | /* initialize jack-sensing, too */ | ||
3779 | static int ad1984a_thinkpad_init(struct hda_codec *codec) | ||
3780 | { | ||
3781 | ad198x_init(codec); | ||
3782 | ad1984a_thinkpad_automute(codec); | ||
3783 | return 0; | ||
3784 | } | ||
3785 | |||
3786 | /* | ||
3705 | */ | 3787 | */ |
3706 | 3788 | ||
3707 | enum { | 3789 | enum { |
3708 | AD1884A_DESKTOP, | 3790 | AD1884A_DESKTOP, |
3709 | AD1884A_LAPTOP, | 3791 | AD1884A_LAPTOP, |
3710 | AD1884A_MOBILE, | 3792 | AD1884A_MOBILE, |
3793 | AD1884A_THINKPAD, | ||
3711 | AD1884A_MODELS | 3794 | AD1884A_MODELS |
3712 | }; | 3795 | }; |
3713 | 3796 | ||
@@ -3715,10 +3798,12 @@ static const char *ad1884a_models[AD1884A_MODELS] = { | |||
3715 | [AD1884A_DESKTOP] = "desktop", | 3798 | [AD1884A_DESKTOP] = "desktop", |
3716 | [AD1884A_LAPTOP] = "laptop", | 3799 | [AD1884A_LAPTOP] = "laptop", |
3717 | [AD1884A_MOBILE] = "mobile", | 3800 | [AD1884A_MOBILE] = "mobile", |
3801 | [AD1884A_THINKPAD] = "thinkpad", | ||
3718 | }; | 3802 | }; |
3719 | 3803 | ||
3720 | static struct snd_pci_quirk ad1884a_cfg_tbl[] = { | 3804 | static struct snd_pci_quirk ad1884a_cfg_tbl[] = { |
3721 | SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), | 3805 | SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), |
3806 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), | ||
3722 | {} | 3807 | {} |
3723 | }; | 3808 | }; |
3724 | 3809 | ||
@@ -3773,6 +3858,15 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
3773 | codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; | 3858 | codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; |
3774 | codec->patch_ops.init = ad1884a_hp_init; | 3859 | codec->patch_ops.init = ad1884a_hp_init; |
3775 | break; | 3860 | break; |
3861 | case AD1884A_THINKPAD: | ||
3862 | spec->mixers[0] = ad1984a_thinkpad_mixers; | ||
3863 | spec->init_verbs[spec->num_init_verbs++] = | ||
3864 | ad1984a_thinkpad_verbs; | ||
3865 | spec->multiout.dig_out_nid = 0; | ||
3866 | spec->input_mux = &ad1984a_thinkpad_capture_source; | ||
3867 | codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; | ||
3868 | codec->patch_ops.init = ad1984a_thinkpad_init; | ||
3869 | break; | ||
3776 | } | 3870 | } |
3777 | 3871 | ||
3778 | return 0; | 3872 | return 0; |