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