Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / sound / sparc / cs4231.c
index 36f9fe4..8804f26 100644 (file)
@@ -61,26 +61,49 @@ MODULE_DESCRIPTION("Sun CS4231");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}");
 
-typedef struct snd_cs4231 {
-       spinlock_t              lock;
-       void __iomem            *port;
+#ifdef SBUS_SUPPORT
+struct sbus_dma_info {
+       spinlock_t      lock;
+       int             dir;
+       void __iomem    *regs;
+};
+#endif
+
+struct snd_cs4231;
+struct cs4231_dma_control {
+        void           (*prepare)(struct cs4231_dma_control *dma_cont, int dir);
+        void           (*enable)(struct cs4231_dma_control *dma_cont, int on);
+        int            (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len);
+        unsigned int   (*address)(struct cs4231_dma_control *dma_cont);
+        void           (*reset)(struct snd_cs4231 *chip); 
+        void           (*preallocate)(struct snd_cs4231 *chip, struct snd_pcm *pcm); 
 #ifdef EBUS_SUPPORT
-       struct ebus_dma_info    eb2c;
-       struct ebus_dma_info    eb2p;
+       struct          ebus_dma_info   ebus_info;
+#endif
+#ifdef SBUS_SUPPORT
+       struct          sbus_dma_info   sbus_info;
 #endif
+};
+
+struct snd_cs4231 {
+       spinlock_t              lock;
+       void __iomem            *port;
+
+       struct cs4231_dma_control       p_dma;
+       struct cs4231_dma_control       c_dma;
 
        u32                     flags;
 #define CS4231_FLAG_EBUS       0x00000001
 #define CS4231_FLAG_PLAYBACK   0x00000002
 #define CS4231_FLAG_CAPTURE    0x00000004
 
-       snd_card_t              *card;
-       snd_pcm_t               *pcm;
-       snd_pcm_substream_t     *playback_substream;
+       struct snd_card         *card;
+       struct snd_pcm          *pcm;
+       struct snd_pcm_substream        *playback_substream;
        unsigned int            p_periods_sent;
-       snd_pcm_substream_t     *capture_substream;
+       struct snd_pcm_substream        *capture_substream;
        unsigned int            c_periods_sent;
-       snd_timer_t             *timer;
+       struct snd_timer        *timer;
 
        unsigned short mode;
 #define CS4231_MODE_NONE       0x0000
@@ -92,8 +115,8 @@ typedef struct snd_cs4231 {
        unsigned char           image[32];      /* registers image */
        int                     mce_bit;
        int                     calibrate_mute;
-       struct semaphore        mce_mutex;
-       struct semaphore        open_mutex;
+       struct mutex            mce_mutex;
+       struct mutex            open_mutex;
 
        union {
 #ifdef SBUS_SUPPORT
@@ -106,9 +129,9 @@ typedef struct snd_cs4231 {
        unsigned int            irq[2];
        unsigned int            regs_size;
        struct snd_cs4231       *next;
-} cs4231_t;
+};
 
-static cs4231_t *cs4231_list;
+static struct snd_cs4231 *cs4231_list;
 
 /* Eventually we can use sound/isa/cs423x/cs4231_lib.c directly, but for
  * now....  -DaveM
@@ -173,7 +196,7 @@ static cs4231_t *cs4231_list;
 
 #define CS4231_GLOBALIRQ       0x01    /* IRQ is active */
 
-/* definitions for codec irq status */
+/* definitions for codec irq status - CS4231_IRQ_STATUS        */
 
 #define CS4231_PLAYBACK_IRQ    0x10
 #define CS4231_RECORD_IRQ      0x20
@@ -251,6 +274,15 @@ static cs4231_t *cs4231_list;
 #define APCPNVA        0x38UL  /* APC Play DMA Next Address */
 #define APCPNC 0x3cUL  /* APC Play Next Count */
 
+/* Defines for SBUS DMA-routines */
+
+#define APCVA  0x0UL   /* APC DMA Address */
+#define APCC   0x4UL   /* APC Count */
+#define APCNVA 0x8UL   /* APC DMA Next Address */
+#define APCNC  0xcUL   /* APC Next Count */
+#define APC_PLAY 0x30UL        /* Play registers start at 0x30 */
+#define APC_RECORD 0x20UL /* Record registers start at 0x20 */
+
 /* APCCSR bits */
 
 #define APC_INT_PENDING 0x800000 /* Interrupt Pending */
@@ -308,12 +340,12 @@ static unsigned int rates[14] = {
        27042, 32000, 33075, 37800, 44100, 48000
 };
 
-static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
        .count  = 14,
        .list   = rates,
 };
 
-static int snd_cs4231_xrate(snd_pcm_runtime_t *runtime)
+static int snd_cs4231_xrate(struct snd_pcm_runtime *runtime)
 {
        return snd_pcm_hw_constraint_list(runtime, 0,
                                          SNDRV_PCM_HW_PARAM_RATE,
@@ -356,7 +388,7 @@ static unsigned char snd_cs4231_original_image[32] =
        0x00,                   /* 1f/31 - cbrl */
 };
 
-static u8 __cs4231_readb(cs4231_t *cp, void __iomem *reg_addr)
+static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr)
 {
 #ifdef EBUS_SUPPORT
        if (cp->flags & CS4231_FLAG_EBUS) {
@@ -371,7 +403,7 @@ static u8 __cs4231_readb(cs4231_t *cp, void __iomem *reg_addr)
 #endif
 }
 
-static void __cs4231_writeb(cs4231_t *cp, u8 val, void __iomem *reg_addr)
+static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, void __iomem *reg_addr)
 {
 #ifdef EBUS_SUPPORT
        if (cp->flags & CS4231_FLAG_EBUS) {
@@ -390,7 +422,7 @@ static void __cs4231_writeb(cs4231_t *cp, u8 val, void __iomem *reg_addr)
  *  Basic I/O functions
  */
 
-static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
+static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg,
                     unsigned char mask, unsigned char value)
 {
        int timeout;
@@ -402,7 +434,7 @@ static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
                udelay(100);
 #ifdef CONFIG_SND_DEBUG
        if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-               snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+               snd_printdd("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
 #endif
        if (chip->calibrate_mute) {
                chip->image[reg] &= mask;
@@ -417,7 +449,7 @@ static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
        }
 }
 
-static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char value)
+static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
 {
        int timeout;
 
@@ -425,12 +457,16 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val
             timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
             timeout--)
                udelay(100);
+#ifdef CONFIG_SND_DEBUG
+       if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
+               snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+#endif
        __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
        __cs4231_writeb(chip, value, CS4231P(chip, REG));
        mb();
 }
 
-static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char value)
+static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
 {
        int timeout;
 
@@ -440,18 +476,15 @@ static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char valu
                udelay(100);
 #ifdef CONFIG_SND_DEBUG
        if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-               snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+               snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
 #endif
        __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
        __cs4231_writeb(chip, value, CS4231P(chip, REG));
        chip->image[reg] = value;
        mb();
-#if 0
-       printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value);
-#endif
 }
 
-static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
+static unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg)
 {
        int timeout;
        unsigned char ret;
@@ -462,80 +495,34 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
                udelay(100);
 #ifdef CONFIG_SND_DEBUG
        if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-               snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
+               snd_printdd("in: auto calibration time out - reg = 0x%x\n", reg);
 #endif
        __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
        mb();
        ret = __cs4231_readb(chip, CS4231P(chip, REG));
-#if 0
-       printk("codec in - reg 0x%x = 0x%x\n", chip->mce_bit | reg, ret);
-#endif
        return ret;
 }
 
