This is a new version of the previous patch, but now also includes:
* use of udelay to force timed loops rather than count-based loops
* fix hdsp_is_9652()
* don't include unnecessary playback mixer controls for Multiface
* don't attempt to download firmware to HDSP9652 systems (its
not the right thing to do, apparently)
--p
Index: hdsp.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/rme9652/hdsp.c,v
retrieving revision 1.26
diff -u -u -r1.26 hdsp.c
--- hdsp.c 4 Mar 2003 16:47:35 -0000 1.26
+++ hdsp.c 4 Mar 2003 22:29:59 -0000
@@ -23,7 +23,6 @@
#include <sound/driver.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/pci.h>
@@ -42,13 +41,14 @@
#include "multiface_firmware.dat"
#include "digiface_firmware.dat"
+#include "multiface_firmware_rev11.dat"
+#include "digiface_firmware_rev11.dat"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable
precise pointer */
static int line_outs_monitor[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0}; /* Send
all inputs/playback to line outs */
-static int force_firmware[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0}; /* Force
firmware reload */
MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
@@ -65,19 +65,17 @@
MODULE_PARM(line_outs_monitor,"1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(line_outs_monitor, "Send all input and playback streams to line outs
by default.");
MODULE_PARM_SYNTAX(line_outs_monitor, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
-MODULE_PARM(force_firmware,"1-" __MODULE_STRING(SNDRV_CARDS) "i");
-MODULE_PARM_DESC(force_firmware, "Force a reload of the I/O box firmware");
-MODULE_PARM_SYNTAX(force_firmware, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
MODULE_AUTHOR("Paul Davis <[EMAIL PROTECTED]>");
MODULE_DESCRIPTION("RME Hammerfall DSP");
MODULE_LICENSE("GPL");
MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{RME,Hammerfall-DSP}}");
+MODULE_DEVICES("{{RME Hammerfall-DSP},"
+ "{RME HDSP-9652}}");
typedef enum {
Digiface,
- Multiface
-} HDSP_Type;
+ Multiface,
+} HDSP_IO_Type;
#define HDSP_MAX_CHANNELS 26
#define DIGIFACE_SS_CHANNELS 26
@@ -123,9 +121,9 @@
#define HDSP_playbackPeakLevel 4096 /* 26 * 32 bit values */
#define HDSP_inputPeakLevel 4224 /* 26 * 32 bit values */
-#define HDSP_outputPeakLevel 4100 /* 26 * 32 bit values */
+#define HDSP_outputPeakLevel 4352 /* 26 * 32 bit values */
#define HDSP_playbackRmsLevel 4612 /* 26 * 64 bit values */
-#define HDSP_inputRmsLevel 4884 /* 26 * 64 bit values */
+#define HDSP_inputRmsLevel 4868 /* 26 * 64 bit values */
#define HDSP_IO_EXTENT 5192
@@ -282,15 +280,11 @@
#define HDSP_SelSyncRef_WORD (HDSP_SelSyncRef2)
#define HDSP_SelSyncRef_ADAT_SYNC (HDSP_SelSyncRef0|HDSP_SelSyncRef2)
-/* FIFO wait times, defined in terms of loops on readl() */
+/* FIFO wait times, defined in terms of 1/10ths of msecs */
-#define HDSP_LONG_WAIT 40000
-#define HDSP_SHORT_WAIT 100
+#define HDSP_LONG_WAIT 5000
+#define HDSP_SHORT_WAIT 30
-/* Computing addresses for adjusting gains */
-
-#define INPUT_TO_OUTPUT_KEY(in,out) ((64 * (out)) + (in))
-#define PLAYBACK_TO_OUTPUT_KEY(chn,out) ((64 * (out)) + 32 + (chn))
#define UNITY_GAIN 32768
#define MINUS_INFINITY_GAIN 0
@@ -335,42 +329,43 @@
};
struct _hdsp {
- spinlock_t lock;
+ spinlock_t lock;
snd_pcm_substream_t *capture_substream;
snd_pcm_substream_t *playback_substream;
- hdsp_midi_t midi[2];
- int precise_ptr;
- u32 control_register; /* cached value */
- u32 creg_spdif;
- u32 creg_spdif_stream;
- char *card_name; /* digiface/multiface */
- HDSP_Type type; /* ditto, but for code use */
- size_t period_bytes; /* guess what this is */
- unsigned char ds_channels;
- unsigned char ss_channels; /* different for multiface/digiface */
- void *capture_buffer_unaligned; /* original buffer addresses */
- void *playback_buffer_unaligned; /* original buffer addresses */
- unsigned char *capture_buffer; /* suitably aligned address */
- unsigned char *playback_buffer; /* suitably aligned address */
- dma_addr_t capture_buffer_addr;
- dma_addr_t playback_buffer_addr;
- pid_t capture_pid;
- pid_t playback_pid;
- int running;
- int passthru; /* non-zero if doing pass-thru */
- int last_spdif_sample_rate; /* so that we can catch externally ... */
- int last_adat_sample_rate; /* ... induced rate changes */
- char *channel_map;
- int dev;
- int irq;
- unsigned long port;
- struct resource *res_port;
- unsigned long iobase;
- snd_card_t *card;
- snd_pcm_t *pcm;
- struct pci_dev *pci;
- snd_kcontrol_t *spdif_ctl;
- unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
+ hdsp_midi_t midi[2];
+ int precise_ptr;
+ u32 control_register; /* cached value */
+ u32 creg_spdif;
+ u32 creg_spdif_stream;
+ char *card_name; /* digiface/multiface */
+ HDSP_IO_Type io_type; /* ditto, but for code use */
+ unsigned short firmware_rev;
+ size_t period_bytes; /* guess what this is */
+ unsigned char ds_channels;
+ unsigned char ss_channels; /* different for
multiface/digiface */
+ void *capture_buffer_unaligned; /* original buffer addresses
*/
+ void *playback_buffer_unaligned; /* original buffer addresses */
+ unsigned char *capture_buffer; /* suitably aligned address */
+ unsigned char *playback_buffer; /* suitably aligned address */
+ dma_addr_t capture_buffer_addr;
+ dma_addr_t playback_buffer_addr;
+ pid_t capture_pid;
+ pid_t playback_pid;
+ int running;
+ int passthru; /* non-zero if doing pass-thru */
+ int last_spdif_sample_rate;/* so that we can catch externally
... */
+ int last_adat_sample_rate; /* ... induced rate changes
*/
+ char *channel_map;
+ int dev;
+ int irq;
+ unsigned long port;
+ struct resource *res_port;
+ unsigned long iobase;
+ snd_card_t *card;
+ snd_pcm_t *pcm;
+ struct pci_dev *pci;
+ snd_kcontrol_t *spdif_ctl;
+ unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
};
/* These tables map the ALSA channels 1..N to the channels that we
@@ -414,8 +409,8 @@
static struct pci_device_id snd_hdsp_ids[] __devinitdata = {
{
- .vendor = PCI_VENDOR_ID_XILINX,
- .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
+ .vendor = PCI_VENDOR_ID_XILINX,
+ .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
}, /* RME Hammerfall-DSP */
@@ -424,6 +419,37 @@
MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
+static inline int hdsp_is_9652 (hdsp_t *hdsp)
+{
+ switch (hdsp->firmware_rev) {
+ case 0x64:
+ case 0x68:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
+{
+ switch (hdsp->firmware_rev) {
+ case 0xa:
+ return (64 * out) + (32 + (in));
+ default:
+ return (52 * out) + (26 + (in));
+ }
+}
+
+static inline int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
+{
+ switch (hdsp->firmware_rev) {
+ case 0xa:
+ return (64 * out) + in;
+ default:
+ return (52 * out) + in;
+ }
+}
+
static inline void hdsp_write(hdsp_t *hdsp, int reg, int val)
{
writel(val, hdsp->iobase + reg);
@@ -460,10 +486,18 @@
are available in the command FIFO.
*/
- for (i = 0; i < timeout; i++)
+ for (i = 0; i < timeout; i++) {
+
if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)
return 0;
+ /* not very friendly, but we only do this during a firmware
+ load and changing the mixer, so we just put up with it.
+ */
+
+ udelay (100);
+ }
+
snd_printk ("wait for FIFO status <= %d failed after %d iterations\n",
count, timeout);
return -1;
@@ -481,16 +515,46 @@
{
unsigned int ad;
- if (addr >= HDSP_MATRIX_MIXER_SIZE)
- return -1;
+ if (hdsp_is_9652 (hdsp)) {
- ad = data + addr * 65536;
+ if ((ad = addr/2) < 676) {
+
+ /* from martin bj�rnsen:
+
+ "You can only write dwords to the
+ mixer memory which contain two
+ mixer values in the low and high
+ word. So if you want to change
+ value 0 you have to read value 1
+ from the cache and write both to
+ the first dword in the mixer
+ memory."
+ */
+
+ hdsp->mixer_matrix[addr] = data;
+ hdsp_write (hdsp, 1024 + ad,
+ (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
+ hdsp->mixer_matrix[addr&0x7fe]);
+ return 0;
+ } else {
+ return -1;
+ }
+
+
+ } else {
+ if (addr >= HDSP_MATRIX_MIXER_SIZE)
+ return -1;
+
+ ad = (addr << 16) + data;
+
+ if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) {
+ return -1;
+ }
+
+ hdsp_write (hdsp, HDSP_fifoData, ad);
+ hdsp->mixer_matrix[addr] = data;
- if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) {
- return -1;
}
- hdsp_write (hdsp, HDSP_fifoData, ad);
- hdsp->mixer_matrix[addr] = data;
return 0;
}
@@ -571,17 +635,7 @@
static inline void hdsp_reset_hw_pointer(hdsp_t *hdsp)
{
-#if 0
- /* reset the hw pointer to zero. We do this by writing to 8
- registers, each of which is a 32bit wide register, and set
- them all to zero.
- */
-
- for (i = 0; i < 8; ++i) {
- hdsp_write(hdsp, i, 0);
- udelay(10);
- }
-#endif
+ hdsp_write (hdsp, HDSP_resetPointer, 0);
}
static inline void hdsp_start_audio(hdsp_t *s)
@@ -644,8 +698,7 @@
Note that a similar but essentially insoluble problem
exists for externally-driven rate changes. All we can do
- is to flag rate changes in the read/write routines.
- */
+ is to flag rate changes in the read/write routines. */
spin_lock_irq(&hdsp->lock);
current_rate = hdsp_system_sample_rate(hdsp);
@@ -707,7 +760,7 @@
if (rate > 48000) {
hdsp->channel_map = channel_map_ds;
} else {
- switch (hdsp->type) {
+ switch (hdsp->io_type) {
case Multiface:
hdsp->channel_map = channel_map_mf_ss;
break;
@@ -734,11 +787,11 @@
if (enable) {
for (i = 0; i < 26; i++) {
- hdsp_write_gain (hdsp, INPUT_TO_OUTPUT_KEY(i,i),
UNITY_GAIN);
+ hdsp_write_gain (hdsp,
hdsp_input_to_output_key(hdsp,i,i), UNITY_GAIN);
}
} else {
for (i = 0; i < 26; i++) {
- hdsp_write_gain (hdsp, INPUT_TO_OUTPUT_KEY(i,i),
MINUS_INFINITY_GAIN);
+ hdsp_write_gain (hdsp,
hdsp_input_to_output_key(hdsp,i,i), MINUS_INFINITY_GAIN);
}
}
@@ -752,9 +805,9 @@
snd_assert(mapped_channel > -1, return);
if (enable) {
- hdsp_write_gain (hdsp,
INPUT_TO_OUTPUT_KEY(mapped_channel,mapped_channel), UNITY_GAIN);
+ hdsp_write_gain (hdsp,
hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), UNITY_GAIN);
} else {
- hdsp_write_gain (hdsp,
INPUT_TO_OUTPUT_KEY(mapped_channel,mapped_channel), MINUS_INFINITY_GAIN);
+ hdsp_write_gain (hdsp,
hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), MINUS_INFINITY_GAIN);
}
}
}
@@ -974,7 +1027,6 @@
if (up)
snd_hdsp_midi_output_write(hmidi);
}
-
static int snd_hdsp_midi_input_open(snd_rawmidi_substream_t * substream)
{
hdsp_midi_t *hmidi;
@@ -1178,9 +1230,12 @@
}
#define HDSP_SPDIF_IN(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+ .name = xname, \
+ .index = xindex, \
.info = snd_hdsp_info_spdif_in, \
- .get = snd_hdsp_get_spdif_in, .put = snd_hdsp_put_spdif_in }
+ .get = snd_hdsp_get_spdif_in, \
+ .put = snd_hdsp_put_spdif_in }
static unsigned int hdsp_spdif_in(hdsp_t *hdsp)
{
@@ -1238,9 +1293,9 @@
}
#define HDSP_SPDIF_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, name: xname, index: xindex, \
.info = snd_hdsp_info_spdif_out, \
- .get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out }
+ .get = snd_hdsp_get_spdif_out, put: snd_hdsp_put_spdif_out }
static int hdsp_spdif_out(hdsp_t *hdsp)
{
@@ -1296,9 +1351,13 @@
}
#define HDSP_SYNC_PREF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+ .name = xname, \
+ .index = xindex, \
.info = snd_hdsp_info_sync_pref, \
- .get = snd_hdsp_get_sync_pref, .put = snd_hdsp_put_sync_pref }
+ .get = snd_hdsp_get_sync_pref, \
+ .put = snd_hdsp_put_sync_pref \
+}
static int hdsp_sync_pref(hdsp_t *hdsp)
{
@@ -1374,7 +1433,7 @@
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- uinfo->value.enumerated.items = (hdsp->type == Digiface) ? 7 : 6;
+ uinfo->value.enumerated.items = (hdsp->io_type == Digiface) ? 7 : 6;
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
@@ -1401,7 +1460,7 @@
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
- max = hdsp->ss_channels == (hdsp->type == Digiface) ? 7 : 6;
+ max = hdsp->ss_channels == (hdsp->io_type == Digiface) ? 7 : 6;
val = ucontrol->value.enumerated.item[0] % max;
spin_lock_irqsave(&hdsp->lock, flags);
change = (int)val != hdsp_sync_pref(hdsp);
@@ -1411,10 +1470,13 @@
}
#define HDSP_PASSTHRU(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+ .name = xname, \
+ .index = xindex, \
.info = snd_hdsp_info_passthru, \
.put = snd_hdsp_put_passthru, \
- .get = snd_hdsp_get_passthru }
+ .get = snd_hdsp_get_passthru \
+}
static int snd_hdsp_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t *
uinfo)
{
@@ -1457,9 +1519,13 @@
}
#define HDSP_LINE_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+ .name = xname, \
+ .index = xindex, \
.info = snd_hdsp_info_line_out, \
- .get = snd_hdsp_get_line_out, .put = snd_hdsp_put_line_out }
+ .get = snd_hdsp_get_line_out, \
+ .put = snd_hdsp_put_line_out \
+}
static int hdsp_line_out(hdsp_t *hdsp)
{
@@ -1515,9 +1581,15 @@
}
#define HDSP_MIXER(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+ .name = xname, \
+ .index = xindex, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
.info = snd_hdsp_info_mixer, \
- .get = snd_hdsp_get_mixer, .put = snd_hdsp_put_mixer }
+ .get = snd_hdsp_get_mixer, \
+ .put = snd_hdsp_put_mixer \
+}
static int snd_hdsp_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
@@ -1541,9 +1613,9 @@
destination = ucontrol->value.integer.value[1];
if (source > 25) {
- addr = PLAYBACK_TO_OUTPUT_KEY(source-26,destination);
+ addr = hdsp_playback_to_output_key(hdsp,source-26,destination);
} else {
- addr = INPUT_TO_OUTPUT_KEY(source, destination);
+ addr = hdsp_input_to_output_key(hdsp,source, destination);
}
spin_lock_irqsave(&hdsp->lock, flags);
@@ -1569,9 +1641,9 @@
destination = ucontrol->value.integer.value[1];
if (source > 25) {
- addr = PLAYBACK_TO_OUTPUT_KEY(source-26, destination);
+ addr = hdsp_playback_to_output_key(hdsp,source-26, destination);
} else {
- addr = INPUT_TO_OUTPUT_KEY(source, destination);
+ addr = hdsp_input_to_output_key(hdsp,source, destination);
}
gain = ucontrol->value.integer.value[2];
@@ -1594,7 +1666,9 @@
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
.info = snd_hdsp_info_playback_mixer, \
- .get = snd_hdsp_get_playback_mixer, .put = snd_hdsp_put_playback_mixer }
+ .get = snd_hdsp_get_playback_mixer, \
+ .put = snd_hdsp_put_playback_mixer \
+}
static int snd_hdsp_info_playback_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
* uinfo)
{
@@ -1622,7 +1696,7 @@
return -EINVAL;
}
- addr = PLAYBACK_TO_OUTPUT_KEY(mapped_channel, mapped_channel);
+ addr = hdsp_playback_to_output_key(hdsp,mapped_channel, mapped_channel);
spin_lock_irqsave(&hdsp->lock, flags);
ucontrol->value.integer.value[0] = hdsp_read_gain (hdsp, addr);
@@ -1651,7 +1725,7 @@
return -EINVAL;
}
- addr = PLAYBACK_TO_OUTPUT_KEY(mapped_channel, mapped_channel);
+ addr = hdsp_playback_to_output_key(hdsp,mapped_channel, mapped_channel);
gain = ucontrol->value.integer.value[0];
@@ -1797,8 +1871,8 @@
.info = snd_hdsp_control_spdif_mask_info,
.get = snd_hdsp_control_spdif_mask_get,
.private_value = IEC958_AES0_NONAUDIO |
- IEC958_AES0_PROFESSIONAL |
- IEC958_AES0_CON_EMPHASIS,
+ IEC958_AES0_PROFESSIONAL |
+ IEC958_AES0_CON_EMPHASIS,
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1807,8 +1881,8 @@
.info = snd_hdsp_control_spdif_mask_info,
.get = snd_hdsp_control_spdif_mask_get,
.private_value = IEC958_AES0_NONAUDIO |
- IEC958_AES0_PROFESSIONAL |
- IEC958_AES0_PRO_EMPHASIS,
+ IEC958_AES0_PROFESSIONAL |
+ IEC958_AES0_PRO_EMPHASIS,
},
HDSP_MIXER("Mixer", 0),
HDSP_SPDIF_IN("IEC958 Input Connector", 0),
@@ -1840,7 +1914,14 @@
hdsp->spdif_ctl = kctl;
}
- if (hdsp->type == Digiface) {
+ snd_hdsp_playback_mixer.name = "Chn";
+ snd_hdsp_input_peak.name = "Input Peak";
+ snd_hdsp_output_peak.name = "Output Peak";
+ snd_hdsp_playback_peak.name = "Playback Peak";
+ snd_hdsp_playback_rms.name = "Playback RMS";
+ snd_hdsp_input_rms.name = "Input RMS";
+
+ if (hdsp->io_type == Digiface) {
limit = DIGIFACE_SS_CHANNELS;
} else {
limit = MULTIFACE_SS_CHANNELS;
@@ -1852,26 +1933,18 @@
does the wrong thing with it ...
*/
- snd_hdsp_playback_mixer.name = "Chn";
- snd_hdsp_input_peak.name = "Input Peak";
- snd_hdsp_output_peak.name = "Output Peak";
- snd_hdsp_playback_peak.name = "Playback Peak";
- snd_hdsp_playback_rms.name = "Playback RMS";
- snd_hdsp_input_rms.name = "Input RMS";
-
for (idx = 0; idx < limit; ++idx) {
snd_hdsp_playback_mixer.index = idx+1;
if ((err = snd_ctl_add (card, kctl =
snd_ctl_new1(&snd_hdsp_playback_mixer, hdsp)))) {
return err;
}
+ }
+
+ for (idx = 0; idx < HDSP_MAX_CHANNELS; ++idx) {
snd_hdsp_input_peak.index = idx+1;
if ((err = snd_ctl_add (card, kctl =
snd_ctl_new1(&snd_hdsp_input_peak, hdsp)))) {
return err;
}
- snd_hdsp_output_peak.index = idx+1;
- if ((err = snd_ctl_add (card, kctl =
snd_ctl_new1(&snd_hdsp_output_peak, hdsp)))) {
- return err;
- }
snd_hdsp_playback_peak.index = idx+1;
if ((err = snd_ctl_add (card, kctl =
snd_ctl_new1(&snd_hdsp_playback_peak, hdsp)))) {
return err;
@@ -1886,6 +1959,17 @@
}
}
+ /* include line out/headphone channels in output
+ peak meters.
+ */
+
+ for (idx = 0; idx < HDSP_MAX_CHANNELS + 2; ++idx) {
+ snd_hdsp_output_peak.index = idx+1;
+ if ((err = snd_ctl_add (card, kctl =
snd_ctl_new1(&snd_hdsp_output_peak, hdsp)))) {
+ return err;
+ }
+ }
+
return 0;
}
@@ -2057,13 +2141,17 @@
snd_iprintf(buffer, "ADAT2: No Lock\n");
}
- if (hdsp->type == Digiface) {
+ switch (hdsp->io_type) {
+ case Digiface:
x = status & HDSP_Sync2;
if (status & HDSP_Lock2) {
snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock");
} else {
snd_iprintf(buffer, "ADAT3: No Lock\n");
}
+ default:
+ /* relax */
+ break;
}
snd_iprintf(buffer, "\n");
@@ -2212,11 +2300,11 @@
for (i = 0; i < HDSP_MAX_CHANNELS; i++) {
if (i & 1) {
- hdsp_write_gain (hdsp, INPUT_TO_OUTPUT_KEY (i, 26),
UNITY_GAIN);
- hdsp_write_gain (hdsp, PLAYBACK_TO_OUTPUT_KEY (i, 26),
UNITY_GAIN);
+ hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp,
i, 26), UNITY_GAIN);
+ hdsp_write_gain (hdsp, hdsp_playback_to_output_key
(hdsp, i, 26), UNITY_GAIN);
} else {
- hdsp_write_gain (hdsp, INPUT_TO_OUTPUT_KEY (i, 27),
UNITY_GAIN);
- hdsp_write_gain (hdsp, PLAYBACK_TO_OUTPUT_KEY (i, 27),
UNITY_GAIN);
+ hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp,
i, 27), UNITY_GAIN);
+ hdsp_write_gain (hdsp, hdsp_playback_to_output_key
(hdsp, i, 27), UNITY_GAIN);
}
}
}
@@ -2310,8 +2398,7 @@
channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream,
channel);
snd_assert(channel_buf != NULL, return -EIO);
- if (copy_from_user(channel_buf + pos * 4, src, count * 4))
- return -EFAULT;
+ copy_from_user(channel_buf + pos * 4, src, count * 4);
return count;
}
@@ -2325,8 +2412,7 @@
channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream,
channel);
snd_assert(channel_buf != NULL, return -EIO);
- if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
- return -EFAULT;
+ copy_to_user(dst, channel_buf + pos * 4, count * 4);
return count;
}
@@ -2400,7 +2486,7 @@
that matter are the same.
*/
- if ((int)params_rate(params) != hdsp_system_sample_rate(hdsp)) {
+ if (params_rate(params) != hdsp_system_sample_rate(hdsp)) {
spin_unlock_irq(&hdsp->lock);
_snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
return -EBUSY;
@@ -2577,11 +2663,11 @@
.channels_min = 14,
.channels_max = HDSP_MAX_CHANNELS,
.buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
- .period_bytes_min = (64 * 4) *10,
+ .period_bytes_min = (64 * 4) * 10,
.period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
.periods_min = 2,
.periods_max = 2,
- .fifo_size = 0,
+ .fifo_size = 0
};
static snd_pcm_hardware_t snd_hdsp_capture_subinfo =
@@ -2606,7 +2692,7 @@
.period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
.periods_min = 2,
.periods_max = 2,
- .fifo_size = 0,
+ .fifo_size = 0
};
static unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
@@ -2638,7 +2724,7 @@
snd_interval_t t = {
.min = hdsp->ds_channels,
.max = hdsp->ds_channels,
- .integer = 1,
+ integer: 1,
};
return snd_interval_refine(c, &t);
} else if (r->max < 64000) {
@@ -2662,7 +2748,7 @@
snd_interval_t t = {
.min = 32000,
.max = 48000,
- .integer = 1,
+ integer: 1,
};
return snd_interval_refine(r, &t);
} else if (c->max <= hdsp->ds_channels) {
@@ -2847,6 +2933,11 @@
int i;
u32 *firmware_ptr;
+ if (hdsp_is_9652 (hdsp)) {
+ /* no firmware needed */
+ return 0;
+ }
+
if (hdsp_check_for_iobox (hdsp)) {
return -EIO;
}
@@ -2862,7 +2953,7 @@
hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1);
}
- if (force_firmware[hdsp->dev] || (hdsp_read (hdsp, HDSP_statusRegister) &
HDSP_DllError) != 0) {
+ if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
snd_printk ("loading firmware\n");
@@ -2877,12 +2968,12 @@
hdsp_write (hdsp, HDSP_fifoData, 0);
if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) {
- hdsp->type = Multiface;
+ hdsp->io_type = Multiface;
hdsp_write (hdsp, HDSP_jtagReg, HDSP_VERSION_BIT);
hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_LOAD);
hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);
} else {
- hdsp->type = Digiface;
+ hdsp->io_type = Digiface;
}
hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_PROGRAM);
@@ -2895,10 +2986,26 @@
hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_LOAD);
- if (hdsp->type == Digiface) {
- firmware_ptr = (u32 *) digiface_firmware;
+ if (hdsp->io_type == Digiface) {
+ switch (hdsp->firmware_rev) {
+ case 0xa:
+ case 0x64:
+ firmware_ptr = (u32 *) digiface_firmware;
+ break;
+ default:
+ firmware_ptr = (u32 *) digiface_firmware_rev11;
+ break;
+ }
+
} else {
- firmware_ptr = (u32 *) multiface_firmware;
+ switch (hdsp->firmware_rev) {
+ case 0xa:
+ case 0x64:
+ firmware_ptr = (u32 *) multiface_firmware;
+ default:
+ firmware_ptr = (u32 *) multiface_firmware_rev11;
+ break;
+ }
}
for (i = 0; i < 24413; ++i) {
@@ -2925,20 +3032,18 @@
*/
if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
- hdsp->type = Multiface;
+ hdsp->io_type = Multiface;
} else {
- hdsp->type = Digiface;
+ hdsp->io_type = Digiface;
}
}
- if (hdsp->type == Digiface) {
- snd_printk ("I/O Box is a Digiface\n");
- hdsp->card_name = "RME Hammerfall DSP (Digiface)";
+ if (hdsp->io_type == Digiface) {
+ strcat (hdsp->card_name, " + Digiface");
hdsp->ss_channels = DIGIFACE_SS_CHANNELS;
hdsp->ds_channels = DIGIFACE_DS_CHANNELS;
} else {
- snd_printk ("I/O Box is a Multiface\n");
- hdsp->card_name = "RME Hammerfall DSP (Multiface)";
+ strcat (hdsp->card_name, " + Multiface");
hdsp->ss_channels = MULTIFACE_SS_CHANNELS;
hdsp->ds_channels = MULTIFACE_DS_CHANNELS;
}
@@ -2959,7 +3064,6 @@
{
struct pci_dev *pci = hdsp->pci;
int err;
- unsigned short rev;
hdsp->irq = -1;
hdsp->midi[0].rmidi = 0;
@@ -2977,18 +3081,19 @@
spin_lock_init(&hdsp->lock);
- pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &rev);
+ pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
strcpy(card->driver, "H-DSP");
strcpy(card->mixername, "Xilinx FPGA");
- switch (rev & 0xff) {
+ switch (hdsp->firmware_rev & 0xff) {
case 0xa:
case 0xb:
- case 0x64:
- /* hdsp_initialize_firmware() will reset this */
hdsp->card_name = "RME Hammerfall DSP";
break;
-
+ case 0x64:
+ case 0x68:
+ hdsp->card_name = "RME HDSP 9652";
+ break;
default:
return -ENODEV;
}
@@ -3136,10 +3241,10 @@
}
static struct pci_driver driver = {
- .name = "RME Hammerfall DSP",
+ .name = "RME Hammerfall DSP",
.id_table = snd_hdsp_ids,
- .probe = snd_hdsp_probe,
- .remove = __devexit_p(snd_hdsp_remove),
+ .probe = snd_hdsp_probe,
+ .remove = __devexit_p(snd_hdsp_remove),
};
static int __init alsa_card_hdsp_init(void)
-------------------------------------------------------
This SF.net email is sponsored by: Etnus, makers of TotalView, The debugger
for complex code. Debugging C/C++ programs can leave you feeling lost and
disoriented. TotalView can help you find your way. Available on major UNIX
and Linux platforms. Try it free. www.etnus.com
_______________________________________________
Alsa-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-devel