aboutsummaryrefslogtreecommitdiffstats
path: root/sound/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'sound/drivers')
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c96
1 files changed, 68 insertions, 28 deletions
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index cd64d3eb9ec8..4bf07ca9b17d 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -95,17 +95,8 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu)
95#endif 95#endif
96} 96}
97 97
98static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) 98static void uart_interrupt_tx(struct snd_mpu401 *mpu)
99{ 99{
100 spin_lock(&mpu->input_lock);
101 if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
102 snd_mpu401_uart_input_read(mpu);
103 else
104 snd_mpu401_uart_clear_rx(mpu);
105 spin_unlock(&mpu->input_lock);
106 /* ok. for better Tx performance try do some output when
107 * input is done
108 */
109 if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && 100 if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
110 test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { 101 test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
111 spin_lock(&mpu->output_lock); 102 spin_lock(&mpu->output_lock);
@@ -114,6 +105,22 @@ static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
114 } 105 }
115} 106}
116 107
108static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
109{
110 if (mpu->info_flags & MPU401_INFO_INPUT) {
111 spin_lock(&mpu->input_lock);
112 if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
113 snd_mpu401_uart_input_read(mpu);
114 else
115 snd_mpu401_uart_clear_rx(mpu);
116 spin_unlock(&mpu->input_lock);
117 }
118 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
119 /* ok. for better Tx performance try do some output
120 when input is done */
121 uart_interrupt_tx(mpu);
122}
123
117/** 124/**
118 * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler 125 * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler
119 * @irq: the irq number 126 * @irq: the irq number
@@ -135,6 +142,27 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id,
135 142
136EXPORT_SYMBOL(snd_mpu401_uart_interrupt); 143EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
137 144
145/**
146 * snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler
147 * @irq: the irq number
148 * @dev_id: mpu401 instance
149 * @regs: the reigster
150 *
151 * Processes the interrupt for MPU401-UART output.
152 */
153irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id,
154 struct pt_regs *regs)
155{
156 struct snd_mpu401 *mpu = dev_id;
157
158 if (mpu == NULL)
159 return IRQ_NONE;
160 uart_interrupt_tx(mpu);
161 return IRQ_HANDLED;
162}
163
164EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx);
165
138/* 166/*
139 * timer callback 167 * timer callback
140 * reprogram the timer and call the interrupt job 168 * reprogram the timer and call the interrupt job
@@ -430,14 +458,16 @@ snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
430 * since the output timer might have been removed in 458 * since the output timer might have been removed in
431 * snd_mpu401_uart_output_write(). 459 * snd_mpu401_uart_output_write().
432 */ 460 */
433 snd_mpu401_uart_add_timer(mpu, 0); 461 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
462 snd_mpu401_uart_add_timer(mpu, 0);
434 463
435 /* output pending data */ 464 /* output pending data */
436 spin_lock_irqsave(&mpu->output_lock, flags); 465 spin_lock_irqsave(&mpu->output_lock, flags);
437 snd_mpu401_uart_output_write(mpu); 466 snd_mpu401_uart_output_write(mpu);
438 spin_unlock_irqrestore(&mpu->output_lock, flags); 467 spin_unlock_irqrestore(&mpu->output_lock, flags);
439 } else { 468 } else {
440 snd_mpu401_uart_remove_timer(mpu, 0); 469 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
470 snd_mpu401_uart_remove_timer(mpu, 0);
441 clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); 471 clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
442 } 472 }
443} 473}
@@ -475,7 +505,7 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
475 * @device: the device index, zero-based 505 * @device: the device index, zero-based
476 * @hardware: the hardware type, MPU401_HW_XXXX 506 * @hardware: the hardware type, MPU401_HW_XXXX
477 * @port: the base address of MPU401 port 507 * @port: the base address of MPU401 port
478 * @integrated: non-zero if the port was already reserved by the chip 508 * @info_flags: bitflags MPU401_INFO_XXX
479 * @irq: the irq number, -1 if no interrupt for mpu 509 * @irq: the irq number, -1 if no interrupt for mpu
480 * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved. 510 * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved.
481 * @rrawmidi: the pointer to store the new rawmidi instance 511 * @rrawmidi: the pointer to store the new rawmidi instance
@@ -490,17 +520,24 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
490 */ 520 */
491int snd_mpu401_uart_new(struct snd_card *card, int device, 521int snd_mpu401_uart_new(struct snd_card *card, int device,
492 unsigned short hardware, 522 unsigned short hardware,
493 unsigned long port, int integrated, 523 unsigned long port,
524 unsigned int info_flags,
494 int irq, int irq_flags, 525 int irq, int irq_flags,
495 struct snd_rawmidi ** rrawmidi) 526 struct snd_rawmidi ** rrawmidi)
496{ 527{
497 struct snd_mpu401 *mpu; 528 struct snd_mpu401 *mpu;
498 struct snd_rawmidi *rmidi; 529 struct snd_rawmidi *rmidi;
530 int in_enable, out_enable;
499 int err; 531 int err;
500 532
501 if (rrawmidi) 533 if (rrawmidi)
502 *rrawmidi = NULL; 534 *rrawmidi = NULL;
503 if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0) 535 if (! (info_flags & (MPU401_INFO_INPUT | MPU401_INFO_OUTPUT)))
536 info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT;
537 in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0;
538 out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0;
539 if ((err = snd_rawmidi_new(card, "MPU-401U", device,
540 out_enable, in_enable, &rmidi)) < 0)
504 return err; 541 return err;
505 mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); 542 mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
506 if (mpu == NULL) { 543 if (mpu == NULL) {
@@ -514,7 +551,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
514 spin_lock_init(&mpu->output_lock); 551 spin_lock_init(&mpu->output_lock);
515 spin_lock_init(&mpu->timer_lock); 552 spin_lock_init(&mpu->timer_lock);
516 mpu->hardware = hardware; 553 mpu->hardware = hardware;
517 if (!integrated) { 554 if (! (info_flags & MPU401_INFO_INTEGRATED)) {
518 int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; 555 int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
519 mpu->res = request_region(port, res_size, "MPU401 UART"); 556 mpu->res = request_region(port, res_size, "MPU401 UART");
520 if (mpu->res == NULL) { 557 if (mpu->res == NULL) {
@@ -525,15 +562,12 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
525 return -EBUSY; 562 return -EBUSY;
526 } 563 }
527 } 564 }
528 switch (hardware) { 565 if (info_flags & MPU401_INFO_MMIO) {
529 case MPU401_HW_AUREAL:
530 mpu->write = mpu401_write_mmio; 566 mpu->write = mpu401_write_mmio;
531 mpu->read = mpu401_read_mmio; 567 mpu->read = mpu401_read_mmio;
532 break; 568 } else {
533 default:
534 mpu->write = mpu401_write_port; 569 mpu->write = mpu401_write_port;
535 mpu->read = mpu401_read_port; 570 mpu->read = mpu401_read_port;
536 break;
537 } 571 }
538 mpu->port = port; 572 mpu->port = port;
539 if (hardware == MPU401_HW_PC98II) 573 if (hardware == MPU401_HW_PC98II)
@@ -549,6 +583,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
549 return -EBUSY; 583 return -EBUSY;
550 } 584 }
551 } 585 }
586 mpu->info_flags = info_flags;
552 mpu->irq = irq; 587 mpu->irq = irq;
553 mpu->irq_flags = irq_flags; 588 mpu->irq_flags = irq_flags;
554 if (card->shortname[0]) 589 if (card->shortname[0])
@@ -556,13 +591,18 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
556 card->shortname); 591 card->shortname);
557 else 592 else
558 sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device); 593 sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device);
559 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 594 if (out_enable) {
560 &snd_mpu401_uart_output); 595 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
561 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 596 &snd_mpu401_uart_output);
562 &snd_mpu401_uart_input); 597 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
563 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | 598 }
564 SNDRV_RAWMIDI_INFO_INPUT | 599 if (in_enable) {
565 SNDRV_RAWMIDI_INFO_DUPLEX; 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 }
566 mpu->rmidi = rmidi; 606 mpu->rmidi = rmidi;
567 if (rrawmidi) 607 if (rrawmidi)
568 *rrawmidi = rmidi; 608 *rrawmidi = rmidi;