Get audio capture fully working with harmony(4) and fix PR/35239.

skrll@ reports that with this patch he can record and playback audio.
Suprisingly the bug was actually with playback and not with capture.
When not capturing or playing audio we write to or read from "empty
buffers", the problem was that playback and capture were using the same
buffer and the playback code managed to pick up a bit of data that was
written from the capture code.
This commit is contained in:
mjf 2009-04-15 20:07:58 +00:00
parent 3d2a48dd46
commit b6791e4a2a
1 changed files with 38 additions and 14 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: harmony.c,v 1.13 2008/09/23 14:07:11 mjf Exp $ */
/* $NetBSD: harmony.c,v 1.14 2009/04/15 20:07:58 mjf Exp $ */
/* $OpenBSD: harmony.c,v 1.23 2004/02/13 21:28:19 mickey Exp $ */
@ -133,6 +133,8 @@ void harmony_tick_pb(void *);
void harmony_tick_cp(void *);
void harmony_try_more(struct harmony_softc *, int, int,
struct harmony_channel *);
static void harmony_empty_input(struct harmony_softc *);
static void harmony_empty_output(struct harmony_softc *);
#if NRND > 0
void harmony_acc_tmo(void *);
@ -243,7 +245,7 @@ harmony_attach(device_t parent, device_t self, void *aux)
for (i = 0; i < CAPTURE_EMPTYS; i++)
sc->sc_capture_paddrs[i] =
sc->sc_empty_map->dm_segs[0].ds_addr +
offsetof(struct harmony_empty, playback[i][0]);
offsetof(struct harmony_empty, capture[i][0]);
bus_dmamap_sync(sc->sc_dmat, sc->sc_empty_map,
offsetof(struct harmony_empty, playback[0][0]),
@ -663,6 +665,18 @@ harmony_commit_settings(void *vsc)
return 0;
}
static void
harmony_empty_output(struct harmony_softc *sc)
{
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;
}
int
harmony_halt_output(void *vsc)
{
@ -670,9 +684,23 @@ harmony_halt_output(void *vsc)
sc = vsc;
sc->sc_playing = 0;
harmony_empty_output(sc);
return 0;
}
static void
harmony_empty_input(struct harmony_softc *sc)
{
WRITE_REG(sc, HARMONY_RNXTADD,
sc->sc_capture_paddrs[sc->sc_capture_empty]);
SYNC_REG(sc, HARMONY_RNXTADD, BUS_SPACE_BARRIER_WRITE);
if (++sc->sc_capture_empty == CAPTURE_EMPTYS)
sc->sc_capture_empty = 0;
}
int
harmony_halt_input(void *vsc)
{
@ -680,6 +708,8 @@ harmony_halt_input(void *vsc)
sc = vsc;
sc->sc_capturing = 0;
harmony_empty_input(sc);
return 0;
}
@ -1097,12 +1127,9 @@ harmony_start_cp(struct harmony_softc *sc, int start)
bus_size_t togo;
c = &sc->sc_capture;
if (sc->sc_capturing == 0) {
WRITE_REG(sc, HARMONY_RNXTADD,
sc->sc_capture_paddrs[sc->sc_capture_empty]);
if (++sc->sc_capture_empty == CAPTURE_EMPTYS)
sc->sc_capture_empty = 0;
} else {
if (sc->sc_capturing == 0)
harmony_empty_input(sc);
else {
d = c->c_current;
togo = c->c_segsz - c->c_cnt;
if (togo == 0) {
@ -1143,12 +1170,9 @@ harmony_start_pp(struct harmony_softc *sc, int start)
bus_size_t togo;
c = &sc->sc_playback;
if (sc->sc_playing == 0) {
WRITE_REG(sc, HARMONY_PNXTADD,
sc->sc_playback_paddrs[sc->sc_playback_empty]);
if (++sc->sc_playback_empty == PLAYBACK_EMPTYS)
sc->sc_playback_empty = 0;
} else {
if (sc->sc_playing == 0)
harmony_empty_output(sc);
else {
d = c->c_current;
togo = c->c_segsz - c->c_cnt;
if (togo == 0) {