fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / sound / oss / ad1889.c
index 98515fe..09263d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001 Randolph Chung <tausq@debian.org>
+ *  Copyright 2001-2004 Randolph Chung <tausq@debian.org>
  *
  *  Analog Devices 1889 PCI audio driver (AD1819 AC97-compatible codec)
  *
@@ -26,7 +26,6 @@
  *
  * $Id: ad1889.c,v 1.3 2002/10/19 21:31:44 grundler Exp $
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
@@ -38,6 +37,7 @@
 #include <linux/ac97_codec.h>
 #include <linux/sound.h>
 #include <linux/interrupt.h>
+#include <linux/mutex.h>
 
 #include <asm/delay.h>
 #include <asm/io.h>
@@ -61,6 +61,7 @@
 #define AD1889_WRITEL(dev,reg,val) writel((val), dev->regbase + reg)
 
 //now 100ms
+/* #define WAIT_10MS() schedule_timeout(HZ/10) */
 #define WAIT_10MS()    do { int __i; for (__i = 0; __i < 100; __i++) udelay(1000); } while(0)
 
 /* currently only support a single device */
@@ -69,41 +70,47 @@ static ad1889_dev_t *ad1889_dev = NULL;
 /************************* helper routines ***************************** */
 static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
 {
+       struct ac97_codec *ac97_codec = dev->ac97_codec;
+
+       DBG("Setting WAV rate to %d\n", rate);
        dev->state[AD_WAV_STATE].dmabuf.rate = rate;
-       AD1889_WRITEW(dev, AD_DSWAS, rate);
-}
+       AD1889_WRITEW(dev, AD_DS_WAS, rate);
 
-static inline void ad1889_set_adc_rate(ad1889_dev_t *dev, int rate)
-{
-       dev->state[AD_ADC_STATE].dmabuf.rate = rate;
-       AD1889_WRITEW(dev, AD_DSRES, rate);
+       /* Cycle the DAC to enable the new rate */
+       ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
+       WAIT_10MS();
+       ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
 }
 
 static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
 {
        u16 tmp;
 
-       tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
-       if (fmt == AFMT_S16_LE) {
+       DBG("Setting WAV format to 0x%x\n", fmt);
+
+       tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
+       if (fmt & AFMT_S16_LE) {
                //tmp |= 0x0100; /* set WA16 */
                tmp |= 0x0300; /* set WA16 stereo */
-       } else if (fmt == AFMT_U8) {
+       } else if (fmt & AFMT_U8) {
                tmp &= ~0x0100; /* clear WA16 */
        } 
-       AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
+       AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
 }
 
 static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
 {
        u16 tmp;
 
-       tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
-       if (fmt == AFMT_S16_LE) {
+       DBG("Setting ADC format to 0x%x\n", fmt);
+
+       tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
+       if (fmt & AFMT_S16_LE) {
                tmp |= 0x0100; /* set WA16 */
-       } else if (fmt == AFMT_U8) {
+       } else if (fmt & AFMT_U8) {
                tmp &= ~0x0100; /* clear WA16 */
        } 
-       AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
+       AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
 }
 
 static void ad1889_start_wav(ad1889_state_t *state)
@@ -133,22 +140,25 @@ static void ad1889_start_wav(ad1889_state_t *state)
        dmabuf->dma_len = cnt;
        dmabuf->ready = 1;
 
+       DBG("Starting playback at 0x%p for %ld bytes\n", dmabuf->rawbuf +
+           dmabuf->rd_ptr, dmabuf->dma_len);
+
         /* load up the current register set */
-       AD1889_WRITEL(ad1889_dev, AD_DMAWAVCC, cnt);
-       AD1889_WRITEL(ad1889_dev, AD_DMAWAVICC, cnt);
-       AD1889_WRITEL(ad1889_dev, AD_DMAWAVCA, dmabuf->dma_handle);
+       AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCC, cnt);
+       AD1889_WRITEL(ad1889_dev, AD_DMA_WAVICC, cnt);
+       AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCA, dmabuf->dma_handle);
 
        /* TODO: for now we load the base registers with the same thing */
-       AD1889_WRITEL(ad1889_dev, AD_DMAWAVBC, cnt);
-       AD1889_WRITEL(ad1889_dev, AD_DMAWAVIBC, cnt);
-       AD1889_WRITEL(ad1889_dev, AD_DMAWAVBA, dmabuf->dma_handle);
+       AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBC, cnt);
+       AD1889_WRITEL(ad1889_dev, AD_DMA_WAVIBC, cnt);
+       AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBA, dmabuf->dma_handle);
 
        /* and we're off to the races... */
