Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162968109
D44084.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
2 KB
Referenced Files
None
Subscribers
None
D44084.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D44084: snd_hdspe(4): Only buffer_copy() audio data once.
Attached
Detach File
Event Timeline
Log In to Comment