1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright 10/16/2005 Tilman Kranz <tilde@tk-sls.de>
4 * Creative Audio MIDI, for the CA0106 Driver
8 * Implementation is based on mpu401 and emu10k1x and
10 * mpu401: Copyright (c) by Jaroslav Kysela <perex@perex.cz>
11 * emu10k1x: Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
14 #include <linux/spinlock.h>
15 #include <sound/core.h>
16 #include <sound/rawmidi.h>
20 #define ca_midi_write_data(midi, data) midi->write(midi, data, 0)
21 #define ca_midi_write_cmd(midi, data) midi->write(midi, data, 1)
22 #define ca_midi_read_data(midi) midi->read(midi, 0)
23 #define ca_midi_read_stat(midi) midi->read(midi, 1)
24 #define ca_midi_input_avail(midi) (!(ca_midi_read_stat(midi) & midi->input_avail))
25 #define ca_midi_output_ready(midi) (!(ca_midi_read_stat(midi) & midi->output_ready))
27 static void ca_midi_clear_rx(struct snd_ca_midi
*midi
)
30 for (; timeout
> 0 && ca_midi_input_avail(midi
); timeout
--)
31 ca_midi_read_data(midi
);
32 #ifdef CONFIG_SND_DEBUG
34 pr_err("ca_midi_clear_rx: timeout (status = 0x%x)\n",
35 ca_midi_read_stat(midi
));
39 static void ca_midi_interrupt(struct snd_ca_midi
*midi
, unsigned int status
)
43 if (midi
->rmidi
== NULL
) {
44 midi
->interrupt_disable(midi
,midi
->tx_enable
| midi
->rx_enable
);
48 spin_lock(&midi
->input_lock
);
49 if ((status
& midi
->ipr_rx
) && ca_midi_input_avail(midi
)) {
50 if (!(midi
->midi_mode
& CA_MIDI_MODE_INPUT
)) {
51 ca_midi_clear_rx(midi
);
53 byte
= ca_midi_read_data(midi
);
54 if(midi
->substream_input
)
55 snd_rawmidi_receive(midi
->substream_input
, &byte
, 1);
60 spin_unlock(&midi
->input_lock
);
62 spin_lock(&midi
->output_lock
);
63 if ((status
& midi
->ipr_tx
) && ca_midi_output_ready(midi
)) {
64 if (midi
->substream_output
&&
65 snd_rawmidi_transmit(midi
->substream_output
, &byte
, 1) == 1) {
66 ca_midi_write_data(midi
, byte
);
68 midi
->interrupt_disable(midi
,midi
->tx_enable
);
71 spin_unlock(&midi
->output_lock
);
75 static void ca_midi_cmd(struct snd_ca_midi
*midi
, unsigned char cmd
, int ack
)
80 spin_lock_irqsave(&midi
->input_lock
, flags
);
81 ca_midi_write_data(midi
, 0x00);
82 /* ca_midi_clear_rx(midi); */
84 ca_midi_write_cmd(midi
, cmd
);
88 while (!ok
&& timeout
-- > 0) {
89 if (ca_midi_input_avail(midi
)) {
90 if (ca_midi_read_data(midi
) == midi
->ack
)
94 if (!ok
&& ca_midi_read_data(midi
) == midi
->ack
)
99 spin_unlock_irqrestore(&midi
->input_lock
, flags
);
101 pr_err("ca_midi_cmd: 0x%x failed at 0x%x (status = 0x%x, data = 0x%x)!!!\n",
103 midi
->get_dev_id_port(midi
->dev_id
),
104 ca_midi_read_stat(midi
),
105 ca_midi_read_data(midi
));
108 static int ca_midi_input_open(struct snd_rawmidi_substream
*substream
)
110 struct snd_ca_midi
*midi
= substream
->rmidi
->private_data
;
113 if (snd_BUG_ON(!midi
->dev_id
))
115 spin_lock_irqsave(&midi
->open_lock
, flags
);
116 midi
->midi_mode
|= CA_MIDI_MODE_INPUT
;
117 midi
->substream_input
= substream
;
118 if (!(midi
->midi_mode
& CA_MIDI_MODE_OUTPUT
)) {
119 spin_unlock_irqrestore(&midi
->open_lock
, flags
);
120 ca_midi_cmd(midi
, midi
->reset
, 1);
121 ca_midi_cmd(midi
, midi
->enter_uart
, 1);
123 spin_unlock_irqrestore(&midi
->open_lock
, flags
);
128 static int ca_midi_output_open(struct snd_rawmidi_substream
*substream
)
130 struct snd_ca_midi
*midi
= substream
->rmidi
->private_data
;
133 if (snd_BUG_ON(!midi
->dev_id
))
135 spin_lock_irqsave(&midi
->open_lock
, flags
);
136 midi
->midi_mode
|= CA_MIDI_MODE_OUTPUT
;
137 midi
->substream_output
= substream
;
138 if (!(midi
->midi_mode
& CA_MIDI_MODE_INPUT
)) {
139 spin_unlock_irqrestore(&midi
->open_lock
, flags
);
140 ca_midi_cmd(midi
, midi
->reset
, 1);
141 ca_midi_cmd(midi
, midi
->enter_uart
, 1);
143 spin_unlock_irqrestore(&midi
->open_lock
, flags
);
148 static int ca_midi_input_close(struct snd_rawmidi_substream
*substream
)
150 struct snd_ca_midi
*midi
= substream
->rmidi
->private_data
;
153 if (snd_BUG_ON(!midi
->dev_id
))
155 spin_lock_irqsave(&midi
->open_lock
, flags
);
156 midi
->interrupt_disable(midi
,midi
->rx_enable
);
157 midi
->midi_mode
&= ~CA_MIDI_MODE_INPUT
;
158 midi
->substream_input
= NULL
;
159 if (!(midi
->midi_mode
& CA_MIDI_MODE_OUTPUT
)) {
160 spin_unlock_irqrestore(&midi
->open_lock
, flags
);
161 ca_midi_cmd(midi
, midi
->reset
, 0);
163 spin_unlock_irqrestore(&midi
->open_lock
, flags
);
168 static int ca_midi_output_close(struct snd_rawmidi_substream
*substream
)
170 struct snd_ca_midi
*midi
= substream
->rmidi
->private_data
;
173 if (snd_BUG_ON(!midi
->dev_id
))
176 spin_lock_irqsave(&midi
->open_lock
, flags
);
178 midi
->interrupt_disable(midi
,midi
->tx_enable
);
179 midi
->midi_mode
&= ~CA_MIDI_MODE_OUTPUT
;
180 midi
->substream_output
= NULL
;
182 if (!(midi
->midi_mode
& CA_MIDI_MODE_INPUT
)) {
183 spin_unlock_irqrestore(&midi
->open_lock
, flags
);
184 ca_midi_cmd(midi
, midi
->reset
, 0);
186 spin_unlock_irqrestore(&midi
->open_lock
, flags
);
191 static void ca_midi_input_trigger(struct snd_rawmidi_substream
*substream
, int up
)
193 struct snd_ca_midi
*midi
= substream
->rmidi
->private_data
;
195 if (snd_BUG_ON(!midi
->dev_id
))
199 midi
->interrupt_enable(midi
,midi
->rx_enable
);
201 midi
->interrupt_disable(midi
, midi
->rx_enable
);
205 static void ca_midi_output_trigger(struct snd_rawmidi_substream
*substream
, int up
)
207 struct snd_ca_midi
*midi
= substream
->rmidi
->private_data
;
210 if (snd_BUG_ON(!midi
->dev_id
))
217 spin_lock_irqsave(&midi
->output_lock
, flags
);
219 /* try to send some amount of bytes here before interrupts */
221 if (ca_midi_output_ready(midi
)) {
222 if (!(midi
->midi_mode
& CA_MIDI_MODE_OUTPUT
) ||
223 snd_rawmidi_transmit(substream
, &byte
, 1) != 1) {
225 spin_unlock_irqrestore(&midi
->output_lock
, flags
);
228 ca_midi_write_data(midi
, byte
);
235 spin_unlock_irqrestore(&midi
->output_lock
, flags
);
236 midi
->interrupt_enable(midi
,midi
->tx_enable
);
239 midi
->interrupt_disable(midi
,midi
->tx_enable
);
243 static const struct snd_rawmidi_ops ca_midi_output
=
245 .open
= ca_midi_output_open
,
246 .close
= ca_midi_output_close
,
247 .trigger
= ca_midi_output_trigger
,
250 static const struct snd_rawmidi_ops ca_midi_input
=
252 .open
= ca_midi_input_open
,
253 .close
= ca_midi_input_close
,
254 .trigger
= ca_midi_input_trigger
,
257 static void ca_midi_free(struct snd_ca_midi
*midi
)
259 midi
->interrupt
= NULL
;
260 midi
->interrupt_enable
= NULL
;
261 midi
->interrupt_disable
= NULL
;
264 midi
->get_dev_id_card
= NULL
;
265 midi
->get_dev_id_port
= NULL
;
269 static void ca_rmidi_free(struct snd_rawmidi
*rmidi
)
271 ca_midi_free(rmidi
->private_data
);
274 int ca_midi_init(void *dev_id
, struct snd_ca_midi
*midi
, int device
, char *name
)
276 struct snd_rawmidi
*rmidi
;
279 if ((err
= snd_rawmidi_new(midi
->get_dev_id_card(midi
->dev_id
), name
, device
, 1, 1, &rmidi
)) < 0)
282 midi
->dev_id
= dev_id
;
283 midi
->interrupt
= ca_midi_interrupt
;
285 spin_lock_init(&midi
->open_lock
);
286 spin_lock_init(&midi
->input_lock
);
287 spin_lock_init(&midi
->output_lock
);
289 strcpy(rmidi
->name
, name
);
290 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
, &ca_midi_output
);
291 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
, &ca_midi_input
);
292 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_OUTPUT
|
293 SNDRV_RAWMIDI_INFO_INPUT
|
294 SNDRV_RAWMIDI_INFO_DUPLEX
;
295 rmidi
->private_data
= midi
;
296 rmidi
->private_free
= ca_rmidi_free
;