aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/patch_analog.c785
1 files changed, 785 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 1f371fe6b92f..25116a883ca6 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -41,6 +41,7 @@ struct ad198x_spec {
41 * max_channels, dacs must be set 41 * max_channels, dacs must be set
42 * dig_out_nid and hp_nid are optional 42 * dig_out_nid and hp_nid are optional
43 */ 43 */
44 unsigned int cur_eapd;
44 45
45 /* capture */ 46 /* capture */
46 unsigned int num_adc_nids; 47 unsigned int num_adc_nids;
@@ -857,11 +858,795 @@ static int patch_ad1981(struct hda_codec *codec)
857 858
858 859
859/* 860/*
861 * AD1988
862 *
863 * Output pins and routes
864 *
865 * Pin Mix Sel DAC
866 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
867 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
868 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
869 * port-D 0x12 (mute/hp) <- 0x29 <- 04
870 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
871 * port-F 0x16 (mute) <- 0x2a <- 06
872 * port-G 0x24 (mute) <- 0x27 <- 05
873 * port-H 0x25 (mute) <- 0x28 <- 0a
874 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
875 *
876 *
877 * Input pins and routes
878 *
879 * pin boost mix input # / adc input #
880 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
881 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
882 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
883 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
884 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
885 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
886 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
887 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
888 *
889 *
890 * DAC assignment
891 * front DAC - 04
892 * surr DAC - 06
893 * CLFE DAC - 05
894 * side DAC - 0a
895 * opt DAC - 03
896 *
897 * Inputs of Analog Mix (0x20)
898 * 0:Port-B (front mic)
899 * 1:Port-C/G/H (line-in)
900 * 2:Port-A
901 * 3:Port-D (line-in/2)
902 * 4:Port-E/G/H (mic-in)
903 * 5:Port-F (mic2-in)
904 * 6:CD
905 * 7:Beep
906 *
907 * ADC selection
908 * 0:Port-A
909 * 1:Port-B (front mic-in)
910 * 2:Port-C (line-in)
911 * 3:Port-F (mic2-in)
912 * 4:Port-E (mic-in)
913 * 5:CD
914 * 6:Port-G
915 * 7:Port-H
916 * 8:Port-D (line-in/2)
917 * 9:Mix
918 *
919 * Proposed pin assignments by the datasheet
920 *
921 * 6-stack
922 * Port-A front headphone
923 * B front mic-in
924 * C rear line-in
925 * D rear front-out
926 * E rear mic-in
927 * F rear surround
928 * G rear CLFE
929 * H rear side
930 *
931 * 3-stack
932 * Port-A front headphone
933 * B front mic
934 * C rear line-in/surround
935 * D rear front-out
936 * E rear mic-in/CLFE
937 *
938 * laptop
939 * Port-A headphone
940 * B mic-in
941 * C docking station
942 * D internal speaker (with EAPD)
943 * E/F quad mic array
944 */
945
946
947/* models */
948enum {
949 AD1988_6STACK,
950 AD1988_6STACK_DIG,
951 AD1988_3STACK,
952 AD1988_3STACK_DIG,
953 AD1988_LAPTOP,
954 AD1988_LAPTOP_DIG,
955 AD1988_MODEL_LAST,
956};
957
958
959/*
960 * mixers
961 */
962
963static hda_nid_t ad1988_dac_nids[4] = {
964 0x04, 0x06, 0x05, 0x0a
965};
966
967static hda_nid_t ad1988_adc_nids[3] = {
968 0x08, 0x09, 0x0f
969};
970
971#define AD1988_SPDIF_OUT 0x02
972#define AD1988_SPDIF_IN 0x07
973
974static struct hda_input_mux ad1988_6stack_capture_source = {
975 .num_items = 5,
976 .items = {
977 { "Front Mic", 0x0 },
978 { "Line", 0x1 },
979 { "Mic", 0x4 },
980 { "CD", 0x5 },
981 { "Mix", 0x9 },
982 },
983};
984
985static struct hda_input_mux ad1988_laptop_capture_source = {
986 .num_items = 3,
987 .items = {
988 { "Mic/Line", 0x0 },
989 { "CD", 0x5 },
990 { "Mix", 0x9 },
991 },
992};
993
994/*
995 */
996static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
997 struct snd_ctl_elem_info *uinfo)
998{
999 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1000 struct ad198x_spec *spec = codec->spec;
1001 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1002 spec->num_channel_mode);
1003}
1004
1005static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1006 struct snd_ctl_elem_value *ucontrol)
1007{
1008 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1009 struct ad198x_spec *spec = codec->spec;
1010 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1011 spec->num_channel_mode, spec->multiout.max_channels);
1012}
1013
1014static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1015 struct snd_ctl_elem_value *ucontrol)
1016{
1017 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1018 struct ad198x_spec *spec = codec->spec;
1019 return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
1020 spec->num_channel_mode, &spec->multiout.max_channels);
1021}
1022
1023/*
1024 * EAPD control
1025 */
1026static int ad1988_eapd_info(struct snd_kcontrol *kcontrol,
1027 struct snd_ctl_elem_info *uinfo)
1028{
1029 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1030 uinfo->count = 1;
1031 uinfo->value.integer.min = 0;
1032 uinfo->value.integer.max = 1;
1033 return 0;
1034}
1035
1036static int ad1988_eapd_get(struct snd_kcontrol *kcontrol,
1037 struct snd_ctl_elem_value *ucontrol)
1038{
1039 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1040 struct ad198x_spec *spec = codec->spec;
1041 ucontrol->value.enumerated.item[0] = ! spec->cur_eapd;
1042 return 0;
1043}
1044
1045static int ad1988_eapd_put(struct snd_kcontrol *kcontrol,
1046 struct snd_ctl_elem_value *ucontrol)
1047{
1048 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1049 struct ad198x_spec *spec = codec->spec;
1050 unsigned int eapd;
1051 eapd = ! ucontrol->value.enumerated.item[0];
1052 if (eapd == spec->cur_eapd && ! codec->in_resume)
1053 return 0;
1054 spec->cur_eapd = eapd;
1055 snd_hda_codec_write(codec, 0x12 /* port-D */,
1056 0, AC_VERB_SET_EAPD_BTLENABLE,
1057 eapd ? 0x02 : 0x00);
1058 return 0;
1059}
1060
1061/* 6-stack mode */
1062static struct snd_kcontrol_new ad1988_6stack_mixers[] = {
1063 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1064 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1065 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1066 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1067 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1068
1069 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1070 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1071 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1072 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1073 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
1074 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1075 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1076
1077 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1078 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1079 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1080 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1081 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1082 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1083 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1084 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1085
1086 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1087 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1088
1089 HDA_CODEC_VOLUME("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1090 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1091
1092 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1093 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1094
1095 { } /* end */
1096};
1097
1098/* 3-stack mode */
1099static struct snd_kcontrol_new ad1988_3stack_mixers[] = {
1100 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1101 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1102 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1103 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1104
1105 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1106 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1107 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1108 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1109 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1110 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1111
1112 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1113 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1114 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1115 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1116 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1117 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1118 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1119 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1120
1121 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1122 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1123
1124 HDA_CODEC_VOLUME("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1125 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1126
1127 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1128 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1129 {
1130 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1131 .name = "Channel Mode",
1132 .info = ad198x_ch_mode_info,
1133 .get = ad198x_ch_mode_get,
1134 .put = ad198x_ch_mode_put,
1135 },
1136
1137 { } /* end */
1138};
1139
1140/* laptop mode */
1141static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
1142 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1143 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
1144 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1145
1146 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1147 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1148 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1149 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1150 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1151 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1152
1153 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1154 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1155
1156 HDA_CODEC_VOLUME("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1157 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1158
1159 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1160
1161 {
1162 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1163 .name = "External Amplifier",
1164 .info = ad1988_eapd_info,
1165 .get = ad1988_eapd_get,
1166 .put = ad1988_eapd_put,
1167 },
1168
1169 { } /* end */
1170};
1171
1172/* capture */
1173static struct snd_kcontrol_new ad1988_capture_mixers[] = {
1174 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
1175 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
1176 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
1177 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
1178 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
1179 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
1180 {
1181 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1182 /* The multiple "Capture Source" controls confuse alsamixer
1183 * So call somewhat different..
1184 * FIXME: the controls appear in the "playback" view!
1185 */
1186 /* .name = "Capture Source", */
1187 .name = "Input Source",
1188 .count = 3,
1189 .info = ad198x_mux_enum_info,
1190 .get = ad198x_mux_enum_get,
1191 .put = ad198x_mux_enum_put,
1192 },
1193 { } /* end */
1194};
1195
1196static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
1197 struct snd_ctl_elem_info *uinfo)
1198{
1199 static char *texts[] = {
1200 "PCM", "ADC1", "ADC2", "ADC3"
1201 };
1202 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1203 uinfo->count = 1;
1204 uinfo->value.enumerated.items = 4;
1205 if (uinfo->value.enumerated.item >= 4)
1206 uinfo->value.enumerated.item = 3;
1207 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1208 return 0;
1209}
1210
1211static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
1212 struct snd_ctl_elem_value *ucontrol)
1213{
1214 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1215 unsigned int sel;
1216
1217 sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
1218 if (sel > 0) {
1219 sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0);
1220 if (sel <= 3)
1221 sel++;
1222 else
1223 sel = 0;
1224 }
1225 ucontrol->value.enumerated.item[0] = sel;
1226 return 0;
1227}
1228
1229static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
1230 struct snd_ctl_elem_value *ucontrol)
1231{
1232 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1233 unsigned int sel;
1234 int change;
1235
1236 sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
1237 if (! ucontrol->value.enumerated.item[0]) {
1238 change = sel != 0;
1239 if (change)
1240 snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 0);
1241 } else {
1242 change = sel == 0;
1243 if (change)
1244 snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 1);
1245 sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0) + 1;
1246 change |= sel == ucontrol->value.enumerated.item[0];
1247 if (change)
1248 snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL,
1249 ucontrol->value.enumerated.item[0] - 1);
1250 }
1251 return change;
1252}
1253
1254static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
1255 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1256 {
1257 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1258 .name = "IEC958 Playback Source",
1259 .info = ad1988_spdif_playback_source_info,
1260 .get = ad1988_spdif_playback_source_get,
1261 .put = ad1988_spdif_playback_source_put,
1262 },
1263 { } /* end */
1264};
1265
1266static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
1267 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
1268 { } /* end */
1269};
1270
1271
1272/*
1273 * initialization verbs
1274 */
1275
1276/*
1277 * for 6-stack (+dig)
1278 */
1279static struct hda_verb ad1988_6stack_init_verbs[] = {
1280 /* Front, Surround, CLFE, side DAC; mute as default */
1281 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1282 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1283 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1284 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1285 /* Port-A front headphon path */
1286 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1287 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1288 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1289 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1290 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1291 /* Port-D line-out path */
1292 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1293 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1294 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1295 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1296 /* Port-F surround path */
1297 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1298 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1299 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1300 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1301 /* Port-G CLFE path */
1302 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1303 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1304 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1305 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1306 /* Port-H side path */
1307 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1308 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1309 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1310 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1311 /* Mono out path */
1312 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1313 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1314 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1315 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1316 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1317 /* Port-B front mic-in path */
1318 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1319 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1320 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1321 /* Port-C line-in path */
1322 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1323 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1324 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1325 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1326 /* Port-E mic-in path */
1327 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1328 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1329 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1330 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
1331
1332 { }
1333};
1334
1335static struct hda_verb ad1988_capture_init_verbs[] = {
1336 /* mute analog mix */
1337 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1338 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1339 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1340 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1341 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1342 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1343 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1344 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1345 /* select ADCs - front-mic */
1346 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1347 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1348 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1349 /* ADCs; muted */
1350 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1351 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1352 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1353
1354 { }
1355};
1356
1357static struct hda_verb ad1988_spdif_init_verbs[] = {
1358 /* SPDIF out sel */
1359 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
1360 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
1361 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1362 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1363 /* SPDIF out pin */
1364 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
1365 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */
1366
1367 { }
1368};
1369
1370/*
1371 * verbs for 3stack (+dig)
1372 */
1373static struct hda_verb ad1988_3stack_ch2_init[] = {
1374 /* set port-C to line-in */
1375 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1376 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1377 /* set port-E to mic-in */
1378 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1379 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1380 { } /* end */
1381};
1382
1383static struct hda_verb ad1988_3stack_ch6_init[] = {
1384 /* set port-C to surround out */
1385 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1386 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1387 /* set port-E to CLFE out */
1388 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1389 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1390 { } /* end */
1391};
1392
1393static struct hda_channel_mode ad1988_3stack_modes[2] = {
1394 { 2, ad1988_3stack_ch2_init },
1395 { 6, ad1988_3stack_ch6_init },
1396};
1397
1398static struct hda_verb ad1988_3stack_init_verbs[] = {
1399 /* Front, Surround, CLFE, side DAC; mute as default */
1400 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1401 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1402 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1403 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1404 /* Port-A front headphon path */
1405 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1406 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1407 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1408 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1409 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1410 /* Port-D line-out path */
1411 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1412 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1413 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1414 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1415 /* Mono out path */
1416 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1417 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1418 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1419 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1420 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1421 /* Port-B front mic-in path */
1422 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1423 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1424 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1425 /* Port-C line-in/surround path */
1426 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1427 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1428 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1429 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1430 /* Port-E mic-in/CLFE path */
1431 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1432 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1433 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1434 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
1435 /* mute analog mix */
1436 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1437 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1438 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1439 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1440 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1441 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1442 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1443 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1444 /* select ADCs - front-mic */
1445 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1446 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1447 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1448 /* ADCs; muted */
1449 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1450 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1451 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1452 { }
1453};
1454
1455/*
1456 * verbs for laptop mode (+dig)
1457 */
1458static struct hda_verb ad1988_laptop_hp_on[] = {
1459 /* unmute port-A and mute port-D */
1460 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1461 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1462 { } /* end */
1463};
1464static struct hda_verb ad1988_laptop_hp_off[] = {
1465 /* mute port-A and unmute port-D */
1466 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1467 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1468 { } /* end */
1469};
1470
1471#define AD1988_HP_EVENT 0x01
1472
1473static struct hda_verb ad1988_laptop_init_verbs[] = {
1474 /* Front, Surround, CLFE, side DAC; mute as default */
1475 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1476 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1477 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1478 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1479 /* Port-A front headphon path */
1480 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1481 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1482 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1483 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1484 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1485 /* unsolicited event for pin-sense */
1486 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
1487 /* Port-D line-out path + EAPD */
1488 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1489 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1490 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1491 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1492 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
1493 /* Mono out path */
1494 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1495 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1496 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1497 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1498 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1499 /* Port-B mic-in path */
1500 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1501 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1502 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1503 /* Port-C docking station - try to output */
1504 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1505 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1506 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1507 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1508 /* mute analog mix */
1509 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1510 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1511 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1512 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1513 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1514 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1515 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1516 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1517 /* select ADCs - mic */
1518 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1519 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1520 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1521 /* ADCs; muted */
1522 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1523 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1524 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1525 { }
1526};
1527
1528static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
1529{
1530 if ((res >> 26) != AD1988_HP_EVENT)
1531 return;
1532 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
1533 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
1534 else
1535 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
1536}
1537
1538
1539/*
1540 */
1541
1542static struct hda_board_config ad1988_cfg_tbl[] = {
1543 { .modelname = "6stack", .config = AD1988_6STACK },
1544 { .modelname = "6stack-dig", .config = AD1988_6STACK_DIG },
1545 { .modelname = "3stack", .config = AD1988_3STACK },
1546 { .modelname = "3stack-dig", .config = AD1988_3STACK_DIG },
1547 { .modelname = "laptop", .config = AD1988_LAPTOP },
1548 { .modelname = "laptop-dig", .config = AD1988_LAPTOP_DIG },
1549 {}
1550};
1551
1552static int patch_ad1988(struct hda_codec *codec)
1553{
1554 struct ad198x_spec *spec;
1555 int board_config;
1556
1557 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1558 if (spec == NULL)
1559 return -ENOMEM;
1560
1561 init_MUTEX(&spec->amp_mutex);
1562 codec->spec = spec;
1563
1564 board_config = snd_hda_check_board_config(codec, ad1988_cfg_tbl);
1565 if (board_config < 0 || board_config >= AD1988_MODEL_LAST) {
1566 printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
1567 board_config = AD1988_6STACK;
1568 }
1569
1570 switch (board_config) {
1571 case AD1988_6STACK:
1572 case AD1988_6STACK_DIG:
1573 spec->multiout.max_channels = 8;
1574 spec->multiout.num_dacs = 4;
1575 spec->multiout.dac_nids = ad1988_dac_nids;
1576 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
1577 spec->adc_nids = ad1988_adc_nids;
1578 spec->input_mux = &ad1988_6stack_capture_source;
1579 spec->num_mixers = 1;
1580 spec->mixers[0] = ad1988_6stack_mixers;
1581 spec->num_init_verbs = 1;
1582 spec->init_verbs[0] = ad1988_6stack_init_verbs;
1583 if (board_config == AD1988_6STACK_DIG) {
1584 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
1585 spec->dig_in_nid = AD1988_SPDIF_IN;
1586 }
1587 break;
1588 case AD1988_3STACK:
1589 case AD1988_3STACK_DIG:
1590 spec->multiout.max_channels = 6;
1591 spec->multiout.num_dacs = 3;
1592 spec->multiout.dac_nids = ad1988_dac_nids;
1593 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
1594 spec->adc_nids = ad1988_adc_nids;
1595 spec->input_mux = &ad1988_6stack_capture_source;
1596 spec->channel_mode = ad1988_3stack_modes;
1597 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
1598 spec->num_mixers = 1;
1599 spec->mixers[0] = ad1988_3stack_mixers;
1600 spec->num_init_verbs = 1;
1601 spec->init_verbs[0] = ad1988_3stack_init_verbs;
1602 if (board_config == AD1988_3STACK_DIG)
1603 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
1604 break;
1605 case AD1988_LAPTOP:
1606 case AD1988_LAPTOP_DIG:
1607 spec->multiout.max_channels = 2;
1608 spec->multiout.num_dacs = 1;
1609 spec->multiout.dac_nids = ad1988_dac_nids;
1610 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
1611 spec->adc_nids = ad1988_adc_nids;
1612 spec->input_mux = &ad1988_laptop_capture_source;
1613 spec->num_mixers = 1;
1614 spec->mixers[0] = ad1988_laptop_mixers;
1615 spec->num_init_verbs = 1;
1616 spec->init_verbs[0] = ad1988_laptop_init_verbs;
1617 if (board_config == AD1988_LAPTOP_DIG)
1618 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
1619 break;
1620 }
1621
1622 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
1623 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
1624 if (spec->multiout.dig_out_nid) {
1625 spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
1626 spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
1627 }
1628 if (spec->dig_in_nid)
1629 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
1630
1631 codec->patch_ops = ad198x_patch_ops;
1632 switch (board_config) {
1633 case AD1988_LAPTOP:
1634 case AD1988_LAPTOP_DIG:
1635 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
1636 break;
1637 }
1638
1639 return 0;
1640}
1641
1642
1643/*
860 * patch entries 1644 * patch entries
861 */ 1645 */
862struct hda_codec_preset snd_hda_preset_analog[] = { 1646struct hda_codec_preset snd_hda_preset_analog[] = {
863 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, 1647 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
864 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, 1648 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
865 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, 1649 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
1650 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
866 {} /* terminator */ 1651 {} /* terminator */
867}; 1652};