diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2007-09-17 11:57:37 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2007-10-16 10:50:51 -0400 |
commit | ec1e7949327a709c83fc7338f89a8c2d1f978fa9 (patch) | |
tree | b1ba63913f01e5d396b46b9542ed0cdaee2f0786 /sound/isa | |
parent | 1ea73412b27ddd88decbdafb83bb2bfc288fe56c (diff) |
[ALSA] sscape: support for audio part of VIVO cards
This patch adds support for audio part of the Ensoniq
SoundScape VIVO cards. The MIDI part is not supported.
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/isa')
-rw-r--r-- | sound/isa/sscape.c | 220 |
1 files changed, 145 insertions, 75 deletions
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 53daa8bd9b78..4902da40b6c0 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c | |||
@@ -142,10 +142,12 @@ enum card_type { | |||
142 | struct soundscape { | 142 | struct soundscape { |
143 | spinlock_t lock; | 143 | spinlock_t lock; |
144 | unsigned io_base; | 144 | unsigned io_base; |
145 | unsigned wss_base; | ||
145 | int codec_type; | 146 | int codec_type; |
146 | int ic_type; | 147 | int ic_type; |
147 | enum card_type type; | 148 | enum card_type type; |
148 | struct resource *io_res; | 149 | struct resource *io_res; |
150 | struct resource *wss_res; | ||
149 | struct snd_cs4231 *chip; | 151 | struct snd_cs4231 *chip; |
150 | struct snd_mpu401 *mpu; | 152 | struct snd_mpu401 *mpu; |
151 | struct snd_hwdep *hw; | 153 | struct snd_hwdep *hw; |
@@ -356,8 +358,9 @@ static inline void activate_ad1845_unsafe(unsigned io_base) | |||
356 | */ | 358 | */ |
357 | static void soundscape_free(struct snd_card *c) | 359 | static void soundscape_free(struct snd_card *c) |
358 | { | 360 | { |
359 | register struct soundscape *sscape = get_card_soundscape(c); | 361 | struct soundscape *sscape = get_card_soundscape(c); |
360 | release_and_free_resource(sscape->io_res); | 362 | release_and_free_resource(sscape->io_res); |
363 | release_and_free_resource(sscape->wss_res); | ||
361 | free_dma(sscape->chip->dma1); | 364 | free_dma(sscape->chip->dma1); |
362 | } | 365 | } |
363 | 366 | ||
@@ -818,6 +821,7 @@ static int __devinit detect_sscape(struct soundscape *s) | |||
818 | unsigned long flags; | 821 | unsigned long flags; |
819 | unsigned d; | 822 | unsigned d; |
820 | int retval = 0; | 823 | int retval = 0; |
824 | int codec = s->wss_base; | ||
821 | 825 | ||
822 | spin_lock_irqsave(&s->lock, flags); | 826 | spin_lock_irqsave(&s->lock, flags); |
823 | 827 | ||
@@ -849,9 +853,27 @@ static int __devinit detect_sscape(struct soundscape *s) | |||
849 | outb(0xfe, ODIE_ADDR_IO(s->io_base)); | 853 | outb(0xfe, ODIE_ADDR_IO(s->io_base)); |
850 | if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e) | 854 | if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e) |
851 | goto _done; | 855 | goto _done; |
852 | if ((inb(ODIE_DATA_IO(s->io_base)) & 0x9f) != 0x0e) | 856 | |
857 | outb(0xfe, ODIE_ADDR_IO(s->io_base)); | ||
858 | d = inb(ODIE_DATA_IO(s->io_base)); | ||
859 | if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e) | ||
853 | goto _done; | 860 | goto _done; |
854 | 861 | ||
862 | d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f; | ||
863 | sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); | ||
864 | |||
865 | if (s->type == SSCAPE_VIVO) | ||
866 | codec += 4; | ||
867 | /* wait for WSS codec */ | ||
868 | for (d = 0; d < 500; d++) { | ||
869 | if ((inb(codec) & 0x80) == 0) | ||
870 | break; | ||
871 | spin_unlock_irqrestore(&s->lock, flags); | ||
872 | msleep(1); | ||
873 | spin_lock_irqsave(&s->lock, flags); | ||
874 | } | ||
875 | snd_printd(KERN_INFO "init delay = %d ms\n", d); | ||
876 | |||
855 | /* | 877 | /* |
856 | * SoundScape successfully detected! | 878 | * SoundScape successfully detected! |
857 | */ | 879 | */ |
@@ -1018,6 +1040,9 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, | |||
1018 | struct snd_cs4231 *chip; | 1040 | struct snd_cs4231 *chip; |
1019 | int err; | 1041 | int err; |
1020 | 1042 | ||
1043 | if (sscape->type == SSCAPE_VIVO) | ||
1044 | port += 4; | ||
1045 | |||
1021 | if (dma1 == dma2) | 1046 | if (dma1 == dma2) |
1022 | dma2 = -1; | 1047 | dma2 = -1; |
1023 | 1048 | ||
@@ -1046,50 +1071,72 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, | |||
1046 | snd_cs4231_mce_down(chip); | 1071 | snd_cs4231_mce_down(chip); |
1047 | */ | 1072 | */ |
1048 | 1073 | ||
1049 | /* | 1074 | if (sscape->type != SSCAPE_VIVO) { |
1050 | * The input clock frequency on the SoundScape must | 1075 | int val; |
1051 | * be 14.31818 MHz, because we must set this register | 1076 | /* |
1052 | * to get the playback to sound correct ... | 1077 | * The input clock frequency on the SoundScape must |
1053 | */ | 1078 | * be 14.31818 MHz, because we must set this register |
1054 | snd_cs4231_mce_up(chip); | 1079 | * to get the playback to sound correct ... |
1055 | spin_lock_irqsave(&chip->reg_lock, flags); | 1080 | */ |
1056 | snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); | 1081 | snd_cs4231_mce_up(chip); |
1057 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1082 | spin_lock_irqsave(&chip->reg_lock, flags); |
1058 | snd_cs4231_mce_down(chip); | 1083 | snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); |
1084 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1085 | snd_cs4231_mce_down(chip); | ||
1059 | 1086 | ||
1060 | /* | 1087 | /* |
1061 | * More custom configuration: | 1088 | * More custom configuration: |
1062 | * a) select "mode 2", and provide a current drive of 8 mA | 1089 | * a) select "mode 2" and provide a current drive of 8mA |
1063 | * b) enable frequency selection (for capture/playback) | 1090 | * b) enable frequency selection (for capture/playback) |
1064 | */ | 1091 | */ |
1065 | spin_lock_irqsave(&chip->reg_lock, flags); | 1092 | spin_lock_irqsave(&chip->reg_lock, flags); |
1066 | snd_cs4231_out(chip, CS4231_MISC_INFO, (CS4231_MODE2 | 0x10)); | 1093 | snd_cs4231_out(chip, CS4231_MISC_INFO, |
1067 | snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL) | AD1845_FREQ_SEL_ENABLE); | 1094 | CS4231_MODE2 | 0x10); |
1068 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1095 | val = snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL); |
1096 | snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, | ||
1097 | val | AD1845_FREQ_SEL_ENABLE); | ||
1098 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1099 | } | ||
1069 | 1100 | ||
1070 | if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) { | 1101 | err = snd_cs4231_pcm(chip, 0, &pcm); |
1071 | snd_printk(KERN_ERR "sscape: No PCM device for AD1845 chip\n"); | 1102 | if (err < 0) { |
1103 | snd_printk(KERN_ERR "sscape: No PCM device " | ||
1104 | "for AD1845 chip\n"); | ||
1072 | goto _error; | 1105 | goto _error; |
1073 | } | 1106 | } |
1074 | 1107 | ||
1075 | if ((err = snd_cs4231_mixer(chip)) < 0) { | 1108 | err = snd_cs4231_mixer(chip); |
1076 | snd_printk(KERN_ERR "sscape: No mixer device for AD1845 chip\n"); | 1109 | if (err < 0) { |
1110 | snd_printk(KERN_ERR "sscape: No mixer device " | ||
1111 | "for AD1845 chip\n"); | ||
1077 | goto _error; | 1112 | goto _error; |
1078 | } | 1113 | } |
1079 | 1114 | err = snd_cs4231_timer(chip, 0, NULL); | |
1080 | if ((err = snd_ctl_add(card, snd_ctl_new1(&midi_mixer_ctl, chip))) < 0) { | 1115 | if (err < 0) { |
1081 | snd_printk(KERN_ERR "sscape: Could not create MIDI mixer control\n"); | 1116 | snd_printk(KERN_ERR "sscape: No timer device " |
1117 | "for AD1845 chip\n"); | ||
1082 | goto _error; | 1118 | goto _error; |
1083 | } | 1119 | } |
1084 | 1120 | ||
1121 | if (sscape->type != SSCAPE_VIVO) { | ||
1122 | err = snd_ctl_add(card, | ||
1123 | snd_ctl_new1(&midi_mixer_ctl, chip)); | ||
1124 | if (err < 0) { | ||
1125 | snd_printk(KERN_ERR "sscape: Could not create " | ||
1126 | "MIDI mixer control\n"); | ||
1127 | goto _error; | ||
1128 | } | ||
1129 | chip->set_playback_format = ad1845_playback_format; | ||
1130 | chip->set_capture_format = ad1845_capture_format; | ||
1131 | } | ||
1132 | |||
1085 | strcpy(card->driver, "SoundScape"); | 1133 | strcpy(card->driver, "SoundScape"); |
1086 | strcpy(card->shortname, pcm->name); | 1134 | strcpy(card->shortname, pcm->name); |
1087 | snprintf(card->longname, sizeof(card->longname), | 1135 | snprintf(card->longname, sizeof(card->longname), |
1088 | "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n", | 1136 | "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n", |
1089 | pcm->name, chip->port, chip->irq, | 1137 | pcm->name, chip->port, chip->irq, |
1090 | chip->dma1, chip->dma2); | 1138 | chip->dma1, chip->dma2); |
1091 | chip->set_playback_format = ad1845_playback_format; | 1139 | |
1092 | chip->set_capture_format = ad1845_capture_format; | ||
1093 | sscape->chip = chip; | 1140 | sscape->chip = chip; |
1094 | } | 1141 | } |
1095 | 1142 | ||
@@ -1104,12 +1151,13 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, | |||
1104 | */ | 1151 | */ |
1105 | static int __devinit create_sscape(int dev, struct snd_card *card) | 1152 | static int __devinit create_sscape(int dev, struct snd_card *card) |
1106 | { | 1153 | { |
1107 | register struct soundscape *sscape; | 1154 | struct soundscape *sscape = get_card_soundscape(card); |
1108 | register unsigned dma_cfg; | 1155 | unsigned dma_cfg; |
1109 | unsigned irq_cfg; | 1156 | unsigned irq_cfg; |
1110 | unsigned mpu_irq_cfg; | 1157 | unsigned mpu_irq_cfg; |
1111 | unsigned xport; | 1158 | unsigned xport; |
1112 | struct resource *io_res; | 1159 | struct resource *io_res; |
1160 | struct resource *wss_res; | ||
1113 | unsigned long flags; | 1161 | unsigned long flags; |
1114 | int err; | 1162 | int err; |
1115 | 1163 | ||
@@ -1133,13 +1181,24 @@ static int __devinit create_sscape(int dev, struct snd_card *card) | |||
1133 | * Grab IO ports that we will need to probe so that we | 1181 | * Grab IO ports that we will need to probe so that we |
1134 | * can detect and control this hardware ... | 1182 | * can detect and control this hardware ... |
1135 | */ | 1183 | */ |
1136 | if ((io_res = request_region(xport, 8, "SoundScape")) == NULL) { | 1184 | io_res = request_region(xport, 8, "SoundScape"); |
1185 | if (!io_res) { | ||
1137 | snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport); | 1186 | snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport); |
1138 | return -EBUSY; | 1187 | return -EBUSY; |
1139 | } | 1188 | } |
1189 | wss_res = NULL; | ||
1190 | if (sscape->type == SSCAPE_VIVO) { | ||
1191 | wss_res = request_region(wss_port[dev], 4, "SoundScape"); | ||
1192 | if (!wss_res) { | ||
1193 | snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n", | ||
1194 | wss_port[dev]); | ||
1195 | err = -EBUSY; | ||
1196 | goto _release_region; | ||
1197 | } | ||
1198 | } | ||
1140 | 1199 | ||
1141 | /* | 1200 | /* |
1142 | * Grab both DMA channels (OK, only one for now) ... | 1201 | * Grab one DMA channel ... |
1143 | */ | 1202 | */ |
1144 | err = request_dma(dma[dev], "SoundScape"); | 1203 | err = request_dma(dma[dev], "SoundScape"); |
1145 | if (err < 0) { | 1204 | if (err < 0) { |
@@ -1147,11 +1206,12 @@ static int __devinit create_sscape(int dev, struct snd_card *card) | |||
1147 | goto _release_region; | 1206 | goto _release_region; |
1148 | } | 1207 | } |
1149 | 1208 | ||
1150 | sscape = get_card_soundscape(card); | ||
1151 | spin_lock_init(&sscape->lock); | 1209 | spin_lock_init(&sscape->lock); |
1152 | spin_lock_init(&sscape->fwlock); | 1210 | spin_lock_init(&sscape->fwlock); |
1153 | sscape->io_res = io_res; | 1211 | sscape->io_res = io_res; |
1212 | sscape->wss_res = wss_res; | ||
1154 | sscape->io_base = xport; | 1213 | sscape->io_base = xport; |
1214 | sscape->wss_base = wss_port[dev]; | ||
1155 | 1215 | ||
1156 | if (!detect_sscape(sscape)) { | 1216 | if (!detect_sscape(sscape)) { |
1157 | printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); | 1217 | printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); |
@@ -1162,23 +1222,28 @@ static int __devinit create_sscape(int dev, struct snd_card *card) | |||
1162 | printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n", | 1222 | printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n", |
1163 | sscape->io_base, irq[dev], dma[dev]); | 1223 | sscape->io_base, irq[dev], dma[dev]); |
1164 | 1224 | ||
1165 | /* | 1225 | if (sscape->type != SSCAPE_VIVO) { |
1166 | * Now create the hardware-specific device so that we can | 1226 | /* |
1167 | * load the microcode into the on-board processor. | 1227 | * Now create the hardware-specific device so that we can |
1168 | * We cannot use the MPU-401 MIDI system until this firmware | 1228 | * load the microcode into the on-board processor. |
1169 | * has been loaded into the card. | 1229 | * We cannot use the MPU-401 MIDI system until this firmware |
1170 | */ | 1230 | * has been loaded into the card. |
1171 | if ((err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw))) < 0) { | 1231 | */ |
1172 | printk(KERN_ERR "sscape: Failed to create firmware device\n"); | 1232 | err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw)); |
1173 | goto _release_dma; | 1233 | if (err < 0) { |
1234 | printk(KERN_ERR "sscape: Failed to create " | ||
1235 | "firmware device\n"); | ||
1236 | goto _release_dma; | ||
1237 | } | ||
1238 | strlcpy(sscape->hw->name, "SoundScape M68K", | ||
1239 | sizeof(sscape->hw->name)); | ||
1240 | sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0'; | ||
1241 | sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE; | ||
1242 | sscape->hw->ops.open = sscape_hw_open; | ||
1243 | sscape->hw->ops.release = sscape_hw_release; | ||
1244 | sscape->hw->ops.ioctl = sscape_hw_ioctl; | ||
1245 | sscape->hw->private_data = sscape; | ||
1174 | } | 1246 | } |
1175 | strlcpy(sscape->hw->name, "SoundScape M68K", sizeof(sscape->hw->name)); | ||
1176 | sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0'; | ||
1177 | sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE; | ||
1178 | sscape->hw->ops.open = sscape_hw_open; | ||
1179 | sscape->hw->ops.release = sscape_hw_release; | ||
1180 | sscape->hw->ops.ioctl = sscape_hw_ioctl; | ||
1181 | sscape->hw->private_data = sscape; | ||
1182 | 1247 | ||
1183 | /* | 1248 | /* |
1184 | * Tell the on-board devices where their resources are (I think - | 1249 | * Tell the on-board devices where their resources are (I think - |
@@ -1220,24 +1285,29 @@ static int __devinit create_sscape(int dev, struct snd_card *card) | |||
1220 | goto _release_dma; | 1285 | goto _release_dma; |
1221 | } | 1286 | } |
1222 | #define MIDI_DEVNUM 0 | 1287 | #define MIDI_DEVNUM 0 |
1223 | if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(xport), mpu_irq[dev])) < 0) { | 1288 | if (sscape->type != SSCAPE_VIVO) { |
1224 | printk(KERN_ERR "sscape: Failed to create MPU-401 device at 0x%x\n", | 1289 | err = create_mpu401(card, MIDI_DEVNUM, |
1225 | MPU401_IO(xport)); | 1290 | MPU401_IO(xport), mpu_irq[dev]); |
1226 | goto _release_dma; | 1291 | if (err < 0) { |
1227 | } | 1292 | printk(KERN_ERR "sscape: Failed to create " |
1293 | "MPU-401 device at 0x%x\n", | ||
1294 | MPU401_IO(xport)); | ||
1295 | goto _release_dma; | ||
1296 | } | ||
1228 | 1297 | ||
1229 | /* | 1298 | /* |
1230 | * Enable the master IRQ ... | 1299 | * Enable the master IRQ ... |
1231 | */ | 1300 | */ |
1232 | sscape_write(sscape, GA_INTENA_REG, 0x80); | 1301 | sscape_write(sscape, GA_INTENA_REG, 0x80); |
1233 | 1302 | ||
1234 | /* | 1303 | /* |
1235 | * Initialize mixer | 1304 | * Initialize mixer |
1236 | */ | 1305 | */ |
1237 | sscape->midi_vol = 0; | 1306 | sscape->midi_vol = 0; |
1238 | host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100); | 1307 | host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100); |
1239 | host_write_ctrl_unsafe(sscape->io_base, 0, 100); | 1308 | host_write_ctrl_unsafe(sscape->io_base, 0, 100); |
1240 | host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100); | 1309 | host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100); |
1310 | } | ||
1241 | 1311 | ||
1242 | /* | 1312 | /* |
1243 | * Now that we have successfully created this sound card, | 1313 | * Now that we have successfully created this sound card, |
@@ -1253,6 +1323,7 @@ _release_dma: | |||
1253 | free_dma(dma[dev]); | 1323 | free_dma(dma[dev]); |
1254 | 1324 | ||
1255 | _release_region: | 1325 | _release_region: |
1326 | release_and_free_resource(wss_res); | ||
1256 | release_and_free_resource(io_res); | 1327 | release_and_free_resource(io_res); |
1257 | 1328 | ||
1258 | return err; | 1329 | return err; |
@@ -1404,12 +1475,6 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, | |||
1404 | else | 1475 | else |
1405 | sscape->type = SSCAPE_PNP; | 1476 | sscape->type = SSCAPE_PNP; |
1406 | 1477 | ||
1407 | /* VIVO fails for now */ | ||
1408 | if (sscape->type == SSCAPE_VIVO) { | ||
1409 | ret = -ENODEV; | ||
1410 | goto _release_card; | ||
1411 | } | ||
1412 | |||
1413 | /* | 1478 | /* |
1414 | * Read the correct parameters off the ISA PnP bus ... | 1479 | * Read the correct parameters off the ISA PnP bus ... |
1415 | */ | 1480 | */ |
@@ -1417,8 +1482,13 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, | |||
1417 | irq[idx] = pnp_irq(dev, 0); | 1482 | irq[idx] = pnp_irq(dev, 0); |
1418 | mpu_irq[idx] = pnp_irq(dev, 1); | 1483 | mpu_irq[idx] = pnp_irq(dev, 1); |
1419 | dma[idx] = pnp_dma(dev, 0) & 0x03; | 1484 | dma[idx] = pnp_dma(dev, 0) & 0x03; |
1420 | dma2[idx] = dma[idx]; | 1485 | if (sscape->type == SSCAPE_PNP) { |
1421 | wss_port[idx] = CODEC_IO(port[idx]); | 1486 | dma2[idx] = dma[idx]; |
1487 | wss_port[idx] = CODEC_IO(port[idx]); | ||
1488 | } else { | ||
1489 | wss_port[idx] = pnp_port_start(dev, 1); | ||
1490 | dma2[idx] = pnp_dma(dev, 1); | ||
1491 | } | ||
1422 | 1492 | ||
1423 | ret = create_sscape(idx, card); | 1493 | ret = create_sscape(idx, card); |
1424 | if (ret < 0) | 1494 | if (ret < 0) |