vserver 2.0 rc7
[linux-2.6.git] / sound / pci / rme9652 / hdsp.c
index e35796c..12efbf0 100644 (file)
@@ -47,8 +47,6 @@
 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 */
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
@@ -56,10 +54,6 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
-module_param_array(precise_ptr, bool, NULL, 0444);
-MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably).");
-module_param_array(line_outs_monitor, bool, NULL, 0444);
-MODULE_PARM_DESC(line_outs_monitor, "Send all input and playback streams to line outs by default.");
 MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
 MODULE_DESCRIPTION("RME Hammerfall DSP");
 MODULE_LICENSE("GPL");
@@ -445,6 +439,7 @@ struct _hdsp {
        snd_pcm_substream_t  *playback_substream;
         hdsp_midi_t           midi[2];
        struct tasklet_struct midi_tasklet;
+       int                   use_midi_tasklet;
        int                   precise_ptr;
        u32                   control_register;      /* cached value */
        u32                   control2_register;     /* cached value */
@@ -472,7 +467,6 @@ struct _hdsp {
        pid_t                 capture_pid;
        pid_t                 playback_pid;
        int                   running;
-        int                   passthru;              /* non-zero if doing pass-thru */
        int                   system_sample_rate;
        char                 *channel_map;
        int                   dev;
@@ -659,13 +653,13 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
 
        if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
                
-               snd_printk ("loading firmware\n");
+               snd_printk ("Hammerfall-DSP: loading firmware\n");
 
                hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
                hdsp_write (hdsp, HDSP_fifoData, 0);
                
                if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
-                       snd_printk ("timeout waiting for download preparation\n");
+                       snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");
                        return -EIO;
                }
                
@@ -674,7 +668,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
                for (i = 0; i < 24413; ++i) {
                        hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
                        if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
-                               snd_printk ("timeout during firmware loading\n");
+                               snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
                                return -EIO;
                        }
                }
@@ -687,7 +681,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
                }
                
                if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
-                       snd_printk ("timeout at end of firmware loading\n");
+                       snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");
                        return -EIO;
                }
 
@@ -697,11 +691,11 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
                hdsp->control2_register = 0;
 #endif
                hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
-               snd_printk ("finished firmware loading\n");
+               snd_printk ("Hammerfall-DSP: finished firmware loading\n");
                
        }
        if (hdsp->state & HDSP_InitializationComplete) {
-               snd_printk("firmware loaded from cache, restoring defaults\n");
+               snd_printk("Hammerfall-DSP: firmware loaded from cache, restoring defaults\n");
                spin_lock_irqsave(&hdsp->lock, flags);
                snd_hdsp_set_defaults(hdsp);
                spin_unlock_irqrestore(&hdsp->lock, flags); 
@@ -714,16 +708,6 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
 
 static int hdsp_get_iobox_version (hdsp_t *hdsp)
 {
-       int err;
-       
-       if (hdsp_check_for_iobox (hdsp)) {
-               return -EIO;
-       }
-
-       if ((err = snd_hdsp_enable_io(hdsp)) < 0) {
-               return err;
-       }
-               
        if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
        
                hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
@@ -759,7 +743,7 @@ static int hdsp_check_for_firmware (hdsp_t *hdsp)
 {
        if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
        if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
-               snd_printk("firmware not present.\n");
+               snd_printk("Hammerfall-DSP: firmware not present.\n");
                hdsp->state &= ~HDSP_FirmwareLoaded;
                return -EIO;
        }
@@ -787,7 +771,7 @@ static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
                udelay (100);
        }
 
-       snd_printk ("wait for FIFO status <= %d failed after %d iterations\n",
+       snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n",
                    count, timeout);
        return -1;
 }
@@ -809,7 +793,7 @@ static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
        
        if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
 
-               /* from martin bjรถrnsen:
+               /* from martin bjornsen:
                   
                   "You can only write dwords to the
                   mixer memory which contain two
@@ -922,7 +906,7 @@ static int hdsp_spdif_sample_rate(hdsp_t *hdsp)
        default:
                break;
        }
-       snd_printk ("unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
+       snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
        return 0;
 }
 
@@ -1008,7 +992,7 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
        if (!(hdsp->control_register & HDSP_ClockModeMaster)) { 
                if (called_internally) {
                        /* request from ctl or card initialization */
