aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/rme9652/hdspm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/rme9652/hdspm.c')
-rw-r--r--sound/pci/rme9652/hdspm.c132
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
3451static 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
3460static 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
3478static 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
3496static 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
3507static 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
4308static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { 4419static 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
6781static struct pci_driver driver = { 6893static 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),