-#if 0
-
-static void snd_cs4231_debug(cs4231_t *chip)
-{
-       printk("CS4231 REGS:      INDEX = 0x%02x  ",
-              __cs4231_readb(chip, CS4231P(chip, REGSEL)));
-       printk("                 STATUS = 0x%02x\n",
-              __cs4231_readb(chip, CS4231P(chip, STATUS)));
-       printk("  0x00: left input      = 0x%02x  ", snd_cs4231_in(chip, 0x00));
-       printk("  0x10: alt 1 (CFIG 2)  = 0x%02x\n", snd_cs4231_in(chip, 0x10));
-       printk("  0x01: right input     = 0x%02x  ", snd_cs4231_in(chip, 0x01));
-       printk("  0x11: alt 2 (CFIG 3)  = 0x%02x\n", snd_cs4231_in(chip, 0x11));
-       printk("  0x02: GF1 left input  = 0x%02x  ", snd_cs4231_in(chip, 0x02));
-       printk("  0x12: left line in    = 0x%02x\n", snd_cs4231_in(chip, 0x12));
-       printk("  0x03: GF1 right input = 0x%02x  ", snd_cs4231_in(chip, 0x03));
-       printk("  0x13: right line in   = 0x%02x\n", snd_cs4231_in(chip, 0x13));
-       printk("  0x04: CD left input   = 0x%02x  ", snd_cs4231_in(chip, 0x04));
-       printk("  0x14: timer low       = 0x%02x\n", snd_cs4231_in(chip, 0x14));
-       printk("  0x05: CD right input  = 0x%02x  ", snd_cs4231_in(chip, 0x05));
-       printk("  0x15: timer high      = 0x%02x\n", snd_cs4231_in(chip, 0x15));
-       printk("  0x06: left output     = 0x%02x  ", snd_cs4231_in(chip, 0x06));
-       printk("  0x16: left MIC (PnP)  = 0x%02x\n", snd_cs4231_in(chip, 0x16));
-       printk("  0x07: right output    = 0x%02x  ", snd_cs4231_in(chip, 0x07));
-       printk("  0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17));
-       printk("  0x08: playback format = 0x%02x  ", snd_cs4231_in(chip, 0x08));
-       printk("  0x18: IRQ status      = 0x%02x\n", snd_cs4231_in(chip, 0x18));
-       printk("  0x09: iface (CFIG 1)  = 0x%02x  ", snd_cs4231_in(chip, 0x09));
-       printk("  0x19: left line out   = 0x%02x\n", snd_cs4231_in(chip, 0x19));
-       printk("  0x0a: pin control     = 0x%02x  ", snd_cs4231_in(chip, 0x0a));
-       printk("  0x1a: mono control    = 0x%02x\n", snd_cs4231_in(chip, 0x1a));
-       printk("  0x0b: init & status   = 0x%02x  ", snd_cs4231_in(chip, 0x0b));
-       printk("  0x1b: right line out  = 0x%02x\n", snd_cs4231_in(chip, 0x1b));
-       printk("  0x0c: revision & mode = 0x%02x  ", snd_cs4231_in(chip, 0x0c));
-       printk("  0x1c: record format   = 0x%02x\n", snd_cs4231_in(chip, 0x1c));
-       printk("  0x0d: loopback        = 0x%02x  ", snd_cs4231_in(chip, 0x0d));
-       printk("  0x1d: var freq (PnP)  = 0x%02x\n", snd_cs4231_in(chip, 0x1d));
-       printk("  0x0e: ply upr count   = 0x%02x  ", snd_cs4231_in(chip, 0x0e));
-       printk("  0x1e: rec upr count   = 0x%02x\n", snd_cs4231_in(chip, 0x1e));
-       printk("  0x0f: ply lwr count   = 0x%02x  ", snd_cs4231_in(chip, 0x0f));
-       printk("  0x1f: rec lwr count   = 0x%02x\n", snd_cs4231_in(chip, 0x1f));
-}
-
-#endif
-
 /*
  *  CS4231 detection / MCE routines
  */
 
-static void snd_cs4231_busy_wait(cs4231_t *chip)
+static void snd_cs4231_busy_wait(struct snd_cs4231 *chip)
 {
        int timeout;
 
        /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
        for (timeout = 5; timeout > 0; timeout--)
                __cs4231_readb(chip, CS4231P(chip, REGSEL));
+
        /* end of cleanup sequence */
-       for (timeout = 250;
+       for (timeout = 500;
             timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
             timeout--)
-               udelay(100);
+               udelay(1000);
 }
 
-static void snd_cs4231_mce_up(cs4231_t *chip)
+static void snd_cs4231_mce_up(struct snd_cs4231 *chip)
 {
        unsigned long flags;
        int timeout;
@@ -545,36 +532,33 @@ static void snd_cs4231_mce_up(cs4231_t *chip)
                udelay(100);
 #ifdef CONFIG_SND_DEBUG
        if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-               snd_printk("mce_up - auto calibration time out (0)\n");
+               snd_printdd("mce_up - auto calibration time out (0)\n");
 #endif
        chip->mce_bit |= CS4231_MCE;
        timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
        if (timeout == 0x80)
-               snd_printk("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
+               snd_printdd("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
        if (!(timeout & CS4231_MCE))
                __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
        spin_unlock_irqrestore(&chip->lock, flags);
 }
 
-static void snd_cs4231_mce_down(cs4231_t *chip)
+static void snd_cs4231_mce_down(struct snd_cs4231 *chip)
 {
        unsigned long flags;
        int timeout;
 
        spin_lock_irqsave(&chip->lock, flags);
        snd_cs4231_busy_wait(chip);
-#if 0
-       printk("(1) timeout = %i\n", timeout);
-#endif
 #ifdef CONFIG_SND_DEBUG
        if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-               snd_printk("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
+               snd_printdd("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
 #endif
        chip->mce_bit &= ~CS4231_MCE;
        timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
        __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
        if (timeout == 0x80)
-               snd_printk("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
+               snd_printdd("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
        if ((timeout & CS4231_MCE) == 0) {
                spin_unlock_irqrestore(&chip->lock, flags);
                return;
@@ -590,9 +574,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
                spin_unlock_irqrestore(&chip->lock, flags);
                return;
        }
-#if 0
-       printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
-#endif
+
        /* in 10ms increments, check condition, up to 250ms */
        timeout = 25;
        while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) {
@@ -604,9 +586,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
                msleep(10);
                spin_lock_irqsave(&chip->lock, flags);
        }
-#if 0
-       printk("(3) jiffies = %li\n", jiffies);
-#endif
+
        /* in 10ms increments, check condition, up to 100ms */
        timeout = 10;
        while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) {
@@ -619,90 +599,61 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
                spin_lock_irqsave(&chip->lock, flags);
        }
        spin_unlock_irqrestore(&chip->lock, flags);
-#if 0
-       printk("(4) jiffies = %li\n", jiffies);
-       snd_printk("mce_down - exit = 0x%x\n", __cs4231_readb(chip, CS4231P(chip, REGSEL)));
-#endif
 }
 
-#if 0 /* Unused for now... */
-static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size)
+static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont,
+                                  struct snd_pcm_substream *substream,
+                                  unsigned int *periods_sent)
 {
-       switch (format & 0xe0) {
-       case CS4231_LINEAR_16:
-       case CS4231_LINEAR_16_BIG:
-               size >>= 1;
-               break;
-       case CS4231_ADPCM_16:
-               return size >> 2;
-       }
-       if (format & CS4231_STEREO)
-               size >>= 1;
-       return size;
-}
-#endif
-
-#ifdef EBUS_SUPPORT
-static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent)
-{
-       snd_pcm_runtime_t *runtime = substream->runtime;
+       struct snd_pcm_runtime *runtime = substream->runtime;
 
        while (1) {
-               unsigned int dma_size = snd_pcm_lib_period_bytes(substream);
-               unsigned int offset = dma_size * (*periods_sent);
+               unsigned int period_size = snd_pcm_lib_period_bytes(substream);
+               unsigned int offset = period_size * (*periods_sent);
 
-               if (dma_size >= (1 << 24))
-                       BUG();
+               BUG_ON(period_size >= (1 << 24));
 
-               if (ebus_dma_request(p, runtime->dma_addr + offset, dma_size))
+               if (dma_cont->request(dma_cont, runtime->dma_addr + offset, period_size))
                        return;
-#if 0
-               printk("ebus_advance: Sent period %u (size[%x] offset[%x])\n",
-                      (*periods_sent), dma_size, offset);
-#endif
                (*periods_sent) = ((*periods_sent) + 1) % runtime->periods;
        }
 }
-#endif
 
-static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on)
+static void cs4231_dma_trigger(struct snd_pcm_substream *substream,
+                              unsigned int what, int on)
 {
-#ifdef EBUS_SUPPORT
-       if (chip->flags & CS4231_FLAG_EBUS) {
-               if (what & CS4231_PLAYBACK_ENABLE) {
-                       if (on) {
-                               ebus_dma_prepare(&chip->eb2p, 0);
-                               ebus_dma_enable(&chip->eb2p, 1);
-                               snd_cs4231_ebus_advance_dma(&chip->eb2p,
-                                       chip->playback_substream,
-                                       &chip->p_periods_sent);
-                       } else {
-                               ebus_dma_enable(&chip->eb2p, 0);
-                       }
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+       struct cs4231_dma_control *dma_cont;
+
+       if (what & CS4231_PLAYBACK_ENABLE) {
+               dma_cont = &chip->p_dma;
+               if (on) {
+                       dma_cont->prepare(dma_cont, 0);
+                       dma_cont->enable(dma_cont, 1);
+                       snd_cs4231_advance_dma(dma_cont,
+                               chip->playback_substream,
+                               &chip->p_periods_sent);
+               } else {
+                       dma_cont->enable(dma_cont, 0);
                }
-               if (what & CS4231_RECORD_ENABLE) {
-                       if (on) {
-                               ebus_dma_prepare(&chip->eb2c, 1);
-                               ebus_dma_enable(&chip->eb2c, 1);
-                               snd_cs4231_ebus_advance_dma(&chip->eb2c,
-                                       chip->capture_substream,
-                                       &chip->c_periods_sent);
-                       } else {
-                               ebus_dma_enable(&chip->eb2c, 0);
-                       }
+       }
+       if (what & CS4231_RECORD_ENABLE) {
+               dma_cont = &chip->c_dma;
+               if (on) {
+                       dma_cont->prepare(dma_cont, 1);
+                       dma_cont->enable(dma_cont, 1);
+                       snd_cs4231_advance_dma(dma_cont,
+                               chip->capture_substream,
+                               &chip->c_periods_sent);
+               } else {
+                       dma_cont->enable(dma_cont, 0);
                }
-       } else {
-#endif
-#ifdef SBUS_SUPPORT
-#endif
-#ifdef EBUS_SUPPORT
        }
-#endif
 }
 
-static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_cs4231_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
        int result = 0;
 
        switch (cmd) {
@@ -710,7 +661,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
        case SNDRV_PCM_TRIGGER_STOP:
        {
                unsigned int what = 0;
-               snd_pcm_substream_t *s;
+               struct snd_pcm_substream *s;
                struct list_head *pos;
                unsigned long flags;
 
@@ -725,25 +676,12 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
                        }
                }
 
-#if 0
-               printk("TRIGGER: what[%x] on(%d)\n",
-                      what, (cmd == SNDRV_PCM_TRIGGER_START));
-#endif
-
                spin_lock_irqsave(&chip->lock, flags);
                if (cmd == SNDRV_PCM_TRIGGER_START) {
-                       cs4231_dma_trigger(chip, what, 1);
+                       cs4231_dma_trigger(substream, what, 1);
                        chip->image[CS4231_IFACE_CTRL] |= what;
-                       if (what & CS4231_PLAYBACK_ENABLE) {
-                               snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, 0xff);
-                               snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, 0xff);
-                       }
-                       if (what & CS4231_RECORD_ENABLE) {
-                               snd_cs4231_out(chip, CS4231_REC_LWR_CNT, 0xff);
-                               snd_cs4231_out(chip, CS4231_REC_UPR_CNT, 0xff);
-                       }
                } else {
-                       cs4231_dma_trigger(chip, what, 0);
+                       cs4231_dma_trigger(substream, what, 0);
                        chip->image[CS4231_IFACE_CTRL] &= ~what;
                }
                snd_cs4231_out(chip, CS4231_IFACE_CTRL,
@@ -755,9 +693,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
                result = -EINVAL;
                break;
        }
-#if 0
-       snd_cs4231_debug(chip);
-#endif
+
        return result;
 }
 
@@ -776,7 +712,7 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate)
        return freq_bits[13];
 }
 