-                       snd_printk("device is not running as a clock master: cannot set sample rate.\n");
+                       snd_printk("Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n");
                        return -1;
                } else {                
                        /* hw_param request while in AutoSync mode */
@@ -1016,11 +1000,11 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
                        int spdif_freq = hdsp_spdif_sample_rate(hdsp);
                
                        if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) {
-                               snd_printk("Detected ADAT in double speed mode\n");
+                               snd_printk("Hammerfall-DSP: Detected ADAT in double speed mode\n");
                        } else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) {
-                               snd_printk("Detected ADAT in quad speed mode\n");                       
+                               snd_printk("Hammerfall-DSP: Detected ADAT in quad speed mode\n");                       
                        } else if (rate != external_freq) {
-                               snd_printk("No AutoSync source for requested rate\n");
+                               snd_printk("Hammerfall-DSP: No AutoSync source for requested rate\n");
                                return -1;
                        }               
                }       
@@ -1102,7 +1086,7 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
        }
 
        if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {
-               snd_printk ("cannot change speed mode (capture PID = %d, playback PID = %d)\n",
+               snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n",
                            hdsp->capture_pid,
                            hdsp->playback_pid);
                return -EBUSY;
@@ -1143,68 +1127,6 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
        return 0;
 }
 
-static void hdsp_set_thru(hdsp_t *hdsp, int channel, int enable)
-{
-
-       hdsp->passthru = 0;
-
-       if (channel < 0) {
-
-               int i;
-
-               /* set thru for all channels */
-
-               if (enable) {
-                       for (i = 0; i < hdsp->max_channels; i++) {
-                               hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), UNITY_GAIN);
-                       }
-               } else {
-                       for (i = 0; i < hdsp->max_channels; i++) {
-                               hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), MINUS_INFINITY_GAIN);
-                       }
-               }
-
-       } else {
-               int mapped_channel;
-
-               snd_assert(channel < hdsp->max_channels, return);
-
-               mapped_channel = hdsp->channel_map[channel];
-
-               snd_assert(mapped_channel > -1, return);
-
-               if (enable) {
-                       hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), UNITY_GAIN);
-               } else {
-                       hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), MINUS_INFINITY_GAIN);
-               }
-       }
-}
-
-static int hdsp_set_passthru(hdsp_t *hdsp, int onoff)
-{
-       if (onoff) {
-               hdsp_set_thru(hdsp, -1, 1);
-               hdsp_reset_hw_pointer(hdsp);
-               hdsp_silence_playback(hdsp);
-
-               /* we don't want interrupts, so do a
-                  custom version of hdsp_start_audio().
-               */
-
-               hdsp->control_register |= (HDSP_Start|HDSP_AudioInterruptEnable|hdsp_encode_latency(7));
-
-               hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
-               hdsp->passthru = 1;
-       } else {
-               hdsp_set_thru(hdsp, -1, 0);
-               hdsp_stop_audio(hdsp);          
-               hdsp->passthru = 0;
-       }
-
-       return 0;
-}
-
 /*----------------------------------------------------------------------------
    MIDI
   ----------------------------------------------------------------------------*/
@@ -1345,6 +1267,7 @@ static void snd_hdsp_midi_input_trigger(snd_rawmidi_substream_t * substream, int
                }
        } else {
                hdsp->control_register &= ~ie;
+               tasklet_kill(&hdsp->midi_tasklet);
        }
 
        hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
@@ -2741,16 +2664,32 @@ static int snd_hdsp_get_autosync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
        return 0;
 }
 
-#define HDSP_PASSTHRU(xname, xindex) \
+#define HDSP_LINE_OUT(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
   .name = xname, \
   .index = xindex, \
-  .info = snd_hdsp_info_passthru, \
-  .put = snd_hdsp_put_passthru, \
-  .get = snd_hdsp_get_passthru \
+  .info = snd_hdsp_info_line_out, \
+  .get = snd_hdsp_get_line_out, \
+  .put = snd_hdsp_put_line_out \
+}
+
+static int hdsp_line_out(hdsp_t *hdsp)
+{
+       return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
+}
+
+static int hdsp_set_line_output(hdsp_t *hdsp, int out)
+{
+       if (out) {
+               hdsp->control_register |= HDSP_LineOut;
+       } else {
+               hdsp->control_register &= ~HDSP_LineOut;
+       }
+       hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
+       return 0;
 }
 
