diff options
Diffstat (limited to 'sound/isa')
-rw-r--r-- | sound/isa/ad1816a/ad1816a_lib.c | 55 | ||||
-rw-r--r-- | sound/isa/ad1848/ad1848_lib.c | 49 | ||||
-rw-r--r-- | sound/isa/es18xx.c | 219 | ||||
-rw-r--r-- | sound/isa/gus/gus_mem_proc.c | 6 | ||||
-rw-r--r-- | sound/isa/opl3sa2.c | 26 |
5 files changed, 262 insertions, 93 deletions
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 8fcf2c151823..fd9b61eda0f3 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
26 | #include <sound/core.h> | 26 | #include <sound/core.h> |
27 | #include <sound/tlv.h> | ||
27 | #include <sound/ad1816a.h> | 28 | #include <sound/ad1816a.h> |
28 | 29 | ||
29 | #include <asm/io.h> | 30 | #include <asm/io.h> |
@@ -765,6 +766,13 @@ static int snd_ad1816a_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
765 | return change; | 766 | return change; |
766 | } | 767 | } |
767 | 768 | ||
769 | #define AD1816A_SINGLE_TLV(xname, reg, shift, mask, invert, xtlv) \ | ||
770 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
771 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
772 | .name = xname, .info = snd_ad1816a_info_single, \ | ||
773 | .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \ | ||
774 | .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ | ||
775 | .tlv = { .p = (xtlv) } } | ||
768 | #define AD1816A_SINGLE(xname, reg, shift, mask, invert) \ | 776 | #define AD1816A_SINGLE(xname, reg, shift, mask, invert) \ |
769 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_single, \ | 777 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_single, \ |
770 | .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \ | 778 | .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \ |
@@ -822,6 +830,14 @@ static int snd_ad1816a_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
822 | return change; | 830 | return change; |
823 | } | 831 | } |
824 | 832 | ||
833 | #define AD1816A_DOUBLE_TLV(xname, reg, shift_left, shift_right, mask, invert, xtlv) \ | ||
834 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
835 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
836 | .name = xname, .info = snd_ad1816a_info_double, \ | ||
837 | .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \ | ||
838 | .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24), \ | ||
839 | .tlv = { .p = (xtlv) } } | ||
840 | |||
825 | #define AD1816A_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ | 841 | #define AD1816A_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ |
826 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_double, \ | 842 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_double, \ |
827 | .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \ | 843 | .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \ |
@@ -890,28 +906,44 @@ static int snd_ad1816a_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
890 | return change; | 906 | return change; |
891 | } | 907 | } |
892 | 908 | ||
909 | static DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); | ||
910 | static DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); | ||
911 | static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); | ||
912 | static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); | ||
913 | static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); | ||
914 | |||
893 | static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = { | 915 | static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = { |
894 | AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1), | 916 | AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1), |
895 | AD1816A_DOUBLE("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1), | 917 | AD1816A_DOUBLE_TLV("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1, |
918 | db_scale_5bit), | ||
896 | AD1816A_DOUBLE("PCM Playback Switch", AD1816A_VOICE_ATT, 15, 7, 1, 1), | 919 | AD1816A_DOUBLE("PCM Playback Switch", AD1816A_VOICE_ATT, 15, 7, 1, 1), |
897 | AD1816A_DOUBLE("PCM Playback Volume", AD1816A_VOICE_ATT, 8, 0, 63, 1), | 920 | AD1816A_DOUBLE_TLV("PCM Playback Volume", AD1816A_VOICE_ATT, 8, 0, 63, 1, |
921 | db_scale_6bit), | ||
898 | AD1816A_DOUBLE("Line Playback Switch", AD1816A_LINE_GAIN_ATT, 15, 7, 1, 1), | 922 | AD1816A_DOUBLE("Line Playback Switch", AD1816A_LINE_GAIN_ATT, 15, 7, 1, 1), |
899 | AD1816A_DOUBLE("Line Playback Volume", AD1816A_LINE_GAIN_ATT, 8, 0, 31, 1), | 923 | AD1816A_DOUBLE_TLV("Line Playback Volume", AD1816A_LINE_GAIN_ATT, 8, 0, 31, 1, |
924 | db_scale_5bit_12db_max), | ||
900 | AD1816A_DOUBLE("CD Playback Switch", AD1816A_CD_GAIN_ATT, 15, 7, 1, 1), | 925 | AD1816A_DOUBLE("CD Playback Switch", AD1816A_CD_GAIN_ATT, 15, 7, 1, 1), |
901 | AD1816A_DOUBLE("CD Playback Volume", AD1816A_CD_GAIN_ATT, 8, 0, 31, 1), | 926 | AD1816A_DOUBLE_TLV("CD Playback Volume", AD1816A_CD_GAIN_ATT, 8, 0, 31, 1, |
927 | db_scale_5bit_12db_max), | ||
902 | AD1816A_DOUBLE("Synth Playback Switch", AD1816A_SYNTH_GAIN_ATT, 15, 7, 1, 1), | 928 | AD1816A_DOUBLE("Synth Playback Switch", AD1816A_SYNTH_GAIN_ATT, 15, 7, 1, 1), |
903 | AD1816A_DOUBLE("Synth Playback Volume", AD1816A_SYNTH_GAIN_ATT, 8, 0, 31, 1), | 929 | AD1816A_DOUBLE_TLV("Synth Playback Volume", AD1816A_SYNTH_GAIN_ATT, 8, 0, 31, 1, |
930 | db_scale_5bit_12db_max), | ||
904 | AD1816A_DOUBLE("FM Playback Switch", AD1816A_FM_ATT, 15, 7, 1, 1), | 931 | AD1816A_DOUBLE("FM Playback Switch", AD1816A_FM_ATT, 15, 7, 1, 1), |
905 | AD1816A_DOUBLE("FM Playback Volume", AD1816A_FM_ATT, 8, 0, 63, 1), | 932 | AD1816A_DOUBLE_TLV("FM Playback Volume", AD1816A_FM_ATT, 8, 0, 63, 1, |
933 | db_scale_6bit), | ||
906 | AD1816A_SINGLE("Mic Playback Switch", AD1816A_MIC_GAIN_ATT, 15, 1, 1), | 934 | AD1816A_SINGLE("Mic Playback Switch", AD1816A_MIC_GAIN_ATT, 15, 1, 1), |
907 | AD1816A_SINGLE("Mic Playback Volume", AD1816A_MIC_GAIN_ATT, 8, 31, 1), | 935 | AD1816A_SINGLE_TLV("Mic Playback Volume", AD1816A_MIC_GAIN_ATT, 8, 31, 1, |
936 | db_scale_5bit_12db_max), | ||
908 | AD1816A_SINGLE("Mic Boost", AD1816A_MIC_GAIN_ATT, 14, 1, 0), | 937 | AD1816A_SINGLE("Mic Boost", AD1816A_MIC_GAIN_ATT, 14, 1, 0), |
909 | AD1816A_DOUBLE("Video Playback Switch", AD1816A_VID_GAIN_ATT, 15, 7, 1, 1), | 938 | AD1816A_DOUBLE("Video Playback Switch", AD1816A_VID_GAIN_ATT, 15, 7, 1, 1), |
910 | AD1816A_DOUBLE("Video Playback Volume", AD1816A_VID_GAIN_ATT, 8, 0, 31, 1), | 939 | AD1816A_DOUBLE_TLV("Video Playback Volume", AD1816A_VID_GAIN_ATT, 8, 0, 31, 1, |
940 | db_scale_5bit_12db_max), | ||
911 | AD1816A_SINGLE("Phone Capture Switch", AD1816A_PHONE_IN_GAIN_ATT, 15, 1, 1), | 941 | AD1816A_SINGLE("Phone Capture Switch", AD1816A_PHONE_IN_GAIN_ATT, 15, 1, 1), |
912 | AD1816A_SINGLE("Phone Capture Volume", AD1816A_PHONE_IN_GAIN_ATT, 0, 15, 1), | 942 | AD1816A_SINGLE_TLV("Phone Capture Volume", AD1816A_PHONE_IN_GAIN_ATT, 0, 15, 1, |
943 | db_scale_4bit), | ||
913 | AD1816A_SINGLE("Phone Playback Switch", AD1816A_PHONE_OUT_ATT, 7, 1, 1), | 944 | AD1816A_SINGLE("Phone Playback Switch", AD1816A_PHONE_OUT_ATT, 7, 1, 1), |
914 | AD1816A_SINGLE("Phone Playback Volume", AD1816A_PHONE_OUT_ATT, 0, 31, 1), | 945 | AD1816A_SINGLE_TLV("Phone Playback Volume", AD1816A_PHONE_OUT_ATT, 0, 31, 1, |
946 | db_scale_5bit), | ||
915 | { | 947 | { |
916 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 948 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
917 | .name = "Capture Source", | 949 | .name = "Capture Source", |
@@ -920,7 +952,8 @@ AD1816A_SINGLE("Phone Playback Volume", AD1816A_PHONE_OUT_ATT, 0, 31, 1), | |||
920 | .put = snd_ad1816a_put_mux, | 952 | .put = snd_ad1816a_put_mux, |
921 | }, | 953 | }, |
922 | AD1816A_DOUBLE("Capture Switch", AD1816A_ADC_PGA, 15, 7, 1, 1), | 954 | AD1816A_DOUBLE("Capture Switch", AD1816A_ADC_PGA, 15, 7, 1, 1), |
923 | AD1816A_DOUBLE("Capture Volume", AD1816A_ADC_PGA, 8, 0, 15, 0), | 955 | AD1816A_DOUBLE_TLV("Capture Volume", AD1816A_ADC_PGA, 8, 0, 15, 0, |
956 | db_scale_rec_gain), | ||
924 | AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1), | 957 | AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1), |
925 | AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0), | 958 | AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0), |
926 | }; | 959 | }; |
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index e711f87d5fd1..a6fbd5d1d62f 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include <sound/ad1848.h> | 30 | #include <sound/ad1848.h> |
31 | #include <sound/control.h> | 31 | #include <sound/control.h> |
32 | #include <sound/tlv.h> | ||
32 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
33 | 34 | ||
34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
@@ -118,6 +119,8 @@ void snd_ad1848_out(struct snd_ad1848 *chip, | |||
118 | #endif | 119 | #endif |
119 | } | 120 | } |
120 | 121 | ||
122 | EXPORT_SYMBOL(snd_ad1848_out); | ||
123 | |||
121 | static void snd_ad1848_dout(struct snd_ad1848 *chip, | 124 | static void snd_ad1848_dout(struct snd_ad1848 *chip, |
122 | unsigned char reg, unsigned char value) | 125 | unsigned char reg, unsigned char value) |
123 | { | 126 | { |
@@ -941,6 +944,8 @@ int snd_ad1848_create(struct snd_card *card, | |||
941 | return 0; | 944 | return 0; |
942 | } | 945 | } |
943 | 946 | ||
947 | EXPORT_SYMBOL(snd_ad1848_create); | ||
948 | |||
944 | static struct snd_pcm_ops snd_ad1848_playback_ops = { | 949 | static struct snd_pcm_ops snd_ad1848_playback_ops = { |
945 | .open = snd_ad1848_playback_open, | 950 | .open = snd_ad1848_playback_open, |
946 | .close = snd_ad1848_playback_close, | 951 | .close = snd_ad1848_playback_close, |
@@ -988,12 +993,16 @@ int snd_ad1848_pcm(struct snd_ad1848 *chip, int device, struct snd_pcm **rpcm) | |||
988 | return 0; | 993 | return 0; |
989 | } | 994 | } |
990 | 995 | ||
996 | EXPORT_SYMBOL(snd_ad1848_pcm); | ||
997 | |||
991 | const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction) | 998 | const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction) |
992 | { | 999 | { |
993 | return direction == SNDRV_PCM_STREAM_PLAYBACK ? | 1000 | return direction == SNDRV_PCM_STREAM_PLAYBACK ? |
994 | &snd_ad1848_playback_ops : &snd_ad1848_capture_ops; | 1001 | &snd_ad1848_playback_ops : &snd_ad1848_capture_ops; |
995 | } | 1002 | } |
996 | 1003 | ||
1004 | EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); | ||
1005 | |||
997 | /* | 1006 | /* |
998 | * MIXER part | 1007 | * MIXER part |
999 | */ | 1008 | */ |
@@ -1171,7 +1180,8 @@ static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1171 | 1180 | ||
1172 | /* | 1181 | /* |
1173 | */ | 1182 | */ |
1174 | int snd_ad1848_add_ctl(struct snd_ad1848 *chip, const char *name, int index, int type, unsigned long value) | 1183 | int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, |
1184 | const struct ad1848_mix_elem *c) | ||
1175 | { | 1185 | { |
1176 | static struct snd_kcontrol_new newctls[] = { | 1186 | static struct snd_kcontrol_new newctls[] = { |
1177 | [AD1848_MIX_SINGLE] = { | 1187 | [AD1848_MIX_SINGLE] = { |
@@ -1196,32 +1206,46 @@ int snd_ad1848_add_ctl(struct snd_ad1848 *chip, const char *name, int index, int | |||
1196 | struct snd_kcontrol *ctl; | 1206 | struct snd_kcontrol *ctl; |
1197 | int err; | 1207 | int err; |
1198 | 1208 | ||
1199 | ctl = snd_ctl_new1(&newctls[type], chip); | 1209 | ctl = snd_ctl_new1(&newctls[c->type], chip); |
1200 | if (! ctl) | 1210 | if (! ctl) |
1201 | return -ENOMEM; | 1211 | return -ENOMEM; |
1202 | strlcpy(ctl->id.name, name, sizeof(ctl->id.name)); | 1212 | strlcpy(ctl->id.name, c->name, sizeof(ctl->id.name)); |
1203 | ctl->id.index = index; | 1213 | ctl->id.index = c->index; |
1204 | ctl->private_value = value; | 1214 | ctl->private_value = c->private_value; |
1215 | if (c->tlv) { | ||
1216 | ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
1217 | ctl->tlv.p = c->tlv; | ||
1218 | } | ||
1205 | if ((err = snd_ctl_add(chip->card, ctl)) < 0) | 1219 | if ((err = snd_ctl_add(chip->card, ctl)) < 0) |
1206 | return err; | 1220 | return err; |
1207 | return 0; | 1221 | return 0; |
1208 | } | 1222 | } |
1209 | 1223 | ||
1224 | EXPORT_SYMBOL(snd_ad1848_add_ctl_elem); | ||
1225 | |||
1226 | static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); | ||
1227 | static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); | ||
1228 | static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); | ||
1210 | 1229 | ||
1211 | static struct ad1848_mix_elem snd_ad1848_controls[] = { | 1230 | static struct ad1848_mix_elem snd_ad1848_controls[] = { |
1212 | AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), | 1231 | AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), |
1213 | AD1848_DOUBLE("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1), | 1232 | AD1848_DOUBLE_TLV("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1, |
1233 | db_scale_6bit), | ||
1214 | AD1848_DOUBLE("Aux Playback Switch", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | 1234 | AD1848_DOUBLE("Aux Playback Switch", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1), |
1215 | AD1848_DOUBLE("Aux Playback Volume", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1), | 1235 | AD1848_DOUBLE_TLV("Aux Playback Volume", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1, |
1236 | db_scale_5bit_12db_max), | ||
1216 | AD1848_DOUBLE("Aux Playback Switch", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | 1237 | AD1848_DOUBLE("Aux Playback Switch", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1), |
1217 | AD1848_DOUBLE("Aux Playback Volume", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1), | 1238 | AD1848_DOUBLE_TLV("Aux Playback Volume", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1, |
1218 | AD1848_DOUBLE("Capture Volume", 0, AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0), | 1239 | db_scale_5bit_12db_max), |
1240 | AD1848_DOUBLE_TLV("Capture Volume", 0, AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0, | ||
1241 | db_scale_rec_gain), | ||
1219 | { | 1242 | { |
1220 | .name = "Capture Source", | 1243 | .name = "Capture Source", |
1221 | .type = AD1848_MIX_CAPTURE, | 1244 | .type = AD1848_MIX_CAPTURE, |
1222 | }, | 1245 | }, |
1223 | AD1848_SINGLE("Loopback Capture Switch", 0, AD1848_LOOPBACK, 0, 1, 0), | 1246 | AD1848_SINGLE("Loopback Capture Switch", 0, AD1848_LOOPBACK, 0, 1, 0), |
1224 | AD1848_SINGLE("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0) | 1247 | AD1848_SINGLE_TLV("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0, |
1248 | db_scale_6bit), | ||
1225 | }; | 1249 | }; |
1226 | 1250 | ||
1227 | int snd_ad1848_mixer(struct snd_ad1848 *chip) | 1251 | int snd_ad1848_mixer(struct snd_ad1848 *chip) |
@@ -1245,12 +1269,7 @@ int snd_ad1848_mixer(struct snd_ad1848 *chip) | |||
1245 | return 0; | 1269 | return 0; |
1246 | } | 1270 | } |
1247 | 1271 | ||
1248 | EXPORT_SYMBOL(snd_ad1848_out); | ||
1249 | EXPORT_SYMBOL(snd_ad1848_create); | ||
1250 | EXPORT_SYMBOL(snd_ad1848_pcm); | ||
1251 | EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); | ||
1252 | EXPORT_SYMBOL(snd_ad1848_mixer); | 1272 | EXPORT_SYMBOL(snd_ad1848_mixer); |
1253 | EXPORT_SYMBOL(snd_ad1848_add_ctl); | ||
1254 | 1273 | ||
1255 | /* | 1274 | /* |
1256 | * INIT part | 1275 | * INIT part |
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 34998de9968c..85818200333f 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c | |||
@@ -2038,7 +2038,80 @@ MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver."); | |||
2038 | static struct platform_device *platform_devices[SNDRV_CARDS]; | 2038 | static struct platform_device *platform_devices[SNDRV_CARDS]; |
2039 | 2039 | ||
2040 | #ifdef CONFIG_PNP | 2040 | #ifdef CONFIG_PNP |
2041 | static int pnp_registered; | 2041 | static int pnp_registered, pnpc_registered; |
2042 | |||
2043 | static struct pnp_device_id snd_audiodrive_pnpbiosids[] = { | ||
2044 | { .id = "ESS1869" }, | ||
2045 | { .id = "" } /* end */ | ||
2046 | }; | ||
2047 | |||
2048 | MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids); | ||
2049 | |||
2050 | /* PnP main device initialization */ | ||
2051 | static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev, | ||
2052 | struct pnp_resource_table *cfg) | ||
2053 | { | ||
2054 | int err; | ||
2055 | |||
2056 | pnp_init_resource_table(cfg); | ||
2057 | if (port[dev] != SNDRV_AUTO_PORT) | ||
2058 | pnp_resource_change(&cfg->port_resource[0], port[dev], 16); | ||
2059 | if (fm_port[dev] != SNDRV_AUTO_PORT) | ||
2060 | pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4); | ||
2061 | if (mpu_port[dev] != SNDRV_AUTO_PORT) | ||
2062 | pnp_resource_change(&cfg->port_resource[2], mpu_port[dev], 2); | ||
2063 | if (dma1[dev] != SNDRV_AUTO_DMA) | ||
2064 | pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1); | ||
2065 | if (dma2[dev] != SNDRV_AUTO_DMA) | ||
2066 | pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1); | ||
2067 | if (irq[dev] != SNDRV_AUTO_IRQ) | ||
2068 | pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1); | ||
2069 | if (pnp_device_is_isapnp(pdev)) { | ||
2070 | err = pnp_manual_config_dev(pdev, cfg, 0); | ||
2071 | if (err < 0) | ||
2072 | snd_printk(KERN_ERR PFX "PnP manual resources are invalid, using auto config\n"); | ||
2073 | } | ||
2074 | err = pnp_activate_dev(pdev); | ||
2075 | if (err < 0) { | ||
2076 | snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n"); | ||
2077 | return -EBUSY; | ||
2078 | } | ||
2079 | /* ok. hack using Vendor-Defined Card-Level registers */ | ||
2080 | /* skip csn and logdev initialization - already done in isapnp_configure */ | ||
2081 | if (pnp_device_is_isapnp(pdev)) { | ||
2082 | isapnp_cfg_begin(isapnp_card_number(pdev), isapnp_csn_number(pdev)); | ||
2083 | isapnp_write_byte(0x27, pnp_irq(pdev, 0)); /* Hardware Volume IRQ Number */ | ||
2084 | if (mpu_port[dev] != SNDRV_AUTO_PORT) | ||
2085 | isapnp_write_byte(0x28, pnp_irq(pdev, 0)); /* MPU-401 IRQ Number */ | ||
2086 | isapnp_write_byte(0x72, pnp_irq(pdev, 0)); /* second IRQ */ | ||
2087 | isapnp_cfg_end(); | ||
2088 | } | ||
2089 | port[dev] = pnp_port_start(pdev, 0); | ||
2090 | fm_port[dev] = pnp_port_start(pdev, 1); | ||
2091 | mpu_port[dev] = pnp_port_start(pdev, 2); | ||
2092 | dma1[dev] = pnp_dma(pdev, 0); | ||
2093 | dma2[dev] = pnp_dma(pdev, 1); | ||
2094 | irq[dev] = pnp_irq(pdev, 0); | ||
2095 | snd_printdd("PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", port[dev], fm_port[dev], mpu_port[dev]); | ||
2096 | snd_printdd("PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); | ||
2097 | return 0; | ||
2098 | } | ||
2099 | |||
2100 | static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard, | ||
2101 | struct pnp_dev *pdev) | ||
2102 | { | ||
2103 | struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); | ||
2104 | |||
2105 | if (!cfg) | ||
2106 | return -ENOMEM; | ||
2107 | acard->dev = pdev; | ||
2108 | if (snd_audiodrive_pnp_init_main(dev, acard->dev, cfg) < 0) { | ||
2109 | kfree(cfg); | ||
2110 | return -EBUSY; | ||
2111 | } | ||
2112 | kfree(cfg); | ||
2113 | return 0; | ||
2114 | } | ||
2042 | 2115 | ||
2043 | static struct pnp_card_device_id snd_audiodrive_pnpids[] = { | 2116 | static struct pnp_card_device_id snd_audiodrive_pnpids[] = { |
2044 | /* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */ | 2117 | /* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */ |
@@ -2061,13 +2134,11 @@ static struct pnp_card_device_id snd_audiodrive_pnpids[] = { | |||
2061 | 2134 | ||
2062 | MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids); | 2135 | MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids); |
2063 | 2136 | ||
2064 | static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard, | 2137 | static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard, |
2065 | struct pnp_card_link *card, | 2138 | struct pnp_card_link *card, |
2066 | const struct pnp_card_device_id *id) | 2139 | const struct pnp_card_device_id *id) |
2067 | { | 2140 | { |
2068 | struct pnp_dev *pdev; | ||
2069 | struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); | 2141 | struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); |
2070 | int err; | ||
2071 | 2142 | ||
2072 | if (!cfg) | 2143 | if (!cfg) |
2073 | return -ENOMEM; | 2144 | return -ENOMEM; |
@@ -2082,58 +2153,16 @@ static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard, | |||
2082 | return -EBUSY; | 2153 | return -EBUSY; |
2083 | } | 2154 | } |
2084 | /* Control port initialization */ | 2155 | /* Control port initialization */ |
2085 | err = pnp_activate_dev(acard->devc); | 2156 | if (pnp_activate_dev(acard->devc) < 0) { |
2086 | if (err < 0) { | ||
2087 | snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n"); | 2157 | snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n"); |
2088 | kfree(cfg); | ||
2089 | return -EAGAIN; | 2158 | return -EAGAIN; |
2090 | } | 2159 | } |
2091 | snd_printdd("pnp: port=0x%llx\n", | 2160 | snd_printdd("pnp: port=0x%llx\n", |
2092 | (unsigned long long)pnp_port_start(acard->devc, 0)); | 2161 | (unsigned long long)pnp_port_start(acard->devc, 0)); |
2093 | /* PnP initialization */ | 2162 | if (snd_audiodrive_pnp_init_main(dev, acard->dev, cfg) < 0) { |
2094 | pdev = acard->dev; | ||
2095 | pnp_init_resource_table(cfg); | ||
2096 | if (port[dev] != SNDRV_AUTO_PORT) | ||
2097 | pnp_resource_change(&cfg->port_resource[0], port[dev], 16); | ||
2098 | if (fm_port[dev] != SNDRV_AUTO_PORT) | ||
2099 | pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4); | ||
2100 | if (mpu_port[dev] != SNDRV_AUTO_PORT) | ||
2101 | pnp_resource_change(&cfg->port_resource[2], mpu_port[dev], 2); | ||
2102 | if (dma1[dev] != SNDRV_AUTO_DMA) | ||
2103 | pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1); | ||
2104 | if (dma2[dev] != SNDRV_AUTO_DMA) | ||
2105 | pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1); | ||
2106 | if (irq[dev] != SNDRV_AUTO_IRQ) | ||
2107 | pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1); | ||
2108 | err = pnp_manual_config_dev(pdev, cfg, 0); | ||
2109 | if (err < 0) | ||
2110 | snd_printk(KERN_ERR PFX "PnP manual resources are invalid, using auto config\n"); | ||
2111 | err = pnp_activate_dev(pdev); | ||
2112 | if (err < 0) { | ||
2113 | snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n"); | ||
2114 | kfree(cfg); | 2163 | kfree(cfg); |
2115 | return -EBUSY; | 2164 | return -EBUSY; |
2116 | } | 2165 | } |
2117 | /* ok. hack using Vendor-Defined Card-Level registers */ | ||
2118 | /* skip csn and logdev initialization - already done in isapnp_configure */ | ||
2119 | if (pnp_device_is_isapnp(pdev)) { | ||
2120 | isapnp_cfg_begin(isapnp_card_number(pdev), isapnp_csn_number(pdev)); | ||
2121 | isapnp_write_byte(0x27, pnp_irq(pdev, 0)); /* Hardware Volume IRQ Number */ | ||
2122 | if (mpu_port[dev] != SNDRV_AUTO_PORT) | ||
2123 | isapnp_write_byte(0x28, pnp_irq(pdev, 0)); /* MPU-401 IRQ Number */ | ||
2124 | isapnp_write_byte(0x72, pnp_irq(pdev, 0)); /* second IRQ */ | ||
2125 | isapnp_cfg_end(); | ||
2126 | } else { | ||
2127 | snd_printk(KERN_ERR PFX "unable to install ISA PnP hack, expect malfunction\n"); | ||
2128 | } | ||
2129 | port[dev] = pnp_port_start(pdev, 0); | ||
2130 | fm_port[dev] = pnp_port_start(pdev, 1); | ||
2131 | mpu_port[dev] = pnp_port_start(pdev, 2); | ||
2132 | dma1[dev] = pnp_dma(pdev, 0); | ||
2133 | dma2[dev] = pnp_dma(pdev, 1); | ||
2134 | irq[dev] = pnp_irq(pdev, 0); | ||
2135 | snd_printdd("PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", port[dev], fm_port[dev], mpu_port[dev]); | ||
2136 | snd_printdd("PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); | ||
2137 | kfree(cfg); | 2166 | kfree(cfg); |
2138 | return 0; | 2167 | return 0; |
2139 | } | 2168 | } |
@@ -2302,7 +2331,69 @@ static struct platform_driver snd_es18xx_nonpnp_driver = { | |||
2302 | #ifdef CONFIG_PNP | 2331 | #ifdef CONFIG_PNP |
2303 | static unsigned int __devinitdata es18xx_pnp_devices; | 2332 | static unsigned int __devinitdata es18xx_pnp_devices; |
2304 | 2333 | ||
2305 | static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard, | 2334 | static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, |
2335 | const struct pnp_device_id *id) | ||
2336 | { | ||
2337 | static int dev; | ||
2338 | int err; | ||
2339 | struct snd_card *card; | ||
2340 | |||
2341 | if (pnp_device_is_isapnp(pdev)) | ||
2342 | return -ENOENT; /* we have another procedure - card */ | ||
2343 | for (; dev < SNDRV_CARDS; dev++) { | ||
2344 | if (enable[dev] && isapnp[dev]) | ||
2345 | break; | ||
2346 | } | ||
2347 | if (dev >= SNDRV_CARDS) | ||
2348 | return -ENODEV; | ||
2349 | |||
2350 | card = snd_es18xx_card_new(dev); | ||
2351 | if (! card) | ||
2352 | return -ENOMEM; | ||
2353 | if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) { | ||
2354 | snd_card_free(card); | ||
2355 | return err; | ||
2356 | } | ||
2357 | snd_card_set_dev(card, &pdev->dev); | ||
2358 | if ((err = snd_audiodrive_probe(card, dev)) < 0) { | ||
2359 | snd_card_free(card); | ||
2360 | return err; | ||
2361 | } | ||
2362 | pnp_set_drvdata(pdev, card); | ||
2363 | dev++; | ||
2364 | es18xx_pnp_devices++; | ||
2365 | return 0; | ||
2366 | } | ||
2367 | |||
2368 | static void __devexit snd_audiodrive_pnp_remove(struct pnp_dev * pdev) | ||
2369 | { | ||
2370 | snd_card_free(pnp_get_drvdata(pdev)); | ||
2371 | pnp_set_drvdata(pdev, NULL); | ||
2372 | } | ||
2373 | |||
2374 | #ifdef CONFIG_PM | ||
2375 | static int snd_audiodrive_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) | ||
2376 | { | ||
2377 | return snd_es18xx_suspend(pnp_get_drvdata(pdev), state); | ||
2378 | } | ||
2379 | static int snd_audiodrive_pnp_resume(struct pnp_dev *pdev) | ||
2380 | { | ||
2381 | return snd_es18xx_resume(pnp_get_drvdata(pdev)); | ||
2382 | } | ||
2383 | #endif | ||
2384 | |||
2385 | static struct pnp_driver es18xx_pnp_driver = { | ||
2386 | .name = "es18xx-pnpbios", | ||
2387 | .id_table = snd_audiodrive_pnpbiosids, | ||
2388 | .probe = snd_audiodrive_pnp_detect, | ||
2389 | .remove = __devexit_p(snd_audiodrive_pnp_remove), | ||
2390 | #ifdef CONFIG_PM | ||
2391 | .suspend = snd_audiodrive_pnp_suspend, | ||
2392 | .resume = snd_audiodrive_pnp_resume, | ||
2393 | #endif | ||
2394 | }; | ||
2395 | |||
2396 | static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, | ||
2306 | const struct pnp_card_device_id *pid) | 2397 | const struct pnp_card_device_id *pid) |
2307 | { | 2398 | { |
2308 | static int dev; | 2399 | static int dev; |
@@ -2320,7 +2411,7 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard, | |||
2320 | if (! card) | 2411 | if (! card) |
2321 | return -ENOMEM; | 2412 | return -ENOMEM; |
2322 | 2413 | ||
2323 | if ((res = snd_audiodrive_pnp(dev, card->private_data, pcard, pid)) < 0) { | 2414 | if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) { |
2324 | snd_card_free(card); | 2415 | snd_card_free(card); |
2325 | return res; | 2416 | return res; |
2326 | } | 2417 | } |
@@ -2336,19 +2427,19 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard, | |||
2336 | return 0; | 2427 | return 0; |
2337 | } | 2428 | } |
2338 | 2429 | ||
2339 | static void __devexit snd_audiodrive_pnp_remove(struct pnp_card_link * pcard) | 2430 | static void __devexit snd_audiodrive_pnpc_remove(struct pnp_card_link * pcard) |
2340 | { | 2431 | { |
2341 | snd_card_free(pnp_get_card_drvdata(pcard)); | 2432 | snd_card_free(pnp_get_card_drvdata(pcard)); |
2342 | pnp_set_card_drvdata(pcard, NULL); | 2433 | pnp_set_card_drvdata(pcard, NULL); |
2343 | } | 2434 | } |
2344 | 2435 | ||
2345 | #ifdef CONFIG_PM | 2436 | #ifdef CONFIG_PM |
2346 | static int snd_audiodrive_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) | 2437 | static int snd_audiodrive_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state) |
2347 | { | 2438 | { |
2348 | return snd_es18xx_suspend(pnp_get_card_drvdata(pcard), state); | 2439 | return snd_es18xx_suspend(pnp_get_card_drvdata(pcard), state); |
2349 | } | 2440 | } |
2350 | 2441 | ||
2351 | static int snd_audiodrive_pnp_resume(struct pnp_card_link *pcard) | 2442 | static int snd_audiodrive_pnpc_resume(struct pnp_card_link *pcard) |
2352 | { | 2443 | { |
2353 | return snd_es18xx_resume(pnp_get_card_drvdata(pcard)); | 2444 | return snd_es18xx_resume(pnp_get_card_drvdata(pcard)); |
2354 | } | 2445 | } |
@@ -2359,11 +2450,11 @@ static struct pnp_card_driver es18xx_pnpc_driver = { | |||
2359 | .flags = PNP_DRIVER_RES_DISABLE, | 2450 | .flags = PNP_DRIVER_RES_DISABLE, |
2360 | .name = "es18xx", | 2451 | .name = "es18xx", |
2361 | .id_table = snd_audiodrive_pnpids, | 2452 | .id_table = snd_audiodrive_pnpids, |
2362 | .probe = snd_audiodrive_pnp_detect, | 2453 | .probe = snd_audiodrive_pnpc_detect, |
2363 | .remove = __devexit_p(snd_audiodrive_pnp_remove), | 2454 | .remove = __devexit_p(snd_audiodrive_pnpc_remove), |
2364 | #ifdef CONFIG_PM | 2455 | #ifdef CONFIG_PM |
2365 | .suspend = snd_audiodrive_pnp_suspend, | 2456 | .suspend = snd_audiodrive_pnpc_suspend, |
2366 | .resume = snd_audiodrive_pnp_resume, | 2457 | .resume = snd_audiodrive_pnpc_resume, |
2367 | #endif | 2458 | #endif |
2368 | }; | 2459 | }; |
2369 | #endif /* CONFIG_PNP */ | 2460 | #endif /* CONFIG_PNP */ |
@@ -2373,8 +2464,10 @@ static void __init_or_module snd_es18xx_unregister_all(void) | |||
2373 | int i; | 2464 | int i; |
2374 | 2465 | ||
2375 | #ifdef CONFIG_PNP | 2466 | #ifdef CONFIG_PNP |
2376 | if (pnp_registered) | 2467 | if (pnpc_registered) |
2377 | pnp_unregister_card_driver(&es18xx_pnpc_driver); | 2468 | pnp_unregister_card_driver(&es18xx_pnpc_driver); |
2469 | if (pnp_registered) | ||
2470 | pnp_unregister_driver(&es18xx_pnp_driver); | ||
2378 | #endif | 2471 | #endif |
2379 | for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) | 2472 | for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) |
2380 | platform_device_unregister(platform_devices[i]); | 2473 | platform_device_unregister(platform_devices[i]); |
@@ -2405,11 +2498,13 @@ static int __init alsa_card_es18xx_init(void) | |||
2405 | } | 2498 | } |
2406 | 2499 | ||
2407 | #ifdef CONFIG_PNP | 2500 | #ifdef CONFIG_PNP |
2408 | err = pnp_register_card_driver(&es18xx_pnpc_driver); | 2501 | err = pnp_register_driver(&es18xx_pnp_driver); |
2409 | if (!err) { | 2502 | if (!err) |
2410 | pnp_registered = 1; | 2503 | pnp_registered = 1; |
2411 | cards += es18xx_pnp_devices; | 2504 | err = pnp_register_card_driver(&es18xx_pnpc_driver); |
2412 | } | 2505 | if (!err) |
2506 | pnpc_registered = 1; | ||
2507 | cards += es18xx_pnp_devices; | ||
2413 | #endif | 2508 | #endif |
2414 | 2509 | ||
2415 | if(!cards) { | 2510 | if(!cards) { |
diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c index 4080255007d5..80f0a83818b2 100644 --- a/sound/isa/gus/gus_mem_proc.c +++ b/sound/isa/gus/gus_mem_proc.c | |||
@@ -61,13 +61,13 @@ static long long snd_gf1_mem_proc_llseek(struct snd_info_entry *entry, | |||
61 | struct gus_proc_private *priv = entry->private_data; | 61 | struct gus_proc_private *priv = entry->private_data; |
62 | 62 | ||
63 | switch (orig) { | 63 | switch (orig) { |
64 | case 0: /* SEEK_SET */ | 64 | case SEEK_SET: |
65 | file->f_pos = offset; | 65 | file->f_pos = offset; |
66 | break; | 66 | break; |
67 | case 1: /* SEEK_CUR */ | 67 | case SEEK_CUR: |
68 | file->f_pos += offset; | 68 | file->f_pos += offset; |
69 | break; | 69 | break; |
70 | case 2: /* SEEK_END, offset is negative */ | 70 | case SEEK_END: /* offset is negative */ |
71 | file->f_pos = priv->size + offset; | 71 | file->f_pos = priv->size + offset; |
72 | break; | 72 | break; |
73 | default: | 73 | default: |
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 4031b61b797f..da92bf6c392b 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <sound/mpu401.h> | 33 | #include <sound/mpu401.h> |
34 | #include <sound/opl3.h> | 34 | #include <sound/opl3.h> |
35 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
36 | #include <sound/tlv.h> | ||
36 | 37 | ||
37 | #include <asm/io.h> | 38 | #include <asm/io.h> |
38 | 39 | ||
@@ -337,6 +338,14 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id, struct pt_regs * | |||
337 | .info = snd_opl3sa2_info_single, \ | 338 | .info = snd_opl3sa2_info_single, \ |
338 | .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ | 339 | .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ |
339 | .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } | 340 | .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } |
341 | #define OPL3SA2_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ | ||
342 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
343 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
344 | .name = xname, .index = xindex, \ | ||
345 | .info = snd_opl3sa2_info_single, \ | ||
346 | .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ | ||
347 | .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ | ||
348 | .tlv = { .p = (xtlv) } } | ||
340 | 349 | ||
341 | static int snd_opl3sa2_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 350 | static int snd_opl3sa2_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
342 | { | 351 | { |
@@ -395,6 +404,14 @@ static int snd_opl3sa2_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
395 | .info = snd_opl3sa2_info_double, \ | 404 | .info = snd_opl3sa2_info_double, \ |
396 | .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ | 405 | .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ |
397 | .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } | 406 | .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } |
407 | #define OPL3SA2_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ | ||
408 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
409 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
410 | .name = xname, .index = xindex, \ | ||
411 | .info = snd_opl3sa2_info_double, \ | ||
412 | .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ | ||
413 | .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \ | ||
414 | .tlv = { .p = (xtlv) } } | ||
398 | 415 | ||
399 | static int snd_opl3sa2_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 416 | static int snd_opl3sa2_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
400 | { | 417 | { |
@@ -469,11 +486,16 @@ static int snd_opl3sa2_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
469 | return change; | 486 | return change; |
470 | } | 487 | } |
471 | 488 | ||
489 | static DECLARE_TLV_DB_SCALE(db_scale_master, -3000, 200, 0); | ||
490 | static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); | ||
491 | |||
472 | static struct snd_kcontrol_new snd_opl3sa2_controls[] = { | 492 | static struct snd_kcontrol_new snd_opl3sa2_controls[] = { |
473 | OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1), | 493 | OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1), |
474 | OPL3SA2_DOUBLE("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1), | 494 | OPL3SA2_DOUBLE_TLV("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1, |
495 | db_scale_master), | ||
475 | OPL3SA2_SINGLE("Mic Playback Switch", 0, 0x09, 7, 1, 1), | 496 | OPL3SA2_SINGLE("Mic Playback Switch", 0, 0x09, 7, 1, 1), |
476 | OPL3SA2_SINGLE("Mic Playback Volume", 0, 0x09, 0, 31, 1) | 497 | OPL3SA2_SINGLE_TLV("Mic Playback Volume", 0, 0x09, 0, 31, 1, |
498 | db_scale_5bit_12db_max), | ||
477 | }; | 499 | }; |
478 | 500 | ||
479 | static struct snd_kcontrol_new snd_opl3sa2_tone_controls[] = { | 501 | static struct snd_kcontrol_new snd_opl3sa2_tone_controls[] = { |