diff options
author | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2008-09-15 22:40:51 +0000 |
---|---|---|
committer | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2008-09-15 22:40:51 +0000 |
commit | 28b1fafca5fb1a8888b84ab98aa5a50a73d115e1 (patch) | |
tree | 6b4bfa271718aaff81fe4d24ef416a02d6da4a6b | |
parent | 7fde72f66b65a8084625ffb1727f3d307c7a17e2 (diff) |
this driver uses three dma segments; play, record, calibrate.
instead of using a linked list to describe the dma segments
use three distinct pointers.
also, this driver only needs 1 buffer descriptor for each dma
segment, since each buffer descriptor can handle as many samples
as each segment can hold.
makes the code a little easier to read and allows us to free
the calibration buffer when we're done with it.
idea originally from ratchov@ a while back. tested by ratchov@
and myself.
ok ratchov@
-rw-r--r-- | sys/dev/pci/auich.c | 76 |
1 files changed, 43 insertions, 33 deletions
diff --git a/sys/dev/pci/auich.c b/sys/dev/pci/auich.c index b69877153fe..620e50b4662 100644 --- a/sys/dev/pci/auich.c +++ b/sys/dev/pci/auich.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auich.c,v 1.73 2008/05/25 23:59:33 jakemsr Exp $ */ +/* $OpenBSD: auich.c,v 1.74 2008/09/15 22:40:50 jakemsr Exp $ */ /* * Copyright (c) 2000,2001 Michael Shalayeff @@ -133,12 +133,11 @@ #define ICH_SIS_CTL_UNMUTE 0x01 /* un-mute the output */ /* - * according to the dev/audiovar.h AU_RING_SIZE is 2^16, what fits - * in our limits perfectly, i.e. setting it to higher value - * in your kernel config would improve perfomance, still 2^21 is the max + * There are 32 buffer descriptors. Each can reference up to 2^16 16-bit + * samples. */ #define AUICH_DMALIST_MAX 32 -#define AUICH_DMASEG_MAX (65536*2) /* 64k samples, 2x16 bit samples */ +#define AUICH_DMASEG_MAX (65536*2) struct auich_dmalist { u_int32_t base; u_int32_t len; @@ -155,10 +154,9 @@ struct auich_dmalist { struct auich_dma { bus_dmamap_t map; caddr_t addr; - bus_dma_segment_t segs[AUICH_DMALIST_MAX]; + bus_dma_segment_t segs[1]; int nsegs; size_t size; - struct auich_dma *next; }; struct auich_cdata { @@ -205,7 +203,9 @@ struct auich_softc { void *arg; } pcmo, pcmi, mici; - struct auich_dma *sc_dmas; + struct auich_dma *sc_pdma; /* play */ + struct auich_dma *sc_rdma; /* record */ + struct auich_dma *sc_cdma; /* calibrate */ #ifdef AUICH_DEBUG int pcmi_fifoe; @@ -1194,8 +1194,12 @@ auich_allocm(v, direction, size, pool, flags) return NULL; } - p->next = sc->sc_dmas; - sc->sc_dmas = p; + if (direction == AUMODE_PLAY) + sc->sc_pdma = p; + else if (direction == AUMODE_RECORD) + sc->sc_rdma = p; + else + sc->sc_cdma = p; return p->addr; } @@ -1204,17 +1208,20 @@ void auich_freem(void *v, void *ptr, int pool) { struct auich_softc *sc; - struct auich_dma *p, **pp; + struct auich_dma *p; sc = v; - for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) { - if (p->addr == ptr) { - auich_freemem(sc, p); - *pp = p->next; - free(p, pool); - return; - } - } + if (sc->sc_pdma != NULL && sc->sc_pdma->addr == ptr) + p = sc->sc_pdma; + else if (sc->sc_rdma != NULL && sc->sc_rdma->addr == ptr) + p = sc->sc_rdma; + else if (sc->sc_cdma != NULL && sc->sc_cdma->addr == ptr) + p = sc->sc_cdma; + else + return; + + auich_freemem(sc, p); + free(p, pool); } size_t @@ -1242,8 +1249,12 @@ auich_mappage(v, mem, off, prot) if (off < 0) return -1; - for (p = sc->sc_dmas; p && p->addr != mem; p = p->next); - if (!p) + p = NULL; + if (sc->sc_pdma != NULL && sc->sc_pdma->addr == mem) + p = sc->sc_pdma; + else if (sc->sc_rdma != NULL && sc->sc_rdma->addr == mem) + p = sc->sc_rdma; + else return -1; return bus_dmamem_mmap(sc->dmat, p->segs, p->nsegs, @@ -1417,8 +1428,9 @@ auich_trigger_output(v, start, end, blksize, intr, arg, param) ("auich_trigger_output(%x, %x, %d, %p, %p, %p)\n", start, end, blksize, intr, arg, param)); - for (p = sc->sc_dmas; p && p->addr != start; p = p->next); - if (!p) + if (sc->sc_pdma->addr == start) + p = sc->sc_pdma; + else return -1; size = (size_t)((caddr_t)end - (caddr_t)start); @@ -1460,8 +1472,9 @@ auich_trigger_input(v, start, end, blksize, intr, arg, param) ("auich_trigger_input(%x, %x, %d, %p, %p, %p)\n", start, end, blksize, intr, arg, param)); - for (p = sc->sc_dmas; p && p->addr != start; p = p->next); - if (!p) + if (sc->sc_rdma->addr == start) + p = sc->sc_rdma; + else return -1; size = (size_t)((caddr_t)end - (caddr_t)start); @@ -1570,7 +1583,7 @@ auich_alloc_cdata(struct auich_softc *sc) goto fail_0; } - if ((error = bus_dmamem_map(sc->dmat, &seg, rseg, + if ((error = bus_dmamem_map(sc->dmat, &seg, 1, sizeof(struct auich_cdata), (caddr_t *) &sc->sc_cdata, sc->sc_dmamap_flags)) != 0) { printf("%s: unable to map control data, error = %d\n", @@ -1663,13 +1676,12 @@ auich_calibrate(struct auich_softc *sc) /* Setup a buffer */ bytes = 16000; - temp_buffer = auich_allocm(sc, AUMODE_RECORD, bytes, M_DEVBUF, - M_NOWAIT); + temp_buffer = auich_allocm(sc, 0, bytes, M_DEVBUF, M_NOWAIT); if (temp_buffer == NULL) return (ac97rate); - for (p = sc->sc_dmas; p && p->addr != temp_buffer; p = p->next) - ; - if (p == NULL) { + if (sc->sc_cdma->addr == temp_buffer) { + p = sc->sc_cdma; + } else { printf("auich_calibrate: bad address %p\n", temp_buffer); return (ac97rate); } @@ -1721,9 +1733,7 @@ auich_calibrate(struct auich_softc *sc) /* turn time delta into us */ wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec; -#if 0 auich_freem(sc, temp_buffer, M_DEVBUF); -#endif if (nciv == ociv) { printf("%s: ac97 link rate calibration timed out after %d us\n", |