aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorSarah Bessmer <aotos@fastmail.fm>2014-01-09 14:36:31 -0500
committerTakashi Iwai <tiwai@suse.de>2014-01-10 04:10:41 -0500
commite240a46965dd14db6e6bdf8974ebb347f3db860b (patch)
treeb8fe7ba7f9956b715e5e4c75285badbb15016842 /sound/pci
parent2d82ea2005624a80b18916e37bce921d6e868b59 (diff)
ALSA: ctxfi - Work around emu20k1 glitch to prevent buffered sound data loss
Occasionally, on playback stream ringbuffer wraparound, the EMU20K1 hardware will momentarily return 0 instead of the proper current(loop) address. This patch handles that case, fixing the problem of playback position corruption and subsequent loss of buffered sound data, that occurs with some common buffering layout patterns(e.g. multiple simultaneous output streams with differently-sized or non-power-of-2-sized buffers). An alternate means of fixing the problem would be to read the ca register continuously, until two sequential reads return the same value; however, that would be a more invasive change, has performance implications, and isn't necessary unless there are also issues with the value not being updated atomically in regards to individual bits or something similar(which I have not encountered through light testing). I have no EMU20K2 hardware to confirm if the issue is present there, but even if it's not, this change shouldn't break anything that's not already broken. Signed-off-by: Sarah Bessmer <aotos@fastmail.fm> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/ctxfi/ctatc.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
index b5fa583a239a..eb86829529eb 100644
--- a/sound/pci/ctxfi/ctatc.c
+++ b/sound/pci/ctxfi/ctatc.c
@@ -435,6 +435,11 @@ atc_pcm_playback_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)
435 return 0; 435 return 0;
436 position = src->ops->get_ca(src); 436 position = src->ops->get_ca(src);
437 437
438 if (position < apcm->vm_block->addr) {
439 snd_printdd("ctxfi: bad ca - ca=0x%08x, vba=0x%08x, vbs=0x%08x\n", position, apcm->vm_block->addr, apcm->vm_block->size);
440 position = apcm->vm_block->addr;
441 }
442
438 size = apcm->vm_block->size; 443 size = apcm->vm_block->size;
439 max_cisz = src->multi * src->rsc.msr; 444 max_cisz = src->multi * src->rsc.msr;
440 max_cisz = 128 * (max_cisz < 8 ? max_cisz : 8); 445 max_cisz = 128 * (max_cisz < 8 ? max_cisz : 8);