-static int snd_hdsp_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
        uinfo->count = 1;
@@ -2759,61 +2698,106 @@ static int snd_hdsp_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
        return 0;
 }
 
-static int snd_hdsp_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
        hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
-
+       
        spin_lock_irq(&hdsp->lock);
-       ucontrol->value.integer.value[0] = hdsp->passthru;
+       ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
        spin_unlock_irq(&hdsp->lock);
        return 0;
 }
 
-static int snd_hdsp_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
        hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
        int change;
        unsigned int val;
-       int err = 0;
-
+       
        if (!snd_hdsp_use_is_exclusive(hdsp))
                return -EBUSY;
-
        val = ucontrol->value.integer.value[0] & 1;
        spin_lock_irq(&hdsp->lock);
-       change = (ucontrol->value.integer.value[0] != hdsp->passthru);
-       if (change)
-               err = hdsp_set_passthru(hdsp, val);
+       change = (int)val != hdsp_line_out(hdsp);
+       hdsp_set_line_output(hdsp, val);
        spin_unlock_irq(&hdsp->lock);
-       return err ? err : change;
+       return change;
 }
 
-#define HDSP_LINE_OUT(xname, xindex) \
+#define HDSP_PRECISE_POINTER(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
   .name = xname, \
   .index = xindex, \
-  .info = snd_hdsp_info_line_out, \
-  .get = snd_hdsp_get_line_out, \
-  .put = snd_hdsp_put_line_out \
+  .info = snd_hdsp_info_precise_pointer, \
+  .get = snd_hdsp_get_precise_pointer, \
+  .put = snd_hdsp_put_precise_pointer \
 }
 
-static int hdsp_line_out(hdsp_t *hdsp)
+static int hdsp_set_precise_pointer(hdsp_t *hdsp, int precise)
 {
-       return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
+       if (precise) {
+               hdsp->precise_ptr = 1;
+       } else {
+               hdsp->precise_ptr = 0;
+       }
+       return 0;
 }
 
-static int hdsp_set_line_output(hdsp_t *hdsp, int out)
+static int snd_hdsp_info_precise_pointer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-       if (out) {
-               hdsp->control_register |= HDSP_LineOut;
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_hdsp_get_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+       
+       spin_lock_irq(&hdsp->lock);
+       ucontrol->value.integer.value[0] = hdsp->precise_ptr;
+       spin_unlock_irq(&hdsp->lock);
+       return 0;
+}
+
+static int snd_hdsp_put_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+       int change;
+       unsigned int val;
+       
+       if (!snd_hdsp_use_is_exclusive(hdsp))
+               return -EBUSY;
+       val = ucontrol->value.integer.value[0] & 1;
+       spin_lock_irq(&hdsp->lock);
+       change = (int)val != hdsp->precise_ptr;
+       hdsp_set_precise_pointer(hdsp, val);
+       spin_unlock_irq(&hdsp->lock);
+       return change;
+}
+
+#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdsp_info_use_midi_tasklet, \
+  .get = snd_hdsp_get_use_midi_tasklet, \
+  .put = snd_hdsp_put_use_midi_tasklet \
+}
+
+static int hdsp_set_use_midi_tasklet(hdsp_t *hdsp, int use_tasklet)
+{
+       if (use_tasklet) {
+               hdsp->use_midi_tasklet = 1;
        } else {
-               hdsp->control_register &= ~HDSP_LineOut;
+               hdsp->use_midi_tasklet = 0;
        }
-       hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
        return 0;
 }
 
-static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_use_midi_tasklet(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
        uinfo->count = 1;
@@ -2822,17 +2806,17 @@ static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
        return 0;
 }
 
-static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
        hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
        
        spin_lock_irq(&hdsp->lock);
-       ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
+       ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
        spin_unlock_irq(&hdsp->lock);
        return 0;
 }
 
-static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
        hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
        int change;
@@ -2842,8 +2826,8 @@ static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
                return -EBUSY;
        val = ucontrol->value.integer.value[0] & 1;
        spin_lock_irq(&hdsp->lock);
