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.c109
1 files changed, 107 insertions, 2 deletions
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index af130ee0c45d..6edc67ced905 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 }
@@ -3415,6 +3432,91 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3415 return change; 3432 return change;
3416} 3433}
3417 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
3444static 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
3453static 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
3471static 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
3489static 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
3500static 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}
3418 3520
3419#define HDSPM_MIXER(xname, xindex) \ 3521#define HDSPM_MIXER(xname, xindex) \
3420{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 3522{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
@@ -4289,7 +4391,8 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
4289 HDSPM_TX_64("TX 64 channels mode", 0), 4391 HDSPM_TX_64("TX 64 channels mode", 0),
4290 HDSPM_C_TMS("Clear Track Marker", 0), 4392 HDSPM_C_TMS("Clear Track Marker", 0),
4291 HDSPM_SAFE_MODE("Safe Mode", 0), 4393 HDSPM_SAFE_MODE("Safe Mode", 0),
4292 HDSPM_INPUT_SELECT("Input Select", 0) 4394 HDSPM_INPUT_SELECT("Input Select", 0),
4395 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
4293}; 4396};
4294 4397
4295 4398
@@ -4302,7 +4405,8 @@ static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4302 HDSPM_SYNC_CHECK("MADI SyncCheck", 0), 4405 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
4303 HDSPM_TX_64("TX 64 channels mode", 0), 4406 HDSPM_TX_64("TX 64 channels mode", 0),
4304 HDSPM_C_TMS("Clear Track Marker", 0), 4407 HDSPM_C_TMS("Clear Track Marker", 0),
4305 HDSPM_SAFE_MODE("Safe Mode", 0) 4408 HDSPM_SAFE_MODE("Safe Mode", 0),
4409 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
4306}; 4410};
4307 4411
4308static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { 4412static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
@@ -6381,6 +6485,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
6381 switch (hdspm->firmware_rev) { 6485 switch (hdspm->firmware_rev) {
6382 case HDSPM_MADI_REV: 6486 case HDSPM_MADI_REV:
6383 case HDSPM_MADI_OLD_REV: 6487 case HDSPM_MADI_OLD_REV:
6488 case HDSPM_MADI_ANCIENT_REV:
6384 hdspm->io_type = MADI; 6489 hdspm->io_type = MADI;
6385 hdspm->card_name = "RME MADI"; 6490 hdspm->card_name = "RME MADI";
6386 hdspm->midiPorts = 3; 6491 hdspm->midiPorts = 3;