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 / oss / au1000.c
index c5d220e..eacb0ae 100644 (file)
@@ -59,6 +59,7 @@
 #include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/init.h>
+#include <linux/page-flags.h>
 #include <linux/poll.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
-#include <linux/wrapper.h>
 #include <linux/interrupt.h>
+#include <linux/mutex.h>
+
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/au1000.h>
-#include <asm/au1000_dma.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1000_dma.h>
 
 /* --------------------------------------------------------------------- */
 
 #undef OSS_DOCUMENTED_MIXER_SEMANTICS
-#define AU1000_DEBUG
+#undef AU1000_DEBUG
 #undef AU1000_VERBOSE_DEBUG
 
-#define USE_COHERENT_DMA
-
 #define AU1000_MODULE_NAME "Au1000 audio"
 #define PFX AU1000_MODULE_NAME
 
 
 /* Boot options */
 static int      vra = 0;       // 0 = no VRA, 1 = use VRA if codec supports it
-MODULE_PARM(vra, "i");
+module_param(vra, bool, 0);
 MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
 
 
@@ -116,14 +116,14 @@ struct au1000_state {
        struct proc_dir_entry *ac97_ps;
 #endif                         /* AU1000_DEBUG */
 
-       struct ac97_codec *codec;
+       struct ac97_codec codec;
        unsigned        codec_base_caps;// AC'97 reg 00h, "Reset Register"
        unsigned        codec_ext_caps; // AC'97 reg 28h, "Extended Audio ID"
        int             no_vra; // do not use VRA
 
        spinlock_t      lock;
-       struct semaphore open_sem;
-       struct semaphore sem;
+       struct mutex open_mutex;
+       struct mutex sem;
        mode_t          open_mode;
        wait_queue_head_t open_wait;
 
@@ -191,35 +191,6 @@ static inline unsigned ld2(unsigned int x)
        return r;
 }
 
-
-#ifdef USE_COHERENT_DMA
-static inline void * dma_alloc(size_t size, dma_addr_t * dma_handle)
-{
-       void* ret = (void *)__get_free_pages(GFP_ATOMIC | GFP_DMA,
-                                            get_order(size));
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *dma_handle = virt_to_phys(ret);
-       }
-       return ret;
-}
-
-static inline void dma_free(size_t size, void* va, dma_addr_t dma_handle)
-{
-       free_pages((unsigned long)va, get_order(size));
-}
-#else
-static inline void * dma_alloc(size_t size, dma_addr_t * dma_handle)
-{
-       return pci_alloc_consistent(NULL, size, dma_handle);
-}
-
-static inline void dma_free(size_t size, void* va, dma_addr_t dma_handle)
-{
-       pci_free_consistent(NULL, size, va, dma_handle);
-}
-#endif
-
 /* --------------------------------------------------------------------- */
 
 static void au1000_delay(int msec)
@@ -356,17 +327,17 @@ static void set_adc_rate(struct au1000_state *s, unsigned rate)
 
        adc->src_factor = 1;
 
-       ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS);
+       ac97_extstat = rdcodec(&s->codec, AC97_EXTENDED_STATUS);
 
        rate = rate > 48000 ? 48000 : rate;
 
        // enable VRA
