[alsa-devel] es1938 - patch trying to improve capture hw pointer reads
Hermann.Lauer at iwr.uni-heidelberg.de
Tue Jan 29 09:31:04 CET 2008
On Thu, Jan 24, 2008 at 04:40:18PM +0100, Takashi Iwai wrote:
> > > The patch is, however, unable to apply as is because of coding style
> > > problems. Try $LINUXKERNEL/scripts/checkpatch.pl, fix what are
> > > suggested there, and repost the patch together with your sign-off.
> > Will do that when I digged trough the details (have to learn about signing).
> See $LINUX/Documentation/SubmittingPatches.
Appended is a cleaned up version of the patch. checkpatch.pl is now
only mucking about the '#if 0' commented out old branch. Should this
be removed or the if-else parts exchanged, which probably will calm down
Have to check compilation, then I will send a signed version.
Netzwerkadministration/Zentrale Dienste, Interdiziplinaeres
Zentrum fuer wissenschaftliches Rechnen der Universitaet Heidelberg
IWR; INF 368; 69120 Heidelberg; Tel: (06221)54-8236 Fax: -5224
Email: Hermann.Lauer at iwr.uni-heidelberg.de
-------------- next part --------------
--- linux-22.214.171.124/sound/pci/es1938.c.trydma 2008-01-10 19:50:14.000000000 +0000
+++ linux-126.96.36.199/sound/pci/es1938.c 2008-01-29 07:33:53.000000000 +0000
@@ -227,6 +227,8 @@
unsigned int dma2_start;
unsigned int dma1_shift;
unsigned int dma2_shift;
+ void *last_capture_dmaaddr;
unsigned int active;
@@ -770,19 +772,42 @@
+/* during the incrementing of dma counters the DMA register reads sometimes
+ returns garbage. To ensure a valid hw pointer, the following checks which
+ should be very unlikely to fail are used:
+ - is the current DMA address in the valid DMA range ?
+ - is the sum of DMA address and DMA counter pointing to the last DMA byte ?
+ One can argue this could differ by one byte depending on which register is
+ updated first, so the implemention below allows for that.
static snd_pcm_uframes_t snd_es1938_capture_pointer(struct snd_pcm_substream *substream)
struct es1938 *chip = snd_pcm_substream_chip(substream);
size_t old, new;
/* This stuff is *needed*, don't ask why - AB */
old = inw(SLDM_REG(chip, DMACOUNT));
while ((new = inw(SLDM_REG(chip, DMACOUNT))) != old)
old = new;
ptr = chip->dma1_size - 1 - new;
- ptr = inl(SLDM_REG(chip, DMAADDR)) - chip->dma1_start;
+ size_t stat, count;
+ unsigned int diff;
+ struct snd_pcm_runtime *runtime;
+ runtime = substream->runtime;
+ ptr = inl(SLDM_REG(chip, DMAADDR));
+ count = inw(SLDM_REG(chip, DMACOUNT));
+ diff = chip->dma1_start+chip->dma1_size-ptr-count;
+ if (diff > 3 || ptr < chip->dma1_start
+ || ptr >= chip->dma1_start+chip->dma1_size)
+ ptr = chip->last_capture_dmaaddr; /* bad, use last saved */
+ chip->last_capture_dmaaddr = ptr; /* good, remember it */
+ ptr -= chip->dma1_start;
return ptr >> chip->dma1_shift;
More information about the Alsa-devel