xref: /OK3568_Linux_fs/kernel/sound/pci/echoaudio/midi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /****************************************************************************
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun    Copyright Echo Digital Audio Corporation (c) 1998 - 2004
4*4882a593Smuzhiyun    All rights reserved
5*4882a593Smuzhiyun    www.echoaudio.com
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun    This file is part of Echo Digital Audio's generic driver library.
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun    Echo Digital Audio's generic driver library is free software;
10*4882a593Smuzhiyun    you can redistribute it and/or modify it under the terms of
11*4882a593Smuzhiyun    the GNU General Public License as published by the Free Software
12*4882a593Smuzhiyun    Foundation.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun    This program is distributed in the hope that it will be useful,
15*4882a593Smuzhiyun    but WITHOUT ANY WARRANTY; without even the implied warranty of
16*4882a593Smuzhiyun    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*4882a593Smuzhiyun    GNU General Public License for more details.
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun    You should have received a copy of the GNU General Public License
20*4882a593Smuzhiyun    along with this program; if not, write to the Free Software
21*4882a593Smuzhiyun    Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22*4882a593Smuzhiyun    MA  02111-1307, USA.
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun    *************************************************************************
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun  Translation from C++ and adaptation for use in ALSA-Driver
27*4882a593Smuzhiyun  were made by Giuliano Pochini <pochini@shiny.it>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun ****************************************************************************/
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun /******************************************************************************
33*4882a593Smuzhiyun 	MIDI lowlevel code
34*4882a593Smuzhiyun ******************************************************************************/
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun /* Start and stop Midi input */
enable_midi_input(struct echoaudio * chip,char enable)37*4882a593Smuzhiyun static int enable_midi_input(struct echoaudio *chip, char enable)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	dev_dbg(chip->card->dev, "enable_midi_input(%d)\n", enable);
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	if (wait_handshake(chip))
42*4882a593Smuzhiyun 		return -EIO;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	if (enable) {
45*4882a593Smuzhiyun 		chip->mtc_state = MIDI_IN_STATE_NORMAL;
46*4882a593Smuzhiyun 		chip->comm_page->flags |=
47*4882a593Smuzhiyun 			cpu_to_le32(DSP_FLAG_MIDI_INPUT);
48*4882a593Smuzhiyun 	} else
49*4882a593Smuzhiyun 		chip->comm_page->flags &=
50*4882a593Smuzhiyun 			~cpu_to_le32(DSP_FLAG_MIDI_INPUT);
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	clear_handshake(chip);
53*4882a593Smuzhiyun 	return send_vector(chip, DSP_VC_UPDATE_FLAGS);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun /* Send a buffer full of MIDI data to the DSP
59*4882a593Smuzhiyun Returns how many actually written or < 0 on error */
write_midi(struct echoaudio * chip,u8 * data,int bytes)60*4882a593Smuzhiyun static int write_midi(struct echoaudio *chip, u8 *data, int bytes)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	if (snd_BUG_ON(bytes <= 0 || bytes >= MIDI_OUT_BUFFER_SIZE))
63*4882a593Smuzhiyun 		return -EINVAL;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	if (wait_handshake(chip))
66*4882a593Smuzhiyun 		return -EIO;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	/* HF4 indicates that it is safe to write MIDI output data */
69*4882a593Smuzhiyun 	if (! (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4))
70*4882a593Smuzhiyun 		return 0;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	chip->comm_page->midi_output[0] = bytes;
73*4882a593Smuzhiyun 	memcpy(&chip->comm_page->midi_output[1], data, bytes);
74*4882a593Smuzhiyun 	chip->comm_page->midi_out_free_count = 0;
75*4882a593Smuzhiyun 	clear_handshake(chip);
76*4882a593Smuzhiyun 	send_vector(chip, DSP_VC_MIDI_WRITE);
77*4882a593Smuzhiyun 	dev_dbg(chip->card->dev, "write_midi: %d\n", bytes);
78*4882a593Smuzhiyun 	return bytes;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun /* Run the state machine for MIDI input data
84*4882a593Smuzhiyun MIDI time code sync isn't supported by this code right now, but you still need
85*4882a593Smuzhiyun this state machine to parse the incoming MIDI data stream.  Every time the DSP
86*4882a593Smuzhiyun sees a 0xF1 byte come in, it adds the DSP sample position to the MIDI data
87*4882a593Smuzhiyun stream. The DSP sample position is represented as a 32 bit unsigned value,
88*4882a593Smuzhiyun with the high 16 bits first, followed by the low 16 bits. Since these aren't
89*4882a593Smuzhiyun real MIDI bytes, the following logic is needed to skip them. */
mtc_process_data(struct echoaudio * chip,short midi_byte)90*4882a593Smuzhiyun static inline int mtc_process_data(struct echoaudio *chip, short midi_byte)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	switch (chip->mtc_state) {
93*4882a593Smuzhiyun 	case MIDI_IN_STATE_NORMAL:
94*4882a593Smuzhiyun 		if (midi_byte == 0xF1)
95*4882a593Smuzhiyun 			chip->mtc_state = MIDI_IN_STATE_TS_HIGH;
96*4882a593Smuzhiyun 		break;
97*4882a593Smuzhiyun 	case MIDI_IN_STATE_TS_HIGH:
98*4882a593Smuzhiyun 		chip->mtc_state = MIDI_IN_STATE_TS_LOW;
99*4882a593Smuzhiyun 		return MIDI_IN_SKIP_DATA;
100*4882a593Smuzhiyun 		break;
101*4882a593Smuzhiyun 	case MIDI_IN_STATE_TS_LOW:
102*4882a593Smuzhiyun 		chip->mtc_state = MIDI_IN_STATE_F1_DATA;
103*4882a593Smuzhiyun 		return MIDI_IN_SKIP_DATA;
104*4882a593Smuzhiyun 		break;
105*4882a593Smuzhiyun 	case MIDI_IN_STATE_F1_DATA:
106*4882a593Smuzhiyun 		chip->mtc_state = MIDI_IN_STATE_NORMAL;
107*4882a593Smuzhiyun 		break;
108*4882a593Smuzhiyun 	}
109*4882a593Smuzhiyun 	return 0;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun /* This function is called from the IRQ handler and it reads the midi data
115*4882a593Smuzhiyun from the DSP's buffer.  It returns the number of bytes received. */
midi_service_irq(struct echoaudio * chip)116*4882a593Smuzhiyun static int midi_service_irq(struct echoaudio *chip)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	short int count, midi_byte, i, received;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	/* The count is at index 0, followed by actual data */
121*4882a593Smuzhiyun 	count = le16_to_cpu(chip->comm_page->midi_input[0]);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	if (snd_BUG_ON(count >= MIDI_IN_BUFFER_SIZE))
124*4882a593Smuzhiyun 		return 0;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	/* Get the MIDI data from the comm page */
127*4882a593Smuzhiyun 	i = 1;
128*4882a593Smuzhiyun 	received = 0;
129*4882a593Smuzhiyun 	for (i = 1; i <= count; i++) {
130*4882a593Smuzhiyun 		/* Get the MIDI byte */
131*4882a593Smuzhiyun 		midi_byte = le16_to_cpu(chip->comm_page->midi_input[i]);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 		/* Parse the incoming MIDI stream. The incoming MIDI data
134*4882a593Smuzhiyun 		consists of MIDI bytes and timestamps for the MIDI time code
135*4882a593Smuzhiyun 		0xF1 bytes. mtc_process_data() is a little state machine that
136*4882a593Smuzhiyun 		parses the stream. If you get MIDI_IN_SKIP_DATA back, then
137*4882a593Smuzhiyun 		this is a timestamp byte, not a MIDI byte, so don't store it
138*4882a593Smuzhiyun 		in the MIDI input buffer. */
139*4882a593Smuzhiyun 		if (mtc_process_data(chip, midi_byte) == MIDI_IN_SKIP_DATA)
140*4882a593Smuzhiyun 			continue;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 		chip->midi_buffer[received++] = (u8)midi_byte;
143*4882a593Smuzhiyun 	}
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	return received;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun /******************************************************************************
152*4882a593Smuzhiyun 	MIDI interface
153*4882a593Smuzhiyun ******************************************************************************/
154*4882a593Smuzhiyun 
snd_echo_midi_input_open(struct snd_rawmidi_substream * substream)155*4882a593Smuzhiyun static int snd_echo_midi_input_open(struct snd_rawmidi_substream *substream)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	struct echoaudio *chip = substream->rmidi->private_data;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	chip->midi_in = substream;
160*4882a593Smuzhiyun 	return 0;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 
snd_echo_midi_input_trigger(struct snd_rawmidi_substream * substream,int up)165*4882a593Smuzhiyun static void snd_echo_midi_input_trigger(struct snd_rawmidi_substream *substream,
166*4882a593Smuzhiyun 					int up)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	struct echoaudio *chip = substream->rmidi->private_data;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	if (up != chip->midi_input_enabled) {
171*4882a593Smuzhiyun 		spin_lock_irq(&chip->lock);
172*4882a593Smuzhiyun 		enable_midi_input(chip, up);
173*4882a593Smuzhiyun 		spin_unlock_irq(&chip->lock);
174*4882a593Smuzhiyun 		chip->midi_input_enabled = up;
175*4882a593Smuzhiyun 	}
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 
snd_echo_midi_input_close(struct snd_rawmidi_substream * substream)180*4882a593Smuzhiyun static int snd_echo_midi_input_close(struct snd_rawmidi_substream *substream)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	struct echoaudio *chip = substream->rmidi->private_data;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	chip->midi_in = NULL;
185*4882a593Smuzhiyun 	return 0;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 
snd_echo_midi_output_open(struct snd_rawmidi_substream * substream)190*4882a593Smuzhiyun static int snd_echo_midi_output_open(struct snd_rawmidi_substream *substream)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun 	struct echoaudio *chip = substream->rmidi->private_data;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	chip->tinuse = 0;
195*4882a593Smuzhiyun 	chip->midi_full = 0;
196*4882a593Smuzhiyun 	chip->midi_out = substream;
197*4882a593Smuzhiyun 	return 0;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 
snd_echo_midi_output_write(struct timer_list * t)202*4882a593Smuzhiyun static void snd_echo_midi_output_write(struct timer_list *t)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun 	struct echoaudio *chip = from_timer(chip, t, timer);
205*4882a593Smuzhiyun 	unsigned long flags;
206*4882a593Smuzhiyun 	int bytes, sent, time;
207*4882a593Smuzhiyun 	unsigned char buf[MIDI_OUT_BUFFER_SIZE - 1];
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	/* No interrupts are involved: we have to check at regular intervals
210*4882a593Smuzhiyun 	if the card's output buffer has room for new data. */
211*4882a593Smuzhiyun 	sent = bytes = 0;
212*4882a593Smuzhiyun 	spin_lock_irqsave(&chip->lock, flags);
213*4882a593Smuzhiyun 	chip->midi_full = 0;
214*4882a593Smuzhiyun 	if (!snd_rawmidi_transmit_empty(chip->midi_out)) {
215*4882a593Smuzhiyun 		bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf,
216*4882a593Smuzhiyun 						  MIDI_OUT_BUFFER_SIZE - 1);
217*4882a593Smuzhiyun 		dev_dbg(chip->card->dev, "Try to send %d bytes...\n", bytes);
218*4882a593Smuzhiyun 		sent = write_midi(chip, buf, bytes);
219*4882a593Smuzhiyun 		if (sent < 0) {
220*4882a593Smuzhiyun 			dev_err(chip->card->dev,
221*4882a593Smuzhiyun 				"write_midi() error %d\n", sent);
222*4882a593Smuzhiyun 			/* retry later */
223*4882a593Smuzhiyun 			sent = 9000;
224*4882a593Smuzhiyun 			chip->midi_full = 1;
225*4882a593Smuzhiyun 		} else if (sent > 0) {
226*4882a593Smuzhiyun 			dev_dbg(chip->card->dev, "%d bytes sent\n", sent);
227*4882a593Smuzhiyun 			snd_rawmidi_transmit_ack(chip->midi_out, sent);
228*4882a593Smuzhiyun 		} else {
229*4882a593Smuzhiyun 			/* Buffer is full. DSP's internal buffer is 64 (128 ?)
230*4882a593Smuzhiyun 			bytes long. Let's wait until half of them are sent */
231*4882a593Smuzhiyun 			dev_dbg(chip->card->dev, "Full\n");
232*4882a593Smuzhiyun 			sent = 32;
233*4882a593Smuzhiyun 			chip->midi_full = 1;
234*4882a593Smuzhiyun 		}
235*4882a593Smuzhiyun 	}
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	/* We restart the timer only if there is some data left to send */
238*4882a593Smuzhiyun 	if (!snd_rawmidi_transmit_empty(chip->midi_out) && chip->tinuse) {
239*4882a593Smuzhiyun 		/* The timer will expire slightly after the data has been
240*4882a593Smuzhiyun 		   sent */
241*4882a593Smuzhiyun 		time = (sent << 3) / 25 + 1;	/* 8/25=0.32ms to send a byte */
242*4882a593Smuzhiyun 		mod_timer(&chip->timer, jiffies + (time * HZ + 999) / 1000);
243*4882a593Smuzhiyun 		dev_dbg(chip->card->dev,
244*4882a593Smuzhiyun 			"Timer armed(%d)\n", ((time * HZ + 999) / 1000));
245*4882a593Smuzhiyun 	}
246*4882a593Smuzhiyun 	spin_unlock_irqrestore(&chip->lock, flags);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 
snd_echo_midi_output_trigger(struct snd_rawmidi_substream * substream,int up)251*4882a593Smuzhiyun static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream,
252*4882a593Smuzhiyun 					 int up)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun 	struct echoaudio *chip = substream->rmidi->private_data;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	dev_dbg(chip->card->dev, "snd_echo_midi_output_trigger(%d)\n", up);
257*4882a593Smuzhiyun 	spin_lock_irq(&chip->lock);
258*4882a593Smuzhiyun 	if (up) {
259*4882a593Smuzhiyun 		if (!chip->tinuse) {
260*4882a593Smuzhiyun 			timer_setup(&chip->timer, snd_echo_midi_output_write,
261*4882a593Smuzhiyun 				    0);
262*4882a593Smuzhiyun 			chip->tinuse = 1;
263*4882a593Smuzhiyun 		}
264*4882a593Smuzhiyun 	} else {
265*4882a593Smuzhiyun 		if (chip->tinuse) {
266*4882a593Smuzhiyun 			chip->tinuse = 0;
267*4882a593Smuzhiyun 			spin_unlock_irq(&chip->lock);
268*4882a593Smuzhiyun 			del_timer_sync(&chip->timer);
269*4882a593Smuzhiyun 			dev_dbg(chip->card->dev, "Timer removed\n");
270*4882a593Smuzhiyun 			return;
271*4882a593Smuzhiyun 		}
272*4882a593Smuzhiyun 	}
273*4882a593Smuzhiyun 	spin_unlock_irq(&chip->lock);
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	if (up && !chip->midi_full)
276*4882a593Smuzhiyun 		snd_echo_midi_output_write(&chip->timer);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 
snd_echo_midi_output_close(struct snd_rawmidi_substream * substream)281*4882a593Smuzhiyun static int snd_echo_midi_output_close(struct snd_rawmidi_substream *substream)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun 	struct echoaudio *chip = substream->rmidi->private_data;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	chip->midi_out = NULL;
286*4882a593Smuzhiyun 	return 0;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun static const struct snd_rawmidi_ops snd_echo_midi_input = {
292*4882a593Smuzhiyun 	.open = snd_echo_midi_input_open,
293*4882a593Smuzhiyun 	.close = snd_echo_midi_input_close,
294*4882a593Smuzhiyun 	.trigger = snd_echo_midi_input_trigger,
295*4882a593Smuzhiyun };
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun static const struct snd_rawmidi_ops snd_echo_midi_output = {
298*4882a593Smuzhiyun 	.open = snd_echo_midi_output_open,
299*4882a593Smuzhiyun 	.close = snd_echo_midi_output_close,
300*4882a593Smuzhiyun 	.trigger = snd_echo_midi_output_trigger,
301*4882a593Smuzhiyun };
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun /* <--snd_echo_probe() */
snd_echo_midi_create(struct snd_card * card,struct echoaudio * chip)306*4882a593Smuzhiyun static int snd_echo_midi_create(struct snd_card *card,
307*4882a593Smuzhiyun 				struct echoaudio *chip)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	int err;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	if ((err = snd_rawmidi_new(card, card->shortname, 0, 1, 1,
312*4882a593Smuzhiyun 				   &chip->rmidi)) < 0)
313*4882a593Smuzhiyun 		return err;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	strcpy(chip->rmidi->name, card->shortname);
316*4882a593Smuzhiyun 	chip->rmidi->private_data = chip;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
319*4882a593Smuzhiyun 			    &snd_echo_midi_input);
320*4882a593Smuzhiyun 	snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
321*4882a593Smuzhiyun 			    &snd_echo_midi_output);
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	chip->rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
324*4882a593Smuzhiyun 		SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
325*4882a593Smuzhiyun 	return 0;
326*4882a593Smuzhiyun }
327