vserver 1.9.5.x5
[linux-2.6.git] / sound / oss / i810_audio.c
index e4f8542..a4b959a 100644 (file)
 #include <linux/ac97_codec.h>
 #include <linux/bitops.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #define DRIVER_VERSION "1.01"
 
@@ -112,6 +111,7 @@ static int ftsodell;
 static int strict_clocking;
 static unsigned int clocking;
 static int spdif_locked;
+static int ac97_quirk = AC97_TUNE_DEFAULT;
 
 //#define DEBUG
 //#define DEBUG2
@@ -407,7 +407,6 @@ struct i810_card {
        u16 pci_id_internal; /* used to access card_cap[] */
 #ifdef CONFIG_PM       
        u16 pm_suspended;
-       u32 pm_save_state[64/sizeof(u32)];
        int pm_saved_mixer_settings[SOUND_MIXER_NRDEVICES][NR_AC97];
 #endif
        /* soundcore stuff */
@@ -431,8 +430,8 @@ struct i810_card {
 
        unsigned long ac97base_mmio_phys;
        unsigned long iobase_mmio_phys;
-       u_int8_t *ac97base_mmio;
-       u_int8_t *iobase_mmio;
+       u_int8_t __iomem *ac97base_mmio;
+       u_int8_t __iomem *iobase_mmio;
 
        int           use_mmio;
        
@@ -450,12 +449,156 @@ struct i810_card {
 /* extract register offset from codec struct */
 #define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
 
-#define GET_CIV(port) MODULOP2(inb((port) + OFF_CIV), SG_LEN)
-#define GET_LVI(port) MODULOP2(inb((port) + OFF_LVI), SG_LEN)
+#define I810_IOREAD(size, type, card, off)                             \
+({                                                                     \
+       type val;                                                       \
+       if (card->use_mmio)                                             \
+               val=read##size(card->iobase_mmio+off);                  \
+       else                                                            \
+               val=in##size(card->iobase+off);                         \
+       val;                                                            \
+})
+
+#define I810_IOREADL(card, off)                I810_IOREAD(l, u32, card, off)
+#define I810_IOREADW(card, off)                I810_IOREAD(w, u16, card, off)
+#define I810_IOREADB(card, off)                I810_IOREAD(b, u8,  card, off)
+
+#define I810_IOWRITE(size, val, card, off)                             \
+({                                                                     \
+       if (card->use_mmio)                                             \
+               write##size(val, card->iobase_mmio+off);                \
+       else                                                            \
+               out##size(val, card->iobase+off);                       \
+})
+
+#define I810_IOWRITEL(val, card, off)  I810_IOWRITE(l, val, card, off)
+#define I810_IOWRITEW(val, card, off)  I810_IOWRITE(w, val, card, off)
+#define I810_IOWRITEB(val, card, off)  I810_IOWRITE(b, val, card, off)
+
+#define GET_CIV(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_CIV), SG_LEN)
+#define GET_LVI(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_LVI), SG_LEN)
 
 /* set LVI from CIV */
-#define CIV_TO_LVI(port, off) \
-       outb(MODULOP2(GET_CIV((port)) + (off), SG_LEN), (port) + OFF_LVI)
+#define CIV_TO_LVI(card, port, off) \
+       I810_IOWRITEB(MODULOP2(GET_CIV((card), (port)) + (off), SG_LEN), (card), (port) + OFF_LVI)
+
+static struct ac97_quirk ac97_quirks[] __devinitdata = {
+       {
+               .vendor = 0x0e11,
+               .device = 0x00b8,
+               .name = "Compaq Evo D510C",
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x1028,
+               .device = 0x00d8,
+               .name = "Dell Precision 530",   /* AD1885 */
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x1028,
+               .device = 0x0126,
+               .name = "Dell Optiplex GX260",  /* AD1981A */
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x1028,
+               .device = 0x012d,
+               .name = "Dell Precision 450",   /* AD1981B*/
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {       /* FIXME: which codec? */
+               .vendor = 0x103c,
+               .device = 0x00c3,
+               .name = "Hewlett-Packard onboard",
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x103c,
+               .device = 0x12f1,
+               .name = "HP xw8200",    /* AD1981B*/
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x103c,
+               .device = 0x3008,
+               .name = "HP xw4200",    /* AD1981B*/
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x10f1,
+               .device = 0x2665,
+               .name = "Fujitsu-Siemens Celsius",      /* AD1981? */
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x10f1,
+               .device = 0x2885,
+               .name = "AMD64 Mobo",   /* ALC650 */
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x110a,
+               .device = 0x0056,
+               .name = "Fujitsu-Siemens Scenic",       /* AD1981? */
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x11d4,
+               .device = 0x5375,
+               .name = "ADI AD1985 (discrete)",
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x1462,
+               .device = 0x5470,
+               .name = "MSI P4 ATX 645 Ultra",
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x1734,
+               .device = 0x0088,
+               .name = "Fujitsu-Siemens D1522",        /* AD1981 */
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x8086,
+               .device = 0x4856,
+               .name = "Intel D845WN (82801BA)",
+               .type = AC97_TUNE_SWAP_HP
+       },
+       {
+               .vendor = 0x8086,
+               .device = 0x4d44,
+               .name = "Intel D850EMV2",       /* AD1885 */
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x8086,
+               .device = 0x4d56,
+               .name = "Intel ICH/AD1885",
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x1028,
+               .device = 0x012d,
+               .name = "Dell Precision 450",   /* AD1981B*/
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x103c,
+               .device = 0x3008,
+               .name = "HP xw4200",    /* AD1981B*/
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .vendor = 0x103c,
+               .device = 0x12f1,
+               .name = "HP xw8200",    /* AD1981B*/
+               .type = AC97_TUNE_HP_ONLY
+       },
+       { } /* terminator */
+};
 
 static struct i810_card *devs = NULL;
 
@@ -714,9 +857,9 @@ static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec)
                return 0;
 
        if (rec)
-               port = state->card->iobase + dmabuf->read_channel->port;
+               port = dmabuf->read_channel->port;
        else
-               port = state->card->iobase + dmabuf->write_channel->port;
+               port = dmabuf->write_channel->port;
 
        if(state->card->pci_id == PCI_DEVICE_ID_SI_7012) {
                port_picb = port + OFF_SR;
@@ -725,8 +868,8 @@ static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec)
                port_picb = port + OFF_PICB;
 
        do {
-               civ = GET_CIV(port);
-               offset = inw(port_picb);
+               civ = GET_CIV(state->card, port);
+               offset = I810_IOREADW(state->card, port_picb);
                /* Must have a delay here! */ 
                if(offset == 0)
                        udelay(1);
@@ -745,7 +888,7 @@ static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec)
                 * that we won't have to worry about the chip still being
                 * out of sync with reality ;-)
                 */
-       } while (civ != GET_CIV(port) || offset != inw(port_picb));
+       } while (civ != GET_CIV(state->card, port) || offset != I810_IOREADW(state->card, port_picb));
                 
        return (((civ + 1) * dmabuf->fragsize - (bytes * offset))
                % dmabuf->dmasize);
