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 / pci / au88x0 / au88x0_core.c
index 684f639..4347e6a 100644 (file)
@@ -21,7 +21,7 @@
  These functions are mainly the result of translations made
  from the original disassembly of the au88x0 binary drivers,
  written by Aureal before they went down.
- Many thanks to the Jeff Muizelar, Kester Maddock, and whoever
+ Many thanks to the Jeff Muizelaar, Kester Maddock, and whoever
  contributed to the OpenVortex project.
  The author of this file, put the few available pieces together
  and translated the rest of the riddle (Mix, Src and connection stuff).
@@ -376,7 +376,7 @@ vortex_mixer_delWTD(vortex_t * vortex, unsigned char mix, unsigned char ch)
 
 static void vortex_mixer_init(vortex_t * vortex)
 {
-       unsigned long addr;
+       u32 addr;
        int x;
 
        // FIXME: get rid of this crap.
@@ -639,7 +639,7 @@ static void vortex_src_setupchannel(vortex_t * card, unsigned char src,
 
 static void vortex_srcblock_init(vortex_t * vortex)
 {
-       unsigned long addr;
+       u32 addr;
        int x;
        hwwrite(vortex->mmio, VORTEX_SRC_SOURCESIZE, 0x1ff);
        /*
@@ -1035,7 +1035,7 @@ vortex_fifo_setwtctrl(vortex_t * vortex, int fifo, int ctrl, int priority,
 static void vortex_fifo_init(vortex_t * vortex)
 {
        int x;
-       unsigned long addr;
+       u32 addr;
 
        /* ADB DMA channels fifos. */
        addr = VORTEX_FIFO_ADBCTRL + ((NR_ADB - 1) * 4);
@@ -1054,7 +1054,7 @@ static void vortex_fifo_init(vortex_t * vortex)
                hwwrite(vortex->mmio, addr, FIFO_U0);
                if (hwread(vortex->mmio, addr) != FIFO_U0)
                        printk(KERN_ERR
-                              "bad wt fifo reset (0x%08lx, 0x%08x)!\n",
+                              "bad wt fifo reset (0x%08x, 0x%08x)!\n",
                               addr, hwread(vortex->mmio, addr));
                vortex_fifo_clearwtdata(vortex, x, FIFO_SIZE);
                addr -= 4;
@@ -1097,7 +1097,7 @@ static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb)
 
 static void
 vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma,
-                        snd_pcm_sgbuf_t * sgbuf, int psize, int count)
+                        struct snd_sg_buf * sgbuf, int psize, int count)
 {
        stream_t *dma = &vortex->dma_adb[adbdma];
 
@@ -1152,7 +1152,7 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma,
 
 static void
 vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie, int dir,
-                     int fmt, int d, unsigned long offset)
+                     int fmt, int d, u32 offset)
 {
        stream_t *dma = &vortex->dma_adb[adbdma];
 
@@ -1223,6 +1223,33 @@ static int vortex_adbdma_bufshift(vortex_t * vortex, int adbdma)
        return delta;
 }
 
+
+static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma) {
+       stream_t *dma = &vortex->dma_adb[adbdma];
+       int p, pp, i;
+
+       /* refresh hw page table */
+       for (i=0 ; i < 4 && i < dma->nr_periods; i++) {
+               /* p: audio buffer page index */
+               p = dma->period_virt + i;
+               if (p >= dma->nr_periods)
+                       p -= dma->nr_periods;
+               /* pp: hardware DMA page index. */
+               pp = dma->period_real + i;
+               if (dma->nr_periods < 4) {
+                       if (pp >= dma->nr_periods)
+                               pp -= dma->nr_periods;
+               }
+               else {
+                       if (pp >= 4)
+                               pp -= 4;
+               }
+               hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE+(((adbdma << 2)+pp) << 2), snd_sgbuf_get_addr(dma->sgbuf, dma->period_bytes * p));
+               /* Force write thru cache. */
+               hwread(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (((adbdma << 2)+pp) << 2));
+       }
+}
+
 static int inline vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma)
 {
        stream_t *dma = &vortex->dma_adb[adbdma];
@@ -1340,7 +1367,7 @@ static void vortex_wtdma_setstartbuffer(vortex_t * vortex, int wtdma, int sb)
 
 static void
 vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma,
-                       snd_pcm_sgbuf_t * sgbuf, int psize, int count)
+                       struct snd_sg_buf * sgbuf, int psize, int count)
 {
        stream_t *dma = &vortex->dma_wt[wtdma];
 
@@ -1384,7 +1411,7 @@ vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma,
 
 static void
 vortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d,
-                    /*int e, */ unsigned long offset)
+                    /*int e, */ u32 offset)
 {
        stream_t *dma = &vortex->dma_wt[wtdma];
 
@@ -2006,7 +2033,7 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype)
                        }
                }
        }
