Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/pci/emu10k1/emumpu401.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (c) by Jaroslav Kysela <[email protected]>
4
* Routines for control of EMU10K1 MPU-401 in UART mode
5
*/
6
7
#include <linux/time.h>
8
#include <linux/init.h>
9
#include <sound/core.h>
10
#include <sound/emu10k1.h>
11
12
#define EMU10K1_MIDI_MODE_INPUT (1<<0)
13
#define EMU10K1_MIDI_MODE_OUTPUT (1<<1)
14
15
static inline unsigned char mpu401_read(struct snd_emu10k1 *emu,
16
struct snd_emu10k1_midi *mpu, int idx)
17
{
18
if (emu->audigy)
19
return (unsigned char)snd_emu10k1_ptr_read(emu, mpu->port + idx, 0);
20
else
21
return inb(emu->port + mpu->port + idx);
22
}
23
24
static inline void mpu401_write(struct snd_emu10k1 *emu,
25
struct snd_emu10k1_midi *mpu, int data, int idx)
26
{
27
if (emu->audigy)
28
snd_emu10k1_ptr_write(emu, mpu->port + idx, 0, data);
29
else
30
outb(data, emu->port + mpu->port + idx);
31
}
32
33
#define mpu401_write_data(emu, mpu, data) mpu401_write(emu, mpu, data, 0)
34
#define mpu401_write_cmd(emu, mpu, data) mpu401_write(emu, mpu, data, 1)
35
#define mpu401_read_data(emu, mpu) mpu401_read(emu, mpu, 0)
36
#define mpu401_read_stat(emu, mpu) mpu401_read(emu, mpu, 1)
37
38
#define mpu401_input_avail(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x80))
39
#define mpu401_output_ready(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x40))
40
41
#define MPU401_RESET 0xff
42
#define MPU401_ENTER_UART 0x3f
43
#define MPU401_ACK 0xfe
44
45
static void mpu401_clear_rx(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *mpu)
46
{
47
int timeout = 100000;
48
for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--)
49
mpu401_read_data(emu, mpu);
50
#ifdef CONFIG_SND_DEBUG
51
if (timeout <= 0)
52
dev_err(emu->card->dev,
53
"cmd: clear rx timeout (status = 0x%x)\n",
54
mpu401_read_stat(emu, mpu));
55
#endif
56
}
57
58
/*
59
60
*/
61
62
static void do_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, unsigned int status)
63
{
64
unsigned char byte;
65
66
if (midi->rmidi == NULL) {
67
snd_emu10k1_intr_disable(emu, midi->tx_enable | midi->rx_enable);
68
return;
69
}
70
71
spin_lock(&midi->input_lock);
72
if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) {
73
if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) {
74
mpu401_clear_rx(emu, midi);
75
} else {
76
byte = mpu401_read_data(emu, midi);
77
if (midi->substream_input)
78
snd_rawmidi_receive(midi->substream_input, &byte, 1);
79
}
80
}
81
spin_unlock(&midi->input_lock);
82
83
spin_lock(&midi->output_lock);
84
if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) {
85
if (midi->substream_output &&
86
snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
87
mpu401_write_data(emu, midi, byte);
88
} else {
89
snd_emu10k1_intr_disable(emu, midi->tx_enable);
90
}
91
}
92
spin_unlock(&midi->output_lock);
93
}
94
95
static void snd_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, unsigned int status)
96
{
97
do_emu10k1_midi_interrupt(emu, &emu->midi, status);
98
}
99
100
static void snd_emu10k1_midi_interrupt2(struct snd_emu10k1 *emu, unsigned int status)
101
{
102
do_emu10k1_midi_interrupt(emu, &emu->midi2, status);
103
}
104
105
static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_midi *midi, unsigned char cmd, int ack)
106
{
107
int timeout, ok;
108
109
spin_lock_irq(&midi->input_lock);
110
mpu401_write_data(emu, midi, 0x00);
111
/* mpu401_clear_rx(emu, midi); */
112
113
mpu401_write_cmd(emu, midi, cmd);
114
if (ack) {
115
ok = 0;
116
timeout = 10000;
117
while (!ok && timeout-- > 0) {
118
if (mpu401_input_avail(emu, midi)) {
119
if (mpu401_read_data(emu, midi) == MPU401_ACK)
120
ok = 1;
121
}
122
}
123
if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK)
124
ok = 1;
125
} else {
126
ok = 1;
127
}
128
spin_unlock_irq(&midi->input_lock);
129
if (!ok) {
130
dev_err(emu->card->dev,
131
"midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n",
132
cmd, emu->port,
133
mpu401_read_stat(emu, midi),
134
mpu401_read_data(emu, midi));
135
return 1;
136
}
137
return 0;
138
}
139
140
static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream)
141
{
142
struct snd_emu10k1 *emu;
143
struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
144
145
emu = midi->emu;
146
if (snd_BUG_ON(!emu))
147
return -ENXIO;
148
spin_lock_irq(&midi->open_lock);
149
midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT;
150
midi->substream_input = substream;
151
if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) {
152
spin_unlock_irq(&midi->open_lock);
153
if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1))
154
goto error_out;
155
if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1))
156
goto error_out;
157
} else {
158
spin_unlock_irq(&midi->open_lock);
159
}
160
return 0;
161
162
error_out:
163
return -EIO;
164
}
165
166
static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream)
167
{
168
struct snd_emu10k1 *emu;
169
struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
170
171
emu = midi->emu;
172
if (snd_BUG_ON(!emu))
173
return -ENXIO;
174
spin_lock_irq(&midi->open_lock);
175
midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT;
176
midi->substream_output = substream;
177
if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) {
178
spin_unlock_irq(&midi->open_lock);
179
if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1))
180
goto error_out;
181
if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1))
182
goto error_out;
183
} else {
184
spin_unlock_irq(&midi->open_lock);
185
}
186
return 0;
187
188
error_out:
189
return -EIO;
190
}
191
192
static int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream)
193
{
194
struct snd_emu10k1 *emu;
195
struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
196
int err = 0;
197
198
emu = midi->emu;
199
if (snd_BUG_ON(!emu))
200
return -ENXIO;
201
spin_lock_irq(&midi->open_lock);
202
snd_emu10k1_intr_disable(emu, midi->rx_enable);
203
midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT;
204
midi->substream_input = NULL;
205
if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) {
206
spin_unlock_irq(&midi->open_lock);
207
err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0);
208
} else {
209
spin_unlock_irq(&midi->open_lock);
210
}
211
return err;
212
}
213
214
static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream)
215
{
216
struct snd_emu10k1 *emu;
217
struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
218
int err = 0;
219
220
emu = midi->emu;
221
if (snd_BUG_ON(!emu))
222
return -ENXIO;
223
spin_lock_irq(&midi->open_lock);
224
snd_emu10k1_intr_disable(emu, midi->tx_enable);
225
midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT;
226
midi->substream_output = NULL;
227
if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) {
228
spin_unlock_irq(&midi->open_lock);
229
err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0);
230
} else {
231
spin_unlock_irq(&midi->open_lock);
232
}
233
return err;
234
}
235
236
static void snd_emu10k1_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
237
{
238
struct snd_emu10k1 *emu;
239
struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
240
emu = midi->emu;
241
if (snd_BUG_ON(!emu))
242
return;
243
244
if (up)
245
snd_emu10k1_intr_enable(emu, midi->rx_enable);
246
else
247
snd_emu10k1_intr_disable(emu, midi->rx_enable);
248
}
249
250
static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
251
{
252
struct snd_emu10k1 *emu;
253
struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
254
255
emu = midi->emu;
256
if (snd_BUG_ON(!emu))
257
return;
258
259
if (up) {
260
int max = 4;
261
unsigned char byte;
262
263
/* try to send some amount of bytes here before interrupts */
264
spin_lock_irq(&midi->output_lock);
265
while (max > 0) {
266
if (mpu401_output_ready(emu, midi)) {
267
if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) ||
268
snd_rawmidi_transmit(substream, &byte, 1) != 1) {
269
/* no more data */
270
spin_unlock_irq(&midi->output_lock);
271
return;
272
}
273
mpu401_write_data(emu, midi, byte);
274
max--;
275
} else {
276
break;
277
}
278
}
279
spin_unlock_irq(&midi->output_lock);
280
snd_emu10k1_intr_enable(emu, midi->tx_enable);
281
} else {
282
snd_emu10k1_intr_disable(emu, midi->tx_enable);
283
}
284
}
285
286
/*
287
288
*/
289
290
static const struct snd_rawmidi_ops snd_emu10k1_midi_output =
291
{
292
.open = snd_emu10k1_midi_output_open,
293
.close = snd_emu10k1_midi_output_close,
294
.trigger = snd_emu10k1_midi_output_trigger,
295
};
296
297
static const struct snd_rawmidi_ops snd_emu10k1_midi_input =
298
{
299
.open = snd_emu10k1_midi_input_open,
300
.close = snd_emu10k1_midi_input_close,
301
.trigger = snd_emu10k1_midi_input_trigger,
302
};
303
304
static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi)
305
{
306
struct snd_emu10k1_midi *midi = rmidi->private_data;
307
midi->interrupt = NULL;
308
midi->rmidi = NULL;
309
}
310
311
static int emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name)
312
{
313
struct snd_rawmidi *rmidi;
314
int err;
315
316
err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi);
317
if (err < 0)
318
return err;
319
midi->emu = emu;
320
spin_lock_init(&midi->open_lock);
321
spin_lock_init(&midi->input_lock);
322
spin_lock_init(&midi->output_lock);
323
strscpy(rmidi->name, name);
324
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1_midi_output);
325
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1_midi_input);
326
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
327
SNDRV_RAWMIDI_INFO_INPUT |
328
SNDRV_RAWMIDI_INFO_DUPLEX;
329
rmidi->private_data = midi;
330
rmidi->private_free = snd_emu10k1_midi_free;
331
midi->rmidi = rmidi;
332
return 0;
333
}
334
335
int snd_emu10k1_midi(struct snd_emu10k1 *emu)
336
{
337
struct snd_emu10k1_midi *midi = &emu->midi;
338
int err;
339
340
err = emu10k1_midi_init(emu, midi, 0, "EMU10K1 MPU-401 (UART)");
341
if (err < 0)
342
return err;
343
344
midi->tx_enable = INTE_MIDITXENABLE;
345
midi->rx_enable = INTE_MIDIRXENABLE;
346
midi->port = MUDATA;
347
midi->ipr_tx = IPR_MIDITRANSBUFEMPTY;
348
midi->ipr_rx = IPR_MIDIRECVBUFEMPTY;
349
midi->interrupt = snd_emu10k1_midi_interrupt;
350
return 0;
351
}
352
353
int snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu)
354
{
355
struct snd_emu10k1_midi *midi;
356
int err;
357
358
midi = &emu->midi;
359
err = emu10k1_midi_init(emu, midi, 0, "Audigy MPU-401 (UART)");
360
if (err < 0)
361
return err;
362
363
midi->tx_enable = INTE_MIDITXENABLE;
364
midi->rx_enable = INTE_MIDIRXENABLE;
365
midi->port = A_MUDATA1;
366
midi->ipr_tx = IPR_MIDITRANSBUFEMPTY;
367
midi->ipr_rx = IPR_MIDIRECVBUFEMPTY;
368
midi->interrupt = snd_emu10k1_midi_interrupt;
369
370
midi = &emu->midi2;
371
err = emu10k1_midi_init(emu, midi, 1, "Audigy MPU-401 #2");
372
if (err < 0)
373
return err;
374
375
midi->tx_enable = INTE_A_MIDITXENABLE2;
376
midi->rx_enable = INTE_A_MIDIRXENABLE2;
377
midi->port = A_MUDATA2;
378
midi->ipr_tx = IPR_A_MIDITRANSBUFEMPTY2;
379
midi->ipr_rx = IPR_A_MIDIRECVBUFEMPTY2;
380
midi->interrupt = snd_emu10k1_midi_interrupt2;
381
return 0;
382
}
383
384