@@ -758,15 +901,15 @@ static inline void __stop_adc(struct i810_state *state)
        struct i810_card *card = state->card;
 
        dmabuf->enable &= ~ADC_RUNNING;
-       outb(0, card->iobase + PI_CR);
+       I810_IOWRITEB(0, card, PI_CR);
        // wait for the card to acknowledge shutdown
-       while( inb(card->iobase + PI_CR) != 0 ) ;
+       while( I810_IOREADB(card, PI_CR) != 0 ) ;
        // now clear any latent interrupt bits (like the halt bit)
        if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-               outb( inb(card->iobase + PI_PICB), card->iobase + PI_PICB );
+               I810_IOWRITEB( I810_IOREADB(card, PI_PICB), card, PI_PICB );
        else
-               outb( inb(card->iobase + PI_SR), card->iobase + PI_SR );
-       outl( inl(card->iobase + GLOB_STA) & INT_PI, card->iobase + GLOB_STA);
+               I810_IOWRITEB( I810_IOREADB(card, PI_SR), card, PI_SR );
+       I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PI, card, GLOB_STA);
 }
 
 static void stop_adc(struct i810_state *state)
@@ -787,7 +930,7 @@ static inline void __start_adc(struct i810_state *state)
            (dmabuf->trigger & PCM_ENABLE_INPUT)) {
                dmabuf->enable |= ADC_RUNNING;
                // Interrupt enable, LVI enable, DMA enable
-               outb(0x10 | 0x04 | 0x01, state->card->iobase + PI_CR);
+               I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PI_CR);
        }
 }
 
