aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ca0106/ca0106_main.c
diff options
context:
space:
mode:
authorJames Courtier-Dutton <James@superbug.co.uk>2005-10-20 16:57:51 -0400
committerJaroslav Kysela <perex@suse.cz>2005-11-04 07:19:26 -0500
commit8a5afd29dc16a9e687f63195cb635ecd611482d0 (patch)
treedff1950bd5302e5b2752e32075166638be1436dd /sound/pci/ca0106/ca0106_main.c
parentb0b9811956db489ca43596c37ef2f38582454e51 (diff)
[ALSA] snd-ca0106: Add midi support.
Modules: PCI drivers,CA0106 driver Author: Tilman Kranz <tilde@tk-sls.de> Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
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)
338 spin_unlock_irqrestore(&emu->emu_lock, flags); 338 spin_unlock_irqrestore(&emu->emu_lock, flags);
339} 339}
340 340
341static void snd_ca0106_intr_disable(ca0106_t *emu, unsigned int intrenb)
342{
343 unsigned long flags;
344 unsigned int enable;
345
346 spin_lock_irqsave(&emu->emu_lock, flags);
347 enable = inl(emu->port + INTE) & ~intrenb;
348 outl(enable, emu->port + INTE);
349 spin_unlock_irqrestore(&emu->emu_lock, flags);
350}
351
352
341static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime) 353static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime)
342{ 354{
343 kfree(runtime->private_data); 355 kfree(runtime->private_data);
@@ -1040,6 +1052,15 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
1040 1052
1041 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76); 1053 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
1042 spin_lock(&chip->emu_lock); 1054 spin_lock(&chip->emu_lock);
1055
1056 if (chip->midi.dev_id &&
1057 (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
1058 if (chip->midi.interrupt)
1059 chip->midi.interrupt(&chip->midi, status);
1060 else
1061 chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable);
1062 }
1063
1043 // acknowledge the interrupt if necessary 1064 // acknowledge the interrupt if necessary
1044 outl(status, chip->port+IPR); 1065 outl(status, chip->port+IPR);
1045 1066
@@ -1309,6 +1330,82 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
1309 return 0; 1330 return 0;
1310} 1331}
1311 1332
1333
1334void ca0106_midi_interrupt_enable(ca_midi_t *midi, int intr){
1335 snd_ca0106_intr_enable((ca0106_t *)(midi->dev_id), intr);
1336}
1337
1338void ca0106_midi_interrupt_disable(ca_midi_t *midi, int intr){
1339 snd_ca0106_intr_disable((ca0106_t *)(midi->dev_id), intr);
1340}
1341
1342unsigned char ca0106_midi_read(ca_midi_t *midi, int idx){
1343 return (unsigned char)snd_ca0106_ptr_read((ca0106_t *)(midi->dev_id), midi->port + idx, 0);
1344}
1345
1346void ca0106_midi_write(ca_midi_t *midi, int data, int idx){
1347 snd_ca0106_ptr_write((ca0106_t *)(midi->dev_id), midi->port + idx, 0, data);
1348}
1349
1350snd_card_t *ca0106_dev_id_card(void *dev_id){
1351 return ((ca0106_t *)dev_id)->card;
1352}
1353
1354int ca0106_dev_id_port(void *dev_id){
1355 return ((ca0106_t *)dev_id)->port;
1356}
1357
1358static int __devinit snd_ca0106_midi(ca0106_t *chip, unsigned int channel)
1359{
1360 ca_midi_t *midi;
1361 char *name;
1362 int err;
1363
1364 if(channel==CA0106_MIDI_CHAN_B) {
1365 name = "CA0106 MPU-401 (UART) B";
1366 midi = &chip->midi2;
1367 midi->tx_enable = INTE_MIDI_TX_B;
1368 midi->rx_enable = INTE_MIDI_RX_B;
1369 midi->ipr_tx = IPR_MIDI_TX_B;
1370 midi->ipr_rx = IPR_MIDI_RX_B;
1371 midi->port = MIDI_UART_B_DATA;
1372 } else {
1373 name = "CA0106 MPU-401 (UART)";
1374 midi = &chip->midi;
1375 midi->tx_enable = INTE_MIDI_TX_A;
1376 midi->rx_enable = INTE_MIDI_TX_B;
1377 midi->ipr_tx = IPR_MIDI_TX_A;
1378 midi->ipr_rx = IPR_MIDI_RX_A;
1379 midi->port = MIDI_UART_A_DATA;
1380 }
1381
1382 midi->reset = CA0106_MPU401_RESET;
1383 midi->enter_uart = CA0106_MPU401_ENTER_UART;
1384 midi->ack = CA0106_MPU401_ACK;
1385
1386 midi->input_avail = CA0106_MIDI_INPUT_AVAIL;
1387 midi->output_ready = CA0106_MIDI_OUTPUT_READY;
1388
1389 midi->channel = channel;
1390
1391 midi->interrupt_enable = ca0106_midi_interrupt_enable;
1392 midi->interrupt_disable = ca0106_midi_interrupt_disable;
1393
1394 midi->read = ca0106_midi_read;
1395 midi->write = ca0106_midi_write;
1396
1397 midi->get_dev_id_card = ca0106_dev_id_card;
1398 midi->get_dev_id_port = ca0106_dev_id_port;
1399
1400 midi->dev_id = chip;
1401
1402 if ((err = ca_midi_init(chip, midi, 0, name)) < 0)
1403 return err;
1404
1405 return 0;
1406}
1407
1408
1312static int __devinit snd_ca0106_probe(struct pci_dev *pci, 1409static int __devinit snd_ca0106_probe(struct pci_dev *pci,
1313 const struct pci_device_id *pci_id) 1410 const struct pci_device_id *pci_id)
1314{ 1411{
@@ -1360,6 +1457,20 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
1360 return err; 1457 return err;
1361 } 1458 }
1362 1459
1460#ifdef CONFIG_SND_DEBUG_DETECT
1461 printk("ca0106: probe for MIDI channel A ...");
1462#endif
1463 if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
1464 snd_card_free(card);
1465#ifdef CONFIG_SND_DEBUG_DETECT
1466 printk(" failed, err=0x%x\n",err);
1467#endif
1468 return err;
1469 }
1470#ifdef CONFIG_SND_DEBUG_DETECT
1471 printk(" done.\n");
1472#endif
1473
1363 snd_ca0106_proc_init(chip); 1474 snd_ca0106_proc_init(chip);
1364 1475
1365 if ((err = snd_card_register(card)) < 0) { 1476 if ((err = snd_card_register(card)) < 0) {