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