@@ -808,15 +951,15 @@ static inline void __stop_dac(struct i810_state *state)
        struct i810_card *card = state->card;
 
        dmabuf->enable &= ~DAC_RUNNING;
-       outb(0, card->iobase + PO_CR);
+       I810_IOWRITEB(0, card, PO_CR);
        // wait for the card to acknowledge shutdown
-       while( inb(card->iobase + PO_CR) != 0 ) ;
+       while( I810_IOREADB(card, PO_CR) != 0 ) ;
        // now clear any latent interrupt bits (like the halt bit)
        if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-               outb( inb(card->iobase + PO_PICB), card->iobase + PO_PICB );
+               I810_IOWRITEB( I810_IOREADB(card, PO_PICB), card, PO_PICB );
        else
-               outb( inb(card->iobase + PO_SR), card->iobase + PO_SR );
-       outl( inl(card->iobase + GLOB_STA) & INT_PO, card->iobase + GLOB_STA);
+               I810_IOWRITEB( I810_IOREADB(card, PO_SR), card, PO_SR );
+       I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PO, card, GLOB_STA);
 }
 
 static void stop_dac(struct i810_state *state)
@@ -837,7 +980,7 @@ static inline void __start_dac(struct i810_state *state)
            (dmabuf->trigger & PCM_ENABLE_OUTPUT)) {
                dmabuf->enable |= DAC_RUNNING;
                // Interrupt enable, LVI enable, DMA enable
-               outb(0x10 | 0x04 | 0x01, state->card->iobase + PO_CR);
+               I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PO_CR);
        }
 }
 static void start_dac(struct i810_state *state)
@@ -892,7 +1035,7 @@ static int alloc_dmabuf(struct i810_state *state)
        dmabuf->rawbuf = rawbuf;
        dmabuf->buforder = order;
        
-       /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
+       /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */
        pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
        for (page = virt_to_page(rawbuf); page <= pend; page++)
                SetPageReserved(page);
@@ -1000,12 +1143,12 @@ static int prog_dmabuf(struct i810_state *state, unsigned rec)
                        sg++;
                }
                spin_lock_irqsave(&state->card->lock, flags);
-               outb(2, state->card->iobase+c->port+OFF_CR);   /* reset DMA machine */
-               while( inb(state->card->iobase+c->port+OFF_CR) & 0x02 ) ;
-               outl((u32)state->card->chandma +
+               I810_IOWRITEB(2, state->card, c->port+OFF_CR);   /* reset DMA machine */
+               while( I810_IOREADB(state->card, c->port+OFF_CR) & 0x02 ) ;
+               I810_IOWRITEL((u32)state->card->chandma +
                    c->num*sizeof(struct i810_channel),
-                   state->card->iobase+c->port+OFF_BDBAR);
-               CIV_TO_LVI(state->card->iobase+c->port, 0);
+                   state->cardc->port+OFF_BDBAR);
+               CIV_TO_LVI(state->cardc->port, 0);
 
                spin_unlock_irqrestore(&state->card->lock, flags);
 
@@ -1037,14 +1180,13 @@ static void __i810_update_lvi(struct i810_state *state, int rec)
        void (*start)(struct i810_state *);
 
        count = dmabuf->count;
-       port = state->card->iobase;
        if (rec) {
-               port += dmabuf->read_channel->port;
+               port = dmabuf->read_channel->port;
                trigger = PCM_ENABLE_INPUT;
                start = __start_adc;
                count = dmabuf->dmasize - count;
        } else {
-               port += dmabuf->write_channel->port;
+               port = dmabuf->write_channel->port;
                trigger = PCM_ENABLE_OUTPUT;
                start = __start_dac;
        }
@@ -1054,19 +1196,32 @@ static void __i810_update_lvi(struct i810_state *state, int rec)
        if (count < fragsize)
                return;
 
+       /* if we are currently stopped, then our CIV is actually set to our
+        * *last* sg segment and we are ready to wrap to the next.  However,
+        * if we set our LVI to the last sg segment, then it won't wrap to
+        * the next sg segment, it won't even get a start.  So, instead, when
+        * we are stopped, we set both the LVI value and also we increment
+        * the CIV value to the next sg segment to be played so that when
+        * we call start, things will operate properly.  Since the CIV can't
+        * be written to directly for this purpose, we set the LVI to CIV + 1
+        * temporarily.  Once the engine has started we set the LVI to its
+        * final value.
+        */
        if (!dmabuf->enable && dmabuf->ready) {
                if (!(dmabuf->trigger & trigger))
                        return;
 
+               CIV_TO_LVI(state->card, port, 1);
+
                start(state);
-               while (!(inb(port + OFF_CR) & ((1<<4) | (1<<2))))
+               while (!(I810_IOREADB(state->card, port + OFF_CR) & ((1<<4) | (1<<2))))
                        ;
        }
 
        /* MASKP2(swptr, fragsize) - 1 is the tail of our transfer */
        x = MODULOP2(MASKP2(dmabuf->swptr, fragsize) - 1, dmabuf->dmasize);
        x >>= dmabuf->fragshift;
-       outb(x, port + OFF_LVI);
+       I810_IOWRITEB(x, state->card, port + OFF_LVI);
 }
 
 static void i810_update_lvi(struct i810_state *state, int rec)
@@ -1108,8 +1263,8 @@ static void i810_update_ptr(struct i810_state *state)
                        /* this is normal for the end of a read */
                        /* only give an error if we went past the */
                        /* last valid sg entry */
-                       if (GET_CIV(state->card->iobase + PI_BASE) !=
-                           GET_LVI(state->card->iobase + PI_BASE)) {
+                       if (GET_CIV(state->card, PI_BASE) !=
+                           GET_LVI(state->card, PI_BASE)) {
                                printk(KERN_WARNING "i810_audio: DMA overrun on read\n");
                                dmabuf->error++;
                        }
@@ -1133,13 +1288,13 @@ static void i810_update_ptr(struct i810_state *state)
                        /* this is normal for the end of a write */
                        /* only give an error if we went past the */
                        /* last valid sg entry */
-                       if (GET_CIV(state->card->iobase + PO_BASE) !=
-                           GET_LVI(state->card->iobase + PO_BASE)) {
+                       if (GET_CIV(state->card, PO_BASE) !=
+                           GET_LVI(state->card, PO_BASE)) {
                                printk(KERN_WARNING "i810_audio: DMA overrun on write\n");
                                printk("i810_audio: CIV %d, LVI %d, hwptr %x, "
                                        "count %d\n",
-                                       GET_CIV(state->card->iobase + PO_BASE),
-                                       GET_LVI(state->card->iobase + PO_BASE),
+                                       GET_CIV(state->card, PO_BASE),
+                                       GET_LVI(state->card, PO_BASE),
                                        dmabuf->hwptr, dmabuf->count);
                                dmabuf->error++;
                        }
@@ -1287,7 +1442,7 @@ static void i810_channel_interrupt(struct i810_card *card)
                struct i810_state *state = card->states[i];
                struct i810_channel *c;
                struct dmabuf *dmabuf;
-               unsigned long port = card->iobase;
+               unsigned long port;
                u16 status;
                
                if(!state)
@@ -1302,12 +1457,12 @@ static void i810_channel_interrupt(struct i810_card *card)
                } else  /* This can occur going from R/W to close */
                        continue;
                
-               port+=c->port;
+               port = c->port;
 
                if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-                       status = inw(port + OFF_PICB);
+                       status = I810_IOREADW(card, port + OFF_PICB);
                else
-                       status = inw(port + OFF_SR);
+                       status = I810_IOREADW(card, port + OFF_SR);
 
 #ifdef DEBUG_INTERRUPTS
                printk("NUM %d PORT %X IRQ ( ST%d ", c->num, c->port, status);
@@ -1340,7 +1495,7 @@ static void i810_channel_interrupt(struct i810_card *card)
                        if(dmabuf->enable & ADC_RUNNING)
                                count = dmabuf->dmasize - count;
                        if (count >= (int)dmabuf->fragsize) {
-                               outb(inb(port+OFF_CR) | 1, port+OFF_CR);
+                               I810_IOWRITEB(I810_IOREADB(card, port+OFF_CR) | 1, card, port+OFF_CR);
 #ifdef DEBUG_INTERRUPTS
                                printk(" CONTINUE ");
 #endif
@@ -1356,9 +1511,9 @@ static void i810_channel_interrupt(struct i810_card *card)
                        }
                }
                if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-                       outw(status & DMA_INT_MASK, port + OFF_PICB);
