• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/sound/isa/wavefront/
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 <asm/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
57static inline int
58wf_mpu_status (snd_wavefront_midi_t *midi)
59
60{
61	return inb (midi->mpu_status_port);
62}
63
64static inline int
65input_avail (snd_wavefront_midi_t *midi)
66
67{
68	return !(wf_mpu_status(midi) & INPUT_AVAIL);
69}
70
71static inline int
72output_ready (snd_wavefront_midi_t *midi)
73
74{
75	return !(wf_mpu_status(midi) & OUTPUT_READY);
76}
77
78static inline int
79read_data (snd_wavefront_midi_t *midi)
80
81{
82	return inb (midi->mpu_data_port);
83}
84
85static inline void
86write_data (snd_wavefront_midi_t *midi, unsigned char byte)
87
88{
89	outb (byte, midi->mpu_data_port);
90}
91
92static snd_wavefront_midi_t *
93get_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
115static 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
142		for (timeout = 30000; timeout > 0; timeout--) {
143			if (output_ready (midi))
144				break;
145		}
146
147		spin_lock_irqsave (&midi->virtual, flags);
148		if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) {
149			spin_unlock_irqrestore (&midi->virtual, flags);
150			goto __second;
151		}
152		if (output_ready (midi)) {
153			if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) {
154				if (!midi->isvirtual ||
155					(midi_byte != WF_INTERNAL_SWITCH &&
156					 midi_byte != WF_EXTERNAL_SWITCH))
157					write_data(midi, midi_byte);
158				max--;
159			} else {
160				if (midi->istimer) {
161					if (--midi->istimer <= 0)
162						del_timer(&midi->timer);
163				}
164				midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
165				spin_unlock_irqrestore (&midi->virtual, flags);
166				goto __second;
167			}
168		} else {
169			spin_unlock_irqrestore (&midi->virtual, flags);
170			return;
171		}
172		spin_unlock_irqrestore (&midi->virtual, flags);
173	}
174
175      __second:
176
177	if (midi->substream_output[!midi->output_mpu] == NULL) {
178		return;
179	}
180
181	while (max > 0) {
182
183
184		for (timeout = 30000; timeout > 0; timeout--) {
185			if (output_ready (midi))
186				break;
187		}
188
189		spin_lock_irqsave (&midi->virtual, flags);
190		if (!midi->isvirtual)
191			mask = 0;
192		mpu = midi->output_mpu ^ mask;
193		mask = 0;	/* don't invert the value from now */
194		if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) {
195			spin_unlock_irqrestore (&midi->virtual, flags);
196			return;
197		}
198		if (snd_rawmidi_transmit_empty(midi->substream_output[mpu]))
199			goto __timer;
200		if (output_ready (midi)) {
201			if (mpu != midi->output_mpu) {
202				write_data(midi, mpu == internal_mpu ?
203							WF_INTERNAL_SWITCH :
204							WF_EXTERNAL_SWITCH);
205				midi->output_mpu = mpu;
206			} else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) {
207				if (!midi->isvirtual ||
208					(midi_byte != WF_INTERNAL_SWITCH &&
209					 midi_byte != WF_EXTERNAL_SWITCH))
210					write_data(midi, midi_byte);
211				max--;
212			} else {
213			      __timer:
214				if (midi->istimer) {
215					if (--midi->istimer <= 0)
216						del_timer(&midi->timer);
217				}
218				midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
219				spin_unlock_irqrestore (&midi->virtual, flags);
220				return;
221			}
222		} else {
223			spin_unlock_irqrestore (&midi->virtual, flags);
224			return;
225		}
226		spin_unlock_irqrestore (&midi->virtual, flags);
227	}
228}
229
230static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream)
231{
232	unsigned long flags;
233	snd_wavefront_midi_t *midi;
234	snd_wavefront_mpu_id mpu;
235
236	if (snd_BUG_ON(!substream || !substream->rmidi))
237		return -ENXIO;
238	if (snd_BUG_ON(!substream->rmidi->private_data))
239		return -ENXIO;
240
241	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
242
243	if ((midi = get_wavefront_midi (substream)) == NULL)
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
254static 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	if ((midi = get_wavefront_midi (substream)) == NULL)
268	        return -EIO;
269
270	spin_lock_irqsave (&midi->open, flags);
271	midi->mode[mpu] |= MPU401_MODE_OUTPUT;
272	midi->substream_output[mpu] = substream;
273	spin_unlock_irqrestore (&midi->open, flags);
274
275	return 0;
276}
277
278static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream)
279{
280	unsigned long flags;
281	snd_wavefront_midi_t *midi;
282	snd_wavefront_mpu_id mpu;
283
284	if (snd_BUG_ON(!substream || !substream->rmidi))
285		return -ENXIO;
286	if (snd_BUG_ON(!substream->rmidi->private_data))
287		return -ENXIO;
288
289	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
290
291	if ((midi = get_wavefront_midi (substream)) == NULL)
292	        return -EIO;
293
294	spin_lock_irqsave (&midi->open, flags);
295	midi->mode[mpu] &= ~MPU401_MODE_INPUT;
296	spin_unlock_irqrestore (&midi->open, flags);
297
298	return 0;
299}
300
301static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream)
302{
303	unsigned long flags;
304	snd_wavefront_midi_t *midi;
305	snd_wavefront_mpu_id mpu;
306
307	if (snd_BUG_ON(!substream || !substream->rmidi))
308		return -ENXIO;
309	if (snd_BUG_ON(!substream->rmidi->private_data))
310		return -ENXIO;
311
312	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
313
314	if ((midi = get_wavefront_midi (substream)) == NULL)
315	        return -EIO;
316
317	spin_lock_irqsave (&midi->open, flags);
318	midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
319	spin_unlock_irqrestore (&midi->open, flags);
320	return 0;
321}
322
323static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
324{
325	unsigned long flags;
326	snd_wavefront_midi_t *midi;
327	snd_wavefront_mpu_id mpu;
328
329	if (substream == NULL || substream->rmidi == NULL)
330	        return;
331
332	if (substream->rmidi->private_data == NULL)
333	        return;
334
335	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
336
337	if ((midi = get_wavefront_midi (substream)) == NULL) {
338		return;
339	}
340
341	spin_lock_irqsave (&midi->virtual, flags);
342	if (up) {
343		midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
344	} else {
345		midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
346	}
347	spin_unlock_irqrestore (&midi->virtual, flags);
348}
349
350static void snd_wavefront_midi_output_timer(unsigned long data)
351{
352	snd_wavefront_card_t *card = (snd_wavefront_card_t *)data;
353	snd_wavefront_midi_t *midi = &card->wavefront.midi;
354	unsigned long flags;
355
356	spin_lock_irqsave (&midi->virtual, flags);
357	midi->timer.expires = 1 + jiffies;
358	add_timer(&midi->timer);
359	spin_unlock_irqrestore (&midi->virtual, flags);
360	snd_wavefront_midi_output_write(card);
361}
362
363static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
364{
365	unsigned long flags;
366	snd_wavefront_midi_t *midi;
367	snd_wavefront_mpu_id mpu;
368
369	if (substream == NULL || substream->rmidi == NULL)
370	        return;
371
372	if (substream->rmidi->private_data == NULL)
373	        return;
374
375	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
376
377	if ((midi = get_wavefront_midi (substream)) == NULL) {
378		return;
379	}
380
381	spin_lock_irqsave (&midi->virtual, flags);
382	if (up) {
383		if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
384			if (!midi->istimer) {
385				init_timer(&midi->timer);
386				midi->timer.function = snd_wavefront_midi_output_timer;
387				midi->timer.data = (unsigned long) substream->rmidi->card->private_data;
388				midi->timer.expires = 1 + jiffies;
389				add_timer(&midi->timer);
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
403void
404snd_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
456void
457snd_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
469void
470snd_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
482int __devinit
483snd_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
499	for (i = 0; i < 30000 && !output_ready (midi); i++);
500
501	if (!output_ready (midi)) {
502		snd_printk ("MIDI interface not ready for command\n");
503		return -1;
504	}
505
506	/* Any interrupts received from now on
507	   are owned by the MIDI side of things.
508	*/
509
510	dev->interrupts_are_midi = 1;
511
512	outb (UART_MODE_ON, midi->mpu_command_port);
513
514	for (ok = 0, i = 50000; i > 0 && !ok; i--) {
515		if (input_avail (midi)) {
516			if (read_data (midi) == MPU_ACK) {
517				ok = 1;
518				break;
519			}
520		}
521	}
522
523	if (!ok) {
524		snd_printk ("cannot set UART mode for MIDI interface");
525		dev->interrupts_are_midi = 0;
526		return -1;
527	}
528
529	/* Route external MIDI to WaveFront synth (by default) */
530
531	if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
532		snd_printk ("can't enable MIDI-IN-2-synth routing.\n");
533	}
534
535	/* Turn on Virtual MIDI, but first *always* turn it off,
536	   since otherwise consectutive reloads of the driver will
537	   never cause the hardware to generate the initial "internal" or
538	   "external" source bytes in the MIDI data stream. This
539	   is pretty important, since the internal hardware generally will
540	   be used to generate none or very little MIDI output, and
541	   thus the only source of MIDI data is actually external. Without
542	   the switch bytes, the driver will think it all comes from
543	   the internal interface. Duh.
544	*/
545
546	if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) {
547		snd_printk ("virtual MIDI mode not disabled\n");
548		return 0; /* We're OK, but missing the external MIDI dev */
549	}
550
551	snd_wavefront_midi_enable_virtual (card);
552
553	if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
554		snd_printk ("cannot enable virtual MIDI mode.\n");
555		snd_wavefront_midi_disable_virtual (card);
556	}
557	return 0;
558}
559
560struct snd_rawmidi_ops snd_wavefront_midi_output =
561{
562	.open =		snd_wavefront_midi_output_open,
563	.close =	snd_wavefront_midi_output_close,
564	.trigger =	snd_wavefront_midi_output_trigger,
565};
566
567struct snd_rawmidi_ops snd_wavefront_midi_input =
568{
569	.open =		snd_wavefront_midi_input_open,
570	.close =	snd_wavefront_midi_input_close,
571	.trigger =	snd_wavefront_midi_input_trigger,
572};
573