-       printk("vortex: FATAL: ResManager: resource type %d exhausted.\n", restype);
+       printk(KERN_ERR "vortex: FATAL: ResManager: resource type %d exhausted.\n", restype);
        return -ENOMEM;
 }
 
@@ -2081,7 +2108,6 @@ vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type)
            || ((dir == SNDRV_PCM_STREAM_CAPTURE) && (nr_ch > 2)))
                return -EBUSY;
 
-       spin_lock(&vortex->lock);
        if (dma >= 0) {
                en = 0;
                vortex_adb_checkinout(vortex,
@@ -2139,7 +2165,7 @@ vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type)
                                memset(stream->resources, 0,
                                       sizeof(unsigned char) *
                                       VORTEX_RESOURCE_LAST);
-                               printk("vortex: out of A3D sources. Sorry\n");
+                               printk(KERN_ERR "vortex: out of A3D sources. Sorry\n");
                                return -EBUSY;
                        }
                        /* (De)Initialize A3D hardware source. */
@@ -2277,7 +2303,6 @@ vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type)
                }
        }
        vortex->dma_adb[dma].nr_ch = nr_ch;
-       spin_unlock(&vortex->lock);
 
 #if 0
        /* AC97 Codec channel setup. FIXME: this has no effect on some cards !! */
@@ -2406,22 +2431,28 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        }
        if (source & IRQ_PCMOUT) {
                /* ALSA period acknowledge. */
+               spin_lock(&vortex->lock);
                for (i = 0; i < NR_ADB; i++) {
                        if (vortex->dma_adb[i].fifo_status == FIFO_START) {
                                if (vortex_adbdma_bufshift(vortex, i)) ;
+                               spin_unlock(&vortex->lock);
                                snd_pcm_period_elapsed(vortex->dma_adb[i].
                                                       substream);
+                               spin_lock(&vortex->lock);
                        }
                }
 #ifndef CHIP_AU8810
                for (i = 0; i < NR_WT; i++) {
                        if (vortex->dma_wt[i].fifo_status == FIFO_START) {
                                if (vortex_wtdma_bufshift(vortex, i)) ;
+                               spin_unlock(&vortex->lock);
                                snd_pcm_period_elapsed(vortex->dma_wt[i].
                                                       substream);
+                               spin_lock(&vortex->lock);
                        }
                }
 #endif
+               spin_unlock(&vortex->lock);
                handled = 1;
        }
        //Acknowledge the Timer interrupt
@@ -2449,53 +2480,51 @@ static void vortex_codec_init(vortex_t * vortex)
        int i;
 
        for (i = 0; i < 32; i++) {
-               hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), 0);
-               udelay(2000);
+               /* the windows driver writes -i, so we write -i */
+               hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i);
+               msleep(2);
        }
        if (0) {
                hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x8068);
-               udelay(1000);
+               msleep(1);
                hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8);
-               udelay(1000);
+               msleep(1);
        } else {
                hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00a8);
-               udelay(2000);
+               msleep(2);
                hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80a8);
-               udelay(2000);
+               msleep(2);
                hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80e8);
-               udelay(2000);
+               msleep(2);
                hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80a8);
-               udelay(2000);
+               msleep(2);
                hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00a8);
-               udelay(2000);
+               msleep(2);
                hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8);
        }
        for (i = 0; i < 32; i++) {
-               hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), 0);
-               udelay(5000);
+               hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i);
+               msleep(5);
        }
        hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0xe8);
-       udelay(1000);
+       msleep(1);
        /* Enable codec channels 0 and 1. */
        hwwrite(vortex->mmio, VORTEX_CODEC_EN,
                hwread(vortex->mmio, VORTEX_CODEC_EN) | EN_CODEC);
 }
 
 static void