+                       I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_PICB);
                else
-                       outw(status & DMA_INT_MASK, port + OFF_SR);
+                       I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_SR);
        }
 #ifdef DEBUG_INTERRUPTS
        printk(")\n");
@@ -1372,7 +1527,7 @@ static irqreturn_t i810_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        spin_lock(&card->lock);
 
-       status = inl(card->iobase + GLOB_STA);
+       status = I810_IOREADL(card, GLOB_STA);
 
        if(!(status & INT_MASK)) 
        {
@@ -1384,7 +1539,7 @@ static irqreturn_t i810_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                i810_channel_interrupt(card);
 
        /* clear 'em */
-       outl(status & INT_MASK, card->iobase + GLOB_STA);
+       I810_IOWRITEL(status & INT_MASK, card, GLOB_STA);
        spin_unlock(&card->lock);
        return IRQ_HANDLED;
 }
@@ -1396,7 +1551,7 @@ static irqreturn_t i810_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static ssize_t i810_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
        struct i810_state *state = (struct i810_state *)file->private_data;
-       struct i810_card *card=state ? state->card : 0;
+       struct i810_card *card=state ? state->card : NULL;
        struct dmabuf *dmabuf = &state->dmabuf;
        ssize_t ret;
        unsigned long flags;
@@ -1409,8 +1564,6 @@ static ssize_t i810_read(struct file *file, char __user *buffer, size_t count, l
        printk("i810_audio: i810_read called, count = %d\n", count);
 #endif
 
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
        if (dmabuf->mapped)
                return -ENXIO;
        if (dmabuf->enable & DAC_RUNNING)
@@ -1536,7 +1689,7 @@ static ssize_t i810_read(struct file *file, char __user *buffer, size_t count, l
 static ssize_t i810_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
        struct i810_state *state = (struct i810_state *)file->private_data;
-       struct i810_card *card=state ? state->card : 0;
+       struct i810_card *card=state ? state->card : NULL;
        struct dmabuf *dmabuf = &state->dmabuf;
        ssize_t ret;
        unsigned long flags;
@@ -1549,8 +1702,6 @@ static ssize_t i810_write(struct file *file, const char __user *buffer, size_t c
        printk("i810_audio: i810_write called, count = %d\n", count);
 #endif
 
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
        if (dmabuf->mapped)
                return -ENXIO;
        if (dmabuf->enable & ADC_RUNNING)
@@ -1730,7 +1881,8 @@ static int i810_mmap(struct file *file, struct vm_area_struct *vma)
        if (size > (PAGE_SIZE << dmabuf->buforder))
                goto out;
        ret = -EAGAIN;
-       if (remap_page_range(vma, vma->vm_start, virt_to_phys(dmabuf->rawbuf),
+       if (remap_pfn_range(vma, vma->vm_start,
+                            virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
                             size, vma->vm_page_prot))
                goto out;
        dmabuf->mapped = 1;
@@ -1784,13 +1936,13 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        __stop_adc(state);
                }
                if (c != NULL) {
-                       outb(2, state->card->iobase+c->port+OFF_CR);   /* reset DMA machine */
-                       while ( inb(state->card->iobase+c->port+OFF_CR) & 2 )
+                       I810_IOWRITEB(2, state->card, c->port+OFF_CR);   /* reset DMA machine */
+                       while ( I810_IOREADB(state->card, c->port+OFF_CR) & 2 )
                                cpu_relax();
-                       outl((u32)state->card->chandma +
+                       I810_IOWRITEL((u32)state->card->chandma +
                            c->num*sizeof(struct i810_channel),
-                           state->card->iobase+c->port+OFF_BDBAR);
-                       CIV_TO_LVI(state->card->iobase+c->port, 0);
+                           state->cardc->port+OFF_BDBAR);
+                       CIV_TO_LVI(state->cardc->port, 0);
                }
 
                spin_unlock_irqrestore(&state->card->lock, flags);
@@ -1920,7 +2072,7 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                /* Global Status and Global Control register are now  */
                /* used to indicate this.                             */
 
-                i_glob_cnt = inl(state->card->iobase + GLOB_CNT);
+                i_glob_cnt = I810_IOREADL(state->card, GLOB_CNT);
 
                /* Current # of channels enabled */
                if ( i_glob_cnt & 0x0100000 )
@@ -1932,14 +2084,14 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                switch ( val ) {
                        case 2: /* 2 channels is always supported */
-                               outl(i_glob_cnt & 0xffcfffff,
-                                    state->card->iobase + GLOB_CNT);
+                               I810_IOWRITEL(i_glob_cnt & 0xffcfffff,
+                                    state->card, GLOB_CNT);
                                /* Do we need to change mixer settings????  */
                                break;
                        case 4: /* Supported on some chipsets, better check first */
                                if ( state->card->channels >= 4 ) {
-                                       outl((i_glob_cnt & 0xffcfffff) | 0x100000,
-                                             state->card->iobase + GLOB_CNT);
+                                       I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x100000,
+                                             state->card, GLOB_CNT);
                                        /* Do we need to change mixer settings??? */
                                } else {
                                        val = ret;
@@ -1947,8 +2099,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                                break;
                        case 6: /* Supported on some chipsets, better check first */
                                if ( state->card->channels >= 6 ) {
-                                       outl((i_glob_cnt & 0xffcfffff) | 0x200000,
-                                             state->card->iobase + GLOB_CNT);
+                                       I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x200000,
+                                             state->card, GLOB_CNT);
                                        /* Do we need to change mixer settings??? */
                                } else {
                                        val = ret;
@@ -2477,8 +2629,8 @@ found_virt:
                } else {
                        i810_set_dac_rate(state, 8000);
                        /* Put the ACLink in 2 channel mode by default */
-                       i = inl(card->iobase + GLOB_CNT);
-                       outl(i & 0xffcfffff, card->iobase + GLOB_CNT);
+                       i = I810_IOREADL(card, GLOB_CNT);
+                       I810_IOWRITEL(i & 0xffcfffff, card, GLOB_CNT);
                }
        }
                
@@ -2493,7 +2645,7 @@ found_virt:
 
        state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
 
-       return 0;
+       return nonseekable_open(inode, file);
 }
 
 static int i810_release(struct inode *inode, struct file *file)
@@ -2569,7 +2721,7 @@ static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg)
        int count = 100;
        u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
        
-       while(count-- && (inb(card->iobase + CAS) & 1)) 
+       while(count-- && (I810_IOREADB(card, CAS) & 1)) 
                udelay(1);
        
        return inw(card->ac97base + reg_set);
@@ -2597,7 +2749,7 @@ static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data)
        int count = 100;
        u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
        
-       while(count-- && (inb(card->iobase + CAS) & 1)) 
+       while(count-- && (I810_IOREADB(card, CAS) & 1)) 
                udelay(1);
        
         outw(data, card->ac97base + reg_set);
@@ -2660,7 +2812,7 @@ static int i810_open_mixdev(struct inode *inode, struct file *file)
                        if (card->ac97_codec[i] != NULL &&
                            card->ac97_codec[i]->dev_mixer == minor) {
                                file->private_data = card->ac97_codec[i];
-                               return 0;
+                               return nonseekable_open(inode, file);
                        }
        }
        return -ENODEV;
@@ -2686,7 +2838,7 @@ static /*const*/ struct file_operations i810_mixer_fops = {
 
 static inline int i810_ac97_exists(struct i810_card *card, int ac97_number)
 {
-       u32 reg = inl(card->iobase + GLOB_STA);
+       u32 reg = I810_IOREADL(card, GLOB_STA);
        switch (ac97_number) {
        case 0:
                return reg & (1<<8);
@@ -2757,7 +2909,7 @@ static inline int ich_use_mmio(struct i810_card *card)
  
 static int i810_ac97_power_up_bus(struct i810_card *card)
 {      
-       u32 reg = inl(card->iobase + GLOB_CNT);
+       u32 reg = I810_IOREADL(card, GLOB_CNT);
        int i;
        int primary_codec_id = 0;
 
@@ -2769,14 +2921,14 @@ static int i810_ac97_power_up_bus(struct i810_card *card)
        reg&=~8;        /* ACLink on */
        
        /* At this point we deassert AC_RESET # */
-       outl(reg , card->iobase + GLOB_CNT);
+       I810_IOWRITEL(reg , card, GLOB_CNT);
 
        /* We must now allow time for the Codec initialisation.
           600mS is the specified time */
                
        for(i=0;i<10;i++)
        {
-               if((inl(card->iobase+GLOB_CNT)&4)==0)
+               if((I810_IOREADL(card, GLOB_CNT)&4)==0)
                        break;
 
                set_current_state(TASK_UNINTERRUPTIBLE);
@@ -2795,8 +2947,11 @@ static int i810_ac97_power_up_bus(struct i810_card *card)
         *      See if the primary codec comes ready. This must happen
         *      before we start doing DMA stuff
         */     
-       /* see i810_ac97_init for the next 7 lines (jsaw) */
-       inw(card->ac97base);
+       /* see i810_ac97_init for the next 10 lines (jsaw) */
+       if (card->use_mmio)
+               readw(card->ac97base_mmio);
+       else
+               inw(card->ac97base);
        if (ich_use_mmio(card)) {
                primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
                printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
@@ -2814,7 +2969,10 @@ static int i810_ac97_power_up_bus(struct i810_card *card)
                else 
                        printk("no response.\n");
        }
-       inw(card->ac97base);
+       if (card->use_mmio)
+               readw(card->ac97base_mmio);
+       else
+               inw(card->ac97base);
        return 1;
 }
 
@@ -2839,15 +2997,15 @@ static int __devinit i810_ac97_init(struct i810_card *card)
        /* to check....                                         */
 
        card->channels = 2;
-       reg = inl(card->iobase + GLOB_STA);
+       reg = I810_IOREADL(card, GLOB_STA);
        if ( reg & 0x0200000 )
                card->channels = 6;
        else if ( reg & 0x0100000 )
                card->channels = 4;
        printk(KERN_INFO "i810_audio: Audio Controller supports %d channels.\n", card->channels);
        printk(KERN_INFO "i810_audio: Defaulting to base 2 channel mode.\n");
-       reg = inl(card->iobase + GLOB_CNT);
-       outl(reg & 0xffcfffff, card->iobase + GLOB_CNT);
+       reg = I810_IOREADL(card, GLOB_CNT);
+       I810_IOWRITEL(reg & 0xffcfffff, card, GLOB_CNT);
                
        for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) 
                card->ac97_codec[num_ac97] = NULL;
@@ -2858,8 +3016,10 @@ static int __devinit i810_ac97_init(struct i810_card *card)
        for (num_ac97 = 0; num_ac97 < nr_ac97_max; num_ac97++) {
                /* codec reset */
                printk(KERN_INFO "i810_audio: Resetting connection %d\n", num_ac97);
-               if (card->use_mmio) readw(card->ac97base_mmio + 0x80*num_ac97);
-               else inw(card->ac97base + 0x80*num_ac97);
+               if (card->use_mmio)
+                       readw(card->ac97base_mmio + 0x80*num_ac97);
+               else
+                       inw(card->ac97base + 0x80*num_ac97);
 
                /* If we have the SDATA_IN Map Register, as on ICH4, we
                   do not loop thru all possible codec IDs but thru all 
@@ -3015,6 +3175,9 @@ static int __devinit i810_ac97_init(struct i810_card *card)
                card->ac97_codec[num_ac97] = codec;
        }
 
+       /* tune up the primary codec */
+       ac97_tune_hardware(card->pci_dev, ac97_quirks, ac97_quirk);
+
        /* pick the minimum of channels supported by ICHx or codec(s) */
        card->channels = (card->channels > total_channels)?total_channels:card->channels;
 
@@ -3062,7 +3225,7 @@ static void __devinit i810_configure_clocking (void)
                        goto config_out;
                }
                dmabuf->count = dmabuf->dmasize;
-               CIV_TO_LVI(card->iobase+dmabuf->write_channel->port, -1);
+               CIV_TO_LVI(carddmabuf->write_channel->port, -1);
                local_irq_save(flags);
                start_dac(state);
                offset = i810_get_dma_addr(state, 0);
@@ -3106,13 +3269,6 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device
                return -ENODEV;
        }
        
-       if( pci_resource_start(pci_dev, 1) == 0)
-       {
-               /* MMIO only ICH5 .. here be dragons .. */
-               printk(KERN_ERR "i810_audio: Pure MMIO interfaces not yet supported.\n");
-               return -ENODEV;
-       }
-
        if ((card = kmalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) {
                printk(KERN_ERR "i810_audio: out of memory\n");
                return -ENOMEM;
@@ -3125,6 +3281,11 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device
        card->ac97base = pci_resource_start (pci_dev, 0);
        card->iobase = pci_resource_start (pci_dev, 1);
 
+       if (!(card->ac97base) || !(card->iobase)) {
+               card->ac97base = 0;
+               card->iobase = 0;
+       }
+
        /* if chipset could have mmio capability, check it */ 
        if (card_cap[pci_id->driver_data].flags & CAP_MMIO) {
                card->ac97base_mmio_phys = pci_resource_start (pci_dev, 2);
@@ -3139,6 +3300,11 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device
                }
        }
 
+       if (!(card->use_mmio) && (!(card->iobase) || !(card->ac97base))) {
+               printk(KERN_ERR "i810_audio: No I/O resources available.\n");
+               goto out_mem;
+       }
+
        card->irq = pci_dev->irq;
        card->next = devs;
        card->magic = I810_CARD_MAGIC;
@@ -3184,8 +3350,14 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device
        }
 
        /* claim our iospace and irq */
-       request_region(card->iobase, 64, card_names[pci_id->driver_data]);
-       request_region(card->ac97base, 256, card_names[pci_id->driver_data]);
+       if (!request_region(card->iobase, 64, card_names[pci_id->driver_data])) {
+               printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->iobase);
+               goto out_region1;
+       }
+       if (!request_region(card->ac97base, 256, card_names[pci_id->driver_data])) {
+               printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->ac97base);
+               goto out_region2;
+       }
 
        if (request_irq(card->irq, &i810_interrupt, SA_SHIRQ,
                        card_names[pci_id->driver_data], card)) {
@@ -3259,7 +3431,9 @@ out_iospace:
        }
 out_pio:       
        release_region(card->iobase, 64);
+out_region2:
        release_region(card->ac97base, 256);
+out_region1:
        pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH,
            card->channel, card->chandma);
 out_mem:
@@ -3346,7 +3520,7 @@ static int i810_pm_suspend(struct pci_dev *dev, u32 pm_state)
                        }
                }
        }
-       pci_save_state(dev,card->pm_save_state); /* XXX do we need this? */
+       pci_save_state(dev); /* XXX do we need this? */
        pci_disable_device(dev); /* disable busmastering */
        pci_set_power_state(dev,3); /* Zzz. */
 
@@ -3359,7 +3533,7 @@ static int i810_pm_resume(struct pci_dev *dev)
        int num_ac97,i=0;
        struct i810_card *card=pci_get_drvdata(dev);
        pci_enable_device(dev);
-       pci_restore_state (dev,card->pm_save_state);
+       pci_restore_state (dev);
 
        /* observation of a toshiba portege 3440ct suggests that the 
           hardware has to be more or less completely reinitialized from
@@ -3421,15 +3595,15 @@ static int i810_pm_resume(struct pci_dev *dev)
 }      
 #endif /* CONFIG_PM */
 
-MODULE_AUTHOR("");
+MODULE_AUTHOR("The Linux kernel team");
 MODULE_DESCRIPTION("Intel 810 audio support");
 MODULE_LICENSE("GPL");
-MODULE_PARM(ftsodell, "i");
-MODULE_PARM(clocking, "i");
-MODULE_PARM(strict_clocking, "i");
-MODULE_PARM(spdif_locked, "i");
+module_param(ftsodell, int, 0444);
+module_param(clocking, uint, 0444);
+module_param(strict_clocking, int, 0444);
+module_param(spdif_locked, int, 0444);
 
-#define I810_MODULE_NAME "intel810_audio"
+#define I810_MODULE_NAME "i810_audio"
 
 static struct pci_driver i810_pci_driver = {
        .name           = I810_MODULE_NAME,
@@ -3445,13 +3619,15 @@ static struct pci_driver i810_pci_driver = {
 
 static int __init i810_init_module (void)
 {
+       int retval;
+
        printk(KERN_INFO "Intel 810 + AC97 Audio, version "
               DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
 
-       if (!pci_register_driver(&i810_pci_driver)) {
-               pci_unregister_driver(&i810_pci_driver);
-                return -ENODEV;
-       }
+       retval = pci_register_driver(&i810_pci_driver);
+       if (retval)
+               return retval;
+
        if(ftsodell != 0) {
                printk("i810_audio: ftsodell is now a deprecated option.\n");
        }