summaryrefslogtreecommitdiff
path: root/sound/pci/ca0106/ca0106_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/ca0106/ca0106_main.c')
-rw-r--r--sound/pci/ca0106/ca0106_main.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index f6920ef5b4ea..aaaef9e66af6 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -338,6 +338,18 @@ static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
+static void snd_ca0106_intr_disable(ca0106_t *emu, unsigned int intrenb)
+{
+ unsigned long flags;
+ unsigned int enable;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ enable = inl(emu->port + INTE) & ~intrenb;
+ outl(enable, emu->port + INTE);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
+
static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
kfree(runtime->private_data);
@@ -1040,6 +1052,15 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
spin_lock(&chip->emu_lock);
+
+ if (chip->midi.dev_id &&
+ (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
+ if (chip->midi.interrupt)
+ chip->midi.interrupt(&chip->midi, status);
+ else
+ chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable);
+ }
+
// acknowledge the interrupt if necessary
outl(status, chip->port+IPR);
@@ -1309,6 +1330,82 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
return 0;
}
+
+void ca0106_midi_interrupt_enable(ca_midi_t *midi, int intr){
+ snd_ca0106_intr_enable((ca0106_t *)(midi->dev_id), intr);
+}
+
+void ca0106_midi_interrupt_disable(ca_midi_t *midi, int intr){
+ snd_ca0106_intr_disable((ca0106_t *)(midi->dev_id), intr);
+}
+
+unsigned char ca0106_midi_read(ca_midi_t *midi, int idx){
+ return (unsigned char)snd_ca0106_ptr_read((ca0106_t *)(midi->dev_id), midi->port + idx, 0);
+}
+
+void ca0106_midi_write(ca_midi_t *midi, int data, int idx){
+ snd_ca0106_ptr_write((ca0106_t *)(midi->dev_id), midi->port + idx, 0, data);
+}
+
+snd_card_t *ca0106_dev_id_card(void *dev_id){
+ return ((ca0106_t *)dev_id)->card;
+}
+
+int ca0106_dev_id_port(void *dev_id){
+ return ((ca0106_t *)dev_id)->port;
+}
+
+static int __devinit snd_ca0106_midi(ca0106_t *chip, unsigned int channel)
+{
+ ca_midi_t *midi;
+ char *name;
+ int err;
+
+ if(channel==CA0106_MIDI_CHAN_B) {
+ name = "CA0106 MPU-401 (UART) B";
+ midi = &chip->midi2;
+ midi->tx_enable = INTE_MIDI_TX_B;
+ midi->rx_enable = INTE_MIDI_RX_B;
+ midi->ipr_tx = IPR_MIDI_TX_B;
+ midi->ipr_rx = IPR_MIDI_RX_B;
+ midi->port = MIDI_UART_B_DATA;
+ } else {
+ name = "CA0106 MPU-401 (UART)";
+ midi = &chip->midi;
+ midi->tx_enable = INTE_MIDI_TX_A;
+ midi->rx_enable = INTE_MIDI_TX_B;
+ midi->ipr_tx = IPR_MIDI_TX_A;
+ midi->ipr_rx = IPR_MIDI_RX_A;
+ midi->port = MIDI_UART_A_DATA;
+ }
+
+ midi->reset = CA0106_MPU401_RESET;
+ midi->enter_uart = CA0106_MPU401_ENTER_UART;
+ midi->ack = CA0106_MPU401_ACK;
+
+ midi->input_avail = CA0106_MIDI_INPUT_AVAIL;
+ midi->output_ready = CA0106_MIDI_OUTPUT_READY;
+
+ midi->channel = channel;
+
+ midi->interrupt_enable = ca0106_midi_interrupt_enable;
+ midi->interrupt_disable = ca0106_midi_interrupt_disable;
+
+ midi->read = ca0106_midi_read;
+ midi->write = ca0106_midi_write;
+
+ midi->get_dev_id_card = ca0106_dev_id_card;
+ midi->get_dev_id_port = ca0106_dev_id_port;
+
+ midi->dev_id = chip;
+
+ if ((err = ca_midi_init(chip, midi, 0, name)) < 0)
+ return err;
+
+ return 0;
+}
+
+
static int __devinit snd_ca0106_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
@@ -1360,6 +1457,20 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
return err;
}
+#ifdef CONFIG_SND_DEBUG_DETECT
+ printk("ca0106: probe for MIDI channel A ...");
+#endif
+ if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
+ snd_card_free(card);
+#ifdef CONFIG_SND_DEBUG_DETECT
+ printk(" failed, err=0x%x\n",err);
+#endif
+ return err;
+ }
+#ifdef CONFIG_SND_DEBUG_DETECT
+ printk(" done.\n");
+#endif
+
snd_ca0106_proc_init(chip);
if ((err = snd_card_register(card)) < 0) {