• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 
snd_wavefront_midi_input_open(struct snd_rawmidi_substream * substream)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 
snd_wavefront_midi_output_open(struct snd_rawmidi_substream * substream)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 
snd_wavefront_midi_input_close(struct snd_rawmidi_substream * substream)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 
snd_wavefront_midi_output_close(struct snd_rawmidi_substream * substream)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 
snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream * substream,int up)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 
snd_wavefront_midi_output_timer(struct timer_list * t)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 
snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream * substream,int up)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
snd_wavefront_midi_interrupt(snd_wavefront_card_t * card)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
snd_wavefront_midi_enable_virtual(snd_wavefront_card_t * card)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
snd_wavefront_midi_disable_virtual(snd_wavefront_card_t * card)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
snd_wavefront_midi_start(snd_wavefront_card_t * card)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 
573