diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/arm/aaci.c | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 91acc9a..24d3013 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -30,6 +30,8 @@ #define DRIVER_NAME "aaci-pl041" +#define FRAME_PERIOD_US 21 + /* * PM support is not complete. Turn it off. */ @@ -64,8 +66,8 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { struct aaci *aaci = ac97->private_data; + int timeout; u32 v; - int timeout = 5000; if (ac97->num >= 4) return; @@ -81,14 +83,17 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, writel(val << 4, aaci->base + AACI_SL2TX); writel(reg << 12, aaci->base + AACI_SL1TX); - /* - * Wait for the transmission of both slots to complete. - */ + /* Initially, wait one frame period */ + udelay(FRAME_PERIOD_US); + + /* And then wait an additional eight frame periods for it to be sent */ + timeout = FRAME_PERIOD_US * 8; do { + udelay(1); v = readl(aaci->base + AACI_SLFR); } while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout); - if (!timeout) + if (v & (SLFR_1TXB|SLFR_2TXB)) dev_err(&aaci->dev->dev, "timeout waiting for write to complete\n"); @@ -101,9 +106,8 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { struct aaci *aaci = ac97->private_data; + int timeout, retries = 10; u32 v; - int timeout = 5000; - int retries = 10; if (ac97->num >= 4) return ~0; @@ -117,35 +121,34 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) */ writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX); - /* - * Wait for the transmission to complete. - */ + /* Initially, wait one frame period */ + udelay(FRAME_PERIOD_US); + + /* And then wait an additional eight frame periods for it to be sent */ + timeout = FRAME_PERIOD_US * 8; do { + udelay(1); v = readl(aaci->base + AACI_SLFR); } while ((v & SLFR_1TXB) && --timeout); - if (!timeout) { + if (v & SLFR_1TXB) { 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 - * to respond. (42us = ~2 frames at 48kHz.) - */ - udelay(42); + /* Now wait for the response frame */ + udelay(FRAME_PERIOD_US); - /* - * Wait for slot 2 to indicate data. - */ - timeout = 5000; + /* And then wait an additional eight frame periods for data */ + timeout = FRAME_PERIOD_US * 8; do { + udelay(1); cond_resched(); v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV); } while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout); - if (!timeout) { + if (v != (SLFR_1RXV|SLFR_2RXV)) { dev_err(&aaci->dev->dev, "timeout on RX valid\n"); v = ~0; goto out; @@ -179,6 +182,7 @@ aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask) int timeout = 5000; do { + udelay(1); val = readl(aacirun->base + AACI_SR); } while (val & mask && timeout--); } @@ -874,7 +878,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci) * Give the AC'97 codec more than enough time * to wake up. (42us = ~2 frames at 48kHz.) */ - udelay(42); + udelay(FRAME_PERIOD_US * 2); ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus); if (ret) |