-static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int channels)
+static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format, int channels)
 {
        unsigned char rformat;
 
@@ -790,13 +726,10 @@ static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int chann
        }
        if (channels > 1)
                rformat |= CS4231_STEREO;
-#if 0
-       snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
-#endif
        return rformat;
 }
 
-static void snd_cs4231_calibrate_mute(cs4231_t *chip, int mute)
+static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute)
 {
        unsigned long flags;
 
@@ -836,12 +769,12 @@ static void snd_cs4231_calibrate_mute(cs4231_t *chip, int mute)
        spin_unlock_irqrestore(&chip->lock, flags);
 }
 
-static void snd_cs4231_playback_format(cs4231_t *chip, snd_pcm_hw_params_t *params,
+static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params,
                                       unsigned char pdfr)
 {
        unsigned long flags;
 
-       down(&chip->mce_mutex);
+       mutex_lock(&chip->mce_mutex);
        snd_cs4231_calibrate_mute(chip, 1);
 
        snd_cs4231_mce_up(chip);
@@ -856,15 +789,15 @@ static void snd_cs4231_playback_format(cs4231_t *chip, snd_pcm_hw_params_t *para
        snd_cs4231_mce_down(chip);
 
        snd_cs4231_calibrate_mute(chip, 0);
-       up(&chip->mce_mutex);
+       mutex_unlock(&chip->mce_mutex);
 }
 
-static void snd_cs4231_capture_format(cs4231_t *chip, snd_pcm_hw_params_t *params,
+static void snd_cs4231_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params,
                                       unsigned char cdfr)
 {
        unsigned long flags;
 
-       down(&chip->mce_mutex);
+       mutex_lock(&chip->mce_mutex);
        snd_cs4231_calibrate_mute(chip, 1);
 
        snd_cs4231_mce_up(chip);
@@ -885,25 +818,25 @@ static void snd_cs4231_capture_format(cs4231_t *chip, snd_pcm_hw_params_t *param
        snd_cs4231_mce_down(chip);
 
        snd_cs4231_calibrate_mute(chip, 0);
-       up(&chip->mce_mutex);
+       mutex_unlock(&chip->mce_mutex);
 }
 
 /*
  *  Timer interface
  */
 
-static unsigned long snd_cs4231_timer_resolution(snd_timer_t *timer)
+static unsigned long snd_cs4231_timer_resolution(struct snd_timer *timer)
 {
-       cs4231_t *chip = snd_timer_chip(timer);
+       struct snd_cs4231 *chip = snd_timer_chip(timer);
 
        return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
 }
 
-static int snd_cs4231_timer_start(snd_timer_t *timer)
+static int snd_cs4231_timer_start(struct snd_timer *timer)
 {
        unsigned long flags;
        unsigned int ticks;
-       cs4231_t *chip = snd_timer_chip(timer);
+       struct snd_cs4231 *chip = snd_timer_chip(timer);
 
        spin_lock_irqsave(&chip->lock, flags);
        ticks = timer->sticks;
@@ -924,10 +857,10 @@ static int snd_cs4231_timer_start(snd_timer_t *timer)
        return 0;
 }
 
-static int snd_cs4231_timer_stop(snd_timer_t *timer)
+static int snd_cs4231_timer_stop(struct snd_timer *timer)
 {
        unsigned long flags;
-       cs4231_t *chip = snd_timer_chip(timer);
+       struct snd_cs4231 *chip = snd_timer_chip(timer);
 
        spin_lock_irqsave(&chip->lock, flags);
        snd_cs4231_out(chip, CS4231_ALT_FEATURE_1,
@@ -937,14 +870,14 @@ static int snd_cs4231_timer_stop(snd_timer_t *timer)
        return 0;
 }
 
-static void snd_cs4231_init(cs4231_t *chip)
+static void __init snd_cs4231_init(struct snd_cs4231 *chip)
 {
        unsigned long flags;
 
        snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-       snd_printk("init: (1)\n");
+       snd_printdd("init: (1)\n");
 #endif
        snd_cs4231_mce_up(chip);
        spin_lock_irqsave(&chip->lock, flags);
@@ -957,7 +890,7 @@ static void snd_cs4231_init(cs4231_t *chip)
        snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-       snd_printk("init: (2)\n");
+       snd_printdd("init: (2)\n");
 #endif
 
        snd_cs4231_mce_up(chip);
@@ -967,7 +900,7 @@ static void snd_cs4231_init(cs4231_t *chip)
        snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-       snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
+       snd_printdd("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
 #endif
 
        spin_lock_irqsave(&chip->lock, flags);
@@ -981,7 +914,7 @@ static void snd_cs4231_init(cs4231_t *chip)
        snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-       snd_printk("init: (4)\n");
+       snd_printdd("init: (4)\n");
 #endif
 
        snd_cs4231_mce_up(chip);
@@ -991,22 +924,22 @@ static void snd_cs4231_init(cs4231_t *chip)
        snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-       snd_printk("init: (5)\n");
+       snd_printdd("init: (5)\n");
 #endif
 }
 
-static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
+static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode)
 {
        unsigned long flags;
 
-       down(&chip->open_mutex);
+       mutex_lock(&chip->open_mutex);
        if ((chip->mode & mode)) {
-               up(&chip->open_mutex);
+               mutex_unlock(&chip->open_mutex);
                return -EAGAIN;
        }
        if (chip->mode & CS4231_MODE_OPEN) {
                chip->mode |= mode;
-               up(&chip->open_mutex);
+               mutex_unlock(&chip->open_mutex);
                return 0;
        }
        /* ok. now enable and ack CODEC IRQ */
@@ -1022,21 +955,22 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
                       CS4231_RECORD_IRQ |
                       CS4231_TIMER_IRQ);
        snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
+
        spin_unlock_irqrestore(&chip->lock, flags);
 
        chip->mode = mode;
-       up(&chip->open_mutex);
+       mutex_unlock(&chip->open_mutex);
        return 0;
 }
 
-static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
+static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode)
 {
        unsigned long flags;
 
-       down(&chip->open_mutex);
+       mutex_lock(&chip->open_mutex);
        chip->mode &= ~mode;
        if (chip->mode & CS4231_MODE_OPEN) {
-               up(&chip->open_mutex);
+               mutex_unlock(&chip->open_mutex);
                return;
        }
        snd_cs4231_calibrate_mute(chip, 1);
@@ -1073,28 +1007,28 @@ static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
        snd_cs4231_calibrate_mute(chip, 0);
 
        chip->mode = 0;
-       up(&chip->open_mutex);
+       mutex_unlock(&chip->open_mutex);
 }
 
 /*
  *  timer open/close
  */
 
-static int snd_cs4231_timer_open(snd_timer_t *timer)
+static int snd_cs4231_timer_open(struct snd_timer *timer)
 {
-       cs4231_t *chip = snd_timer_chip(timer);
+       struct snd_cs4231 *chip = snd_timer_chip(timer);
        snd_cs4231_open(chip, CS4231_MODE_TIMER);
        return 0;
 }
 
-static int snd_cs4231_timer_close(snd_timer_t * timer)
+static int snd_cs4231_timer_close(struct snd_timer * timer)
 {
-       cs4231_t *chip = snd_timer_chip(timer);
+       struct snd_cs4231 *chip = snd_timer_chip(timer);
        snd_cs4231_close(chip, CS4231_MODE_TIMER);
        return 0;
 }
 
-static struct _snd_timer_hardware snd_cs4231_timer_table =
+static struct snd_timer_hardware snd_cs4231_timer_table =
 {
        .flags          =       SNDRV_TIMER_HW_AUTO,
        .resolution     =       9945,
@@ -1110,10 +1044,10 @@ static struct _snd_timer_hardware snd_cs4231_timer_table =
  *  ok.. exported functions..
  */
 
-static int snd_cs4231_playback_hw_params(snd_pcm_substream_t *substream,
-                                        snd_pcm_hw_params_t *hw_params)
+static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream,
+                                        struct snd_pcm_hw_params *hw_params)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
        unsigned char new_pdfr;
        int err;
 
@@ -1128,28 +1062,34 @@ static int snd_cs4231_playback_hw_params(snd_pcm_substream_t *substream,
        return 0;
 }
 
-static int snd_cs4231_playback_hw_free(snd_pcm_substream_t *substream)
+static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream)
 {
        return snd_pcm_lib_free_pages(substream);
 }
 
