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