summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>2003-02-05 08:47:06 +0000
committerJason Wright <jason@cvs.openbsd.org>2003-02-05 08:47:06 +0000
commit000c59c5ecadeeaf9c15ee74aff432337795cc10 (patch)
treea9fcd18230431c834e6c0279f4e5392a3a7e80a2 /sys
parente6cf03899f11f3af06d27a1d205307adf5620a55 (diff)
Get rid of the pops:
- interrupt is called when the block has been DMA'd... since LASI seems to include a FIFO this is -not- the same as block completion which we have to poll for. Luckily the FIFO is deep enough that polling in the interrupt handler seems to work. - This probably breaks capture, but I'll fix that when I get up tomorrow. (committed to the tune of Fugazi's "Waiting Room")
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/hppa/gsc/harmony.c136
-rw-r--r--sys/arch/hppa/gsc/harmonyreg.h11
-rw-r--r--sys/arch/hppa/gsc/harmonyvar.h4
3 files changed, 102 insertions, 49 deletions
diff --git a/sys/arch/hppa/gsc/harmony.c b/sys/arch/hppa/gsc/harmony.c
index 7d5302dcfeb..e7f245ffff0 100644
--- a/sys/arch/hppa/gsc/harmony.c
+++ b/sys/arch/hppa/gsc/harmony.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: harmony.c,v 1.14 2003/01/30 03:34:26 mickey Exp $ */
+/* $OpenBSD: harmony.c,v 1.15 2003/02/05 08:47:05 jason Exp $ */
/*
* Copyright (c) 2003 Jason L. Wright (jason@thought.net)
@@ -36,6 +36,7 @@
*/
#include <sys/param.h>
+#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
@@ -76,9 +77,9 @@ void harmony_freem(void *, void *, int);
size_t harmony_round_buffersize(void *, int, size_t);
int harmony_get_props(void *);
int harmony_trigger_output(void *, void *, void *, int,
- void (*intr)(void *), void *arg, struct audio_params *);
+ void (*intr)(void *), void *, struct audio_params *);
int harmony_trigger_input(void *, void *, void *, int,
- void (*intr)(void *), void *arg, struct audio_params *);
+ void (*intr)(void *), void *, struct audio_params *);
struct audio_hw_if harmony_sa_hw_if = {
harmony_open,
@@ -117,8 +118,10 @@ void harmony_intr_disable(struct harmony_softc *);
u_int32_t harmony_speed_bits(struct harmony_softc *, u_long *);
int harmony_set_gainctl(struct harmony_softc *);
void harmony_reset_codec(struct harmony_softc *);
-void harmony_start_pb(struct harmony_softc *);
void harmony_start_cp(struct harmony_softc *);
+void harmony_tick_pb(void *);
+void harmony_tick_cp(void *);
+void harmony_try_more(struct harmony_softc *);
int
harmony_match(parent, match, aux)
@@ -270,11 +273,32 @@ harmony_intr(vsc)
dstatus = READ_REG(sc, HARMONY_DSTATUS);
if (dstatus & DSTATUS_PN) {
- c = &sc->sc_playback;
+ struct harmony_dma *d;
+ bus_addr_t nextaddr;
+ bus_size_t togo;
+
r = 1;
- harmony_start_pb(sc);
- if (sc->sc_playing && c->c_intr != NULL)
- (*c->c_intr)(c->c_intrarg);
+ c = &sc->sc_playback;
+ d = c->c_current;
+ togo = c->c_segsz - c->c_cnt;
+ if (togo == 0) {
+ nextaddr = d->d_map->dm_segs[0].ds_addr;
+ c->c_cnt = togo = c->c_blksz;
+ } else {
+ nextaddr = c->c_lastaddr;
+ if (togo > c->c_blksz)
+ togo = c->c_blksz;
+ c->c_cnt += togo;
+ }
+
+ bus_dmamap_sync(sc->sc_dmat, d->d_map,
+ nextaddr - d->d_map->dm_segs[0].ds_addr,
+ c->c_blksz, BUS_DMASYNC_PREWRITE);
+
+ WRITE_REG(sc, HARMONY_PNXTADD, nextaddr);
+ SYNC_REG(sc, HARMONY_PNXTADD, BUS_SPACE_BARRIER_WRITE);
+ c->c_lastaddr = nextaddr + togo;
+ harmony_try_more(sc);
}
dstatus = READ_REG(sc, HARMONY_DSTATUS);
@@ -902,6 +926,8 @@ harmony_trigger_output(void *vsc, void *start, void *end, int blksize,
struct harmony_softc *sc = vsc;
struct harmony_channel *c = &sc->sc_playback;
struct harmony_dma *d;
+ bus_addr_t nextaddr;
+ bus_size_t togo;
for (d = sc->sc_dmas; d->d_kva != start; d = d->d_next)
/*EMPTY*/;
@@ -920,48 +946,31 @@ harmony_trigger_output(void *vsc, void *start, void *end, int blksize,
c->c_lastaddr = d->d_map->dm_segs[0].ds_addr;
sc->sc_playing = 1;
- harmony_start_pb(sc);
- harmony_start_cp(sc);
- harmony_intr_enable(sc);
- return (0);
-}
+ togo = c->c_segsz - c->c_cnt;
+ if (togo == 0) {
+ nextaddr = d->d_map->dm_segs[0].ds_addr;
+ c->c_cnt = togo = c->c_blksz;
+ } else {
+ nextaddr = c->c_lastaddr;
+ if (togo > c->c_blksz)
+ togo = c->c_blksz;
+ c->c_cnt += togo;
+ }
-void
-harmony_start_pb(struct harmony_softc *sc)
-{
- struct harmony_channel *c = &sc->sc_playback;
- struct harmony_dma *d;
- bus_addr_t nextaddr;
- bus_size_t togo;
+ bus_dmamap_sync(sc->sc_dmat, d->d_map,
+ nextaddr - d->d_map->dm_segs[0].ds_addr,
+ c->c_blksz, BUS_DMASYNC_PREWRITE);
- if (sc->sc_playing == 0) {
- WRITE_REG(sc, HARMONY_PNXTADD,
- sc->sc_playback_paddrs[sc->sc_playback_empty]);
- SYNC_REG(sc, HARMONY_PNXTADD, BUS_SPACE_BARRIER_WRITE);
- if (++sc->sc_playback_empty == PLAYBACK_EMPTYS)
- sc->sc_playback_empty = 0;
- } else {
- d = c->c_current;
- togo = c->c_segsz - c->c_cnt;
- if (togo == 0) {
- nextaddr = d->d_map->dm_segs[0].ds_addr;
- c->c_cnt = togo = c->c_blksz;
- } else {
- nextaddr = c->c_lastaddr;
- if (togo > c->c_blksz)
- togo = c->c_blksz;
- c->c_cnt += togo;
- }
+ WRITE_REG(sc, HARMONY_PNXTADD, nextaddr);
+ c->c_theaddr = nextaddr;
+ SYNC_REG(sc, HARMONY_PNXTADD, BUS_SPACE_BARRIER_WRITE);
+ c->c_lastaddr = nextaddr + togo;
- bus_dmamap_sync(sc->sc_dmat, d->d_map,
- nextaddr - d->d_map->dm_segs[0].ds_addr,
- c->c_blksz, BUS_DMASYNC_PREWRITE);
+ harmony_start_cp(sc);
+ harmony_intr_enable(sc);
- WRITE_REG(sc, HARMONY_PNXTADD, nextaddr);
- SYNC_REG(sc, HARMONY_PNXTADD, BUS_SPACE_BARRIER_WRITE);
- c->c_lastaddr = nextaddr + togo;
- }
+ return (0);
}
void
@@ -1025,7 +1034,6 @@ harmony_trigger_input(void *vsc, void *start, void *end, int blksize,
c->c_lastaddr = d->d_map->dm_segs[0].ds_addr;
sc->sc_capturing = 1;
- harmony_start_pb(sc);
harmony_start_cp(sc);
harmony_intr_enable(sc);
return (0);
@@ -1136,6 +1144,42 @@ harmony_set_gainctl(struct harmony_softc *sc)
return (0);
}
+void
+harmony_try_more(struct harmony_softc *sc)
+{
+ struct harmony_channel *c = &sc->sc_playback;
+ struct harmony_dma *d = c->c_current;
+ u_int32_t cur;
+ int i, nsegs;
+
+ cur = bus_space_read_4(sc->sc_bt, sc->sc_bh, HARMONY_PCURADD);
+ cur &= PCURADD_BUFMASK;
+ nsegs = 0;
+
+#ifdef DIAGNOSTIC
+ if (cur < d->d_map->dm_segs[0].ds_addr ||
+ cur >= (d->d_map->dm_segs[0].ds_addr + c->c_segsz))
+ panic("%s: bad current %x < %x || %x > %x", sc->sc_dv.dv_xname,
+ cur, d->d_map->dm_segs[0].ds_addr, cur,
+ d->d_map->dm_segs[0].ds_addr + c->c_segsz);
+#endif /* DIAGNOSTIC */
+
+ if (cur > c->c_theaddr) {
+ nsegs = (cur - c->c_theaddr) / HARMONY_BUFSIZE;
+ } else if (cur < c->c_theaddr) {
+ nsegs = (d->d_map->dm_segs[0].ds_addr + c->c_segsz -
+ c->c_theaddr) / HARMONY_BUFSIZE;
+ nsegs += (cur - d->d_map->dm_segs[0].ds_addr) /
+ HARMONY_BUFSIZE;
+ }
+
+ if (nsegs != 0 && c->c_intr != NULL) {
+ for (i = 0; i < nsegs; i++)
+ (*c->c_intr)(c->c_intrarg);
+ c->c_theaddr = cur;
+ }
+}
+
struct cfdriver harmony_cd = {
NULL, "harmony", DV_DULL
};
diff --git a/sys/arch/hppa/gsc/harmonyreg.h b/sys/arch/hppa/gsc/harmonyreg.h
index 6dbc6a198f0..8e9f2d62ad5 100644
--- a/sys/arch/hppa/gsc/harmonyreg.h
+++ b/sys/arch/hppa/gsc/harmonyreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: harmonyreg.h,v 1.2 2003/01/30 01:23:24 jason Exp $ */
+/* $OpenBSD: harmonyreg.h,v 1.3 2003/02/05 08:47:05 jason Exp $ */
/*
* Copyright (c) 2003 Jason L. Wright (jason@thought.net)
@@ -36,6 +36,9 @@
* "712 I/O Subsystem ERS", Revision 1.1, 12 February 1993
*/
+/* harmony always uses a 4K buffer */
+#define HARMONY_BUFSIZE 4096
+
#define HARMONY_NREGS 0x40
#define HARMONY_ID 0x00 /* identification */
@@ -122,6 +125,12 @@
#define GAINCTL_OUTPUT_RIGHT_S 0
#define GAINCTL_OUTPUT_BITS 6
+/* HARMONY_PCURADD */
+#define PCURADD_BUFMASK (~(HARMONY_BUFSIZE - 1))
+
+/* HARMONY_RCURADD */
+#define PCURADD_BUFMASK (~(HARMONY_BUFSIZE - 1))
+
/* HARMONY_DSTATUS */
#define DSTATUS_IE 0x80000000 /* interrupt enable */
#define DSTATUS_PN 0x00000200 /* playback next empty */
diff --git a/sys/arch/hppa/gsc/harmonyvar.h b/sys/arch/hppa/gsc/harmonyvar.h
index 59085f750be..9ad811dd6ba 100644
--- a/sys/arch/hppa/gsc/harmonyvar.h
+++ b/sys/arch/hppa/gsc/harmonyvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: harmonyvar.h,v 1.3 2003/01/30 03:23:19 mickey Exp $ */
+/* $OpenBSD: harmonyvar.h,v 1.4 2003/02/05 08:47:05 jason Exp $ */
/*
* Copyright (c) 2003 Jason L. Wright (jason@thought.net)
@@ -50,7 +50,6 @@
#define PLAYBACK_EMPTYS 3 /* playback empty buffers */
#define CAPTURE_EMPTYS 3 /* capture empty buffers */
-#define HARMONY_BUFSIZE 4096
struct harmony_volume {
u_char left, right;
@@ -77,6 +76,7 @@ struct harmony_channel {
bus_addr_t c_lastaddr;
void (*c_intr)(void *);
void *c_intrarg;
+ bus_addr_t c_theaddr;
};
struct harmony_softc {