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.
|
||||
|
@ -81,23 +81,57 @@ struct {
|
|||
int wmidi;
|
||||
} 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
|
||||
void
|
||||
sb_printsc(struct sbdsp_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("open %d dmachan %d iobase %x\n", sc->sc_open, sc->sc_drq,
|
||||
sc->sc_iobase);
|
||||
printf("hispeed %d irate %d orate %d encoding %x\n",
|
||||
sc->sc_adacmode, sc->sc_irate, sc->sc_orate, sc->encoding);
|
||||
printf("open %d dmachan %d iobase %x\n",
|
||||
sc->sc_open, sc->sc_drq, sc->sc_iobase);
|
||||
printf("itc %d imode %d otc %d omode %d encoding %x\n",
|
||||
sc->sc_itc, sc->sc_imode, sc->sc_otc, sc->sc_omode, sc->encoding);
|
||||
printf("outport %d inport %d spkron %d nintr %d\n",
|
||||
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,
|
||||
sc->sc_intr, sc->sc_arg);
|
||||
sc->out_port, sc->in_port, sc->spkr_state, sc->sc_interrupts);
|
||||
printf("chans %x intr %x arg %x\n",
|
||||
sc->sc_chans, sc->sc_intr, sc->sc_arg);
|
||||
printf("gain: ");
|
||||
for (i = 0; i < SB_NDEVS; i++)
|
||||
printf("%d ", sc->gain[i]);
|
||||
printf("%d ", sc->gain[i]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
@ -136,15 +170,12 @@ sbdsp_attach(sc)
|
|||
|
||||
/* Set defaults */
|
||||
if (ISSBPROCLASS(sc))
|
||||
sc->sc_irate = sc->sc_orate = 45454;
|
||||
sc->sc_itc = sc->sc_otc = SBPRO_ADC_HS_MAX;
|
||||
else
|
||||
sc->sc_irate = sc->sc_orate = 14925;
|
||||
sc->sc_itc = sc->sc_otc = SBCLA_ADC_HS_MAX;
|
||||
sc->sc_chans = 1;
|
||||
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_out_port(sc, SB_SPEAKER);
|
||||
|
||||
|
@ -164,8 +195,9 @@ sbdsp_attach(sc)
|
|||
sbdsp_mix_write(sc, SBP_LINE_VOL,
|
||||
sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL));
|
||||
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",
|
||||
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;
|
||||
|
||||
sc->sc_irate = sr;
|
||||
|
||||
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;
|
||||
return (sbdsp_srtotc(sc, sr, SB_INPUT_RATE, &sc->sc_itc, &sc->sc_imode));
|
||||
}
|
||||
|
||||
u_long
|
||||
|
@ -232,7 +246,7 @@ sbdsp_get_in_sr(addr)
|
|||
{
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
|
||||
return(sc->sc_irate);
|
||||
return (sbdsp_tctosr(sc, sc->sc_itc));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -242,24 +256,7 @@ sbdsp_set_out_sr(addr, sr)
|
|||
{
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
|
||||
sc->sc_orate = sr;
|
||||
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;
|
||||
return (sbdsp_srtotc(sc, sr, SB_OUTPUT_RATE, &sc->sc_otc, &sc->sc_omode));
|
||||
}
|
||||
|
||||
u_long
|
||||
|
@ -268,30 +265,29 @@ sbdsp_get_out_sr(addr)
|
|||
{
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
|
||||
return(sc->sc_orate);
|
||||
return (sbdsp_tctosr(sc, sc->sc_otc));
|
||||
}
|
||||
|
||||
int
|
||||
sbdsp_query_encoding(addr, fp)
|
||||
void *addr;
|
||||
struct audio_encoding *fp;
|
||||
void *addr;
|
||||
struct audio_encoding *fp;
|
||||
{
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
|
||||
switch (fp->index) {
|
||||
case 0:
|
||||
strcpy(fp->name, AudioEmulaw);
|
||||
fp->format_id = AUDIO_ENCODING_ULAW;
|
||||
break;
|
||||
case 1:
|
||||
strcpy(fp->name, AudioEpcm16);
|
||||
fp->format_id = AUDIO_ENCODING_PCM16;
|
||||
break;
|
||||
default:
|
||||
return(EINVAL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
return (0);
|
||||
switch (fp->index) {
|
||||
case 0:
|
||||
strcpy(fp->name, AudioEmulaw);
|
||||
fp->format_id = AUDIO_ENCODING_ULAW;
|
||||
break;
|
||||
case 1:
|
||||
strcpy(fp->name, AudioEpcm16);
|
||||
fp->format_id = AUDIO_ENCODING_PCM16;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -320,7 +316,7 @@ sbdsp_get_encoding(addr)
|
|||
{
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
|
||||
return(sc->encoding);
|
||||
return (sc->encoding);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -330,15 +326,15 @@ sbdsp_set_precision(addr, prec)
|
|||
{
|
||||
|
||||
if (prec != 8)
|
||||
return(EINVAL);
|
||||
return(0);
|
||||
return (EINVAL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
sbdsp_get_precision(addr)
|
||||
void *addr;
|
||||
{
|
||||
return(8);
|
||||
return (8);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -347,29 +343,30 @@ sbdsp_set_channels(addr, chans)
|
|||
int chans;
|
||||
{
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
int rval;
|
||||
|
||||
if (ISSBPROCLASS(sc)) {
|
||||
if (chans != 1 && chans != 2)
|
||||
return(EINVAL);
|
||||
|
||||
return (EINVAL);
|
||||
sc->sc_chans = chans;
|
||||
|
||||
#if 0
|
||||
if (rval = sbdsp_set_in_sr_real(addr, sc->sc_irate))
|
||||
return rval;
|
||||
return rval;
|
||||
#endif
|
||||
|
||||
sbdsp_mix_write(sc, SBP_STEREO,
|
||||
(sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
|
||||
(chans == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
|
||||
/* recording channels needs to be done right when we start
|
||||
DMA recording. Just record number of channels for now
|
||||
and set stereo when ready. */
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (chans != 1)
|
||||
return(EINVAL);
|
||||
sc->sc_chans = 1;
|
||||
return (EINVAL);
|
||||
sc->sc_chans = chans;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -381,19 +378,15 @@ sbdsp_get_channels(addr)
|
|||
#if 0
|
||||
/* recording stereo may frob the mixer output */
|
||||
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;
|
||||
}
|
||||
else {
|
||||
else
|
||||
sc->sc_chans = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else
|
||||
sc->sc_chans = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return(sc->sc_chans);
|
||||
return (sc->sc_chans);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -405,7 +398,7 @@ sbdsp_set_out_port(addr, port)
|
|||
|
||||
sc->out_port = port; /* Just record it */
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -414,7 +407,7 @@ sbdsp_get_out_port(addr)
|
|||
{
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
|
||||
return(sc->out_port);
|
||||
return (sc->out_port);
|
||||
}
|
||||
|
||||
|
||||
|
@ -427,36 +420,33 @@ sbdsp_set_in_port(addr, port)
|
|||
int mixport, sbport;
|
||||
|
||||
if (ISSBPROCLASS(sc)) {
|
||||
switch (port) {
|
||||
case SB_MIC_PORT:
|
||||
sbport = SBP_FROM_MIC;
|
||||
mixport = SBP_MIC_VOL;
|
||||
break;
|
||||
case SB_LINE_IN_PORT:
|
||||
sbport = SBP_FROM_LINE;
|
||||
mixport = SBP_LINE_VOL;
|
||||
break;
|
||||
case SB_CD_PORT:
|
||||
sbport = SBP_FROM_CD;
|
||||
mixport = SBP_CD_VOL;
|
||||
break;
|
||||
case SB_DAC_PORT:
|
||||
case SB_FM_PORT:
|
||||
default:
|
||||
return(EINVAL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (port) {
|
||||
case SB_MIC_PORT:
|
||||
sbport = SBP_FROM_MIC;
|
||||
mixport = SBP_MIC_VOL;
|
||||
break;
|
||||
default:
|
||||
return(EINVAL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
switch (port) {
|
||||
case SB_MIC_PORT:
|
||||
sbport = SBP_FROM_MIC;
|
||||
mixport = SBP_MIC_VOL;
|
||||
break;
|
||||
case SB_LINE_IN_PORT:
|
||||
sbport = SBP_FROM_LINE;
|
||||
mixport = SBP_LINE_VOL;
|
||||
break;
|
||||
case SB_CD_PORT:
|
||||
sbport = SBP_FROM_CD;
|
||||
mixport = SBP_CD_VOL;
|
||||
break;
|
||||
case SB_DAC_PORT:
|
||||
case SB_FM_PORT:
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
} else {
|
||||
switch (port) {
|
||||
case SB_MIC_PORT:
|
||||
sbport = SBP_FROM_MIC;
|
||||
mixport = SBP_MIC_VOL;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
sc->in_port = port; /* Just record it */
|
||||
|
@ -470,7 +460,7 @@ sbdsp_set_in_port(addr, port)
|
|||
sc->gain[port] = sbdsp_mix_read(sc, mixport);
|
||||
}
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -479,7 +469,7 @@ sbdsp_get_in_port(addr)
|
|||
{
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
|
||||
return(sc->in_port);
|
||||
return (sc->in_port);
|
||||
}
|
||||
|
||||
|
||||
|
@ -513,30 +503,34 @@ sbdsp_round_blocksize(addr, blk)
|
|||
sc->sc_last_hs_size = 0;
|
||||
|
||||
/* 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;
|
||||
/* 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)
|
||||
return (blk & ~1); /* must be even to preserve stereo separation */
|
||||
else
|
||||
return(blk); /* Anything goes :-) */
|
||||
return (blk); /* Anything goes :-) */
|
||||
}
|
||||
|
||||
int
|
||||
sbdsp_commit_settings(addr)
|
||||
void *addr;
|
||||
{
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
|
||||
/* due to potentially unfortunate ordering in the above layers,
|
||||
re-do a few sets which may be important--input gains
|
||||
(adjust the proper channels), number of input channels (hit the
|
||||
record rate and set mode) */
|
||||
|
||||
register struct sbdsp_softc *sc = addr;
|
||||
|
||||
sbdsp_set_out_sr_real(addr, sc->sc_orate);
|
||||
sbdsp_set_in_sr_real(addr, sc->sc_irate);
|
||||
/*
|
||||
* XXX
|
||||
* Should wait for chip to be idle.
|
||||
*/
|
||||
sc->sc_dmadir = SB_DMA_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -604,9 +598,9 @@ sbdsp_reset(sc)
|
|||
register int iobase = sc->sc_iobase;
|
||||
|
||||
sc->sc_intr = 0;
|
||||
if (sc->sc_dmadir != SBP_DMA_NONE) {
|
||||
if (sc->sc_dmadir != SB_DMA_NONE) {
|
||||
isa_dmaabort(sc->sc_drq);
|
||||
sc->sc_dmadir = SBP_DMA_NONE;
|
||||
sc->sc_dmadir = SB_DMA_NONE;
|
||||
}
|
||||
sc->sc_last_hs_size = 0;
|
||||
|
||||
|
@ -768,39 +762,6 @@ sbdsp_contdma(addr)
|
|||
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.
|
||||
* 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.
|
||||
*/
|
||||
int
|
||||
sbdsp_srtotc(sc, sr, mode, isdac)
|
||||
sbdsp_srtotc(sc, sr, isdac, tcp, modep)
|
||||
register struct sbdsp_softc *sc;
|
||||
int sr;
|
||||
int *mode;
|
||||
int isdac;
|
||||
int *tcp, *modep;
|
||||
{
|
||||
int adc_ls_max, adc_hs_max;
|
||||
register int tc;
|
||||
int tc, mode;
|
||||
|
||||
if (sr == 0) {
|
||||
*mode = SB_ADAC_LS;
|
||||
return SB_LS_MIN;
|
||||
tc = SB_LS_MIN;
|
||||
mode = SB_ADAC_LS;
|
||||
goto out;
|
||||
}
|
||||
tc = 256 - 1000000 / sr;
|
||||
|
||||
tc = 256 - (1000000 / sr);
|
||||
|
||||
/* XXX use better rounding--compare distance to nearest tc on both
|
||||
sides of requested speed */
|
||||
if (ISSBPROCLASS(sc)) {
|
||||
adc_ls_max = SBPRO_ADC_LS_MAX;
|
||||
adc_hs_max = SBPRO_ADC_HS_MAX;
|
||||
}
|
||||
else {
|
||||
adc_ls_max = SBCLA_ADC_LS_MAX;
|
||||
adc_hs_max = SBCLA_ADC_HS_MAX;
|
||||
}
|
||||
|
||||
if (tc < SB_LS_MIN) {
|
||||
tc = SB_LS_MIN;
|
||||
*mode = SB_ADAC_LS;
|
||||
mode = SB_ADAC_LS;
|
||||
goto out;
|
||||
} else if (isdac) {
|
||||
if (tc <= SB_DAC_LS_MAX)
|
||||
*mode = SB_ADAC_LS;
|
||||
mode = SB_ADAC_LS;
|
||||
else {
|
||||
*mode = SB_ADAC_HS;
|
||||
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
|
||||
sides of requested speed */
|
||||
if (ISSBPROCLASS(sc)) {
|
||||
adc_ls_max = SBPRO_ADC_LS_MAX;
|
||||
adc_hs_max = SBPRO_ADC_HS_MAX;
|
||||
} else {
|
||||
adc_ls_max = SBCLA_ADC_LS_MAX;
|
||||
adc_hs_max = SBCLA_ADC_HS_MAX;
|
||||
}
|
||||
|
||||
if (tc <= adc_ls_max)
|
||||
*mode = SB_ADAC_LS;
|
||||
mode = SB_ADAC_LS;
|
||||
else {
|
||||
*mode = SB_ADAC_HS;
|
||||
mode = SB_ADAC_HS;
|
||||
if (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
|
||||
sbdsp_set_sr(sc, srp, isdac)
|
||||
sbdsp_set_tc(sc, tc)
|
||||
register struct sbdsp_softc *sc;
|
||||
u_long *srp;
|
||||
int isdac;
|
||||
int tc;
|
||||
{
|
||||
register int tc;
|
||||
int mode;
|
||||
int sr = *srp;
|
||||
register int iobase;
|
||||
|
||||
/*
|
||||
* A SBPro in stereo mode uses time constants at double the
|
||||
* actual rate.
|
||||
*/
|
||||
if (ISSBPRO(sc) && sc->sc_chans == 2) {
|
||||
if (sr > 22727)
|
||||
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;
|
||||
if (ISSBPRO(sc) && sc->sc_chans == 2)
|
||||
tc = 256 - ((256 - tc) / 2);
|
||||
|
||||
tc = sbdsp_srtotc(sc, sr, &mode, isdac);
|
||||
DPRINTF(("sbdsp_set_sr: sc=0x%x sr=%d mode=0x%x\n", sc, sr, mode));
|
||||
DPRINTF(("sbdsp_set_tc: sc=%p tc=%d\n", sc, tc));
|
||||
|
||||
iobase = sc->sc_iobase;
|
||||
if (sbdsp_wdsp(iobase, SB_DSP_TIMECONST) < 0 ||
|
||||
sbdsp_wdsp(iobase, tc) < 0)
|
||||
return EIO;
|
||||
return (EIO);
|
||||
|
||||
sr = sbdsp_tctosr(sc, tc);
|
||||
if (ISSBPRO(sc) && sc->sc_chans == 2)
|
||||
*srp = sr / 2;
|
||||
else
|
||||
*srp = sr;
|
||||
|
||||
sc->sc_adacmode = mode;
|
||||
sc->sc_adactc = tc;
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -946,22 +894,24 @@ sbdsp_dma_input(addr, p, cc, intr, arg)
|
|||
}
|
||||
|
||||
iobase = sc->sc_iobase;
|
||||
if (ISSBPROCLASS(sc) && sc->sc_dmadir != SBP_DMA_IN) {
|
||||
if (sc->sc_chans == 2) {
|
||||
if (sbdsp_wdsp(iobase, SB_DSP_RECORD_STEREO) < 0)
|
||||
goto badmode;
|
||||
sbdsp_mix_write(sc, SBP_INFILTER,
|
||||
sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF);
|
||||
if (sc->sc_dmadir != SB_DMA_IN) {
|
||||
if (ISSBPROCLASS(sc)) {
|
||||
if (sc->sc_chans == 2) {
|
||||
if (sbdsp_wdsp(iobase, SB_DSP_RECORD_STEREO) < 0)
|
||||
goto badmode;
|
||||
sbdsp_mix_write(sc, SBP_INFILTER,
|
||||
sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF);
|
||||
} else {
|
||||
if (sbdsp_wdsp(iobase, SB_DSP_RECORD_MONO) < 0)
|
||||
goto badmode;
|
||||
sbdsp_mix_write(sc, SBP_INFILTER, sc->sc_itc > SB_8K ?
|
||||
sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF :
|
||||
sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_FILTER_MASK);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sbdsp_wdsp(iobase, SB_DSP_RECORD_MONO) < 0)
|
||||
goto badmode;
|
||||
sbdsp_mix_write(sc, SBP_INFILTER,
|
||||
sc->sc_irate <= 8000 ?
|
||||
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);
|
||||
|
@ -971,7 +921,7 @@ sbdsp_dma_input(addr, p, cc, intr, arg)
|
|||
sc->dmaaddr = p;
|
||||
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 ||
|
||||
sbdsp_wdsp(iobase, cc) < 0 ||
|
||||
sbdsp_wdsp(iobase, cc >> 8) < 0) {
|
||||
|
@ -1027,14 +977,17 @@ sbdsp_dma_output(addr, p, cc, intr, arg)
|
|||
}
|
||||
|
||||
iobase = sc->sc_iobase;
|
||||
if (ISSBPROCLASS(sc) && sc->sc_dmadir != SBP_DMA_OUT) {
|
||||
/* make sure we re-set stereo mixer bit when we start
|
||||
output. */
|
||||
sbdsp_mix_write(sc, SBP_STEREO,
|
||||
(sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
|
||||
(sc->sc_chans == 2 ?
|
||||
SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
|
||||
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
|
||||
output. */
|
||||
sbdsp_mix_write(sc, SBP_STEREO,
|
||||
(sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
|
||||
(sc->sc_chans == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
|
||||
}
|
||||
|
||||
sbdsp_set_tc(sc, sc->sc_otc);
|
||||
sc->sc_dmadir = SB_DMA_OUT;
|
||||
}
|
||||
|
||||
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->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 ||
|
||||
sbdsp_wdsp(iobase, cc) < 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.
|
||||
|
@ -80,10 +80,6 @@ struct sbdsp_softc {
|
|||
int sc_drq; /* DMA */
|
||||
|
||||
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
|
||||
in a nibble */
|
||||
|
@ -95,9 +91,14 @@ struct sbdsp_softc {
|
|||
|
||||
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_HS 1
|
||||
u_short sc_adactc; /* current adac time constant */
|
||||
|
||||
u_long sc_interrupts; /* number of interrupts taken */
|
||||
void (*sc_intr)(void*); /* dma completion 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_chans; /* # of channels */
|
||||
int sc_dmadir; /* DMA direction */
|
||||
#define SBP_DMA_NONE 0
|
||||
#define SBP_DMA_IN 1
|
||||
#define SBP_DMA_OUT 2
|
||||
#define SB_DMA_NONE 0
|
||||
#define SB_DMA_IN 1
|
||||
#define SB_DMA_OUT 2
|
||||
|
||||
u_int sc_model; /* DSP model */
|
||||
#define SBVER_MAJOR(v) ((v)>>8)
|
||||
|
|
Loading…
Reference in New Issue