a337a86f7a65f4724a405381917a81090ecf8830
[releases.git] / wavefront_midi.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) by Paul Barton-Davis 1998-1999
4  */
5
6 /* The low level driver for the WaveFront ICS2115 MIDI interface(s)
7  *
8  * Note that there is also an MPU-401 emulation (actually, a UART-401
9  * emulation) on the CS4232 on the Tropez and Tropez Plus. This code
10  * has nothing to do with that interface at all.
11  *
12  * The interface is essentially just a UART-401, but is has the
13  * interesting property of supporting what Turtle Beach called
14  * "Virtual MIDI" mode. In this mode, there are effectively *two*
15  * MIDI buses accessible via the interface, one that is routed
16  * solely to/from the external WaveFront synthesizer and the other
17  * corresponding to the pin/socket connector used to link external
18  * MIDI devices to the board.
19  *
20  * This driver fully supports this mode, allowing two distinct MIDI
21  * busses to be used completely independently, giving 32 channels of
22  * MIDI routing, 16 to the WaveFront synth and 16 to the external MIDI
23  * bus. The devices are named /dev/snd/midiCnD0 and /dev/snd/midiCnD1,
24  * where `n' is the card number. Note that the device numbers may be
25  * something other than 0 and 1 if the CS4232 UART/MPU-401 interface
26  * is enabled.
27  *
28  * Switching between the two is accomplished externally by the driver
29  * using the two otherwise unused MIDI bytes. See the code for more details.
30  *
31  * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see lowlevel/isa/wavefront.c)
32  *
33  * The main reason to turn off Virtual MIDI mode is when you want to
34  * tightly couple the WaveFront synth with an external MIDI
35  * device. You won't be able to distinguish the source of any MIDI
36  * data except via SysEx ID, but thats probably OK, since for the most
37  * part, the WaveFront won't be sending any MIDI data at all.
38  *  
39  * The main reason to turn on Virtual MIDI Mode is to provide two
40  * completely independent 16-channel MIDI buses, one to the
41  * WaveFront and one to any external MIDI devices. Given the 32
42  * voice nature of the WaveFront, its pretty easy to find a use
43  * for all 16 channels driving just that synth.
44  *  
45  */
46
47 #include <linux/io.h>
48 #include <linux/init.h>
49 #include <linux/time.h>
50 #include <linux/wait.h>
51 #include <sound/core.h>
52 #include <sound/snd_wavefront.h>
53
54 static inline int 
55 wf_mpu_status (snd_wavefront_midi_t *midi)
56
57 {
58         return inb (midi->mpu_status_port);
59 }
60
61 static inline int 
62 input_avail (snd_wavefront_midi_t *midi)
63
64 {
65         return !(wf_mpu_status(midi) & INPUT_AVAIL);
66 }
67
68 static inline int
69 output_ready (snd_wavefront_midi_t *midi)
70
71 {
72         return !(wf_mpu_status(midi) & OUTPUT_READY);
73 }
74
75 static inline int 
76 read_data (snd_wavefront_midi_t *midi)
77
78 {
79         return inb (midi->mpu_data_port);
80 }
81
82 static inline void 
83 write_data (snd_wavefront_midi_t *midi, unsigned char byte)
84
85 {
86         outb (byte, midi->mpu_data_port);
87 }
88
89 static snd_wavefront_midi_t *
90 get_wavefront_midi (struct snd_rawmidi_substream *substream)
91
92 {
93         struct snd_card *card;
94         snd_wavefront_card_t *acard;
95
96         if (substream == NULL || substream->rmidi == NULL) 
97                 return NULL;
98
99         card = substream->rmidi->card;
100
101         if (card == NULL) 
102                 return NULL;
103
104         if (card->private_data == NULL) 
105                 return NULL;
106
107         acard = card->private_data;
108
109         return &acard->wavefront.midi;
110 }
111
112 static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card)
113 {
114         snd_wavefront_midi_t *midi = &card->wavefront.midi;
115         snd_wavefront_mpu_id  mpu;
116         unsigned long flags;
117         unsigned char midi_byte;
118         int max = 256, mask = 1;
119         int timeout;
120
121         /* Its not OK to try to change the status of "virtuality" of
122            the MIDI interface while we're outputting stuff.  See
123            snd_wavefront_midi_{enable,disable}_virtual () for the
124            other half of this.  
125
126            The first loop attempts to flush any data from the
127            current output device, and then the second 
128            emits the switch byte (if necessary), and starts
129            outputting data for the output device currently in use.
130         */
131
132         if (midi->substream_output[midi->output_mpu] == NULL) {
133                 goto __second;
134         }
135
136         while (max > 0) {
137
138                 /* XXX fix me - no hard timing loops allowed! */
139
140                 for (timeout = 30000; timeout > 0; timeout--) {
141                         if (output_ready (midi))
142                                 break;
143                 }
144         
145                 spin_lock_irqsave (&midi->virtual, flags);
146                 if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) {
147                         spin_unlock_irqrestore (&midi->virtual, flags);
148                         goto __second;
149                 }
150                 if (output_ready (midi)) {
151                         if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) {
152                                 if (!midi->isvirtual ||
153                                         (midi_byte != WF_INTERNAL_SWITCH &&
154                                          midi_byte != WF_EXTERNAL_SWITCH))
155                                         write_data(midi, midi_byte);
156                                 max--;
157                         } else {
158                                 if (midi->istimer) {
159                                         if (--midi->istimer <= 0)
160                                                 del_timer(&midi->timer);
161                                 }
162                                 midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
163                                 spin_unlock_irqrestore (&midi->virtual, flags);
164                                 goto __second;
165                         }
166                 } else {
167                         spin_unlock_irqrestore (&midi->virtual, flags);
168                         return;
169                 }
170                 spin_unlock_irqrestore (&midi->virtual, flags);
171         }
172
173       __second:
174
175         if (midi->substream_output[!midi->output_mpu] == NULL) {
176                 return;
177         }
178
179         while (max > 0) {
180
181                 /* XXX fix me - no hard timing loops allowed! */
182
183                 for (timeout = 30000; timeout > 0; timeout--) {
184                         if (output_ready (midi))
185                                 break;
186                 }
187         
188                 spin_lock_irqsave (&midi->virtual, flags);
189                 if (!midi->isvirtual)
190                         mask = 0;
191                 mpu = midi->output_mpu ^ mask;
192                 mask = 0;       /* don't invert the value from now */
193                 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) {
194                         spin_unlock_irqrestore (&midi->virtual, flags);
195                         return;
196                 }
197                 if (snd_rawmidi_transmit_empty(midi->substream_output[mpu]))
198                         goto __timer;
199                 if (output_ready (midi)) {
200                         if (mpu != midi->output_mpu) {
201                                 write_data(midi, mpu == internal_mpu ?
202                                                         WF_INTERNAL_SWITCH :
203                                                         WF_EXTERNAL_SWITCH);
204                                 midi->output_mpu = mpu;
205                         } else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) {
206                                 if (!midi->isvirtual ||
207                                         (midi_byte != WF_INTERNAL_SWITCH &&
208                                          midi_byte != WF_EXTERNAL_SWITCH))
209                                         write_data(midi, midi_byte);
210                                 max--;
211                         } else {
212                               __timer:
213                                 if (midi->istimer) {
214                                         if (--midi->istimer <= 0)
215                                                 del_timer(&midi->timer);
216                                 }
217                                 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
218                                 spin_unlock_irqrestore (&midi->virtual, flags);
219                                 return;
220                         }
221                 } else {
222                         spin_unlock_irqrestore (&midi->virtual, flags);
223                         return;
224                 }
225                 spin_unlock_irqrestore (&midi->virtual, flags);
226         }
227 }
228
229 static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream)
230 {
231         unsigned long flags;
232         snd_wavefront_midi_t *midi;
233         snd_wavefront_mpu_id mpu;
234
235         if (snd_BUG_ON(!substream || !substream->rmidi))
236                 return -ENXIO;
237         if (snd_BUG_ON(!substream->rmidi->private_data))
238                 return -ENXIO;
239
240         mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
241
242         if ((midi = get_wavefront_midi (substream)) == NULL)
243                 return -EIO;
244
245         spin_lock_irqsave (&midi->open, flags);
246         midi->mode[mpu] |= MPU401_MODE_INPUT;
247         midi->substream_input[mpu] = substream;
248         spin_unlock_irqrestore (&midi->open, flags);
249
250         return 0;
251 }
252
253 static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream)
254 {
255         unsigned long flags;
256         snd_wavefront_midi_t *midi;
257         snd_wavefront_mpu_id mpu;
258
259         if (snd_BUG_ON(!substream || !substream->rmidi))
260                 return -ENXIO;
261         if (snd_BUG_ON(!substream->rmidi->private_data))
262                 return -ENXIO;
263
264         mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
265
266         if ((midi = get_wavefront_midi (substream)) == NULL)
267                 return -EIO;
268
269         spin_lock_irqsave (&midi->open, flags);
270         midi->mode[mpu] |= MPU401_MODE_OUTPUT;
271         midi->substream_output[mpu] = substream;
272         spin_unlock_irqrestore (&midi->open, flags);
273
274         return 0;
275 }
276
277 static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream)
278 {
279         unsigned long flags;
280         snd_wavefront_midi_t *midi;
281         snd_wavefront_mpu_id mpu;
282
283         if (snd_BUG_ON(!substream || !substream->rmidi))
284                 return -ENXIO;
285         if (snd_BUG_ON(!substream->rmidi->private_data))
286                 return -ENXIO;
287
288         mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
289
290         if ((midi = get_wavefront_midi (substream)) == NULL)
291                 return -EIO;
292
293         spin_lock_irqsave (&midi->open, flags);
294         midi->mode[mpu] &= ~MPU401_MODE_INPUT;
295         spin_unlock_irqrestore (&midi->open, flags);
296
297         return 0;
298 }
299
300 static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream)
301 {
302         unsigned long flags;
303         snd_wavefront_midi_t *midi;
304         snd_wavefront_mpu_id mpu;
305
306         if (snd_BUG_ON(!substream || !substream->rmidi))
307                 return -ENXIO;
308         if (snd_BUG_ON(!substream->rmidi->private_data))
309                 return -ENXIO;
310
311         mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
312
313         if ((midi = get_wavefront_midi (substream)) == NULL)
314                 return -EIO;
315
316         spin_lock_irqsave (&midi->open, flags);
317         midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
318         spin_unlock_irqrestore (&midi->open, flags);
319         return 0;
320 }
321
322 static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
323 {
324         unsigned long flags;
325         snd_wavefront_midi_t *midi;
326         snd_wavefront_mpu_id mpu;
327
328         if (substream == NULL || substream->rmidi == NULL) 
329                 return;
330
331         if (substream->rmidi->private_data == NULL)
332                 return;
333
334         mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
335
336         if ((midi = get_wavefront_midi (substream)) == NULL) {
337                 return;
338         }
339
340         spin_lock_irqsave (&midi->virtual, flags);
341         if (up) {
342                 midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
343         } else {
344                 midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
345         }
346         spin_unlock_irqrestore (&midi->virtual, flags);
347 }
348
349 static void snd_wavefront_midi_output_timer(struct timer_list *t)
350 {
351         snd_wavefront_midi_t *midi = from_timer(midi, t, timer);
352         snd_wavefront_card_t *card = midi->timer_card;
353         unsigned long flags;
354         
355         spin_lock_irqsave (&midi->virtual, flags);
356         mod_timer(&midi->timer, 1 + jiffies);
357         spin_unlock_irqrestore (&midi->virtual, flags);
358         snd_wavefront_midi_output_write(card);
359 }
360
361 static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
362 {
363         unsigned long flags;
364         snd_wavefront_midi_t *midi;
365         snd_wavefront_mpu_id mpu;
366
367         if (substream == NULL || substream->rmidi == NULL) 
368                 return;
369
370         if (substream->rmidi->private_data == NULL)
371                 return;
372
373         mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
374
375         if ((midi = get_wavefront_midi (substream)) == NULL) {
376                 return;
377         }
378
379         spin_lock_irqsave (&midi->virtual, flags);
380         if (up) {
381                 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
382                         if (!midi->istimer) {
383                                 timer_setup(&midi->timer,
384                                             snd_wavefront_midi_output_timer,
385                                             0);
386                                 mod_timer(&midi->timer, 1 + jiffies);
387                         }
388                         midi->istimer++;
389                         midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
390                 }
391         } else {
392                 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
393         }
394         spin_unlock_irqrestore (&midi->virtual, flags);
395
396         if (up)
397                 snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);
398 }
399
400 void
401 snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
402
403 {
404         unsigned long flags;
405         snd_wavefront_midi_t *midi;
406         static struct snd_rawmidi_substream *substream = NULL;
407         static int mpu = external_mpu; 
408         int max = 128;
409         unsigned char byte;
410
411         midi = &card->wavefront.midi;
412
413         if (!input_avail (midi)) { /* not for us */
414                 snd_wavefront_midi_output_write(card);
415                 return;
416         }
417
418         spin_lock_irqsave (&midi->virtual, flags);
419         while (--max) {
420
421                 if (input_avail (midi)) {
422                         byte = read_data (midi);
423
424                         if (midi->isvirtual) {                          
425                                 if (byte == WF_EXTERNAL_SWITCH) {
426                                         substream = midi->substream_input[external_mpu];
427                                         mpu = external_mpu;
428                                 } else if (byte == WF_INTERNAL_SWITCH) { 
429                                         substream = midi->substream_output[internal_mpu];
430                                         mpu = internal_mpu;
431                                 } /* else just leave it as it is */
432                         } else {
433                                 substream = midi->substream_input[internal_mpu];
434                                 mpu = internal_mpu;
435                         }
436
437                         if (substream == NULL) {
438                                 continue;
439                         }
440
441                         if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
442                                 snd_rawmidi_receive(substream, &byte, 1);
443                         }
444                 } else {
445                         break;
446                 }
447         } 
448         spin_unlock_irqrestore (&midi->virtual, flags);
449
450         snd_wavefront_midi_output_write(card);
451 }
452
453 void
454 snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card)
455
456 {
457         unsigned long flags;
458
459         spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
460         card->wavefront.midi.isvirtual = 1;
461         card->wavefront.midi.output_mpu = internal_mpu;
462         card->wavefront.midi.input_mpu = internal_mpu;
463         spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
464 }
465
466 void
467 snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
468
469 {
470         unsigned long flags;
471
472         spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
473         // snd_wavefront_midi_input_close (card->ics2115_external_rmidi);
474         // snd_wavefront_midi_output_close (card->ics2115_external_rmidi);
475         card->wavefront.midi.isvirtual = 0;
476         spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
477 }
478
479 int
480 snd_wavefront_midi_start (snd_wavefront_card_t *card)
481
482 {
483         int ok, i;
484         unsigned char rbuf[4], wbuf[4];
485         snd_wavefront_t *dev;
486         snd_wavefront_midi_t *midi;
487
488         dev = &card->wavefront;
489         midi = &dev->midi;
490
491         /* The ICS2115 MPU-401 interface doesn't do anything
492            until its set into UART mode.
493         */
494
495         /* XXX fix me - no hard timing loops allowed! */
496
497         for (i = 0; i < 30000 && !output_ready (midi); i++);
498
499         if (!output_ready (midi)) {
500                 snd_printk ("MIDI interface not ready for command\n");
501                 return -1;
502         }
503
504         /* Any interrupts received from now on
505            are owned by the MIDI side of things.
506         */
507
508         dev->interrupts_are_midi = 1;
509         
510         outb (UART_MODE_ON, midi->mpu_command_port);
511
512         for (ok = 0, i = 50000; i > 0 && !ok; i--) {
513                 if (input_avail (midi)) {
514                         if (read_data (midi) == MPU_ACK) {
515                                 ok = 1;
516                                 break;
517                         }
518                 }
519         }
520
521         if (!ok) {
522                 snd_printk ("cannot set UART mode for MIDI interface");
523                 dev->interrupts_are_midi = 0;
524                 return -1;
525         }
526
527         /* Route external MIDI to WaveFront synth (by default) */
528     
529         if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
530                 snd_printk ("can't enable MIDI-IN-2-synth routing.\n");
531                 /* XXX error ? */
532         }
533
534         /* Turn on Virtual MIDI, but first *always* turn it off,
535            since otherwise consecutive reloads of the driver will
536            never cause the hardware to generate the initial "internal" or 
537            "external" source bytes in the MIDI data stream. This
538            is pretty important, since the internal hardware generally will
539            be used to generate none or very little MIDI output, and
540            thus the only source of MIDI data is actually external. Without
541            the switch bytes, the driver will think it all comes from
542            the internal interface. Duh.
543         */
544
545         if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { 
546                 snd_printk ("virtual MIDI mode not disabled\n");
547                 return 0; /* We're OK, but missing the external MIDI dev */
548         }
549
550         snd_wavefront_midi_enable_virtual (card);
551
552         if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
553                 snd_printk ("cannot enable virtual MIDI mode.\n");
554                 snd_wavefront_midi_disable_virtual (card);
555         } 
556         return 0;
557 }
558
559 const struct snd_rawmidi_ops snd_wavefront_midi_output =
560 {
561         .open =         snd_wavefront_midi_output_open,
562         .close =        snd_wavefront_midi_output_close,
563         .trigger =      snd_wavefront_midi_output_trigger,
564 };
565
566 const struct snd_rawmidi_ops snd_wavefront_midi_input =
567 {
568         .open =         snd_wavefront_midi_input_open,
569         .close =        snd_wavefront_midi_input_close,
570         .trigger =      snd_wavefront_midi_input_trigger,
571 };
572