xref: /openbmc/linux/sound/isa/wavefront/wavefront_midi.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * Copyright (C) by Paul Barton-Davis 1998-1999
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
5*1da177e4SLinus Torvalds  * Version 2 (June 1991). See the "COPYING" file distributed with this
6*1da177e4SLinus Torvalds  * software for more info.
7*1da177e4SLinus Torvalds  */
8*1da177e4SLinus Torvalds 
9*1da177e4SLinus Torvalds /* The low level driver for the WaveFront ICS2115 MIDI interface(s)
10*1da177e4SLinus Torvalds  *
11*1da177e4SLinus Torvalds  * Note that there is also an MPU-401 emulation (actually, a UART-401
12*1da177e4SLinus Torvalds  * emulation) on the CS4232 on the Tropez and Tropez Plus. This code
13*1da177e4SLinus Torvalds  * has nothing to do with that interface at all.
14*1da177e4SLinus Torvalds  *
15*1da177e4SLinus Torvalds  * The interface is essentially just a UART-401, but is has the
16*1da177e4SLinus Torvalds  * interesting property of supporting what Turtle Beach called
17*1da177e4SLinus Torvalds  * "Virtual MIDI" mode. In this mode, there are effectively *two*
18*1da177e4SLinus Torvalds  * MIDI buses accessible via the interface, one that is routed
19*1da177e4SLinus Torvalds  * solely to/from the external WaveFront synthesizer and the other
20*1da177e4SLinus Torvalds  * corresponding to the pin/socket connector used to link external
21*1da177e4SLinus Torvalds  * MIDI devices to the board.
22*1da177e4SLinus Torvalds  *
23*1da177e4SLinus Torvalds  * This driver fully supports this mode, allowing two distinct MIDI
24*1da177e4SLinus Torvalds  * busses to be used completely independently, giving 32 channels of
25*1da177e4SLinus Torvalds  * MIDI routing, 16 to the WaveFront synth and 16 to the external MIDI
26*1da177e4SLinus Torvalds  * bus. The devices are named /dev/snd/midiCnD0 and /dev/snd/midiCnD1,
27*1da177e4SLinus Torvalds  * where `n' is the card number. Note that the device numbers may be
28*1da177e4SLinus Torvalds  * something other than 0 and 1 if the CS4232 UART/MPU-401 interface
29*1da177e4SLinus Torvalds  * is enabled.
30*1da177e4SLinus Torvalds  *
31*1da177e4SLinus Torvalds  * Switching between the two is accomplished externally by the driver
32*1da177e4SLinus Torvalds  * using the two otherwise unused MIDI bytes. See the code for more details.
33*1da177e4SLinus Torvalds  *
34*1da177e4SLinus Torvalds  * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see lowlevel/isa/wavefront.c)
35*1da177e4SLinus Torvalds  *
36*1da177e4SLinus Torvalds  * The main reason to turn off Virtual MIDI mode is when you want to
37*1da177e4SLinus Torvalds  * tightly couple the WaveFront synth with an external MIDI
38*1da177e4SLinus Torvalds  * device. You won't be able to distinguish the source of any MIDI
39*1da177e4SLinus Torvalds  * data except via SysEx ID, but thats probably OK, since for the most
40*1da177e4SLinus Torvalds  * part, the WaveFront won't be sending any MIDI data at all.
41*1da177e4SLinus Torvalds  *
42*1da177e4SLinus Torvalds  * The main reason to turn on Virtual MIDI Mode is to provide two
43*1da177e4SLinus Torvalds  * completely independent 16-channel MIDI buses, one to the
44*1da177e4SLinus Torvalds  * WaveFront and one to any external MIDI devices. Given the 32
45*1da177e4SLinus Torvalds  * voice nature of the WaveFront, its pretty easy to find a use
46*1da177e4SLinus Torvalds  * for all 16 channels driving just that synth.
47*1da177e4SLinus Torvalds  *
48*1da177e4SLinus Torvalds  */
49*1da177e4SLinus Torvalds 
50*1da177e4SLinus Torvalds #include <sound/driver.h>
51*1da177e4SLinus Torvalds #include <asm/io.h>
52*1da177e4SLinus Torvalds #include <linux/init.h>
53*1da177e4SLinus Torvalds #include <linux/time.h>
54*1da177e4SLinus Torvalds #include <linux/wait.h>
55*1da177e4SLinus Torvalds #include <sound/core.h>
56*1da177e4SLinus Torvalds #include <sound/snd_wavefront.h>
57*1da177e4SLinus Torvalds 
58*1da177e4SLinus Torvalds static inline int
59*1da177e4SLinus Torvalds wf_mpu_status (snd_wavefront_midi_t *midi)
60*1da177e4SLinus Torvalds 
61*1da177e4SLinus Torvalds {
62*1da177e4SLinus Torvalds 	return inb (midi->mpu_status_port);
63*1da177e4SLinus Torvalds }
64*1da177e4SLinus Torvalds 
65*1da177e4SLinus Torvalds static inline int
66*1da177e4SLinus Torvalds input_avail (snd_wavefront_midi_t *midi)
67*1da177e4SLinus Torvalds 
68*1da177e4SLinus Torvalds {
69*1da177e4SLinus Torvalds 	return !(wf_mpu_status(midi) & INPUT_AVAIL);
70*1da177e4SLinus Torvalds }
71*1da177e4SLinus Torvalds 
72*1da177e4SLinus Torvalds static inline int
73*1da177e4SLinus Torvalds output_ready (snd_wavefront_midi_t *midi)
74*1da177e4SLinus Torvalds 
75*1da177e4SLinus Torvalds {
76*1da177e4SLinus Torvalds 	return !(wf_mpu_status(midi) & OUTPUT_READY);
77*1da177e4SLinus Torvalds }
78*1da177e4SLinus Torvalds 
79*1da177e4SLinus Torvalds static inline int
80*1da177e4SLinus Torvalds read_data (snd_wavefront_midi_t *midi)
81*1da177e4SLinus Torvalds 
82*1da177e4SLinus Torvalds {
83*1da177e4SLinus Torvalds 	return inb (midi->mpu_data_port);
84*1da177e4SLinus Torvalds }
85*1da177e4SLinus Torvalds 
86*1da177e4SLinus Torvalds static inline void
87*1da177e4SLinus Torvalds write_data (snd_wavefront_midi_t *midi, unsigned char byte)
88*1da177e4SLinus Torvalds 
89*1da177e4SLinus Torvalds {
90*1da177e4SLinus Torvalds 	outb (byte, midi->mpu_data_port);
91*1da177e4SLinus Torvalds }
92*1da177e4SLinus Torvalds 
93*1da177e4SLinus Torvalds static snd_wavefront_midi_t *
94*1da177e4SLinus Torvalds get_wavefront_midi (snd_rawmidi_substream_t *substream)
95*1da177e4SLinus Torvalds 
96*1da177e4SLinus Torvalds {
97*1da177e4SLinus Torvalds 	snd_card_t *card;
98*1da177e4SLinus Torvalds 	snd_wavefront_card_t *acard;
99*1da177e4SLinus Torvalds 
100*1da177e4SLinus Torvalds 	if (substream == NULL || substream->rmidi == NULL)
101*1da177e4SLinus Torvalds 	        return NULL;
102*1da177e4SLinus Torvalds 
103*1da177e4SLinus Torvalds 	card = substream->rmidi->card;
104*1da177e4SLinus Torvalds 
105*1da177e4SLinus Torvalds 	if (card == NULL)
106*1da177e4SLinus Torvalds 	        return NULL;
107*1da177e4SLinus Torvalds 
108*1da177e4SLinus Torvalds 	if (card->private_data == NULL)
109*1da177e4SLinus Torvalds  	        return NULL;
110*1da177e4SLinus Torvalds 
111*1da177e4SLinus Torvalds 	acard = card->private_data;
112*1da177e4SLinus Torvalds 
113*1da177e4SLinus Torvalds 	return &acard->wavefront.midi;
114*1da177e4SLinus Torvalds }
115*1da177e4SLinus Torvalds 
116*1da177e4SLinus Torvalds static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card)
117*1da177e4SLinus Torvalds {
118*1da177e4SLinus Torvalds 	snd_wavefront_midi_t *midi = &card->wavefront.midi;
119*1da177e4SLinus Torvalds 	snd_wavefront_mpu_id  mpu;
120*1da177e4SLinus Torvalds 	unsigned long flags;
121*1da177e4SLinus Torvalds 	unsigned char midi_byte;
122*1da177e4SLinus Torvalds 	int max = 256, mask = 1;
123*1da177e4SLinus Torvalds 	int timeout;
124*1da177e4SLinus Torvalds 
125*1da177e4SLinus Torvalds 	/* Its not OK to try to change the status of "virtuality" of
126*1da177e4SLinus Torvalds 	   the MIDI interface while we're outputting stuff.  See
127*1da177e4SLinus Torvalds 	   snd_wavefront_midi_{enable,disable}_virtual () for the
128*1da177e4SLinus Torvalds 	   other half of this.
129*1da177e4SLinus Torvalds 
130*1da177e4SLinus Torvalds 	   The first loop attempts to flush any data from the
131*1da177e4SLinus Torvalds 	   current output device, and then the second
132*1da177e4SLinus Torvalds 	   emits the switch byte (if necessary), and starts
133*1da177e4SLinus Torvalds 	   outputting data for the output device currently in use.
134*1da177e4SLinus Torvalds 	*/
135*1da177e4SLinus Torvalds 
136*1da177e4SLinus Torvalds 	if (midi->substream_output[midi->output_mpu] == NULL) {
137*1da177e4SLinus Torvalds 		goto __second;
138*1da177e4SLinus Torvalds 	}
139*1da177e4SLinus Torvalds 
140*1da177e4SLinus Torvalds 	while (max > 0) {
141*1da177e4SLinus Torvalds 
142*1da177e4SLinus Torvalds 		/* XXX fix me - no hard timing loops allowed! */
143*1da177e4SLinus Torvalds 
144*1da177e4SLinus Torvalds 		for (timeout = 30000; timeout > 0; timeout--) {
145*1da177e4SLinus Torvalds 			if (output_ready (midi))
146*1da177e4SLinus Torvalds 				break;
147*1da177e4SLinus Torvalds 		}
148*1da177e4SLinus Torvalds 
149*1da177e4SLinus Torvalds 		spin_lock_irqsave (&midi->virtual, flags);
150*1da177e4SLinus Torvalds 		if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) {
151*1da177e4SLinus Torvalds 			spin_unlock_irqrestore (&midi->virtual, flags);
152*1da177e4SLinus Torvalds 			goto __second;
153*1da177e4SLinus Torvalds 		}
154*1da177e4SLinus Torvalds 		if (output_ready (midi)) {
155*1da177e4SLinus Torvalds 			if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) {
156*1da177e4SLinus Torvalds 				if (!midi->isvirtual ||
157*1da177e4SLinus Torvalds 					(midi_byte != WF_INTERNAL_SWITCH &&
158*1da177e4SLinus Torvalds 					 midi_byte != WF_EXTERNAL_SWITCH))
159*1da177e4SLinus Torvalds 					write_data(midi, midi_byte);
160*1da177e4SLinus Torvalds 				max--;
161*1da177e4SLinus Torvalds 			} else {
162*1da177e4SLinus Torvalds 				if (midi->istimer) {
163*1da177e4SLinus Torvalds 					if (--midi->istimer <= 0)
164*1da177e4SLinus Torvalds 						del_timer(&midi->timer);
165*1da177e4SLinus Torvalds 				}
166*1da177e4SLinus Torvalds 				midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
167*1da177e4SLinus Torvalds 				spin_unlock_irqrestore (&midi->virtual, flags);
168*1da177e4SLinus Torvalds 				goto __second;
169*1da177e4SLinus Torvalds 			}
170*1da177e4SLinus Torvalds 		} else {
171*1da177e4SLinus Torvalds 			spin_unlock_irqrestore (&midi->virtual, flags);
172*1da177e4SLinus Torvalds 			return;
173*1da177e4SLinus Torvalds 		}
174*1da177e4SLinus Torvalds 		spin_unlock_irqrestore (&midi->virtual, flags);
175*1da177e4SLinus Torvalds 	}
176*1da177e4SLinus Torvalds 
177*1da177e4SLinus Torvalds       __second:
178*1da177e4SLinus Torvalds 
179*1da177e4SLinus Torvalds 	if (midi->substream_output[!midi->output_mpu] == NULL) {
180*1da177e4SLinus Torvalds 		return;
181*1da177e4SLinus Torvalds 	}
182*1da177e4SLinus Torvalds 
183*1da177e4SLinus Torvalds 	while (max > 0) {
184*1da177e4SLinus Torvalds 
185*1da177e4SLinus Torvalds 		/* XXX fix me - no hard timing loops allowed! */
186*1da177e4SLinus Torvalds 
187*1da177e4SLinus Torvalds 		for (timeout = 30000; timeout > 0; timeout--) {
188*1da177e4SLinus Torvalds 			if (output_ready (midi))
189*1da177e4SLinus Torvalds 				break;
190*1da177e4SLinus Torvalds 		}
191*1da177e4SLinus Torvalds 
192*1da177e4SLinus Torvalds 		spin_lock_irqsave (&midi->virtual, flags);
193*1da177e4SLinus Torvalds 		if (!midi->isvirtual)
194*1da177e4SLinus Torvalds 			mask = 0;
195*1da177e4SLinus Torvalds 		mpu = midi->output_mpu ^ mask;
196*1da177e4SLinus Torvalds 		mask = 0;	/* don't invert the value from now */
197*1da177e4SLinus Torvalds 		if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) {
198*1da177e4SLinus Torvalds 			spin_unlock_irqrestore (&midi->virtual, flags);
199*1da177e4SLinus Torvalds 			return;
200*1da177e4SLinus Torvalds 		}
201*1da177e4SLinus Torvalds 		if (snd_rawmidi_transmit_empty(midi->substream_output[mpu]))
202*1da177e4SLinus Torvalds 			goto __timer;
203*1da177e4SLinus Torvalds 		if (output_ready (midi)) {
204*1da177e4SLinus Torvalds 			if (mpu != midi->output_mpu) {
205*1da177e4SLinus Torvalds 				write_data(midi, mpu == internal_mpu ?
206*1da177e4SLinus Torvalds 							WF_INTERNAL_SWITCH :
207*1da177e4SLinus Torvalds 							WF_EXTERNAL_SWITCH);
208*1da177e4SLinus Torvalds 				midi->output_mpu = mpu;
209*1da177e4SLinus Torvalds 			} else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) {
210*1da177e4SLinus Torvalds 				if (!midi->isvirtual ||
211*1da177e4SLinus Torvalds 					(midi_byte != WF_INTERNAL_SWITCH &&
212*1da177e4SLinus Torvalds 					 midi_byte != WF_EXTERNAL_SWITCH))
213*1da177e4SLinus Torvalds 					write_data(midi, midi_byte);
214*1da177e4SLinus Torvalds 				max--;
215*1da177e4SLinus Torvalds 			} else {
216*1da177e4SLinus Torvalds 			      __timer:
217*1da177e4SLinus Torvalds 				if (midi->istimer) {
218*1da177e4SLinus Torvalds 					if (--midi->istimer <= 0)
219*1da177e4SLinus Torvalds 						del_timer(&midi->timer);
220*1da177e4SLinus Torvalds 				}
221*1da177e4SLinus Torvalds 				midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
222*1da177e4SLinus Torvalds 				spin_unlock_irqrestore (&midi->virtual, flags);
223*1da177e4SLinus Torvalds 				return;
224*1da177e4SLinus Torvalds 			}
225*1da177e4SLinus Torvalds 		} else {
226*1da177e4SLinus Torvalds 			spin_unlock_irqrestore (&midi->virtual, flags);
227*1da177e4SLinus Torvalds 			return;
228*1da177e4SLinus Torvalds 		}
229*1da177e4SLinus Torvalds 		spin_unlock_irqrestore (&midi->virtual, flags);
230*1da177e4SLinus Torvalds 	}
231*1da177e4SLinus Torvalds }
232*1da177e4SLinus Torvalds 
233*1da177e4SLinus Torvalds static int snd_wavefront_midi_input_open(snd_rawmidi_substream_t * substream)
234*1da177e4SLinus Torvalds {
235*1da177e4SLinus Torvalds 	unsigned long flags;
236*1da177e4SLinus Torvalds 	snd_wavefront_midi_t *midi;
237*1da177e4SLinus Torvalds 	snd_wavefront_mpu_id mpu;
238*1da177e4SLinus Torvalds 
239*1da177e4SLinus Torvalds 	snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
240*1da177e4SLinus Torvalds 	snd_assert(substream->rmidi->private_data != NULL, return -EIO);
241*1da177e4SLinus Torvalds 
242*1da177e4SLinus Torvalds 	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
243*1da177e4SLinus Torvalds 
244*1da177e4SLinus Torvalds 	if ((midi = get_wavefront_midi (substream)) == NULL)
245*1da177e4SLinus Torvalds 	        return -EIO;
246*1da177e4SLinus Torvalds 
247*1da177e4SLinus Torvalds 	spin_lock_irqsave (&midi->open, flags);
248*1da177e4SLinus Torvalds 	midi->mode[mpu] |= MPU401_MODE_INPUT;
249*1da177e4SLinus Torvalds 	midi->substream_input[mpu] = substream;
250*1da177e4SLinus Torvalds 	spin_unlock_irqrestore (&midi->open, flags);
251*1da177e4SLinus Torvalds 
252*1da177e4SLinus Torvalds 	return 0;
253*1da177e4SLinus Torvalds }
254*1da177e4SLinus Torvalds 
255*1da177e4SLinus Torvalds static int snd_wavefront_midi_output_open(snd_rawmidi_substream_t * substream)
256*1da177e4SLinus Torvalds {
257*1da177e4SLinus Torvalds 	unsigned long flags;
258*1da177e4SLinus Torvalds 	snd_wavefront_midi_t *midi;
259*1da177e4SLinus Torvalds 	snd_wavefront_mpu_id mpu;
260*1da177e4SLinus Torvalds 
261*1da177e4SLinus Torvalds 	snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
262*1da177e4SLinus Torvalds 	snd_assert(substream->rmidi->private_data != NULL, return -EIO);
263*1da177e4SLinus Torvalds 
264*1da177e4SLinus Torvalds 	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
265*1da177e4SLinus Torvalds 
266*1da177e4SLinus Torvalds 	if ((midi = get_wavefront_midi (substream)) == NULL)
267*1da177e4SLinus Torvalds 	        return -EIO;
268*1da177e4SLinus Torvalds 
269*1da177e4SLinus Torvalds 	spin_lock_irqsave (&midi->open, flags);
270*1da177e4SLinus Torvalds 	midi->mode[mpu] |= MPU401_MODE_OUTPUT;
271*1da177e4SLinus Torvalds 	midi->substream_output[mpu] = substream;
272*1da177e4SLinus Torvalds 	spin_unlock_irqrestore (&midi->open, flags);
273*1da177e4SLinus Torvalds 
274*1da177e4SLinus Torvalds 	return 0;
275*1da177e4SLinus Torvalds }
276*1da177e4SLinus Torvalds 
277*1da177e4SLinus Torvalds static int snd_wavefront_midi_input_close(snd_rawmidi_substream_t * substream)
278*1da177e4SLinus Torvalds {
279*1da177e4SLinus Torvalds 	unsigned long flags;
280*1da177e4SLinus Torvalds 	snd_wavefront_midi_t *midi;
281*1da177e4SLinus Torvalds 	snd_wavefront_mpu_id mpu;
282*1da177e4SLinus Torvalds 
283*1da177e4SLinus Torvalds 	snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
284*1da177e4SLinus Torvalds 	snd_assert(substream->rmidi->private_data != NULL, return -EIO);
285*1da177e4SLinus Torvalds 
286*1da177e4SLinus Torvalds 	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
287*1da177e4SLinus Torvalds 
288*1da177e4SLinus Torvalds 	if ((midi = get_wavefront_midi (substream)) == NULL)
289*1da177e4SLinus Torvalds 	        return -EIO;
290*1da177e4SLinus Torvalds 
291*1da177e4SLinus Torvalds 	spin_lock_irqsave (&midi->open, flags);
292*1da177e4SLinus Torvalds 	midi->mode[mpu] &= ~MPU401_MODE_INPUT;
293*1da177e4SLinus Torvalds 	spin_unlock_irqrestore (&midi->open, flags);
294*1da177e4SLinus Torvalds 
295*1da177e4SLinus Torvalds 	return 0;
296*1da177e4SLinus Torvalds }
297*1da177e4SLinus Torvalds 
298*1da177e4SLinus Torvalds static int snd_wavefront_midi_output_close(snd_rawmidi_substream_t * substream)
299*1da177e4SLinus Torvalds {
300*1da177e4SLinus Torvalds 	unsigned long flags;
301*1da177e4SLinus Torvalds 	snd_wavefront_midi_t *midi;
302*1da177e4SLinus Torvalds 	snd_wavefront_mpu_id mpu;
303*1da177e4SLinus Torvalds 
304*1da177e4SLinus Torvalds 	snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
305*1da177e4SLinus Torvalds 	snd_assert(substream->rmidi->private_data != NULL, return -EIO);
306*1da177e4SLinus Torvalds 
307*1da177e4SLinus Torvalds 	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
308*1da177e4SLinus Torvalds 
309*1da177e4SLinus Torvalds 	if ((midi = get_wavefront_midi (substream)) == NULL)
310*1da177e4SLinus Torvalds 	        return -EIO;
311*1da177e4SLinus Torvalds 
312*1da177e4SLinus Torvalds 	spin_lock_irqsave (&midi->open, flags);
313*1da177e4SLinus Torvalds 	midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
314*1da177e4SLinus Torvalds 	spin_unlock_irqrestore (&midi->open, flags);
315*1da177e4SLinus Torvalds 	return 0;
316*1da177e4SLinus Torvalds }
317*1da177e4SLinus Torvalds 
318*1da177e4SLinus Torvalds static void snd_wavefront_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
319*1da177e4SLinus Torvalds {
320*1da177e4SLinus Torvalds 	unsigned long flags;
321*1da177e4SLinus Torvalds 	snd_wavefront_midi_t *midi;
322*1da177e4SLinus Torvalds 	snd_wavefront_mpu_id mpu;
323*1da177e4SLinus Torvalds 
324*1da177e4SLinus Torvalds 	if (substream == NULL || substream->rmidi == NULL)
325*1da177e4SLinus Torvalds 	        return;
326*1da177e4SLinus Torvalds 
327*1da177e4SLinus Torvalds 	if (substream->rmidi->private_data == NULL)
328*1da177e4SLinus Torvalds 	        return;
329*1da177e4SLinus Torvalds 
330*1da177e4SLinus Torvalds 	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
331*1da177e4SLinus Torvalds 
332*1da177e4SLinus Torvalds 	if ((midi = get_wavefront_midi (substream)) == NULL) {
333*1da177e4SLinus Torvalds 		return;
334*1da177e4SLinus Torvalds 	}
335*1da177e4SLinus Torvalds 
336*1da177e4SLinus Torvalds 	spin_lock_irqsave (&midi->virtual, flags);
337*1da177e4SLinus Torvalds 	if (up) {
338*1da177e4SLinus Torvalds 		midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
339*1da177e4SLinus Torvalds 	} else {
340*1da177e4SLinus Torvalds 		midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
341*1da177e4SLinus Torvalds 	}
342*1da177e4SLinus Torvalds 	spin_unlock_irqrestore (&midi->virtual, flags);
343*1da177e4SLinus Torvalds }
344*1da177e4SLinus Torvalds 
345*1da177e4SLinus Torvalds static void snd_wavefront_midi_output_timer(unsigned long data)
346*1da177e4SLinus Torvalds {
347*1da177e4SLinus Torvalds 	snd_wavefront_card_t *card = (snd_wavefront_card_t *)data;
348*1da177e4SLinus Torvalds 	snd_wavefront_midi_t *midi = &card->wavefront.midi;
349*1da177e4SLinus Torvalds 	unsigned long flags;
350*1da177e4SLinus Torvalds 
351*1da177e4SLinus Torvalds 	spin_lock_irqsave (&midi->virtual, flags);
352*1da177e4SLinus Torvalds 	midi->timer.expires = 1 + jiffies;
353*1da177e4SLinus Torvalds 	add_timer(&midi->timer);
354*1da177e4SLinus Torvalds 	spin_unlock_irqrestore (&midi->virtual, flags);
355*1da177e4SLinus Torvalds 	snd_wavefront_midi_output_write(card);
356*1da177e4SLinus Torvalds }
357*1da177e4SLinus Torvalds 
358*1da177e4SLinus Torvalds static void snd_wavefront_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
359*1da177e4SLinus Torvalds {
360*1da177e4SLinus Torvalds 	unsigned long flags;
361*1da177e4SLinus Torvalds 	snd_wavefront_midi_t *midi;
362*1da177e4SLinus Torvalds 	snd_wavefront_mpu_id mpu;
363*1da177e4SLinus Torvalds 
364*1da177e4SLinus Torvalds 	if (substream == NULL || substream->rmidi == NULL)
365*1da177e4SLinus Torvalds 	        return;
366*1da177e4SLinus Torvalds 
367*1da177e4SLinus Torvalds 	if (substream->rmidi->private_data == NULL)
368*1da177e4SLinus Torvalds 	        return;
369*1da177e4SLinus Torvalds 
370*1da177e4SLinus Torvalds 	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
371*1da177e4SLinus Torvalds 
372*1da177e4SLinus Torvalds 	if ((midi = get_wavefront_midi (substream)) == NULL) {
373*1da177e4SLinus Torvalds 		return;
374*1da177e4SLinus Torvalds 	}
375*1da177e4SLinus Torvalds 
376*1da177e4SLinus Torvalds 	spin_lock_irqsave (&midi->virtual, flags);
377*1da177e4SLinus Torvalds 	if (up) {
378*1da177e4SLinus Torvalds 		if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
379*1da177e4SLinus Torvalds 			if (!midi->istimer) {
380*1da177e4SLinus Torvalds 				init_timer(&midi->timer);
381*1da177e4SLinus Torvalds 				midi->timer.function = snd_wavefront_midi_output_timer;
382*1da177e4SLinus Torvalds 				midi->timer.data = (unsigned long) substream->rmidi->card->private_data;
383*1da177e4SLinus Torvalds 				midi->timer.expires = 1 + jiffies;
384*1da177e4SLinus Torvalds 				add_timer(&midi->timer);
385*1da177e4SLinus Torvalds 			}
386*1da177e4SLinus Torvalds 			midi->istimer++;
387*1da177e4SLinus Torvalds 			midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
388*1da177e4SLinus Torvalds 		}
389*1da177e4SLinus Torvalds 	} else {
390*1da177e4SLinus Torvalds 		midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
391*1da177e4SLinus Torvalds 	}
392*1da177e4SLinus Torvalds 	spin_unlock_irqrestore (&midi->virtual, flags);
393*1da177e4SLinus Torvalds 
394*1da177e4SLinus Torvalds 	if (up)
395*1da177e4SLinus Torvalds 		snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);
396*1da177e4SLinus Torvalds }
397*1da177e4SLinus Torvalds 
398*1da177e4SLinus Torvalds void
399*1da177e4SLinus Torvalds snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
400*1da177e4SLinus Torvalds 
401*1da177e4SLinus Torvalds {
402*1da177e4SLinus Torvalds 	unsigned long flags;
403*1da177e4SLinus Torvalds 	snd_wavefront_midi_t *midi;
404*1da177e4SLinus Torvalds 	static snd_rawmidi_substream_t *substream = NULL;
405*1da177e4SLinus Torvalds 	static int mpu = external_mpu;
406*1da177e4SLinus Torvalds 	int max = 128;
407*1da177e4SLinus Torvalds 	unsigned char byte;
408*1da177e4SLinus Torvalds 
409*1da177e4SLinus Torvalds 	midi = &card->wavefront.midi;
410*1da177e4SLinus Torvalds 
411*1da177e4SLinus Torvalds 	if (!input_avail (midi)) { /* not for us */
412*1da177e4SLinus Torvalds 		snd_wavefront_midi_output_write(card);
413*1da177e4SLinus Torvalds 		return;
414*1da177e4SLinus Torvalds 	}
415*1da177e4SLinus Torvalds 
416*1da177e4SLinus Torvalds 	spin_lock_irqsave (&midi->virtual, flags);
417*1da177e4SLinus Torvalds 	while (--max) {
418*1da177e4SLinus Torvalds 
419*1da177e4SLinus Torvalds 		if (input_avail (midi)) {
420*1da177e4SLinus Torvalds 			byte = read_data (midi);
421*1da177e4SLinus Torvalds 
422*1da177e4SLinus Torvalds 			if (midi->isvirtual) {
423*1da177e4SLinus Torvalds 				if (byte == WF_EXTERNAL_SWITCH) {
424*1da177e4SLinus Torvalds 					substream = midi->substream_input[external_mpu];
425*1da177e4SLinus Torvalds 					mpu = external_mpu;
426*1da177e4SLinus Torvalds 				} else if (byte == WF_INTERNAL_SWITCH) {
427*1da177e4SLinus Torvalds 					substream = midi->substream_output[internal_mpu];
428*1da177e4SLinus Torvalds 					mpu = internal_mpu;
429*1da177e4SLinus Torvalds 				} /* else just leave it as it is */
430*1da177e4SLinus Torvalds 			} else {
431*1da177e4SLinus Torvalds 				substream = midi->substream_input[internal_mpu];
432*1da177e4SLinus Torvalds 				mpu = internal_mpu;
433*1da177e4SLinus Torvalds 			}
434*1da177e4SLinus Torvalds 
435*1da177e4SLinus Torvalds 			if (substream == NULL) {
436*1da177e4SLinus Torvalds 				continue;
437*1da177e4SLinus Torvalds 			}
438*1da177e4SLinus Torvalds 
439*1da177e4SLinus Torvalds 			if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
440*1da177e4SLinus Torvalds 				snd_rawmidi_receive(substream, &byte, 1);
441*1da177e4SLinus Torvalds 			}
442*1da177e4SLinus Torvalds 		} else {
443*1da177e4SLinus Torvalds 			break;
444*1da177e4SLinus Torvalds 		}
445*1da177e4SLinus Torvalds 	}
446*1da177e4SLinus Torvalds 	spin_unlock_irqrestore (&midi->virtual, flags);
447*1da177e4SLinus Torvalds 
448*1da177e4SLinus Torvalds 	snd_wavefront_midi_output_write(card);
449*1da177e4SLinus Torvalds }
450*1da177e4SLinus Torvalds 
451*1da177e4SLinus Torvalds void
452*1da177e4SLinus Torvalds snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card)
453*1da177e4SLinus Torvalds 
454*1da177e4SLinus Torvalds {
455*1da177e4SLinus Torvalds 	unsigned long flags;
456*1da177e4SLinus Torvalds 
457*1da177e4SLinus Torvalds 	spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
458*1da177e4SLinus Torvalds 	card->wavefront.midi.isvirtual = 1;
459*1da177e4SLinus Torvalds 	card->wavefront.midi.output_mpu = internal_mpu;
460*1da177e4SLinus Torvalds 	card->wavefront.midi.input_mpu = internal_mpu;
461*1da177e4SLinus Torvalds 	spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
462*1da177e4SLinus Torvalds }
463*1da177e4SLinus Torvalds 
464*1da177e4SLinus Torvalds void
465*1da177e4SLinus Torvalds snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
466*1da177e4SLinus Torvalds 
467*1da177e4SLinus Torvalds {
468*1da177e4SLinus Torvalds 	unsigned long flags;
469*1da177e4SLinus Torvalds 
470*1da177e4SLinus Torvalds 	spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
471*1da177e4SLinus Torvalds 	// snd_wavefront_midi_input_close (card->ics2115_external_rmidi);
472*1da177e4SLinus Torvalds 	// snd_wavefront_midi_output_close (card->ics2115_external_rmidi);
473*1da177e4SLinus Torvalds 	card->wavefront.midi.isvirtual = 0;
474*1da177e4SLinus Torvalds 	spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
475*1da177e4SLinus Torvalds }
476*1da177e4SLinus Torvalds 
477*1da177e4SLinus Torvalds int __init
478*1da177e4SLinus Torvalds snd_wavefront_midi_start (snd_wavefront_card_t *card)
479*1da177e4SLinus Torvalds 
480*1da177e4SLinus Torvalds {
481*1da177e4SLinus Torvalds 	int ok, i;
482*1da177e4SLinus Torvalds 	unsigned char rbuf[4], wbuf[4];
483*1da177e4SLinus Torvalds 	snd_wavefront_t *dev;
484*1da177e4SLinus Torvalds 	snd_wavefront_midi_t *midi;
485*1da177e4SLinus Torvalds 
486*1da177e4SLinus Torvalds 	dev = &card->wavefront;
487*1da177e4SLinus Torvalds 	midi = &dev->midi;
488*1da177e4SLinus Torvalds 
489*1da177e4SLinus Torvalds 	/* The ICS2115 MPU-401 interface doesn't do anything
490*1da177e4SLinus Torvalds 	   until its set into UART mode.
491*1da177e4SLinus Torvalds 	*/
492*1da177e4SLinus Torvalds 
493*1da177e4SLinus Torvalds 	/* XXX fix me - no hard timing loops allowed! */
494*1da177e4SLinus Torvalds 
495*1da177e4SLinus Torvalds 	for (i = 0; i < 30000 && !output_ready (midi); i++);
496*1da177e4SLinus Torvalds 
497*1da177e4SLinus Torvalds 	if (!output_ready (midi)) {
498*1da177e4SLinus Torvalds 		snd_printk ("MIDI interface not ready for command\n");
499*1da177e4SLinus Torvalds 		return -1;
500*1da177e4SLinus Torvalds 	}
501*1da177e4SLinus Torvalds 
502*1da177e4SLinus Torvalds 	/* Any interrupts received from now on
503*1da177e4SLinus Torvalds 	   are owned by the MIDI side of things.
504*1da177e4SLinus Torvalds 	*/
505*1da177e4SLinus Torvalds 
506*1da177e4SLinus Torvalds 	dev->interrupts_are_midi = 1;
507*1da177e4SLinus Torvalds 
508*1da177e4SLinus Torvalds 	outb (UART_MODE_ON, midi->mpu_command_port);
509*1da177e4SLinus Torvalds 
510*1da177e4SLinus Torvalds 	for (ok = 0, i = 50000; i > 0 && !ok; i--) {
511*1da177e4SLinus Torvalds 		if (input_avail (midi)) {
512*1da177e4SLinus Torvalds 			if (read_data (midi) == MPU_ACK) {
513*1da177e4SLinus Torvalds 				ok = 1;
514*1da177e4SLinus Torvalds 				break;
515*1da177e4SLinus Torvalds 			}
516*1da177e4SLinus Torvalds 		}
517*1da177e4SLinus Torvalds 	}
518*1da177e4SLinus Torvalds 
519*1da177e4SLinus Torvalds 	if (!ok) {
520*1da177e4SLinus Torvalds 		snd_printk ("cannot set UART mode for MIDI interface");
521*1da177e4SLinus Torvalds 		dev->interrupts_are_midi = 0;
522*1da177e4SLinus Torvalds 		return -1;
523*1da177e4SLinus Torvalds 	}
524*1da177e4SLinus Torvalds 
525*1da177e4SLinus Torvalds 	/* Route external MIDI to WaveFront synth (by default) */
526*1da177e4SLinus Torvalds 
527*1da177e4SLinus Torvalds 	if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
528*1da177e4SLinus Torvalds 		snd_printk ("can't enable MIDI-IN-2-synth routing.\n");
529*1da177e4SLinus Torvalds 		/* XXX error ? */
530*1da177e4SLinus Torvalds 	}
531*1da177e4SLinus Torvalds 
532*1da177e4SLinus Torvalds 	/* Turn on Virtual MIDI, but first *always* turn it off,
533*1da177e4SLinus Torvalds 	   since otherwise consectutive reloads of the driver will
534*1da177e4SLinus Torvalds 	   never cause the hardware to generate the initial "internal" or
535*1da177e4SLinus Torvalds 	   "external" source bytes in the MIDI data stream. This
536*1da177e4SLinus Torvalds 	   is pretty important, since the internal hardware generally will
537*1da177e4SLinus Torvalds 	   be used to generate none or very little MIDI output, and
538*1da177e4SLinus Torvalds 	   thus the only source of MIDI data is actually external. Without
539*1da177e4SLinus Torvalds 	   the switch bytes, the driver will think it all comes from
540*1da177e4SLinus Torvalds 	   the internal interface. Duh.
541*1da177e4SLinus Torvalds 	*/
542*1da177e4SLinus Torvalds 
543*1da177e4SLinus Torvalds 	if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) {
544*1da177e4SLinus Torvalds 		snd_printk ("virtual MIDI mode not disabled\n");
545*1da177e4SLinus Torvalds 		return 0; /* We're OK, but missing the external MIDI dev */
546*1da177e4SLinus Torvalds 	}
547*1da177e4SLinus Torvalds 
548*1da177e4SLinus Torvalds 	snd_wavefront_midi_enable_virtual (card);
549*1da177e4SLinus Torvalds 
550*1da177e4SLinus Torvalds 	if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
551*1da177e4SLinus Torvalds 		snd_printk ("cannot enable virtual MIDI mode.\n");
552*1da177e4SLinus Torvalds 		snd_wavefront_midi_disable_virtual (card);
553*1da177e4SLinus Torvalds 	}
554*1da177e4SLinus Torvalds 	return 0;
555*1da177e4SLinus Torvalds }
556*1da177e4SLinus Torvalds 
557*1da177e4SLinus Torvalds snd_rawmidi_ops_t snd_wavefront_midi_output =
558*1da177e4SLinus Torvalds {
559*1da177e4SLinus Torvalds 	.open =		snd_wavefront_midi_output_open,
560*1da177e4SLinus Torvalds 	.close =	snd_wavefront_midi_output_close,
561*1da177e4SLinus Torvalds 	.trigger =	snd_wavefront_midi_output_trigger,
562*1da177e4SLinus Torvalds };
563*1da177e4SLinus Torvalds 
564*1da177e4SLinus Torvalds snd_rawmidi_ops_t snd_wavefront_midi_input =
565*1da177e4SLinus Torvalds {
566*1da177e4SLinus Torvalds 	.open =		snd_wavefront_midi_input_open,
567*1da177e4SLinus Torvalds 	.close =	snd_wavefront_midi_input_close,
568*1da177e4SLinus Torvalds 	.trigger =	snd_wavefront_midi_input_trigger,
569*1da177e4SLinus Torvalds };
570*1da177e4SLinus Torvalds 
571