-static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
        unsigned long flags;
 
        spin_lock_irqsave(&chip->lock, flags);
+
        chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
                                            CS4231_PLAYBACK_PIO);
+
+       BUG_ON(runtime->period_size > 0xffff + 1);
+
+       chip->p_periods_sent = 0;
        spin_unlock_irqrestore(&chip->lock, flags);
 
        return 0;
 }
 
-static int snd_cs4231_capture_hw_params(snd_pcm_substream_t *substream,
-                                       snd_pcm_hw_params_t *hw_params)
+static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream,
+                                       struct snd_pcm_hw_params *hw_params)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
        unsigned char new_cdfr;
        int err;
 
@@ -1164,26 +1104,28 @@ static int snd_cs4231_capture_hw_params(snd_pcm_substream_t *substream,
        return 0;
 }
 
-static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream)
+static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream)
 {
        return snd_pcm_lib_free_pages(substream);
 }
 
-static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream)
+static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
        unsigned long flags;
 
        spin_lock_irqsave(&chip->lock, flags);
        chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE |
                                            CS4231_RECORD_PIO);
 
+
+       chip->c_periods_sent = 0;
        spin_unlock_irqrestore(&chip->lock, flags);
 
        return 0;
 }
 
-static void snd_cs4231_overrange(cs4231_t *chip)
+static void snd_cs4231_overrange(struct snd_cs4231 *chip)
 {
        unsigned long flags;
        unsigned char res;
@@ -1196,125 +1138,51 @@ static void snd_cs4231_overrange(cs4231_t *chip)
                chip->capture_substream->runtime->overrange++;
 }
 
-static void snd_cs4231_generic_interrupt(cs4231_t *chip)
-{
-       unsigned long flags;
-       unsigned char status;
-
-       status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
-       if (!status)
-               return;
-
-       if (status & CS4231_TIMER_IRQ) {
-               if (chip->timer)
-                       snd_timer_interrupt(chip->timer, chip->timer->sticks);
-       }               
-       if (status & CS4231_PLAYBACK_IRQ)
-               snd_pcm_period_elapsed(chip->playback_substream);
-       if (status & CS4231_RECORD_IRQ) {
-               snd_cs4231_overrange(chip);
-               snd_pcm_period_elapsed(chip->capture_substream);
-       }
-
-       /* ACK the CS4231 interrupt. */
-       spin_lock_irqsave(&chip->lock, flags);
-       snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
-       spin_unlock_irqrestore(&chip->lock, flags);
-}
-
-#ifdef SBUS_SUPPORT
-static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void snd_cs4231_play_callback(struct snd_cs4231 *chip)
 {
-       cs4231_t *chip = dev_id;
-       u32 csr;
-
-       csr = sbus_readl(chip->port + APCCSR);
-       if (!(csr & (APC_INT_PENDING |
-                    APC_PLAY_INT |
-                    APC_CAPT_INT |
-                    APC_GENL_INT |
-                    APC_XINT_PEMP |
-                    APC_XINT_CEMP)))
-               return IRQ_NONE;
-
-       /* ACK the APC interrupt. */
-       sbus_writel(csr, chip->port + APCCSR);
-
-       snd_cs4231_generic_interrupt(chip);
-
-       return IRQ_HANDLED;
-}
-#endif
-
-#ifdef EBUS_SUPPORT
-static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie)
-{
-       cs4231_t *chip = cookie;
-
        if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) {
                snd_pcm_period_elapsed(chip->playback_substream);
-               snd_cs4231_ebus_advance_dma(p, chip->playback_substream,
+               snd_cs4231_advance_dma(&chip->p_dma, chip->playback_substream,
                                            &chip->p_periods_sent);
        }
 }
 
