diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/isa/ad1848/ad1848.c | 2 | ||||
-rw-r--r-- | sound/isa/ad1848/ad1848_lib.c | 261 | ||||
-rw-r--r-- | sound/isa/opti9xx/opti92x-ad1848.c | 22 | ||||
-rw-r--r-- | sound/isa/sc6000.c | 4 | ||||
-rw-r--r-- | sound/isa/sgalaxy.c | 5 | ||||
-rw-r--r-- | sound/isa/wss/wss_lib.c | 61 |
6 files changed, 73 insertions, 282 deletions
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 40de24b280d3..d5a96631587c 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c | |||
@@ -106,7 +106,7 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) | |||
106 | if (error < 0) | 106 | if (error < 0) |
107 | goto out; | 107 | goto out; |
108 | 108 | ||
109 | error = snd_ad1848_mixer(chip); | 109 | error = snd_wss_mixer(chip); |
110 | if (error < 0) | 110 | if (error < 0) |
111 | goto out; | 111 | goto out; |
112 | 112 | ||
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 07756fa36947..5de046014337 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c | |||
@@ -995,267 +995,6 @@ const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction) | |||
995 | EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); | 995 | EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); |
996 | 996 | ||
997 | /* | 997 | /* |
998 | * MIXER part | ||
999 | */ | ||
1000 | |||
1001 | static int snd_ad1848_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
1002 | { | ||
1003 | static char *texts[4] = { | ||
1004 | "Line", "Aux", "Mic", "Mix" | ||
1005 | }; | ||
1006 | |||
1007 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1008 | uinfo->count = 2; | ||
1009 | uinfo->value.enumerated.items = 4; | ||
1010 | if (uinfo->value.enumerated.item > 3) | ||
1011 | uinfo->value.enumerated.item = 3; | ||
1012 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | static int snd_ad1848_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
1017 | { | ||
1018 | struct snd_wss *chip = snd_kcontrol_chip(kcontrol); | ||
1019 | unsigned long flags; | ||
1020 | |||
1021 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
1022 | ucontrol->value.enumerated.item[0] = (chip->image[AD1848_LEFT_INPUT] & AD1848_MIXS_ALL) >> 6; | ||
1023 | ucontrol->value.enumerated.item[1] = (chip->image[AD1848_RIGHT_INPUT] & AD1848_MIXS_ALL) >> 6; | ||
1024 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | static int snd_ad1848_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
1029 | { | ||
1030 | struct snd_wss *chip = snd_kcontrol_chip(kcontrol); | ||
1031 | unsigned long flags; | ||
1032 | unsigned short left, right; | ||
1033 | int change; | ||
1034 | |||
1035 | if (ucontrol->value.enumerated.item[0] > 3 || | ||
1036 | ucontrol->value.enumerated.item[1] > 3) | ||
1037 | return -EINVAL; | ||
1038 | left = ucontrol->value.enumerated.item[0] << 6; | ||
1039 | right = ucontrol->value.enumerated.item[1] << 6; | ||
1040 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
1041 | left = (chip->image[AD1848_LEFT_INPUT] & ~AD1848_MIXS_ALL) | left; | ||
1042 | right = (chip->image[AD1848_RIGHT_INPUT] & ~AD1848_MIXS_ALL) | right; | ||
1043 | change = left != chip->image[AD1848_LEFT_INPUT] || | ||
1044 | right != chip->image[AD1848_RIGHT_INPUT]; | ||
1045 | snd_ad1848_out(chip, AD1848_LEFT_INPUT, left); | ||
1046 | snd_ad1848_out(chip, AD1848_RIGHT_INPUT, right); | ||
1047 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1048 | return change; | ||
1049 | } | ||
1050 | |||
1051 | static int snd_ad1848_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
1052 | { | ||
1053 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
1054 | |||
1055 | uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1056 | uinfo->count = 1; | ||
1057 | uinfo->value.integer.min = 0; | ||
1058 | uinfo->value.integer.max = mask; | ||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | static int snd_ad1848_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
1063 | { | ||
1064 | struct snd_wss *chip = snd_kcontrol_chip(kcontrol); | ||
1065 | unsigned long flags; | ||
1066 | int reg = kcontrol->private_value & 0xff; | ||
1067 | int shift = (kcontrol->private_value >> 8) & 0xff; | ||
1068 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
1069 | int invert = (kcontrol->private_value >> 24) & 0xff; | ||
1070 | |||
1071 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
1072 | ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; | ||
1073 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1074 | if (invert) | ||
1075 | ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; | ||
1076 | return 0; | ||
1077 | } | ||
1078 | |||
1079 | static int snd_ad1848_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
1080 | { | ||
1081 | struct snd_wss *chip = snd_kcontrol_chip(kcontrol); | ||
1082 | unsigned long flags; | ||
1083 | int reg = kcontrol->private_value & 0xff; | ||
1084 | int shift = (kcontrol->private_value >> 8) & 0xff; | ||
1085 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
1086 | int invert = (kcontrol->private_value >> 24) & 0xff; | ||
1087 | int change; | ||
1088 | unsigned short val; | ||
1089 | |||
1090 | val = (ucontrol->value.integer.value[0] & mask); | ||
1091 | if (invert) | ||
1092 | val = mask - val; | ||
1093 | val <<= shift; | ||
1094 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
1095 | val = (chip->image[reg] & ~(mask << shift)) | val; | ||
1096 | change = val != chip->image[reg]; | ||
1097 | snd_ad1848_out(chip, reg, val); | ||
1098 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1099 | return change; | ||
1100 | } | ||
1101 | |||
1102 | static int snd_ad1848_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
1103 | { | ||
1104 | int mask = (kcontrol->private_value >> 24) & 0xff; | ||
1105 | |||
1106 | uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1107 | uinfo->count = 2; | ||
1108 | uinfo->value.integer.min = 0; | ||
1109 | uinfo->value.integer.max = mask; | ||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | static int snd_ad1848_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
1114 | { | ||
1115 | struct snd_wss *chip = snd_kcontrol_chip(kcontrol); | ||
1116 | unsigned long flags; | ||
1117 | int left_reg = kcontrol->private_value & 0xff; | ||
1118 | int right_reg = (kcontrol->private_value >> 8) & 0xff; | ||
1119 | int shift_left = (kcontrol->private_value >> 16) & 0x07; | ||
1120 | int shift_right = (kcontrol->private_value >> 19) & 0x07; | ||
1121 | int mask = (kcontrol->private_value >> 24) & 0xff; | ||
1122 | int invert = (kcontrol->private_value >> 22) & 1; | ||
1123 | |||
1124 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
1125 | ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; | ||
1126 | ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask; | ||
1127 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1128 | if (invert) { | ||
1129 | ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; | ||
1130 | ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; | ||
1131 | } | ||
1132 | return 0; | ||
1133 | } | ||
1134 | |||
1135 | static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
1136 | { | ||
1137 | struct snd_wss *chip = snd_kcontrol_chip(kcontrol); | ||
1138 | unsigned long flags; | ||
1139 | int left_reg = kcontrol->private_value & 0xff; | ||
1140 | int right_reg = (kcontrol->private_value >> 8) & 0xff; | ||
1141 | int shift_left = (kcontrol->private_value >> 16) & 0x07; | ||
1142 | int shift_right = (kcontrol->private_value >> 19) & 0x07; | ||
1143 | int mask = (kcontrol->private_value >> 24) & 0xff; | ||
1144 | int invert = (kcontrol->private_value >> 22) & 1; | ||
1145 | int change; | ||
1146 | unsigned short val1, val2; | ||
1147 | |||
1148 | val1 = ucontrol->value.integer.value[0] & mask; | ||
1149 | val2 = ucontrol->value.integer.value[1] & mask; | ||
1150 | if (invert) { | ||
1151 | val1 = mask - val1; | ||
1152 | val2 = mask - val2; | ||
1153 | } | ||
1154 | val1 <<= shift_left; | ||
1155 | val2 <<= shift_right; | ||
1156 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
1157 | if (left_reg != right_reg) { | ||
1158 | val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; | ||
1159 | val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; | ||
1160 | change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg]; | ||
1161 | snd_ad1848_out(chip, left_reg, val1); | ||
1162 | snd_ad1848_out(chip, right_reg, val2); | ||
1163 | } else { | ||
1164 | val1 = (chip->image[left_reg] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; | ||
1165 | change = val1 != chip->image[left_reg]; | ||
1166 | snd_ad1848_out(chip, left_reg, val1); | ||
1167 | } | ||
1168 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1169 | return change; | ||
1170 | } | ||
1171 | |||
1172 | static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); | ||
1173 | static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); | ||
1174 | static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); | ||
1175 | |||
1176 | #define AD1848_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ | ||
1177 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1178 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
1179 | .name = xname, \ | ||
1180 | .index = xindex, \ | ||
1181 | .info = snd_ad1848_info_single, \ | ||
1182 | .get = snd_ad1848_get_single, \ | ||
1183 | .put = snd_ad1848_put_single, \ | ||
1184 | .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ | ||
1185 | .tlv = { .p = (xtlv) } } | ||
1186 | |||
1187 | #define AD1848_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ | ||
1188 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1189 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
1190 | .name = xname, \ | ||
1191 | .index = xindex, \ | ||
1192 | .info = snd_ad1848_info_double, \ | ||
1193 | .get = snd_ad1848_get_double, \ | ||
1194 | .put = snd_ad1848_put_double, \ | ||
1195 | .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ | ||
1196 | (shift_right << 19) | (mask << 24) | (invert << 22), \ | ||
1197 | .tlv = { .p = (xtlv) } } | ||
1198 | |||
1199 | static struct snd_kcontrol_new snd_ad1848_controls[] = { | ||
1200 | WSS_DOUBLE("PCM Playback Switch", 0, | ||
1201 | AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), | ||
1202 | AD1848_DOUBLE_TLV("PCM Playback Volume", 0, | ||
1203 | AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1, | ||
1204 | db_scale_6bit), | ||
1205 | WSS_DOUBLE("Aux Playback Switch", 0, | ||
1206 | AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | ||
1207 | AD1848_DOUBLE_TLV("Aux Playback Volume", 0, | ||
1208 | AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1, | ||
1209 | db_scale_5bit_12db_max), | ||
1210 | WSS_DOUBLE("Aux Playback Switch", 1, | ||
1211 | AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | ||
1212 | AD1848_DOUBLE_TLV("Aux Playback Volume", 1, | ||
1213 | AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1, | ||
1214 | db_scale_5bit_12db_max), | ||
1215 | AD1848_DOUBLE_TLV("Capture Volume", 0, | ||
1216 | AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0, | ||
1217 | db_scale_rec_gain), | ||
1218 | { | ||
1219 | .name = "Capture Source", | ||
1220 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1221 | .info = snd_ad1848_info_mux, | ||
1222 | .get = snd_ad1848_get_mux, | ||
1223 | .put = snd_ad1848_put_mux, | ||
1224 | }, | ||
1225 | WSS_SINGLE("Loopback Capture Switch", 0, | ||
1226 | AD1848_LOOPBACK, 0, 1, 0), | ||
1227 | AD1848_SINGLE_TLV("Loopback Capture Volume", 0, | ||
1228 | AD1848_LOOPBACK, 1, 63, 0, | ||
1229 | db_scale_6bit), | ||
1230 | }; | ||
1231 | |||
1232 | int snd_ad1848_mixer(struct snd_wss *chip) | ||
1233 | { | ||
1234 | struct snd_card *card; | ||
1235 | struct snd_pcm *pcm; | ||
1236 | unsigned int idx; | ||
1237 | int err; | ||
1238 | |||
1239 | snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL); | ||
1240 | |||
1241 | pcm = chip->pcm; | ||
1242 | card = chip->card; | ||
1243 | |||
1244 | strcpy(card->mixername, pcm->name); | ||
1245 | |||
1246 | for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) { | ||
1247 | err = snd_ctl_add(card, | ||
1248 | snd_ctl_new1(&snd_ad1848_controls[idx], chip)); | ||
1249 | if (err < 0) | ||
1250 | return err; | ||
1251 | } | ||
1252 | |||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1256 | EXPORT_SYMBOL(snd_ad1848_mixer); | ||
1257 | |||
1258 | /* | ||
1259 | * INIT part | 998 | * INIT part |
1260 | */ | 999 | */ |
1261 | 1000 | ||
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 1f6d6fcd6e57..4f172a219244 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -757,6 +757,15 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
757 | error = snd_wss_pcm(codec, 0, &pcm); | 757 | error = snd_wss_pcm(codec, 0, &pcm); |
758 | if (error < 0) | 758 | if (error < 0) |
759 | return error; | 759 | return error; |
760 | #else | ||
761 | error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq, | ||
762 | chip->dma1, WSS_HW_DETECT, &codec); | ||
763 | if (error < 0) | ||
764 | return error; | ||
765 | error = snd_ad1848_pcm(codec, 0, &pcm); | ||
766 | if (error < 0) | ||
767 | return error; | ||
768 | #endif | ||
760 | error = snd_wss_mixer(codec); | 769 | error = snd_wss_mixer(codec); |
761 | if (error < 0) | 770 | if (error < 0) |
762 | return error; | 771 | return error; |
@@ -764,7 +773,8 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
764 | error = snd_wss_timer(codec, 0, &timer); | 773 | error = snd_wss_timer(codec, 0, &timer); |
765 | if (error < 0) | 774 | if (error < 0) |
766 | return error; | 775 | return error; |
767 | #else /* OPTI93X */ | 776 | #endif |
777 | #ifdef OPTi93X | ||
768 | error = request_irq(chip->irq, snd_opti93x_interrupt, | 778 | error = request_irq(chip->irq, snd_opti93x_interrupt, |
769 | IRQF_DISABLED, DEV_NAME" - WSS", codec); | 779 | IRQF_DISABLED, DEV_NAME" - WSS", codec); |
770 | if (error < 0) { | 780 | if (error < 0) { |
@@ -772,16 +782,6 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
772 | return error; | 782 | return error; |
773 | } | 783 | } |
774 | #endif | 784 | #endif |
775 | #else | ||
776 | if ((error = snd_ad1848_create(card, chip->wss_base + 4, | ||
777 | chip->irq, chip->dma1, | ||
778 | WSS_HW_DETECT, &codec)) < 0) | ||
779 | return error; | ||
780 | if ((error = snd_ad1848_pcm(codec, 0, &pcm)) < 0) | ||
781 | return error; | ||
782 | if ((error = snd_ad1848_mixer(codec)) < 0) | ||
783 | return error; | ||
784 | #endif | ||
785 | strcpy(card->driver, chip->name); | 785 | strcpy(card->driver, chip->name); |
786 | sprintf(card->shortname, "OPTi %s", card->driver); | 786 | sprintf(card->shortname, "OPTi %s", card->driver); |
787 | #if defined(CS4231) || defined(OPTi93X) | 787 | #if defined(CS4231) || defined(OPTi93X) |
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 0b6cf472ddcb..ef98fe7dced8 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c | |||
@@ -560,9 +560,9 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) | |||
560 | "error creating new ad1848 PCM device\n"); | 560 | "error creating new ad1848 PCM device\n"); |
561 | goto err_unmap2; | 561 | goto err_unmap2; |
562 | } | 562 | } |
563 | err = snd_ad1848_mixer(chip); | 563 | err = snd_wss_mixer(chip); |
564 | if (err < 0) { | 564 | if (err < 0) { |
565 | snd_printk(KERN_ERR PFX "error creating new ad1848 mixer\n"); | 565 | snd_printk(KERN_ERR PFX "error creating new WSS mixer\n"); |
566 | goto err_unmap2; | 566 | goto err_unmap2; |
567 | } | 567 | } |
568 | err = snd_sc6000_mixer(chip); | 568 | err = snd_sc6000_mixer(chip); |
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index 5894b2d4db64..e4f06de3480c 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c | |||
@@ -277,8 +277,9 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) | |||
277 | snd_printdd(PFX "error creating new ad1848 PCM device\n"); | 277 | snd_printdd(PFX "error creating new ad1848 PCM device\n"); |
278 | goto _err; | 278 | goto _err; |
279 | } | 279 | } |
280 | if ((err = snd_ad1848_mixer(chip)) < 0) { | 280 | err = snd_wss_mixer(chip); |
281 | snd_printdd(PFX "error creating new ad1848 mixer\n"); | 281 | if (err < 0) { |
282 | snd_printdd(PFX "error creating new WSS mixer\n"); | ||
282 | goto _err; | 283 | goto _err; |
283 | } | 284 | } |
284 | if ((err = snd_sgalaxy_mixer(chip)) < 0) { | 285 | if ((err = snd_sgalaxy_mixer(chip)) < 0) { |
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index a982997805c4..1688f07a14b0 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <sound/core.h> | 33 | #include <sound/core.h> |
34 | #include <sound/wss.h> | 34 | #include <sound/wss.h> |
35 | #include <sound/pcm_params.h> | 35 | #include <sound/pcm_params.h> |
36 | #include <sound/tlv.h> | ||
36 | 37 | ||
37 | #include <asm/io.h> | 38 | #include <asm/io.h> |
38 | #include <asm/dma.h> | 39 | #include <asm/dma.h> |
@@ -1957,16 +1958,58 @@ int snd_wss_put_double(struct snd_kcontrol *kcontrol, | |||
1957 | val1 <<= shift_left; | 1958 | val1 <<= shift_left; |
1958 | val2 <<= shift_right; | 1959 | val2 <<= shift_right; |
1959 | spin_lock_irqsave(&chip->reg_lock, flags); | 1960 | spin_lock_irqsave(&chip->reg_lock, flags); |
1960 | val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; | 1961 | if (left_reg != right_reg) { |
1961 | val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; | 1962 | val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; |
1962 | change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg]; | 1963 | val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; |
1963 | snd_wss_out(chip, left_reg, val1); | 1964 | change = val1 != chip->image[left_reg] || |
1964 | snd_wss_out(chip, right_reg, val2); | 1965 | val2 != chip->image[right_reg]; |
1966 | snd_wss_out(chip, left_reg, val1); | ||
1967 | snd_wss_out(chip, right_reg, val2); | ||
1968 | } else { | ||
1969 | mask = (mask << shift_left) | (mask << shift_right); | ||
1970 | val1 = (chip->image[left_reg] & ~mask) | val1 | val2; | ||
1971 | change = val1 != chip->image[left_reg]; | ||
1972 | snd_wss_out(chip, left_reg, val1); | ||
1973 | } | ||
1965 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1974 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1966 | return change; | 1975 | return change; |
1967 | } | 1976 | } |
1968 | EXPORT_SYMBOL(snd_wss_put_double); | 1977 | EXPORT_SYMBOL(snd_wss_put_double); |
1969 | 1978 | ||
1979 | static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); | ||
1980 | static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); | ||
1981 | static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); | ||
1982 | |||
1983 | static struct snd_kcontrol_new snd_ad1848_controls[] = { | ||
1984 | WSS_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, | ||
1985 | 7, 7, 1, 1), | ||
1986 | WSS_DOUBLE_TLV("PCM Playback Volume", 0, | ||
1987 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1, | ||
1988 | db_scale_6bit), | ||
1989 | WSS_DOUBLE("Aux Playback Switch", 0, | ||
1990 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | ||
1991 | WSS_DOUBLE_TLV("Aux Playback Volume", 0, | ||
1992 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1, | ||
1993 | db_scale_5bit_12db_max), | ||
1994 | WSS_DOUBLE("Aux Playback Switch", 1, | ||
1995 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | ||
1996 | WSS_DOUBLE_TLV("Aux Playback Volume", 1, | ||
1997 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1, | ||
1998 | db_scale_5bit_12db_max), | ||
1999 | WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, | ||
2000 | 0, 0, 15, 0, db_scale_rec_gain), | ||
2001 | { | ||
2002 | .name = "Capture Source", | ||
2003 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2004 | .info = snd_wss_info_mux, | ||
2005 | .get = snd_wss_get_mux, | ||
2006 | .put = snd_wss_put_mux, | ||
2007 | }, | ||
2008 | WSS_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), | ||
2009 | WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 1, 63, 0, | ||
2010 | db_scale_6bit), | ||
2011 | }; | ||
2012 | |||
1970 | static struct snd_kcontrol_new snd_wss_controls[] = { | 2013 | static struct snd_kcontrol_new snd_wss_controls[] = { |
1971 | WSS_DOUBLE("PCM Playback Switch", 0, | 2014 | WSS_DOUBLE("PCM Playback Switch", 0, |
1972 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), | 2015 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), |
@@ -2071,6 +2114,14 @@ int snd_wss_mixer(struct snd_wss *chip) | |||
2071 | if (err < 0) | 2114 | if (err < 0) |
2072 | return err; | 2115 | return err; |
2073 | } | 2116 | } |
2117 | else if (chip->hardware & WSS_HW_AD1848_MASK) | ||
2118 | for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) { | ||
2119 | err = snd_ctl_add(card, | ||
2120 | snd_ctl_new1(&snd_ad1848_controls[idx], | ||
2121 | chip)); | ||
2122 | if (err < 0) | ||
2123 | return err; | ||
2124 | } | ||
2074 | else | 2125 | else |
2075 | for (idx = 0; idx < ARRAY_SIZE(snd_wss_controls); idx++) { | 2126 | for (idx = 0; idx < ARRAY_SIZE(snd_wss_controls); idx++) { |
2076 | err = snd_ctl_add(card, | 2127 | err = snd_ctl_add(card, |