diff options
Diffstat (limited to 'sound/isa')
-rw-r--r-- | sound/isa/es18xx.c | 99 |
1 files changed, 90 insertions, 9 deletions
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index bde9860327fe..0488eba051e9 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c | |||
@@ -939,37 +939,118 @@ static int snd_es18xx_capture_close(struct snd_pcm_substream *substream) | |||
939 | * MIXER part | 939 | * MIXER part |
940 | */ | 940 | */ |
941 | 941 | ||
942 | /* Record source mux routines: | ||
943 | * Depending on the chipset this mux switches between 4, 5, or 8 possible inputs. | ||
944 | * bit table for the 4/5 source mux: | ||
945 | * reg 1C: | ||
946 | * b2 b1 b0 muxSource | ||
947 | * x 0 x microphone | ||
948 | * 0 1 x CD | ||
949 | * 1 1 0 line | ||
950 | * 1 1 1 mixer | ||
951 | * if it's "mixer" and it's a 5 source mux chipset then reg 7A bit 3 determines | ||
952 | * either the play mixer or the capture mixer. | ||
953 | * | ||
954 | * "map4Source" translates from source number to reg bit pattern | ||
955 | * "invMap4Source" translates from reg bit pattern to source number | ||
956 | */ | ||
957 | |||
942 | static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 958 | static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
943 | { | 959 | { |
944 | static char *texts[8] = { | 960 | static char *texts4Source[4] = { |
961 | "Mic", "CD", "Line", "Master" | ||
962 | }; | ||
963 | static char *texts5Source[5] = { | ||
964 | "Mic", "CD", "Line", "Master", "Mix" | ||
965 | }; | ||
966 | static char *texts8Source[8] = { | ||
945 | "Mic", "Mic Master", "CD", "AOUT", | 967 | "Mic", "Mic Master", "CD", "AOUT", |
946 | "Mic1", "Mix", "Line", "Master" | 968 | "Mic1", "Mix", "Line", "Master" |
947 | }; | 969 | }; |
970 | struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); | ||
948 | 971 | ||
949 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 972 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
950 | uinfo->count = 1; | 973 | uinfo->count = 1; |
951 | uinfo->value.enumerated.items = 8; | 974 | switch (chip->version) { |
952 | if (uinfo->value.enumerated.item > 7) | 975 | case 0x1868: |
953 | uinfo->value.enumerated.item = 7; | 976 | case 0x1878: |
954 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | 977 | uinfo->value.enumerated.items = 4; |
978 | if (uinfo->value.enumerated.item > 3) | ||
979 | uinfo->value.enumerated.item = 3; | ||
980 | strcpy(uinfo->value.enumerated.name, texts4Source[uinfo->value.enumerated.item]); | ||
981 | break; | ||
982 | case 0x1887: | ||
983 | case 0x1888: | ||
984 | uinfo->value.enumerated.items = 5; | ||
985 | if (uinfo->value.enumerated.item > 4) | ||
986 | uinfo->value.enumerated.item = 4; | ||
987 | strcpy(uinfo->value.enumerated.name, texts5Source[uinfo->value.enumerated.item]); | ||
988 | break; | ||
989 | case 0x1869: /* DS somewhat contradictory for 1869: could be be 5 or 8 */ | ||
990 | case 0x1879: | ||
991 | uinfo->value.enumerated.items = 8; | ||
992 | if (uinfo->value.enumerated.item > 7) | ||
993 | uinfo->value.enumerated.item = 7; | ||
994 | strcpy(uinfo->value.enumerated.name, texts8Source[uinfo->value.enumerated.item]); | ||
995 | break; | ||
996 | default: | ||
997 | return -EINVAL; | ||
998 | } | ||
955 | return 0; | 999 | return 0; |
956 | } | 1000 | } |
957 | 1001 | ||
958 | static int snd_es18xx_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1002 | static int snd_es18xx_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
959 | { | 1003 | { |
1004 | static unsigned char invMap4Source[8] = {0, 0, 1, 1, 0, 0, 2, 3}; | ||
960 | struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); | 1005 | struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); |
961 | ucontrol->value.enumerated.item[0] = snd_es18xx_mixer_read(chip, 0x1c) & 0x07; | 1006 | int muxSource = snd_es18xx_mixer_read(chip, 0x1c) & 0x07; |
1007 | if (!(chip->version == 0x1869 || chip->version == 0x1879)) { | ||
1008 | muxSource = invMap4Source[muxSource]; | ||
1009 | if (muxSource==3 && | ||
1010 | (chip->version == 0x1887 || chip->version == 0x1888) && | ||
1011 | (snd_es18xx_mixer_read(chip, 0x7a) & 0x08) | ||
1012 | ) | ||
1013 | muxSource = 4; | ||
1014 | } | ||
1015 | ucontrol->value.enumerated.item[0] = muxSource; | ||
962 | return 0; | 1016 | return 0; |
963 | } | 1017 | } |
964 | 1018 | ||
965 | static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1019 | static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
966 | { | 1020 | { |
1021 | static unsigned char map4Source[4] = {0, 2, 6, 7}; | ||
967 | struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); | 1022 | struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); |
968 | unsigned char val = ucontrol->value.enumerated.item[0]; | 1023 | unsigned char val = ucontrol->value.enumerated.item[0]; |
969 | 1024 | unsigned char retVal = 0; | |
970 | if (val > 7) | 1025 | |
1026 | switch (chip->version) { | ||
1027 | /* 5 source chips */ | ||
1028 | case 0x1887: | ||
1029 | case 0x1888: | ||
1030 | if (val > 4) | ||
1031 | return -EINVAL; | ||
1032 | if (val == 4) { | ||
1033 | retVal = snd_es18xx_mixer_bits(chip, 0x7a, 0x08, 0x08) != 0x08; | ||
1034 | val = 3; | ||
1035 | } else | ||
1036 | retVal = snd_es18xx_mixer_bits(chip, 0x7a, 0x08, 0x00) != 0x00; | ||
1037 | /* 4 source chips */ | ||
1038 | case 0x1868: | ||
1039 | case 0x1878: | ||
1040 | if (val > 3) | ||
1041 | return -EINVAL; | ||
1042 | val = map4Source[val]; | ||
1043 | break; | ||
1044 | /* 8 source chips */ | ||
1045 | case 0x1869: | ||
1046 | case 0x1879: | ||
1047 | if (val > 7) | ||
1048 | return -EINVAL; | ||
1049 | break; | ||
1050 | default: | ||
971 | return -EINVAL; | 1051 | return -EINVAL; |
972 | return snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val; | 1052 | } |
1053 | return (snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val) || retVal; | ||
973 | } | 1054 | } |
974 | 1055 | ||
975 | static int snd_es18xx_info_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1056 | static int snd_es18xx_info_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |