Module Name: src
Committed By: isaki
Date: Sat Sep 2 12:52:55 UTC 2017
Modified Files:
src/sys/arch/x68k/dev: vs.c vsvar.h
Log Message:
- Revert temporary local conversion introduced at rev 1.43.
- But does not revert to trigger method. trigger method is not suitable for
x68k ADPCM+DMA mechanism.
- Don't (re)start ADPCM when DMA is running. This solves the noise.
From Y.Sugahara.
- Cache dmac xfer.
To generate a diff of this commit:
cvs rdiff -u -r1.46 -r1.47 src/sys/arch/x68k/dev/vs.c
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/x68k/dev/vsvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/x68k/dev/vs.c
diff -u src/sys/arch/x68k/dev/vs.c:1.46 src/sys/arch/x68k/dev/vs.c:1.47
--- src/sys/arch/x68k/dev/vs.c:1.46 Fri Aug 11 07:08:40 2017
+++ src/sys/arch/x68k/dev/vs.c Sat Sep 2 12:52:55 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: vs.c,v 1.46 2017/08/11 07:08:40 isaki Exp $ */
+/* $NetBSD: vs.c,v 1.47 2017/09/02 12:52:55 isaki Exp $ */
/*
* Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vs.c,v 1.46 2017/08/11 07:08:40 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vs.c,v 1.47 2017/09/02 12:52:55 isaki Exp $");
#include "audio.h"
#include "vs.h"
@@ -101,7 +101,6 @@ static void vs_get_locks(void *, kmutex_
static int vs_round_sr(u_long);
static void vs_set_sr(struct vs_softc *, int);
static inline void vs_set_po(struct vs_softc *, u_long);
-static void *vs_realloc_hwbuf(struct vs_softc *, int);
extern struct cfdriver vs_cd;
@@ -130,8 +129,8 @@ static const struct audio_hw_if vs_hw_if
vs_set_port,
vs_get_port,
vs_query_devinfo,
- NULL, /* allocm */
- NULL, /* freem */
+ vs_allocm,
+ vs_freem,
vs_round_buffersize,
NULL, /* mappage */
vs_get_props,
@@ -161,6 +160,8 @@ struct {
#define NUM_RATE (sizeof(vs_l2r)/sizeof(vs_l2r[0]))
+extern stream_filter_factory_t null_filter;
+
static int
vs_match(device_t parent, cfdata_t cf, void *aux)
{
@@ -220,10 +221,8 @@ vs_attach(device_t parent, device_t self
sc->sc_hw_if = &vs_hw_if;
sc->sc_addr = (void *) ia->ia_addr;
sc->sc_dmas = NULL;
+ sc->sc_prev_vd = NULL;
sc->sc_active = 0;
- sc->sc_hwbuf = NULL;
- sc->sc_hwbufsize = 0;
- sc->sc_codec = vs_alloc_msm6258codec();
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
@@ -257,13 +256,9 @@ vs_dmaintr(void *hdl)
mutex_spin_enter(&sc->sc_intr_lock);
- sc->sc_active = 0;
if (sc->sc_pintr) {
sc->sc_pintr(sc->sc_parg);
} else if (sc->sc_rintr) {
- /* convert ADPCM to slinear */
- sc->sc_rconv(sc->sc_codec, sc->sc_current.rblock,
- sc->sc_current.blksize, sc->sc_hwbuf);
sc->sc_rintr(sc->sc_rarg);
} else {
printf("vs_dmaintr: spurious interrupt\n");
@@ -301,6 +296,7 @@ vs_open(void *hdl, int flags)
sc = hdl;
sc->sc_pintr = NULL;
sc->sc_rintr = NULL;
+ sc->sc_active = 0;
return 0;
}
@@ -369,6 +365,8 @@ vs_set_params(void *hdl, int setmode, in
stream_filter_list_t *pfil, stream_filter_list_t *rfil)
{
struct vs_softc *sc;
+ stream_filter_factory_t *pconv;
+ stream_filter_factory_t *rconv;
int rate;
sc = hdl;
@@ -391,16 +389,12 @@ vs_set_params(void *hdl, int setmode, in
}
if (play->precision == 8 && play->encoding == AUDIO_ENCODING_SLINEAR) {
- sc->sc_current.precision = 8;
- sc->sc_pconv = vs_slinear8_to_adpcm;
- sc->sc_rconv = vs_adpcm_to_slinear8;
-
+ pconv = msm6258_linear8_to_adpcm;
+ rconv = msm6258_adpcm_to_linear8;
} else if (play->precision == 16 &&
play->encoding == AUDIO_ENCODING_SLINEAR_BE) {
- sc->sc_current.precision = 16;
- sc->sc_pconv = vs_slinear16be_to_adpcm;
- sc->sc_rconv = vs_adpcm_to_slinear16be;
-
+ pconv = msm6258_slinear16_to_adpcm;
+ rconv = msm6258_adpcm_to_slinear16;
} else {
DPRINTF(1, ("prec/enc not matched\n"));
return EINVAL;
@@ -410,11 +404,20 @@ vs_set_params(void *hdl, int setmode, in
/* pfil and rfil are independent even if !AUDIO_PROP_INDEPENDENT */
- /*
- * XXX MI audio(4) layer does not seem to support non SLINEAR devices.
- * So vs(4) behaves as SLINEAR device completely against MI layer
- * and converts SLINEAR <-> ADPCM by myself.
- */
+ if ((setmode & AUMODE_PLAY) != 0) {
+ pfil->append(pfil, null_filter, play);
+ play->encoding = AUDIO_ENCODING_ADPCM;
+ play->validbits = 4;
+ play->precision = 4;
+ pfil->append(pfil, pconv, play);
+ }
+ if ((setmode & AUMODE_RECORD) != 0) {
+ rfil->append(rfil, null_filter, rec);
+ rec->encoding = AUDIO_ENCODING_ADPCM;
+ rec->validbits = 4;
+ rec->precision = 4;
+ rfil->append(rfil, rconv, rec);
+ }
DPRINTF(1, ("accepted\n"));
return 0;
@@ -470,22 +473,6 @@ vs_init_input(void *hdl, void *buffer, i
return 0;
}
-/* (re)allocate sc_hwbuf with hwbufsize */
-static void *
-vs_realloc_hwbuf(struct vs_softc *sc, int hwbufsize)
-{
- if (sc->sc_hwbuf != NULL) {
- vs_freem(sc, sc->sc_hwbuf, sc->sc_hwbufsize);
- }
- sc->sc_hwbufsize = hwbufsize;
- sc->sc_hwbuf = vs_allocm(sc, 0, sc->sc_hwbufsize);
- if (sc->sc_hwbuf == NULL) {
- sc->sc_hwbufsize = 0;
- return NULL;
- }
- return sc->sc_hwbuf;
-}
-
static int
vs_start_output(void *hdl, void *block, int blksize, void (*intr)(void *),
void *arg)
@@ -493,42 +480,40 @@ vs_start_output(void *hdl, void *block,
struct vs_softc *sc;
struct vs_dma *vd;
struct dmac_channel_stat *chan;
- int hwblksize;
DPRINTF(2, ("%s: block=%p blksize=%d\n", __func__, block, blksize));
sc = hdl;
- hwblksize = blksize / (sc->sc_current.precision / 4);
- if (hwblksize > sc->sc_hwbufsize) {
- if (vs_realloc_hwbuf(sc, hwblksize) == NULL) {
- DPRINTF(1, ("%s: alloc hwbuf failed\n", __func__));
- return ENOMEM;
- }
- }
-
- /* Convert slinear to ADPCM */
- sc->sc_pconv(sc->sc_codec, sc->sc_hwbuf, block, blksize);
-
sc->sc_pintr = intr;
sc->sc_parg = arg;
- sc->sc_current.blksize = hwblksize;
- sc->sc_current.bufsize = hwblksize;
- sc->sc_current.dmap = 0;
- /* vd is always first of sc_dmas */
- vd = sc->sc_dmas;
+ /* Find DMA buffer. */
+ for (vd = sc->sc_dmas; vd != NULL; vd = vd->vd_next) {
+ if (KVADDR(vd) <= block && block < KVADDR_END(vd)
+ break;
+ }
+ if (vd == NULL) {
+ printf("%s: start_output: bad addr %p\n",
+ device_xname(sc->sc_dev), block);
+ return EINVAL;
+ }
chan = sc->sc_dma_ch;
- sc->sc_current.xfer = dmac_prepare_xfer(chan, sc->sc_dmat, vd->vd_map,
- DMAC_OCR_DIR_MTD,
- (DMAC_SCR_MAC_COUNT_UP | DMAC_SCR_DAC_NO_COUNT),
- sc->sc_addr + MSM6258_DATA * 2 + 1);
-
- dmac_start_xfer_offset(chan->ch_softc, sc->sc_current.xfer, 0,
- sc->sc_current.blksize);
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 2);
- sc->sc_active = 1;
+ if (vd != sc->sc_prev_vd) {
+ sc->sc_current.xfer = dmac_prepare_xfer(chan, sc->sc_dmat,
+ vd->vd_map, DMAC_OCR_DIR_MTD,
+ (DMAC_SCR_MAC_COUNT_UP | DMAC_SCR_DAC_NO_COUNT),
+ sc->sc_addr + MSM6258_DATA * 2 + 1);
+ sc->sc_prev_vd = vd;
+ }
+ dmac_start_xfer_offset(chan->ch_softc, sc->sc_current.xfer,
+ (int)block - (int)KVADDR(vd), blksize);
+
+ if (sc->sc_active == 0) {
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 2);
+ sc->sc_active = 1;
+ }
return 0;
}
@@ -540,40 +525,40 @@ vs_start_input(void *hdl, void *block, i
struct vs_softc *sc;
struct vs_dma *vd;
struct dmac_channel_stat *chan;
- int hwblksize;
DPRINTF(2, ("%s: block=%p blksize=%d\n", __func__, block, blksize));
sc = hdl;
- hwblksize = blksize / (sc->sc_current.precision / 4);
- if (hwblksize > sc->sc_hwbufsize) {
- if (vs_realloc_hwbuf(sc, hwblksize) == NULL) {
- DPRINTF(1, ("%s: alloc hwbuf failed\n", __func__));
- return ENOMEM;
- }
- }
-
sc->sc_rintr = intr;
sc->sc_rarg = arg;
- sc->sc_current.rblock = block;
- sc->sc_current.blksize = hwblksize;
- sc->sc_current.bufsize = hwblksize;
- sc->sc_current.dmap = 0;
- /* vd is always first of sc_dmas */
- vd = sc->sc_dmas;
+ /* Find DMA buffer. */
+ for (vd = sc->sc_dmas; vd != NULL; vd = vd->vd_next) {
+ if (KVADDR(vd) <= block && block < KVADDR_END(vd)
+ break;
+ }
+ if (vd == NULL) {
+ printf("%s: start_output: bad addr %p\n",
+ device_xname(sc->sc_dev), block);
+ return EINVAL;
+ }
chan = sc->sc_dma_ch;
- sc->sc_current.xfer = dmac_prepare_xfer(chan, sc->sc_dmat, vd->vd_map,
- DMAC_OCR_DIR_DTM,
- (DMAC_SCR_MAC_COUNT_UP | DMAC_SCR_DAC_NO_COUNT),
- sc->sc_addr + MSM6258_DATA * 2 + 1);
-
- dmac_start_xfer_offset(chan->ch_softc, sc->sc_current.xfer, 0,
- sc->sc_current.blksize);
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 4);
- sc->sc_active = 1;
+ if (vd != sc->sc_prev_vd) {
+ sc->sc_current.xfer = dmac_prepare_xfer(chan, sc->sc_dmat,
+ vd->vd_map, DMAC_OCR_DIR_DTM,
+ (DMAC_SCR_MAC_COUNT_UP | DMAC_SCR_DAC_NO_COUNT),
+ sc->sc_addr + MSM6258_DATA * 2 + 1);
+ sc->sc_prev_vd = vd;
+ }
+ dmac_start_xfer_offset(chan->ch_softc, sc->sc_current.xfer,
+ (int)block - (int)KVADDR(vd), blksize);
+
+ if (sc->sc_active == 0) {
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 4);
+ sc->sc_active = 1;
+ }
return 0;
}
@@ -591,9 +576,6 @@ vs_halt_output(void *hdl)
bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 1);
sc->sc_active = 0;
}
- vs_freem(sc, sc->sc_hwbuf, sc->sc_hwbufsize);
- sc->sc_hwbuf = NULL;
- sc->sc_hwbufsize = 0;
return 0;
}
@@ -611,9 +593,6 @@ vs_halt_input(void *hdl)
bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 1);
sc->sc_active = 0;
}
- vs_freem(sc, sc->sc_hwbuf, sc->sc_hwbufsize);
- sc->sc_hwbuf = NULL;
- sc->sc_hwbufsize = 0;
return 0;
}
Index: src/sys/arch/x68k/dev/vsvar.h
diff -u src/sys/arch/x68k/dev/vsvar.h:1.14 src/sys/arch/x68k/dev/vsvar.h:1.15
--- src/sys/arch/x68k/dev/vsvar.h:1.14 Sat Aug 5 06:05:37 2017
+++ src/sys/arch/x68k/dev/vsvar.h Sat Sep 2 12:52:55 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: vsvar.h,v 1.14 2017/08/05 06:05:37 isaki Exp $ */
+/* $NetBSD: vsvar.h,v 1.15 2017/09/02 12:52:55 isaki Exp $ */
/*
* Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
@@ -72,6 +72,7 @@ struct vs_dma {
struct vs_dma *vd_next;
};
#define KVADDR(dma) ((void *)(dma)->vd_addr)
+#define KVADDR_END(dma) ((void *)((size_t)KVADDR(dma) + (dma)->vd_size)))
#define DMAADDR(dma) ((dma)->vd_map->dm_segs[0].ds_addr)
struct vs_softc {
@@ -87,14 +88,11 @@ struct vs_softc {
bus_dma_tag_t sc_dmat;
struct dmac_channel_stat *sc_dma_ch;
struct vs_dma *sc_dmas;
+ struct vs_dma *sc_prev_vd;
struct {
struct dmac_dma_xfer *xfer;
int rate;
- int precision;
- int bufsize, blksize;
- int dmap;
- void *rblock; /* block specified by start_input() */
} sc_current;
int sc_active;
@@ -104,11 +102,4 @@ struct vs_softc {
void (*sc_rintr)(void *);
void *sc_parg;
void *sc_rarg;
-
- /* local conversion */
- void (*sc_pconv)(void *, void *, const void *, int);
- void (*sc_rconv)(void *, void *, int, const void *);
- void *sc_hwbuf; /* ADPCM buffer */
- int sc_hwbufsize; /* buffer size */
- void *sc_codec; /* msm6258codecvar */
};