diff options
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r-- | sound/pci/hda/patch_analog.c | 406 |
1 files changed, 317 insertions, 89 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 84cc49ca914..2d603f6aba6 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -72,6 +72,7 @@ struct ad198x_spec { | |||
72 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 72 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
73 | 73 | ||
74 | unsigned int jack_present :1; | 74 | unsigned int jack_present :1; |
75 | unsigned int inv_jack_detect:1; | ||
75 | 76 | ||
76 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 77 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
77 | struct hda_loopback_check loopback; | 78 | struct hda_loopback_check loopback; |
@@ -669,39 +670,13 @@ static struct hda_input_mux ad1986a_automic_capture_source = { | |||
669 | }, | 670 | }, |
670 | }; | 671 | }; |
671 | 672 | ||
672 | static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | 673 | static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = { |
673 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), | 674 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), |
674 | HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), | 675 | HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), |
675 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
676 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | ||
677 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT), | ||
678 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT), | ||
679 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
680 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
681 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | ||
682 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | ||
683 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | ||
684 | { | ||
685 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
686 | .name = "Capture Source", | ||
687 | .info = ad198x_mux_enum_info, | ||
688 | .get = ad198x_mux_enum_get, | ||
689 | .put = ad198x_mux_enum_put, | ||
690 | }, | ||
691 | { | ||
692 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
693 | .name = "External Amplifier", | ||
694 | .info = ad198x_eapd_info, | ||
695 | .get = ad198x_eapd_get, | ||
696 | .put = ad198x_eapd_put, | ||
697 | .private_value = 0x1b | (1 << 8), /* port-D, inversed */ | ||
698 | }, | ||
699 | { } /* end */ | 676 | { } /* end */ |
700 | }; | 677 | }; |
701 | 678 | ||
702 | static struct snd_kcontrol_new ad1986a_samsung_mixers[] = { | 679 | static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { |
703 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), | ||
704 | HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), | ||
705 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | 680 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
706 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | 681 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), |
707 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 682 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
@@ -727,6 +702,12 @@ static struct snd_kcontrol_new ad1986a_samsung_mixers[] = { | |||
727 | { } /* end */ | 702 | { } /* end */ |
728 | }; | 703 | }; |
729 | 704 | ||
705 | static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = { | ||
706 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT), | ||
707 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT), | ||
708 | { } /* end */ | ||
709 | }; | ||
710 | |||
730 | /* re-connect the mic boost input according to the jack sensing */ | 711 | /* re-connect the mic boost input according to the jack sensing */ |
731 | static void ad1986a_automic(struct hda_codec *codec) | 712 | static void ad1986a_automic(struct hda_codec *codec) |
732 | { | 713 | { |
@@ -776,8 +757,9 @@ static void ad1986a_hp_automute(struct hda_codec *codec) | |||
776 | unsigned int present; | 757 | unsigned int present; |
777 | 758 | ||
778 | present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); | 759 | present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); |
779 | /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */ | 760 | spec->jack_present = !!(present & 0x80000000); |
780 | spec->jack_present = !(present & 0x80000000); | 761 | if (spec->inv_jack_detect) |
762 | spec->jack_present = !spec->jack_present; | ||
781 | ad1986a_update_hp(codec); | 763 | ad1986a_update_hp(codec); |
782 | } | 764 | } |
783 | 765 | ||
@@ -816,7 +798,7 @@ static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
816 | return change; | 798 | return change; |
817 | } | 799 | } |
818 | 800 | ||
819 | static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = { | 801 | static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = { |
820 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), | 802 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), |
821 | { | 803 | { |
822 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 804 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -826,33 +808,10 @@ static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = { | |||
826 | .put = ad1986a_hp_master_sw_put, | 808 | .put = ad1986a_hp_master_sw_put, |
827 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | 809 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), |
828 | }, | 810 | }, |
829 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
830 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | ||
831 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), | ||
832 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), | ||
833 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
834 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
835 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | ||
836 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | ||
837 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | ||
838 | { | ||
839 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
840 | .name = "Capture Source", | ||
841 | .info = ad198x_mux_enum_info, | ||
842 | .get = ad198x_mux_enum_get, | ||
843 | .put = ad198x_mux_enum_put, | ||
844 | }, | ||
845 | { | ||
846 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
847 | .name = "External Amplifier", | ||
848 | .info = ad198x_eapd_info, | ||
849 | .get = ad198x_eapd_get, | ||
850 | .put = ad198x_eapd_put, | ||
851 | .private_value = 0x1b | (1 << 8), /* port-D, inversed */ | ||
852 | }, | ||
853 | { } /* end */ | 811 | { } /* end */ |
854 | }; | 812 | }; |
855 | 813 | ||
814 | |||
856 | /* | 815 | /* |
857 | * initialization verbs | 816 | * initialization verbs |
858 | */ | 817 | */ |
@@ -981,6 +940,27 @@ static struct hda_verb ad1986a_hp_init_verbs[] = { | |||
981 | {} | 940 | {} |
982 | }; | 941 | }; |
983 | 942 | ||
943 | static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec, | ||
944 | unsigned int res) | ||
945 | { | ||
946 | switch (res >> 26) { | ||
947 | case AD1986A_HP_EVENT: | ||
948 | ad1986a_hp_automute(codec); | ||
949 | break; | ||
950 | case AD1986A_MIC_EVENT: | ||
951 | ad1986a_automic(codec); | ||
952 | break; | ||
953 | } | ||
954 | } | ||
955 | |||
956 | static int ad1986a_samsung_p50_init(struct hda_codec *codec) | ||
957 | { | ||
958 | ad198x_init(codec); | ||
959 | ad1986a_hp_automute(codec); | ||
960 | ad1986a_automic(codec); | ||
961 | return 0; | ||
962 | } | ||
963 | |||
984 | 964 | ||
985 | /* models */ | 965 | /* models */ |
986 | enum { | 966 | enum { |
@@ -991,6 +971,7 @@ enum { | |||
991 | AD1986A_LAPTOP_AUTOMUTE, | 971 | AD1986A_LAPTOP_AUTOMUTE, |
992 | AD1986A_ULTRA, | 972 | AD1986A_ULTRA, |
993 | AD1986A_SAMSUNG, | 973 | AD1986A_SAMSUNG, |
974 | AD1986A_SAMSUNG_P50, | ||
994 | AD1986A_MODELS | 975 | AD1986A_MODELS |
995 | }; | 976 | }; |
996 | 977 | ||
@@ -1002,6 +983,7 @@ static const char *ad1986a_models[AD1986A_MODELS] = { | |||
1002 | [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute", | 983 | [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute", |
1003 | [AD1986A_ULTRA] = "ultra", | 984 | [AD1986A_ULTRA] = "ultra", |
1004 | [AD1986A_SAMSUNG] = "samsung", | 985 | [AD1986A_SAMSUNG] = "samsung", |
986 | [AD1986A_SAMSUNG_P50] = "samsung-p50", | ||
1005 | }; | 987 | }; |
1006 | 988 | ||
1007 | static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | 989 | static struct snd_pci_quirk ad1986a_cfg_tbl[] = { |
@@ -1024,6 +1006,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
1024 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), | 1006 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), |
1025 | SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), | 1007 | SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), |
1026 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), | 1008 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), |
1009 | SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50), | ||
1027 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), | 1010 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), |
1028 | SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG), | 1011 | SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG), |
1029 | SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), | 1012 | SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), |
@@ -1111,7 +1094,10 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
1111 | spec->multiout.dac_nids = ad1986a_laptop_dac_nids; | 1094 | spec->multiout.dac_nids = ad1986a_laptop_dac_nids; |
1112 | break; | 1095 | break; |
1113 | case AD1986A_LAPTOP_EAPD: | 1096 | case AD1986A_LAPTOP_EAPD: |
1114 | spec->mixers[0] = ad1986a_laptop_eapd_mixers; | 1097 | spec->num_mixers = 3; |
1098 | spec->mixers[0] = ad1986a_laptop_master_mixers; | ||
1099 | spec->mixers[1] = ad1986a_laptop_eapd_mixers; | ||
1100 | spec->mixers[2] = ad1986a_laptop_intmic_mixers; | ||
1115 | spec->num_init_verbs = 2; | 1101 | spec->num_init_verbs = 2; |
1116 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; | 1102 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; |
1117 | spec->multiout.max_channels = 2; | 1103 | spec->multiout.max_channels = 2; |
@@ -1122,7 +1108,9 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
1122 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; | 1108 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; |
1123 | break; | 1109 | break; |
1124 | case AD1986A_SAMSUNG: | 1110 | case AD1986A_SAMSUNG: |
1125 | spec->mixers[0] = ad1986a_samsung_mixers; | 1111 | spec->num_mixers = 2; |
1112 | spec->mixers[0] = ad1986a_laptop_master_mixers; | ||
1113 | spec->mixers[1] = ad1986a_laptop_eapd_mixers; | ||
1126 | spec->num_init_verbs = 3; | 1114 | spec->num_init_verbs = 3; |
1127 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; | 1115 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; |
1128 | spec->init_verbs[2] = ad1986a_automic_verbs; | 1116 | spec->init_verbs[2] = ad1986a_automic_verbs; |
@@ -1135,8 +1123,28 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
1135 | codec->patch_ops.unsol_event = ad1986a_automic_unsol_event; | 1123 | codec->patch_ops.unsol_event = ad1986a_automic_unsol_event; |
1136 | codec->patch_ops.init = ad1986a_automic_init; | 1124 | codec->patch_ops.init = ad1986a_automic_init; |
1137 | break; | 1125 | break; |
1126 | case AD1986A_SAMSUNG_P50: | ||
1127 | spec->num_mixers = 2; | ||
1128 | spec->mixers[0] = ad1986a_automute_master_mixers; | ||
1129 | spec->mixers[1] = ad1986a_laptop_eapd_mixers; | ||
1130 | spec->num_init_verbs = 4; | ||
1131 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; | ||
1132 | spec->init_verbs[2] = ad1986a_automic_verbs; | ||
1133 | spec->init_verbs[3] = ad1986a_hp_init_verbs; | ||
1134 | spec->multiout.max_channels = 2; | ||
1135 | spec->multiout.num_dacs = 1; | ||
1136 | spec->multiout.dac_nids = ad1986a_laptop_dac_nids; | ||
1137 | if (!is_jack_available(codec, 0x25)) | ||
1138 | spec->multiout.dig_out_nid = 0; | ||
1139 | spec->input_mux = &ad1986a_automic_capture_source; | ||
1140 | codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event; | ||
1141 | codec->patch_ops.init = ad1986a_samsung_p50_init; | ||
1142 | break; | ||
1138 | case AD1986A_LAPTOP_AUTOMUTE: | 1143 | case AD1986A_LAPTOP_AUTOMUTE: |
1139 | spec->mixers[0] = ad1986a_laptop_automute_mixers; | 1144 | spec->num_mixers = 3; |
1145 | spec->mixers[0] = ad1986a_automute_master_mixers; | ||
1146 | spec->mixers[1] = ad1986a_laptop_eapd_mixers; | ||
1147 | spec->mixers[2] = ad1986a_laptop_intmic_mixers; | ||
1140 | spec->num_init_verbs = 3; | 1148 | spec->num_init_verbs = 3; |
1141 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; | 1149 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; |
1142 | spec->init_verbs[2] = ad1986a_hp_init_verbs; | 1150 | spec->init_verbs[2] = ad1986a_hp_init_verbs; |
@@ -1148,6 +1156,10 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
1148 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; | 1156 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; |
1149 | codec->patch_ops.unsol_event = ad1986a_hp_unsol_event; | 1157 | codec->patch_ops.unsol_event = ad1986a_hp_unsol_event; |
1150 | codec->patch_ops.init = ad1986a_hp_init; | 1158 | codec->patch_ops.init = ad1986a_hp_init; |
1159 | /* Lenovo N100 seems to report the reversed bit | ||
1160 | * for HP jack-sensing | ||
1161 | */ | ||
1162 | spec->inv_jack_detect = 1; | ||
1151 | break; | 1163 | break; |
1152 | case AD1986A_ULTRA: | 1164 | case AD1986A_ULTRA: |
1153 | spec->mixers[0] = ad1986a_laptop_eapd_mixers; | 1165 | spec->mixers[0] = ad1986a_laptop_eapd_mixers; |
@@ -2970,7 +2982,8 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2970 | board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST, | 2982 | board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST, |
2971 | ad1988_models, ad1988_cfg_tbl); | 2983 | ad1988_models, ad1988_cfg_tbl); |
2972 | if (board_config < 0) { | 2984 | if (board_config < 0) { |
2973 | printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n"); | 2985 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", |
2986 | codec->chip_name); | ||
2974 | board_config = AD1988_AUTO; | 2987 | board_config = AD1988_AUTO; |
2975 | } | 2988 | } |
2976 | 2989 | ||
@@ -3690,19 +3703,29 @@ static struct hda_amp_list ad1884a_loopbacks[] = { | |||
3690 | * Port F: Internal speakers | 3703 | * Port F: Internal speakers |
3691 | */ | 3704 | */ |
3692 | 3705 | ||
3693 | static struct hda_input_mux ad1884a_laptop_capture_source = { | 3706 | static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol, |
3694 | .num_items = 4, | 3707 | struct snd_ctl_elem_value *ucontrol) |
3695 | .items = { | 3708 | { |
3696 | { "Mic", 0x0 }, /* port-B */ | 3709 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
3697 | { "Internal Mic", 0x1 }, /* port-C */ | 3710 | int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); |
3698 | { "Dock Mic", 0x4 }, /* port-E */ | 3711 | int mute = (!ucontrol->value.integer.value[0] && |
3699 | { "Mix", 0x3 }, | 3712 | !ucontrol->value.integer.value[1]); |
3700 | }, | 3713 | /* toggle GPIO1 according to the mute state */ |
3701 | }; | 3714 | snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, |
3715 | mute ? 0x02 : 0x0); | ||
3716 | return ret; | ||
3717 | } | ||
3702 | 3718 | ||
3703 | static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { | 3719 | static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { |
3704 | HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 3720 | HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
3705 | HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 3721 | { |
3722 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3723 | .name = "Master Playback Switch", | ||
3724 | .info = snd_hda_mixer_amp_switch_info, | ||
3725 | .get = snd_hda_mixer_amp_switch_get, | ||
3726 | .put = ad1884a_mobile_master_sw_put, | ||
3727 | .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), | ||
3728 | }, | ||
3706 | HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT), | 3729 | HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT), |
3707 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), | 3730 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), |
3708 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | 3731 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), |
@@ -3717,26 +3740,20 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { | |||
3717 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 3740 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT), |
3718 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3741 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
3719 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 3742 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
3720 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | ||
3721 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), | ||
3722 | { | ||
3723 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3724 | /* The multiple "Capture Source" controls confuse alsamixer | ||
3725 | * So call somewhat different.. | ||
3726 | */ | ||
3727 | /* .name = "Capture Source", */ | ||
3728 | .name = "Input Source", | ||
3729 | .count = 2, | ||
3730 | .info = ad198x_mux_enum_info, | ||
3731 | .get = ad198x_mux_enum_get, | ||
3732 | .put = ad198x_mux_enum_put, | ||
3733 | }, | ||
3734 | { } /* end */ | 3743 | { } /* end */ |
3735 | }; | 3744 | }; |
3736 | 3745 | ||
3737 | static struct snd_kcontrol_new ad1884a_mobile_mixers[] = { | 3746 | static struct snd_kcontrol_new ad1884a_mobile_mixers[] = { |
3738 | HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 3747 | HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
3739 | HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 3748 | /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ |
3749 | { | ||
3750 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3751 | .name = "Master Playback Switch", | ||
3752 | .info = snd_hda_mixer_amp_switch_info, | ||
3753 | .get = snd_hda_mixer_amp_switch_get, | ||
3754 | .put = ad1884a_mobile_master_sw_put, | ||
3755 | .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), | ||
3756 | }, | ||
3740 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), | 3757 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), |
3741 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | 3758 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), |
3742 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), | 3759 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), |
@@ -3795,6 +3812,63 @@ static int ad1884a_hp_init(struct hda_codec *codec) | |||
3795 | return 0; | 3812 | return 0; |
3796 | } | 3813 | } |
3797 | 3814 | ||
3815 | /* mute internal speaker if HP or docking HP is plugged */ | ||
3816 | static void ad1884a_laptop_automute(struct hda_codec *codec) | ||
3817 | { | ||
3818 | unsigned int present; | ||
3819 | |||
3820 | present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0); | ||
3821 | present &= AC_PINSENSE_PRESENCE; | ||
3822 | if (!present) { | ||
3823 | present = snd_hda_codec_read(codec, 0x12, 0, | ||
3824 | AC_VERB_GET_PIN_SENSE, 0); | ||
3825 | present &= AC_PINSENSE_PRESENCE; | ||
3826 | } | ||
3827 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, | ||
3828 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
3829 | snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
3830 | present ? 0x00 : 0x02); | ||
3831 | } | ||
3832 | |||
3833 | /* switch to external mic if plugged */ | ||
3834 | static void ad1884a_laptop_automic(struct hda_codec *codec) | ||
3835 | { | ||
3836 | unsigned int idx; | ||
3837 | |||
3838 | if (snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0) & | ||
3839 | AC_PINSENSE_PRESENCE) | ||
3840 | idx = 0; | ||
3841 | else if (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) & | ||
3842 | AC_PINSENSE_PRESENCE) | ||
3843 | idx = 4; | ||
3844 | else | ||
3845 | idx = 1; | ||
3846 | snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx); | ||
3847 | } | ||
3848 | |||
3849 | /* unsolicited event for HP jack sensing */ | ||
3850 | static void ad1884a_laptop_unsol_event(struct hda_codec *codec, | ||
3851 | unsigned int res) | ||
3852 | { | ||
3853 | switch (res >> 26) { | ||
3854 | case AD1884A_HP_EVENT: | ||
3855 | ad1884a_laptop_automute(codec); | ||
3856 | break; | ||
3857 | case AD1884A_MIC_EVENT: | ||
3858 | ad1884a_laptop_automic(codec); | ||
3859 | break; | ||
3860 | } | ||
3861 | } | ||
3862 | |||
3863 | /* initialize jack-sensing, too */ | ||
3864 | static int ad1884a_laptop_init(struct hda_codec *codec) | ||
3865 | { | ||
3866 | ad198x_init(codec); | ||
3867 | ad1884a_laptop_automute(codec); | ||
3868 | ad1884a_laptop_automic(codec); | ||
3869 | return 0; | ||
3870 | } | ||
3871 | |||
3798 | /* additional verbs for laptop model */ | 3872 | /* additional verbs for laptop model */ |
3799 | static struct hda_verb ad1884a_laptop_verbs[] = { | 3873 | static struct hda_verb ad1884a_laptop_verbs[] = { |
3800 | /* Port-A (HP) pin - always unmuted */ | 3874 | /* Port-A (HP) pin - always unmuted */ |
@@ -3802,18 +3876,28 @@ static struct hda_verb ad1884a_laptop_verbs[] = { | |||
3802 | /* Port-F (int speaker) mixer - route only from analog mixer */ | 3876 | /* Port-F (int speaker) mixer - route only from analog mixer */ |
3803 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3877 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3804 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 3878 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
3805 | /* Port-F pin */ | 3879 | /* Port-F (int speaker) pin */ |
3806 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 3880 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
3807 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3881 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
3882 | /* required for compaq 6530s/6531s speaker output */ | ||
3883 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3808 | /* Port-C pin - internal mic-in */ | 3884 | /* Port-C pin - internal mic-in */ |
3809 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3885 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3810 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ | 3886 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ |
3811 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ | 3887 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ |
3888 | /* Port-D (docking line-out) pin - default unmuted */ | ||
3889 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3812 | /* analog mix */ | 3890 | /* analog mix */ |
3813 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | 3891 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3814 | /* unsolicited event for pin-sense */ | 3892 | /* unsolicited event for pin-sense */ |
3815 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, | 3893 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, |
3894 | {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, | ||
3816 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, | 3895 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, |
3896 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, | ||
3897 | /* allow to touch GPIO1 (for mute control) */ | ||
3898 | {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, | ||
3899 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, | ||
3900 | {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ | ||
3817 | { } /* end */ | 3901 | { } /* end */ |
3818 | }; | 3902 | }; |
3819 | 3903 | ||
@@ -3857,6 +3941,10 @@ static struct hda_verb ad1884a_mobile_verbs[] = { | |||
3857 | /* unsolicited event for pin-sense */ | 3941 | /* unsolicited event for pin-sense */ |
3858 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, | 3942 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, |
3859 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, | 3943 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, |
3944 | /* allow to touch GPIO1 (for mute control) */ | ||
3945 | {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, | ||
3946 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, | ||
3947 | {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ | ||
3860 | { } /* end */ | 3948 | { } /* end */ |
3861 | }; | 3949 | }; |
3862 | 3950 | ||
@@ -3944,6 +4032,127 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec) | |||
3944 | } | 4032 | } |
3945 | 4033 | ||
3946 | /* | 4034 | /* |
4035 | * HP Touchsmart | ||
4036 | * port-A (0x11) - front hp-out | ||
4037 | * port-B (0x14) - unused | ||
4038 | * port-C (0x15) - unused | ||
4039 | * port-D (0x12) - rear line out | ||
4040 | * port-E (0x1c) - front mic-in | ||
4041 | * port-F (0x16) - Internal speakers | ||
4042 | * digital-mic (0x17) - Internal mic | ||
4043 | */ | ||
4044 | |||
4045 | static struct hda_verb ad1984a_touchsmart_verbs[] = { | ||
4046 | /* DACs; unmute as default */ | ||
4047 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ | ||
4048 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ | ||
4049 | /* Port-A (HP) mixer - route only from analog mixer */ | ||
4050 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4051 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4052 | /* Port-A pin */ | ||
4053 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
4054 | /* Port-A (HP) pin - always unmuted */ | ||
4055 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
4056 | /* Port-E (int speaker) mixer - route only from analog mixer */ | ||
4057 | {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03}, | ||
4058 | /* Port-E pin */ | ||
4059 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
4060 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
4061 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
4062 | /* Port-F (int speaker) mixer - route only from analog mixer */ | ||
4063 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4064 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4065 | /* Port-F pin */ | ||
4066 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
4067 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4068 | /* Analog mixer; mute as default */ | ||
4069 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4070 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
4071 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
4072 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
4073 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
4074 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, | ||
4075 | /* Analog Mix output amp */ | ||
4076 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4077 | /* capture sources */ | ||
4078 | /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ | ||
4079 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4080 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
4081 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4082 | /* unsolicited event for pin-sense */ | ||
4083 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, | ||
4084 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, | ||
4085 | /* allow to touch GPIO1 (for mute control) */ | ||
4086 | {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, | ||
4087 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, | ||
4088 | {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ | ||
4089 | /* internal mic - dmic */ | ||
4090 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
4091 | /* set magic COEFs for dmic */ | ||
4092 | {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, | ||
4093 | {0x01, AC_VERB_SET_PROC_COEF, 0x08}, | ||
4094 | { } /* end */ | ||
4095 | }; | ||
4096 | |||
4097 | static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { | ||
4098 | HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), | ||
4099 | /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ | ||
4100 | { | ||
4101 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4102 | .name = "Master Playback Switch", | ||
4103 | .info = snd_hda_mixer_amp_switch_info, | ||
4104 | .get = snd_hda_mixer_amp_switch_get, | ||
4105 | .put = ad1884a_mobile_master_sw_put, | ||
4106 | .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), | ||
4107 | }, | ||
4108 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), | ||
4109 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | ||
4110 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
4111 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | ||
4112 | HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), | ||
4113 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), | ||
4114 | { } /* end */ | ||
4115 | }; | ||
4116 | |||
4117 | /* switch to external mic if plugged */ | ||
4118 | static void ad1984a_touchsmart_automic(struct hda_codec *codec) | ||
4119 | { | ||
4120 | if (snd_hda_codec_read(codec, 0x1c, 0, | ||
4121 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) { | ||
4122 | snd_hda_codec_write(codec, 0x0c, 0, | ||
4123 | AC_VERB_SET_CONNECT_SEL, 0x4); | ||
4124 | } else { | ||
4125 | snd_hda_codec_write(codec, 0x0c, 0, | ||
4126 | AC_VERB_SET_CONNECT_SEL, 0x5); | ||
4127 | } | ||
4128 | } | ||
4129 | |||
4130 | |||
4131 | /* unsolicited event for HP jack sensing */ | ||
4132 | static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec, | ||
4133 | unsigned int res) | ||
4134 | { | ||
4135 | switch (res >> 26) { | ||
4136 | case AD1884A_HP_EVENT: | ||
4137 | ad1884a_hp_automute(codec); | ||
4138 | break; | ||
4139 | case AD1884A_MIC_EVENT: | ||
4140 | ad1984a_touchsmart_automic(codec); | ||
4141 | break; | ||
4142 | } | ||
4143 | } | ||
4144 | |||
4145 | /* initialize jack-sensing, too */ | ||
4146 | static int ad1984a_touchsmart_init(struct hda_codec *codec) | ||
4147 | { | ||
4148 | ad198x_init(codec); | ||
4149 | ad1884a_hp_automute(codec); | ||
4150 | ad1984a_touchsmart_automic(codec); | ||
4151 | return 0; | ||
4152 | } | ||
4153 | |||
4154 | |||
4155 | /* | ||
3947 | */ | 4156 | */ |
3948 | 4157 | ||
3949 | enum { | 4158 | enum { |
@@ -3951,6 +4160,7 @@ enum { | |||
3951 | AD1884A_LAPTOP, | 4160 | AD1884A_LAPTOP, |
3952 | AD1884A_MOBILE, | 4161 | AD1884A_MOBILE, |
3953 | AD1884A_THINKPAD, | 4162 | AD1884A_THINKPAD, |
4163 | AD1984A_TOUCHSMART, | ||
3954 | AD1884A_MODELS | 4164 | AD1884A_MODELS |
3955 | }; | 4165 | }; |
3956 | 4166 | ||
@@ -3959,6 +4169,7 @@ static const char *ad1884a_models[AD1884A_MODELS] = { | |||
3959 | [AD1884A_LAPTOP] = "laptop", | 4169 | [AD1884A_LAPTOP] = "laptop", |
3960 | [AD1884A_MOBILE] = "mobile", | 4170 | [AD1884A_MOBILE] = "mobile", |
3961 | [AD1884A_THINKPAD] = "thinkpad", | 4171 | [AD1884A_THINKPAD] = "thinkpad", |
4172 | [AD1984A_TOUCHSMART] = "touchsmart", | ||
3962 | }; | 4173 | }; |
3963 | 4174 | ||
3964 | static struct snd_pci_quirk ad1884a_cfg_tbl[] = { | 4175 | static struct snd_pci_quirk ad1884a_cfg_tbl[] = { |
@@ -3966,9 +4177,12 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { | |||
3966 | SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), | 4177 | SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), |
3967 | SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), | 4178 | SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), |
3968 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE), | 4179 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE), |
4180 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP), | ||
3969 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP), | 4181 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP), |
3970 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), | 4182 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), |
4183 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), | ||
3971 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), | 4184 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), |
4185 | SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART), | ||
3972 | {} | 4186 | {} |
3973 | }; | 4187 | }; |
3974 | 4188 | ||
@@ -4017,9 +4231,8 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
4017 | spec->mixers[0] = ad1884a_laptop_mixers; | 4231 | spec->mixers[0] = ad1884a_laptop_mixers; |
4018 | spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs; | 4232 | spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs; |
4019 | spec->multiout.dig_out_nid = 0; | 4233 | spec->multiout.dig_out_nid = 0; |
4020 | spec->input_mux = &ad1884a_laptop_capture_source; | 4234 | codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event; |
4021 | codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; | 4235 | codec->patch_ops.init = ad1884a_laptop_init; |
4022 | codec->patch_ops.init = ad1884a_hp_init; | ||
4023 | /* set the upper-limit for mixer amp to 0dB for avoiding the | 4236 | /* set the upper-limit for mixer amp to 0dB for avoiding the |
4024 | * possible damage by overloading | 4237 | * possible damage by overloading |
4025 | */ | 4238 | */ |
@@ -4053,6 +4266,21 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
4053 | codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; | 4266 | codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; |
4054 | codec->patch_ops.init = ad1984a_thinkpad_init; | 4267 | codec->patch_ops.init = ad1984a_thinkpad_init; |
4055 | break; | 4268 | break; |
4269 | case AD1984A_TOUCHSMART: | ||
4270 | spec->mixers[0] = ad1984a_touchsmart_mixers; | ||
4271 | spec->init_verbs[0] = ad1984a_touchsmart_verbs; | ||
4272 | spec->multiout.dig_out_nid = 0; | ||
4273 | codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event; | ||
4274 | codec->patch_ops.init = ad1984a_touchsmart_init; | ||
4275 | /* set the upper-limit for mixer amp to 0dB for avoiding the | ||
4276 | * possible damage by overloading | ||
4277 | */ | ||
4278 | snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, | ||
4279 | (0x17 << AC_AMPCAP_OFFSET_SHIFT) | | ||
4280 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
4281 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
4282 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
4283 | break; | ||
4056 | } | 4284 | } |
4057 | 4285 | ||
4058 | return 0; | 4286 | return 0; |