OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [pci/] [ca0106/] [ca_midi.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 *  Copyright 10/16/2005 Tilman Kranz <tilde@tk-sls.de>
3
 *  Creative Audio MIDI, for the CA0106 Driver
4
 *  Version: 0.0.1
5
 *
6
 *  Changelog:
7
 *    Implementation is based on mpu401 and emu10k1x and
8
 *    tested with ca0106.
9
 *    mpu401: Copyright (c) by Jaroslav Kysela <perex@perex.cz>
10
 *    emu10k1x: Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
11
 *
12
 *   This program is free software; you can redistribute it and/or modify
13
 *   it under the terms of the GNU General Public License as published by
14
 *   the Free Software Foundation; either version 2 of the License, or
15
 *   (at your option) any later version.
16
 *
17
 *   This program is distributed in the hope that it will be useful,
18
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 *   GNU General Public License for more details.
21
 *
22
 *   You should have received a copy of the GNU General Public License
23
 *   along with this program; if not, write to the Free Software
24
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
25
 *
26
 *
27
 */
28
 
29
#include <linux/spinlock.h>
30
#include <sound/driver.h>
31
#include <sound/core.h>
32
#include <sound/rawmidi.h>
33
 
34
#include "ca_midi.h"
35
 
36
#define ca_midi_write_data(midi, data)  midi->write(midi, data, 0)
37
#define ca_midi_write_cmd(midi, data)   midi->write(midi, data, 1)
38
#define ca_midi_read_data(midi)         midi->read(midi, 0)
39
#define ca_midi_read_stat(midi)         midi->read(midi, 1)
40
#define ca_midi_input_avail(midi)       (!(ca_midi_read_stat(midi) & midi->input_avail))
41
#define ca_midi_output_ready(midi)      (!(ca_midi_read_stat(midi) & midi->output_ready))
42
 
43
static void ca_midi_clear_rx(struct snd_ca_midi *midi)
44
{
45
        int timeout = 100000;
46
        for (; timeout > 0 && ca_midi_input_avail(midi); timeout--)
47
                ca_midi_read_data(midi);
48
#ifdef CONFIG_SND_DEBUG
49
        if (timeout <= 0)
50
                snd_printk(KERN_ERR "ca_midi_clear_rx: timeout (status = 0x%x)\n",
51
                           ca_midi_read_stat(midi));
52
#endif
53
}
54
 
55
static void ca_midi_interrupt(struct snd_ca_midi *midi, unsigned int status)
56
{
57
        unsigned char byte;
58
 
59
        if (midi->rmidi == NULL) {
60
                midi->interrupt_disable(midi,midi->tx_enable | midi->rx_enable);
61
                return;
62
        }
63
 
64
        spin_lock(&midi->input_lock);
65
        if ((status & midi->ipr_rx) && ca_midi_input_avail(midi)) {
66
                if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) {
67
                        ca_midi_clear_rx(midi);
68
                } else {
69
                        byte = ca_midi_read_data(midi);
70
                        if(midi->substream_input)
71
                                snd_rawmidi_receive(midi->substream_input, &byte, 1);
72
 
73
 
74
                }
75
        }
76
        spin_unlock(&midi->input_lock);
77
 
78
        spin_lock(&midi->output_lock);
79
        if ((status & midi->ipr_tx) && ca_midi_output_ready(midi)) {
80
                if (midi->substream_output &&
81
                    snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
82
                        ca_midi_write_data(midi, byte);
83
                } else {
84
                        midi->interrupt_disable(midi,midi->tx_enable);
85
                }
86
        }
87
        spin_unlock(&midi->output_lock);
88
 
89
}
90
 