-       wrcodec(s->codec, AC97_EXTENDED_STATUS,
+       wrcodec(&s->codec, AC97_EXTENDED_STATUS,
                ac97_extstat | AC97_EXTSTAT_VRA);
        // now write the sample rate
-       wrcodec(s->codec, AC97_PCM_LR_ADC_RATE, (u16) rate);
+       wrcodec(&s->codec, AC97_PCM_LR_ADC_RATE, (u16) rate);
        // read it back for actual supported rate
-       adc_rate = rdcodec(s->codec, AC97_PCM_LR_ADC_RATE);
+       adc_rate = rdcodec(&s->codec, AC97_PCM_LR_ADC_RATE);
 
 #ifdef AU1000_VERBOSE_DEBUG
        dbg("%s: set to %d Hz", __FUNCTION__, adc_rate);
@@ -374,11 +345,11 @@ static void set_adc_rate(struct au1000_state *s, unsigned rate)
 
        // some codec's don't allow unequal DAC and ADC rates, in which case
        // writing one rate reg actually changes both.
-       dac_rate = rdcodec(s->codec, AC97_PCM_FRONT_DAC_RATE);
+       dac_rate = rdcodec(&s->codec, AC97_PCM_FRONT_DAC_RATE);
        if (dac->num_channels > 2)
-               wrcodec(s->codec, AC97_PCM_SURR_DAC_RATE, dac_rate);
+               wrcodec(&s->codec, AC97_PCM_SURR_DAC_RATE, dac_rate);
        if (dac->num_channels > 4)
-               wrcodec(s->codec, AC97_PCM_LFE_DAC_RATE, dac_rate);
+               wrcodec(&s->codec, AC97_PCM_LFE_DAC_RATE, dac_rate);
 
        adc->sample_rate = adc_rate;
        dac->sample_rate = dac_rate;
@@ -401,23 +372,23 @@ static void set_dac_rate(struct au1000_state *s, unsigned rate)
 
        dac->src_factor = 1;
 
-       ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS);
+       ac97_extstat = rdcodec(&s->codec, AC97_EXTENDED_STATUS);
 
        rate = rate > 48000 ? 48000 : rate;
 
        // enable VRA
-       wrcodec(s->codec, AC97_EXTENDED_STATUS,
+       wrcodec(&s->codec, AC97_EXTENDED_STATUS,
                ac97_extstat | AC97_EXTSTAT_VRA);
        // now write the sample rate
-       wrcodec(s->codec, AC97_PCM_FRONT_DAC_RATE, (u16) rate);
+       wrcodec(&s->codec, AC97_PCM_FRONT_DAC_RATE, (u16) rate);
        // I don't support different sample rates for multichannel,
        // so make these channels the same.
        if (dac->num_channels > 2)
-               wrcodec(s->codec, AC97_PCM_SURR_DAC_RATE, (u16) rate);
+               wrcodec(&s->codec, AC97_PCM_SURR_DAC_RATE, (u16) rate);
        if (dac->num_channels > 4)
-               wrcodec(s->codec, AC97_PCM_LFE_DAC_RATE, (u16) rate);
+               wrcodec(&s->codec, AC97_PCM_LFE_DAC_RATE, (u16) rate);
        // read it back for actual supported rate
-       dac_rate = rdcodec(s->codec, AC97_PCM_FRONT_DAC_RATE);
+       dac_rate = rdcodec(&s->codec, AC97_PCM_FRONT_DAC_RATE);
 
 #ifdef AU1000_VERBOSE_DEBUG
        dbg("%s: set to %d Hz", __FUNCTION__, dac_rate);
@@ -425,7 +396,7 @@ static void set_dac_rate(struct au1000_state *s, unsigned rate)
 
        // some codec's don't allow unequal DAC and ADC rates, in which case
        // writing one rate reg actually changes both.
-       adc_rate = rdcodec(s->codec, AC97_PCM_LR_ADC_RATE);
+       adc_rate = rdcodec(&s->codec, AC97_PCM_LR_ADC_RATE);
 
        dac->sample_rate = dac_rate;
        adc->sample_rate = adc_rate;
@@ -594,7 +565,7 @@ static void start_adc(struct au1000_state *s)
 #define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-extern inline void dealloc_dmabuf(struct au1000_state *s, struct dmabuf *db)
+static inline void dealloc_dmabuf(struct au1000_state *s, struct dmabuf *db)
 {
        struct page    *page, *pend;
 
@@ -603,8 +574,11 @@ extern inline void dealloc_dmabuf(struct au1000_state *s, struct dmabuf *db)
                pend = virt_to_page(db->rawbuf +
                                    (PAGE_SIZE << db->buforder) - 1);
                for (page = virt_to_page(db->rawbuf); page <= pend; page++)
-                       mem_map_unreserve(page);
-               dma_free(PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr);
+                       ClearPageReserved(page);
+               dma_free_noncoherent(NULL,
+                               PAGE_SIZE << db->buforder,
+                               db->rawbuf,
+                               db->dmaaddr);
        }
        db->rawbuf = db->nextIn = db->nextOut = NULL;
        db->mapped = db->ready = 0;
@@ -622,18 +596,20 @@ static int prog_dmabuf(struct au1000_state *s, struct dmabuf *db)
                db->ready = db->mapped = 0;
                for (order = DMABUF_DEFAULTORDER;
                     order >= DMABUF_MINORDER; order--)
-                       if ((db->rawbuf = dma_alloc(PAGE_SIZE << order,
-                                                 &db->dmaaddr)))
+                       if ((db->rawbuf = dma_alloc_noncoherent(NULL,
+                                               PAGE_SIZE << order,
+                                               &db->dmaaddr,
+                                               0)))
                                break;
                if (!db->rawbuf)
                        return -ENOMEM;
                db->buforder = order;
                /* now mark the pages as reserved;
-                  otherwise remap_page_range doesn't do what we want */
+                  otherwise remap_pfn_range doesn't do what we want */
                pend = virt_to_page(db->rawbuf +
                                    (PAGE_SIZE << db->buforder) - 1);
                for (page = virt_to_page(db->rawbuf); page <= pend; page++)
-                       mem_map_reserve(page);
+                       SetPageReserved(page);
        }
 
        db->cnt_factor = 1;
