diff options
| -rw-r--r-- | Documentation/sound/alsa/HD-Audio-Models.txt | 1 | ||||
| -rw-r--r-- | sound/pci/hda/patch_analog.c | 128 |
2 files changed, 71 insertions, 58 deletions
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 0d8d23581c44..939a3dd58148 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt | |||
| @@ -240,6 +240,7 @@ AD1986A | |||
| 240 | laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100) | 240 | laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100) |
| 241 | ultra 2-channel with EAPD (Samsung Ultra tablet PC) | 241 | ultra 2-channel with EAPD (Samsung Ultra tablet PC) |
| 242 | samsung 2-channel with EAPD (Samsung R65) | 242 | samsung 2-channel with EAPD (Samsung R65) |
| 243 | samsung-p50 2-channel with HP-automute (Samsung P50) | ||
| 243 | 244 | ||
| 244 | AD1988/AD1988B/AD1989A/AD1989B | 245 | AD1988/AD1988B/AD1989A/AD1989B |
| 245 | ============================== | 246 | ============================== |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 84cc49ca9148..1988582d1ab8 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; |