-       change = (int)val != hdsp_line_out(hdsp);
-       hdsp_set_line_output(hdsp, val);
+       change = (int)val != hdsp->use_midi_tasklet;
+       hdsp_set_use_midi_tasklet(hdsp, val);
        spin_unlock_irq(&hdsp->lock);
        return change;
 }
@@ -3139,8 +3123,9 @@ HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
 HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0),
 HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
 HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
-HDSP_PASSTHRU("Passthru", 0),
 HDSP_LINE_OUT("Line Out", 0),
+HDSP_PRECISE_POINTER("Precise Pointer", 0),
+HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
 };
 
 static snd_kcontrol_new_t snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
@@ -3240,11 +3225,11 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
        snd_iprintf(buffer, "Status register: 0x%x\n", status);
        snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
        snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
-
        snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
        snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
        snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
        snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
+       snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
 
        snd_iprintf(buffer, "\n");
 
@@ -3252,7 +3237,7 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 
        snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes);
        snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp));
-       snd_iprintf(buffer, "Passthru: %s\n", hdsp->passthru ? "yes" : "no");
+       snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off");
        snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off");
 
        snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2);
@@ -3612,40 +3597,6 @@ static int snd_hdsp_set_defaults(hdsp_t *hdsp)
                }
        }
        
-       if ((hdsp->io_type != H9652) && line_outs_monitor[hdsp->dev]) {
-               
-               int lineouts_base;
-               
-               snd_printk ("sending all inputs and playback streams to line outs.\n");
-
-               /* route all inputs to the line outs for easy monitoring. send
-                  odd numbered channels to right, even to left.
-               */
-               if (hdsp->io_type == H9632) {
-                       /* this is the phones/analog output */
-                       lineouts_base = 10;
-               } else {
-                       lineouts_base = 26;
-               }
-               
-               for (i = 0; i < hdsp->max_channels; i++) {
-                       if (i & 1) { 
-                               if (hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp, i, lineouts_base), UNITY_GAIN) ||
-                                   hdsp_write_gain (hdsp, hdsp_playback_to_output_key (hdsp, i, lineouts_base), UNITY_GAIN)) {
-                                   return -EIO;
-                               }    
-                       } else {
-                               if (hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp, i, lineouts_base+1), UNITY_GAIN) ||
-                                   hdsp_write_gain (hdsp, hdsp_playback_to_output_key (hdsp, i, lineouts_base+1), UNITY_GAIN)) {
-                                   
-                                   return -EIO;
-                               }
-                       }
-               }
-       }
-
-       hdsp->passthru = 0;
-
        /* H9632 specific defaults */
        if (hdsp->io_type == H9632) {
                hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
@@ -3709,21 +3660,29 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg
        }
        
        if (midi0 && midi0status) {
-               /* we disable interrupts for this input until processing is done */
-               hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
-               hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
-               hdsp->midi[0].pending = 1;
-               schedule = 1;
+               if (hdsp->use_midi_tasklet) {
+                       /* we disable interrupts for this input until processing is done */
+                       hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
+                       hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
+                       hdsp->midi[0].pending = 1;
+                       schedule = 1;
+               } else {
+                       snd_hdsp_midi_input_read (&hdsp->midi[0]);
+               }
        }
-       if (midi1 && midi1status) {
-               /* we disable interrupts for this input until processing is done */
-               hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
-               hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
-               hdsp->midi[1].pending = 1;
-               schedule = 1;
+       if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) {
+               if (hdsp->use_midi_tasklet) {
+                       /* we disable interrupts for this input until processing is done */
+                       hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
+                       hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
+                       hdsp->midi[1].pending = 1;
+                       schedule = 1;
+               } else {
+                       snd_hdsp_midi_input_read (&hdsp->midi[1]);
+               }
        }
-       if (schedule)
-           tasklet_hi_schedule(&hdsp->midi_tasklet);
+       if (hdsp->use_midi_tasklet && schedule)
+               tasklet_hi_schedule(&hdsp->midi_tasklet);
        return IRQ_HANDLED;
 }
 
