Merge branch 'upstream-fixes'
[pandora-kernel.git] / sound / sparc / dbri.c
index 941c7b1..2164b7d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Driver for DBRI sound chip found on Sparcs.
- * Copyright (C) 2004 Martin Habets (mhabets@users.sourceforge.net)
+ * Copyright (C) 2004, 2005 Martin Habets (mhabets@users.sourceforge.net)
  *
  * Based entirely upon drivers/sbus/audio/dbri.c which is:
  * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
  * audio devices. But the SUN HW group decided against it, at least on my
  * LX the speakerbox connector has at least 1 pin missing and 1 wrongly
  * connected.
+ *
+ * I've tried to stick to the following function naming conventions:
+ * snd_*       ALSA stuff
+ * cs4215_*    CS4215 codec specfic stuff
+ * dbri_*      DBRI high-level stuff
+ * other       DBRI low-level stuff
  */
 
 #include <sound/driver.h>
@@ -87,7 +93,7 @@ MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard.");
 #define D_DESC (1<<5)
 
 static int dbri_debug = 0;
-module_param(dbri_debug, int, 0444);
+module_param(dbri_debug, int, 0644);
 MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard.");
 
 #ifdef DBRI_DEBUG
@@ -293,8 +299,8 @@ struct dbri_desc {
 };
 
 /* Per stream (playback or record) information */
-typedef struct dbri_streaminfo {
-       snd_pcm_substream_t *substream;
+struct dbri_streaminfo {
+       struct snd_pcm_substream *substream;
        u32 dvma_buffer;        /* Device view of Alsa DMA buffer */
        int left;               /* # of bytes left in DMA buffer  */
        int size;               /* Size of DMA buffer             */
@@ -303,12 +309,12 @@ typedef struct dbri_streaminfo {
        int left_gain;          /* mixer elements                 */
        int right_gain;
        int balance;
-} dbri_streaminfo_t;
+};
 
 /* This structure holds the information for both chips (DBRI & CS4215) */
-typedef struct snd_dbri {
-       snd_card_t *card;       /* ALSA card */
-       snd_pcm_t *pcm;
+struct snd_dbri {
+       struct snd_card *card;  /* ALSA card */
+       struct snd_pcm *pcm;
 
        int regs_size, irq;     /* Needed for unload */
        struct sbus_dev *sdev;  /* SBUS device info */
@@ -320,7 +326,8 @@ typedef struct snd_dbri {
        void __iomem *regs;     /* dbri HW regs */
        int dbri_version;       /* 'e' and up is OK */
        int dbri_irqp;          /* intr queue pointer */
-       int wait_seen;
+       int wait_send;          /* sequence of command buffers send */
+       int wait_ackd;          /* sequence of command buffers acknowledged */
 
        struct dbri_pipe pipes[DBRI_NO_PIPES];  /* DBRI's 32 data pipes */
        struct dbri_desc descs[DBRI_NO_DESCS];
@@ -334,10 +341,7 @@ typedef struct snd_dbri {
        struct dbri_streaminfo stream_info[DBRI_NO_STREAMS];
 
        struct snd_dbri *next;
-} snd_dbri_t;
-
-/* Needed for the ALSA macros to work */
-#define chip_t snd_dbri_t
+};
 
 #define DBRI_MAX_VOLUME                63      /* Output volume */
 #define DBRI_MAX_GAIN          15      /* Input gain */
@@ -589,7 +593,7 @@ typedef struct snd_dbri {
 /* Return a pointer to dbri_streaminfo */
 #define DBRI_STREAM(dbri, substream)   &dbri->stream_info[DBRI_STREAMNO(substream)]
 
-static snd_dbri_t *dbri_list = NULL;   /* All DBRI devices */
+static struct snd_dbri *dbri_list = NULL;      /* All DBRI devices */
 
 /*
  * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr.
@@ -625,16 +629,13 @@ static __u32 reverse_bytes(__u32 b, int len)
 
 Commands are sent to the DBRI by building a list of them in memory,
 then writing the address of the first list item to DBRI register 8.
-The list is terminated with a WAIT command, which can generate a
-CPU interrupt if required.
+The list is terminated with a WAIT command, which generates a
+CPU interrupt to signal completion.
 
 Since the DBRI can run in parallel with the CPU, several means of
-synchronization present themselves.  The original scheme (Rudolf's)
-was to set a flag when we "cmdlock"ed the DBRI, clear the flag when
-an interrupt signaled completion, and wait on a wait_queue if a routine
-attempted to cmdlock while the flag was set.  The problems arose when
-we tried to cmdlock from inside an interrupt handler, which might
-cause scheduling in an interrupt (if we waited), etc, etc
+synchronization present themselves.  The method implemented here is close
+to the original scheme (Rudolf's), and uses 2 counters (wait_send and
+wait_ackd) to synchronize the command buffer between the CPU and the DBRI.
 
 A more sophisticated scheme might involve a circular command buffer
 or an array of command buffers.  A routine could fill one with
@@ -642,76 +643,81 @@ commands and link it onto a list.  When a interrupt signaled
 completion of the current command buffer, look on the list for
 the next one.
 
-I've decided to implement something much simpler - after each command,
-the CPU waits for the DBRI to finish the command by polling the P bit
-in DBRI register 0.  I've tried to implement this in such a way
-that might make implementing a more sophisticated scheme easier.
-
 Every time a routine wants to write commands to the DBRI, it must
 first call dbri_cmdlock() and get an initial pointer into dbri->dma->cmd
-in return.  After the commands have been writen, dbri_cmdsend() is
-called with the final pointer value.
+in return. dbri_cmdlock() will block if the previous commands have not
+been completed yet. After this the commands can be written to the buffer,
+and dbri_cmdsend() is called with the final pointer value to send them
+to the DBRI.
 
 */
 
-enum dbri_lock_t { NoGetLock, GetLock };
+static void dbri_process_interrupt_buffer(struct snd_dbri * dbri);
+
+enum dbri_lock { NoGetLock, GetLock };
+#define MAXLOOPS 10
 
-static volatile s32 *dbri_cmdlock(snd_dbri_t * dbri, enum dbri_lock_t get)
+static volatile s32 *dbri_cmdlock(struct snd_dbri * dbri, enum dbri_lock get)
 {
+       int maxloops = MAXLOOPS;
+
 #ifndef SMP
        if ((get == GetLock) && spin_is_locked(&dbri->lock)) {
                printk(KERN_ERR "DBRI: cmdlock called while in spinlock.");
        }
 #endif
 
+       /* Delay if previous commands are still being processed */
+       while ((--maxloops) > 0 && (dbri->wait_send != dbri->wait_ackd)) {
+               msleep_interruptible(1);
+               /* If dbri_cmdlock() got called from inside the
+                * interrupt handler, this will do the processing.
+                */
+               dbri_process_interrupt_buffer(dbri);
+       }
+       if (maxloops == 0) {
+               printk(KERN_ERR "DBRI: Chip never completed command buffer %d\n",
+                       dbri->wait_send);
+       } else {
+               dprintk(D_CMD, "Chip completed command buffer (%d)\n",
+                       MAXLOOPS - maxloops - 1);
+       }
+
        /*if (get == GetLock) spin_lock(&dbri->lock); */
        return &dbri->dma->cmd[0];
 }
 
-static void dbri_process_interrupt_buffer(snd_dbri_t *);
-
-static void dbri_cmdsend(snd_dbri_t * dbri, volatile s32 * cmd)
+static void dbri_cmdsend(struct snd_dbri * dbri, volatile s32 * cmd)
 {
-       int MAXLOOPS = 1000000;
-       int maxloops = MAXLOOPS;
        volatile s32 *ptr;
+       u32     reg;
 
        for (ptr = &dbri->dma->cmd[0]; ptr < cmd; ptr++) {
                dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr);
        }
 
        if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS - 1) {
-               printk("DBRI: Command buffer overflow! (bug in driver)\n");
+               printk(KERN_ERR "DBRI: Command buffer overflow! (bug in driver)\n");
                /* Ignore the last part. */
                cmd = &dbri->dma->cmd[DBRI_NO_CMDS - 3];
        }
 
+       dbri->wait_send++;
+       dbri->wait_send &= 0xffff;      /* restrict it to a 16 bit counter. */
        *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
-       *(cmd++) = DBRI_CMD(D_WAIT, 1, 0);
-       dbri->wait_seen = 0;
+       *(cmd++) = DBRI_CMD(D_WAIT, 1, dbri->wait_send);
+
+       /* Set command pointer and signal it is valid. */
        sbus_writel(dbri->dma_dvma, dbri->regs + REG8);
-       while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P))
-               barrier();
-       if (maxloops == 0) {
-               printk(KERN_ERR "DBRI: Chip never completed command buffer\n");
-               dprintk(D_CMD, "DBRI: Chip never completed command buffer\n");
-       } else {
-               while ((--maxloops) > 0 && (!dbri->wait_seen))
-                       dbri_process_interrupt_buffer(dbri);
-               if (maxloops == 0) {
-                       printk(KERN_ERR "DBRI: Chip never acked WAIT\n");
-                       dprintk(D_CMD, "DBRI: Chip never acked WAIT\n");
-               } else {
-                       dprintk(D_CMD, "Chip completed command "
-                               "buffer (%d)\n", MAXLOOPS - maxloops);
-               }
-       }
+       reg = sbus_readl(dbri->regs + REG0);
+       reg |= D_P;
+       sbus_writel(reg, dbri->regs + REG0);
 
        /*spin_unlock(&dbri->lock); */
 }
 
 /* Lock must be held when calling this */
