ASoC: au1x: psc-ac97: reorganize timeouts
Manuel Lauss [Mon, 19 Oct 2009 14:10:59 +0000 (16:10 +0200)]
Codec read/write functions: wait 21us between the pokings of hardware.
Add timeouts to unbounded loops waiting for bits to change.

Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

sound/soc/au1x/psc-ac97.c

index efe2afd..2a06a9c 100644 (file)
@@ -75,10 +75,12 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
                          AC97_CDC(pscdata));
                au_sync();
 
-               tmo = 2000;
-               while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD))
-                       && --tmo)
-                       udelay(2);
+               tmo = 20;
+               do {
+                       udelay(21);
+                       if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
+                               break;
+               } while (--tmo);
 
                data = au_readl(AC97_CDC(pscdata));
 
@@ -114,10 +116,12 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
                          AC97_CDC(pscdata));
                au_sync();
 
-               tmo = 2000;
-               while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD))
-                      && --tmo)
-                       udelay(2);
+               tmo = 20;
+               do {
+                       udelay(21);
+                       if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
+                               break;
+               } while (--tmo);
 
                au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
                au_sync();
@@ -200,7 +204,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
        /* FIXME */
        struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
        unsigned long r, ro, stat;
-       int chans, stype = SUBSTREAM_TYPE(substream);
+       int chans, t, stype = SUBSTREAM_TYPE(substream);
 
        chans = params_channels(params);
 
@@ -242,8 +246,12 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
                au_sync();
 
                /* ...wait for it... */
-               while (au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)
-                       asm volatile ("nop");
+               t = 100;
+               while ((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t)
+                       msleep(1);
+
+               if (!t)
+                       printk(KERN_ERR "PSC-AC97: can't disable!\n");
 
                /* ...write config... */
                au_writel(r, AC97_CFG(pscdata));
@@ -254,8 +262,12 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
                au_sync();
 
                /* ...and wait for ready bit */
-               while (!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR))
-                       asm volatile ("nop");
+               t = 100;
+               while ((!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t)
+                       msleep(1);
+
+               if (!t)
+                       printk(KERN_ERR "PSC-AC97: can't enable!\n");
 
                mutex_unlock(&pscdata->lock);