@@ -3838,10 +3797,10 @@ static int snd_hdsp_hw_params(snd_pcm_substream_t *substream,
        if (hdsp_check_for_firmware(hdsp)) {
                if (hdsp->state & HDSP_FirmwareCached) {
                        if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-                               snd_printk("Firmware loading from cache failed, please upload manually.\n");
+                               snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
                        }
                } else {
-                       snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+                       snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
                }
                return -EIO;
        }
@@ -3957,10 +3916,10 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
        if (hdsp_check_for_firmware(hdsp)) {
                if (hdsp->state & HDSP_FirmwareCached) {
                        if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-                               snd_printk("Firmware loading from cache failed, please upload manually.\n");
+                               snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
                        }
                } else {
-                       snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+                       snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
                }
                return -EIO;
        }
@@ -4035,10 +3994,10 @@ static int snd_hdsp_prepare(snd_pcm_substream_t *substream)
        if (hdsp_check_for_firmware(hdsp)) {
                if (hdsp->state & HDSP_FirmwareCached) {
                        if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-                               snd_printk("Firmware loading from cache failed, please upload manually.\n");
+                               snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
                        }
                } else {
-                       snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+                       snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
                }
                return -EIO;
        }
@@ -4057,7 +4016,11 @@ static snd_pcm_hardware_t snd_hdsp_playback_subinfo =
                                 SNDRV_PCM_INFO_NONINTERLEAVED |
                                 SNDRV_PCM_INFO_SYNC_START |
                                 SNDRV_PCM_INFO_DOUBLE),
+#ifdef SNDRV_BIG_ENDIAN
+       .formats =              SNDRV_PCM_FMTBIT_S32_BE,
+#else
        .formats =              SNDRV_PCM_FMTBIT_S32_LE,
+#endif
        .rates =                (SNDRV_PCM_RATE_32000 |
                                 SNDRV_PCM_RATE_44100 | 
                                 SNDRV_PCM_RATE_48000 | 
@@ -4082,7 +4045,11 @@ static snd_pcm_hardware_t snd_hdsp_capture_subinfo =
                                 SNDRV_PCM_INFO_MMAP_VALID |
                                 SNDRV_PCM_INFO_NONINTERLEAVED |
                                 SNDRV_PCM_INFO_SYNC_START),
+#ifdef SNDRV_BIG_ENDIAN
+       .formats =              SNDRV_PCM_FMTBIT_S32_BE,
+#else
        .formats =              SNDRV_PCM_FMTBIT_S32_LE,
+#endif
        .rates =                (SNDRV_PCM_RATE_32000 |
                                 SNDRV_PCM_RATE_44100 | 
                                 SNDRV_PCM_RATE_48000 | 
@@ -4290,10 +4257,10 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
        if (hdsp_check_for_firmware(hdsp)) {
                if (hdsp->state & HDSP_FirmwareCached) {
                        if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-                               snd_printk("Firmware loading from cache failed, please upload manually.\n");
+                               snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
                        }
                } else {
-                       snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+                       snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
                }
                return -EIO;
        }
@@ -4306,11 +4273,6 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
        runtime->dma_area = hdsp->playback_buffer;
        runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
 
-       if (hdsp->capture_substream == NULL) {
-               hdsp_stop_audio(hdsp);
-               hdsp_set_thru(hdsp, -1, 0);
-       }
-
        hdsp->playback_pid = current->pid;
        hdsp->playback_substream = substream;
 
@@ -4373,10 +4335,10 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
        if (hdsp_check_for_firmware(hdsp)) {
                if (hdsp->state & HDSP_FirmwareCached) {
                        if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-                               snd_printk("Firmware loading from cache failed, please upload manually.\n");
+                               snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
                        }
                } else {
-                       snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+                       snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
                }
                return -EIO;
        }
@@ -4389,11 +4351,6 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
        runtime->dma_area = hdsp->capture_buffer;
        runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
 
-       if (hdsp->playback_substream == NULL) {
-               hdsp_stop_audio(hdsp);
-               hdsp_set_thru(hdsp, -1, 0);
-       }
-
        hdsp->capture_pid = current->pid;
        hdsp->capture_substream = substream;
 
