ALSA: ASoC: OMAP: Add multilink support to McBSP DAI driver
[pandora-kernel.git] / sound / arm / aaci.c
index a032aee..b0a4744 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/irq.h>
 #include <asm/sizes.h>
 
-#include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/ac97_codec.h>
@@ -65,10 +64,12 @@ static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97)
  *  SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
  *  register.
  */
-static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
+static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+                           unsigned short val)
 {
        struct aaci *aaci = ac97->private_data;
        u32 v;
+       int timeout = 5000;
 
        if (ac97->num >= 4)
                return;
@@ -89,7 +90,11 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned
         */
        do {
                v = readl(aaci->base + AACI_SLFR);
-       } while (v & (SLFR_1TXB|SLFR_2TXB));
+       } while ((v & (SLFR_1TXB|SLFR_2TXB)) && timeout--);
+
+       if (!timeout)
+               dev_err(&aaci->dev->dev,
+                       "timeout waiting for write to complete\n");
 
        mutex_unlock(&aaci->ac97_sem);
 }
@@ -101,6 +106,8 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
        struct aaci *aaci = ac97->private_data;
        u32 v;
+       int timeout = 5000;
+       int retries = 10;
 
        if (ac97->num >= 4)
                return ~0;
@@ -119,7 +126,13 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
         */
        do {
                v = readl(aaci->base + AACI_SLFR);
-       } while (v & SLFR_1TXB);
+       } while ((v & SLFR_1TXB) && timeout--);
+
+       if (!timeout) {
+               dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n");
+               v = ~0;
+               goto out;
+       }
 
        /*
         * Give the AC'97 codec more than enough time
@@ -130,21 +143,35 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
        /*
         * Wait for slot 2 to indicate data.
         */
+       timeout = 5000;
        do {
                cond_resched();
                v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
-       } while (v != (SLFR_1RXV|SLFR_2RXV));
+       } while ((v != (SLFR_1RXV|SLFR_2RXV)) && timeout--);
 
-       v = readl(aaci->base + AACI_SL1RX) >> 12;
-       if (v == reg) {
-               v = readl(aaci->base + AACI_SL2RX) >> 4;
-       } else {
-               dev_err(&aaci->dev->dev,
-                       "wrong ac97 register read back (%x != %x)\n",
-                       v, reg);
+       if (!timeout) {
+               dev_err(&aaci->dev->dev, "timeout on RX valid\n");
                v = ~0;
+               goto out;
        }
 
+       do {
+               v = readl(aaci->base + AACI_SL1RX) >> 12;
+               if (v == reg) {
+                       v = readl(aaci->base + AACI_SL2RX) >> 4;
+                       break;
+               } else if (--retries) {
+                       dev_warn(&aaci->dev->dev,
+                                "ac97 read back fail.  retry\n");
+                       continue;
+               } else {
+                       dev_warn(&aaci->dev->dev,
+                               "wrong ac97 register read back (%x != %x)\n",
+                               v, reg);
+                       v = ~0;
+               }
+       } while (retries);
+ out:
        mutex_unlock(&aaci->ac97_sem);
        return v;
 }
@@ -181,7 +208,7 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
                void *ptr;
 
                if (!aacirun->substream || !aacirun->start) {
-                       dev_warn(&aaci->dev->dev, "RX interrupt???");
+                       dev_warn(&aaci->dev->dev, "RX interrupt???\n");
                        writel(0, aacirun->base + AACI_IE);
                        return;
                }
@@ -235,7 +262,7 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
                void *ptr;
 
                if (!aacirun->substream || !aacirun->start) {
-                       dev_warn(&aaci->dev->dev, "TX interrupt???");
+                       dev_warn(&aaci->dev->dev, "TX interrupt???\n");
                        writel(0, aacirun->base + AACI_IE);
                        return;
                }
@@ -698,8 +725,8 @@ static struct snd_pcm_ops aaci_playback_ops = {
        .mmap           = aaci_pcm_mmap,
 };
 
-static int aaci_pcm_capture_hw_params(snd_pcm_substream_t *substream,
-                                     snd_pcm_hw_params_t *params)
+static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream,
+                                     struct snd_pcm_hw_params *params)
 {
        struct aaci *aaci = substream->private_data;
        struct aaci_runtime *aacirun = substream->runtime->private_data;
@@ -755,8 +782,8 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
        writel(ie, aacirun->base + AACI_IE);
 }
 
-static int aaci_pcm_capture_trigger(snd_pcm_substream_t *substream, int cmd){
-
+static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
        struct aaci *aaci = substream->private_data;
        struct aaci_runtime *aacirun = substream->runtime->private_data;
        unsigned long flags;
@@ -796,7 +823,7 @@ static int aaci_pcm_capture_trigger(snd_pcm_substream_t *substream, int cmd){
        return ret;
 }
 
-static int aaci_pcm_capture_prepare(snd_pcm_substream_t *substream)
+static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct aaci *aaci = substream->private_data;
@@ -814,7 +841,7 @@ static int aaci_pcm_capture_prepare(snd_pcm_substream_t *substream)
        return 0;
 }
 
-static snd_pcm_ops_t aaci_capture_ops = {
+static struct snd_pcm_ops aaci_capture_ops = {
        .open           = aaci_pcm_open,
        .close          = aaci_pcm_close,
        .ioctl          = snd_pcm_lib_ioctl,