91
static void ca_midi_cmd(struct snd_ca_midi *midi, unsigned char cmd, int ack)
92
{
93
        unsigned long flags;
94
        int timeout, ok;
95
 
96
        spin_lock_irqsave(&midi->input_lock, flags);
97
        ca_midi_write_data(midi, 0x00);
98
        /* ca_midi_clear_rx(midi); */
99
 
100
        ca_midi_write_cmd(midi, cmd);
101
        if (ack) {
102
                ok = 0;
103
                timeout = 10000;
104
                while (!ok && timeout-- > 0) {
105
                        if (ca_midi_input_avail(midi)) {
106
                                if (ca_midi_read_data(midi) == midi->ack)
107
                                        ok = 1;
108
                        }
109
                }
110
                if (!ok && ca_midi_read_data(midi) == midi->ack)
111
                        ok = 1;
112
        } else {
113
                ok = 1;
114
        }
115
        spin_unlock_irqrestore(&midi->input_lock, flags);
116
        if (!ok)
117
                snd_printk(KERN_ERR "ca_midi_cmd: 0x%x failed at 0x%x (status = 0x%x, data = 0x%x)!!!\n",
118
                           cmd,
119
                           midi->get_dev_id_port(midi->dev_id),
120
                           ca_midi_read_stat(midi),
121
                           ca_midi_read_data(midi));
122
}
123
 
124
static int ca_midi_input_open(struct snd_rawmidi_substream *substream)
125
{
126
        struct snd_ca_midi *midi = substream->rmidi->private_data;
127
        unsigned long flags;
128
 
129
        snd_assert(midi->dev_id, return -ENXIO);
130
        spin_lock_irqsave(&midi->open_lock, flags);
131
        midi->midi_mode |= CA_MIDI_MODE_INPUT;
132
        midi->substream_input = substream;
133
        if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) {
134
                spin_unlock_irqrestore(&midi->open_lock, flags);
135
                ca_midi_cmd(midi, midi->reset, 1);
136
                ca_midi_cmd(midi, midi->enter_uart, 1);
137
        } else {
138
                spin_unlock_irqrestore(&midi->open_lock, flags);
139
        }
140
        return 0;
141
}
142
 
143
static int ca_midi_output_open(struct snd_rawmidi_substream *substream)
144
{
145
        struct snd_ca_midi *midi = substream->rmidi->private_data;
146
        unsigned long flags;
147
 
148
        snd_assert(midi->dev_id, return -ENXIO);
149
        spin_lock_irqsave(&midi->open_lock, flags);
150
        midi->midi_mode |= CA_MIDI_MODE_OUTPUT;
151
        midi->substream_output = substream;
152
        if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) {
153
                spin_unlock_irqrestore(&midi->open_lock, flags);
154
                ca_midi_cmd(midi, midi->reset, 1);
155
                ca_midi_cmd(midi, midi->enter_uart, 1);
156
        } else {
157
                spin_unlock_irqrestore(&midi->open_lock, flags);
158
        }
159
        return 0;
160
}
161
 
162
static int ca_midi_input_close(struct snd_rawmidi_substream *substream)
163
{
164
        struct snd_ca_midi *midi = substream->rmidi->private_data;
165
        unsigned long flags;
166
 
167
        snd_assert(midi->dev_id, return -ENXIO);
168
        spin_lock_irqsave(&midi->open_lock, flags);
169
        midi->interrupt_disable(midi,midi->rx_enable);
170
        midi->midi_mode &= ~CA_MIDI_MODE_INPUT;
171
        midi->substream_input = NULL;
172
        if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) {
173
                spin_unlock_irqrestore(&midi->open_lock, flags);
174
                ca_midi_cmd(midi, midi->reset, 0);
175
        } else {
176
                spin_unlock_irqrestore(&midi->open_lock, flags);
177
        }
178
        return 0;
179
}
180
 
181
static int ca_midi_output_close(struct snd_rawmidi_substream *substream)
182
{
183
        struct snd_ca_midi *midi = substream->rmidi->private_data;
184
        unsigned long flags;
185
        snd_assert(midi->dev_id, return -ENXIO);
186
 
187
        spin_lock_irqsave(&midi->open_lock, flags);
188
 
189
        midi->interrupt_disable(midi,midi->tx_enable);
190
        midi->midi_mode &= ~CA_MIDI_MODE_OUTPUT;
191
        midi->substream_output = NULL;
192
 
193
        if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) {
194
                spin_unlock_irqrestore(&midi->open_lock, flags);
195
                ca_midi_cmd(midi, midi->reset, 0);
196
        } else {
197
                spin_unlock_irqrestore(&midi->open_lock, flags);
198
        }
