aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@suse.cz>2005-01-12 22:29:54 +0100
committerJaroslav Kysela <perex@suse.cz>2005-01-12 22:29:54 +0100
commitbdd03b88e1a318f7c50647b4dfe7d214c4e7a324 (patch)
tree5c4d852e4e2b4e16699a9def459b5eeeff7a9d0a /sound
parentffcce5e2f9bc2169b7611bbf3b5b5d37d959760a (diff)
downloadhistory-bdd03b88e1a318f7c50647b4dfe7d214c4e7a324.tar.gz
[ALSA] Fix DMA pointer read
ATIIXP driver Try to reread DMA pointer register if the value is invalid. The register shows bogus values on some broken hardwares. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/atiixp.c23
1 files changed, 11 insertions, 12 deletions
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index f05b51b23bdc7e..3cb1c33e5f2a75 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -630,21 +630,20 @@ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
snd_pcm_runtime_t *runtime = substream->runtime;
atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data;
unsigned int curptr;
+ int timeout = 1000;
- spin_lock(&chip->reg_lock);
- curptr = readl(chip->remap_addr + dma->ops->dt_cur);
- if (curptr < dma->buf_addr) {
- snd_printdd("curptr = %x, base = %x\n", curptr, dma->buf_addr);
- curptr = 0;
- } else {
+ while (timeout--) {
+ curptr = readl(chip->remap_addr + dma->ops->dt_cur);
+ if (curptr < dma->buf_addr)
+ continue;
curptr -= dma->buf_addr;
- if (curptr >= dma->buf_bytes) {
- snd_printdd("curptr = %x, size = %x\n", curptr, dma->buf_bytes);
- curptr = 0;
- }
+ if (curptr >= dma->buf_bytes)
+ continue;
+ return bytes_to_frames(runtime, curptr);
}
- spin_unlock(&chip->reg_lock);
- return bytes_to_frames(runtime, curptr);
+ snd_printd("atiixp: invalid DMA pointer read 0x%x (buf=%x)\n",
+ readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr);
+ return 0;
}
/*