-vortex_codec_write(ac97_t * codec, unsigned short addr, unsigned short data)
+vortex_codec_write(struct snd_ac97 * codec, unsigned short addr, unsigned short data)
 {
 
        vortex_t *card = (vortex_t *) codec->private_data;
-       unsigned long flags;
        unsigned int lifeboat = 0;
-       spin_lock_irqsave(&card->lock, flags);
 
        /* wait for transactions to clear */
        while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) {
                udelay(100);
                if (lifeboat++ > POLL_COUNT) {
                        printk(KERN_ERR "vortex: ac97 codec stuck busy\n");
-                       spin_unlock_irqrestore(&card->lock, flags);
                        return;
                }
        }
@@ -2503,52 +2532,43 @@ vortex_codec_write(ac97_t * codec, unsigned short addr, unsigned short data)
        hwwrite(card->mmio, VORTEX_CODEC_IO,
                ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK) |
                ((data << VORTEX_CODEC_DATSHIFT) & VORTEX_CODEC_DATMASK) |
-               VORTEX_CODEC_WRITE);
+               VORTEX_CODEC_WRITE |
+               (codec->num << VORTEX_CODEC_ID_SHIFT) );
 
        /* Flush Caches. */
        hwread(card->mmio, VORTEX_CODEC_IO);
-
-       spin_unlock_irqrestore(&card->lock, flags);
 }
 
-static unsigned short vortex_codec_read(ac97_t * codec, unsigned short addr)
+static unsigned short vortex_codec_read(struct snd_ac97 * codec, unsigned short addr)
 {
 
        vortex_t *card = (vortex_t *) codec->private_data;
        u32 read_addr, data;
-       unsigned long flags;
        unsigned lifeboat = 0;
 
-       spin_lock_irqsave(&card->lock, flags);
-
        /* wait for transactions to clear */
        while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) {
                udelay(100);
                if (lifeboat++ > POLL_COUNT) {
                        printk(KERN_ERR "vortex: ac97 codec stuck busy\n");
-                       spin_unlock_irqrestore(&card->lock, flags);
                        return 0xffff;
                }
        }
        /* set up read address */
-       read_addr = ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK);
+       read_addr = ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK) |
+               (codec->num << VORTEX_CODEC_ID_SHIFT) ;
        hwwrite(card->mmio, VORTEX_CODEC_IO, read_addr);
 
        /* wait for address */
-       {
+       do {
                udelay(100);
                data = hwread(card->mmio, VORTEX_CODEC_IO);
                if (lifeboat++ > POLL_COUNT) {
                        printk(KERN_ERR "vortex: ac97 address never arrived\n");
-                       spin_unlock_irqrestore(&card->lock, flags);
                        return 0xffff;
                }
-       }
-       while ((data & VORTEX_CODEC_ADDMASK) !=
-              (addr << VORTEX_CODEC_ADDSHIFT)) ;
-
-       /* Unlock. */
-       spin_unlock_irqrestore(&card->lock, flags);
+       } while ((data & VORTEX_CODEC_ADDMASK) !=
+                (addr << VORTEX_CODEC_ADDSHIFT));
 
        /* return data. */
        return (u16) (data & VORTEX_CODEC_DATMASK);
@@ -2638,16 +2658,16 @@ static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode)
 
 /* Initialization */
 
-static int vortex_core_init(vortex_t * vortex)
+static int __devinit vortex_core_init(vortex_t * vortex)
 {
 
        printk(KERN_INFO "Vortex: init.... ");
        /* Hardware Init. */
        hwwrite(vortex->mmio, VORTEX_CTRL, 0xffffffff);
-       udelay(5000);
+       msleep(5);
        hwwrite(vortex->mmio, VORTEX_CTRL,
                hwread(vortex->mmio, VORTEX_CTRL) & 0xffdfffff);
-       udelay(5000);
+       msleep(5);
        /* Reset IRQ flags */
        hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffffffff);
        hwread(vortex->mmio, VORTEX_IRQ_STAT);
@@ -2714,7 +2734,7 @@ static int vortex_core_shutdown(vortex_t * vortex)
 
        hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, 0);
        hwwrite(vortex->mmio, VORTEX_CTRL, 0);
-       udelay(5000);
+       msleep(5);
        hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffff);
 
        printk(KERN_INFO "done.\n");