@@ -693,14 +669,14 @@ static int prog_dmabuf(struct au1000_state *s, struct dmabuf *db)
        return 0;
 }
 
-extern inline int prog_dmabuf_adc(struct au1000_state *s)
+static inline int prog_dmabuf_adc(struct au1000_state *s)
 {
        stop_adc(s);
        return prog_dmabuf(s, &s->dma_adc);
 
 }
 
-extern inline int prog_dmabuf_dac(struct au1000_state *s)
+static inline int prog_dmabuf_dac(struct au1000_state *s)
 {
        stop_dac(s);
        return prog_dmabuf(s, &s->dma_dac);
@@ -708,7 +684,7 @@ extern inline int prog_dmabuf_dac(struct au1000_state *s)
 
 
 /* hold spinlock for the following */
-static void dac_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dac_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct au1000_state *s = (struct au1000_state *) dev_id;
        struct dmabuf  *dac = &s->dma_dac;
@@ -723,7 +699,7 @@ static void dac_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        if ((buff_done = get_dma_buffer_done(dac->dmanr)) == 0) {
                /* fastpath out, to ease interrupt sharing */
-               return;
+               return IRQ_HANDLED;
        }
 
        spin_lock(&s->lock);
@@ -786,10 +762,12 @@ static void dac_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                wake_up(&dac->wait);
 
        spin_unlock(&s->lock);
+
+       return IRQ_HANDLED;
 }
 
 
-static void adc_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t adc_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct au1000_state *s = (struct au1000_state *) dev_id;
        struct dmabuf  *adc = &s->dma_adc;
@@ -804,7 +782,7 @@ static void adc_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        if ((buff_done = get_dma_buffer_done(adc->dmanr)) == 0) {
                /* fastpath out, to ease interrupt sharing */
-               return;
+               return IRQ_HANDLED;
        }
 
        spin_lock(&s->lock);
@@ -816,7 +794,7 @@ static void adc_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        stop_adc(s);
                        adc->error++;
                        err("adc overrun");
-                       return;
+                       return IRQ_NONE;
                }
 
                adc->nextIn += adc->dma_fragsize;
@@ -853,7 +831,7 @@ static void adc_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        adc->error++;
                        err("adc overrun");
                        spin_unlock(&s->lock);
-                       return;
+                       return IRQ_NONE;
                }
 
                adc->nextIn += 2*adc->dma_fragsize;
@@ -873,6 +851,8 @@ static void adc_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                wake_up(&adc->wait);
 
        spin_unlock(&s->lock);
+
+       return IRQ_HANDLED;
 }
 
 /* --------------------------------------------------------------------- */
@@ -904,7 +884,7 @@ static int au1000_ioctl_mixdev(struct inode *inode, struct file *file,
                               unsigned int cmd, unsigned long arg)
 {
        struct au1000_state *s = (struct au1000_state *)file->private_data;
-       struct ac97_codec *codec = s->codec;
+       struct ac97_codec *codec = &s->codec;
 
        return mixdev_ioctl(codec, cmd, arg);
 }