-static void dbri_reset(snd_dbri_t * dbri)
+static void dbri_reset(struct snd_dbri * dbri)
 {
        int i;
 
@@ -726,7 +732,7 @@ static void dbri_reset(snd_dbri_t * dbri)
 }
 
 /* Lock must not be held before calling this */
-static void dbri_initialize(snd_dbri_t * dbri)
+static void dbri_initialize(struct snd_dbri * dbri)
 {
        volatile s32 *cmd;
        u32 dma_addr, tmp;
@@ -757,10 +763,11 @@ static void dbri_initialize(snd_dbri_t * dbri)
        for (n = 0; n < DBRI_NO_PIPES; n++)
                dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1;
 
-       /* We should query the openprom to see what burst sizes this
-        * SBus supports.  For now, just disable all SBus bursts */
+       /* A brute approach - DBRI falls back to working burst size by itself
+        * On SS20 D_S does not work, so do not try so high. */
        tmp = sbus_readl(dbri->regs + REG0);
-       tmp &= ~(D_G | D_S | D_E);
+       tmp |= D_G | D_E;
+       tmp &= ~D_S;
        sbus_writel(tmp, dbri->regs + REG0);
 
        /*
@@ -788,7 +795,7 @@ list ordering, among other things.  The transmit and receive functions
 here interface closely with the transmit and receive interrupt code.
 
 */
-static int pipe_active(snd_dbri_t * dbri, int pipe)
+static int pipe_active(struct snd_dbri * dbri, int pipe)
 {
        return ((pipe >= 0) && (dbri->pipes[pipe].desc != -1));
 }
@@ -798,20 +805,20 @@ static int pipe_active(snd_dbri_t * dbri, int pipe)
  * Called on an in-use pipe to clear anything being transmitted or received
  * Lock must be held before calling this.
  */
-static void reset_pipe(snd_dbri_t * dbri, int pipe)
+static void reset_pipe(struct snd_dbri * dbri, int pipe)
 {
        int sdp;
        int desc;
        volatile int *cmd;
 
        if (pipe < 0 || pipe > 31) {
-               printk("DBRI: reset_pipe called with illegal pipe number\n");
+               printk(KERN_ERR "DBRI: reset_pipe called with illegal pipe number\n");
                return;
        }
 
        sdp = dbri->pipes[pipe].sdp;
        if (sdp == 0) {
-               printk("DBRI: reset_pipe called on uninitialized pipe\n");
+               printk(KERN_ERR "DBRI: reset_pipe called on uninitialized pipe\n");
                return;
        }
 
@@ -831,15 +838,15 @@ static void reset_pipe(snd_dbri_t * dbri, int pipe)
 }
 
 /* FIXME: direction as an argument? */
-static void setup_pipe(snd_dbri_t * dbri, int pipe, int sdp)
+static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp)
 {
        if (pipe < 0 || pipe > 31) {
-               printk("DBRI: setup_pipe called with illegal pipe number\n");
+               printk(KERN_ERR "DBRI: setup_pipe called with illegal pipe number\n");
                return;
        }
 
        if ((sdp & 0xf800) != sdp) {
-               printk("DBRI: setup_pipe called with strange SDP value\n");
+               printk(KERN_ERR "DBRI: setup_pipe called with strange SDP value\n");
                /* sdp &= 0xf800; */
        }
 
@@ -862,7 +869,7 @@ static void setup_pipe(snd_dbri_t * dbri, int pipe, int sdp)
 }
 
 /* FIXME: direction not needed */
