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

source code of linux/sound/drivers/mpu401/mpu401_uart.c