Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177100721
D58372.1793802762.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
11 KB
Referenced Files
None
Subscribers
None
D58372.1793802762.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
@@ -108,21 +108,14 @@
return (ports & (~(ports - 1))); /* Extract first bit set. */
}
-static uint32_t
-hdspe_port_first_row(uint32_t ports)
+/* AIO ADAT channels use strided slots at double and quad speed. */
+static unsigned int
+hdspe_port_slot_stride(struct sc_info *sc, uint32_t port)
{
- uint32_t ends;
-
- /* Restrict ports to one set with contiguous slots. */
- if (ports & HDSPE_CHAN_AIO_ALL)
- ports &= HDSPE_CHAN_AIO_ALL; /* All AIO slots. */
- else if (ports & HDSPE_CHAN_RAY_ALL)
- ports &= HDSPE_CHAN_RAY_ALL; /* All RayDAT slots. */
-
- /* Ends of port rows are followed by a port which is not in the set. */
- ends = ports & (~(ports >> 1));
- /* First row of contiguous ports ends in the first row end. */
- return (ports & (ends ^ (ends - 1)));
+ if (sc->type == HDSPE_AIO &&
+ hdspe_port_first(port) == HDSPE_CHAN_AIO_ADAT)
+ return (8 / hdspe_adat_width(sc->speed));
+ return (1);
}
static unsigned int
@@ -184,7 +177,7 @@
static unsigned int
hdspe_port_slot_offset(uint32_t port, unsigned int adat_width)
{
- /* Exctract the first port (lowest bit) if set of ports. */
+ /* Extract the first port if a set of ports is specified. */
switch (hdspe_port_first(port)) {
/* AIO ports */
case HDSPE_CHAN_AIO_LINE:
@@ -219,13 +212,9 @@
}
static unsigned int
-hdspe_port_slot_width(uint32_t ports, unsigned int adat_width)
+hdspe_port_slot_width(uint32_t port, unsigned int adat_width)
{
- uint32_t row;
-
- /* Count number of contiguous slots from the first physical port. */
- row = hdspe_port_first_row(ports);
- return (hdspe_channel_count(row, adat_width));
+ return (hdspe_channel_count(hdspe_port_first(port), adat_width));
}
static int
@@ -255,7 +244,7 @@
{
struct sc_info *sc;
uint32_t port, ports;
- unsigned int slot, end_slot;
+ unsigned int base, width, stride, i, slot;
unsigned short volume;
sc = ch->parent->sc;
@@ -264,15 +253,14 @@
ports = ch->ports;
port = hdspe_port_first(ports);
while (port != 0) {
- /* Get slot range of the physical port. */
- slot =
- hdspe_port_slot_offset(port, hdspe_adat_width(sc->speed));
- end_slot = slot +
- hdspe_port_slot_width(port, hdspe_adat_width(sc->speed));
+ base = hdspe_port_slot_offset(port, hdspe_adat_width(sc->speed));
+ width = hdspe_port_slot_width(port, hdspe_adat_width(sc->speed));
+ stride = hdspe_port_slot_stride(sc, port);
/* Treat first slot as left channel. */
volume = ch->lvol * HDSPE_MAX_GAIN / 100;
- for (; slot < end_slot; slot++) {
+ for (i = 0; i < width; i++) {
+ slot = base + i * stride;
hdspe_hw_mixer(ch, slot, slot, volume);
/* Subsequent slots all get the right channel volume. */
volume = ch->rvol * HDSPE_MAX_GAIN / 100;
@@ -354,9 +342,9 @@
{
struct sc_pcminfo *scp;
struct sc_info *sc;
- uint32_t row, ports;
+ uint32_t port, ports;
int reg;
- unsigned int slot, end_slot;
+ unsigned int base, width, stride, i, slot;
scp = ch->parent;
sc = scp->sc;
@@ -368,21 +356,20 @@
ch->run = value;
- /* Iterate through rows of ports with contiguous slots. */
ports = ch->ports;
- row = hdspe_port_first_row(ports);
- while (row != 0) {
- slot =
- hdspe_port_slot_offset(row, hdspe_adat_width(sc->speed));
- end_slot = slot +
- hdspe_port_slot_width(row, hdspe_adat_width(sc->speed));
-
- for (; slot < end_slot; slot++) {
+ port = hdspe_port_first(ports);
+ while (port != 0) {
+ base = hdspe_port_slot_offset(port, hdspe_adat_width(sc->speed));
+ width = hdspe_port_slot_width(port, hdspe_adat_width(sc->speed));
+ stride = hdspe_port_slot_stride(sc, port);
+
+ for (i = 0; i < width; i++) {
+ slot = base + i * stride;
hdspe_write_1(sc, reg + (4 * slot), value);
}
- ports &= ~row;
- row = hdspe_port_first_row(ports);
+ ports &= ~port;
+ port = hdspe_port_first(ports);
}
}
@@ -429,96 +416,83 @@
static void
buffer_mux_write(uint32_t *dma, uint32_t *pcm, unsigned int pos,
- unsigned int samples, unsigned int slots, unsigned int channels)
+ unsigned int samples, unsigned int nch, unsigned int channels,
+ unsigned int stride)
{
- int slot;
+ unsigned int i;
for (; samples > 0; samples--) {
- for (slot = 0; slot < slots; slot++) {
- dma[slot * HDSPE_CHANBUF_SAMPLES + pos] =
- pcm[pos * channels + slot];
+ for (i = 0; i < nch; i++) {
+ dma[i * stride * HDSPE_CHANBUF_SAMPLES + pos] =
+ pcm[pos * channels + i];
}
pos = (pos + 1) % HDSPE_CHANBUF_SAMPLES;
}
}
static void
-buffer_mux_port(uint32_t *dma, uint32_t *pcm, uint32_t subset, uint32_t ports,
- unsigned int pos, unsigned int samples, unsigned int adat_width,
- unsigned int pcm_width)
+buffer_mux_port(struct sc_info *sc, uint32_t *dma, uint32_t *pcm,
+ uint32_t port, uint32_t ports, unsigned int pos, unsigned int samples,
+ unsigned int adat_width, unsigned int pcm_width)
{
- unsigned int slot_offset, slots;
+ unsigned int slot_offset, nch, stride;
unsigned int channels, chan_pos;
/* Translate DMA slot offset to DMA buffer offset. */
- slot_offset = hdspe_port_slot_offset(subset, adat_width);
+ slot_offset = hdspe_port_slot_offset(port, adat_width);
dma += slot_offset * HDSPE_CHANBUF_SAMPLES;
- /* Channel position of the port subset and total number of channels. */
- chan_pos = hdspe_channel_offset(subset, ports, pcm_width);
+ /* Channel position of the port and total number of channels. */
+ chan_pos = hdspe_channel_offset(port, ports, pcm_width);
pcm += chan_pos;
channels = hdspe_channel_count(ports, pcm_width);
/* Only copy as much as supported by both hardware and pcm channel. */
- slots = hdspe_port_slot_width(subset, min(adat_width, pcm_width));
-
- /* Let the compiler inline and loop unroll common cases. */
- if (slots == 2)
- buffer_mux_write(dma, pcm, pos, samples, 2, channels);
- else if (slots == 4)
- buffer_mux_write(dma, pcm, pos, samples, 4, channels);
- else if (slots == 8)
- buffer_mux_write(dma, pcm, pos, samples, 8, channels);
- else
- buffer_mux_write(dma, pcm, pos, samples, slots, channels);
+ nch = hdspe_port_slot_width(port, min(adat_width, pcm_width));
+ stride = hdspe_port_slot_stride(sc, port);
+
+ buffer_mux_write(dma, pcm, pos, samples, nch, channels, stride);
}
static void
buffer_demux_read(uint32_t *dma, uint32_t *pcm, unsigned int pos,
- unsigned int samples, unsigned int slots, unsigned int channels)
+ unsigned int samples, unsigned int nch, unsigned int channels,
+ unsigned int stride)
{
- int slot;
+ unsigned int i;
for (; samples > 0; samples--) {
- for (slot = 0; slot < slots; slot++) {
- pcm[pos * channels + slot] =
- dma[slot * HDSPE_CHANBUF_SAMPLES + pos];
+ for (i = 0; i < nch; i++) {
+ pcm[pos * channels + i] =
+ dma[i * stride * HDSPE_CHANBUF_SAMPLES + pos];
}
pos = (pos + 1) % HDSPE_CHANBUF_SAMPLES;
}
}
static void
-buffer_demux_port(uint32_t *dma, uint32_t *pcm, uint32_t subset, uint32_t ports,
- unsigned int pos, unsigned int samples, unsigned int adat_width,
- unsigned int pcm_width)
+buffer_demux_port(struct sc_info *sc, uint32_t *dma, uint32_t *pcm,
+ uint32_t port, uint32_t ports, unsigned int pos, unsigned int samples,
+ unsigned int adat_width, unsigned int pcm_width)
{
- unsigned int slot_offset, slots;
+ unsigned int slot_offset, nch, stride;
unsigned int channels, chan_pos;
/* Translate port slot offset to DMA buffer offset. */
- slot_offset = hdspe_port_slot_offset(subset, adat_width);
+ slot_offset = hdspe_port_slot_offset(port, adat_width);
dma += slot_offset * HDSPE_CHANBUF_SAMPLES;
- /* Channel position of the port subset and total number of channels. */
- chan_pos = hdspe_channel_offset(subset, ports, pcm_width);
+ /* Channel position of the port and total number of channels. */
+ chan_pos = hdspe_channel_offset(port, ports, pcm_width);
pcm += chan_pos;
channels = hdspe_channel_count(ports, pcm_width);
/* Only copy as much as supported by both hardware and pcm channel. */
- slots = hdspe_port_slot_width(subset, min(adat_width, pcm_width));
-
- /* Let the compiler inline and loop unroll common cases. */
- if (slots == 2)
- buffer_demux_read(dma, pcm, pos, samples, 2, channels);
- else if (slots == 4)
- buffer_demux_read(dma, pcm, pos, samples, 4, channels);
- else if (slots == 8)
- buffer_demux_read(dma, pcm, pos, samples, 8, channels);
- else
- buffer_demux_read(dma, pcm, pos, samples, slots, channels);
-}
+ nch = hdspe_port_slot_width(port, min(adat_width, pcm_width));
+ stride = hdspe_port_slot_stride(sc, port);
+ buffer_demux_read(dma, pcm, pos, samples, nch, channels, stride);
+}
/* Copy data between DMA and PCM buffers. */
static void
@@ -526,7 +500,7 @@
{
struct sc_pcminfo *scp;
struct sc_info *sc;
- uint32_t row, ports;
+ uint32_t port, ports;
uint32_t dma_pos;
unsigned int pos, length, offset;
unsigned int n;
@@ -575,26 +549,19 @@
pos /= 4;
length /= 4;
- /* Iterate through rows of ports with contiguous slots. */
+ /* Copy each port separately to preserve strided AIO ADAT slots. */
ports = ch->ports;
- if (pcm_width == adat_width)
- row = hdspe_port_first_row(ports);
- else
- row = hdspe_port_first(ports);
-
- while (row != 0) {
+ port = hdspe_port_first(ports);
+ while (port != 0) {
if (ch->dir == PCMDIR_PLAY)
- buffer_mux_port(sc->pbuf, ch->data, row, ch->ports, pos,
- length, adat_width, pcm_width);
- else
- buffer_demux_port(sc->rbuf, ch->data, row, ch->ports,
+ buffer_mux_port(sc, sc->pbuf, ch->data, port, ch->ports,
pos, length, adat_width, pcm_width);
-
- ports &= ~row;
- if (pcm_width == adat_width)
- row = hdspe_port_first_row(ports);
else
- row = hdspe_port_first(ports);
+ buffer_demux_port(sc, sc->rbuf, ch->data, port,
+ ch->ports, pos, length, adat_width, pcm_width);
+
+ ports &= ~port;
+ port = hdspe_port_first(ports);
}
if (ch->dir == PCMDIR_PLAY && length > 0) {
@@ -612,8 +579,8 @@
struct sc_pcminfo *scp;
struct sc_info *sc;
uint32_t *buf;
- uint32_t row, ports;
- unsigned int offset, slots;
+ uint32_t port, ports;
+ unsigned int base, width, stride, i, slot;
scp = ch->parent;
sc = scp->sc;
@@ -627,19 +594,23 @@
else
bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_POSTREAD);
- /* Iterate through rows of ports with contiguous slots. */
ports = ch->ports;
- row = hdspe_port_first_row(ports);
- while (row != 0) {
- offset = hdspe_port_slot_offset(row,
+ port = hdspe_port_first(ports);
+ while (port != 0) {
+ base = hdspe_port_slot_offset(port,
hdspe_adat_width(sc->speed));
- slots = hdspe_port_slot_width(row, hdspe_adat_width(sc->speed));
+ width = hdspe_port_slot_width(port,
+ hdspe_adat_width(sc->speed));
+ stride = hdspe_port_slot_stride(sc, port);
- bzero(buf + offset * HDSPE_CHANBUF_SAMPLES,
- slots * HDSPE_CHANBUF_SIZE);
+ for (i = 0; i < width; i++) {
+ slot = base + i * stride;
+ bzero(buf + slot * HDSPE_CHANBUF_SAMPLES,
+ HDSPE_CHANBUF_SIZE);
+ }
- ports &= ~row;
- row = hdspe_port_first_row(ports);
+ ports &= ~port;
+ port = hdspe_port_first(ports);
}
if (ch->dir == PCMDIR_PLAY)
diff --git a/sys/dev/sound/pci/hdspe.c b/sys/dev/sound/pci/hdspe.c
--- a/sys/dev/sound/pci/hdspe.c
+++ b/sys/dev/sound/pci/hdspe.c
@@ -957,9 +957,9 @@
if (sc->dmat)
bus_dma_tag_destroy(sc->dmat);
if (sc->irq)
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
if (sc->cs)
- bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), sc->cs);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->csid, sc->cs);
cv_destroy(&sc->pcm_cv);
mtx_destroy(&sc->lock);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 4, 2:32 PM (12 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41379170
Default Alt Text
D58372.1793802762.diff (11 KB)
Attached To
Mode
D58372: snd_hdspe: Use busdma for DMA buffers
Attached
Detach File
Event Timeline