199
        return 0;
200
}
201
 
202
static void ca_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
203
{
204
        struct snd_ca_midi *midi = substream->rmidi->private_data;
205
        snd_assert(midi->dev_id, return);
206
 
207
        if (up) {
208
                midi->interrupt_enable(midi,midi->rx_enable);
209
        } else {
210
                midi->interrupt_disable(midi, midi->rx_enable);
211
        }
212
}
213
 
214
static void ca_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
215
{
216
        struct snd_ca_midi *midi = substream->rmidi->private_data;
217
        unsigned long flags;
218
 
219
        snd_assert(midi->dev_id, return);
220
 
221
        if (up) {
222
                int max = 4;
223
                unsigned char byte;
224
 
225
                spin_lock_irqsave(&midi->output_lock, flags);
226
 
227
                /* try to send some amount of bytes here before interrupts */
228
                while (max > 0) {
229
                        if (ca_midi_output_ready(midi)) {
230
                                if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT) ||
231
                                    snd_rawmidi_transmit(substream, &byte, 1) != 1) {
232
                                        /* no more data */
233
                                        spin_unlock_irqrestore(&midi->output_lock, flags);
234
                                        return;
235
                                }
236
                                ca_midi_write_data(midi, byte);
237
                                max--;
238
                        } else {
239
                                break;
240
                        }
241
                }
242
 
243
                spin_unlock_irqrestore(&midi->output_lock, flags);
244
                midi->interrupt_enable(midi,midi->tx_enable);
245
 
246
        } else {
247
                midi->interrupt_disable(midi,midi->tx_enable);
248
        }
249
}
250
 
251
static struct snd_rawmidi_ops ca_midi_output =
252
{
253
        .open =         ca_midi_output_open,
254
        .close =        ca_midi_output_close,
255
        .trigger =      ca_midi_output_trigger,
256
};
257
 
258
static struct snd_rawmidi_ops ca_midi_input =
259
{
260
        .open =         ca_midi_input_open,
261
        .close =        ca_midi_input_close,
262
        .trigger =      ca_midi_input_trigger,
263
};
264
 
265
static void ca_midi_free(struct snd_ca_midi *midi)
266
{
267
        midi->interrupt = NULL;
268
        midi->interrupt_enable = NULL;
269
        midi->interrupt_disable = NULL;
270
        midi->read = NULL;
271
        midi->write = NULL;
272
        midi->get_dev_id_card = NULL;
273
        midi->get_dev_id_port = NULL;
274
        midi->rmidi = NULL;
275
}
276
 
277
static void ca_rmidi_free(struct snd_rawmidi *rmidi)
278
{
279
        ca_midi_free(rmidi->private_data);
280
}
281
 
282
int __devinit ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name)
283
{
284
        struct snd_rawmidi *rmidi;
285
        int err;
286
 
287
        if ((err = snd_rawmidi_new(midi->get_dev_id_card(midi->dev_id), name, device, 1, 1, &rmidi)) < 0)
288
                return err;
289
 
290
        midi->dev_id = dev_id;
291
        midi->interrupt = ca_midi_interrupt;
292
 
293
        spin_lock_init(&midi->open_lock);
294
        spin_lock_init(&midi->input_lock);
295
        spin_lock_init(&midi->output_lock);
296
 
297
        strcpy(rmidi->name, name);
298
        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &ca_midi_output);
299
        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &ca_midi_input);
300
        rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
301
                             SNDRV_RAWMIDI_INFO_INPUT |
302
                             SNDRV_RAWMIDI_INFO_DUPLEX;
303
        rmidi->private_data = midi;
304
        rmidi->private_free = ca_rmidi_free;
305
 
306
        midi->rmidi = rmidi;
307
        return 0;
308
}
309
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.