-static void link_time_slot(snd_dbri_t * dbri, int pipe,
+static void link_time_slot(struct snd_dbri * dbri, int pipe,
                           enum in_or_out direction, int basepipe,
                           int length, int cycle)
 {
@@ -872,13 +879,13 @@ static void link_time_slot(snd_dbri_t * dbri, int pipe,
        int nextpipe;
 
        if (pipe < 0 || pipe > 31 || basepipe < 0 || basepipe > 31) {
-               printk
-                   ("DBRI: link_time_slot called with illegal pipe number\n");
+               printk(KERN_ERR 
+                   "DBRI: link_time_slot called with illegal pipe number\n");
                return;
        }
 
        if (dbri->pipes[pipe].sdp == 0 || dbri->pipes[basepipe].sdp == 0) {
-               printk("DBRI: link_time_slot called on uninitialized pipe\n");
+               printk(KERN_ERR "DBRI: link_time_slot called on uninitialized pipe\n");
                return;
        }
 
@@ -952,7 +959,7 @@ static void link_time_slot(snd_dbri_t * dbri, int pipe,
        dbri_cmdsend(dbri, cmd);
 }
 
-static void unlink_time_slot(snd_dbri_t * dbri, int pipe,
+static void unlink_time_slot(struct snd_dbri * dbri, int pipe,
                             enum in_or_out direction, int prevpipe,
                             int nextpipe)
 {
@@ -960,8 +967,8 @@ static void unlink_time_slot(snd_dbri_t * dbri, int pipe,
        int val;
 
        if (pipe < 0 || pipe > 31 || prevpipe < 0 || prevpipe > 31) {
-               printk
-                   ("DBRI: unlink_time_slot called with illegal pipe number\n");
+               printk(KERN_ERR 
+                   "DBRI: unlink_time_slot called with illegal pipe number\n");
                return;
        }
 
@@ -996,27 +1003,27 @@ static void unlink_time_slot(snd_dbri_t * dbri, int pipe,
  * in the low-order 8 bits, filled either MSB-first or LSB-first,
  * depending on the settings passed to setup_pipe()
  */
-static void xmit_fixed(snd_dbri_t * dbri, int pipe, unsigned int data)
+static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data)
 {
        volatile s32 *cmd;
 
        if (pipe < 16 || pipe > 31) {
-               printk("DBRI: xmit_fixed: Illegal pipe number\n");
+               printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n");
                return;
        }
 
        if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) {
-               printk("DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe);
+               printk(KERN_ERR "DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe);
                return;
        }
 
        if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
-               printk("DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe);
+               printk(KERN_ERR "DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe);
                return;
        }
 
        if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) {
-               printk("DBRI: xmit_fixed: Called on receive pipe %d\n", pipe);
+               printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", pipe);
                return;
        }
 
@@ -1033,20 +1040,20 @@ static void xmit_fixed(snd_dbri_t * dbri, int pipe, unsigned int data)
        dbri_cmdsend(dbri, cmd);
 }
 
-static void recv_fixed(snd_dbri_t * dbri, int pipe, volatile __u32 * ptr)
+static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr)
 {
        if (pipe < 16 || pipe > 31) {
-               printk("DBRI: recv_fixed called with illegal pipe number\n");
+               printk(KERN_ERR "DBRI: recv_fixed called with illegal pipe number\n");
                return;
        }
 
        if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
-               printk("DBRI: recv_fixed called on non-fixed pipe %d\n", pipe);
+               printk(KERN_ERR "DBRI: recv_fixed called on non-fixed pipe %d\n", pipe);
                return;
        }
 
        if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) {
-               printk("DBRI: recv_fixed called on transmit pipe %d\n", pipe);
+               printk(KERN_ERR "DBRI: recv_fixed called on transmit pipe %d\n", pipe);
                return;
        }
 
@@ -1065,9 +1072,9 @@ static void recv_fixed(snd_dbri_t * dbri, int pipe, volatile __u32 * ptr)
  * data buffers.  Buffers too large for a single descriptor will
  * be spread across multiple descriptors.
  */
-static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
+static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period)
 {
-       dbri_streaminfo_t *info = &dbri->stream_info[streamno];
+       struct dbri_streaminfo *info = &dbri->stream_info[streamno];
        __u32 dvma_buffer;
        int desc = 0;
        int len;
@@ -1075,12 +1082,12 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
        int last_desc = -1;
 
        if (info->pipe < 0 || info->pipe > 15) {
-               printk("DBRI: setup_descs: Illegal pipe number\n");
+               printk(KERN_ERR "DBRI: setup_descs: Illegal pipe number\n");
                return -2;
        }
 
        if (dbri->pipes[info->pipe].sdp == 0) {
-               printk("DBRI: setup_descs: Uninitialized pipe %d\n",
+               printk(KERN_ERR "DBRI: setup_descs: Uninitialized pipe %d\n",
                       info->pipe);
                return -2;
        }
@@ -1090,20 +1097,20 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
 
        if (streamno == DBRI_PLAY) {
                if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) {
-                       printk("DBRI: setup_descs: Called on receive pipe %d\n",
+                       printk(KERN_ERR "DBRI: setup_descs: Called on receive pipe %d\n",
                               info->pipe);
                        return -2;
                }
        } else {
                if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) {
-                       printk
-                           ("DBRI: setup_descs: Called on transmit pipe %d\n",
+                       printk(KERN_ERR 
+                           "DBRI: setup_descs: Called on transmit pipe %d\n",
                             info->pipe);
                        return -2;
                }
                /* Should be able to queue multiple buffers to receive on a pipe */
                if (pipe_active(dbri, info->pipe)) {
-                       printk("DBRI: recv_on_pipe: Called on active pipe %d\n",
+                       printk(KERN_ERR "DBRI: recv_on_pipe: Called on active pipe %d\n",
                               info->pipe);
                        return -2;
                }
@@ -1120,7 +1127,7 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
                                break;
                }
                if (desc == DBRI_NO_DESCS) {
-                       printk("DBRI: setup_descs: No descriptors\n");
+                       printk(KERN_ERR "DBRI: setup_descs: No descriptors\n");
                        return -1;
                }
 
@@ -1165,7 +1172,7 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
        }
 
        if (first_desc == -1 || last_desc == -1) {
-               printk("DBRI: setup_descs: Not enough descriptors available\n");
+               printk(KERN_ERR "DBRI: setup_descs: Not enough descriptors available\n");
                return -1;
        }
 
@@ -1200,7 +1207,7 @@ multiplexed serial interface which the DBRI can operate in either master
 
 enum master_or_slave { CHImaster, CHIslave };
 
-static void reset_chi(snd_dbri_t * dbri, enum master_or_slave master_or_slave,
+static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave,
                      int bits_per_frame)
 {
        volatile s32 *cmd;
@@ -1270,7 +1277,7 @@ static void reset_chi(snd_dbri_t * dbri, enum master_or_slave master_or_slave,
                int divisor = 12288 / clockrate;
 
                if (divisor > 255 || divisor * clockrate != 12288)
-                       printk("DBRI: illegal bits_per_frame in setup_chi\n");
+                       printk(KERN_ERR "DBRI: illegal bits_per_frame in setup_chi\n");
 
                *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD
                                    | D_CHI_BPF(bits_per_frame));
@@ -1301,7 +1308,7 @@ In the standard SPARC audio configuration, the CS4215 codec is attached
 to the DBRI via the CHI interface and few of the DBRI's PIO pins.
 
 */
-static void cs4215_setup_pipes(snd_dbri_t * dbri)
+static void cs4215_setup_pipes(struct snd_dbri * dbri)
 {
        /*
         * Data mode:
@@ -1362,7 +1369,7 @@ static int cs4215_init_data(struct cs4215 *mm)
        return 0;
 }
 
-static void cs4215_setdata(snd_dbri_t * dbri, int muted)
+static void cs4215_setdata(struct snd_dbri * dbri, int muted)
 {
        if (muted) {
                dbri->mm.data[0] |= 63;
@@ -1371,7 +1378,7 @@ static void cs4215_setdata(snd_dbri_t * dbri, int muted)
                dbri->mm.data[3] &= ~15;
        } else {
                /* Start by setting the playback attenuation. */
-               dbri_streaminfo_t *info = &dbri->stream_info[DBRI_PLAY];
+               struct dbri_streaminfo *info = &dbri->stream_info[DBRI_PLAY];
                int left_gain = info->left_gain % 64;
                int right_gain = info->right_gain % 64;
 
@@ -1402,7 +1409,7 @@ static void cs4215_setdata(snd_dbri_t * dbri, int muted)
 /*
  * Set the CS4215 to data mode.
  */
-static void cs4215_open(snd_dbri_t * dbri)
+static void cs4215_open(struct snd_dbri * dbri)
 {
        int data_width;
        u32 tmp;
@@ -1464,7 +1471,7 @@ static void cs4215_open(snd_dbri_t * dbri)
 /*
  * Send the control information (i.e. audio format)
  */
-static int cs4215_setctrl(snd_dbri_t * dbri)
+static int cs4215_setctrl(struct snd_dbri * dbri)
 {
        int i, val;
        u32 tmp;
@@ -1474,7 +1481,6 @@ static int cs4215_setctrl(snd_dbri_t * dbri)
        /* Temporarily mute outputs, and wait 1/8000 sec (125 us)
         * to make sure this takes.  This avoids clicking noises.
         */
-
        cs4215_setdata(dbri, 1);
        udelay(125);
 
@@ -1530,8 +1536,8 @@ static int cs4215_setctrl(snd_dbri_t * dbri)
        tmp |= D_C;             /* Enable CHI */
        sbus_writel(tmp, dbri->regs + REG0);
 
-       for (i = 64; ((dbri->mm.status & 0xe4) != 0x20); --i) {
-               udelay(125);
+       for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) {
+               msleep_interruptible(1);
        }
        if (i == 0) {
                dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n",
@@ -1564,7 +1570,7 @@ static int cs4215_setctrl(snd_dbri_t * dbri)
  * As part of the process we resend the settings for the data
  * timeslots as well.
  */
-static int cs4215_prepare(snd_dbri_t * dbri, unsigned int rate,
+static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate,
                          snd_pcm_format_t format, unsigned int channels)
 {
        int freq_idx;
@@ -1622,7 +1628,7 @@ static int cs4215_prepare(snd_dbri_t * dbri, unsigned int rate,
 /*
  *
  */
-static int cs4215_init(snd_dbri_t * dbri)
+static int cs4215_init(struct snd_dbri * dbri)
 {
        u32 reg2 = sbus_readl(dbri->regs + REG2);
        dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2);
@@ -1678,8 +1684,8 @@ buffer and calls dbri_process_one_interrupt() for each interrupt word.
 Complicated interrupts are handled by dedicated functions (which
 appear first in this file).  Any pending interrupts can be serviced by
 calling dbri_process_interrupt_buffer(), which works even if the CPU's
-interrupts are disabled.  This function is used by dbri_cmdsend()
-to make sure we're synced up with the chip after each command sequence,
+interrupts are disabled.  This function is used by dbri_cmdlock()
+to make sure we're synced up with the chip before each command sequence,
 even if we're running cli'ed.
 
 */
@@ -1691,8 +1697,8 @@ even if we're running cli'ed.
  */
 static void xmit_descs(unsigned long data)
 {
-       snd_dbri_t *dbri = (snd_dbri_t *) data;
-       dbri_streaminfo_t *info;
+       struct snd_dbri *dbri = (struct snd_dbri *) data;
+       struct dbri_streaminfo *info;
        volatile s32 *cmd;
        unsigned long flags;
        int first_td;
@@ -1758,23 +1764,25 @@ play:
        spin_unlock_irqrestore(&dbri->lock, flags);
 }
 
-DECLARE_TASKLET(xmit_descs_task, xmit_descs, 0);
+static DECLARE_TASKLET(xmit_descs_task, xmit_descs, 0);
 
 /* transmission_complete_intr()
  *
  * Called by main interrupt handler when DBRI signals transmission complete
  * on a pipe (interrupt triggered by the B bit in a transmit descriptor).
  *
- * Walks through the pipe's list of transmit buffer descriptors, releasing
- * each one's DMA buffer (if present), flagging the descriptor available,
- * and signaling its callback routine (if present), before proceeding
- * to the next one.  Stops when the first descriptor is found without
+ * Walks through the pipe's list of transmit buffer descriptors and marks
+ * them as available. Stops when the first descriptor is found without
  * TBC (Transmit Buffer Complete) set, or we've run through them all.
+ *
+ * The DMA buffers are not released, but re-used. Since the transmit buffer
+ * descriptors are not clobbered, they can be re-submitted as is. This is
+ * done by the xmit_descs() tasklet above since that could take longer.
  */
 
-static void transmission_complete_intr(snd_dbri_t * dbri, int pipe)
+static void transmission_complete_intr(struct snd_dbri * dbri, int pipe)
 {
-       dbri_streaminfo_t *info;
+       struct dbri_streaminfo *info;
        int td;
        int status;
 
@@ -1822,9 +1830,9 @@ static void transmission_complete_intr(snd_dbri_t * dbri, int pipe)
                snd_pcm_period_elapsed(info->substream);
 }
 
-static void reception_complete_intr(snd_dbri_t * dbri, int pipe)
+static void reception_complete_intr(struct snd_dbri * dbri, int pipe)
 {
-       dbri_streaminfo_t *info;
+       struct dbri_streaminfo *info;
        int rd = dbri->pipes[pipe].desc;
        s32 status;
 
@@ -1866,7 +1874,7 @@ static void reception_complete_intr(snd_dbri_t * dbri, int pipe)
                snd_pcm_period_elapsed(info->substream);
 }
 
-static void dbri_process_one_interrupt(snd_dbri_t * dbri, int x)
+static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x)
 {
        int val = D_INTR_GETVAL(x);
        int channel = D_INTR_GETCHAN(x);
@@ -1885,7 +1893,11 @@ static void dbri_process_one_interrupt(snd_dbri_t * dbri, int x)
        }
 
        if (channel == D_INTR_CMD && command == D_WAIT) {
-               dbri->wait_seen++;
+               dbri->wait_ackd = val;
+               if (dbri->wait_send != val) {
+                       printk(KERN_ERR "Processing wait command %d when %d was send.\n",
+                              val, dbri->wait_send);
+               }
                return;
        }
 
@@ -1938,7 +1950,7 @@ static void dbri_process_one_interrupt(snd_dbri_t * dbri, int x)
  * order is important since we might recurse back into this function
  * and need to make sure the pointer has been advanced first.
  */
-static void dbri_process_interrupt_buffer(snd_dbri_t * dbri)
+static void dbri_process_interrupt_buffer(struct snd_dbri * dbri)
 {
        s32 x;
 
@@ -1957,7 +1969,7 @@ static void dbri_process_interrupt_buffer(snd_dbri_t * dbri)
 static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id,
                                      struct pt_regs *regs)
 {
-       snd_dbri_t *dbri = dev_id;
+       struct snd_dbri *dbri = dev_id;
        static int errcnt = 0;
        int x;
 
@@ -1994,8 +2006,7 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id,
                 * The only one I've seen is MRR, which will be triggered
                 * if you let a transmit pipe underrun, then try to CDP it.
                 *
-                * If these things persist, we should probably reset
-                * and re-init the chip.
+                * If these things persist, we reset the chip.
                 */
                if ((++errcnt) % 10 == 0) {
                        dprintk(D_INT, "Interrupt errors exceeded.\n");
@@ -2019,7 +2030,7 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id,
 /****************************************************************************
                PCM Interface
 ****************************************************************************/
-static snd_pcm_hardware_t snd_dbri_pcm_hw = {
+static struct snd_pcm_hardware snd_dbri_pcm_hw = {
        .info                   = (SNDRV_PCM_INFO_MMAP |
                                   SNDRV_PCM_INFO_INTERLEAVED |
                                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -2040,11 +2051,11 @@ static snd_pcm_hardware_t snd_dbri_pcm_hw = {
        .periods_max            = 1024,
 };
 
-static int snd_dbri_open(snd_pcm_substream_t * substream)
+static int snd_dbri_open(struct snd_pcm_substream *substream)
 {
-       snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
-       snd_pcm_runtime_t *runtime = substream->runtime;
-       dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+       struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
        unsigned long flags;
 
        dprintk(D_USR, "open audio output.\n");
@@ -2063,10 +2074,10 @@ static int snd_dbri_open(snd_pcm_substream_t * substream)
        return 0;
 }
 
-static int snd_dbri_close(snd_pcm_substream_t * substream)
+static int snd_dbri_close(struct snd_pcm_substream *substream)
 {
-       snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
-       dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+       struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+       struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
 
        dprintk(D_USR, "close audio output.\n");
        info->substream = NULL;
@@ -2076,12 +2087,12 @@ static int snd_dbri_close(snd_pcm_substream_t * substream)
        return 0;
 }
 
-static int snd_dbri_hw_params(snd_pcm_substream_t * substream,
-                             snd_pcm_hw_params_t * hw_params)
+static int snd_dbri_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *hw_params)
 {
-       snd_pcm_runtime_t *runtime = substream->runtime;
-       snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
-       dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+       struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
        int direction;
        int ret;
 
@@ -2094,7 +2105,7 @@ static int snd_dbri_hw_params(snd_pcm_substream_t * substream,
 
        if ((ret = snd_pcm_lib_malloc_pages(substream,
                                params_buffer_bytes(hw_params))) < 0) {
-               snd_printk(KERN_ERR "malloc_pages failed with %d\n", ret);
+               printk(KERN_ERR "malloc_pages failed with %d\n", ret);
                return ret;
        }
 
@@ -2118,10 +2129,10 @@ static int snd_dbri_hw_params(snd_pcm_substream_t * substream,
        return 0;
 }
 
-static int snd_dbri_hw_free(snd_pcm_substream_t * substream)
+static int snd_dbri_hw_free(struct snd_pcm_substream *substream)
 {
-       snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
-       dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+       struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+       struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
        int direction;
        dprintk(D_USR, "hw_free.\n");
 
@@ -2142,11 +2153,11 @@ static int snd_dbri_hw_free(snd_pcm_substream_t * substream)
        return snd_pcm_lib_free_pages(substream);
 }
 
-static int snd_dbri_prepare(snd_pcm_substream_t * substream)
+static int snd_dbri_prepare(struct snd_pcm_substream *substream)
 {
-       snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
-       dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
-       snd_pcm_runtime_t *runtime = substream->runtime;
+       struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+       struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
        int ret;
 
        info->size = snd_pcm_lib_buffer_bytes(substream);
@@ -2173,10 +2184,10 @@ static int snd_dbri_prepare(snd_pcm_substream_t * substream)
        return ret;
 }
 
-static int snd_dbri_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_dbri_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-       snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
-       dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+       struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+       struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
        int ret = 0;
 
        switch (cmd) {
@@ -2200,10 +2211,10 @@ static int snd_dbri_trigger(snd_pcm_substream_t * substream, int cmd)
        return ret;
 }
 
-static snd_pcm_uframes_t snd_dbri_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_dbri_pointer(struct snd_pcm_substream *substream)
 {
-       snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
-       dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+       struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+       struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
        snd_pcm_uframes_t ret;
 
        ret = bytes_to_frames(substream->runtime, info->offset)
@@ -2213,7 +2224,7 @@ static snd_pcm_uframes_t snd_dbri_pointer(snd_pcm_substream_t * substream)
        return ret;
 }
 
-static snd_pcm_ops_t snd_dbri_ops = {
+static struct snd_pcm_ops snd_dbri_ops = {
        .open = snd_dbri_open,
        .close = snd_dbri_close,
        .ioctl = snd_pcm_lib_ioctl,
@@ -2224,9 +2235,9 @@ static snd_pcm_ops_t snd_dbri_ops = {
        .pointer = snd_dbri_pointer,
 };
 
-static int __devinit snd_dbri_pcm(snd_dbri_t * dbri)
+static int __devinit snd_dbri_pcm(struct snd_dbri * dbri)
 {
-       snd_pcm_t *pcm;
+       struct snd_pcm *pcm;
        int err;
 
        if ((err = snd_pcm_new(dbri->card,
@@ -2259,8 +2270,8 @@ static int __devinit snd_dbri_pcm(snd_dbri_t * dbri)
                        Mixer interface
 *****************************************************************************/
 
-static int snd_cs4215_info_volume(snd_kcontrol_t * kcontrol,
-                                 snd_ctl_elem_info_t * uinfo)
+static int snd_cs4215_info_volume(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 2;
@@ -2273,11 +2284,11 @@ static int snd_cs4215_info_volume(snd_kcontrol_t * kcontrol,
        return 0;
 }
 
-static int snd_cs4215_get_volume(snd_kcontrol_t * kcontrol,
-                                snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4215_get_volume(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol);
-       dbri_streaminfo_t *info;
+       struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
+       struct dbri_streaminfo *info;
        snd_assert(dbri != NULL, return -EINVAL);
        info = &dbri->stream_info[kcontrol->private_value];
        snd_assert(info != NULL, return -EINVAL);
@@ -2287,11 +2298,11 @@ static int snd_cs4215_get_volume(snd_kcontrol_t * kcontrol,
        return 0;
 }
 
-static int snd_cs4215_put_volume(snd_kcontrol_t * kcontrol,
-                                snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol);
-       dbri_streaminfo_t *info = &dbri->stream_info[kcontrol->private_value];
+       struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
+       struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value];
        unsigned long flags;
        int changed = 0;
 
@@ -2318,8 +2329,8 @@ static int snd_cs4215_put_volume(snd_kcontrol_t * kcontrol,
        return changed;
 }
 
-static int snd_cs4215_info_single(snd_kcontrol_t * kcontrol,
-                                 snd_ctl_elem_info_t * uinfo)
+static int snd_cs4215_info_single(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_info *uinfo)
 {
        int mask = (kcontrol->private_value >> 16) & 0xff;
 
@@ -2331,10 +2342,10 @@ static int snd_cs4215_info_single(snd_kcontrol_t * kcontrol,
        return 0;
 }
 
-static int snd_cs4215_get_single(snd_kcontrol_t * kcontrol,
-                                snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4215_get_single(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol);
+       struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
        int elem = kcontrol->private_value & 0xff;
        int shift = (kcontrol->private_value >> 8) & 0xff;
        int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -2356,10 +2367,10 @@ static int snd_cs4215_get_single(snd_kcontrol_t * kcontrol,
        return 0;
 }
 
-static int snd_cs4215_put_single(snd_kcontrol_t * kcontrol,
-                                snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol);
+       struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
        unsigned long flags;
        int elem = kcontrol->private_value & 0xff;
        int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -2414,7 +2425,7 @@ static int snd_cs4215_put_single(snd_kcontrol_t * kcontrol,
   .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \
   .private_value = entry | (shift << 8) | (mask << 16) | (invert << 24) },
 
-static snd_kcontrol_new_t dbri_controls[] __devinitdata = {
+static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
        {
         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
         .name  = "Playback Volume",
@@ -2441,11 +2452,11 @@ static snd_kcontrol_new_t dbri_controls[] __devinitdata = {
        CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
 };
 
-#define NUM_CS4215_CONTROLS (sizeof(dbri_controls)/sizeof(snd_kcontrol_new_t))
+#define NUM_CS4215_CONTROLS (sizeof(dbri_controls)/sizeof(struct snd_kcontrol_new))
 
-static int __init snd_dbri_mixer(snd_dbri_t * dbri)
+static int __init snd_dbri_mixer(struct snd_dbri * dbri)
 {
-       snd_card_t *card;
+       struct snd_card *card;
        int idx, err;
 
        snd_assert(dbri != NULL && dbri->card != NULL, return -EINVAL);
@@ -2455,8 +2466,7 @@ static int __init snd_dbri_mixer(snd_dbri_t * dbri)
 
        for (idx = 0; idx < NUM_CS4215_CONTROLS; idx++) {
                if ((err = snd_ctl_add(card,
-                                      snd_ctl_new1(&dbri_controls[idx],
-                                                   dbri))) < 0)
+                               snd_ctl_new1(&dbri_controls[idx], dbri))) < 0)
                        return err;
        }
 
@@ -2472,9 +2482,9 @@ static int __init snd_dbri_mixer(snd_dbri_t * dbri)
 /****************************************************************************
                        /proc interface
 ****************************************************************************/
-static void dbri_regs_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
+static void dbri_regs_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer)
 {
-       snd_dbri_t *dbri = entry->private_data;
+       struct snd_dbri *dbri = entry->private_data;
 
        snd_iprintf(buffer, "REG0: 0x%x\n", sbus_readl(dbri->regs + REG0));
        snd_iprintf(buffer, "REG2: 0x%x\n", sbus_readl(dbri->regs + REG2));
@@ -2483,15 +2493,13 @@ static void dbri_regs_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
 }
 
 #ifdef DBRI_DEBUG
-static void dbri_debug_read(snd_info_entry_t * entry,
-                           snd_info_buffer_t * buffer)
+static void dbri_debug_read(struct snd_info_entry * entry,
+                           struct snd_info_buffer *buffer)
 {
-       snd_dbri_t *dbri = entry->private_data;
+       struct snd_dbri *dbri = entry->private_data;
        int pipe;
        snd_iprintf(buffer, "debug=%d\n", dbri_debug);
 
-       snd_iprintf(buffer, "CHI pipe in=%d, out=%d\n",
-                   dbri->chi_in_pipe, dbri->chi_out_pipe);
        for (pipe = 0; pipe < 32; pipe++) {
                if (pipe_active(dbri, pipe)) {
                        struct dbri_pipe *pptr = &dbri->pipes[pipe];
@@ -2506,34 +2514,20 @@ static void dbri_debug_read(snd_info_entry_t * entry,
                }
        }
 }
-
-static void dbri_debug_write(snd_info_entry_t * entry,
-                            snd_info_buffer_t * buffer)
-{
-       char line[80];
-       int i;
-
-       if (snd_info_get_line(buffer, line, 80) == 0) {
-               sscanf(line, "%d\n", &i);
-               dbri_debug = i & 0x3f;
-       }
-}
 #endif
 
-void snd_dbri_proc(snd_dbri_t * dbri)
+void snd_dbri_proc(struct snd_dbri * dbri)
 {
-       snd_info_entry_t *entry;
-       int err;
+       struct snd_info_entry *entry;
 
-       err = snd_card_proc_new(dbri->card, "regs", &entry);
-       snd_info_set_text_ops(entry, dbri, 1024, dbri_regs_read);
+       if (! snd_card_proc_new(dbri->card, "regs", &entry))
+               snd_info_set_text_ops(entry, dbri, 1024, dbri_regs_read);
 
 #ifdef DBRI_DEBUG
-       err = snd_card_proc_new(dbri->card, "debug", &entry);
-       snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read);
-       entry->mode = S_IFREG | S_IRUGO | S_IWUSR; /* Writable for root */
-       entry->c.text.write_size = 256;
-       entry->c.text.write = dbri_debug_write;
+       if (! snd_card_proc_new(dbri->card, "debug", &entry)) {
+               snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read);
+               entry->mode = S_IFREG | S_IRUGO;        /* Readable only. */
+       }
 #endif
 }
 
@@ -2542,13 +2536,13 @@ void snd_dbri_proc(snd_dbri_t * dbri)
 **************************** Initialization ********************************
 ****************************************************************************
 */
-static void snd_dbri_free(snd_dbri_t * dbri);
+static void snd_dbri_free(struct snd_dbri * dbri);
 
-static int __init snd_dbri_create(snd_card_t * card,
+static int __init snd_dbri_create(struct snd_card *card,
                                  struct sbus_dev *sdev,
                                  struct linux_prom_irqs *irq, int dev)
 {
-       snd_dbri_t *dbri = card->private_data;
+       struct snd_dbri *dbri = card->private_data;
        int err;
 
        spin_lock_init(&dbri->lock);
@@ -2599,7 +2593,7 @@ static int __init snd_dbri_create(snd_card_t * card,
        return 0;
 }
 
-static void snd_dbri_free(snd_dbri_t * dbri)
+static void snd_dbri_free(struct snd_dbri * dbri)
 {
        dprintk(D_GEN, "snd_dbri_free\n");
        dbri_reset(dbri);
@@ -2617,10 +2611,10 @@ static void snd_dbri_free(snd_dbri_t * dbri)
 
 static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
 {
-       snd_dbri_t *dbri;
+       struct snd_dbri *dbri;
        struct linux_prom_irqs irq;
        struct resource *rp;
-       snd_card_t *card;
+       struct snd_card *card;
        static int dev = 0;
        int err;
 
@@ -2637,10 +2631,14 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
                return -ENOENT;
        }
 
-       prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq));
+       err = prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq));
+       if (err < 0) {
+               printk(KERN_ERR "DBRI-%d: Firmware node lacks IRQ property.\n", dev);
+               return -ENODEV;
+       }
 
        card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-                           sizeof(snd_dbri_t));
+                           sizeof(struct snd_dbri));
        if (card == NULL)
                return -ENOMEM;
 
@@ -2656,27 +2654,18 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
                return err;
        }
 
-       dbri = (snd_dbri_t *) card->private_data;
-       if ((err = snd_dbri_pcm(dbri)) < 0) {
-               snd_dbri_free(dbri);
-               snd_card_free(card);
-               return err;
-       }
+       dbri = card->private_data;
+       if ((err = snd_dbri_pcm(dbri)) < 0)
+               goto _err;
 
-       if ((err = snd_dbri_mixer(dbri)) < 0) {
-               snd_dbri_free(dbri);
-               snd_card_free(card);
-               return err;
-       }
+       if ((err = snd_dbri_mixer(dbri)) < 0)
+               goto _err;
 
        /* /proc file handling */
        snd_dbri_proc(dbri);
 
-       if ((err = snd_card_register(card)) < 0) {
-               snd_dbri_free(dbri);
-               snd_card_free(card);
-               return err;
-       }
+       if ((err = snd_card_register(card)) < 0)
+               goto _err;
 
        printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n",
               dev, dbri->regs,
@@ -2684,6 +2673,11 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
        dev++;
 
        return 0;
+
+ _err:
+       snd_dbri_free(dbri);
+       snd_card_free(card);
+       return err;
 }
 
 /* Probe for the dbri chip and then attach the driver. */
@@ -2712,11 +2706,11 @@ static int __init dbri_init(void)
 
 static void __exit dbri_exit(void)
 {
-       snd_dbri_t *this = dbri_list;
+       struct snd_dbri *this = dbri_list;
 
        while (this != NULL) {
-               snd_dbri_t *next = this->next;
-               snd_card_t *card = this->card;
+               struct snd_dbri *next = this->next;
+               struct snd_card *card = this->card;
 
                snd_dbri_free(this);
                snd_card_free(card);