@@ -4553,12 +4510,12 @@ static int hdsp_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
        }
        for (i = 0; i < 26; ++i) {
                if (copy_u64_le(&peak_rms->playback_rms[i],
-                               hdsp->iobase + HDSP_playbackRmsLevel + i * 8,
-                               hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4))
+                               hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
+                               hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
                        return -EFAULT;
                if (copy_u64_le(&peak_rms->input_rms[i], 
-                               hdsp->iobase + HDSP_inputRmsLevel + i * 8,
-                               hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4))
+                               hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
+                               hdsp->iobase + HDSP_inputRmsLevel + i * 8))
                        return -EFAULT;
        }
        return 0;
@@ -4574,7 +4531,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
                hdsp_peak_rms_t __user *peak_rms = (hdsp_peak_rms_t __user *)arg;
 
                if (!(hdsp->state & HDSP_FirmwareLoaded)) {
-                       snd_printk(KERN_ERR "firmware needs to be uploaded to the card.\n");
+                       snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n");
                        return -EINVAL;
                }
 
@@ -4593,7 +4550,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
                int i;
                
                if (!(hdsp->state & HDSP_FirmwareLoaded)) {
-                       snd_printk("Firmware needs to be uploaded to the card.\n");     
+                       snd_printk("Hammerfall-DSP: Firmware needs to be uploaded to the card.\n");     
                        return -EINVAL;
                }
                spin_lock_irqsave(&hdsp->lock, flags);
@@ -4618,7 +4575,6 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
                info.clock_source = (unsigned char)hdsp_clock_source(hdsp);
                info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp);
                info.line_out = (unsigned char)hdsp_line_out(hdsp);
-               info.passthru = (unsigned char)hdsp->passthru;
                if (hdsp->io_type == H9632) {
                        info.da_gain = (unsigned char)hdsp_da_gain(hdsp);
                        info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
@@ -4661,7 +4617,6 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
                }
                break;
        }
-#ifndef HDSP_FW_LOADER
        case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
                hdsp_firmware_t __user *firmware;
                u32 __user *firmware_data;
@@ -4674,7 +4629,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
                if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
                        return -EBUSY;
 
-               snd_printk("initializing firmware upload\n");
+               snd_printk("Hammerfall-DSP: initializing firmware upload\n");
                firmware = (hdsp_firmware_t __user *)argp;
 
                if (get_user(firmware_data, &firmware->firmware_data)) {
@@ -4696,18 +4651,20 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
                }
                
                if (!(hdsp->state & HDSP_InitializationComplete)) {
-                       snd_hdsp_initialize_channels(hdsp);
-               
+                       if ((err = snd_hdsp_enable_io(hdsp)) < 0) {
+                               return err;
+                       }
+                       
+                       snd_hdsp_initialize_channels(hdsp);             
                        snd_hdsp_initialize_midi_flush(hdsp);
            
                        if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
-                               snd_printk("error creating alsa devices\n");
+                               snd_printk("Hammerfall-DSP: error creating alsa devices\n");
                            return err;
                        }
                }
                break;
        }
-#endif
        case SNDRV_HDSP_IOCTL_GET_MIXER: {
                hdsp_mixer_t __user *mixer = (hdsp_mixer_t __user *)argp;
                if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
@@ -4794,6 +4751,7 @@ static int snd_hdsp_enable_io (hdsp_t *hdsp)
        int i;
        
        if (hdsp_fifo_wait (hdsp, 0, 100)) {
+               snd_printk("Hammerfall-DSP: enable_io fifo_wait failed\n");
                return -EIO;
        }
        
@@ -4859,24 +4817,25 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
        int err;
        
        if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
-               snd_printk("Error creating pcm interface\n");
+               snd_printk("Hammerfall-DSP: Error creating pcm interface\n");
                return err;
        }
        
 
        if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
-               snd_printk("Error creating first midi interface\n");
+               snd_printk("Hammerfall-DSP: Error creating first midi interface\n");
                return err;
        }
 
-
-       if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
-               snd_printk("Error creating second midi interface\n");
-               return err;
+       if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
+               if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
+                       snd_printk("Hammerfall-DSP: Error creating second midi interface\n");
+                       return err;
+               }
        }
 
        if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) {
-               snd_printk("Error creating ctl interface\n");
+               snd_printk("Hammerfall-DSP: Error creating ctl interface\n");
                return err;
        }
 
