diff options
Diffstat (limited to 'sound/pci/ca0106/ca0106_main.c')
-rw-r--r-- | sound/pci/ca0106/ca0106_main.c | 123 |
1 files changed, 116 insertions, 7 deletions
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index ba07960921d8..ee58d16002e5 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -281,7 +281,7 @@ int snd_ca0106_i2c_write(ca0106_t *emu, | |||
281 | int retry; | 281 | int retry; |
282 | if ((reg > 0x7f) || (value > 0x1ff)) | 282 | if ((reg > 0x7f) || (value > 0x1ff)) |
283 | { | 283 | { |
284 | snd_printk("i2c_write: invalid values.\n"); | 284 | snd_printk(KERN_ERR "i2c_write: invalid values.\n"); |
285 | return -EINVAL; | 285 | return -EINVAL; |
286 | } | 286 | } |
287 | 287 | ||
@@ -319,7 +319,7 @@ int snd_ca0106_i2c_write(ca0106_t *emu, | |||
319 | 319 | ||
320 | if(retry==10) | 320 | if(retry==10) |
321 | { | 321 | { |
322 | snd_printk("Writing to ADC failed!\n"); | 322 | snd_printk(KERN_ERR "Writing to ADC failed!\n"); |
323 | return -EINVAL; | 323 | return -EINVAL; |
324 | } | 324 | } |
325 | 325 | ||
@@ -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 | ||
341 | static 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 | |||
341 | static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime) | 353 | static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime) |
342 | { | 354 | { |
343 | kfree(runtime->private_data); | 355 | kfree(runtime->private_data); |
@@ -421,7 +433,7 @@ static int snd_ca0106_pcm_open_capture_channel(snd_pcm_substream_t *substream, i | |||
421 | 433 | ||
422 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); | 434 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); |
423 | if (epcm == NULL) { | 435 | if (epcm == NULL) { |
424 | snd_printk("open_capture_channel: failed epcm alloc\n"); | 436 | snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n"); |
425 | return -ENOMEM; | 437 | return -ENOMEM; |
426 | } | 438 | } |
427 | epcm->emu = chip; | 439 | epcm->emu = chip; |
@@ -969,10 +981,8 @@ static int snd_ca0106_free(ca0106_t *chip) | |||
969 | #endif | 981 | #endif |
970 | 982 | ||
971 | // release the i/o port | 983 | // release the i/o port |
972 | if (chip->res_port) { | 984 | release_and_free_resource(chip->res_port); |
973 | release_resource(chip->res_port); | 985 | |
974 | kfree_nocheck(chip->res_port); | ||
975 | } | ||
976 | // release the irq | 986 | // release the irq |
977 | if (chip->irq >= 0) | 987 | if (chip->irq >= 0) |
978 | free_irq(chip->irq, (void *)chip); | 988 | free_irq(chip->irq, (void *)chip); |
@@ -1042,6 +1052,15 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id, | |||
1042 | 1052 | ||
1043 | snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76); | 1053 | snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76); |
1044 | 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 | |||
1045 | // acknowledge the interrupt if necessary | 1064 | // acknowledge the interrupt if necessary |
1046 | outl(status, chip->port+IPR); | 1065 | outl(status, chip->port+IPR); |
1047 | 1066 | ||
@@ -1311,6 +1330,88 @@ static int __devinit snd_ca0106_create(snd_card_t *card, | |||
1311 | return 0; | 1330 | return 0; |
1312 | } | 1331 | } |
1313 | 1332 | ||
1333 | |||
1334 | static void ca0106_midi_interrupt_enable(ca_midi_t *midi, int intr) | ||
1335 | { | ||
1336 | snd_ca0106_intr_enable((ca0106_t *)(midi->dev_id), intr); | ||
1337 | } | ||
1338 | |||
1339 | static void ca0106_midi_interrupt_disable(ca_midi_t *midi, int intr) | ||
1340 | { | ||
1341 | snd_ca0106_intr_disable((ca0106_t *)(midi->dev_id), intr); | ||
1342 | } | ||
1343 | |||
1344 | static unsigned char ca0106_midi_read(ca_midi_t *midi, int idx) | ||
1345 | { | ||
1346 | return (unsigned char)snd_ca0106_ptr_read((ca0106_t *)(midi->dev_id), midi->port + idx, 0); | ||
1347 | } | ||
1348 | |||
1349 | static void ca0106_midi_write(ca_midi_t *midi, int data, int idx) | ||
1350 | { | ||
1351 | snd_ca0106_ptr_write((ca0106_t *)(midi->dev_id), midi->port + idx, 0, data); | ||
1352 | } | ||
1353 | |||
1354 | static snd_card_t *ca0106_dev_id_card(void *dev_id) | ||
1355 | { | ||
1356 | return ((ca0106_t *)dev_id)->card; | ||
1357 | } | ||
1358 | |||
1359 | static int ca0106_dev_id_port(void *dev_id) | ||
1360 | { | ||
1361 | return ((ca0106_t *)dev_id)->port; | ||
1362 | } | ||
1363 | |||
1364 | static int __devinit snd_ca0106_midi(ca0106_t *chip, unsigned int channel) | ||
1365 | { | ||
1366 | ca_midi_t *midi; | ||
1367 | char *name; | ||
1368 | int err; | ||
1369 | |||
1370 | if(channel==CA0106_MIDI_CHAN_B) { | ||
1371 | name = "CA0106 MPU-401 (UART) B"; | ||
1372 | midi = &chip->midi2; | ||
1373 | midi->tx_enable = INTE_MIDI_TX_B; | ||
1374 | midi->rx_enable = INTE_MIDI_RX_B; | ||
1375 | midi->ipr_tx = IPR_MIDI_TX_B; | ||
1376 | midi->ipr_rx = IPR_MIDI_RX_B; | ||
1377 | midi->port = MIDI_UART_B_DATA; | ||
1378 | } else { | ||
1379 | name = "CA0106 MPU-401 (UART)"; | ||
1380 | midi = &chip->midi; | ||
1381 | midi->tx_enable = INTE_MIDI_TX_A; | ||
1382 | midi->rx_enable = INTE_MIDI_TX_B; | ||
1383 | midi->ipr_tx = IPR_MIDI_TX_A; | ||
1384 | midi->ipr_rx = IPR_MIDI_RX_A; | ||
1385 | midi->port = MIDI_UART_A_DATA; | ||
1386 | } | ||
1387 | |||
1388 | midi->reset = CA0106_MPU401_RESET; | ||
1389 | midi->enter_uart = CA0106_MPU401_ENTER_UART; | ||
1390 | midi->ack = CA0106_MPU401_ACK; | ||
1391 | |||
1392 | midi->input_avail = CA0106_MIDI_INPUT_AVAIL; | ||
1393 | midi->output_ready = CA0106_MIDI_OUTPUT_READY; | ||
1394 | |||
1395 | midi->channel = channel; | ||
1396 | |||
1397 | midi->interrupt_enable = ca0106_midi_interrupt_enable; | ||
1398 | midi->interrupt_disable = ca0106_midi_interrupt_disable; | ||
1399 | |||
1400 | midi->read = ca0106_midi_read; | ||
1401 | midi->write = ca0106_midi_write; | ||
1402 | |||
1403 | midi->get_dev_id_card = ca0106_dev_id_card; | ||
1404 | midi->get_dev_id_port = ca0106_dev_id_port; | ||
1405 | |||
1406 | midi->dev_id = chip; | ||
1407 | |||
1408 | if ((err = ca_midi_init(chip, midi, 0, name)) < 0) | ||
1409 | return err; | ||
1410 | |||
1411 | return 0; | ||
1412 | } | ||
1413 | |||
1414 | |||
1314 | static int __devinit snd_ca0106_probe(struct pci_dev *pci, | 1415 | static int __devinit snd_ca0106_probe(struct pci_dev *pci, |
1315 | const struct pci_device_id *pci_id) | 1416 | const struct pci_device_id *pci_id) |
1316 | { | 1417 | { |
@@ -1362,6 +1463,14 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1362 | return err; | 1463 | return err; |
1363 | } | 1464 | } |
1364 | 1465 | ||
1466 | snd_printdd("ca0106: probe for MIDI channel A ..."); | ||
1467 | if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) { | ||
1468 | snd_card_free(card); | ||
1469 | snd_printdd(" failed, err=0x%x\n",err); | ||
1470 | return err; | ||
1471 | } | ||
1472 | snd_printdd(" done.\n"); | ||
1473 | |||
1365 | snd_ca0106_proc_init(chip); | 1474 | snd_ca0106_proc_init(chip); |
1366 | 1475 | ||
1367 | if ((err = snd_card_register(card)) < 0) { | 1476 | if ((err = snd_card_register(card)) < 0) { |