-static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie)
+static void snd_cs4231_capture_callback(struct snd_cs4231 *chip)
 {
-       cs4231_t *chip = cookie;
-
        if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) {
                snd_pcm_period_elapsed(chip->capture_substream);
-               snd_cs4231_ebus_advance_dma(p, chip->capture_substream,
+               snd_cs4231_advance_dma(&chip->c_dma, chip->capture_substream,
                                            &chip->c_periods_sent);
        }
 }
-#endif
 
-static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *substream)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
-       size_t ptr, residue, period_bytes;
-
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+       struct cs4231_dma_control *dma_cont = &chip->p_dma;
+       size_t ptr;
+       
        if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
                return 0;
-       period_bytes = snd_pcm_lib_period_bytes(substream);
-       ptr = period_bytes * chip->p_periods_sent;
-#ifdef EBUS_SUPPORT
-       if (chip->flags & CS4231_FLAG_EBUS) {
-               residue = ebus_dma_residue(&chip->eb2p);
-       } else {
-#endif
-#ifdef SBUS_SUPPORT
-               residue = sbus_readl(chip->port + APCPC);
-#endif
-#ifdef EBUS_SUPPORT
-       }
-#endif
-       ptr += (period_bytes - residue);
+       ptr = dma_cont->address(dma_cont);
+       if (ptr != 0)
+               ptr -= substream->runtime->dma_addr;
+       
        return bytes_to_frames(substream->runtime, ptr);
 }
 
-static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *substream)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
-       size_t ptr, residue, period_bytes;
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+       struct cs4231_dma_control *dma_cont = &chip->c_dma;
+       size_t ptr;
        
        if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
                return 0;
-       period_bytes = snd_pcm_lib_period_bytes(substream);
-       ptr = period_bytes * chip->c_periods_sent;
-#ifdef EBUS_SUPPORT
-       if (chip->flags & CS4231_FLAG_EBUS) {
-               residue = ebus_dma_residue(&chip->eb2c);
-       } else {
-#endif
-#ifdef SBUS_SUPPORT
-               residue = sbus_readl(chip->port + APCCC);
-#endif
-#ifdef EBUS_SUPPORT
-       }
-#endif
-       ptr += (period_bytes - residue);
+       ptr = dma_cont->address(dma_cont);
+       if (ptr != 0)
+               ptr -= substream->runtime->dma_addr;
+       
        return bytes_to_frames(substream->runtime, ptr);
 }
 
@@ -1322,15 +1190,12 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr
 
  */
 
-static int snd_cs4231_probe(cs4231_t *chip)
+static int __init snd_cs4231_probe(struct snd_cs4231 *chip)
 {
        unsigned long flags;
        int i, id, vers;
        unsigned char *ptr;
 
-#if 0
-       snd_cs4231_debug(chip);
-#endif
        id = vers = 0;
        for (i = 0; i < 50; i++) {
                mb();
@@ -1353,30 +1218,8 @@ static int snd_cs4231_probe(cs4231_t *chip)
        spin_lock_irqsave(&chip->lock, flags);
 
 
-       /* Reset DMA engine.  */
-#ifdef EBUS_SUPPORT
-       if (chip->flags & CS4231_FLAG_EBUS) {
-               /* Done by ebus_dma_register */
-       } else {
-#endif
-#ifdef SBUS_SUPPORT
-                sbus_writel(APC_CHIP_RESET, chip->port + APCCSR);
-                sbus_writel(0x00, chip->port + APCCSR);
-                sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET,
-                           chip->port + APCCSR);
-  
-                udelay(20);
-  
-                sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET,
-                           chip->port + APCCSR);
-                sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA |
-                                                              APC_XINT_PENA |
-                                                              APC_XINT_CENA),
-                           chip->port + APCCSR);
-#endif
-#ifdef EBUS_SUPPORT
-       }
-#endif
+       /* Reset DMA engine (sbus only).  */
+       chip->p_dma.reset(chip);
 
        __cs4231_readb(chip, CS4231P(chip, STATUS));    /* clear any pendings IRQ */
        __cs4231_writeb(chip, 0, CS4231P(chip, STATUS));
@@ -1412,7 +1255,7 @@ static int snd_cs4231_probe(cs4231_t *chip)
        return 0;               /* all things are ok.. */
 }
 
-static snd_pcm_hardware_t snd_cs4231_playback =
+static struct snd_pcm_hardware snd_cs4231_playback =
 {
        .info                   = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
@@ -1432,7 +1275,7 @@ static snd_pcm_hardware_t snd_cs4231_playback =
        .periods_max            = 1024,
 };
 
-static snd_pcm_hardware_t snd_cs4231_capture =
+static struct snd_pcm_hardware snd_cs4231_capture =
 {
        .info                   = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
@@ -1452,10 +1295,10 @@ static snd_pcm_hardware_t snd_cs4231_capture =
        .periods_max            = 1024,
 };
 
-static int snd_cs4231_playback_open(snd_pcm_substream_t *substream)
+static int snd_cs4231_playback_open(struct snd_pcm_substream *substream)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
-       snd_pcm_runtime_t *runtime = substream->runtime;
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
 
        runtime->hw = snd_cs4231_playback;
@@ -1472,10 +1315,10 @@ static int snd_cs4231_playback_open(snd_pcm_substream_t *substream)
        return 0;
 }
 
-static int snd_cs4231_capture_open(snd_pcm_substream_t *substream)
+static int snd_cs4231_capture_open(struct snd_pcm_substream *substream)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
-       snd_pcm_runtime_t *runtime = substream->runtime;
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
 
        runtime->hw = snd_cs4231_capture;
@@ -1492,22 +1335,22 @@ static int snd_cs4231_capture_open(snd_pcm_substream_t *substream)
        return 0;
 }
 
-static int snd_cs4231_playback_close(snd_pcm_substream_t *substream)
+static int snd_cs4231_playback_close(struct snd_pcm_substream *substream)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
 
-       chip->playback_substream = NULL;
        snd_cs4231_close(chip, CS4231_MODE_PLAY);
+       chip->playback_substream = NULL;
 
        return 0;
 }
 
-static int snd_cs4231_capture_close(snd_pcm_substream_t *substream)
+static int snd_cs4231_capture_close(struct snd_pcm_substream *substream)
 {
-       cs4231_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
 
-       chip->capture_substream = NULL;
        snd_cs4231_close(chip, CS4231_MODE_RECORD);
+       chip->capture_substream = NULL;
 
        return 0;
 }
@@ -1516,7 +1359,7 @@ static int snd_cs4231_capture_close(snd_pcm_substream_t *substream)
  * XXX the audio AUXIO register...
  */
 