@@ -1128,7 +1108,7 @@ static ssize_t au1000_read(struct file *file, char *buffer,
 
        count *= db->cnt_factor;
 
-       down(&s->sem);
+       mutex_lock(&s->sem);
        add_wait_queue(&db->wait, &wait);
 
        while (count > 0) {
@@ -1147,14 +1127,14 @@ static ssize_t au1000_read(struct file *file, char *buffer,
                                                ret = -EAGAIN;
                                        goto out;
                                }
-                               up(&s->sem);
+                               mutex_unlock(&s->sem);
                                schedule();
                                if (signal_pending(current)) {
                                        if (!ret)
                                                ret = -ERESTARTSYS;
                                        goto out2;
                                }
-                               down(&s->sem);
+                               mutex_lock(&s->sem);
                        }
                } while (avail <= 0);
 
@@ -1181,7 +1161,7 @@ static ssize_t au1000_read(struct file *file, char *buffer,
        }                       // while (count > 0)
 
 out:
-       up(&s->sem);
+       mutex_unlock(&s->sem);
 out2:
        remove_wait_queue(&db->wait, &wait);
        set_current_state(TASK_RUNNING);
@@ -1209,7 +1189,7 @@ static ssize_t au1000_write(struct file *file, const char *buffer,
 
        count *= db->cnt_factor;
 
-       down(&s->sem);  
+       mutex_lock(&s->sem);
        add_wait_queue(&db->wait, &wait);
 
        while (count > 0) {
@@ -1226,14 +1206,14 @@ static ssize_t au1000_write(struct file *file, const char *buffer,
                                                ret = -EAGAIN;
                                        goto out;
                                }
-                               up(&s->sem);
+                               mutex_unlock(&s->sem);
                                schedule();
                                if (signal_pending(current)) {
                                        if (!ret)
                                                ret = -ERESTARTSYS;
                                        goto out2;
                                }
-                               down(&s->sem);
+                               mutex_lock(&s->sem);
                        }
                } while (avail <= 0);
 
@@ -1262,7 +1242,7 @@ static ssize_t au1000_write(struct file *file, const char *buffer,
        }                       // while (count > 0)
 
 out:
-       up(&s->sem);
+       mutex_unlock(&s->sem);
 out2:
        remove_wait_queue(&db->wait, &wait);
        set_current_state(TASK_RUNNING);
@@ -1317,10 +1297,10 @@ static int au1000_mmap(struct file *file, struct vm_area_struct *vma)
        unsigned long   size;
        int ret = 0;
 
-       dbg(__FUNCTION__);
+       dbg("%s", __FUNCTION__);
     
        lock_kernel();
-       down(&s->sem);
+       mutex_lock(&s->sem);
        if (vma->vm_flags & VM_WRITE)
                db = &s->dma_dac;
        else if (vma->vm_flags & VM_READ)
@@ -1338,7 +1318,7 @@ static int au1000_mmap(struct file *file, struct vm_area_struct *vma)
                ret = -EINVAL;
                goto out;
        }
-       if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf),
+       if (remap_pfn_range(vma, vma->vm_start, virt_to_phys(db->rawbuf),
                             size, vma->vm_page_prot)) {
                ret = -EAGAIN;
                goto out;
@@ -1346,7 +1326,7 @@ static int au1000_mmap(struct file *file, struct vm_area_struct *vma)
        vma->vm_flags &= ~VM_IO;
        db->mapped = 1;
 out:
-       up(&s->sem);
+       mutex_unlock(&s->sem);
        unlock_kernel();
        return ret;
 }
