Lines Matching +full:tx +full:- +full:output +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Routines for control of MPU-401 in UART mode
6 * MPU-401 supports UART mode which is not capable generate transmit
7 * interrupts thus output is done via polling. Without interrupt,
10 * 13-03-2003:
12 * are port and mmio. For other kind of I/O, set mpu->read and
13 * mpu->write to your own I/O functions.
28 MODULE_DESCRIPTION("Routines for control of MPU-401 in UART mode");
39 (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_RX_EMPTY))
41 (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_TX_FULL))
72 for (; timeout > 0 && snd_mpu401_input_avail(mpu); timeout--) in snd_mpu401_uart_clear_rx()
73 mpu->read(mpu, MPU401D(mpu)); in snd_mpu401_uart_clear_rx()
76 dev_err(mpu->rmidi->dev, in snd_mpu401_uart_clear_rx()
78 mpu->read(mpu, MPU401C(mpu))); in snd_mpu401_uart_clear_rx()
86 if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && in uart_interrupt_tx()
87 test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { in uart_interrupt_tx()
88 spin_lock_irqsave(&mpu->output_lock, flags); in uart_interrupt_tx()
90 spin_unlock_irqrestore(&mpu->output_lock, flags); in uart_interrupt_tx()
98 if (mpu->info_flags & MPU401_INFO_INPUT) { in _snd_mpu401_uart_interrupt()
99 spin_lock_irqsave(&mpu->input_lock, flags); in _snd_mpu401_uart_interrupt()
100 if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) in _snd_mpu401_uart_interrupt()
104 spin_unlock_irqrestore(&mpu->input_lock, flags); in _snd_mpu401_uart_interrupt()
106 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) in _snd_mpu401_uart_interrupt()
107 /* ok. for better Tx performance try do some output in _snd_mpu401_uart_interrupt()
113 * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler
117 * Processes the interrupt for MPU401-UART i/o.
134 * snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler
138 * Processes the interrupt for MPU401-UART output.
163 spin_lock_irqsave(&mpu->timer_lock, flags); in snd_mpu401_uart_timer()
164 /*mpu->mode |= MPU401_MODE_TIMER;*/ in snd_mpu401_uart_timer()
165 mod_timer(&mpu->timer, 1 + jiffies); in snd_mpu401_uart_timer()
166 spin_unlock_irqrestore(&mpu->timer_lock, flags); in snd_mpu401_uart_timer()
167 if (mpu->rmidi) in snd_mpu401_uart_timer()
178 spin_lock_irqsave (&mpu->timer_lock, flags); in snd_mpu401_uart_add_timer()
179 if (mpu->timer_invoked == 0) { in snd_mpu401_uart_add_timer()
180 timer_setup(&mpu->timer, snd_mpu401_uart_timer, 0); in snd_mpu401_uart_add_timer()
181 mod_timer(&mpu->timer, 1 + jiffies); in snd_mpu401_uart_add_timer()
183 mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : in snd_mpu401_uart_add_timer()
185 spin_unlock_irqrestore (&mpu->timer_lock, flags); in snd_mpu401_uart_add_timer()
195 spin_lock_irqsave (&mpu->timer_lock, flags); in snd_mpu401_uart_remove_timer()
196 if (mpu->timer_invoked) { in snd_mpu401_uart_remove_timer()
197 mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : in snd_mpu401_uart_remove_timer()
199 if (! mpu->timer_invoked) in snd_mpu401_uart_remove_timer()
200 timer_delete(&mpu->timer); in snd_mpu401_uart_remove_timer()
202 spin_unlock_irqrestore (&mpu->timer_lock, flags); in snd_mpu401_uart_remove_timer()
207 * return zero if successful, non-zero for some errors
216 spin_lock_irqsave(&mpu->input_lock, flags); in snd_mpu401_uart_cmd()
217 if (mpu->hardware != MPU401_HW_TRID4DWAVE) { in snd_mpu401_uart_cmd()
218 mpu->write(mpu, 0x00, MPU401D(mpu)); in snd_mpu401_uart_cmd()
221 /* ok. standard MPU-401 initialization */ in snd_mpu401_uart_cmd()
222 if (mpu->hardware != MPU401_HW_SB) { in snd_mpu401_uart_cmd()
224 !snd_mpu401_output_ready(mpu); timeout--) in snd_mpu401_uart_cmd()
228 dev_err(mpu->rmidi->dev, in snd_mpu401_uart_cmd()
229 "cmd: tx timeout (status = 0x%x)\n", in snd_mpu401_uart_cmd()
230 mpu->read(mpu, MPU401C(mpu))); in snd_mpu401_uart_cmd()
233 mpu->write(mpu, cmd, MPU401C(mpu)); in snd_mpu401_uart_cmd()
234 if (ack && !(mpu->info_flags & MPU401_INFO_NO_ACK)) { in snd_mpu401_uart_cmd()
237 while (!ok && timeout-- > 0) { in snd_mpu401_uart_cmd()
239 if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) in snd_mpu401_uart_cmd()
243 if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) in snd_mpu401_uart_cmd()
247 spin_unlock_irqrestore(&mpu->input_lock, flags); in snd_mpu401_uart_cmd()
249 dev_err(mpu->rmidi->dev, in snd_mpu401_uart_cmd()
251 cmd, mpu->port, in snd_mpu401_uart_cmd()
252 mpu->read(mpu, MPU401C(mpu)), in snd_mpu401_uart_cmd()
253 mpu->read(mpu, MPU401D(mpu))); in snd_mpu401_uart_cmd()
262 return -EIO; in snd_mpu401_do_reset()
264 return -EIO; in snd_mpu401_do_reset()
269 * input/output open/close - protected by open_mutex in rawmidi.c
276 mpu = substream->rmidi->private_data; in snd_mpu401_uart_input_open()
277 if (mpu->open_input) { in snd_mpu401_uart_input_open()
278 err = mpu->open_input(mpu); in snd_mpu401_uart_input_open()
282 if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) { in snd_mpu401_uart_input_open()
286 mpu->substream_input = substream; in snd_mpu401_uart_input_open()
287 set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); in snd_mpu401_uart_input_open()
291 if (mpu->open_input && mpu->close_input) in snd_mpu401_uart_input_open()
292 mpu->close_input(mpu); in snd_mpu401_uart_input_open()
293 return -EIO; in snd_mpu401_uart_input_open()
301 mpu = substream->rmidi->private_data; in snd_mpu401_uart_output_open()
302 if (mpu->open_output) { in snd_mpu401_uart_output_open()
303 err = mpu->open_output(mpu); in snd_mpu401_uart_output_open()
307 if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { in snd_mpu401_uart_output_open()
311 mpu->substream_output = substream; in snd_mpu401_uart_output_open()
312 set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); in snd_mpu401_uart_output_open()
316 if (mpu->open_output && mpu->close_output) in snd_mpu401_uart_output_open()
317 mpu->close_output(mpu); in snd_mpu401_uart_output_open()
318 return -EIO; in snd_mpu401_uart_output_open()
326 mpu = substream->rmidi->private_data; in snd_mpu401_uart_input_close()
327 clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); in snd_mpu401_uart_input_close()
328 mpu->substream_input = NULL; in snd_mpu401_uart_input_close()
329 if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) in snd_mpu401_uart_input_close()
331 if (mpu->close_input) in snd_mpu401_uart_input_close()
332 mpu->close_input(mpu); in snd_mpu401_uart_input_close()
334 return -EIO; in snd_mpu401_uart_input_close()
343 mpu = substream->rmidi->private_data; in snd_mpu401_uart_output_close()
344 clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); in snd_mpu401_uart_output_close()
345 mpu->substream_output = NULL; in snd_mpu401_uart_output_close()
346 if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) in snd_mpu401_uart_output_close()
348 if (mpu->close_output) in snd_mpu401_uart_output_close()
349 mpu->close_output(mpu); in snd_mpu401_uart_output_close()
351 return -EIO; in snd_mpu401_uart_output_close()
365 mpu = substream->rmidi->private_data; in snd_mpu401_uart_input_trigger()
368 &mpu->mode)) { in snd_mpu401_uart_input_trigger()
369 /* first time - flush FIFO */ in snd_mpu401_uart_input_trigger()
370 while (max-- > 0) in snd_mpu401_uart_input_trigger()
371 mpu->read(mpu, MPU401D(mpu)); in snd_mpu401_uart_input_trigger()
372 if (mpu->info_flags & MPU401_INFO_USE_TIMER) in snd_mpu401_uart_input_trigger()
377 spin_lock_irqsave(&mpu->input_lock, flags); in snd_mpu401_uart_input_trigger()
379 spin_unlock_irqrestore(&mpu->input_lock, flags); in snd_mpu401_uart_input_trigger()
381 if (mpu->info_flags & MPU401_INFO_USE_TIMER) in snd_mpu401_uart_input_trigger()
383 clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode); in snd_mpu401_uart_input_trigger()
397 while (max-- > 0) { in snd_mpu401_uart_input_read()
400 byte = mpu->read(mpu, MPU401D(mpu)); in snd_mpu401_uart_input_read()
401 if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) in snd_mpu401_uart_input_read()
402 snd_rawmidi_receive(mpu->substream_input, &byte, 1); in snd_mpu401_uart_input_read()
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)
415 * write output pending bytes
424 if (snd_rawmidi_transmit_peek(mpu->substream_output, in snd_mpu401_uart_output_write()
428 * setting the output busy bit after each write. in snd_mpu401_uart_output_write()
432 break; /* Tx FIFO full - try again later */ in snd_mpu401_uart_output_write()
433 mpu->write(mpu, byte, MPU401D(mpu)); in snd_mpu401_uart_output_write()
434 snd_rawmidi_transmit_ack(mpu->substream_output, 1); in snd_mpu401_uart_output_write()
437 break; /* no other data - leave the tx loop */ in snd_mpu401_uart_output_write()
439 } while (--max > 0); in snd_mpu401_uart_output_write()
443 * output trigger callback
451 mpu = substream->rmidi->private_data; in snd_mpu401_uart_output_trigger()
453 set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); in snd_mpu401_uart_output_trigger()
455 /* try to add the timer at each output trigger, in snd_mpu401_uart_output_trigger()
456 * since the output timer might have been removed in in snd_mpu401_uart_output_trigger()
459 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) in snd_mpu401_uart_output_trigger()
462 /* output pending data */ in snd_mpu401_uart_output_trigger()
463 spin_lock_irqsave(&mpu->output_lock, flags); in snd_mpu401_uart_output_trigger()
465 spin_unlock_irqrestore(&mpu->output_lock, flags); in snd_mpu401_uart_output_trigger()
467 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) in snd_mpu401_uart_output_trigger()
469 clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); in snd_mpu401_uart_output_trigger()
493 struct snd_mpu401 *mpu = rmidi->private_data; in snd_mpu401_uart_free()
494 if (mpu->irq >= 0) in snd_mpu401_uart_free()
495 free_irq(mpu->irq, (void *) mpu); in snd_mpu401_uart_free()
496 release_and_free_resource(mpu->res); in snd_mpu401_uart_free()
501 * snd_mpu401_uart_new - create an MPU401-UART instance
503 * @device: the device index, zero-based
507 * @irq: the ISA irq number, -1 if not to be allocated
510 * Creates a new MPU-401 instance.
514 * cast from rawmidi->private_data (with struct snd_mpu401 magic-cast).
536 err = snd_rawmidi_new(card, "MPU-401U", device, in snd_mpu401_uart_new()
542 err = -ENOMEM; in snd_mpu401_uart_new()
545 rmidi->private_data = mpu; in snd_mpu401_uart_new()
546 rmidi->private_free = snd_mpu401_uart_free; in snd_mpu401_uart_new()
547 spin_lock_init(&mpu->input_lock); in snd_mpu401_uart_new()
548 spin_lock_init(&mpu->output_lock); in snd_mpu401_uart_new()
549 spin_lock_init(&mpu->timer_lock); in snd_mpu401_uart_new()
550 mpu->hardware = hardware; in snd_mpu401_uart_new()
551 mpu->irq = -1; in snd_mpu401_uart_new()
552 mpu->rmidi = rmidi; in snd_mpu401_uart_new()
555 mpu->res = request_region(port, res_size, "MPU401 UART"); in snd_mpu401_uart_new()
556 if (!mpu->res) { in snd_mpu401_uart_new()
557 dev_err(rmidi->dev, in snd_mpu401_uart_new()
560 err = -EBUSY; in snd_mpu401_uart_new()
565 mpu->write = mpu401_write_mmio; in snd_mpu401_uart_new()
566 mpu->read = mpu401_read_mmio; in snd_mpu401_uart_new()
568 mpu->write = mpu401_write_port; in snd_mpu401_uart_new()
569 mpu->read = mpu401_read_port; in snd_mpu401_uart_new()
571 mpu->port = port; in snd_mpu401_uart_new()
573 mpu->cport = port + 2; in snd_mpu401_uart_new()
575 mpu->cport = port + 1; in snd_mpu401_uart_new()
579 dev_err(rmidi->dev, in snd_mpu401_uart_new()
581 err = -EBUSY; in snd_mpu401_uart_new()
587 mpu->info_flags = info_flags; in snd_mpu401_uart_new()
588 mpu->irq = irq; in snd_mpu401_uart_new()
589 if (card->shortname[0]) in snd_mpu401_uart_new()
590 snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", in snd_mpu401_uart_new()
591 card->shortname); in snd_mpu401_uart_new()
593 sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device); in snd_mpu401_uart_new()
597 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; in snd_mpu401_uart_new()
602 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; in snd_mpu401_uart_new()
604 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; in snd_mpu401_uart_new()