Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) by Paul Barton-Davis 1998-1999
0004  */
0005 
0006 /* The low level driver for the WaveFront ICS2115 MIDI interface(s)
0007  *
0008  * Note that there is also an MPU-401 emulation (actually, a UART-401
0009  * emulation) on the CS4232 on the Tropez and Tropez Plus. This code
0010  * has nothing to do with that interface at all.
0011  *
0012  * The interface is essentially just a UART-401, but is has the
0013  * interesting property of supporting what Turtle Beach called
0014  * "Virtual MIDI" mode. In this mode, there are effectively *two*
0015  * MIDI buses accessible via the interface, one that is routed
0016  * solely to/from the external WaveFront synthesizer and the other
0017  * corresponding to the pin/socket connector used to link external
0018  * MIDI devices to the board.
0019  *
0020  * This driver fully supports this mode, allowing two distinct MIDI
0021  * busses to be used completely independently, giving 32 channels of
0022  * MIDI routing, 16 to the WaveFront synth and 16 to the external MIDI
0023  * bus. The devices are named /dev/snd/midiCnD0 and /dev/snd/midiCnD1,
0024  * where `n' is the card number. Note that the device numbers may be
0025  * something other than 0 and 1 if the CS4232 UART/MPU-401 interface
0026  * is enabled.
0027  *
0028  * Switching between the two is accomplished externally by the driver
0029  * using the two otherwise unused MIDI bytes. See the code for more details.
0030  *
0031  * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see lowlevel/isa/wavefront.c)
0032  *
0033  * The main reason to turn off Virtual MIDI mode is when you want to
0034  * tightly couple the WaveFront synth with an external MIDI
0035  * device. You won't be able to distinguish the source of any MIDI
0036  * data except via SysEx ID, but thats probably OK, since for the most
0037  * part, the WaveFront won't be sending any MIDI data at all.
0038  *  
0039  * The main reason to turn on Virtual MIDI Mode is to provide two
0040  * completely independent 16-channel MIDI buses, one to the
0041  * WaveFront and one to any external MIDI devices. Given the 32
0042  * voice nature of the WaveFront, its pretty easy to find a use
0043  * for all 16 channels driving just that synth.
0044  *  
0045  */
0046 
0047 #include <linux/io.h>
0048 #include <linux/init.h>
0049 #include <linux/time.h>
0050 #include <linux/wait.h>
0051 #include <sound/core.h>
0052 #include <sound/snd_wavefront.h>
0053 
0054 static inline int 
0055 wf_mpu_status (snd_wavefront_midi_t *midi)
0056 
0057 {
0058     return inb (midi->mpu_status_port);
0059 }
0060 
0061 static inline int 
0062 input_avail (snd_wavefront_midi_t *midi)
0063 
0064 {
0065     return !(wf_mpu_status(midi) & INPUT_AVAIL);
0066 }
0067 
0068 static inline int
0069 output_ready (snd_wavefront_midi_t *midi)
0070 
0071 {
0072     return !(wf_mpu_status(midi) & OUTPUT_READY);
0073 }
0074 
0075 static inline int 
0076 read_data (snd_wavefront_midi_t *midi)
0077 
0078 {
0079     return inb (midi->mpu_data_port);
0080 }
0081 
0082 static inline void 
0083 write_data (snd_wavefront_midi_t *midi, unsigned char byte)
0084 
0085 {
0086     outb (byte, midi->mpu_data_port);
0087 }
0088 
0089 static snd_wavefront_midi_t *
0090 get_wavefront_midi (struct snd_rawmidi_substream *substream)
0091 
0092 {
0093     struct snd_card *card;
0094     snd_wavefront_card_t *acard;
0095 
0096     if (substream == NULL || substream->rmidi == NULL) 
0097             return NULL;
0098 
0099     card = substream->rmidi->card;
0100 
0101     if (card == NULL) 
0102             return NULL;
0103 
0104     if (card->private_data == NULL) 
0105             return NULL;
0106 
0107     acard = card->private_data;
0108 
0109     return &acard->wavefront.midi;
0110 }
0111 
0112 static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card)
0113 {
0114     snd_wavefront_midi_t *midi = &card->wavefront.midi;
0115     snd_wavefront_mpu_id  mpu;
0116     unsigned long flags;
0117     unsigned char midi_byte;
0118     int max = 256, mask = 1;
0119     int timeout;
0120 
0121     /* Its not OK to try to change the status of "virtuality" of
0122        the MIDI interface while we're outputting stuff.  See
0123        snd_wavefront_midi_{enable,disable}_virtual () for the
0124        other half of this.  
0125 
0126        The first loop attempts to flush any data from the
0127        current output device, and then the second 
0128        emits the switch byte (if necessary), and starts
0129        outputting data for the output device currently in use.
0130     */
0131 
0132     if (midi->substream_output[midi->output_mpu] == NULL) {
0133         goto __second;
0134     }
0135 
0136     while (max > 0) {
0137 
0138         /* XXX fix me - no hard timing loops allowed! */
0139 
0140         for (timeout = 30000; timeout > 0; timeout--) {
0141             if (output_ready (midi))
0142                 break;
0143         }
0144     
0145         spin_lock_irqsave (&midi->virtual, flags);
0146         if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) {
0147             spin_unlock_irqrestore (&midi->virtual, flags);
0148             goto __second;
0149         }
0150         if (output_ready (midi)) {
0151             if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) {
0152                 if (!midi->isvirtual ||
0153                     (midi_byte != WF_INTERNAL_SWITCH &&
0154                      midi_byte != WF_EXTERNAL_SWITCH))
0155                     write_data(midi, midi_byte);
0156                 max--;
0157             } else {
0158                 if (midi->istimer) {
0159                     if (--midi->istimer <= 0)
0160                         del_timer(&midi->timer);
0161                 }
0162                 midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
0163                 spin_unlock_irqrestore (&midi->virtual, flags);
0164                 goto __second;
0165             }
0166         } else {
0167             spin_unlock_irqrestore (&midi->virtual, flags);
0168             return;
0169         }
0170         spin_unlock_irqrestore (&midi->virtual, flags);
0171     }
0172 
0173       __second:
0174 
0175     if (midi->substream_output[!midi->output_mpu] == NULL) {
0176         return;
0177     }
0178 
0179     while (max > 0) {
0180 
0181         /* XXX fix me - no hard timing loops allowed! */
0182 
0183         for (timeout = 30000; timeout > 0; timeout--) {
0184             if (output_ready (midi))
0185                 break;
0186         }
0187     
0188         spin_lock_irqsave (&midi->virtual, flags);
0189         if (!midi->isvirtual)
0190             mask = 0;
0191         mpu = midi->output_mpu ^ mask;
0192         mask = 0;   /* don't invert the value from now */
0193         if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) {
0194             spin_unlock_irqrestore (&midi->virtual, flags);
0195             return;
0196         }
0197         if (snd_rawmidi_transmit_empty(midi->substream_output[mpu]))
0198             goto __timer;
0199         if (output_ready (midi)) {
0200             if (mpu != midi->output_mpu) {
0201                 write_data(midi, mpu == internal_mpu ?
0202                             WF_INTERNAL_SWITCH :
0203                             WF_EXTERNAL_SWITCH);
0204                 midi->output_mpu = mpu;
0205             } else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) {
0206                 if (!midi->isvirtual ||
0207                     (midi_byte != WF_INTERNAL_SWITCH &&
0208                      midi_byte != WF_EXTERNAL_SWITCH))
0209                     write_data(midi, midi_byte);
0210                 max--;
0211             } else {
0212                   __timer:
0213                 if (midi->istimer) {
0214                     if (--midi->istimer <= 0)
0215                         del_timer(&midi->timer);
0216                 }
0217                 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
0218                 spin_unlock_irqrestore (&midi->virtual, flags);
0219                 return;
0220             }
0221         } else {
0222             spin_unlock_irqrestore (&midi->virtual, flags);
0223             return;
0224         }
0225         spin_unlock_irqrestore (&midi->virtual, flags);
0226     }
0227 }
0228 
0229 static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream)
0230 {
0231     unsigned long flags;
0232     snd_wavefront_midi_t *midi;
0233     snd_wavefront_mpu_id mpu;
0234 
0235     if (snd_BUG_ON(!substream || !substream->rmidi))
0236         return -ENXIO;
0237     if (snd_BUG_ON(!substream->rmidi->private_data))
0238         return -ENXIO;
0239 
0240     mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
0241 
0242     midi = get_wavefront_midi(substream);
0243     if (!midi)
0244             return -EIO;
0245 
0246     spin_lock_irqsave (&midi->open, flags);
0247     midi->mode[mpu] |= MPU401_MODE_INPUT;
0248     midi->substream_input[mpu] = substream;
0249     spin_unlock_irqrestore (&midi->open, flags);
0250 
0251     return 0;
0252 }
0253 
0254 static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream)
0255 {
0256     unsigned long flags;
0257     snd_wavefront_midi_t *midi;
0258     snd_wavefront_mpu_id mpu;
0259 
0260     if (snd_BUG_ON(!substream || !substream->rmidi))
0261         return -ENXIO;
0262     if (snd_BUG_ON(!substream->rmidi->private_data))
0263         return -ENXIO;
0264 
0265     mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
0266 
0267     midi = get_wavefront_midi(substream);
0268     if (!midi)
0269             return -EIO;
0270 
0271     spin_lock_irqsave (&midi->open, flags);
0272     midi->mode[mpu] |= MPU401_MODE_OUTPUT;
0273     midi->substream_output[mpu] = substream;
0274     spin_unlock_irqrestore (&midi->open, flags);
0275 
0276     return 0;
0277 }
0278 
0279 static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream)
0280 {
0281     unsigned long flags;
0282     snd_wavefront_midi_t *midi;
0283     snd_wavefront_mpu_id mpu;
0284 
0285     if (snd_BUG_ON(!substream || !substream->rmidi))
0286         return -ENXIO;
0287     if (snd_BUG_ON(!substream->rmidi->private_data))
0288         return -ENXIO;
0289 
0290     mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
0291 
0292     midi = get_wavefront_midi(substream);
0293     if (!midi)
0294             return -EIO;
0295 
0296     spin_lock_irqsave (&midi->open, flags);
0297     midi->mode[mpu] &= ~MPU401_MODE_INPUT;
0298     spin_unlock_irqrestore (&midi->open, flags);
0299 
0300     return 0;
0301 }
0302 
0303 static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream)
0304 {
0305     unsigned long flags;
0306     snd_wavefront_midi_t *midi;
0307     snd_wavefront_mpu_id mpu;
0308 
0309     if (snd_BUG_ON(!substream || !substream->rmidi))
0310         return -ENXIO;
0311     if (snd_BUG_ON(!substream->rmidi->private_data))
0312         return -ENXIO;
0313 
0314     mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
0315 
0316     midi = get_wavefront_midi(substream);
0317     if (!midi)
0318             return -EIO;
0319 
0320     spin_lock_irqsave (&midi->open, flags);
0321     midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
0322     spin_unlock_irqrestore (&midi->open, flags);
0323     return 0;
0324 }
0325 
0326 static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
0327 {
0328     unsigned long flags;
0329     snd_wavefront_midi_t *midi;
0330     snd_wavefront_mpu_id mpu;
0331 
0332     if (substream == NULL || substream->rmidi == NULL) 
0333             return;
0334 
0335     if (substream->rmidi->private_data == NULL)
0336             return;
0337 
0338     mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
0339 
0340     midi = get_wavefront_midi(substream);
0341     if (!midi)
0342         return;
0343 
0344     spin_lock_irqsave (&midi->virtual, flags);
0345     if (up) {
0346         midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
0347     } else {
0348         midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
0349     }
0350     spin_unlock_irqrestore (&midi->virtual, flags);
0351 }
0352 
0353 static void snd_wavefront_midi_output_timer(struct timer_list *t)
0354 {
0355     snd_wavefront_midi_t *midi = from_timer(midi, t, timer);
0356     snd_wavefront_card_t *card = midi->timer_card;
0357     unsigned long flags;
0358     
0359     spin_lock_irqsave (&midi->virtual, flags);
0360     mod_timer(&midi->timer, 1 + jiffies);
0361     spin_unlock_irqrestore (&midi->virtual, flags);
0362     snd_wavefront_midi_output_write(card);
0363 }
0364 
0365 static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
0366 {
0367     unsigned long flags;
0368     snd_wavefront_midi_t *midi;
0369     snd_wavefront_mpu_id mpu;
0370 
0371     if (substream == NULL || substream->rmidi == NULL) 
0372             return;
0373 
0374     if (substream->rmidi->private_data == NULL)
0375             return;
0376 
0377     mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
0378 
0379     midi = get_wavefront_midi(substream);
0380     if (!midi)
0381         return;
0382 
0383     spin_lock_irqsave (&midi->virtual, flags);
0384     if (up) {
0385         if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
0386             if (!midi->istimer) {
0387                 timer_setup(&midi->timer,
0388                         snd_wavefront_midi_output_timer,
0389                         0);
0390                 mod_timer(&midi->timer, 1 + jiffies);
0391             }
0392             midi->istimer++;
0393             midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
0394         }
0395     } else {
0396         midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
0397     }
0398     spin_unlock_irqrestore (&midi->virtual, flags);
0399 
0400     if (up)
0401         snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);
0402 }
0403 
0404 void
0405 snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
0406 
0407 {
0408     unsigned long flags;
0409     snd_wavefront_midi_t *midi;
0410     static struct snd_rawmidi_substream *substream = NULL;
0411     static int mpu = external_mpu; 
0412     int max = 128;
0413     unsigned char byte;
0414 
0415     midi = &card->wavefront.midi;
0416 
0417     if (!input_avail (midi)) { /* not for us */
0418         snd_wavefront_midi_output_write(card);
0419         return;
0420     }
0421 
0422     spin_lock_irqsave (&midi->virtual, flags);
0423     while (--max) {
0424 
0425         if (input_avail (midi)) {
0426             byte = read_data (midi);
0427 
0428             if (midi->isvirtual) {              
0429                 if (byte == WF_EXTERNAL_SWITCH) {
0430                     substream = midi->substream_input[external_mpu];
0431                     mpu = external_mpu;
0432                 } else if (byte == WF_INTERNAL_SWITCH) { 
0433                     substream = midi->substream_output[internal_mpu];
0434                     mpu = internal_mpu;
0435                 } /* else just leave it as it is */
0436             } else {
0437                 substream = midi->substream_input[internal_mpu];
0438                 mpu = internal_mpu;
0439             }
0440 
0441             if (substream == NULL) {
0442                 continue;
0443             }
0444 
0445             if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
0446                 snd_rawmidi_receive(substream, &byte, 1);
0447             }
0448         } else {
0449             break;
0450         }
0451     } 
0452     spin_unlock_irqrestore (&midi->virtual, flags);
0453 
0454     snd_wavefront_midi_output_write(card);
0455 }
0456 
0457 void
0458 snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card)
0459 
0460 {
0461     unsigned long flags;
0462 
0463     spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
0464     card->wavefront.midi.isvirtual = 1;
0465     card->wavefront.midi.output_mpu = internal_mpu;
0466     card->wavefront.midi.input_mpu = internal_mpu;
0467     spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
0468 }
0469 
0470 void
0471 snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
0472 
0473 {
0474     unsigned long flags;
0475 
0476     spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
0477     // snd_wavefront_midi_input_close (card->ics2115_external_rmidi);
0478     // snd_wavefront_midi_output_close (card->ics2115_external_rmidi);
0479     card->wavefront.midi.isvirtual = 0;
0480     spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
0481 }
0482 
0483 int
0484 snd_wavefront_midi_start (snd_wavefront_card_t *card)
0485 
0486 {
0487     int ok, i;
0488     unsigned char rbuf[4], wbuf[4];
0489     snd_wavefront_t *dev;
0490     snd_wavefront_midi_t *midi;
0491 
0492     dev = &card->wavefront;
0493     midi = &dev->midi;
0494 
0495     /* The ICS2115 MPU-401 interface doesn't do anything
0496        until its set into UART mode.
0497     */
0498 
0499     /* XXX fix me - no hard timing loops allowed! */
0500 
0501     for (i = 0; i < 30000 && !output_ready (midi); i++);
0502 
0503     if (!output_ready (midi)) {
0504         snd_printk ("MIDI interface not ready for command\n");
0505         return -1;
0506     }
0507 
0508     /* Any interrupts received from now on
0509        are owned by the MIDI side of things.
0510     */
0511 
0512     dev->interrupts_are_midi = 1;
0513     
0514     outb (UART_MODE_ON, midi->mpu_command_port);
0515 
0516     for (ok = 0, i = 50000; i > 0 && !ok; i--) {
0517         if (input_avail (midi)) {
0518             if (read_data (midi) == MPU_ACK) {
0519                 ok = 1;
0520                 break;
0521             }
0522         }
0523     }
0524 
0525     if (!ok) {
0526         snd_printk ("cannot set UART mode for MIDI interface");
0527         dev->interrupts_are_midi = 0;
0528         return -1;
0529     }
0530 
0531     /* Route external MIDI to WaveFront synth (by default) */
0532     
0533     if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
0534         snd_printk ("can't enable MIDI-IN-2-synth routing.\n");
0535         /* XXX error ? */
0536     }
0537 
0538     /* Turn on Virtual MIDI, but first *always* turn it off,
0539        since otherwise consecutive reloads of the driver will
0540        never cause the hardware to generate the initial "internal" or 
0541        "external" source bytes in the MIDI data stream. This
0542        is pretty important, since the internal hardware generally will
0543        be used to generate none or very little MIDI output, and
0544        thus the only source of MIDI data is actually external. Without
0545        the switch bytes, the driver will think it all comes from
0546        the internal interface. Duh.
0547     */
0548 
0549     if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { 
0550         snd_printk ("virtual MIDI mode not disabled\n");
0551         return 0; /* We're OK, but missing the external MIDI dev */
0552     }
0553 
0554     snd_wavefront_midi_enable_virtual (card);
0555 
0556     if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
0557         snd_printk ("cannot enable virtual MIDI mode.\n");
0558         snd_wavefront_midi_disable_virtual (card);
0559     } 
0560     return 0;
0561 }
0562 
0563 const struct snd_rawmidi_ops snd_wavefront_midi_output =
0564 {
0565     .open =     snd_wavefront_midi_output_open,
0566     .close =    snd_wavefront_midi_output_close,
0567     .trigger =  snd_wavefront_midi_output_trigger,
0568 };
0569 
0570 const struct snd_rawmidi_ops snd_wavefront_midi_input =
0571 {
0572     .open =     snd_wavefront_midi_input_open,
0573     .close =    snd_wavefront_midi_input_close,
0574     .trigger =  snd_wavefront_midi_input_trigger,
0575 };
0576