@@ -1499,9 +1479,9 @@ static int au1000_ioctl(struct inode *inode, struct file *file,
                        s->dma_dac.num_channels = val ? 2 : 1;
                        if (s->codec_ext_caps & AC97_EXT_DACS) {
                                // disable surround and center/lfe in AC'97
-                               u16 ext_stat = rdcodec(s->codec,
+                               u16 ext_stat = rdcodec(&s->codec,
                                                       AC97_EXTENDED_STATUS);
-                               wrcodec(s->codec, AC97_EXTENDED_STATUS,
+                               wrcodec(&s->codec, AC97_EXTENDED_STATUS,
                                        ext_stat | (AC97_EXTSTAT_PRI |
                                                    AC97_EXTSTAT_PRJ |
                                                    AC97_EXTSTAT_PRK));
@@ -1551,9 +1531,9 @@ static int au1000_ioctl(struct inode *inode, struct file *file,
                                        // disable surround and center/lfe
                                        // channels in AC'97
                                        u16             ext_stat =
-                                               rdcodec(s->codec,
+                                               rdcodec(&s->codec,
                                                        AC97_EXTENDED_STATUS);
-                                       wrcodec(s->codec,
+                                       wrcodec(&s->codec,
                                                AC97_EXTENDED_STATUS,
                                                ext_stat | (AC97_EXTSTAT_PRI |
                                                            AC97_EXTSTAT_PRJ |
@@ -1562,14 +1542,14 @@ static int au1000_ioctl(struct inode *inode, struct file *file,
                                        // enable surround, center/lfe
                                        // channels in AC'97
                                        u16             ext_stat =
-                                               rdcodec(s->codec,
+                                               rdcodec(&s->codec,
                                                        AC97_EXTENDED_STATUS);
                                        ext_stat &= ~AC97_EXTSTAT_PRJ;
                                        if (val == 6)
                                                ext_stat &=
                                                        ~(AC97_EXTSTAT_PRI |
                                                          AC97_EXTSTAT_PRK);
-                                       wrcodec(s->codec,
+                                       wrcodec(&s->codec,
                                                AC97_EXTENDED_STATUS,
                                                ext_stat);
                                }
@@ -1831,7 +1811,7 @@ static int au1000_ioctl(struct inode *inode, struct file *file,
                return -EINVAL;
        }
 
-       return mixdev_ioctl(s->codec, cmd, arg);
+       return mixdev_ioctl(&s->codec, cmd, arg);
 }
 
 
@@ -1851,21 +1831,21 @@ static int  au1000_open(struct inode *inode, struct file *file)
        
        file->private_data = s;
        /* wait for device to become free */
-       down(&s->open_sem);
+       mutex_lock(&s->open_mutex);
        while (s->open_mode & file->f_mode) {
                if (file->f_flags & O_NONBLOCK) {
-                       up(&s->open_sem);
+                       mutex_unlock(&s->open_mutex);
                        return -EBUSY;
                }
                add_wait_queue(&s->open_wait, &wait);
                __set_current_state(TASK_INTERRUPTIBLE);
-               up(&s->open_sem);
+               mutex_unlock(&s->open_mutex);
                schedule();
                remove_wait_queue(&s->open_wait, &wait);
                set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
-               down(&s->open_sem);
+               mutex_lock(&s->open_mutex);
        }
 
        stop_dac(s);
@@ -1901,8 +1881,8 @@ static int  au1000_open(struct inode *inode, struct file *file)
        }
 
        s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
-       up(&s->open_sem);
-       init_MUTEX(&s->sem);
+       mutex_unlock(&s->open_mutex);
+       mutex_init(&s->sem);
        return nonseekable_open(inode, file);
 }
 
@@ -1918,7 +1898,7 @@ static int au1000_release(struct inode *inode, struct file *file)
                lock_kernel();
        }
 
-       down(&s->open_sem);
+       mutex_lock(&s->open_mutex);
        if (file->f_mode & FMODE_WRITE) {
                stop_dac(s);
                dealloc_dmabuf(s, &s->dma_dac);
@@ -1928,7 +1908,7 @@ static int au1000_release(struct inode *inode, struct file *file)
                dealloc_dmabuf(s, &s->dma_adc);
        }
        s->open_mode &= ((~file->f_mode) & (FMODE_READ|FMODE_WRITE));
-       up(&s->open_sem);
+       mutex_unlock(&s->open_mutex);
        wake_up(&s->open_wait);
        unlock_kernel();
        return 0;
@@ -1982,7 +1962,7 @@ static int proc_au1000_dump(char *buf, char **start, off_t fpos,
        len += sprintf(buf + len, "----------------------\n");
        for (cnt = 0; cnt <= 0x7e; cnt += 2)
                len += sprintf(buf + len, "reg %02x = %04x\n",
-                              cnt, rdcodec(s->codec, cnt));
+                              cnt, rdcodec(&s->codec, cnt));
 
        if (fpos >= len) {
                *start = buf;
@@ -2009,32 +1989,27 @@ static int __devinit au1000_probe(void)
 {
        struct au1000_state *s = &au1000_state;
        int             val;
+#ifdef AU1000_DEBUG
        char            proc_str[80];
+#endif
 
        memset(s, 0, sizeof(struct au1000_state));
 
        init_waitqueue_head(&s->dma_adc.wait);
        init_waitqueue_head(&s->dma_dac.wait);
        init_waitqueue_head(&s->open_wait);
-       init_MUTEX(&s->open_sem);
+       mutex_init(&s->open_mutex);
        spin_lock_init(&s->lock);
-       
-       s->codec = ac97_alloc_codec();
-       if(s->codec == NULL)
-       {
-               error("Out of memory");
-               return -1;
-       }
-       s->codec->private_data = s;
-       s->codec->id = 0;
-       s->codec->codec_read = rdcodec;
-       s->codec->codec_write = wrcodec;
-       s->codec->codec_wait = waitcodec;
+       s->codec.private_data = s;
+       s->codec.id = 0;
+       s->codec.codec_read = rdcodec;
+       s->codec.codec_write = wrcodec;
+       s->codec.codec_wait = waitcodec;
 
-       if (!request_region(virt_to_phys((void *) AC97C_CONFIG),
+       if (!request_mem_region(CPHYSADDR(AC97C_CONFIG),
                            0x14, AU1000_MODULE_NAME)) {
                err("AC'97 ports in use");
-               goto err_codec;
+               return -1;
        }
        // Allocate the DMA Channels
        if ((s->dma_dac.dmanr = request_au1000_dma(DMA_ID_AC97C_TX,
@@ -2056,25 +2031,17 @@ static int __devinit au1000_probe(void)
             s->dma_dac.dmanr, get_dma_done_irq(s->dma_dac.dmanr),
             s->dma_adc.dmanr, get_dma_done_irq(s->dma_adc.dmanr));
 
-#ifdef USE_COHERENT_DMA
        // enable DMA coherency in read/write DMA channels
        set_dma_mode(s->dma_dac.dmanr,
                     get_dma_mode(s->dma_dac.dmanr) & ~DMA_NC);
        set_dma_mode(s->dma_adc.dmanr,
                     get_dma_mode(s->dma_adc.dmanr) & ~DMA_NC);
-#else
-       // disable DMA coherency in read/write DMA channels
-       set_dma_mode(s->dma_dac.dmanr,
-                    get_dma_mode(s->dma_dac.dmanr) | DMA_NC);
-       set_dma_mode(s->dma_adc.dmanr,
-                    get_dma_mode(s->dma_adc.dmanr) | DMA_NC);
-#endif
 
        /* register devices */
 
        if ((s->dev_audio = register_sound_dsp(&au1000_audio_fops, -1)) < 0)
                goto err_dev1;
-       if ((s->codec->dev_mixer =
+       if ((s->codec.dev_mixer =
             register_sound_mixer(&au1000_mixer_fops, -1)) < 0)
                goto err_dev2;
 
@@ -2107,11 +2074,11 @@ static int __devinit au1000_probe(void)
        au_writel(0, AC97C_CONFIG);
 
        /* codec init */
-       if (!ac97_probe_codec(s->codec))
+       if (!ac97_probe_codec(&s->codec))
                goto err_dev3;
 
-       s->codec_base_caps = rdcodec(s->codec, AC97_RESET);
-       s->codec_ext_caps = rdcodec(s->codec, AC97_EXTENDED_ID);
+       s->codec_base_caps = rdcodec(&s->codec, AC97_RESET);
+       s->codec_ext_caps = rdcodec(&s->codec, AC97_EXTENDED_ID);
        info("AC'97 Base/Extended ID = %04x/%04x",
             s->codec_base_caps, s->codec_ext_caps);
 
@@ -2123,12 +2090,12 @@ static int __devinit au1000_probe(void)
         * ALTPCM). ac97_codec.c does not handle detection
         * of this channel correctly.
         */
-       s->codec->supported_mixers |= SOUND_MASK_ALTPCM;
+       s->codec.supported_mixers |= SOUND_MASK_ALTPCM;
        /*
         * Now set AUX_OUT's default volume.
         */
        val = 0x4343;
-       mixdev_ioctl(s->codec, SOUND_MIXER_WRITE_ALTPCM,
+       mixdev_ioctl(&s->codec, SOUND_MIXER_WRITE_ALTPCM,
                     (unsigned long) &val);
        
        if (!(s->codec_ext_caps & AC97_EXTID_VRA)) {
@@ -2136,8 +2103,8 @@ static int __devinit au1000_probe(void)
                s->no_vra = 1;
        } else if (!vra) {
                // Boot option says disable VRA
-               u16 ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS);
-               wrcodec(s->codec, AC97_EXTENDED_STATUS,
+               u16 ac97_extstat = rdcodec(&s->codec, AC97_EXTENDED_STATUS);
+               wrcodec(&s->codec, AC97_EXTENDED_STATUS,
                        ac97_extstat & ~AC97_EXTSTAT_VRA);
                s->no_vra = 1;
        }
@@ -2146,20 +2113,38 @@ static int __devinit au1000_probe(void)
 
        /* set mic to be the recording source */
        val = SOUND_MASK_MIC;
-       mixdev_ioctl(s->codec, SOUND_MIXER_WRITE_RECSRC,
+       mixdev_ioctl(&s->codec, SOUND_MIXER_WRITE_RECSRC,
                     (unsigned long) &val);
 
 #ifdef AU1000_DEBUG
        sprintf(proc_str, "driver/%s/%d/ac97", AU1000_MODULE_NAME,
-               s->codec->id);
+               s->codec.id);
        s->ac97_ps = create_proc_read_entry (proc_str, 0, NULL,
-                                            ac97_read_proc, s->codec);
+                                            ac97_read_proc, &s->codec);
+#endif
+
+#ifdef CONFIG_MIPS_XXS1500
+       /* deassert eapd */
+       wrcodec(&s->codec, AC97_POWER_CONTROL,
+                       rdcodec(&s->codec, AC97_POWER_CONTROL) & ~0x8000);
+       /* mute a number of signals which seem to be causing problems
+        * if not muted.
+        */
+       wrcodec(&s->codec, AC97_PCBEEP_VOL, 0x8000);
+       wrcodec(&s->codec, AC97_PHONE_VOL, 0x8008);
+       wrcodec(&s->codec, AC97_MIC_VOL, 0x8008);
+       wrcodec(&s->codec, AC97_LINEIN_VOL, 0x8808);
+       wrcodec(&s->codec, AC97_CD_VOL, 0x8808);
+       wrcodec(&s->codec, AC97_VIDEO_VOL, 0x8808);
+       wrcodec(&s->codec, AC97_AUX_VOL, 0x8808);
+       wrcodec(&s->codec, AC97_PCMOUT_VOL, 0x0808);
+       wrcodec(&s->codec, AC97_GENERAL_PURPOSE, 0x2000);
 #endif
 
        return 0;
 
  err_dev3:
-       unregister_sound_mixer(s->codec->dev_mixer);
+       unregister_sound_mixer(s->codec.dev_mixer);
  err_dev2:
        unregister_sound_dsp(s->dev_audio);
  err_dev1:
@@ -2167,9 +2152,7 @@ static int __devinit au1000_probe(void)
  err_dma2:
        free_au1000_dma(s->dma_dac.dmanr);
  err_dma1:
-       release_region(virt_to_phys((void *) AC97C_CONFIG), 0x14);
- err_codec:
-       ac97_release_codec(s->codec);
+       release_mem_region(CPHYSADDR(AC97C_CONFIG), 0x14);
        return -1;
 }
 
@@ -2186,10 +2169,9 @@ static void au1000_remove(void)
        synchronize_irq();
        free_au1000_dma(s->dma_adc.dmanr);
        free_au1000_dma(s->dma_dac.dmanr);
-       release_region(virt_to_phys((void *) AC97C_CONFIG), 0x14);
+       release_mem_region(CPHYSADDR(AC97C_CONFIG), 0x14);
        unregister_sound_dsp(s->dev_audio);
-       unregister_sound_mixer(s->codec->dev_mixer);
-       ac97_release_codec(s->codec);
+       unregister_sound_mixer(s->codec.dev_mixer);
 }
 
 static int __init init_au1000(void)
@@ -2218,7 +2200,7 @@ static int __init au1000_setup(char *options)
        if (!options || !*options)
                return 0;
 
-       while (this_opt = strsep(&options, ",")) {
+       while ((this_opt = strsep(&options, ","))) {
                if (!*this_opt)
                        continue;
                if (!strncmp(this_opt, "vra", 3)) {