@@ -4889,7 +4848,7 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
        hdsp->playback_substream = NULL;
 
        if ((err = snd_hdsp_set_defaults(hdsp)) < 0) {
-               snd_printk("Error setting default values\n");
+               snd_printk("Hammerfall-DSP: Error setting default values\n");
                return err;
        }
        
@@ -4898,7 +4857,7 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
                        hdsp->port, hdsp->irq);
            
                if ((err = snd_card_register(card)) < 0) {
-                       snd_printk("error registering card\n");
+                       snd_printk("Hammerfall-DSP: error registering card\n");
                        return err;
                }
                hdsp->state |= HDSP_InitializationComplete;
@@ -4923,9 +4882,7 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
                if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
                        return 0;
        }
-       if (hdsp_check_for_iobox (hdsp))
-               return -EIO;
-
+       
        /* caution: max length of firmware filename is 30! */
        switch (hdsp->io_type) {
        case Multiface:
@@ -4941,16 +4898,16 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
                        fwfile = "digiface_firmware_rev11.bin";
                break;
        default:
-               snd_printk(KERN_ERR "hdsp: invalid io_type %d\n", hdsp->io_type);
+               snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type);
                return -EINVAL;
        }
 
        if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
-               snd_printk(KERN_ERR "hdsp: cannot load firmware %s\n", fwfile);
+               snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile);
                return -ENOENT;
        }
        if (fw->size < sizeof(hdsp->firmware_cache)) {
-               snd_printk(KERN_ERR "hdsp: too short firmware size %d (expected %d)\n",
+               snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n",
                           (int)fw->size, (int)sizeof(hdsp->firmware_cache));
                release_firmware(fw);
                return -EINVAL;
@@ -4958,7 +4915,7 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
 #ifdef SNDRV_BIG_ENDIAN
        {
                int i;
-               u32 *src = (void *)fw->data;
+               u32 *src = (u32*)fw->data;
                for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++)
                        hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) |
                                ((*src & 0x0000ff00) << 8)  |
@@ -4969,17 +4926,25 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
        memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
 #endif
        release_firmware(fw);
-       
+               
        hdsp->state |= HDSP_FirmwareCached;
 
        if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
                return err;
                
        if (!(hdsp->state & HDSP_InitializationComplete)) {
+               if ((err = snd_hdsp_enable_io(hdsp)) < 0) {
+                       return err;
+               }
+
+               if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) {
+                       snd_printk("Hammerfall-DSP: error creating hwdep device\n");
+                       return err;
+               }
                snd_hdsp_initialize_channels(hdsp);
                snd_hdsp_initialize_midi_flush(hdsp);
                if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
-                       snd_printk("error creating alsa devices\n");
+                       snd_printk("Hammerfall-DSP: error creating alsa devices\n");
                        return err;
                }
        }
