Page MenuHomeFreeBSD

D44084.id.diff
No OneTemporary

D44084.id.diff

diff --git a/sys/dev/sound/pci/hdspe-pcm.c b/sys/dev/sound/pci/hdspe-pcm.c
--- a/sys/dev/sound/pci/hdspe-pcm.c
+++ b/sys/dev/sound/pci/hdspe-pcm.c
@@ -540,7 +540,8 @@
struct sc_pcminfo *scp;
struct sc_info *sc;
uint32_t row, ports;
- unsigned int pos;
+ uint32_t dma_pos;
+ unsigned int pos, length, offset;
unsigned int n;
unsigned int adat_width, pcm_width;
@@ -558,13 +559,35 @@
else
pcm_width = 8;
- if (ch->dir == PCMDIR_PLAY)
- pos = sndbuf_getreadyptr(ch->buffer);
- else
- pos = sndbuf_getfreeptr(ch->buffer);
+ /* Derive buffer position and length to be copied. */
+ if (ch->dir == PCMDIR_PLAY) {
+ /* Position per channel is n times smaller than PCM. */
+ pos = sndbuf_getreadyptr(ch->buffer) / n;
+ length = sndbuf_getready(ch->buffer) / n;
+ /* Copy no more than 2 periods in advance. */
+ if (length > (sc->period * 4 * 2))
+ length = (sc->period * 4 * 2);
+ /* Skip what was already copied last time. */
+ offset = (ch->position + HDSPE_CHANBUF_SIZE) - pos;
+ offset %= HDSPE_CHANBUF_SIZE;
+ if (offset <= length) {
+ pos = (pos + offset) % HDSPE_CHANBUF_SIZE;
+ length -= offset;
+ }
+ } else {
+ /* Position per channel is n times smaller than PCM. */
+ pos = sndbuf_getfreeptr(ch->buffer) / n;
+ /* Get DMA buffer write position. */
+ dma_pos = hdspe_read_2(sc, HDSPE_STATUS_REG);
+ dma_pos &= HDSPE_BUF_POSITION_MASK;
+ /* Copy what is newly available. */
+ length = (dma_pos + HDSPE_CHANBUF_SIZE) - pos;
+ length %= HDSPE_CHANBUF_SIZE;
+ }
- pos /= 4; /* Bytes per sample. */
- pos /= n; /* Destination buffer n-times smaller. */
+ /* Position and length in samples (4 bytes). */
+ pos /= 4;
+ length /= 4;
/* Iterate through rows of ports with contiguous slots. */
ports = ch->ports;
@@ -576,10 +599,10 @@
while (row != 0) {
if (ch->dir == PCMDIR_PLAY)
buffer_mux_port(sc->pbuf, ch->data, row, ch->ports, pos,
- sc->period * 2, adat_width, pcm_width);
+ length, adat_width, pcm_width);
else
buffer_demux_port(sc->rbuf, ch->data, row, ch->ports,
- pos, sc->period * 2, adat_width, pcm_width);
+ pos, length, adat_width, pcm_width);
ports &= ~row;
if (pcm_width == adat_width)
@@ -587,6 +610,8 @@
else
row = hdspe_port_first(ports);
}
+
+ ch->position = ((pos + length) * 4) % HDSPE_CHANBUF_SIZE;
}
static int
@@ -620,6 +645,8 @@
row = hdspe_port_first_row(ports);
}
+ ch->position = 0;
+
return (0);
}
@@ -664,6 +691,7 @@
/* Allocate maximum buffer size. */
ch->size = HDSPE_CHANBUF_SIZE * hdspe_channel_count(ch->ports, 8);
ch->data = malloc(ch->size, M_HDSPE, M_NOWAIT);
+ ch->position = 0;
ch->buffer = b;
ch->channel = c;
diff --git a/sys/dev/sound/pci/hdspe.h b/sys/dev/sound/pci/hdspe.h
--- a/sys/dev/sound/pci/hdspe.h
+++ b/sys/dev/sound/pci/hdspe.h
@@ -184,6 +184,7 @@
/* Buffer */
uint32_t *data;
uint32_t size;
+ uint32_t position;
/* Flags */
uint32_t run;

File Metadata

Mime Type
text/plain
Expires
Sun, Jul 19, 7:15 PM (19 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35245601
Default Alt Text
D44084.id.diff (2 KB)

Event Timeline