summaryrefslogtreecommitdiffstats
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.c197
1 files changed, 102 insertions, 95 deletions
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 493e3946756..e760adad952 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -41,7 +41,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/math64.h>
@@ -520,16 +520,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
-/* revisions >= 230 indicate AES32 card */
-#define HDSPM_MADI_ANCIENT_REV 204
-#define HDSPM_MADI_OLD_REV 207
-#define HDSPM_MADI_REV 210
#define HDSPM_RAYDAT_REV 211
#define HDSPM_AIO_REV 212
#define HDSPM_MADIFACE_REV 213
-#define HDSPM_AES_REV 240
-#define HDSPM_AES32_REV 234
-#define HDSPM_AES32_OLD_REV 233
/* speed factor modes */
#define HDSPM_SPEED_SINGLE 0
@@ -1241,10 +1234,30 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
return rate;
}
+/* return latency in samples per period */
+static int hdspm_get_latency(struct hdspm *hdspm)
+{
+ int n;
+
+ n = hdspm_decode_latency(hdspm->control_register);
+
+ /* Special case for new RME cards with 32 samples period size.
+ * The three latency bits in the control register
+ * (HDSP_LatencyMask) encode latency values of 64 samples as
+ * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
+ * denotes 8192 samples, but on new cards like RayDAT or AIO,
+ * it corresponds to 32 samples.
+ */
+ if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
+ n = -1;
+
+ return 1 << (n + 6);
+}
+
/* Latency function */
static inline void hdspm_compute_period_size(struct hdspm *hdspm)
{
- hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
+ hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
}
@@ -1303,12 +1316,27 @@ static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
spin_lock_irq(&s->lock);
- frames >>= 7;
- n = 0;
- while (frames) {
- n++;
- frames >>= 1;
+ if (32 == frames) {
+ /* Special case for new RME cards like RayDAT/AIO which
+ * support period sizes of 32 samples. Since latency is
+ * encoded in the three bits of HDSP_LatencyMask, we can only
+ * have values from 0 .. 7. While 0 still means 64 samples and
+ * 6 represents 4096 samples on all cards, 7 represents 8192
+ * on older cards and 32 samples on new cards.
+ *
+ * In other words, period size in samples is calculated by
+ * 2^(n+6) with n ranging from 0 .. 7.
+ */
+ n = 7;
+ } else {
+ frames >>= 7;
+ n = 0;
+ while (frames) {
+ n++;
+ frames >>= 1;
+ }
}
+
s->control_register &= ~HDSPM_LatencyMask;
s->control_register |= hdspm_encode_latency(n);
@@ -4801,8 +4829,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
snd_iprintf(buffer, "--- Settings ---\n");
- x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
- HDSPM_LatencyMask));
+ x = hdspm_get_latency(hdspm);
snd_iprintf(buffer,
"Size (Latency): %d samples (2 periods of %lu bytes)\n",
@@ -4965,8 +4992,7 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
snd_iprintf(buffer, "--- Settings ---\n");
- x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
- HDSPM_LatencyMask));
+ x = hdspm_get_latency(hdspm);
snd_iprintf(buffer,
"Size (Latency): %d samples (2 periods of %lu bytes)\n",
@@ -5672,19 +5698,6 @@ static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
return 0;
}
-static unsigned int period_sizes_old[] = {
- 64, 128, 256, 512, 1024, 2048, 4096
-};
-
-static unsigned int period_sizes_new[] = {
- 32, 64, 128, 256, 512, 1024, 2048, 4096
-};
-
-/* RayDAT and AIO always have a buffer of 16384 samples per channel */
-static unsigned int raydat_aio_buffer_sizes[] = {
- 16384
-};
-
static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -5703,8 +5716,8 @@ static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
.channels_max = HDSPM_MAX_CHANNELS,
.buffer_bytes_max =
HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
- .period_bytes_min = (64 * 4),
- .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
+ .period_bytes_min = (32 * 4),
+ .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
.periods_min = 2,
.periods_max = 512,
.fifo_size = 0
@@ -5728,31 +5741,13 @@ static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
.channels_max = HDSPM_MAX_CHANNELS,
.buffer_bytes_max =
HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
- .period_bytes_min = (64 * 4),
- .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
+ .period_bytes_min = (32 * 4),
+ .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
.periods_min = 2,
.periods_max = 512,
.fifo_size = 0
};
-static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = {
- .count = ARRAY_SIZE(period_sizes_old),
- .list = period_sizes_old,
- .mask = 0
-};
-
-static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = {
- .count = ARRAY_SIZE(period_sizes_new),
- .list = period_sizes_new,
- .mask = 0
-};
-
-static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = {
- .count = ARRAY_SIZE(raydat_aio_buffer_sizes),
- .list = raydat_aio_buffer_sizes,
- .mask = 0
-};
-
static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
@@ -5953,26 +5948,29 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
spin_unlock_irq(&hdspm->lock);
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+ snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
switch (hdspm->io_type) {
case AIO:
case RayDAT:
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- &hw_constraints_period_sizes_new);
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
- &hw_constraints_raydat_io_buffer);
-
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ 32, 4096);
+ /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+ 16384, 16384);
break;
default:
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- &hw_constraints_period_sizes_old);
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ 64, 8192);
+ break;
}
if (AES32 == hdspm->io_type) {
+ runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&hdspm_hw_constraints_aes32_sample_rates);
} else {
@@ -6025,24 +6023,28 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
spin_unlock_irq(&hdspm->lock);
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+ snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+
switch (hdspm->io_type) {
case AIO:
case RayDAT:
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- &hw_constraints_period_sizes_new);
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
- &hw_constraints_raydat_io_buffer);
- break;
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ 32, 4096);
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+ 16384, 16384);
+ break;
default:
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- &hw_constraints_period_sizes_old);
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ 64, 8192);
+ break;
}
if (AES32 == hdspm->io_type) {
+ runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&hdspm_hw_constraints_aes32_sample_rates);
} else {
@@ -6088,7 +6090,7 @@ static inline int copy_u32_le(void __user *dest, void __iomem *src)
}
static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
- unsigned int cmd, unsigned long __user arg)
+ unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
struct hdspm *hdspm = hw->private_data;
@@ -6213,11 +6215,13 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
info.line_out = hdspm_line_out(hdspm);
info.passthru = 0;
spin_unlock_irq(&hdspm->lock);
- if (copy_to_user((void __user *) arg, &info, sizeof(info)))
+ if (copy_to_user(argp, &info, sizeof(info)))
return -EFAULT;
break;
case SNDRV_HDSPM_IOCTL_GET_STATUS:
+ memset(&status, 0, sizeof(status));
+
status.card_type = hdspm->io_type;
status.autosync_source = hdspm_autosync_ref(hdspm);
@@ -6242,7 +6246,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
status.card_specific.madi.madi_input =
(statusregister & HDSPM_AB_int) ? 1 : 0;
status.card_specific.madi.channel_format =
- (statusregister & HDSPM_TX_64ch) ? 1 : 0;
+ (statusregister & HDSPM_RX_64ch) ? 1 : 0;
/* TODO: Mac driver sets it when f_s>48kHz */
status.card_specific.madi.frame_format = 0;
@@ -6250,13 +6254,15 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
break;
}
- if (copy_to_user((void __user *) arg, &status, sizeof(status)))
+ if (copy_to_user(argp, &status, sizeof(status)))
return -EFAULT;
break;
case SNDRV_HDSPM_IOCTL_GET_VERSION:
+ memset(&hdspm_version, 0, sizeof(hdspm_version));
+
hdspm_version.card_type = hdspm->io_type;
strncpy(hdspm_version.cardname, hdspm->card_name,
sizeof(hdspm_version.cardname));
@@ -6267,13 +6273,13 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
if (hdspm->tco)
hdspm_version.addons |= HDSPM_ADDON_TCO;
- if (copy_to_user((void __user *) arg, &hdspm_version,
+ if (copy_to_user(argp, &hdspm_version,
sizeof(hdspm_version)))
return -EFAULT;
break;
case SNDRV_HDSPM_IOCTL_GET_MIXER:
- if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
+ if (copy_from_user(&mixer, argp, sizeof(mixer)))
return -EFAULT;
if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
sizeof(struct hdspm_mixer)))
@@ -6490,13 +6496,6 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
strcpy(card->driver, "HDSPM");
switch (hdspm->firmware_rev) {
- case HDSPM_MADI_REV:
- case HDSPM_MADI_OLD_REV:
- case HDSPM_MADI_ANCIENT_REV:
- hdspm->io_type = MADI;
- hdspm->card_name = "RME MADI";
- hdspm->midiPorts = 3;
- break;
case HDSPM_RAYDAT_REV:
hdspm->io_type = RayDAT;
hdspm->card_name = "RME RayDAT";
@@ -6512,17 +6511,25 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
hdspm->card_name = "RME MADIface";
hdspm->midiPorts = 1;
break;
- case HDSPM_AES_REV:
- case HDSPM_AES32_REV:
- case HDSPM_AES32_OLD_REV:
- hdspm->io_type = AES32;
- hdspm->card_name = "RME AES32";
- hdspm->midiPorts = 2;
- break;
default:
- snd_printk(KERN_ERR "HDSPM: unknown firmware revision %x\n",
+ if ((hdspm->firmware_rev == 0xf0) ||
+ ((hdspm->firmware_rev >= 0xe6) &&
+ (hdspm->firmware_rev <= 0xea))) {
+ hdspm->io_type = AES32;
+ hdspm->card_name = "RME AES32";
+ hdspm->midiPorts = 2;
+ } else if ((hdspm->firmware_rev == 0xd5) ||
+ ((hdspm->firmware_rev >= 0xc8) &&
+ (hdspm->firmware_rev <= 0xcf))) {
+ hdspm->io_type = MADI;
+ hdspm->card_name = "RME MADI";
+ hdspm->midiPorts = 3;
+ } else {
+ snd_printk(KERN_ERR
+ "HDSPM: unknown firmware revision %x\n",
hdspm->firmware_rev);
- return -ENODEV;
+ return -ENODEV;
+ }
}
err = pci_enable_device(pci);