diff options
Diffstat (limited to 'sound/pci/rme9652/hdspm.c')
-rw-r--r-- | sound/pci/rme9652/hdspm.c | 132 |
1 files changed, 122 insertions, 10 deletions
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index c8e402fc378..493e3946756 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -521,6 +521,7 @@ 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 | ||
524 | #define HDSPM_MADI_OLD_REV 207 | 525 | #define HDSPM_MADI_OLD_REV 207 |
525 | #define HDSPM_MADI_REV 210 | 526 | #define HDSPM_MADI_REV 210 |
526 | #define HDSPM_RAYDAT_REV 211 | 527 | #define HDSPM_RAYDAT_REV 211 |
@@ -1217,6 +1218,22 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
1217 | rate = 0; | 1218 | rate = 0; |
1218 | break; | 1219 | break; |
1219 | } | 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 | } | ||
1220 | } | 1237 | } |
1221 | break; | 1238 | break; |
1222 | } | 1239 | } |
@@ -1322,6 +1339,10 @@ static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period) | |||
1322 | break; | 1339 | break; |
1323 | case MADIface: | 1340 | case MADIface: |
1324 | freq_const = 131072000000000ULL; | 1341 | freq_const = 131072000000000ULL; |
1342 | break; | ||
1343 | default: | ||
1344 | snd_BUG(); | ||
1345 | return 0; | ||
1325 | } | 1346 | } |
1326 | 1347 | ||
1327 | return div_u64(freq_const, period); | 1348 | return div_u64(freq_const, period); |
@@ -1339,16 +1360,19 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) | |||
1339 | 1360 | ||
1340 | switch (hdspm->io_type) { | 1361 | switch (hdspm->io_type) { |
1341 | case MADIface: | 1362 | case MADIface: |
1342 | n = 131072000000000ULL; /* 125 MHz */ | 1363 | n = 131072000000000ULL; /* 125 MHz */ |
1343 | break; | 1364 | break; |
1344 | case MADI: | 1365 | case MADI: |
1345 | case AES32: | 1366 | case AES32: |
1346 | n = 110069313433624ULL; /* 105 MHz */ | 1367 | n = 110069313433624ULL; /* 105 MHz */ |
1347 | break; | 1368 | break; |
1348 | case RayDAT: | 1369 | case RayDAT: |
1349 | case AIO: | 1370 | case AIO: |
1350 | n = 104857600000000ULL; /* 100 MHz */ | 1371 | n = 104857600000000ULL; /* 100 MHz */ |
1351 | break; | 1372 | break; |
1373 | default: | ||
1374 | snd_BUG(); | ||
1375 | return; | ||
1352 | } | 1376 | } |
1353 | 1377 | ||
1354 | n = div_u64(n, rate); | 1378 | n = div_u64(n, rate); |
@@ -3415,6 +3439,91 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol, | |||
3415 | return change; | 3439 | return change; |
3416 | } | 3440 | } |
3417 | 3441 | ||
3442 | #define HDSPM_MADI_SPEEDMODE(xname, xindex) \ | ||
3443 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3444 | .name = xname, \ | ||
3445 | .index = xindex, \ | ||
3446 | .info = snd_hdspm_info_madi_speedmode, \ | ||
3447 | .get = snd_hdspm_get_madi_speedmode, \ | ||
3448 | .put = snd_hdspm_put_madi_speedmode \ | ||
3449 | } | ||
3450 | |||
3451 | static int hdspm_madi_speedmode(struct hdspm *hdspm) | ||
3452 | { | ||
3453 | if (hdspm->control_register & HDSPM_QuadSpeed) | ||
3454 | return 2; | ||
3455 | if (hdspm->control_register & HDSPM_DoubleSpeed) | ||
3456 | return 1; | ||
3457 | return 0; | ||
3458 | } | ||
3459 | |||
3460 | static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode) | ||
3461 | { | ||
3462 | hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed); | ||
3463 | switch (mode) { | ||
3464 | case 0: | ||
3465 | break; | ||
3466 | case 1: | ||
3467 | hdspm->control_register |= HDSPM_DoubleSpeed; | ||
3468 | break; | ||
3469 | case 2: | ||
3470 | hdspm->control_register |= HDSPM_QuadSpeed; | ||
3471 | break; | ||
3472 | } | ||
3473 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
3474 | |||
3475 | return 0; | ||
3476 | } | ||
3477 | |||
3478 | static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol, | ||
3479 | struct snd_ctl_elem_info *uinfo) | ||
3480 | { | ||
3481 | static char *texts[] = { "Single", "Double", "Quad" }; | ||
3482 | |||
3483 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3484 | uinfo->count = 1; | ||
3485 | uinfo->value.enumerated.items = 3; | ||
3486 | |||
3487 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3488 | uinfo->value.enumerated.item = | ||
3489 | uinfo->value.enumerated.items - 1; | ||
3490 | strcpy(uinfo->value.enumerated.name, | ||
3491 | texts[uinfo->value.enumerated.item]); | ||
3492 | |||
3493 | return 0; | ||
3494 | } | ||
3495 | |||
3496 | static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol, | ||
3497 | struct snd_ctl_elem_value *ucontrol) | ||
3498 | { | ||
3499 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3500 | |||
3501 | spin_lock_irq(&hdspm->lock); | ||
3502 | ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm); | ||
3503 | spin_unlock_irq(&hdspm->lock); | ||
3504 | return 0; | ||
3505 | } | ||
3506 | |||
3507 | static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol, | ||
3508 | struct snd_ctl_elem_value *ucontrol) | ||
3509 | { | ||
3510 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3511 | int change; | ||
3512 | int val; | ||
3513 | |||
3514 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
3515 | return -EBUSY; | ||
3516 | val = ucontrol->value.integer.value[0]; | ||
3517 | if (val < 0) | ||
3518 | val = 0; | ||
3519 | if (val > 2) | ||
3520 | val = 2; | ||
3521 | spin_lock_irq(&hdspm->lock); | ||
3522 | change = val != hdspm_madi_speedmode(hdspm); | ||
3523 | hdspm_set_madi_speedmode(hdspm, val); | ||
3524 | spin_unlock_irq(&hdspm->lock); | ||
3525 | return change; | ||
3526 | } | ||
3418 | 3527 | ||
3419 | #define HDSPM_MIXER(xname, xindex) \ | 3528 | #define HDSPM_MIXER(xname, xindex) \ |
3420 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | 3529 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ |
@@ -4289,7 +4398,8 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { | |||
4289 | HDSPM_TX_64("TX 64 channels mode", 0), | 4398 | HDSPM_TX_64("TX 64 channels mode", 0), |
4290 | HDSPM_C_TMS("Clear Track Marker", 0), | 4399 | HDSPM_C_TMS("Clear Track Marker", 0), |
4291 | HDSPM_SAFE_MODE("Safe Mode", 0), | 4400 | HDSPM_SAFE_MODE("Safe Mode", 0), |
4292 | HDSPM_INPUT_SELECT("Input Select", 0) | 4401 | HDSPM_INPUT_SELECT("Input Select", 0), |
4402 | HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0) | ||
4293 | }; | 4403 | }; |
4294 | 4404 | ||
4295 | 4405 | ||
@@ -4302,7 +4412,8 @@ static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = { | |||
4302 | HDSPM_SYNC_CHECK("MADI SyncCheck", 0), | 4412 | HDSPM_SYNC_CHECK("MADI SyncCheck", 0), |
4303 | HDSPM_TX_64("TX 64 channels mode", 0), | 4413 | HDSPM_TX_64("TX 64 channels mode", 0), |
4304 | HDSPM_C_TMS("Clear Track Marker", 0), | 4414 | HDSPM_C_TMS("Clear Track Marker", 0), |
4305 | HDSPM_SAFE_MODE("Safe Mode", 0) | 4415 | HDSPM_SAFE_MODE("Safe Mode", 0), |
4416 | HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0) | ||
4306 | }; | 4417 | }; |
4307 | 4418 | ||
4308 | static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { | 4419 | static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { |
@@ -6381,6 +6492,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
6381 | switch (hdspm->firmware_rev) { | 6492 | switch (hdspm->firmware_rev) { |
6382 | case HDSPM_MADI_REV: | 6493 | case HDSPM_MADI_REV: |
6383 | case HDSPM_MADI_OLD_REV: | 6494 | case HDSPM_MADI_OLD_REV: |
6495 | case HDSPM_MADI_ANCIENT_REV: | ||
6384 | hdspm->io_type = MADI; | 6496 | hdspm->io_type = MADI; |
6385 | hdspm->card_name = "RME MADI"; | 6497 | hdspm->card_name = "RME MADI"; |
6386 | hdspm->midiPorts = 3; | 6498 | hdspm->midiPorts = 3; |
@@ -6441,7 +6553,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
6441 | hdspm->port + io_extent - 1); | 6553 | hdspm->port + io_extent - 1); |
6442 | 6554 | ||
6443 | if (request_irq(pci->irq, snd_hdspm_interrupt, | 6555 | if (request_irq(pci->irq, snd_hdspm_interrupt, |
6444 | IRQF_SHARED, "hdspm", hdspm)) { | 6556 | IRQF_SHARED, KBUILD_MODNAME, hdspm)) { |
6445 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); | 6557 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); |
6446 | return -EBUSY; | 6558 | return -EBUSY; |
6447 | } | 6559 | } |
@@ -6779,7 +6891,7 @@ static void __devexit snd_hdspm_remove(struct pci_dev *pci) | |||
6779 | } | 6891 | } |
6780 | 6892 | ||
6781 | static struct pci_driver driver = { | 6893 | static struct pci_driver driver = { |
6782 | .name = "RME Hammerfall DSP MADI", | 6894 | .name = KBUILD_MODNAME, |
6783 | .id_table = snd_hdspm_ids, | 6895 | .id_table = snd_hdspm_ids, |
6784 | .probe = snd_hdspm_probe, | 6896 | .probe = snd_hdspm_probe, |
6785 | .remove = __devexit_p(snd_hdspm_remove), | 6897 | .remove = __devexit_p(snd_hdspm_remove), |