-static snd_pcm_ops_t snd_cs4231_playback_ops = {
+static struct snd_pcm_ops snd_cs4231_playback_ops = {
        .open           =       snd_cs4231_playback_open,
        .close          =       snd_cs4231_playback_close,
        .ioctl          =       snd_pcm_lib_ioctl,
@@ -1527,7 +1370,7 @@ static snd_pcm_ops_t snd_cs4231_playback_ops = {
        .pointer        =       snd_cs4231_playback_pointer,
 };
 
-static snd_pcm_ops_t snd_cs4231_capture_ops = {
+static struct snd_pcm_ops snd_cs4231_capture_ops = {
        .open           =       snd_cs4231_capture_open,
        .close          =       snd_cs4231_capture_close,
        .ioctl          =       snd_pcm_lib_ioctl,
@@ -1538,16 +1381,9 @@ static snd_pcm_ops_t snd_cs4231_capture_ops = {
        .pointer        =       snd_cs4231_capture_pointer,
 };
 
-static void snd_cs4231_pcm_free(snd_pcm_t *pcm)
-{
-       cs4231_t *chip = pcm->private_data;
-       chip->pcm = NULL;
-       snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_cs4231_pcm(cs4231_t *chip)
+static int __init snd_cs4231_pcm(struct snd_cs4231 *chip)
 {
-       snd_pcm_t *pcm;
+       struct snd_pcm *pcm;
        int err;
 
        if ((err = snd_pcm_new(chip->card, "CS4231", 0, 1, 1, &pcm)) < 0)
@@ -1558,41 +1394,20 @@ int snd_cs4231_pcm(cs4231_t *chip)
        
        /* global setup */
        pcm->private_data = chip;
-       pcm->private_free = snd_cs4231_pcm_free;
        pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
        strcpy(pcm->name, "CS4231");
 
-#ifdef EBUS_SUPPORT
-       if (chip->flags & CS4231_FLAG_EBUS) {
-               snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                                     snd_dma_pci_data(chip->dev_u.pdev),
-                                                     64*1024, 128*1024);
-       } else {
-#endif
-#ifdef SBUS_SUPPORT
-               snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS,
-                                                     snd_dma_sbus_data(chip->dev_u.sdev),
-                                                     64*1024, 128*1024);
-#endif
-#ifdef EBUS_SUPPORT
-       }
-#endif
+       chip->p_dma.preallocate(chip, pcm);
 
        chip->pcm = pcm;
 
        return 0;
 }
 
-static void snd_cs4231_timer_free(snd_timer_t *timer)
+static int __init snd_cs4231_timer(struct snd_cs4231 *chip)
 {
-       cs4231_t *chip = timer->private_data;
-       chip->timer = NULL;
-}
-
-int snd_cs4231_timer(cs4231_t *chip)
-{
-       snd_timer_t *timer;
-       snd_timer_id_t tid;
+       struct snd_timer *timer;
+       struct snd_timer_id tid;
        int err;
 
        /* Timer initialization */
@@ -1605,7 +1420,6 @@ int snd_cs4231_timer(cs4231_t *chip)
                return err;
        strcpy(timer->name, "CS4231");
        timer->private_data = chip;
-       timer->private_free = snd_cs4231_timer_free;
        timer->hw = snd_cs4231_timer_table;
        chip->timer = timer;
 
@@ -1616,12 +1430,13 @@ int snd_cs4231_timer(cs4231_t *chip)
  *  MIXER part
  */
 
-static int snd_cs4231_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_info *uinfo)
 {
        static char *texts[4] = {
                "Line", "CD", "Mic", "Mix"
        };
-       cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+       struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
 
        snd_assert(chip->card != NULL, return -EINVAL);
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -1634,9 +1449,10 @@ static int snd_cs4231_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *ui
        return 0;
 }
 
-static int snd_cs4231_get_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
 {
-       cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+       struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
        unsigned long flags;
        
        spin_lock_irqsave(&chip->lock, flags);
@@ -1649,9 +1465,10 @@ static int snd_cs4231_get_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
        return 0;
 }
 
-static int snd_cs4231_put_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
 {
-       cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+       struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
        unsigned long flags;
        unsigned short left, right;
        int change;
@@ -1676,7 +1493,8 @@ static int snd_cs4231_put_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
        return change;
 }
 
-int snd_cs4231_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_cs4231_info_single(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_info *uinfo)
 {
        int mask = (kcontrol->private_value >> 16) & 0xff;
 
@@ -1689,9 +1507,10 @@ int snd_cs4231_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
        return 0;
 }
 
-int snd_cs4231_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_get_single(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+       struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
        unsigned long flags;
        int reg = kcontrol->private_value & 0xff;
        int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -1711,9 +1530,10 @@ int snd_cs4231_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
        return 0;
 }
 
-int snd_cs4231_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_put_single(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+       struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
        unsigned long flags;
        int reg = kcontrol->private_value & 0xff;
        int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -1738,7 +1558,8 @@ int snd_cs4231_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
        return change;
 }
 
-int snd_cs4231_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_cs4231_info_double(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_info *uinfo)
 {
        int mask = (kcontrol->private_value >> 24) & 0xff;
 
@@ -1751,9 +1572,10 @@ int snd_cs4231_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
        return 0;
 }
 
-int snd_cs4231_get_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_get_double(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+       struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
        unsigned long flags;
        int left_reg = kcontrol->private_value & 0xff;
        int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -1779,9 +1601,10 @@ int snd_cs4231_get_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
        return 0;
 }
 
-int snd_cs4231_put_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+       struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
        unsigned long flags;
        int left_reg = kcontrol->private_value & 0xff;
        int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -1826,7 +1649,7 @@ int snd_cs4231_put_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
   .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \
   .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
 
-static snd_kcontrol_new_t snd_cs4231_controls[] = {
+static struct snd_kcontrol_new snd_cs4231_controls[] __initdata = {
 CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
 CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
 CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
@@ -1855,9 +1678,9 @@ CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1),
 CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1)
 };
                                         
-int snd_cs4231_mixer(cs4231_t *chip)
+static int __init snd_cs4231_mixer(struct snd_cs4231 *chip)
 {
-       snd_card_t *card;
+       struct snd_card *card;
        int err, idx;
 
        snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
@@ -1877,9 +1700,9 @@ int snd_cs4231_mixer(cs4231_t *chip)
 
 static int dev;
 
-static int cs4231_attach_begin(snd_card_t **rcard)
+static int __init cs4231_attach_begin(struct snd_card **rcard)
 {
-       snd_card_t *card;
+       struct snd_card *card;
 
        *rcard = NULL;
 
@@ -1902,7 +1725,7 @@ static int cs4231_attach_begin(snd_card_t **rcard)
        return 0;
 }
 
-static int cs4231_attach_finish(snd_card_t *card, cs4231_t *chip)
+static int __init cs4231_attach_finish(struct snd_card *card, struct snd_cs4231 *chip)
 {
        int err;
 
@@ -1930,7 +1753,181 @@ out_err:
 }
 
 #ifdef SBUS_SUPPORT
-static int snd_cs4231_sbus_free(cs4231_t *chip)
+
+static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       unsigned long flags;
+       unsigned char status;
+       u32 csr;
+       struct snd_cs4231 *chip = dev_id;
+
+       /*This is IRQ is not raised by the cs4231*/
+       if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ))
+               return IRQ_NONE;
+
+       /* ACK the APC interrupt. */
+       csr = sbus_readl(chip->port + APCCSR);
+
+       sbus_writel(csr, chip->port + APCCSR);
+
+       if ((csr & APC_PDMA_READY) && 
+           (csr & APC_PLAY_INT) &&
+           (csr & APC_XINT_PNVA) &&
+           !(csr & APC_XINT_EMPT))
+                       snd_cs4231_play_callback(chip);
+
+       if ((csr & APC_CDMA_READY) && 
+           (csr & APC_CAPT_INT) &&
+           (csr & APC_XINT_CNVA) &&
+           !(csr & APC_XINT_EMPT))
+                       snd_cs4231_capture_callback(chip);
+       
+       status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
+
+       if (status & CS4231_TIMER_IRQ) {
+               if (chip->timer)
+                       snd_timer_interrupt(chip->timer, chip->timer->sticks);
+       }               
+
+       if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY))
+               snd_cs4231_overrange(chip);
+
+       /* ACK the CS4231 interrupt. */
+       spin_lock_irqsave(&chip->lock, flags);
+       snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+/*
+ * SBUS DMA routines
+ */
+
+static int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len)
+{
+       unsigned long flags;
+       u32 test, csr;
+       int err;
+       struct sbus_dma_info *base = &dma_cont->sbus_info;
+       
+       if (len >= (1 << 24))
+               return -EINVAL;
+       spin_lock_irqsave(&base->lock, flags);
+       csr = sbus_readl(base->regs + APCCSR);
+       err = -EINVAL;
+       test = APC_CDMA_READY;
+       if ( base->dir == APC_PLAY )
+               test = APC_PDMA_READY;
+       if (!(csr & test))
+               goto out;
+       err = -EBUSY;
+       csr = sbus_readl(base->regs + APCCSR);
+       test = APC_XINT_CNVA;
+       if ( base->dir == APC_PLAY )
+               test = APC_XINT_PNVA;
+       if (!(csr & test))
+               goto out;
+       err = 0;
+       sbus_writel(bus_addr, base->regs + base->dir + APCNVA);
+       sbus_writel(len, base->regs + base->dir + APCNC);
+out:
+       spin_unlock_irqrestore(&base->lock, flags);
+       return err;
+}
+
+static void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d)
+{
+       unsigned long flags;
+       u32 csr, test;
+       struct sbus_dma_info *base = &dma_cont->sbus_info;
+
+       spin_lock_irqsave(&base->lock, flags);
+       csr = sbus_readl(base->regs + APCCSR);
+       test =  APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA |
+               APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL |
+                APC_XINT_PENA;
+       if ( base->dir == APC_RECORD )
+               test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA |
+                       APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL;
+       csr |= test;
+       sbus_writel(csr, base->regs + APCCSR);
+       spin_unlock_irqrestore(&base->lock, flags);
+}
+
+static void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
+{
+       unsigned long flags;
+       u32 csr, shift;
+       struct sbus_dma_info *base = &dma_cont->sbus_info;
+
+       spin_lock_irqsave(&base->lock, flags);
+       if (!on) {
+               if (base->dir == APC_PLAY) { 
+                       sbus_writel(0, base->regs + base->dir + APCNVA); 
+                       sbus_writel(1, base->regs + base->dir + APCC); 
+               }
+               else
+               {
+                       sbus_writel(0, base->regs + base->dir + APCNC); 
+                       sbus_writel(0, base->regs + base->dir + APCVA); 
+               } 
+       } 
+       udelay(600); 
+       csr = sbus_readl(base->regs + APCCSR);
+       shift = 0;
+       if ( base->dir == APC_PLAY )
+               shift = 1;
+       if (on)
+               csr &= ~(APC_CPAUSE << shift);
+       else
+               csr |= (APC_CPAUSE << shift); 
+       sbus_writel(csr, base->regs + APCCSR);
+       if (on)
+               csr |= (APC_CDMA_READY << shift);
+       else
+               csr &= ~(APC_CDMA_READY << shift);
+       sbus_writel(csr, base->regs + APCCSR);
+       
+       spin_unlock_irqrestore(&base->lock, flags);
+}
+
+static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont)
+{
+       struct sbus_dma_info *base = &dma_cont->sbus_info;
+
+        return sbus_readl(base->regs + base->dir + APCVA);
+}
+
+static void sbus_dma_reset(struct snd_cs4231 *chip)
+{
+        sbus_writel(APC_CHIP_RESET, chip->port + APCCSR);
+        sbus_writel(0x00, chip->port + APCCSR);
+        sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET,
+                   chip->port + APCCSR);
+  
+        udelay(20);
+  
+        sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET,
+                   chip->port + APCCSR);
+        sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA |
+                      APC_XINT_PENA |
+                      APC_XINT_CENA),
+                      chip->port + APCCSR);
+}
+
+static void sbus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm)
+{
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS,
+                                             snd_dma_sbus_data(chip->dev_u.sdev),
+                                             64*1024, 128*1024);
+}
+
+/*
+ * Init and exit routines
+ */
+
+static int snd_cs4231_sbus_free(struct snd_cs4231 *chip)
 {
        if (chip->irq[0])
                free_irq(chip->irq[0], chip);
@@ -1938,41 +1935,40 @@ static int snd_cs4231_sbus_free(cs4231_t *chip)
        if (chip->port)
                sbus_iounmap(chip->port, chip->regs_size);
 
-       if (chip->timer)
-               snd_device_free(chip->card, chip->timer);
-
        kfree(chip);
 
        return 0;
 }
 
