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
wf_mpu_status(snd_wavefront_midi_t * midi)55 wf_mpu_status (snd_wavefront_midi_t *midi)
56
57 {
58 return inb (midi->mpu_status_port);
59 }
60
61 static inline int
input_avail(snd_wavefront_midi_t * midi)62 input_avail (snd_wavefront_midi_t *midi)
63
64 {
65 return !(wf_mpu_status(midi) & INPUT_AVAIL);
66 }
67
68 static inline int
output_ready(snd_wavefront_midi_t * midi)69 output_ready (snd_wavefront_midi_t *midi)
70
71 {
72 return !(wf_mpu_status(midi) & OUTPUT_READY);
73 }
74
75 static inline int
read_data(snd_wavefront_midi_t * midi)76 read_data (snd_wavefront_midi_t *midi)
77
78 {
79 return inb (midi->mpu_data_port);
80 }
81
82 static inline void
write_data(snd_wavefront_midi_t * midi,unsigned char byte)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 *
get_wavefront_midi(struct snd_rawmidi_substream * substream)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
snd_wavefront_midi_output_write(snd_wavefront_card_t * card)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 char midi_byte;
117 int max = 256, mask = 1;
118 int timeout;
119
120 /* Its not OK to try to change the status of "virtuality" of
121 the MIDI interface while we're outputting stuff. See
122 snd_wavefront_midi_{enable,disable}_virtual () for the
123 other half of this.
124
125 The first loop attempts to flush any data from the
126 current output device, and then the second
127 emits the switch byte (if necessary), and starts
128 outputting data for the output device currently in use.
129 */
130
131 if (midi->substream_output[midi->output_mpu] == NULL) {
132 goto __second;
133 }
134
135 while (max > 0) {
136
137 /* XXX fix me - no hard timing loops allowed! */
138
139 for (timeout = 30000; timeout > 0; timeout--) {
140 if (output_ready (midi))
141 break;
142 }
143
144 guard(spinlock_irqsave)(&midi->virtual);
145 if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0)
146 goto __second;
147 if (output_ready (midi)) {
148 if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) {
149 if (!midi->isvirtual ||
150 (midi_byte != WF_INTERNAL_SWITCH &&
151 midi_byte != WF_EXTERNAL_SWITCH))
152 write_data(midi, midi_byte);
153 max--;
154 } else {
155 if (midi->istimer) {
156 if (--midi->istimer <= 0)
157 timer_delete(&midi->timer);
158 }
159 midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
160 goto __second;
161 }
162 } else {
163 return;
164 }
165 }
166
167 __second:
168
169 if (midi->substream_output[!midi->output_mpu] == NULL) {
170 return;
171 }
172
173 while (max > 0) {
174
175 /* XXX fix me - no hard timing loops allowed! */
176
177 for (timeout = 30000; timeout > 0; timeout--) {
178 if (output_ready (midi))
179 break;
180 }
181
182 guard(spinlock_irqsave)(&midi->virtual);
183 if (!midi->isvirtual)
184 mask = 0;
185 mpu = midi->output_mpu ^ mask;
186 mask = 0; /* don't invert the value from now */
187 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0)
188 return;
189 if (snd_rawmidi_transmit_empty(midi->substream_output[mpu]))
190 goto __timer;
191 if (output_ready (midi)) {
192 if (mpu != midi->output_mpu) {
193 write_data(midi, mpu == internal_mpu ?
194 WF_INTERNAL_SWITCH :
195 WF_EXTERNAL_SWITCH);
196 midi->output_mpu = mpu;
197 } else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) {
198 if (!midi->isvirtual ||
199 (midi_byte != WF_INTERNAL_SWITCH &&
200 midi_byte != WF_EXTERNAL_SWITCH))
201 write_data(midi, midi_byte);
202 max--;
203 } else {
204 __timer:
205 if (midi->istimer) {
206 if (--midi->istimer <= 0)
207 timer_delete(&midi->timer);
208 }
209 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
210 return;
211 }
212 } else {
213 return;
214 }
215 }
216 }
217
snd_wavefront_midi_input_open(struct snd_rawmidi_substream * substream)218 static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream)
219 {
220 snd_wavefront_midi_t *midi;
221 snd_wavefront_mpu_id mpu;
222
223 if (snd_BUG_ON(!substream || !substream->rmidi))
224 return -ENXIO;
225 if (snd_BUG_ON(!substream->rmidi->private_data))
226 return -ENXIO;
227
228 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
229
230 midi = get_wavefront_midi(substream);
231 if (!midi)
232 return -EIO;
233
234 guard(spinlock_irqsave)(&midi->open);
235 midi->mode[mpu] |= MPU401_MODE_INPUT;
236 midi->substream_input[mpu] = substream;
237
238 return 0;
239 }
240
snd_wavefront_midi_output_open(struct snd_rawmidi_substream * substream)241 static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream)
242 {
243 snd_wavefront_midi_t *midi;
244 snd_wavefront_mpu_id mpu;
245
246 if (snd_BUG_ON(!substream || !substream->rmidi))
247 return -ENXIO;
248 if (snd_BUG_ON(!substream->rmidi->private_data))
249 return -ENXIO;
250
251 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
252
253 midi = get_wavefront_midi(substream);
254 if (!midi)
255 return -EIO;
256
257 guard(spinlock_irqsave)(&midi->open);
258 midi->mode[mpu] |= MPU401_MODE_OUTPUT;
259 midi->substream_output[mpu] = substream;
260
261 return 0;
262 }
263
snd_wavefront_midi_input_close(struct snd_rawmidi_substream * substream)264 static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream)
265 {
266 snd_wavefront_midi_t *midi;
267 snd_wavefront_mpu_id mpu;
268
269 if (snd_BUG_ON(!substream || !substream->rmidi))
270 return -ENXIO;
271 if (snd_BUG_ON(!substream->rmidi->private_data))
272 return -ENXIO;
273
274 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
275
276 midi = get_wavefront_midi(substream);
277 if (!midi)
278 return -EIO;
279
280 guard(spinlock_irqsave)(&midi->open);
281 midi->substream_input[mpu] = NULL;
282 midi->mode[mpu] &= ~MPU401_MODE_INPUT;
283
284 return 0;
285 }
286
snd_wavefront_midi_output_close(struct snd_rawmidi_substream * substream)287 static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream)
288 {
289 snd_wavefront_midi_t *midi;
290 snd_wavefront_mpu_id mpu;
291
292 if (snd_BUG_ON(!substream || !substream->rmidi))
293 return -ENXIO;
294 if (snd_BUG_ON(!substream->rmidi->private_data))
295 return -ENXIO;
296
297 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
298
299 midi = get_wavefront_midi(substream);
300 if (!midi)
301 return -EIO;
302
303 guard(spinlock_irqsave)(&midi->open);
304 midi->substream_output[mpu] = NULL;
305 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
306 return 0;
307 }
308
snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream * substream,int up)309 static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
310 {
311 snd_wavefront_midi_t *midi;
312 snd_wavefront_mpu_id mpu;
313
314 if (substream == NULL || substream->rmidi == NULL)
315 return;
316
317 if (substream->rmidi->private_data == NULL)
318 return;
319
320 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
321
322 midi = get_wavefront_midi(substream);
323 if (!midi)
324 return;
325
326 guard(spinlock_irqsave)(&midi->virtual);
327 if (up) {
328 midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
329 } else {
330 midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
331 }
332 }
333
snd_wavefront_midi_output_timer(struct timer_list * t)334 static void snd_wavefront_midi_output_timer(struct timer_list *t)
335 {
336 snd_wavefront_midi_t *midi = timer_container_of(midi, t, timer);
337 snd_wavefront_card_t *card = midi->timer_card;
338
339 scoped_guard(spinlock_irqsave, &midi->virtual) {
340 mod_timer(&midi->timer, 1 + jiffies);
341 }
342 snd_wavefront_midi_output_write(card);
343 }
344
snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream * substream,int up)345 static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
346 {
347 snd_wavefront_midi_t *midi;
348 snd_wavefront_mpu_id mpu;
349
350 if (substream == NULL || substream->rmidi == NULL)
351 return;
352
353 if (substream->rmidi->private_data == NULL)
354 return;
355
356 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
357
358 midi = get_wavefront_midi(substream);
359 if (!midi)
360 return;
361
362 scoped_guard(spinlock_irqsave, &midi->virtual) {
363 if (up) {
364 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
365 if (!midi->istimer) {
366 timer_setup(&midi->timer,
367 snd_wavefront_midi_output_timer,
368 0);
369 mod_timer(&midi->timer, 1 + jiffies);
370 }
371 midi->istimer++;
372 midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
373 }
374 } else {
375 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
376 }
377 }
378
379 if (up)
380 snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);
381 }
382
383 void
snd_wavefront_midi_interrupt(snd_wavefront_card_t * card)384 snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
385
386 {
387 snd_wavefront_midi_t *midi;
388 static struct snd_rawmidi_substream *substream = NULL;
389 static int mpu = external_mpu;
390 int max = 128;
391 unsigned char byte;
392
393 midi = &card->wavefront.midi;
394
395 if (!input_avail (midi)) { /* not for us */
396 snd_wavefront_midi_output_write(card);
397 return;
398 }
399
400 scoped_guard(spinlock_irqsave, &midi->virtual) {
401 while (--max) {
402
403 if (input_avail(midi)) {
404 byte = read_data(midi);
405
406 if (midi->isvirtual) {
407 if (byte == WF_EXTERNAL_SWITCH) {
408 substream = midi->substream_input[external_mpu];
409 mpu = external_mpu;
410 } else if (byte == WF_INTERNAL_SWITCH) {
411 substream = midi->substream_output[internal_mpu];
412 mpu = internal_mpu;
413 } /* else just leave it as it is */
414 } else {
415 substream = midi->substream_input[internal_mpu];
416 mpu = internal_mpu;
417 }
418
419 if (substream == NULL) {
420 continue;
421 }
422
423 if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
424 snd_rawmidi_receive(substream, &byte, 1);
425 }
426 } else {
427 break;
428 }
429 }
430 }
431
432 snd_wavefront_midi_output_write(card);
433 }
434
435 void
snd_wavefront_midi_enable_virtual(snd_wavefront_card_t * card)436 snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card)
437
438 {
439 unsigned long flags;
440
441 spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
442 card->wavefront.midi.isvirtual = 1;
443 card->wavefront.midi.output_mpu = internal_mpu;
444 card->wavefront.midi.input_mpu = internal_mpu;
445 spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
446 }
447
448 void
snd_wavefront_midi_disable_virtual(snd_wavefront_card_t * card)449 snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
450
451 {
452 guard(spinlock_irqsave)(&card->wavefront.midi.virtual);
453 // snd_wavefront_midi_input_close (card->ics2115_external_rmidi);
454 // snd_wavefront_midi_output_close (card->ics2115_external_rmidi);
455 card->wavefront.midi.isvirtual = 0;
456 }
457
458 int
snd_wavefront_midi_start(snd_wavefront_card_t * card)459 snd_wavefront_midi_start (snd_wavefront_card_t *card)
460
461 {
462 int ok, i;
463 unsigned char rbuf[4], wbuf[4];
464 snd_wavefront_t *dev;
465 snd_wavefront_midi_t *midi;
466
467 dev = &card->wavefront;
468 midi = &dev->midi;
469
470 /* The ICS2115 MPU-401 interface doesn't do anything
471 until its set into UART mode.
472 */
473
474 /* XXX fix me - no hard timing loops allowed! */
475
476 for (i = 0; i < 30000 && !output_ready (midi); i++);
477
478 if (!output_ready (midi)) {
479 dev_err(card->wavefront.card->dev,
480 "MIDI interface not ready for command\n");
481 return -1;
482 }
483
484 /* Any interrupts received from now on
485 are owned by the MIDI side of things.
486 */
487
488 dev->interrupts_are_midi = 1;
489
490 outb (UART_MODE_ON, midi->mpu_command_port);
491
492 for (ok = 0, i = 50000; i > 0 && !ok; i--) {
493 if (input_avail (midi)) {
494 if (read_data (midi) == MPU_ACK) {
495 ok = 1;
496 break;
497 }
498 }
499 }
500
501 if (!ok) {
502 dev_err(card->wavefront.card->dev,
503 "cannot set UART mode for MIDI interface");
504 dev->interrupts_are_midi = 0;
505 return -1;
506 }
507
508 /* Route external MIDI to WaveFront synth (by default) */
509
510 if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
511 dev_warn(card->wavefront.card->dev,
512 "can't enable MIDI-IN-2-synth routing.\n");
513 /* XXX error ? */
514 }
515
516 /* Turn on Virtual MIDI, but first *always* turn it off,
517 since otherwise consecutive reloads of the driver will
518 never cause the hardware to generate the initial "internal" or
519 "external" source bytes in the MIDI data stream. This
520 is pretty important, since the internal hardware generally will
521 be used to generate none or very little MIDI output, and
522 thus the only source of MIDI data is actually external. Without
523 the switch bytes, the driver will think it all comes from
524 the internal interface. Duh.
525 */
526
527 if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) {
528 dev_warn(card->wavefront.card->dev,
529 "virtual MIDI mode not disabled\n");
530 return 0; /* We're OK, but missing the external MIDI dev */
531 }
532
533 snd_wavefront_midi_enable_virtual (card);
534
535 if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
536 dev_warn(card->wavefront.card->dev,
537 "cannot enable virtual MIDI mode.\n");
538 snd_wavefront_midi_disable_virtual (card);
539 }
540 return 0;
541 }
542
543 const struct snd_rawmidi_ops snd_wavefront_midi_output =
544 {
545 .open = snd_wavefront_midi_output_open,
546 .close = snd_wavefront_midi_output_close,
547 .trigger = snd_wavefront_midi_output_trigger,
548 };
549
550 const struct snd_rawmidi_ops snd_wavefront_midi_input =
551 {
552 .open = snd_wavefront_midi_input_open,
553 .close = snd_wavefront_midi_input_close,
554 .trigger = snd_wavefront_midi_input_trigger,
555 };
556
557