Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 81734
b: refs/heads/master
c: 19e2e3c
h: refs/heads/master
v: v3
  • Loading branch information
Hermann Lauer authored and Mercurial server committed Jan 31, 2008
1 parent c7b6cc6 commit 2e8dda3
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4979bca9dcfe4c21c26f378ce446c912fc583ac1
refs/heads/master: 19e2e3c30485ba78a653dc521ed9e1f2b6a8bee1
27 changes: 25 additions & 2 deletions trunk/sound/pci/es1938.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ struct es1938 {
unsigned int dma2_start;
unsigned int dma1_shift;
unsigned int dma2_shift;
unsigned int last_capture_dmaaddr;
unsigned int active;

spinlock_t reg_lock;
Expand Down Expand Up @@ -528,6 +529,7 @@ static void snd_es1938_capture_setdma(struct es1938 *chip)
outb(1, SLDM_REG(chip, DMAMASK));
outb(0x14, SLDM_REG(chip, DMAMODE));
outl(chip->dma1_start, SLDM_REG(chip, DMAADDR));
chip->last_capture_dmaaddr = chip->dma1_start;
outw(chip->dma1_size - 1, SLDM_REG(chip, DMACOUNT));
/* 3. Unmask DMA */
outb(0, SLDM_REG(chip, DMAMASK));
Expand Down Expand Up @@ -769,19 +771,40 @@ static int snd_es1938_playback_prepare(struct snd_pcm_substream *substream)
return -EINVAL;
}

/* 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 implementation 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 ptr;
#if 0
size_t old, new;
#if 1
/* 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;
#else
ptr = inl(SLDM_REG(chip, DMAADDR)) - chip->dma1_start;
size_t count;
unsigned int diff;

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 */
else
chip->last_capture_dmaaddr = ptr; /* good, remember it */

ptr -= chip->dma1_start;
#endif
return ptr >> chip->dma1_shift;
}
Expand Down

0 comments on commit 2e8dda3

Please sign in to comment.