-       AD1889_WRITEL(ad1889_dev, AD_DMACHSS, 0x8);
-       tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+       AD1889_WRITEL(ad1889_dev, AD_DMA_CHSS, 0x8);
+       tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
        tmp |= 0x0400; /* set WAEN */
-       AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
-       (void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */
+       AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
+       (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
 
        dmabuf->enable |= DAC_RUNNING;
 
@@ -168,10 +178,10 @@ static void ad1889_stop_wav(ad1889_state_t *state)
                u16 tmp;
                unsigned long cnt = dmabuf->dma_len;
 
-               tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+               tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
                tmp &= ~0x0400; /* clear WAEN */
-               AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
-               (void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */
+               AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
+               (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
                pci_unmap_single(ad1889_dev->pci, dmabuf->dma_handle, 
                                cnt, PCI_DMA_TODEVICE);
 
@@ -200,7 +210,7 @@ static void ad1889_startstop_adc(ad1889_state_t *state, int start)
 
        spin_lock_irqsave(&state->card->lock, flags);
        
-       tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
+       tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
        if (start) {
                state->dmabuf.enable |= ADC_RUNNING;
                tmp |= 0x0004; /* set ADEN */
@@ -208,7 +218,7 @@ static void ad1889_startstop_adc(ad1889_state_t *state, int start)
                state->dmabuf.enable &= ~ADC_RUNNING;
                tmp &= ~0x0004; /* clear ADEN */
        }
-       AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
+       AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
 
        spin_unlock_irqrestore(&state->card->lock, flags);
 }
@@ -228,7 +238,7 @@ static ad1889_dev_t *ad1889_alloc_dev(struct pci_dev *pci)
 
        for (i = 0; i < AD_MAX_STATES; i++) {
                dev->state[i].card = dev;
-               init_MUTEX(&dev->state[i].sem);
+               mutex_init(&dev->state[i].mutex);
                init_waitqueue_head(&dev->state[i].dmabuf.wait);
        }
 
@@ -243,7 +253,7 @@ static ad1889_dev_t *ad1889_alloc_dev(struct pci_dev *pci)
                dmabuf->dma_handle = 0;
                dmabuf->rd_ptr = dmabuf->wr_ptr = dmabuf->dma_len = 0UL;
                dmabuf->ready = 0;
-               dmabuf->rate = 44100;
+               dmabuf->rate = 48000;
        }
        return dev;
 
@@ -267,8 +277,7 @@ static void ad1889_free_dev(ad1889_dev_t *dev)
 
        for (j = 0; j < AD_MAX_STATES; j++) {
                dmabuf = &dev->state[j].dmabuf;
-               if (dmabuf->rawbuf != NULL) 
-                       kfree(dmabuf->rawbuf);
+               kfree(dmabuf->rawbuf);
        }
 
        kfree(dev);
@@ -284,61 +293,61 @@ static inline void ad1889_trigger_playback(ad1889_dev_t *dev)
        ad1889_start_wav(&dev->state[AD_WAV_STATE]);
 }
 
-int ad1889_read_proc (char *page, char **start, off_t off,
-                     int count, int *eof, void *data)
+static int ad1889_read_proc (char *page, char **start, off_t off,
+                            int count, int *eof, void *data)
 {
        char *out = page;
        int len, i;
        ad1889_dev_t *dev = data;
        ad1889_reg_t regs[] = {
-               { "WSMC", AD_DSWSMC, 16 },
-               { "RAMC", AD_DSRAMC, 16 },
-               { "WADA", AD_DSWADA, 16 },
-               { "SYDA", AD_DSSYDA, 16 },
-               { "WAS", AD_DSWAS, 16 },
-               { "RES", AD_DSRES, 16 },
-               { "CCS", AD_DSCCS, 16 },
-               { "ADCBA", AD_DMAADCBA, 32 },
-               { "ADCCA", AD_DMAADCCA, 32 },
-               { "ADCBC", AD_DMAADCBC, 32 },
-               { "ADCCC", AD_DMAADCCC, 32 },
-               { "ADCIBC", AD_DMAADCIBC, 32 },
-               { "ADCICC", AD_DMAADCICC, 32 },
-               { "ADCCTRL", AD_DMAADCCTRL, 16 },
-               { "WAVBA", AD_DMAWAVBA, 32 },
-               { "WAVCA", AD_DMAWAVCA, 32 },
-               { "WAVBC", AD_DMAWAVBC, 32 },
-               { "WAVCC", AD_DMAWAVCC, 32 },
-               { "WAVIBC", AD_DMAWAVIBC, 32 },
-               { "WAVICC", AD_DMAWAVICC, 32 },
-               { "WAVCTRL", AD_DMAWAVCTRL, 16 },
-               { "DISR", AD_DMADISR, 32 },
-               { "CHSS", AD_DMACHSS, 32 },
-               { "IPC", AD_GPIOIPC, 16 },
-               { "OP", AD_GPIOOP, 16 },
-               { "IP", AD_GPIOIP, 16 },
-               { "ACIC", AD_ACIC, 16 },
-               { "AC97_RESET", 0x100 + AC97_RESET, 16 },
-               { "AC97_MASTER_VOL_STEREO", 0x100 + AC97_MASTER_VOL_STEREO, 16 },
-               { "AC97_HEADPHONE_VOL", 0x100 + AC97_HEADPHONE_VOL, 16 },
-               { "AC97_MASTER_VOL_MONO", 0x100 + AC97_MASTER_VOL_MONO, 16 },
-               { "AC97_MASTER_TONE", 0x100 + AC97_MASTER_TONE, 16 },
-               { "AC97_PCBEEP_VOL", 0x100 + AC97_PCBEEP_VOL, 16 },
-               { "AC97_PHONE_VOL", 0x100 + AC97_PHONE_VOL, 16 },
-               { "AC97_MIC_VOL", 0x100 + AC97_MIC_VOL, 16 },
-               { "AC97_LINEIN_VOL", 0x100 + AC97_LINEIN_VOL, 16 },
-               { "AC97_CD_VOL", 0x100 + AC97_CD_VOL, 16 },
-               { "AC97_VIDEO_VOL", 0x100 + AC97_VIDEO_VOL, 16 },
-               { "AC97_AUX_VOL", 0x100 + AC97_AUX_VOL, 16 },
-               { "AC97_PCMOUT_VOL", 0x100 + AC97_PCMOUT_VOL, 16 },
-               { "AC97_RECORD_SELECT", 0x100 + AC97_RECORD_SELECT, 16 },
-               { "AC97_RECORD_GAIN", 0x100 + AC97_RECORD_GAIN, 16 },
-               { "AC97_RECORD_GAIN_MIC", 0x100 + AC97_RECORD_GAIN_MIC, 16 },
-               { "AC97_GENERAL_PURPOSE", 0x100 + AC97_GENERAL_PURPOSE, 16 },
-               { "AC97_3D_CONTROL", 0x100 + AC97_3D_CONTROL, 16 },
-               { "AC97_MODEM_RATE", 0x100 + AC97_MODEM_RATE, 16 },
-               { "AC97_POWER_CONTROL", 0x100 + AC97_POWER_CONTROL, 16 },
-               { 0 }
+               { "WSMC", AD_DS_WSMC, 16 },
+               { "RAMC", AD_DS_RAMC, 16 },
+               { "WADA", AD_DS_WADA, 16 },
+               { "SYDA", AD_DS_SYDA, 16 },
+               { "WAS", AD_DS_WAS, 16 },
+               { "RES", AD_DS_RES, 16 },
+               { "CCS", AD_DS_CCS, 16 },
+               { "ADCBA", AD_DMA_ADCBA, 32 },
+               { "ADCCA", AD_DMA_ADCCA, 32 },
+               { "ADCBC", AD_DMA_ADCBC, 32 },
+               { "ADCCC", AD_DMA_ADCCC, 32 },
+               { "ADCIBC", AD_DMA_ADCIBC, 32 },
+               { "ADCICC", AD_DMA_ADCICC, 32 },
+               { "ADCCTRL", AD_DMA_ADCCTRL, 16 },
+               { "WAVBA", AD_DMA_WAVBA, 32 },
+               { "WAVCA", AD_DMA_WAVCA, 32 },
+               { "WAVBC", AD_DMA_WAVBC, 32 },
+               { "WAVCC", AD_DMA_WAVCC, 32 },
+               { "WAVIBC", AD_DMA_WAVIBC, 32 },
+               { "WAVICC", AD_DMA_WAVICC, 32 },
+               { "WAVCTRL", AD_DMA_WAVCTRL, 16 },
+               { "DISR", AD_DMA_DISR, 32 },
+               { "CHSS", AD_DMA_CHSS, 32 },
+               { "IPC", AD_GPIO_IPC, 16 },
+               { "OP", AD_GPIO_OP, 16 },
+               { "IP", AD_GPIO_IP, 16 },
+               { "ACIC", AD_AC97_ACIC, 16 },
+               { "AC97_RESET", AD_AC97_BASE + AC97_RESET, 16 },
+               { "AC97_MASTER_VOL_STEREO", AD_AC97_BASE + AC97_MASTER_VOL_STEREO, 16 },
+               { "AC97_HEADPHONE_VOL", AD_AC97_BASE + AC97_HEADPHONE_VOL, 16 },
+               { "AC97_MASTER_VOL_MONO", AD_AC97_BASE + AC97_MASTER_VOL_MONO, 16 },
+               { "AC97_MASTER_TONE", AD_AC97_BASE + AC97_MASTER_TONE, 16 },
+               { "AC97_PCBEEP_VOL", AD_AC97_BASE + AC97_PCBEEP_VOL, 16 },
+               { "AC97_PHONE_VOL", AD_AC97_BASE + AC97_PHONE_VOL, 16 },
+               { "AC97_MIC_VOL", AD_AC97_BASE + AC97_MIC_VOL, 16 },
+               { "AC97_LINEIN_VOL", AD_AC97_BASE + AC97_LINEIN_VOL, 16 },
+               { "AC97_CD_VOL", AD_AC97_BASE + AC97_CD_VOL, 16 },
+               { "AC97_VIDEO_VOL", AD_AC97_BASE + AC97_VIDEO_VOL, 16 },
+               { "AC97_AUX_VOL", AD_AC97_BASE + AC97_AUX_VOL, 16 },
+               { "AC97_PCMOUT_VOL", AD_AC97_BASE + AC97_PCMOUT_VOL, 16 },
+               { "AC97_RECORD_SELECT", AD_AC97_BASE + AC97_RECORD_SELECT, 16 },
+               { "AC97_RECORD_GAIN", AD_AC97_BASE + AC97_RECORD_GAIN, 16 },
+               { "AC97_RECORD_GAIN_MIC", AD_AC97_BASE + AC97_RECORD_GAIN_MIC, 16 },
+               { "AC97_GENERAL_PURPOSE", AD_AC97_BASE + AC97_GENERAL_PURPOSE, 16 },
+               { "AC97_3D_CONTROL", AD_AC97_BASE + AC97_3D_CONTROL, 16 },
+               { "AC97_MODEM_RATE", AD_AC97_BASE + AC97_MODEM_RATE, 16 },
+               { "AC97_POWER_CONTROL", AD_AC97_BASE + AC97_POWER_CONTROL, 16 },
+               { NULL }
        };
 
        if (dev == NULL)
@@ -390,9 +399,9 @@ static inline unsigned long ad1889_get_dma_addr(ad1889_state_t *state)
        }
        
        if (dmabuf->enable & DAC_RUNNING)
-               offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAWAVBA));
+               offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_WAVBA));
        else
