Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/drivers/mpu401/mpu401_uart.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 MPU-401 in UART mode
5
*
6
* MPU-401 supports UART mode which is not capable generate transmit
7
* interrupts thus output is done via polling. Without interrupt,
8
* input is done also via polling. Do not expect good performance.
9
*
10
* 13-03-2003:
11
* Added support for different kind of hardware I/O. Build in choices
12
* are port and mmio. For other kind of I/O, set mpu->read and
13
* mpu->write to your own I/O functions.
14
*/
15
16
#include <linux/io.h>
17
#include <linux/delay.h>
18
#include <linux/init.h>
19
#include <linux/slab.h>
20
#include <linux/ioport.h>
21
#include <linux/module.h>
22
#include <linux/interrupt.h>
23
#include <linux/errno.h>
24
#include <sound/core.h>
25
#include <sound/mpu401.h>
26
27
MODULE_AUTHOR("Jaroslav Kysela <[email protected]>");
28
MODULE_DESCRIPTION("Routines for control of MPU-401 in UART mode");
29
MODULE_LICENSE("GPL");
30
31
static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu);
32
static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu);
33
34
/*
35
36
*/
37
38
#define snd_mpu401_input_avail(mpu) \
39
(!(mpu->read(mpu, MPU401C(mpu)) & MPU401_RX_EMPTY))
40
#define snd_mpu401_output_ready(mpu) \
41
(!(mpu->read(mpu, MPU401C(mpu)) & MPU401_TX_FULL))
42
43
/* Build in lowlevel io */
44
static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data,
45
unsigned long addr)
46
{
47
outb(data, addr);
48
}
49
50
static unsigned char mpu401_read_port(struct snd_mpu401 *mpu,
51
unsigned long addr)
52
{
53
return inb(addr);
54
}
55
56
static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data,
57
unsigned long addr)
58
{
59
writeb(data, (void __iomem *)addr);
60
}
61
62
static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu,
63
unsigned long addr)
64
{
65
return readb((void __iomem *)addr);
66
}
67
/* */
68
69
static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu)
70
{
71
int timeout = 100000;
72
for (; timeout > 0 && snd_mpu401_input_avail(mpu); timeout--)
73
mpu->read(mpu, MPU401D(mpu));
74
#ifdef CONFIG_SND_DEBUG
75
if (timeout <= 0)
76
dev_err(mpu->rmidi->dev,
77
"cmd: clear rx timeout (status = 0x%x)\n",
78
mpu->read(mpu, MPU401C(mpu)));
79
#endif
80
}
81
82
static void uart_interrupt_tx(struct snd_mpu401 *mpu)
83
{
84
unsigned long flags;
85
86
if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
87
test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
88
spin_lock_irqsave(&mpu->output_lock, flags);
89
snd_mpu401_uart_output_write(mpu);
90
spin_unlock_irqrestore(&mpu->output_lock, flags);
91
}
92
}
93
94
static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
95
{
96
unsigned long flags;
97
98
if (mpu->info_flags & MPU401_INFO_INPUT) {
99
spin_lock_irqsave(&mpu->input_lock, flags);
100
if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
101
snd_mpu401_uart_input_read(mpu);
102
else
103
snd_mpu401_uart_clear_rx(mpu);
104
spin_unlock_irqrestore(&mpu->input_lock, flags);
105
}
106
if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
107
/* ok. for better Tx performance try do some output
108
when input is done */
109
uart_interrupt_tx(mpu);
110
}
111
112
/**
113
* snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler
114
* @irq: the irq number
115
* @dev_id: mpu401 instance
116
*
117
* Processes the interrupt for MPU401-UART i/o.
118
*
119
* Return: %IRQ_HANDLED if the interrupt was handled. %IRQ_NONE otherwise.
120
*/
121
irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id)
122
{
123
struct snd_mpu401 *mpu = dev_id;
124
125
if (!mpu)
126
return IRQ_NONE;
127
_snd_mpu401_uart_interrupt(mpu);
128
return IRQ_HANDLED;
129
}
130
131
EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
132
133
/**
134
* snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler
135
* @irq: the irq number
136
* @dev_id: mpu401 instance
137
*
138
* Processes the interrupt for MPU401-UART output.
139
*
140
* Return: %IRQ_HANDLED if the interrupt was handled. %IRQ_NONE otherwise.
141
*/
142
irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id)
143
{
144
struct snd_mpu401 *mpu = dev_id;
145
146
if (!mpu)
147
return IRQ_NONE;
148
uart_interrupt_tx(mpu);
149
return IRQ_HANDLED;
150
}
151
152
EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx);
153
154
/*
155
* timer callback
156
* reprogram the timer and call the interrupt job
157
*/
158
static void snd_mpu401_uart_timer(struct timer_list *t)
159
{
160
struct snd_mpu401 *mpu = timer_container_of(mpu, t, timer);
161
unsigned long flags;
162
163
spin_lock_irqsave(&mpu->timer_lock, flags);
164
/*mpu->mode |= MPU401_MODE_TIMER;*/
165
mod_timer(&mpu->timer, 1 + jiffies);
166
spin_unlock_irqrestore(&mpu->timer_lock, flags);
167
if (mpu->rmidi)
168
_snd_mpu401_uart_interrupt(mpu);
169
}
170
171
/*
172
* initialize the timer callback if not programmed yet
173
*/
174
static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input)
175
{
176
unsigned long flags;
177
178
spin_lock_irqsave (&mpu->timer_lock, flags);
179
if (mpu->timer_invoked == 0) {
180
timer_setup(&mpu->timer, snd_mpu401_uart_timer, 0);
181
mod_timer(&mpu->timer, 1 + jiffies);
182
}
183
mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER :
184
MPU401_MODE_OUTPUT_TIMER;
185
spin_unlock_irqrestore (&mpu->timer_lock, flags);
186
}
187
188
/*
189
* remove the timer callback if still active
190
*/
191
static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input)
192
{
193
unsigned long flags;
194
195
spin_lock_irqsave (&mpu->timer_lock, flags);
196
if (mpu->timer_invoked) {
197
mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER :
198
~MPU401_MODE_OUTPUT_TIMER;
199
if (! mpu->timer_invoked)
200
timer_delete(&mpu->timer);
201
}
202
spin_unlock_irqrestore (&mpu->timer_lock, flags);
203
}
204
205
/*
206
* send a UART command
207
* return zero if successful, non-zero for some errors
208
*/
209
210
static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
211
int ack)
212
{
213
unsigned long flags;
214
int timeout, ok;
215
216
spin_lock_irqsave(&mpu->input_lock, flags);
217
if (mpu->hardware != MPU401_HW_TRID4DWAVE) {
218
mpu->write(mpu, 0x00, MPU401D(mpu));
219
/*snd_mpu401_uart_clear_rx(mpu);*/
220
}
221
/* ok. standard MPU-401 initialization */
222
if (mpu->hardware != MPU401_HW_SB) {
223
for (timeout = 1000; timeout > 0 &&
224
!snd_mpu401_output_ready(mpu); timeout--)
225
udelay(10);
226
#ifdef CONFIG_SND_DEBUG
227
if (!timeout)
228
dev_err(mpu->rmidi->dev,
229
"cmd: tx timeout (status = 0x%x)\n",
230
mpu->read(mpu, MPU401C(mpu)));
231
#endif
232
}
233
mpu->write(mpu, cmd, MPU401C(mpu));
234
if (ack && !(mpu->info_flags & MPU401_INFO_NO_ACK)) {
235
ok = 0;
236
timeout = 10000;
237
while (!ok && timeout-- > 0) {
238
if (snd_mpu401_input_avail(mpu)) {
239
if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
240
ok = 1;
241
}
242
}
243
if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
244
ok = 1;
245
} else
246
ok = 1;
247
spin_unlock_irqrestore(&mpu->input_lock, flags);
248
if (!ok) {
249
dev_err(mpu->rmidi->dev,
250
"cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n",
251
cmd, mpu->port,
252
mpu->read(mpu, MPU401C(mpu)),
253
mpu->read(mpu, MPU401D(mpu)));
254
return 1;
255
}
256
return 0;
257
}
258
259
static int snd_mpu401_do_reset(struct snd_mpu401 *mpu)
260
{
261
if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
262
return -EIO;
263
if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 0))
264
return -EIO;
265
return 0;
266
}
267
268
/*
269
* input/output open/close - protected by open_mutex in rawmidi.c
270
*/
271
static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
272
{
273
struct snd_mpu401 *mpu;
274
int err;
275
276
mpu = substream->rmidi->private_data;
277
if (mpu->open_input) {
278
err = mpu->open_input(mpu);
279
if (err < 0)
280
return err;
281
}
282
if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
283
if (snd_mpu401_do_reset(mpu) < 0)
284
goto error_out;
285
}
286
mpu->substream_input = substream;
287
set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
288
return 0;
289
290
error_out:
291
if (mpu->open_input && mpu->close_input)
292
mpu->close_input(mpu);
293
return -EIO;
294
}
295
296
static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
297
{
298
struct snd_mpu401 *mpu;
299
int err;
300
301
mpu = substream->rmidi->private_data;
302
if (mpu->open_output) {
303
err = mpu->open_output(mpu);
304
if (err < 0)
305
return err;
306
}
307
if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
308
if (snd_mpu401_do_reset(mpu) < 0)
309
goto error_out;
310
}
311
mpu->substream_output = substream;
312
set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
313
return 0;
314
315
error_out:
316
if (mpu->open_output && mpu->close_output)
317
mpu->close_output(mpu);
318
return -EIO;
319
}
320
321
static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream)
322
{
323
struct snd_mpu401 *mpu;
324
int err = 0;
325
326
mpu = substream->rmidi->private_data;
327
clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
328
mpu->substream_input = NULL;
329
if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
330
err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
331
if (mpu->close_input)
332
mpu->close_input(mpu);
333
if (err)
334
return -EIO;
335
return 0;
336
}
337
338
static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream)
339
{
340
struct snd_mpu401 *mpu;
341
int err = 0;
342
343
mpu = substream->rmidi->private_data;
344
clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
345
mpu->substream_output = NULL;
346
if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
347
err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
348
if (mpu->close_output)
349
mpu->close_output(mpu);
350
if (err)
351
return -EIO;
352
return 0;
353
}
354
355
/*
356
* trigger input callback
357
*/
358
static void
359
snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
360
{
361
unsigned long flags;
362
struct snd_mpu401 *mpu;
363
int max = 64;
364
365
mpu = substream->rmidi->private_data;
366
if (up) {
367
if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER,
368
&mpu->mode)) {
369
/* first time - flush FIFO */
370
while (max-- > 0)
371
mpu->read(mpu, MPU401D(mpu));
372
if (mpu->info_flags & MPU401_INFO_USE_TIMER)
373
snd_mpu401_uart_add_timer(mpu, 1);
374
}
375
376
/* read data in advance */
377
spin_lock_irqsave(&mpu->input_lock, flags);
378
snd_mpu401_uart_input_read(mpu);
379
spin_unlock_irqrestore(&mpu->input_lock, flags);
380
} else {
381
if (mpu->info_flags & MPU401_INFO_USE_TIMER)
382
snd_mpu401_uart_remove_timer(mpu, 1);
383
clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
384
}
385
386
}
387
388
/*
389
* transfer input pending data
390
* call with input_lock spinlock held
391
*/
392
static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu)
393
{
394
int max = 128;
395
unsigned char byte;
396
397
while (max-- > 0) {
398
if (! snd_mpu401_input_avail(mpu))
399
break; /* input not available */
400
byte = mpu->read(mpu, MPU401D(mpu));
401
if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
402
snd_rawmidi_receive(mpu->substream_input, &byte, 1);
403
}
404
}
405
406
/*
407
* Tx FIFO sizes:
408
* CS4237B - 16 bytes
409
* AudioDrive ES1688 - 12 bytes
410
* S3 SonicVibes - 8 bytes
411
* SoundBlaster AWE 64 - 2 bytes (ugly hardware)
412
*/
413
414
/*
415
* write output pending bytes
416
* call with output_lock spinlock held
417
*/
418
static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
419
{
420
unsigned char byte;
421
int max = 256;
422
423
do {
424
if (snd_rawmidi_transmit_peek(mpu->substream_output,
425
&byte, 1) == 1) {
426
/*
427
* Try twice because there is hardware that insists on
428
* setting the output busy bit after each write.
429
*/
430
if (!snd_mpu401_output_ready(mpu) &&
431
!snd_mpu401_output_ready(mpu))
432
break; /* Tx FIFO full - try again later */
433
mpu->write(mpu, byte, MPU401D(mpu));
434
snd_rawmidi_transmit_ack(mpu->substream_output, 1);
435
} else {
436
snd_mpu401_uart_remove_timer (mpu, 0);
437
break; /* no other data - leave the tx loop */
438
}
439
} while (--max > 0);
440
}
441
442
/*
443
* output trigger callback
444
*/
445
static void
446
snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
447
{
448
unsigned long flags;
449
struct snd_mpu401 *mpu;
450
451
mpu = substream->rmidi->private_data;
452
if (up) {
453
set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
454
455
/* try to add the timer at each output trigger,
456
* since the output timer might have been removed in
457
* snd_mpu401_uart_output_write().
458
*/
459
if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
460
snd_mpu401_uart_add_timer(mpu, 0);
461
462
/* output pending data */
463
spin_lock_irqsave(&mpu->output_lock, flags);
464
snd_mpu401_uart_output_write(mpu);
465
spin_unlock_irqrestore(&mpu->output_lock, flags);
466
} else {
467
if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
468
snd_mpu401_uart_remove_timer(mpu, 0);
469
clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
470
}
471
}
472
473
/*
474
475
*/
476
477
static const struct snd_rawmidi_ops snd_mpu401_uart_output =
478
{
479
.open = snd_mpu401_uart_output_open,
480
.close = snd_mpu401_uart_output_close,
481
.trigger = snd_mpu401_uart_output_trigger,
482
};
483
484
static const struct snd_rawmidi_ops snd_mpu401_uart_input =
485
{
486
.open = snd_mpu401_uart_input_open,
487
.close = snd_mpu401_uart_input_close,
488
.trigger = snd_mpu401_uart_input_trigger,
489
};
490
491
static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
492
{
493
struct snd_mpu401 *mpu = rmidi->private_data;
494
if (mpu->irq >= 0)
495
free_irq(mpu->irq, (void *) mpu);
496
release_and_free_resource(mpu->res);
497
kfree(mpu);
498
}
499
500
/**
501
* snd_mpu401_uart_new - create an MPU401-UART instance
502
* @card: the card instance
503
* @device: the device index, zero-based
504
* @hardware: the hardware type, MPU401_HW_XXXX
505
* @port: the base address of MPU401 port
506
* @info_flags: bitflags MPU401_INFO_XXX
507
* @irq: the ISA irq number, -1 if not to be allocated
508
* @rrawmidi: the pointer to store the new rawmidi instance
509
*
510
* Creates a new MPU-401 instance.
511
*
512
* Note that the rawmidi instance is returned on the rrawmidi argument,
513
* not the mpu401 instance itself. To access to the mpu401 instance,
514
* cast from rawmidi->private_data (with struct snd_mpu401 magic-cast).
515
*
516
* Return: Zero if successful, or a negative error code.
517
*/
518
int snd_mpu401_uart_new(struct snd_card *card, int device,
519
unsigned short hardware,
520
unsigned long port,
521
unsigned int info_flags,
522
int irq,
523
struct snd_rawmidi ** rrawmidi)
524
{
525
struct snd_mpu401 *mpu;
526
struct snd_rawmidi *rmidi;
527
int in_enable, out_enable;
528
int err;
529
530
if (rrawmidi)
531
*rrawmidi = NULL;
532
if (! (info_flags & (MPU401_INFO_INPUT | MPU401_INFO_OUTPUT)))
533
info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT;
534
in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0;
535
out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0;
536
err = snd_rawmidi_new(card, "MPU-401U", device,
537
out_enable, in_enable, &rmidi);
538
if (err < 0)
539
return err;
540
mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
541
if (!mpu) {
542
err = -ENOMEM;
543
goto free_device;
544
}
545
rmidi->private_data = mpu;
546
rmidi->private_free = snd_mpu401_uart_free;
547
spin_lock_init(&mpu->input_lock);
548
spin_lock_init(&mpu->output_lock);
549
spin_lock_init(&mpu->timer_lock);
550
mpu->hardware = hardware;
551
mpu->irq = -1;
552
mpu->rmidi = rmidi;
553
if (! (info_flags & MPU401_INFO_INTEGRATED)) {
554
int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
555
mpu->res = request_region(port, res_size, "MPU401 UART");
556
if (!mpu->res) {
557
dev_err(rmidi->dev,
558
"mpu401_uart: unable to grab port 0x%lx size %d\n",
559
port, res_size);
560
err = -EBUSY;
561
goto free_device;
562
}
563
}
564
if (info_flags & MPU401_INFO_MMIO) {
565
mpu->write = mpu401_write_mmio;
566
mpu->read = mpu401_read_mmio;
567
} else {
568
mpu->write = mpu401_write_port;
569
mpu->read = mpu401_read_port;
570
}
571
mpu->port = port;
572
if (hardware == MPU401_HW_PC98II)
573
mpu->cport = port + 2;
574
else
575
mpu->cport = port + 1;
576
if (irq >= 0) {
577
if (request_irq(irq, snd_mpu401_uart_interrupt, 0,
578
"MPU401 UART", (void *) mpu)) {
579
dev_err(rmidi->dev,
580
"mpu401_uart: unable to grab IRQ %d\n", irq);
581
err = -EBUSY;
582
goto free_device;
583
}
584
}
585
if (irq < 0 && !(info_flags & MPU401_INFO_IRQ_HOOK))
586
info_flags |= MPU401_INFO_USE_TIMER;
587
mpu->info_flags = info_flags;
588
mpu->irq = irq;
589
if (card->shortname[0])
590
snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI",
591
card->shortname);
592
else
593
sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device);
594
if (out_enable) {
595
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
596
&snd_mpu401_uart_output);
597
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
598
}
599
if (in_enable) {
600
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
601
&snd_mpu401_uart_input);
602
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
603
if (out_enable)
604
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
605
}
606
if (rrawmidi)
607
*rrawmidi = rmidi;
608
return 0;
609
free_device:
610
snd_device_free(card, rmidi);
611
return err;
612
}
613
614
EXPORT_SYMBOL(snd_mpu401_uart_new);
615
616