-static int snd_cs4231_sbus_dev_free(snd_device_t *device)
+static int snd_cs4231_sbus_dev_free(struct snd_device *device)
 {
-       cs4231_t *cp = device->device_data;
+       struct snd_cs4231 *cp = device->device_data;
 
        return snd_cs4231_sbus_free(cp);
 }
 
-static snd_device_ops_t snd_cs4231_sbus_dev_ops = {
+static struct snd_device_ops snd_cs4231_sbus_dev_ops = {
        .dev_free       =       snd_cs4231_sbus_dev_free,
 };
 
-static int __init snd_cs4231_sbus_create(snd_card_t *card,
+static int __init snd_cs4231_sbus_create(struct snd_card *card,
                                         struct sbus_dev *sdev,
                                         int dev,
-                                        cs4231_t **rchip)
+                                        struct snd_cs4231 **rchip)
 {
-       cs4231_t *chip;
+       struct snd_cs4231 *chip;
        int err;
 
        *rchip = NULL;
-       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
 
        spin_lock_init(&chip->lock);
-       init_MUTEX(&chip->mce_mutex);
-       init_MUTEX(&chip->open_mutex);
+       spin_lock_init(&chip->c_dma.sbus_info.lock);
+       spin_lock_init(&chip->p_dma.sbus_info.lock);
+       mutex_init(&chip->mce_mutex);
+       mutex_init(&chip->open_mutex);
        chip->card = card;
        chip->dev_u.sdev = sdev;
        chip->regs_size = sdev->reg_addrs[0].reg_size;
@@ -1982,13 +1978,32 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
        chip->port = sbus_ioremap(&sdev->resource[0], 0,
                                  chip->regs_size, "cs4231");
        if (!chip->port) {
-               snd_printk("cs4231-%d: Unable to map chip registers.\n", dev);
+               snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev);
                return -EIO;
        }
 
+       chip->c_dma.sbus_info.regs = chip->port;
+       chip->p_dma.sbus_info.regs = chip->port;
+       chip->c_dma.sbus_info.dir = APC_RECORD;
+       chip->p_dma.sbus_info.dir = APC_PLAY;
+
+       chip->p_dma.prepare = sbus_dma_prepare;
+       chip->p_dma.enable = sbus_dma_enable;
+       chip->p_dma.request = sbus_dma_request;
+       chip->p_dma.address = sbus_dma_addr;
+       chip->p_dma.reset = sbus_dma_reset;
+       chip->p_dma.preallocate = sbus_dma_preallocate;
+
+       chip->c_dma.prepare = sbus_dma_prepare;
+       chip->c_dma.enable = sbus_dma_enable;
+       chip->c_dma.request = sbus_dma_request;
+       chip->c_dma.address = sbus_dma_addr;
+       chip->c_dma.reset = sbus_dma_reset;
+       chip->c_dma.preallocate = sbus_dma_preallocate;
+
        if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt,
                        SA_SHIRQ, "cs4231", chip)) {
-               snd_printk("cs4231-%d: Unable to grab SBUS IRQ %s\n",
+               snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n",
                           dev,
                           __irq_itoa(sdev->irqs[0]));
                snd_cs4231_sbus_free(chip);
@@ -2012,11 +2027,11 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
        return 0;
 }
 
-static int cs4231_sbus_attach(struct sbus_dev *sdev)
+static int __init cs4231_sbus_attach(struct sbus_dev *sdev)
 {
        struct resource *rp = &sdev->resource[0];
-       cs4231_t *cp;
-       snd_card_t *card;
+       struct snd_cs4231 *cp;
+       struct snd_card *card;
        int err;
 
        err = cs4231_attach_begin(&card);
@@ -2039,100 +2054,167 @@ static int cs4231_sbus_attach(struct sbus_dev *sdev)
 #endif
 
 #ifdef EBUS_SUPPORT
-static int snd_cs4231_ebus_free(cs4231_t *chip)
+
+static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie)
+{
+       struct snd_cs4231 *chip = cookie;
+       
+       snd_cs4231_play_callback(chip);
+}
+
+static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie)
+{
+       struct snd_cs4231 *chip = cookie;
+
+       snd_cs4231_capture_callback(chip);
+}
+
+/*
+ * EBUS DMA wrappers
+ */
+
+static int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len)
+{
+       return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len);
+}
+
+static void _ebus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
+{
+       ebus_dma_enable(&dma_cont->ebus_info, on);
+}
+
+static void _ebus_dma_prepare(struct cs4231_dma_control *dma_cont, int dir)
+{
+       ebus_dma_prepare(&dma_cont->ebus_info, dir);
+}
+
+static unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont)
+{
+       return ebus_dma_addr(&dma_cont->ebus_info);
+}
+
+static void _ebus_dma_reset(struct snd_cs4231 *chip)
+{
+       return;
+}
+
+static void _ebus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm)
+{
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                     snd_dma_pci_data(chip->dev_u.pdev),
+                                     64*1024, 128*1024);
+}
+
+/*
+ * Init and exit routines
+ */
+
+static int snd_cs4231_ebus_free(struct snd_cs4231 *chip)
 {
-       if (chip->eb2c.regs) {
-               ebus_dma_unregister(&chip->eb2c);
-               iounmap(chip->eb2c.regs);
+       if (chip->c_dma.ebus_info.regs) {
+               ebus_dma_unregister(&chip->c_dma.ebus_info);
+               iounmap(chip->c_dma.ebus_info.regs);
        }
-       if (chip->eb2p.regs) {
-               ebus_dma_unregister(&chip->eb2p);
-               iounmap(chip->eb2p.regs);
+       if (chip->p_dma.ebus_info.regs) {
+               ebus_dma_unregister(&chip->p_dma.ebus_info);
+               iounmap(chip->p_dma.ebus_info.regs);
        }
 
        if (chip->port)
                iounmap(chip->port);
-       if (chip->timer)
-               snd_device_free(chip->card, chip->timer);
 
        kfree(chip);
 
        return 0;
 }
 
-static int snd_cs4231_ebus_dev_free(snd_device_t *device)
+static int snd_cs4231_ebus_dev_free(struct snd_device *device)
 {
-       cs4231_t *cp = device->device_data;
+       struct snd_cs4231 *cp = device->device_data;
 
        return snd_cs4231_ebus_free(cp);
 }
 
-static snd_device_ops_t snd_cs4231_ebus_dev_ops = {
+static struct snd_device_ops snd_cs4231_ebus_dev_ops = {
        .dev_free       =       snd_cs4231_ebus_dev_free,
 };
 
-static int __init snd_cs4231_ebus_create(snd_card_t *card,
+static int __init snd_cs4231_ebus_create(struct snd_card *card,
                                         struct linux_ebus_device *edev,
                                         int dev,
-                                        cs4231_t **rchip)
+                                        struct snd_cs4231 **rchip)
 {
-       cs4231_t *chip;
+       struct snd_cs4231 *chip;
        int err;
 
        *rchip = NULL;
-       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
 
        spin_lock_init(&chip->lock);
-       spin_lock_init(&chip->eb2c.lock);
-       spin_lock_init(&chip->eb2p.lock);
-       init_MUTEX(&chip->mce_mutex);
-       init_MUTEX(&chip->open_mutex);
+       spin_lock_init(&chip->c_dma.ebus_info.lock);
+       spin_lock_init(&chip->p_dma.ebus_info.lock);
+       mutex_init(&chip->mce_mutex);
+       mutex_init(&chip->open_mutex);
        chip->flags |= CS4231_FLAG_EBUS;
        chip->card = card;
        chip->dev_u.pdev = edev->bus->self;
        memcpy(&chip->image, &snd_cs4231_original_image,
               sizeof(snd_cs4231_original_image));
-       strcpy(chip->eb2c.name, "cs4231(capture)");
-       chip->eb2c.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
-       chip->eb2c.callback = snd_cs4231_ebus_capture_callback;
-       chip->eb2c.client_cookie = chip;
-       chip->eb2c.irq = edev->irqs[0];
-       strcpy(chip->eb2p.name, "cs4231(play)");
-       chip->eb2p.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
-       chip->eb2p.callback = snd_cs4231_ebus_play_callback;
-       chip->eb2p.client_cookie = chip;
-       chip->eb2p.irq = edev->irqs[1];
+       strcpy(chip->c_dma.ebus_info.name, "cs4231(capture)");
+       chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
+       chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback;
+       chip->c_dma.ebus_info.client_cookie = chip;
+       chip->c_dma.ebus_info.irq = edev->irqs[0];
+       strcpy(chip->p_dma.ebus_info.name, "cs4231(play)");
+       chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
+       chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback;
+       chip->p_dma.ebus_info.client_cookie = chip;
+       chip->p_dma.ebus_info.irq = edev->irqs[1];
+
+       chip->p_dma.prepare = _ebus_dma_prepare;
+       chip->p_dma.enable = _ebus_dma_enable;
+       chip->p_dma.request = _ebus_dma_request;
+       chip->p_dma.address = _ebus_dma_addr;
+       chip->p_dma.reset = _ebus_dma_reset;
+       chip->p_dma.preallocate = _ebus_dma_preallocate;
+
+       chip->c_dma.prepare = _ebus_dma_prepare;
+       chip->c_dma.enable = _ebus_dma_enable;
+       chip->c_dma.request = _ebus_dma_request;
+       chip->c_dma.address = _ebus_dma_addr;
+       chip->c_dma.reset = _ebus_dma_reset;
+       chip->c_dma.preallocate = _ebus_dma_preallocate;
 
        chip->port = ioremap(edev->resource[0].start, 0x10);
-       chip->eb2p.regs = ioremap(edev->resource[1].start, 0x10);
-       chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10);
-       if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) {
+       chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10);
+       chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10);
+       if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) {
                snd_cs4231_ebus_free(chip);
-               snd_printk("cs4231-%d: Unable to map chip registers.\n", dev);
+               snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev);
                return -EIO;
        }
 
-       if (ebus_dma_register(&chip->eb2c)) {
+       if (ebus_dma_register(&chip->c_dma.ebus_info)) {
                snd_cs4231_ebus_free(chip);
-               snd_printk("cs4231-%d: Unable to register EBUS capture DMA\n", dev);
+               snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev);
                return -EBUSY;
        }
-       if (ebus_dma_irq_enable(&chip->eb2c, 1)) {
+       if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) {
                snd_cs4231_ebus_free(chip);
-               snd_printk("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev);
+               snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev);
                return -EBUSY;
        }
 
-       if (ebus_dma_register(&chip->eb2p)) {
+       if (ebus_dma_register(&chip->p_dma.ebus_info)) {
                snd_cs4231_ebus_free(chip);
-               snd_printk("cs4231-%d: Unable to register EBUS play DMA\n", dev);
+               snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev);
                return -EBUSY;
        }
-       if (ebus_dma_irq_enable(&chip->eb2p, 1)) {
+       if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) {
                snd_cs4231_ebus_free(chip);
-               snd_printk("cs4231-%d: Unable to enable EBUS play IRQ\n", dev);
+               snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev);
                return -EBUSY;
        }
 
@@ -2152,10 +2234,10 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
        return 0;
 }
 
-static int cs4231_ebus_attach(struct linux_ebus_device *edev)
+static int __init cs4231_ebus_attach(struct linux_ebus_device *edev)
 {
-       snd_card_t *card;
-       cs4231_t *chip;
+       struct snd_card *card;
+       struct snd_cs4231 *chip;
        int err;
 
        err = cs4231_attach_begin(&card);
@@ -2228,10 +2310,10 @@ static int __init cs4231_init(void)
 
 static void __exit cs4231_exit(void)
 {
-       cs4231_t *p = cs4231_list;
+       struct snd_cs4231 *p = cs4231_list;
 
        while (p != NULL) {
-               cs4231_t *next = p->next;
+               struct snd_cs4231 *next = p->next;
 
                snd_card_free(p->card);