-               offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAADCBA));
+               offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_ADCBA));
 
        return (unsigned long)bus_to_virt((unsigned long)offset) - (unsigned long)dmabuf->rawbuf;
 }
@@ -437,13 +446,13 @@ XXX
 
 /************************* /dev/dsp interfaces ************************* */
 
-static ssize_t ad1889_read(struct file *file, char *buffer, size_t count,
+static ssize_t ad1889_read(struct file *file, char __user *buffer, size_t count,
        loff_t *ppos)
 {
        return 0;
 }
 
-static ssize_t ad1889_write(struct file *file, const char *buffer, size_t count,
+static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t count,
        loff_t *ppos)
 {
        ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
@@ -452,10 +461,7 @@ static ssize_t ad1889_write(struct file *file, const char *buffer, size_t count,
        ssize_t ret = 0;
        DECLARE_WAITQUEUE(wait, current);
 
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-
-       down(&state->sem);
+       mutex_lock(&state->mutex);
 #if 0
        if (dmabuf->mapped) {
                ret = -ENXIO;
@@ -475,7 +481,6 @@ static ssize_t ad1889_write(struct file *file, const char *buffer, size_t count,
                long cnt = count;
                unsigned long flags;
 
-
                for (;;) {
                        long used_bytes;
                        long timeout;   /* max time for DMA in jiffies */
@@ -501,17 +506,11 @@ static ssize_t ad1889_write(struct file *file, const char *buffer, size_t count,
                        }
 
                        set_current_state(TASK_INTERRUPTIBLE);
-                       if (!schedule_timeout(timeout + 1))
-                               printk(KERN_WARNING "AD1889 timeout(%ld) r/w %lx/%lx len %lx\n",
-                                   timeout+1,
-                                   dmabuf->rd_ptr, dmabuf->wr_ptr,
-                                   dmabuf->dma_len);
-
+                       schedule_timeout(timeout + 1);
                        if (signal_pending(current)) {
                                ret = -ERESTARTSYS;
                                goto err2;
                        }
-
                }
 
                /* watch out for wrapping around static buffer */
@@ -547,7 +546,7 @@ static ssize_t ad1889_write(struct file *file, const char *buffer, size_t count,
 err2:
        remove_wait_queue(&state->dmabuf.wait, &wait);
 err1:
-       up(&state->sem);
+       mutex_unlock(&state->mutex);
        return ret;
 }
 
@@ -617,11 +616,14 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
        struct dmabuf *dmabuf;
        audio_buf_info abinfo;
+       int __user *p = (int __user *)arg;
+
+       DBG("ad1889_ioctl cmd 0x%x arg %lu\n", cmd, arg);
 
        switch (cmd)
        {
        case OSS_GETVERSION:
-               return put_user(SOUND_VERSION, (int *)arg);
+               return put_user(SOUND_VERSION, p);
 
        case SNDCTL_DSP_RESET:
                break;
@@ -631,58 +633,62 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 
        case SNDCTL_DSP_SPEED:
                /* set sampling rate */
-               if (get_user(val, (int *)arg))
+               if (get_user(val, p))
                        return -EFAULT;
                if (val > 5400 && val < 48000)
                {
                        if (file->f_mode & FMODE_WRITE)
-                               AD1889_WRITEW(ad1889_dev, AD_DSWAS, val);
+                               AD1889_WRITEW(ad1889_dev, AD_DS_WAS, val);
                        if (file->f_mode & FMODE_READ)
-                               AD1889_WRITEW(ad1889_dev, AD_DSRES, val);
+                               AD1889_WRITEW(ad1889_dev, AD_DS_RES, val);
                }
                return 0;
 
        case SNDCTL_DSP_STEREO: /* undocumented? */
-               if (get_user(val, (int *)arg))
+               if (get_user(val, p))
                        return -EFAULT;
                if (file->f_mode & FMODE_READ) {
-                       val = AD1889_READW(ad1889_dev, AD_DSWSMC);
+                       val = AD1889_READW(ad1889_dev, AD_DS_WSMC);
                        if (val) {
                                val |= 0x0200;  /* set WAST */
                        } else {
                                val &= ~0x0200; /* clear WAST */
                        }
-                       AD1889_WRITEW(ad1889_dev, AD_DSWSMC, val);
+                       AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, val);
                }
                if (file->f_mode & FMODE_WRITE) {
-                       val = AD1889_READW(ad1889_dev, AD_DSRAMC);
+                       val = AD1889_READW(ad1889_dev, AD_DS_RAMC);
                        if (val) {
                                val |= 0x0002;  /* set ADST */
                        } else {
                                val &= ~0x0002; /* clear ADST */
                        }
-                       AD1889_WRITEW(ad1889_dev, AD_DSRAMC, val);
+                       AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, val);
                }
 
                return 0;
 
        case SNDCTL_DSP_GETBLKSIZE:
-               return put_user(DMA_SIZE, (int *)arg);
+               return put_user(DMA_SIZE, p);
 
        case SNDCTL_DSP_GETFMTS:
-               return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
+               return put_user(AFMT_S16_LE|AFMT_U8, p);
 
        case SNDCTL_DSP_SETFMT:
-               if (get_user(val, (int *)arg))
+               if (get_user(val, p))
                        return -EFAULT;
 
-               if (file->f_mode & FMODE_READ) 
-                       ad1889_set_adc_fmt(dev, val);
+               if (val == 0) {
+                       if (file->f_mode & FMODE_READ) 
+                               ad1889_set_adc_fmt(dev, val);
 
-               if (file->f_mode & FMODE_WRITE) 
-                       ad1889_set_wav_fmt(dev, val);
+                       if (file->f_mode & FMODE_WRITE) 
+                               ad1889_set_wav_fmt(dev, val);
+               } else {
+                       val = AFMT_S16_LE | AFMT_U8;
+               }
 
-               return put_user(val, (int *)arg);
+               return put_user(val, p);
 
        case SNDCTL_DSP_CHANNELS:
                break;
@@ -696,7 +702,7 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 
        case SNDCTL_DSP_SETFRAGMENT:
                /* not supported; uses fixed fragment sizes */
-               return put_user(DMA_SIZE, (int *)arg);
+               return put_user(DMA_SIZE, p);
 
        case SNDCTL_DSP_GETOSPACE:
        case SNDCTL_DSP_GETISPACE:
@@ -709,13 +715,13 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                abinfo.fragstotal = 1;
                abinfo.fragsize = DMA_SIZE;
                abinfo.bytes = DMA_SIZE;
-               return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+               return copy_to_user(p, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
        case SNDCTL_DSP_NONBLOCK:
                file->f_flags |= O_NONBLOCK;
                return 0;
 
        case SNDCTL_DSP_GETCAPS:
-               return put_user(0, (int *)arg);
+               return put_user(0, p);
 
        case SNDCTL_DSP_GETTRIGGER:
        case SNDCTL_DSP_SETTRIGGER:
@@ -732,7 +738,7 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                break;
 
        case SOUND_PCM_READ_RATE:
-               return put_user(AD1889_READW(ad1889_dev, AD_DSWAS), (int *)arg);
+               return put_user(AD1889_READW(ad1889_dev, AD_DS_WAS), p);
 
        case SOUND_PCM_READ_CHANNELS:
        case SOUND_PCM_READ_BITS:
@@ -760,10 +766,10 @@ static int ad1889_open(struct inode *inode, struct file *file)
        
        file->private_data = ad1889_dev;
 
-       ad1889_set_wav_rate(ad1889_dev, 44100);
+       ad1889_set_wav_rate(ad1889_dev, 48000);
        ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
-       AD1889_WRITEW(ad1889_dev, AD_DSWADA, 0x0404); /* attenuation */
-       return 0;
+       AD1889_WRITEW(ad1889_dev, AD_DS_WADA, 0x0404); /* attenuation */
+       return nonseekable_open(inode, file);
 }
 
 static int ad1889_release(struct inode *inode, struct file *file)
@@ -819,15 +825,15 @@ static void ad1889_codec_write(struct ac97_codec *ac97, u8 reg, u16 val)
 {
        ad1889_dev_t *dev = ac97->private_data;
 
-       //DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + 0x100 + reg);
-       AD1889_WRITEW(dev, 0x100 + reg, val);
+       //DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + AD_AC97_BASE + reg);
+       AD1889_WRITEW(dev, AD_AC97_BASE + reg, val);
 }
 
 static u16 ad1889_codec_read(struct ac97_codec *ac97, u8 reg)
 {
        ad1889_dev_t *dev = ac97->private_data;
-       //DBG("Reading from 0x%lx\n", dev->regbase + 0x100 + reg);
-       return AD1889_READW(dev, 0x100 + reg);
+       //DBG("Reading from 0x%lx\n", dev->regbase + AD_AC97_BASE + reg);
+       return AD1889_READW(dev, AD_AC97_BASE + reg);
 }      
 
 static int ad1889_ac97_init(ad1889_dev_t *dev, int id)
@@ -850,7 +856,7 @@ static int ad1889_ac97_init(ad1889_dev_t *dev, int id)
        }
 
        eid = ad1889_codec_read(ac97, AC97_EXTENDED_ID);
-       if (eid == 0xffffff) {
+       if (eid == 0xffff) {
                printk(KERN_WARNING DEVNAME ": no codec attached?\n");
                goto out_free;
        }
@@ -876,24 +882,24 @@ static int ad1889_aclink_reset(struct pci_dev * pcidev)
        int retry = 200;
        ad1889_dev_t *dev = pci_get_drvdata(pcidev);
 
-       AD1889_WRITEW(dev, AD_DSCCS, 0x8000); /* turn on clock */
-       AD1889_READW(dev, AD_DSCCS); 
+       AD1889_WRITEW(dev, AD_DS_CCS, 0x8000); /* turn on clock */
+       AD1889_READW(dev, AD_DS_CCS);
 
        WAIT_10MS();
 
-       stat = AD1889_READW(dev, AD_ACIC);
+       stat = AD1889_READW(dev, AD_AC97_ACIC);
        stat |= 0x0002;                         /* Reset Disable */
-       AD1889_WRITEW(dev, AD_ACIC, stat);
-       (void) AD1889_READW(dev, AD_ACIC);      /* flush posted write */
+       AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
+       (void) AD1889_READW(dev, AD_AC97_ACIC); /* flush posted write */
 
        udelay(10);
 
-       stat = AD1889_READW(dev, AD_ACIC);
+       stat = AD1889_READW(dev, AD_AC97_ACIC);
        stat |= 0x0001;                         /* Interface Enable */
-       AD1889_WRITEW(dev, AD_ACIC, stat);
+       AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
 
        do {
-               if (AD1889_READW(dev, AD_ACIC) & 0x8000)        /* Ready */
+               if (AD1889_READW(dev, AD_AC97_ACIC) & 0x8000)   /* Ready */
                        break;
                WAIT_10MS();
                retry--;
@@ -901,16 +907,16 @@ static int ad1889_aclink_reset(struct pci_dev * pcidev)
 
        if (!retry) {
                printk(KERN_ERR "ad1889_aclink_reset: codec is not ready [0x%x]\n",
-                           AD1889_READW(dev, AD_ACIC));
+                           AD1889_READW(dev, AD_AC97_ACIC));
                return -EBUSY;
        }
 
        /* TODO reset AC97 codec */
        /* TODO set wave/adc pci ctrl status */
 
-       stat = AD1889_READW(dev, AD_ACIC);
+       stat = AD1889_READW(dev, AD_AC97_ACIC);
        stat |= 0x0004;                         /* Audio Stream Output Enable */
-       AD1889_WRITEW(dev, AD_ACIC, stat);
+       AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
        return 0;
 }
 
@@ -923,15 +929,15 @@ static struct pci_device_id ad1889_id_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, ad1889_id_tbl);
 
-static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ad1889_interrupt(int irq, void *dev_id)
 {
        u32 stat;
        ad1889_dev_t *dev = (ad1889_dev_t *)dev_id;
 
-       stat = AD1889_READL(dev, AD_DMADISR);
+       stat = AD1889_READL(dev, AD_DMA_DISR);
 
        /* clear ISR */
-       AD1889_WRITEL(dev, AD_DMADISR, stat);
+       AD1889_WRITEL(dev, AD_DMA_DISR, stat);
 
        if (stat & 0x8) {               /* WAVI */
                DBG("WAV interrupt\n");
@@ -940,7 +946,6 @@ static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        ad1889_stop_wav(&dev->state[AD_WAV_STATE]);     /* clean up */
                        ad1889_start_wav(&dev->state[AD_WAV_STATE]);    /* start new */
                }
-
        }
 
        if ((stat & 0x2) && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */
@@ -954,18 +959,19 @@ static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 static void ad1889_initcfg(ad1889_dev_t *dev)
 {
-       u16 tmp;
+       u16 tmp16;
+       u32 tmp32;
 
        /* make sure the interrupt bits are setup the way we want */
-       tmp = AD1889_READW(dev, AD_DMAWAVCTRL);
-       tmp &= ~0x00ff; /* flat dma, no sg, mask out the intr bits */
-       tmp |= 0x0004;  /* intr on count, loop */
-       AD1889_WRITEW(dev, AD_DMAWAVCTRL, tmp);
+       tmp32 = AD1889_READL(dev, AD_DMA_WAVCTRL);
+       tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
+       tmp32 |= 0x6;  /* intr on count, loop */
+       AD1889_WRITEL(dev, AD_DMA_WAVCTRL, tmp32);
 
        /* unmute... */
-       tmp = AD1889_READW(dev, AD_DSWADA);
-       tmp &= ~0x8080;
-       AD1889_WRITEW(dev, AD_DSWADA, tmp);
+       tmp16 = AD1889_READW(dev, AD_DS_WADA);
+       tmp16 &= ~0x8080;
+       AD1889_WRITEW(dev, AD_DS_WADA, tmp16);
 }
 
 static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
@@ -990,36 +996,45 @@ static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_devic
        
         if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
                printk(KERN_ERR DEVNAME ": memory region not assigned\n");
-               goto err_free_mem;
+               goto out1;
        }
 
-       if (request_irq(pcidev->irq, ad1889_interrupt, SA_SHIRQ, DEVNAME, dev) != 0) {
-               printk(KERN_ERR DEVNAME ": unable to request interrupt\n");
-               goto err_free_mem;
+       if (pci_request_region(pcidev, 0, DEVNAME)) {
+               printk(KERN_ERR DEVNAME ": unable to request memory region\n");
+               goto out1;
        }
 
-       request_mem_region(bar, AD_DSIOMEMSIZE, DEVNAME);
-       dev->regbase = (unsigned long)ioremap_nocache(bar, AD_DSIOMEMSIZE);
+       dev->regbase = ioremap_nocache(bar, AD_DS_IOMEMSIZE);
+       if (!dev->regbase) {
+               printk(KERN_ERR DEVNAME ": unable to remap iomem\n");
+               goto out2;
+       }
+
+       if (request_irq(pcidev->irq, ad1889_interrupt, IRQF_SHARED, DEVNAME, dev) != 0) {
+               printk(KERN_ERR DEVNAME ": unable to request interrupt\n");
+               goto out3;
+       }
 
-       printk(KERN_INFO DEVNAME ": %s at 0x%lx IRQ %d\n",
+       printk(KERN_INFO DEVNAME ": %s at %p IRQ %d\n",
                (char *)ent->driver_data, dev->regbase, pcidev->irq);
 
        if (ad1889_aclink_reset(pcidev) != 0)
-               goto err_free_mem;
+               goto out4;
 
        /* register /dev/dsp */
        if ((dev->dev_audio = register_sound_dsp(&ad1889_fops, -1)) < 0) {
                printk(KERN_ERR DEVNAME ": cannot register /dev/dsp\n");
-               goto err_free_irq;
+               goto out4;
        }
 
        if ((err = ad1889_ac97_init(dev, 0)) != 0)
-               goto err_free_dsp;
+               goto out5;
 
-       if (((proc_root = proc_mkdir("driver/ad1889", 0)) == NULL) ||
+       /* XXX: cleanups */
+       if (((proc_root = proc_mkdir("driver/ad1889", NULL)) == NULL) ||
            create_proc_read_entry("ac97", S_IFREG|S_IRUGO, proc_root, ac97_read_proc, dev->ac97_codec) == NULL ||
            create_proc_read_entry("info", S_IFREG|S_IRUGO, proc_root, ad1889_read_proc, dev) == NULL) 
-               goto err_free_dsp;
+               goto out5;
        
        ad1889_initcfg(dev);
 
@@ -1029,15 +1044,17 @@ static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_devic
 
        return 0;
 
-err_free_dsp:
+out5:
        unregister_sound_dsp(dev->dev_audio);
-
-err_free_irq:
+out4:
        free_irq(pcidev->irq, dev);
-
-err_free_mem:
+out3:
+       iounmap(dev->regbase);
+out2:
+       pci_release_region(pcidev, 0);
+out1:
        ad1889_free_dev(dev);
-       pci_set_drvdata(pcidev, 0);
+       pci_set_drvdata(pcidev, NULL);
 
        return -ENODEV;
 }
@@ -1051,10 +1068,12 @@ static void __devexit ad1889_remove(struct pci_dev *pcidev)
        unregister_sound_mixer(dev->ac97_codec->dev_mixer);
        unregister_sound_dsp(dev->dev_audio);
        free_irq(pcidev->irq, dev);
-       release_mem_region(dev->regbase, AD_DSIOMEMSIZE);
+       iounmap(dev->regbase);
+       pci_release_region(pcidev, 0);
 
        /* any hw programming needed? */
        ad1889_free_dev(dev);
+       pci_set_drvdata(pcidev, NULL);
 }
 
 MODULE_AUTHOR("Randolph Chung");
@@ -1070,7 +1089,7 @@ static struct pci_driver ad1889_driver = {
 
 static int __init ad1889_init_module(void)
 {
-       return pci_module_init(&ad1889_driver);
+       return pci_register_driver(&ad1889_driver);
 }
 
 static void ad1889_exit_module(void)