ALSA: ctxfi - Work around emu20k1 glitch to prevent buffered sound data loss
authorSarah Bessmer <aotos@fastmail.fm>
Thu, 9 Jan 2014 19:36:31 +0000 (11:36 -0800)
committerTakashi Iwai <tiwai@suse.de>
Fri, 10 Jan 2014 09:10:41 +0000 (10:10 +0100)
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>
sound/pci/ctxfi/ctatc.c

index b5fa583a239a5c978a1af60defe47a61886aeab0..eb86829529eb3e7f56da61324f8f16a87f3a44c6 100644 (file)
@@ -435,6 +435,11 @@ atc_pcm_playback_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                return 0;
        position = src->ops->get_ca(src);
 
+       if (position < apcm->vm_block->addr) {
+               snd_printdd("ctxfi: bad ca - ca=0x%08x, vba=0x%08x, vbs=0x%08x\n", position, apcm->vm_block->addr, apcm->vm_block->size);
+               position = apcm->vm_block->addr;
+       }
+
        size = apcm->vm_block->size;
        max_cisz = src->multi * src->rsc.msr;
        max_cisz = 128 * (max_cisz < 8 ? max_cisz : 8);