Correct playing mu-law and linear.
This commit is contained in:
parent
5c15afd718
commit
58b62ea0cf
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: vs.c,v 1.1 2001/05/02 13:00:20 minoura Exp $ */
|
/* $NetBSD: vs.c,v 1.2 2001/05/03 02:09:12 minoura Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
|
* Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
|
||||||
|
@ -100,8 +100,8 @@ static size_t vs_round_buffersize __P((void *, int, size_t));
|
||||||
static int vs_get_props __P((void *));
|
static int vs_get_props __P((void *));
|
||||||
|
|
||||||
/* lower functions */
|
/* lower functions */
|
||||||
static u_long vs_round_sr(u_long);
|
static int vs_round_sr(u_long);
|
||||||
static void vs_set_sr(struct vs_softc *sc, u_long);
|
static void vs_set_sr(struct vs_softc *sc, int);
|
||||||
static inline void vs_set_po(struct vs_softc *sc, u_long);
|
static inline void vs_set_po(struct vs_softc *sc, u_long);
|
||||||
static int adpcm_estimindex[];
|
static int adpcm_estimindex[];
|
||||||
static int adpcm_estim[];
|
static int adpcm_estim[];
|
||||||
|
@ -160,18 +160,18 @@ static struct audio_device vs_device = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u_long low;
|
|
||||||
u_long rate;
|
u_long rate;
|
||||||
u_char clk;
|
u_char clk;
|
||||||
u_char den;
|
u_char den;
|
||||||
} vs_l2r[] = {
|
} vs_l2r[] = {
|
||||||
{ 13021, VS_RATE_15K, VS_CLK_8MHZ, VS_SRATE_512 },
|
{ VS_RATE_15K, VS_CLK_8MHZ, VS_SRATE_512 },
|
||||||
{ 9115, VS_RATE_10K, VS_CLK_8MHZ, VS_SRATE_768 },
|
{ VS_RATE_10K, VS_CLK_8MHZ, VS_SRATE_768 },
|
||||||
{ 6510, VS_RATE_7K, VS_CLK_8MHZ, VS_SRATE_1024},
|
{ VS_RATE_7K, VS_CLK_8MHZ, VS_SRATE_1024},
|
||||||
{ 4557, VS_RATE_5K, VS_CLK_4MHZ, VS_SRATE_768 },
|
{ VS_RATE_5K, VS_CLK_4MHZ, VS_SRATE_768 },
|
||||||
{ 0, VS_RATE_3K, VS_CLK_4MHZ, VS_SRATE_1024}
|
{ VS_RATE_3K, VS_CLK_4MHZ, VS_SRATE_1024}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NUM_RATE (sizeof(vs_l2r)/sizeof(vs_l2r[0]))
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vs_match(struct device *parent, struct cfdata *cf, void *aux)
|
vs_match(struct device *parent, struct cfdata *cf, void *aux)
|
||||||
|
@ -258,24 +258,24 @@ vs_dmaintr(void *hdl)
|
||||||
|
|
||||||
if (sc->sc_pintr) {
|
if (sc->sc_pintr) {
|
||||||
/* start next transfer */
|
/* start next transfer */
|
||||||
sc->sc_current.dmap += sc->sc_current.rawblk;
|
sc->sc_current.dmap += sc->sc_current.blksize;
|
||||||
if (sc->sc_current.dmap + sc->sc_current.rawblk
|
if (sc->sc_current.dmap + sc->sc_current.blksize
|
||||||
> sc->sc_current.bufsize)
|
> sc->sc_current.bufsize)
|
||||||
sc->sc_current.dmap -= sc->sc_current.bufsize;
|
sc->sc_current.dmap -= sc->sc_current.bufsize;
|
||||||
dmac_start_xfer_offset (sc->sc_dma_ch->ch_softc,
|
dmac_start_xfer_offset (sc->sc_dma_ch->ch_softc,
|
||||||
sc->sc_current.xfer,
|
sc->sc_current.xfer,
|
||||||
sc->sc_current.dmap,
|
sc->sc_current.dmap,
|
||||||
sc->sc_current.hwblk);
|
sc->sc_current.blksize);
|
||||||
sc->sc_pintr(sc->sc_parg);
|
sc->sc_pintr(sc->sc_parg);
|
||||||
} else if (sc->sc_rintr) {
|
} else if (sc->sc_rintr) {
|
||||||
/* start next transfer */
|
/* start next transfer */
|
||||||
sc->sc_current.dmap += sc->sc_current.rawblk;
|
sc->sc_current.dmap += sc->sc_current.blksize;
|
||||||
if (sc->sc_current.dmap + sc->sc_current.rawblk
|
if (sc->sc_current.dmap + sc->sc_current.blksize
|
||||||
>= sc->sc_current.bufsize)
|
>= sc->sc_current.bufsize)
|
||||||
dmac_start_xfer_offset (sc->sc_dma_ch->ch_softc,
|
dmac_start_xfer_offset (sc->sc_dma_ch->ch_softc,
|
||||||
sc->sc_current.xfer,
|
sc->sc_current.xfer,
|
||||||
sc->sc_current.dmap,
|
sc->sc_current.dmap,
|
||||||
sc->sc_current.hwblk);
|
sc->sc_current.blksize);
|
||||||
sc->sc_rintr(sc->sc_rarg);
|
sc->sc_rintr(sc->sc_rarg);
|
||||||
} else {
|
} else {
|
||||||
printf ("vs_dmaintr: spurious interrupt\n");
|
printf ("vs_dmaintr: spurious interrupt\n");
|
||||||
|
@ -349,15 +349,30 @@ vs_query_encoding(void *hdl, struct audio_encoding *fp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u_long
|
static int
|
||||||
vs_round_sr(u_long rate)
|
vs_round_sr(u_long rate)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 5; i++) {
|
int diff = rate;
|
||||||
if (rate >= vs_l2r[i].low)
|
int nearest = 0;
|
||||||
return vs_l2r[i].rate;
|
|
||||||
|
for (i = 0; i < NUM_RATE; i++) {
|
||||||
|
if (rate >= vs_l2r[i].rate) {
|
||||||
|
if (rate - vs_l2r[i].rate < diff) {
|
||||||
|
diff = rate - vs_l2r[i].rate;
|
||||||
|
nearest = i;
|
||||||
}
|
}
|
||||||
/*NOTREACHED*/
|
} else {
|
||||||
|
if (vs_l2r[i].rate - rate < diff) {
|
||||||
|
diff = vs_l2r[i].rate - rate;
|
||||||
|
nearest = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (diff * 100 / rate > 15)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return nearest;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -367,10 +382,10 @@ vs_set_params(void *hdl, int setmode, int usemode,
|
||||||
struct vs_softc *sc = hdl;
|
struct vs_softc *sc = hdl;
|
||||||
struct audio_params *p;
|
struct audio_params *p;
|
||||||
int mode;
|
int mode;
|
||||||
|
int rate;
|
||||||
|
|
||||||
DPRINTF(("vs_set_params: setmode=%d, usemode=%d\n", setmode, usemode));
|
DPRINTF(("vs_set_params: setmode=%d, usemode=%d\n", setmode, usemode));
|
||||||
|
|
||||||
sc->sc_current.pdenom = 1;
|
|
||||||
/* set first record info, then play info */
|
/* set first record info, then play info */
|
||||||
for (mode = AUMODE_RECORD; mode != -1;
|
for (mode = AUMODE_RECORD; mode != -1;
|
||||||
mode = (mode == AUMODE_RECORD) ? AUMODE_PLAY : -1) {
|
mode = (mode == AUMODE_RECORD) ? AUMODE_PLAY : -1) {
|
||||||
|
@ -382,8 +397,7 @@ vs_set_params(void *hdl, int setmode, int usemode,
|
||||||
if (p->channels != 1)
|
if (p->channels != 1)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
p->sample_rate = vs_round_sr(p->sample_rate);
|
rate = p->sample_rate;
|
||||||
|
|
||||||
p->sw_code = NULL;
|
p->sw_code = NULL;
|
||||||
p->factor = 1;
|
p->factor = 1;
|
||||||
switch (p->encoding) {
|
switch (p->encoding) {
|
||||||
|
@ -392,7 +406,7 @@ vs_set_params(void *hdl, int setmode, int usemode,
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
if (mode == AUMODE_PLAY) {
|
if (mode == AUMODE_PLAY) {
|
||||||
p->sw_code = msm6258_mulaw_to_adpcm;
|
p->sw_code = msm6258_mulaw_to_adpcm;
|
||||||
sc->sc_current.pdenom = 2;
|
rate = p->sample_rate * 2;
|
||||||
} else {
|
} else {
|
||||||
p->sw_code = msm6258_adpcm_to_mulaw;
|
p->sw_code = msm6258_adpcm_to_mulaw;
|
||||||
p->factor = 2;
|
p->factor = 2;
|
||||||
|
@ -404,7 +418,7 @@ vs_set_params(void *hdl, int setmode, int usemode,
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
if (mode == AUMODE_PLAY) {
|
if (mode == AUMODE_PLAY) {
|
||||||
p->sw_code = msm6258_ulinear8_to_adpcm;
|
p->sw_code = msm6258_ulinear8_to_adpcm;
|
||||||
sc->sc_current.pdenom = 2;
|
rate = p->sample_rate * 2;
|
||||||
} else {
|
} else {
|
||||||
p->sw_code = msm6258_adpcm_to_ulinear8;
|
p->sw_code = msm6258_adpcm_to_ulinear8;
|
||||||
p->factor = 2;
|
p->factor = 2;
|
||||||
|
@ -413,34 +427,34 @@ vs_set_params(void *hdl, int setmode, int usemode,
|
||||||
case AUDIO_ENCODING_ADPCM:
|
case AUDIO_ENCODING_ADPCM:
|
||||||
if (p->precision != 4)
|
if (p->precision != 4)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
p->sw_code = NULL;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DPRINTF(("vs_set_params: mode=%d, encoding=%d\n",
|
DPRINTF(("vs_set_params: mode=%d, encoding=%d\n",
|
||||||
mode, p->encoding));
|
mode, p->encoding));
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
|
rate = vs_round_sr(rate);
|
||||||
|
if (rate < 0)
|
||||||
|
return (EINVAL);
|
||||||
|
if (mode == AUMODE_PLAY)
|
||||||
|
sc->sc_current.prate = rate;
|
||||||
|
else
|
||||||
|
sc->sc_current.rrate = rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vs_set_sr(struct vs_softc *sc, u_long rate)
|
vs_set_sr(struct vs_softc *sc, int rate)
|
||||||
{
|
{
|
||||||
int i;
|
DPRINTF(("setting sample rate to %d, %d\n",
|
||||||
for (i = 0; i < 5; i++) {
|
rate, (int)vs_l2r[rate].rate));
|
||||||
if (rate >= vs_l2r[i].low) {
|
|
||||||
bus_space_write_1(sc->sc_iot, sc->sc_ppi, PPI_PORTC,
|
bus_space_write_1(sc->sc_iot, sc->sc_ppi, PPI_PORTC,
|
||||||
(bus_space_read_1 (sc->sc_iot,
|
(bus_space_read_1 (sc->sc_iot, sc->sc_ppi,
|
||||||
sc->sc_ppi,
|
|
||||||
PPI_PORTC) & 0xf0)
|
PPI_PORTC) & 0xf0)
|
||||||
| vs_l2r[i].den);
|
| vs_l2r[rate].den);
|
||||||
adpcm_chgclk(vs_l2r[i].clk);
|
adpcm_chgclk(vs_l2r[rate].clk);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -467,8 +481,7 @@ vs_trigger_output(void *hdl, void *start, void *end, int bsize,
|
||||||
|
|
||||||
sc->sc_pintr = intr;
|
sc->sc_pintr = intr;
|
||||||
sc->sc_parg = arg;
|
sc->sc_parg = arg;
|
||||||
sc->sc_current.rawblk = bsize;
|
sc->sc_current.blksize = bsize;
|
||||||
sc->sc_current.hwblk = bsize / sc->sc_current.pdenom;;
|
|
||||||
sc->sc_current.bufsize = (char*)end - (char*)start;
|
sc->sc_current.bufsize = (char*)end - (char*)start;
|
||||||
sc->sc_current.dmap = 0;
|
sc->sc_current.dmap = 0;
|
||||||
|
|
||||||
|
@ -482,8 +495,9 @@ vs_trigger_output(void *hdl, void *start, void *end, int bsize,
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
vs_set_sr(sc, p->sample_rate);
|
vs_set_sr(sc, sc->sc_current.prate);
|
||||||
vs_set_po(sc, VS_PANOUT_LR);
|
vs_set_po(sc, VS_PANOUT_LR);
|
||||||
|
|
||||||
xf = dmac_alloc_xfer (chan, sc->sc_dmat, vd->vd_map);
|
xf = dmac_alloc_xfer (chan, sc->sc_dmat, vd->vd_map);
|
||||||
sc->sc_current.xfer = xf;
|
sc->sc_current.xfer = xf;
|
||||||
chan->ch_dcr = (DMAC_DCR_XRM_CSWOH | DMAC_DCR_OTYP_EASYNC |
|
chan->ch_dcr = (DMAC_DCR_XRM_CSWOH | DMAC_DCR_OTYP_EASYNC |
|
||||||
|
@ -492,10 +506,9 @@ vs_trigger_output(void *hdl, void *start, void *end, int bsize,
|
||||||
xf->dx_ocr = DMAC_OCR_DIR_MTD;
|
xf->dx_ocr = DMAC_OCR_DIR_MTD;
|
||||||
xf->dx_scr = DMAC_SCR_MAC_COUNT_UP | DMAC_SCR_DAC_NO_COUNT;
|
xf->dx_scr = DMAC_SCR_MAC_COUNT_UP | DMAC_SCR_DAC_NO_COUNT;
|
||||||
xf->dx_device = sc->sc_addr + MSM6258_DATA*2 + 1;
|
xf->dx_device = sc->sc_addr + MSM6258_DATA*2 + 1;
|
||||||
if (sc->sc_current.pdenom == 2)
|
|
||||||
chan->ch_ocr |= DMAC_OCR_SIZE_BYTE_NOPACK;
|
|
||||||
dmac_load_xfer (chan->ch_softc, xf);
|
dmac_load_xfer (chan->ch_softc, xf);
|
||||||
dmac_start_xfer_offset (chan->ch_softc, xf, 0, sc->sc_current.hwblk);
|
dmac_start_xfer_offset (chan->ch_softc, xf, 0, sc->sc_current.blksize);
|
||||||
bus_space_write_1 (sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 2);
|
bus_space_write_1 (sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 2);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -508,6 +521,8 @@ vs_trigger_input(void *hdl, void *start, void *end, int bsize,
|
||||||
{
|
{
|
||||||
struct vs_softc *sc = hdl;
|
struct vs_softc *sc = hdl;
|
||||||
struct vs_dma *vd;
|
struct vs_dma *vd;
|
||||||
|
struct dmac_dma_xfer *xf;
|
||||||
|
struct dmac_channel_stat *chan = sc->sc_dma_ch;
|
||||||
|
|
||||||
DPRINTF(("vs_trigger_input\n"));
|
DPRINTF(("vs_trigger_input\n"));
|
||||||
DPRINTF(("trigger_input: start=%p, bsize=%d, intr=%p, arg=%p\n",
|
DPRINTF(("trigger_input: start=%p, bsize=%d, intr=%p, arg=%p\n",
|
||||||
|
@ -515,8 +530,7 @@ vs_trigger_input(void *hdl, void *start, void *end, int bsize,
|
||||||
|
|
||||||
sc->sc_rintr = intr;
|
sc->sc_rintr = intr;
|
||||||
sc->sc_rarg = arg;
|
sc->sc_rarg = arg;
|
||||||
sc->sc_current.rawblk = bsize;
|
sc->sc_current.blksize = bsize;
|
||||||
sc->sc_current.hwblk = bsize;
|
|
||||||
sc->sc_current.bufsize = (char*)end - (char*)start;
|
sc->sc_current.bufsize = (char*)end - (char*)start;
|
||||||
sc->sc_current.dmap = 0;
|
sc->sc_current.dmap = 0;
|
||||||
|
|
||||||
|
@ -530,14 +544,18 @@ vs_trigger_input(void *hdl, void *start, void *end, int bsize,
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
vs_set_sr(sc, p->sample_rate);
|
vs_set_sr(sc, sc->sc_current.rrate);
|
||||||
sc->sc_current.xfer
|
xf = dmac_alloc_xfer (chan, sc->sc_dmat, vd->vd_map);
|
||||||
= dmac_prepare_xfer (sc->sc_dma_ch, sc->sc_dmat, vd->vd_map,
|
sc->sc_current.xfer = xf;
|
||||||
DMAC_OCR_DIR_DTM,
|
chan->ch_dcr = (DMAC_DCR_XRM_CSWOH | DMAC_DCR_OTYP_EASYNC |
|
||||||
DMAC_SCR_MAC_COUNT_UP | DMAC_SCR_DAC_NO_COUNT,
|
DMAC_DCR_OPS_8BIT);
|
||||||
sc->sc_addr + MSM6258_DATA*2);
|
chan->ch_ocr = DMAC_OCR_REQG_EXTERNAL;
|
||||||
dmac_start_xfer_offset (sc->sc_dma_ch->ch_softc, sc->sc_current.xfer,
|
xf->dx_ocr = DMAC_OCR_DIR_DTM;
|
||||||
0, sc->sc_current.hwblk);
|
xf->dx_scr = DMAC_SCR_MAC_COUNT_UP | DMAC_SCR_DAC_NO_COUNT;
|
||||||
|
xf->dx_device = sc->sc_addr + MSM6258_DATA*2 + 1;
|
||||||
|
|
||||||
|
dmac_load_xfer (chan->ch_softc, xf);
|
||||||
|
dmac_start_xfer_offset (chan->ch_softc, xf, 0, sc->sc_current.blksize);
|
||||||
bus_space_write_1 (sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 4);
|
bus_space_write_1 (sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 4);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: vsvar.h,v 1.1 2001/05/02 13:00:20 minoura Exp $ */
|
/* $NetBSD: vsvar.h,v 1.2 2001/05/03 02:09:12 minoura Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
|
* Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
|
||||||
|
@ -95,8 +95,8 @@ struct vs_softc {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct dmac_dma_xfer *xfer;
|
struct dmac_dma_xfer *xfer;
|
||||||
int pdenom;
|
int prate, rrate;
|
||||||
int bufsize, rawblk, hwblk;
|
int bufsize, blksize;
|
||||||
int dmap;
|
int dmap;
|
||||||
} sc_current;
|
} sc_current;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: msm6258.c,v 1.2 2001/05/02 13:34:33 minoura Exp $ */
|
/* $NetBSD: msm6258.c,v 1.3 2001/05/03 02:09:11 minoura Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
|
* Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
|
||||||
|
@ -133,10 +133,9 @@ msm6258_ulinear8_to_adpcm(void *hdl, u_char *p, int cc)
|
||||||
register int i;
|
register int i;
|
||||||
u_char f;
|
u_char f;
|
||||||
|
|
||||||
for (i = 0; i < cc; i += 2) {
|
for (i = 0; i < cc; i++) {
|
||||||
f = pcm2adpcm_step(p[i], y, x);
|
f = pcm2adpcm_step(p[i], y, x);
|
||||||
p[i] = f + (pcm2adpcm_step(p[i+1], y, x) << 4);
|
p[i] = f + (pcm2adpcm_step(p[i], y, x) << 4);
|
||||||
p[i+1] = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue