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 	midi = get_wavefront_midi(substream);
243 	if (!midi)
244 	        return -EIO;
245 
246 	spin_lock_irqsave (&midi->open, flags);
247 	midi->mode[mpu] |= MPU401_MODE_INPUT;
248 	midi->substream_input[mpu] = substream;
249 	spin_unlock_irqrestore (&midi->open, flags);
250 
251 	return 0;
252 }
253 
snd_wavefront_midi_output_open(struct snd_rawmidi_substream * substream)254 static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream)
255 {
256 	unsigned long flags;
257 	snd_wavefront_midi_t *midi;
258 	snd_wavefront_mpu_id mpu;
259 
260 	if (snd_BUG_ON(!substream || !substream->rmidi))
261 		return -ENXIO;
262 	if (snd_BUG_ON(!substream->rmidi->private_data))
263 		return -ENXIO;
264 
265 	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
266 
267 	midi = get_wavefront_midi(substream);
268 	if (!midi)
269 	        return -EIO;
270 
271 	spin_lock_irqsave (&midi->open, flags);
272 	midi->mode[mpu] |= MPU401_MODE_OUTPUT;
273 	midi->substream_output[mpu] = substream;
274 	spin_unlock_irqrestore (&midi->open, flags);
275 
276 	return 0;
277 }
278 
snd_wavefront_midi_input_close(struct snd_rawmidi_substream * substream)279 static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream)
280 {
281 	unsigned long flags;
282 	snd_wavefront_midi_t *midi;
283 	snd_wavefront_mpu_id mpu;
284 
285 	if (snd_BUG_ON(!substream || !substream->rmidi))
286 		return -ENXIO;
287 	if (snd_BUG_ON(!substream->rmidi->private_data))
288 		return -ENXIO;
289 
290 	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
291 
292 	midi = get_wavefront_midi(substream);
293 	if (!midi)
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 
snd_wavefront_midi_output_close(struct snd_rawmidi_substream * substream)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 	midi = get_wavefront_midi(substream);
317 	if (!midi)
318 	        return -EIO;
319 
320 	spin_lock_irqsave (&midi->open, flags);
321 	midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
322 	spin_unlock_irqrestore (&midi->open, flags);
323 	return 0;
324 }
325 
snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream * substream,int up)326 static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
327 {
328 	unsigned long flags;
329 	snd_wavefront_midi_t *midi;
330 	snd_wavefront_mpu_id mpu;
331 
332 	if (substream == NULL || substream->rmidi == NULL)
333 	        return;
334 
335 	if (substream->rmidi->private_data == NULL)
336 	        return;
337 
338 	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
339 
340 	midi = get_wavefront_midi(substream);
341 	if (!midi)
342 		return;
343 
344 	spin_lock_irqsave (&midi->virtual, flags);
345 	if (up) {
346 		midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
347 	} else {
348 		midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
349 	}
350 	spin_unlock_irqrestore (&midi->virtual, flags);
351 }
352 
snd_wavefront_midi_output_timer(struct timer_list * t)353 static void snd_wavefront_midi_output_timer(struct timer_list *t)
354 {
355 	snd_wavefront_midi_t *midi = from_timer(midi, t, timer);
356 	snd_wavefront_card_t *card = midi->timer_card;
357 	unsigned long flags;
358 
359 	spin_lock_irqsave (&midi->virtual, flags);
360 	mod_timer(&midi->timer, 1 + jiffies);
361 	spin_unlock_irqrestore (&midi->virtual, flags);
362 	snd_wavefront_midi_output_write(card);
363 }
364 
snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream * substream,int up)365 static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
366 {
367 	unsigned long flags;
368 	snd_wavefront_midi_t *midi;
369 	snd_wavefront_mpu_id mpu;
370 
371 	if (substream == NULL || substream->rmidi == NULL)
372 	        return;
373 
374 	if (substream->rmidi->private_data == NULL)
375 	        return;
376 
377 	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
378 
379 	midi = get_wavefront_midi(substream);
380 	if (!midi)
381 		return;
382 
383 	spin_lock_irqsave (&midi->virtual, flags);
384 	if (up) {
385 		if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
386 			if (!midi->istimer) {
387 				timer_setup(&midi->timer,
388 					    snd_wavefront_midi_output_timer,
389 					    0);
390 				mod_timer(&midi->timer, 1 + jiffies);
391 			}
392 			midi->istimer++;
393 			midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
394 		}
395 	} else {
396 		midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
397 	}
398 	spin_unlock_irqrestore (&midi->virtual, flags);
399 
400 	if (up)
401 		snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);
402 }
403 
404 void
snd_wavefront_midi_interrupt(snd_wavefront_card_t * card)405 snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
406 
407 {
408 	unsigned long flags;
409 	snd_wavefront_midi_t *midi;
410 	static struct snd_rawmidi_substream *substream = NULL;
411 	static int mpu = external_mpu;
412 	int max = 128;
413 	unsigned char byte;
414 
415 	midi = &card->wavefront.midi;
416 
417 	if (!input_avail (midi)) { /* not for us */
418 		snd_wavefront_midi_output_write(card);
419 		return;
420 	}
421 
422 	spin_lock_irqsave (&midi->virtual, flags);
423 	while (--max) {
424 
425 		if (input_avail (midi)) {
426 			byte = read_data (midi);
427 
428 			if (midi->isvirtual) {
429 				if (byte == WF_EXTERNAL_SWITCH) {
430 					substream = midi->substream_input[external_mpu];
431 					mpu = external_mpu;
432 				} else if (byte == WF_INTERNAL_SWITCH) {
433 					substream = midi->substream_output[internal_mpu];
434 					mpu = internal_mpu;
435 				} /* else just leave it as it is */
436 			} else {
437 				substream = midi->substream_input[internal_mpu];
438 				mpu = internal_mpu;
439 			}
440 
441 			if (substream == NULL) {
442 				continue;
443 			}
444 
445 			if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
446 				snd_rawmidi_receive(substream, &byte, 1);
447 			}
448 		} else {
449 			break;
450 		}
451 	}
452 	spin_unlock_irqrestore (&midi->virtual, flags);
453 
454 	snd_wavefront_midi_output_write(card);
455 }
456 
457 void
snd_wavefront_midi_enable_virtual(snd_wavefront_card_t * card)458 snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card)
459 
460 {
461 	unsigned long flags;
462 
463 	spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
464 	card->wavefront.midi.isvirtual = 1;
465 	card->wavefront.midi.output_mpu = internal_mpu;
466 	card->wavefront.midi.input_mpu = internal_mpu;
467 	spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
468 }
469 
470 void
snd_wavefront_midi_disable_virtual(snd_wavefront_card_t * card)471 snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
472 
473 {
474 	unsigned long flags;
475 
476 	spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
477 	// snd_wavefront_midi_input_close (card->ics2115_external_rmidi);
478 	// snd_wavefront_midi_output_close (card->ics2115_external_rmidi);
479 	card->wavefront.midi.isvirtual = 0;
480 	spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
481 }
482 
483 int
snd_wavefront_midi_start(snd_wavefront_card_t * card)484 snd_wavefront_midi_start (snd_wavefront_card_t *card)
485 
486 {
487 	int ok, i;
488 	unsigned char rbuf[4], wbuf[4];
489 	snd_wavefront_t *dev;
490 	snd_wavefront_midi_t *midi;
491 
492 	dev = &card->wavefront;
493 	midi = &dev->midi;
494 
495 	/* The ICS2115 MPU-401 interface doesn't do anything
496 	   until its set into UART mode.
497 	*/
498 
499 	/* XXX fix me - no hard timing loops allowed! */
500 
501 	for (i = 0; i < 30000 && !output_ready (midi); i++);
502 
503 	if (!output_ready (midi)) {
504 		snd_printk ("MIDI interface not ready for command\n");
505 		return -1;
506 	}
507 
508 	/* Any interrupts received from now on
509 	   are owned by the MIDI side of things.
510 	*/
511 
512 	dev->interrupts_are_midi = 1;
513 
514 	outb (UART_MODE_ON, midi->mpu_command_port);
515 
516 	for (ok = 0, i = 50000; i > 0 && !ok; i--) {
517 		if (input_avail (midi)) {
518 			if (read_data (midi) == MPU_ACK) {
519 				ok = 1;
520 				break;
521 			}
522 		}
523 	}
524 
525 	if (!ok) {
526 		snd_printk ("cannot set UART mode for MIDI interface");
527 		dev->interrupts_are_midi = 0;
528 		return -1;
529 	}
530 
531 	/* Route external MIDI to WaveFront synth (by default) */
532 
533 	if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
534 		snd_printk ("can't enable MIDI-IN-2-synth routing.\n");
535 		/* XXX error ? */
536 	}
537 
538 	/* Turn on Virtual MIDI, but first *always* turn it off,
539 	   since otherwise consecutive reloads of the driver will
540 	   never cause the hardware to generate the initial "internal" or
541 	   "external" source bytes in the MIDI data stream. This
542 	   is pretty important, since the internal hardware generally will
543 	   be used to generate none or very little MIDI output, and
544 	   thus the only source of MIDI data is actually external. Without
545 	   the switch bytes, the driver will think it all comes from
546 	   the internal interface. Duh.
547 	*/
548 
549 	if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) {
550 		snd_printk ("virtual MIDI mode not disabled\n");
551 		return 0; /* We're OK, but missing the external MIDI dev */
552 	}
553 
554 	snd_wavefront_midi_enable_virtual (card);
555 
556 	if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
557 		snd_printk ("cannot enable virtual MIDI mode.\n");
558 		snd_wavefront_midi_disable_virtual (card);
559 	}
560 	return 0;
561 }
562 
563 const struct snd_rawmidi_ops snd_wavefront_midi_output =
564 {
565 	.open =		snd_wavefront_midi_output_open,
566 	.close =	snd_wavefront_midi_output_close,
567 	.trigger =	snd_wavefront_midi_output_trigger,
568 };
569 
570 const struct snd_rawmidi_ops snd_wavefront_midi_input =
571 {
572 	.open =		snd_wavefront_midi_input_open,
573 	.close =	snd_wavefront_midi_input_close,
574 	.trigger =	snd_wavefront_midi_input_trigger,
575 };
576 
577