Various:
* Snap the sample rate when setting it, and remember only the time constant. * Set the time constant when changing between play/record. * Always return the actual sample rate with AUDIO_GETINFO.
This commit is contained in:
parent
19f59bf3c2
commit
7847c9efee
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: sbdsp.c,v 1.15 1996/02/16 08:07:40 mycroft Exp $ */
|
/* $NetBSD: sbdsp.c,v 1.16 1996/02/16 10:10:21 mycroft Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1991-1993 Regents of the University of California.
|
* Copyright (c) 1991-1993 Regents of the University of California.
|
||||||
|
@ -81,20 +81,54 @@ struct {
|
||||||
int wmidi;
|
int wmidi;
|
||||||
} sberr;
|
} sberr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Time constant routines follow. See SBK, section 12.
|
||||||
|
* Although they don't come out and say it (in the docs),
|
||||||
|
* the card clearly uses a 1MHz countdown timer, as the
|
||||||
|
* low-speed formula (p. 12-4) is:
|
||||||
|
* tc = 256 - 10^6 / sr
|
||||||
|
* In high-speed mode, the constant is the upper byte of a 16-bit counter,
|
||||||
|
* and a 256MHz clock is used:
|
||||||
|
* tc = 65536 - 256 * 10^ 6 / sr
|
||||||
|
* Since we can only use the upper byte of the HS TC, the two formulae
|
||||||
|
* are equivalent. (Why didn't they say so?) E.g.,
|
||||||
|
* (65536 - 256 * 10 ^ 6 / x) >> 8 = 256 - 10^6 / x
|
||||||
|
*
|
||||||
|
* The crossover point (from low- to high-speed modes) is different
|
||||||
|
* for the SBPRO and SB20. The table on p. 12-5 gives the following data:
|
||||||
|
*
|
||||||
|
* SBPRO SB20
|
||||||
|
* ----- --------
|
||||||
|
* input ls min 4 KHz 4 KHz
|
||||||
|
* input ls max 23 KHz 13 KHz
|
||||||
|
* input hs max 44.1 KHz 15 KHz
|
||||||
|
* output ls min 4 KHz 4 KHz
|
||||||
|
* output ls max 23 KHz 23 KHz
|
||||||
|
* output hs max 44.1 KHz 44.1 KHz
|
||||||
|
*/
|
||||||
|
#define SB_LS_MIN 0x06 /* 4000 Hz */
|
||||||
|
#define SB_8K 0x83 /* 8000 Hz */
|
||||||
|
#define SBPRO_ADC_LS_MAX 0xd4 /* 22727 Hz */
|
||||||
|
#define SBPRO_ADC_HS_MAX 0xea /* 45454 Hz */
|
||||||
|
#define SBCLA_ADC_LS_MAX 0xb3 /* 12987 Hz */
|
||||||
|
#define SBCLA_ADC_HS_MAX 0xbd /* 14925 Hz */
|
||||||
|
#define SB_DAC_LS_MAX 0xd4 /* 22727 Hz */
|
||||||
|
#define SB_DAC_HS_MAX 0xea /* 45454 Hz */
|
||||||
|
|
||||||
#ifdef AUDIO_DEBUG
|
#ifdef AUDIO_DEBUG
|
||||||
void
|
void
|
||||||
sb_printsc(struct sbdsp_softc *sc)
|
sb_printsc(struct sbdsp_softc *sc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("open %d dmachan %d iobase %x\n", sc->sc_open, sc->sc_drq,
|
printf("open %d dmachan %d iobase %x\n",
|
||||||
sc->sc_iobase);
|
sc->sc_open, sc->sc_drq, sc->sc_iobase);
|
||||||
printf("hispeed %d irate %d orate %d encoding %x\n",
|
printf("itc %d imode %d otc %d omode %d encoding %x\n",
|
||||||
sc->sc_adacmode, sc->sc_irate, sc->sc_orate, sc->encoding);
|
sc->sc_itc, sc->sc_imode, sc->sc_otc, sc->sc_omode, sc->encoding);
|
||||||
printf("outport %d inport %d spkron %d nintr %d\n",
|
printf("outport %d inport %d spkron %d nintr %d\n",
|
||||||
sc->out_port, sc->in_port, sc->spkr_state, sc->sc_interrupts);
|
sc->out_port, sc->in_port, sc->spkr_state, sc->sc_interrupts);
|
||||||
printf("tc %x chans %x scintr %x arg %x\n", sc->sc_adactc, sc->sc_chans,
|
printf("chans %x intr %x arg %x\n",
|
||||||
sc->sc_intr, sc->sc_arg);
|
sc->sc_chans, sc->sc_intr, sc->sc_arg);
|
||||||
printf("gain: ");
|
printf("gain: ");
|
||||||
for (i = 0; i < SB_NDEVS; i++)
|
for (i = 0; i < SB_NDEVS; i++)
|
||||||
printf("%d ", sc->gain[i]);
|
printf("%d ", sc->gain[i]);
|
||||||
|
@ -136,15 +170,12 @@ sbdsp_attach(sc)
|
||||||
|
|
||||||
/* Set defaults */
|
/* Set defaults */
|
||||||
if (ISSBPROCLASS(sc))
|
if (ISSBPROCLASS(sc))
|
||||||
sc->sc_irate = sc->sc_orate = 45454;
|
sc->sc_itc = sc->sc_otc = SBPRO_ADC_HS_MAX;
|
||||||
else
|
else
|
||||||
sc->sc_irate = sc->sc_orate = 14925;
|
sc->sc_itc = sc->sc_otc = SBCLA_ADC_HS_MAX;
|
||||||
sc->sc_chans = 1;
|
sc->sc_chans = 1;
|
||||||
sc->encoding = AUDIO_ENCODING_LINEAR;
|
sc->encoding = AUDIO_ENCODING_LINEAR;
|
||||||
|
|
||||||
(void) sbdsp_set_in_sr_real(sc, sc->sc_irate);
|
|
||||||
(void) sbdsp_set_out_sr_real(sc, sc->sc_orate);
|
|
||||||
|
|
||||||
(void) sbdsp_set_in_port(sc, SB_MIC_PORT);
|
(void) sbdsp_set_in_port(sc, SB_MIC_PORT);
|
||||||
(void) sbdsp_set_out_port(sc, SB_SPEAKER);
|
(void) sbdsp_set_out_port(sc, SB_SPEAKER);
|
||||||
|
|
||||||
|
@ -166,6 +197,7 @@ sbdsp_attach(sc)
|
||||||
for (i = 0; i < SB_NDEVS; i++)
|
for (i = 0; i < SB_NDEVS; i++)
|
||||||
sc->gain[i] = sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL);
|
sc->gain[i] = sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(": dsp v%d.%02d\n",
|
printf(": dsp v%d.%02d\n",
|
||||||
SBVER_MAJOR(sc->sc_model), SBVER_MINOR(sc->sc_model));
|
SBVER_MAJOR(sc->sc_model), SBVER_MINOR(sc->sc_model));
|
||||||
}
|
}
|
||||||
|
@ -205,25 +237,7 @@ sbdsp_set_in_sr(addr, sr)
|
||||||
{
|
{
|
||||||
register struct sbdsp_softc *sc = addr;
|
register struct sbdsp_softc *sc = addr;
|
||||||
|
|
||||||
sc->sc_irate = sr;
|
return (sbdsp_srtotc(sc, sr, SB_INPUT_RATE, &sc->sc_itc, &sc->sc_imode));
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
sbdsp_set_in_sr_real(addr, sr)
|
|
||||||
void *addr;
|
|
||||||
u_long sr;
|
|
||||||
{
|
|
||||||
register struct sbdsp_softc *sc = addr;
|
|
||||||
int rval;
|
|
||||||
|
|
||||||
if (rval = sbdsp_set_sr(sc, &sr, SB_INPUT_RATE))
|
|
||||||
return rval;
|
|
||||||
sc->sc_irate = sr;
|
|
||||||
if (sc->sc_dmadir == SBP_DMA_IN)
|
|
||||||
sc->sc_dmadir = SBP_DMA_NONE; /* do it again on next DMA in */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u_long
|
u_long
|
||||||
|
@ -232,7 +246,7 @@ sbdsp_get_in_sr(addr)
|
||||||
{
|
{
|
||||||
register struct sbdsp_softc *sc = addr;
|
register struct sbdsp_softc *sc = addr;
|
||||||
|
|
||||||
return(sc->sc_irate);
|
return (sbdsp_tctosr(sc, sc->sc_itc));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -242,24 +256,7 @@ sbdsp_set_out_sr(addr, sr)
|
||||||
{
|
{
|
||||||
register struct sbdsp_softc *sc = addr;
|
register struct sbdsp_softc *sc = addr;
|
||||||
|
|
||||||
sc->sc_orate = sr;
|
return (sbdsp_srtotc(sc, sr, SB_OUTPUT_RATE, &sc->sc_otc, &sc->sc_omode));
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
sbdsp_set_out_sr_real(addr, sr)
|
|
||||||
void *addr;
|
|
||||||
u_long sr;
|
|
||||||
{
|
|
||||||
register struct sbdsp_softc *sc = addr;
|
|
||||||
int rval;
|
|
||||||
|
|
||||||
if (rval = sbdsp_set_sr(sc, &sr, SB_OUTPUT_RATE))
|
|
||||||
return rval;
|
|
||||||
sc->sc_orate = sr;
|
|
||||||
if (sc->sc_dmadir == SBP_DMA_OUT)
|
|
||||||
sc->sc_dmadir = SBP_DMA_NONE; /* do it again on next DMA out */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u_long
|
u_long
|
||||||
|
@ -268,7 +265,7 @@ sbdsp_get_out_sr(addr)
|
||||||
{
|
{
|
||||||
register struct sbdsp_softc *sc = addr;
|
register struct sbdsp_softc *sc = addr;
|
||||||
|
|
||||||
return(sc->sc_orate);
|
return (sbdsp_tctosr(sc, sc->sc_otc));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -289,7 +286,6 @@ sbdsp_query_encoding(addr, fp)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
@ -347,26 +343,27 @@ sbdsp_set_channels(addr, chans)
|
||||||
int chans;
|
int chans;
|
||||||
{
|
{
|
||||||
register struct sbdsp_softc *sc = addr;
|
register struct sbdsp_softc *sc = addr;
|
||||||
int rval;
|
|
||||||
|
|
||||||
if (ISSBPROCLASS(sc)) {
|
if (ISSBPROCLASS(sc)) {
|
||||||
if (chans != 1 && chans != 2)
|
if (chans != 1 && chans != 2)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
sc->sc_chans = chans;
|
sc->sc_chans = chans;
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (rval = sbdsp_set_in_sr_real(addr, sc->sc_irate))
|
if (rval = sbdsp_set_in_sr_real(addr, sc->sc_irate))
|
||||||
return rval;
|
return rval;
|
||||||
|
#endif
|
||||||
|
|
||||||
sbdsp_mix_write(sc, SBP_STEREO,
|
sbdsp_mix_write(sc, SBP_STEREO,
|
||||||
(sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
|
(sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
|
||||||
(chans == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
|
(chans == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
|
||||||
/* recording channels needs to be done right when we start
|
/* recording channels needs to be done right when we start
|
||||||
DMA recording. Just record number of channels for now
|
DMA recording. Just record number of channels for now
|
||||||
and set stereo when ready. */
|
and set stereo when ready. */
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (chans != 1)
|
if (chans != 1)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
sc->sc_chans = 1;
|
sc->sc_chans = chans;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -381,16 +378,12 @@ sbdsp_get_channels(addr)
|
||||||
#if 0
|
#if 0
|
||||||
/* recording stereo may frob the mixer output */
|
/* recording stereo may frob the mixer output */
|
||||||
if (ISSBPROCLASS(sc)) {
|
if (ISSBPROCLASS(sc)) {
|
||||||
if ((sbdsp_mix_read(sc, SBP_STEREO) & SBP_PLAYMODE_MASK) == SBP_PLAYMODE_STEREO) {
|
if ((sbdsp_mix_read(sc, SBP_STEREO) & SBP_PLAYMODE_MASK) == SBP_PLAYMODE_STEREO)
|
||||||
sc->sc_chans = 2;
|
sc->sc_chans = 2;
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
sc->sc_chans = 1;
|
sc->sc_chans = 1;
|
||||||
}
|
} else
|
||||||
}
|
|
||||||
else {
|
|
||||||
sc->sc_chans = 1;
|
sc->sc_chans = 1;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (sc->sc_chans);
|
return (sc->sc_chans);
|
||||||
|
@ -444,10 +437,8 @@ sbdsp_set_in_port(addr, port)
|
||||||
case SB_FM_PORT:
|
case SB_FM_PORT:
|
||||||
default:
|
default:
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
switch (port) {
|
switch (port) {
|
||||||
case SB_MIC_PORT:
|
case SB_MIC_PORT:
|
||||||
sbport = SBP_FROM_MIC;
|
sbport = SBP_FROM_MIC;
|
||||||
|
@ -455,7 +446,6 @@ sbdsp_set_in_port(addr, port)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,11 +503,12 @@ sbdsp_round_blocksize(addr, blk)
|
||||||
sc->sc_last_hs_size = 0;
|
sc->sc_last_hs_size = 0;
|
||||||
|
|
||||||
/* Higher speeds need bigger blocks to avoid popping and silence gaps. */
|
/* Higher speeds need bigger blocks to avoid popping and silence gaps. */
|
||||||
if ((sc->sc_orate > 8000 || sc->sc_irate > 8000) &&
|
if ((sc->sc_otc > SB_8K || sc->sc_itc > SB_8K) &&
|
||||||
(blk > NBPG/2 || blk < NBPG/4))
|
(blk > NBPG/2 || blk < NBPG/4))
|
||||||
blk = NBPG/2;
|
blk = NBPG/2;
|
||||||
/* don't try to DMA too much at once, though. */
|
/* don't try to DMA too much at once, though. */
|
||||||
if (blk > NBPG) blk = NBPG;
|
if (blk > NBPG)
|
||||||
|
blk = NBPG;
|
||||||
if (sc->sc_chans == 2)
|
if (sc->sc_chans == 2)
|
||||||
return (blk & ~1); /* must be even to preserve stereo separation */
|
return (blk & ~1); /* must be even to preserve stereo separation */
|
||||||
else
|
else
|
||||||
|
@ -528,15 +519,18 @@ int
|
||||||
sbdsp_commit_settings(addr)
|
sbdsp_commit_settings(addr)
|
||||||
void *addr;
|
void *addr;
|
||||||
{
|
{
|
||||||
|
register struct sbdsp_softc *sc = addr;
|
||||||
|
|
||||||
/* due to potentially unfortunate ordering in the above layers,
|
/* due to potentially unfortunate ordering in the above layers,
|
||||||
re-do a few sets which may be important--input gains
|
re-do a few sets which may be important--input gains
|
||||||
(adjust the proper channels), number of input channels (hit the
|
(adjust the proper channels), number of input channels (hit the
|
||||||
record rate and set mode) */
|
record rate and set mode) */
|
||||||
|
|
||||||
register struct sbdsp_softc *sc = addr;
|
/*
|
||||||
|
* XXX
|
||||||
sbdsp_set_out_sr_real(addr, sc->sc_orate);
|
* Should wait for chip to be idle.
|
||||||
sbdsp_set_in_sr_real(addr, sc->sc_irate);
|
*/
|
||||||
|
sc->sc_dmadir = SB_DMA_NONE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -604,9 +598,9 @@ sbdsp_reset(sc)
|
||||||
register int iobase = sc->sc_iobase;
|
register int iobase = sc->sc_iobase;
|
||||||
|
|
||||||
sc->sc_intr = 0;
|
sc->sc_intr = 0;
|
||||||
if (sc->sc_dmadir != SBP_DMA_NONE) {
|
if (sc->sc_dmadir != SB_DMA_NONE) {
|
||||||
isa_dmaabort(sc->sc_drq);
|
isa_dmaabort(sc->sc_drq);
|
||||||
sc->sc_dmadir = SBP_DMA_NONE;
|
sc->sc_dmadir = SB_DMA_NONE;
|
||||||
}
|
}
|
||||||
sc->sc_last_hs_size = 0;
|
sc->sc_last_hs_size = 0;
|
||||||
|
|
||||||
|
@ -768,39 +762,6 @@ sbdsp_contdma(addr)
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Time constant routines follow. See SBK, section 12.
|
|
||||||
* Although they don't come out and say it (in the docs),
|
|
||||||
* the card clearly uses a 1MHz countdown timer, as the
|
|
||||||
* low-speed formula (p. 12-4) is:
|
|
||||||
* tc = 256 - 10^6 / sr
|
|
||||||
* In high-speed mode, the constant is the upper byte of a 16-bit counter,
|
|
||||||
* and a 256MHz clock is used:
|
|
||||||
* tc = 65536 - 256 * 10^ 6 / sr
|
|
||||||
* Since we can only use the upper byte of the HS TC, the two formulae
|
|
||||||
* are equivalent. (Why didn't they say so?) E.g.,
|
|
||||||
* (65536 - 256 * 10 ^ 6 / x) >> 8 = 256 - 10^6 / x
|
|
||||||
*
|
|
||||||
* The crossover point (from low- to high-speed modes) is different
|
|
||||||
* for the SBPRO and SB20. The table on p. 12-5 gives the following data:
|
|
||||||
*
|
|
||||||
* SBPRO SB20
|
|
||||||
* ----- --------
|
|
||||||
* input ls min 4 KHz 4 KHz
|
|
||||||
* input ls max 23 KHz 13 KHz
|
|
||||||
* input hs max 44.1 KHz 15 KHz
|
|
||||||
* output ls min 4 KHz 4 KHz
|
|
||||||
* output ls max 23 KHz 23 KHz
|
|
||||||
* output hs max 44.1 KHz 44.1 KHz
|
|
||||||
*/
|
|
||||||
#define SB_LS_MIN 0x06 /* 4000 Hz */
|
|
||||||
#define SBPRO_ADC_LS_MAX 0xd4 /* 22727 Hz */
|
|
||||||
#define SBPRO_ADC_HS_MAX 0xea /* 45454 Hz */
|
|
||||||
#define SBCLA_ADC_LS_MAX 0xb3 /* 12987 Hz */
|
|
||||||
#define SBCLA_ADC_HS_MAX 0xbd /* 14925 Hz */
|
|
||||||
#define SB_DAC_LS_MAX 0xd4 /* 22727 Hz */
|
|
||||||
#define SB_DAC_HS_MAX 0xea /* 45454 Hz */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert a linear sampling rate into the DAC time constant.
|
* Convert a linear sampling rate into the DAC time constant.
|
||||||
* Set *mode to indicate the high/low-speed DMA operation.
|
* Set *mode to indicate the high/low-speed DMA operation.
|
||||||
|
@ -810,53 +771,60 @@ sbdsp_contdma(addr)
|
||||||
* so isdac indicates output, and !isdac indicates input.
|
* so isdac indicates output, and !isdac indicates input.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
sbdsp_srtotc(sc, sr, mode, isdac)
|
sbdsp_srtotc(sc, sr, isdac, tcp, modep)
|
||||||
register struct sbdsp_softc *sc;
|
register struct sbdsp_softc *sc;
|
||||||
int sr;
|
int sr;
|
||||||
int *mode;
|
|
||||||
int isdac;
|
int isdac;
|
||||||
|
int *tcp, *modep;
|
||||||
{
|
{
|
||||||
int adc_ls_max, adc_hs_max;
|
int tc, mode;
|
||||||
register int tc;
|
|
||||||
|
|
||||||
if (sr == 0) {
|
if (sr == 0) {
|
||||||
*mode = SB_ADAC_LS;
|
tc = SB_LS_MIN;
|
||||||
return SB_LS_MIN;
|
mode = SB_ADAC_LS;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
tc = 256 - 1000000 / sr;
|
|
||||||
|
tc = 256 - (1000000 / sr);
|
||||||
|
|
||||||
|
if (tc < SB_LS_MIN) {
|
||||||
|
tc = SB_LS_MIN;
|
||||||
|
mode = SB_ADAC_LS;
|
||||||
|
goto out;
|
||||||
|
} else if (isdac) {
|
||||||
|
if (tc <= SB_DAC_LS_MAX)
|
||||||
|
mode = SB_ADAC_LS;
|
||||||
|
else {
|
||||||
|
mode = SB_ADAC_HS;
|
||||||
|
if (tc > SB_DAC_HS_MAX)
|
||||||
|
tc = SB_DAC_HS_MAX;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int adc_ls_max, adc_hs_max;
|
||||||
|
|
||||||
/* XXX use better rounding--compare distance to nearest tc on both
|
/* XXX use better rounding--compare distance to nearest tc on both
|
||||||
sides of requested speed */
|
sides of requested speed */
|
||||||
if (ISSBPROCLASS(sc)) {
|
if (ISSBPROCLASS(sc)) {
|
||||||
adc_ls_max = SBPRO_ADC_LS_MAX;
|
adc_ls_max = SBPRO_ADC_LS_MAX;
|
||||||
adc_hs_max = SBPRO_ADC_HS_MAX;
|
adc_hs_max = SBPRO_ADC_HS_MAX;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
adc_ls_max = SBCLA_ADC_LS_MAX;
|
adc_ls_max = SBCLA_ADC_LS_MAX;
|
||||||
adc_hs_max = SBCLA_ADC_HS_MAX;
|
adc_hs_max = SBCLA_ADC_HS_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tc < SB_LS_MIN) {
|
|
||||||
tc = SB_LS_MIN;
|
|
||||||
*mode = SB_ADAC_LS;
|
|
||||||
} else if (isdac) {
|
|
||||||
if (tc <= SB_DAC_LS_MAX)
|
|
||||||
*mode = SB_ADAC_LS;
|
|
||||||
else {
|
|
||||||
*mode = SB_ADAC_HS;
|
|
||||||
if (tc > SB_DAC_HS_MAX)
|
|
||||||
tc = SB_DAC_HS_MAX;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tc <= adc_ls_max)
|
if (tc <= adc_ls_max)
|
||||||
*mode = SB_ADAC_LS;
|
mode = SB_ADAC_LS;
|
||||||
else {
|
else {
|
||||||
*mode = SB_ADAC_HS;
|
mode = SB_ADAC_HS;
|
||||||
if (tc > adc_hs_max)
|
if (tc > adc_hs_max)
|
||||||
tc = adc_hs_max;
|
tc = adc_hs_max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tc;
|
|
||||||
|
out:
|
||||||
|
*tcp = tc;
|
||||||
|
*modep = mode;
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -882,47 +850,27 @@ sbdsp_tctosr(sc, tc)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sbdsp_set_sr(sc, srp, isdac)
|
sbdsp_set_tc(sc, tc)
|
||||||
register struct sbdsp_softc *sc;
|
register struct sbdsp_softc *sc;
|
||||||
u_long *srp;
|
int tc;
|
||||||
int isdac;
|
|
||||||
{
|
{
|
||||||
register int tc;
|
|
||||||
int mode;
|
|
||||||
int sr = *srp;
|
|
||||||
register int iobase;
|
register int iobase;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A SBPro in stereo mode uses time constants at double the
|
* A SBPro in stereo mode uses time constants at double the
|
||||||
* actual rate.
|
* actual rate.
|
||||||
*/
|
*/
|
||||||
if (ISSBPRO(sc) && sc->sc_chans == 2) {
|
if (ISSBPRO(sc) && sc->sc_chans == 2)
|
||||||
if (sr > 22727)
|
tc = 256 - ((256 - tc) / 2);
|
||||||
sr = 22727; /* Can't bounce it...order of
|
|
||||||
operations may yield bogus
|
|
||||||
sr here. */
|
|
||||||
sr *= 2;
|
|
||||||
}
|
|
||||||
else if (!ISSBPROCLASS(sc) && sc->sc_chans != 1)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
tc = sbdsp_srtotc(sc, sr, &mode, isdac);
|
DPRINTF(("sbdsp_set_tc: sc=%p tc=%d\n", sc, tc));
|
||||||
DPRINTF(("sbdsp_set_sr: sc=0x%x sr=%d mode=0x%x\n", sc, sr, mode));
|
|
||||||
|
|
||||||
iobase = sc->sc_iobase;
|
iobase = sc->sc_iobase;
|
||||||
if (sbdsp_wdsp(iobase, SB_DSP_TIMECONST) < 0 ||
|
if (sbdsp_wdsp(iobase, SB_DSP_TIMECONST) < 0 ||
|
||||||
sbdsp_wdsp(iobase, tc) < 0)
|
sbdsp_wdsp(iobase, tc) < 0)
|
||||||
return EIO;
|
return (EIO);
|
||||||
|
|
||||||
sr = sbdsp_tctosr(sc, tc);
|
return (0);
|
||||||
if (ISSBPRO(sc) && sc->sc_chans == 2)
|
|
||||||
*srp = sr / 2;
|
|
||||||
else
|
|
||||||
*srp = sr;
|
|
||||||
|
|
||||||
sc->sc_adacmode = mode;
|
|
||||||
sc->sc_adactc = tc;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -946,22 +894,24 @@ sbdsp_dma_input(addr, p, cc, intr, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
iobase = sc->sc_iobase;
|
iobase = sc->sc_iobase;
|
||||||
if (ISSBPROCLASS(sc) && sc->sc_dmadir != SBP_DMA_IN) {
|
if (sc->sc_dmadir != SB_DMA_IN) {
|
||||||
|
if (ISSBPROCLASS(sc)) {
|
||||||
if (sc->sc_chans == 2) {
|
if (sc->sc_chans == 2) {
|
||||||
if (sbdsp_wdsp(iobase, SB_DSP_RECORD_STEREO) < 0)
|
if (sbdsp_wdsp(iobase, SB_DSP_RECORD_STEREO) < 0)
|
||||||
goto badmode;
|
goto badmode;
|
||||||
sbdsp_mix_write(sc, SBP_INFILTER,
|
sbdsp_mix_write(sc, SBP_INFILTER,
|
||||||
sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF);
|
sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (sbdsp_wdsp(iobase, SB_DSP_RECORD_MONO) < 0)
|
if (sbdsp_wdsp(iobase, SB_DSP_RECORD_MONO) < 0)
|
||||||
goto badmode;
|
goto badmode;
|
||||||
sbdsp_mix_write(sc, SBP_INFILTER,
|
sbdsp_mix_write(sc, SBP_INFILTER, sc->sc_itc > SB_8K ?
|
||||||
sc->sc_irate <= 8000 ?
|
sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF :
|
||||||
sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_FILTER_MASK :
|
sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_FILTER_MASK);
|
||||||
sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF);
|
|
||||||
}
|
}
|
||||||
sc->sc_dmadir = SBP_DMA_IN;
|
}
|
||||||
|
|
||||||
|
sbdsp_set_tc(sc, sc->sc_itc);
|
||||||
|
sc->sc_dmadir = SB_DMA_IN;
|
||||||
}
|
}
|
||||||
|
|
||||||
isa_dmastart(B_READ, p, cc, sc->sc_drq);
|
isa_dmastart(B_READ, p, cc, sc->sc_drq);
|
||||||
|
@ -971,7 +921,7 @@ sbdsp_dma_input(addr, p, cc, intr, arg)
|
||||||
sc->dmaaddr = p;
|
sc->dmaaddr = p;
|
||||||
sc->dmacnt = --cc; /* DMA controller is strange...? */
|
sc->dmacnt = --cc; /* DMA controller is strange...? */
|
||||||
|
|
||||||
if (sc->sc_adacmode == SB_ADAC_LS) {
|
if (sc->sc_imode == SB_ADAC_LS) {
|
||||||
if (sbdsp_wdsp(iobase, SB_DSP_RDMA) < 0 ||
|
if (sbdsp_wdsp(iobase, SB_DSP_RDMA) < 0 ||
|
||||||
sbdsp_wdsp(iobase, cc) < 0 ||
|
sbdsp_wdsp(iobase, cc) < 0 ||
|
||||||
sbdsp_wdsp(iobase, cc >> 8) < 0) {
|
sbdsp_wdsp(iobase, cc >> 8) < 0) {
|
||||||
|
@ -1027,14 +977,17 @@ sbdsp_dma_output(addr, p, cc, intr, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
iobase = sc->sc_iobase;
|
iobase = sc->sc_iobase;
|
||||||
if (ISSBPROCLASS(sc) && sc->sc_dmadir != SBP_DMA_OUT) {
|
if (sc->sc_dmadir != SB_DMA_OUT) {
|
||||||
|
if (ISSBPROCLASS(sc)) {
|
||||||
/* make sure we re-set stereo mixer bit when we start
|
/* make sure we re-set stereo mixer bit when we start
|
||||||
output. */
|
output. */
|
||||||
sbdsp_mix_write(sc, SBP_STEREO,
|
sbdsp_mix_write(sc, SBP_STEREO,
|
||||||
(sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
|
(sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
|
||||||
(sc->sc_chans == 2 ?
|
(sc->sc_chans == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
|
||||||
SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
|
}
|
||||||
sc->sc_dmadir = SBP_DMA_OUT;
|
|
||||||
|
sbdsp_set_tc(sc, sc->sc_otc);
|
||||||
|
sc->sc_dmadir = SB_DMA_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
isa_dmastart(B_WRITE, p, cc, sc->sc_drq);
|
isa_dmastart(B_WRITE, p, cc, sc->sc_drq);
|
||||||
|
@ -1044,7 +997,7 @@ sbdsp_dma_output(addr, p, cc, intr, arg)
|
||||||
sc->dmaaddr = p;
|
sc->dmaaddr = p;
|
||||||
sc->dmacnt = --cc; /* a vagary of how DMA works, apparently. */
|
sc->dmacnt = --cc; /* a vagary of how DMA works, apparently. */
|
||||||
|
|
||||||
if (sc->sc_adacmode == SB_ADAC_LS) {
|
if (sc->sc_omode == SB_ADAC_LS) {
|
||||||
if (sbdsp_wdsp(iobase, SB_DSP_WDMA) < 0 ||
|
if (sbdsp_wdsp(iobase, SB_DSP_WDMA) < 0 ||
|
||||||
sbdsp_wdsp(iobase, cc) < 0 ||
|
sbdsp_wdsp(iobase, cc) < 0 ||
|
||||||
sbdsp_wdsp(iobase, cc >> 8) < 0) {
|
sbdsp_wdsp(iobase, cc >> 8) < 0) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: sbdspvar.h,v 1.8 1996/02/16 08:07:46 mycroft Exp $ */
|
/* $NetBSD: sbdspvar.h,v 1.9 1996/02/16 10:10:23 mycroft Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1991-1993 Regents of the University of California.
|
* Copyright (c) 1991-1993 Regents of the University of California.
|
||||||
|
@ -80,10 +80,6 @@ struct sbdsp_softc {
|
||||||
int sc_drq; /* DMA */
|
int sc_drq; /* DMA */
|
||||||
|
|
||||||
u_short sc_open; /* reference count of open calls */
|
u_short sc_open; /* reference count of open calls */
|
||||||
u_short sc_adacmode; /* low/high speed mode indicator */
|
|
||||||
|
|
||||||
u_long sc_irate; /* Sample rate for input */
|
|
||||||
u_long sc_orate; /* ...and output */
|
|
||||||
|
|
||||||
u_int gain[SB_NDEVS]; /* kept in SB levels: right/left each
|
u_int gain[SB_NDEVS]; /* kept in SB levels: right/left each
|
||||||
in a nibble */
|
in a nibble */
|
||||||
|
@ -95,9 +91,14 @@ struct sbdsp_softc {
|
||||||
|
|
||||||
u_int spkr_state; /* non-null is on */
|
u_int spkr_state; /* non-null is on */
|
||||||
|
|
||||||
|
int sc_itc; /* Sample rate for input */
|
||||||
|
int sc_otc; /* ...and output */
|
||||||
|
|
||||||
|
int sc_imode;
|
||||||
|
int sc_omode;
|
||||||
#define SB_ADAC_LS 0
|
#define SB_ADAC_LS 0
|
||||||
#define SB_ADAC_HS 1
|
#define SB_ADAC_HS 1
|
||||||
u_short sc_adactc; /* current adac time constant */
|
|
||||||
u_long sc_interrupts; /* number of interrupts taken */
|
u_long sc_interrupts; /* number of interrupts taken */
|
||||||
void (*sc_intr)(void*); /* dma completion intr handler */
|
void (*sc_intr)(void*); /* dma completion intr handler */
|
||||||
void (*sc_mintr)(void*, int);/* midi input intr handler */
|
void (*sc_mintr)(void*, int);/* midi input intr handler */
|
||||||
|
@ -109,9 +110,9 @@ struct sbdsp_softc {
|
||||||
int sc_last_hs_size; /* last HS dma size */
|
int sc_last_hs_size; /* last HS dma size */
|
||||||
int sc_chans; /* # of channels */
|
int sc_chans; /* # of channels */
|
||||||
int sc_dmadir; /* DMA direction */
|
int sc_dmadir; /* DMA direction */
|
||||||
#define SBP_DMA_NONE 0
|
#define SB_DMA_NONE 0
|
||||||
#define SBP_DMA_IN 1
|
#define SB_DMA_IN 1
|
||||||
#define SBP_DMA_OUT 2
|
#define SB_DMA_OUT 2
|
||||||
|
|
||||||
u_int sc_model; /* DSP model */
|
u_int sc_model; /* DSP model */
|
||||||
#define SBVER_MAJOR(v) ((v)>>8)
|
#define SBVER_MAJOR(v) ((v)>>8)
|
||||||
|
|
Loading…
Reference in New Issue