diff options
Diffstat (limited to 'sound/pci/rme9652/hdspm.c')
-rw-r--r-- | sound/pci/rme9652/hdspm.c | 129 |
1 files changed, 119 insertions, 10 deletions
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 949691a876d..6edc67ced90 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -521,6 +521,8 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
521 | #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) | 521 | #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) |
522 | 522 | ||
523 | /* revisions >= 230 indicate AES32 card */ | 523 | /* revisions >= 230 indicate AES32 card */ |
524 | #define HDSPM_MADI_ANCIENT_REV 204 | ||
525 | #define HDSPM_MADI_OLD_REV 207 | ||
524 | #define HDSPM_MADI_REV 210 | 526 | #define HDSPM_MADI_REV 210 |
525 | #define HDSPM_RAYDAT_REV 211 | 527 | #define HDSPM_RAYDAT_REV 211 |
526 | #define HDSPM_AIO_REV 212 | 528 | #define HDSPM_AIO_REV 212 |
@@ -895,11 +897,11 @@ struct hdspm { | |||
895 | unsigned char max_channels_in; | 897 | unsigned char max_channels_in; |
896 | unsigned char max_channels_out; | 898 | unsigned char max_channels_out; |
897 | 899 | ||
898 | char *channel_map_in; | 900 | signed char *channel_map_in; |
899 | char *channel_map_out; | 901 | signed char *channel_map_out; |
900 | 902 | ||
901 | char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; | 903 | signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; |
902 | char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; | 904 | signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; |
903 | 905 | ||
904 | char **port_names_in; | 906 | char **port_names_in; |
905 | char **port_names_out; | 907 | char **port_names_out; |
@@ -1143,7 +1145,7 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
1143 | 1145 | ||
1144 | /* if wordclock has synced freq and wordclock is valid */ | 1146 | /* if wordclock has synced freq and wordclock is valid */ |
1145 | if ((status2 & HDSPM_wcLock) != 0 && | 1147 | if ((status2 & HDSPM_wcLock) != 0 && |
1146 | (status & HDSPM_SelSyncRef0) == 0) { | 1148 | (status2 & HDSPM_SelSyncRef0) == 0) { |
1147 | 1149 | ||
1148 | rate_bits = status2 & HDSPM_wcFreqMask; | 1150 | rate_bits = status2 & HDSPM_wcFreqMask; |
1149 | 1151 | ||
@@ -1216,6 +1218,22 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
1216 | rate = 0; | 1218 | rate = 0; |
1217 | break; | 1219 | break; |
1218 | } | 1220 | } |
1221 | |||
1222 | /* QS and DS rates normally can not be detected | ||
1223 | * automatically by the card. Only exception is MADI | ||
1224 | * in 96k frame mode. | ||
1225 | * | ||
1226 | * So if we read SS values (32 .. 48k), check for | ||
1227 | * user-provided DS/QS bits in the control register | ||
1228 | * and multiply the base frequency accordingly. | ||
1229 | */ | ||
1230 | if (rate <= 48000) { | ||
1231 | if (hdspm->control_register & HDSPM_QuadSpeed) | ||
1232 | rate *= 4; | ||
1233 | else if (hdspm->control_register & | ||
1234 | HDSPM_DoubleSpeed) | ||
1235 | rate *= 2; | ||
1236 | } | ||
1219 | } | 1237 | } |
1220 | break; | 1238 | break; |
1221 | } | 1239 | } |
@@ -1639,12 +1657,14 @@ static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) | |||
1639 | } | 1657 | } |
1640 | } | 1658 | } |
1641 | hmidi->pending = 0; | 1659 | hmidi->pending = 0; |
1660 | spin_unlock_irqrestore(&hmidi->lock, flags); | ||
1642 | 1661 | ||
1662 | spin_lock_irqsave(&hmidi->hdspm->lock, flags); | ||
1643 | hmidi->hdspm->control_register |= hmidi->ie; | 1663 | hmidi->hdspm->control_register |= hmidi->ie; |
1644 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, | 1664 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, |
1645 | hmidi->hdspm->control_register); | 1665 | hmidi->hdspm->control_register); |
1666 | spin_unlock_irqrestore(&hmidi->hdspm->lock, flags); | ||
1646 | 1667 | ||
1647 | spin_unlock_irqrestore (&hmidi->lock, flags); | ||
1648 | return snd_hdspm_midi_output_write (hmidi); | 1668 | return snd_hdspm_midi_output_write (hmidi); |
1649 | } | 1669 | } |
1650 | 1670 | ||
@@ -3412,6 +3432,91 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol, | |||
3412 | return change; | 3432 | return change; |
3413 | } | 3433 | } |
3414 | 3434 | ||
3435 | #define HDSPM_MADI_SPEEDMODE(xname, xindex) \ | ||
3436 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3437 | .name = xname, \ | ||
3438 | .index = xindex, \ | ||
3439 | .info = snd_hdspm_info_madi_speedmode, \ | ||
3440 | .get = snd_hdspm_get_madi_speedmode, \ | ||
3441 | .put = snd_hdspm_put_madi_speedmode \ | ||
3442 | } | ||
3443 | |||
3444 | static int hdspm_madi_speedmode(struct hdspm *hdspm) | ||
3445 | { | ||
3446 | if (hdspm->control_register & HDSPM_QuadSpeed) | ||
3447 | return 2; | ||
3448 | if (hdspm->control_register & HDSPM_DoubleSpeed) | ||
3449 | return 1; | ||
3450 | return 0; | ||
3451 | } | ||
3452 | |||
3453 | static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode) | ||
3454 | { | ||
3455 | hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed); | ||
3456 | switch (mode) { | ||
3457 | case 0: | ||
3458 | break; | ||
3459 | case 1: | ||
3460 | hdspm->control_register |= HDSPM_DoubleSpeed; | ||
3461 | break; | ||
3462 | case 2: | ||
3463 | hdspm->control_register |= HDSPM_QuadSpeed; | ||
3464 | break; | ||
3465 | } | ||
3466 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
3467 | |||
3468 | return 0; | ||
3469 | } | ||
3470 | |||
3471 | static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol, | ||
3472 | struct snd_ctl_elem_info *uinfo) | ||
3473 | { | ||
3474 | static char *texts[] = { "Single", "Double", "Quad" }; | ||
3475 | |||
3476 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3477 | uinfo->count = 1; | ||
3478 | uinfo->value.enumerated.items = 3; | ||
3479 | |||
3480 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3481 | uinfo->value.enumerated.item = | ||
3482 | uinfo->value.enumerated.items - 1; | ||
3483 | strcpy(uinfo->value.enumerated.name, | ||
3484 | texts[uinfo->value.enumerated.item]); | ||
3485 | |||
3486 | return 0; | ||
3487 | } | ||
3488 | |||
3489 | static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol, | ||
3490 | struct snd_ctl_elem_value *ucontrol) | ||
3491 | { | ||
3492 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3493 | |||
3494 | spin_lock_irq(&hdspm->lock); | ||
3495 | ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm); | ||
3496 | spin_unlock_irq(&hdspm->lock); | ||
3497 | return 0; | ||
3498 | } | ||
3499 | |||
3500 | static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol, | ||
3501 | struct snd_ctl_elem_value *ucontrol) | ||
3502 | { | ||
3503 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3504 | int change; | ||
3505 | int val; | ||
3506 | |||
3507 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
3508 | return -EBUSY; | ||
3509 | val = ucontrol->value.integer.value[0]; | ||
3510 | if (val < 0) | ||
3511 | val = 0; | ||
3512 | if (val > 2) | ||
3513 | val = 2; | ||
3514 | spin_lock_irq(&hdspm->lock); | ||
3515 | change = val != hdspm_madi_speedmode(hdspm); | ||
3516 | hdspm_set_madi_speedmode(hdspm, val); | ||
3517 | spin_unlock_irq(&hdspm->lock); | ||
3518 | return change; | ||
3519 | } | ||
3415 | 3520 | ||
3416 | #define HDSPM_MIXER(xname, xindex) \ | 3521 | #define HDSPM_MIXER(xname, xindex) \ |
3417 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | 3522 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ |
@@ -4286,7 +4391,8 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { | |||
4286 | HDSPM_TX_64("TX 64 channels mode", 0), | 4391 | HDSPM_TX_64("TX 64 channels mode", 0), |
4287 | HDSPM_C_TMS("Clear Track Marker", 0), | 4392 | HDSPM_C_TMS("Clear Track Marker", 0), |
4288 | HDSPM_SAFE_MODE("Safe Mode", 0), | 4393 | HDSPM_SAFE_MODE("Safe Mode", 0), |
4289 | HDSPM_INPUT_SELECT("Input Select", 0) | 4394 | HDSPM_INPUT_SELECT("Input Select", 0), |
4395 | HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0) | ||
4290 | }; | 4396 | }; |
4291 | 4397 | ||
4292 | 4398 | ||
@@ -4299,7 +4405,8 @@ static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = { | |||
4299 | HDSPM_SYNC_CHECK("MADI SyncCheck", 0), | 4405 | HDSPM_SYNC_CHECK("MADI SyncCheck", 0), |
4300 | HDSPM_TX_64("TX 64 channels mode", 0), | 4406 | HDSPM_TX_64("TX 64 channels mode", 0), |
4301 | HDSPM_C_TMS("Clear Track Marker", 0), | 4407 | HDSPM_C_TMS("Clear Track Marker", 0), |
4302 | HDSPM_SAFE_MODE("Safe Mode", 0) | 4408 | HDSPM_SAFE_MODE("Safe Mode", 0), |
4409 | HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0) | ||
4303 | }; | 4410 | }; |
4304 | 4411 | ||
4305 | static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { | 4412 | static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { |
@@ -6377,6 +6484,8 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
6377 | 6484 | ||
6378 | switch (hdspm->firmware_rev) { | 6485 | switch (hdspm->firmware_rev) { |
6379 | case HDSPM_MADI_REV: | 6486 | case HDSPM_MADI_REV: |
6487 | case HDSPM_MADI_OLD_REV: | ||
6488 | case HDSPM_MADI_ANCIENT_REV: | ||
6380 | hdspm->io_type = MADI; | 6489 | hdspm->io_type = MADI; |
6381 | hdspm->card_name = "RME MADI"; | 6490 | hdspm->card_name = "RME MADI"; |
6382 | hdspm->midiPorts = 3; | 6491 | hdspm->midiPorts = 3; |
@@ -6437,7 +6546,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
6437 | hdspm->port + io_extent - 1); | 6546 | hdspm->port + io_extent - 1); |
6438 | 6547 | ||
6439 | if (request_irq(pci->irq, snd_hdspm_interrupt, | 6548 | if (request_irq(pci->irq, snd_hdspm_interrupt, |
6440 | IRQF_SHARED, "hdspm", hdspm)) { | 6549 | IRQF_SHARED, KBUILD_MODNAME, hdspm)) { |
6441 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); | 6550 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); |
6442 | return -EBUSY; | 6551 | return -EBUSY; |
6443 | } | 6552 | } |
@@ -6775,7 +6884,7 @@ static void __devexit snd_hdspm_remove(struct pci_dev *pci) | |||
6775 | } | 6884 | } |
6776 | 6885 | ||
6777 | static struct pci_driver driver = { | 6886 | static struct pci_driver driver = { |
6778 | .name = "RME Hammerfall DSP MADI", | 6887 | .name = KBUILD_MODNAME, |
6779 | .id_table = snd_hdspm_ids, | 6888 | .id_table = snd_hdspm_ids, |
6780 | .probe = snd_hdspm_probe, | 6889 | .probe = snd_hdspm_probe, |
6781 | .remove = __devexit_p(snd_hdspm_remove), | 6890 | .remove = __devexit_p(snd_hdspm_remove), |