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

Reply via email to