@@ -4988,8 +4953,7 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
 #endif
 
 static int __devinit snd_hdsp_create(snd_card_t *card,
-                                    hdsp_t *hdsp,
-                                    int precise_ptr)
+                                    hdsp_t *hdsp)
 {
        struct pci_dev *pci = hdsp->pci;
        int err;
@@ -5004,6 +4968,8 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
        hdsp->midi[1].input = NULL;
        hdsp->midi[0].output = NULL;
        hdsp->midi[1].output = NULL;
+       hdsp->midi[0].pending = 0;
+       hdsp->midi[1].pending = 0;
        spin_lock_init(&hdsp->midi[0].lock);
        spin_lock_init(&hdsp->midi[1].lock);
        hdsp->iobase = NULL;
@@ -5019,6 +4985,7 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
        tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
        
        pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
+       hdsp->firmware_rev &= 0xff;
        
        /* From Martin Bjoernsen :
            "It is important that the card's latency timer register in
@@ -5032,27 +4999,17 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
        strcpy(card->driver, "H-DSP");
        strcpy(card->mixername, "Xilinx FPGA");
 
-       switch (hdsp->firmware_rev & 0xff) {
-       case 0xa:
-       case 0xb:
-       case 0x32:
+       if (hdsp->firmware_rev < 0xa) {
+               return -ENODEV;
+       } else if (hdsp->firmware_rev < 0x64) {
                hdsp->card_name = "RME Hammerfall DSP";
-               break;
-
-       case 0x64:
-       case 0x65:
-       case 0x68:
+       } else if (hdsp->firmware_rev < 0x96) {
                hdsp->card_name = "RME HDSP 9652";
                is_9652 = 1;
-               break;
-       case 0x96:
-       case 0x97:
+       } else {
                hdsp->card_name = "RME HDSP 9632";
                hdsp->max_channels = 16;
-               is_9632 = 1;
-               break;
-       default:
-               return -ENODEV;
+               is_9632 = 1;    
        }
 
        if ((err = pci_enable_device(pci)) < 0) {
@@ -5065,56 +5022,65 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
                return err;
        hdsp->port = pci_resource_start(pci, 0);
        if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
-               snd_printk("unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
+               snd_printk("Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
                return -EBUSY;
        }
 
        if (request_irq(pci->irq, snd_hdsp_interrupt, SA_INTERRUPT|SA_SHIRQ, "hdsp", (void *)hdsp)) {
-               snd_printk("unable to use IRQ %d\n", pci->irq);
+               snd_printk("Hammerfall-DSP: unable to use IRQ %d\n", pci->irq);
                return -EBUSY;
        }
 
        hdsp->irq = pci->irq;
-       hdsp->precise_ptr = precise_ptr;
+       hdsp->precise_ptr = 1;
+       hdsp->use_midi_tasklet = 1;
 
        if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) {
                return err;
        }
        
-       if (!is_9652 && !is_9632 && hdsp_check_for_iobox (hdsp)) {
-               /* no iobox connected, we defer initialization */
-               snd_printk("card initialization pending : waiting for firmware\n");
-               if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
-                       return err;
+       if (!is_9652 && !is_9632) {
+               /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */
+               if ((1000 / HZ) < 2000) {
+                       set_current_state(TASK_UNINTERRUPTIBLE);
+                       schedule_timeout((2000 * HZ + 999) / 1000);
+               } else {
+                       mdelay(2000);
+               }
+
+               if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
+#ifdef HDSP_FW_LOADER
+                       if ((err = hdsp_request_fw_loader(hdsp)) < 0) {
+                               /* we don't fail as this can happen
+                                  if userspace is not ready for
+                                  firmware upload
+                               */
+                               snd_printk("Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n");
+                       } else {
+                               /* init is complete, we return */
+                               return 0;
+                       }
+#endif
+                       /* no iobox connected, we defer initialization */
+                       snd_printk("Hammerfall-DSP: card initialization pending : waiting for firmware\n");
+                       if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
+                               return err;
+                       }
+                       return 0;
+               } else {
+                       snd_printk("Hammerfall-DSP: Firmware already present, initializing card.\n");       
+                       if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
+                               hdsp->io_type = Multiface;
+                       } else {
+                               hdsp->io_type = Digiface;
+                       }
                }
-               return 0;
        }
        
        if ((err = snd_hdsp_enable_io(hdsp)) != 0) {
                return err;
        }
        
-       if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
-#ifdef HDSP_FW_LOADER
-               if ((err = hdsp_request_fw_loader(hdsp)) < 0)
-                       return err;
-#else
-               snd_printk("card initialization pending : waiting for firmware\n");
-               if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
-                       return err;
-               }
-               return 0;
-#endif
-       } 
-       
-       snd_printk("Firmware already loaded, initializing card.\n");
-       
-       if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
-               hdsp->io_type = Multiface;
-       } else {
-               hdsp->io_type = Digiface;
-       }
-
        if (is_9652) {
                hdsp->io_type = H9652;
        }
@@ -5143,6 +5109,7 @@ static int snd_hdsp_free(hdsp_t *hdsp)
 {
        if (hdsp->port) {
                /* stop the audio, and cancel all interrupts */
+               tasklet_kill(&hdsp->midi_tasklet);
                hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
                hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
        }
@@ -5194,7 +5161,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci,
        hdsp->pci = pci;
        snd_card_set_dev(card, &pci->dev);
 
-       if ((err = snd_hdsp_create(card, hdsp, precise_ptr[dev])) < 0) {
+       if ((err = snd_hdsp_create(card, hdsp)) < 0) {
                snd_card_free(card);
                return err;
        }