summaryrefslogtreecommitdiff
path: root/sys/dev/isa/sbdsp.c
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1996-04-18 23:48:25 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1996-04-18 23:48:25 +0000
commit76067dc38b59d22fa68139e9e0f6387455213fef (patch)
treea07a31d71b761635bad242646844c4ead9cdbed8 /sys/dev/isa/sbdsp.c
parent740ab8eb879aa7a6c29f0a9c83c747b8ae4988c9 (diff)
NetBSD 960317 merge
Diffstat (limited to 'sys/dev/isa/sbdsp.c')
-rw-r--r--sys/dev/isa/sbdsp.c1112
1 files changed, 714 insertions, 398 deletions
diff --git a/sys/dev/isa/sbdsp.c b/sys/dev/isa/sbdsp.c
index fb87ad28aa9..b5fcce0c5ea 100644
--- a/sys/dev/isa/sbdsp.c
+++ b/sys/dev/isa/sbdsp.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sbdsp.c,v 1.3 1996/03/08 16:43:14 niklas Exp $ */
-/* $NetBSD: sbdsp.c,v 1.16 1996/02/16 10:10:21 mycroft Exp $ */
+/* $OpenBSD: sbdsp.c,v 1.4 1996/04/18 23:47:47 niklas Exp $ */
+/* $NetBSD: sbdsp.c,v 1.24 1996/03/16 04:00:11 jtk Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -82,6 +82,10 @@ struct {
int wmidi;
} sberr;
+int sbdsp_srtotc __P((struct sbdsp_softc *sc, int sr, int isdac,
+ int *tcp, int *modep));
+u_int sbdsp_jazz16_probe __P((struct sbdsp_softc *));
+
/*
* Time constant routines follow. See SBK, section 12.
* Although they don't come out and say it (in the docs),
@@ -124,12 +128,13 @@ sb_printsc(struct sbdsp_softc *sc)
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("irate %d itc %d imode %d orate %d otc %d omode %d encoding %x\n",
+ sc->sc_irate, sc->sc_itc, sc->sc_imode,
+ sc->sc_orate, 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("chans %x intr %x arg %x\n",
- sc->sc_chans, sc->sc_intr, sc->sc_arg);
+ printf("precision %d channels %d intr %x arg %x\n",
+ sc->sc_precision, sc->sc_channels, sc->sc_intr, sc->sc_arg);
printf("gain: ");
for (i = 0; i < SB_NDEVS; i++)
printf("%d ", sc->gain[i]);
@@ -154,12 +159,63 @@ sbdsp_probe(sc)
DPRINTF(("sbdsp: couldn't reset card\n"));
return 0;
}
- sc->sc_model = sbversion(sc);
+ /* if flags set, go and probe the jazz16 stuff */
+ if (sc->sc_dev.dv_cfdata->cf_flags != 0)
+ sc->sc_model = sbdsp_jazz16_probe(sc);
+ else
+ sc->sc_model = sbversion(sc);
return 1;
}
/*
+ * Try add-on stuff for Jazz16.
+ */
+u_int
+sbdsp_jazz16_probe(sc)
+ struct sbdsp_softc *sc;
+{
+ static u_char jazz16_irq_conf[16] = {
+ -1, -1, 0x02, 0x03,
+ -1, 0x01, -1, 0x04,
+ -1, 0x02, 0x05, -1,
+ -1, -1, -1, 0x06};
+ static u_char jazz16_drq_conf[8] = {
+ -1, 0x01, -1, 0x02,
+ -1, 0x03, -1, 0x04};
+
+ u_int rval = sbversion(sc);
+ register int iobase = sc->sc_iobase;
+
+ if (jazz16_drq_conf[sc->sc_drq] == (u_char)-1 ||
+ jazz16_irq_conf[sc->sc_irq] == (u_char)-1)
+ return rval; /* give up, we can't do it. */
+ outb(JAZZ16_CONFIG_PORT, JAZZ16_WAKEUP);
+ delay(10000); /* delay 10 ms */
+ outb(JAZZ16_CONFIG_PORT, JAZZ16_SETBASE);
+ outb(JAZZ16_CONFIG_PORT, iobase & 0x70);
+
+ if (sbdsp_reset(sc) < 0)
+ return rval; /* XXX? what else could we do? */
+
+ if (sbdsp_wdsp(iobase, JAZZ16_READ_VER))
+ return rval;
+ if (sbdsp_rdsp(iobase) != JAZZ16_VER_JAZZ)
+ return rval;
+
+ if (sbdsp_wdsp(iobase, JAZZ16_SET_DMAINTR) ||
+ /* set both 8 & 16-bit drq to same channel, it works fine. */
+ sbdsp_wdsp(iobase,
+ (jazz16_drq_conf[sc->sc_drq] << 4) |
+ jazz16_drq_conf[sc->sc_drq]) ||
+ sbdsp_wdsp(iobase, jazz16_irq_conf[sc->sc_irq])) {
+ DPRINTF(("sbdsp: can't write jazz16 probe stuff"));
+ return rval;
+ }
+ return (rval | MODEL_JAZZ16);
+}
+
+/*
* Attach hardware to driver, attach hardware driver to audio
* pseudo-device driver .
*/
@@ -170,12 +226,15 @@ sbdsp_attach(sc)
register int iobase = sc->sc_iobase;
/* Set defaults */
- if (ISSBPROCLASS(sc))
- sc->sc_itc = sc->sc_otc = SBPRO_ADC_HS_MAX;
+ if (ISSB16CLASS(sc))
+ sc->sc_irate = sc->sc_orate = 8000;
+ else if (ISSBPROCLASS(sc))
+ sc->sc_itc = sc->sc_otc = SB_8K;
else
- sc->sc_itc = sc->sc_otc = SBCLA_ADC_HS_MAX;
- sc->sc_chans = 1;
- sc->encoding = AUDIO_ENCODING_LINEAR;
+ sc->sc_itc = sc->sc_otc = SB_8K;
+ sc->sc_precision = 8;
+ sc->sc_channels = 1;
+ sc->encoding = AUDIO_ENCODING_ULAW;
(void) sbdsp_set_in_port(sc, SB_MIC_PORT);
(void) sbdsp_set_out_port(sc, SB_SPEAKER);
@@ -192,15 +251,29 @@ sbdsp_attach(sc)
sbdsp_mix_write(sc, SBP_DAC_VOL,
sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL));
sbdsp_mix_write(sc, SBP_MASTER_VOL,
- sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL));
+ sbdsp_stereo_vol(SBP_MAXVOL/2, SBP_MAXVOL/2));
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->in_filter = 0; /* no filters turned on, please */
}
- printf(": dsp v%d.%02d\n",
- SBVER_MAJOR(sc->sc_model), SBVER_MINOR(sc->sc_model));
+ printf(": dsp v%d.%02d%s\n",
+ SBVER_MAJOR(sc->sc_model), SBVER_MINOR(sc->sc_model),
+ ISJAZZ16(sc) ? ": <Jazz16>" : "");
+
+#ifdef notyet
+ sbdsp_mix_write(sc, SBP_SET_IRQ, 0x04);
+ sbdsp_mix_write(sc, SBP_SET_DRQ, 0x22);
+
+ printf("sbdsp_attach: irq=%02x, drq=%02x\n",
+ sbdsp_mix_read(sc, SBP_SET_IRQ),
+ sbdsp_mix_read(sc, SBP_SET_DRQ));
+#else
+ if (ISSB16CLASS(sc))
+ sc->sc_model = 0x0300;
+#endif
}
/*
@@ -238,7 +311,10 @@ sbdsp_set_in_sr(addr, sr)
{
register struct sbdsp_softc *sc = addr;
- return (sbdsp_srtotc(sc, sr, SB_INPUT_RATE, &sc->sc_itc, &sc->sc_imode));
+ if (ISSB16CLASS(sc))
+ return (sbdsp_setrate(sc, sr, SB_INPUT_RATE, &sc->sc_irate));
+ else
+ return (sbdsp_srtotc(sc, sr, SB_INPUT_RATE, &sc->sc_itc, &sc->sc_imode));
}
u_long
@@ -247,7 +323,10 @@ sbdsp_get_in_sr(addr)
{
register struct sbdsp_softc *sc = addr;
- return (sbdsp_tctosr(sc, sc->sc_itc));
+ if (ISSB16CLASS(sc))
+ return (sc->sc_irate);
+ else
+ return (sbdsp_tctosr(sc, sc->sc_itc));
}
int
@@ -257,7 +336,10 @@ sbdsp_set_out_sr(addr, sr)
{
register struct sbdsp_softc *sc = addr;
- return (sbdsp_srtotc(sc, sr, SB_OUTPUT_RATE, &sc->sc_otc, &sc->sc_omode));
+ if (ISSB16CLASS(sc))
+ return (sbdsp_setrate(sc, sr, SB_OUTPUT_RATE, &sc->sc_orate));
+ else
+ return (sbdsp_srtotc(sc, sr, SB_OUTPUT_RATE, &sc->sc_otc, &sc->sc_omode));
}
u_long
@@ -266,7 +348,10 @@ sbdsp_get_out_sr(addr)
{
register struct sbdsp_softc *sc = addr;
- return (sbdsp_tctosr(sc, sc->sc_otc));
+ if (ISSB16CLASS(sc))
+ return (sc->sc_orate);
+ else
+ return (sbdsp_tctosr(sc, sc->sc_otc));
}
int
@@ -292,13 +377,13 @@ sbdsp_query_encoding(addr, fp)
}
int
-sbdsp_set_encoding(addr, enc)
+sbdsp_set_encoding(addr, encoding)
void *addr;
- u_int enc;
+ u_int encoding;
{
register struct sbdsp_softc *sc = addr;
- switch(enc){
+ switch (encoding) {
case AUDIO_ENCODING_ULAW:
sc->encoding = AUDIO_ENCODING_ULAW;
break;
@@ -308,6 +393,7 @@ sbdsp_set_encoding(addr, enc)
default:
return (EINVAL);
}
+
return (0);
}
@@ -321,13 +407,22 @@ sbdsp_get_encoding(addr)
}
int
-sbdsp_set_precision(addr, prec)
+sbdsp_set_precision(addr, precision)
void *addr;
- u_int prec;
+ u_int precision;
{
+ register struct sbdsp_softc *sc = addr;
+
+ if (ISSB16CLASS(sc) || ISJAZZ16(sc)) {
+ if (precision != 16 && precision != 8)
+ return (EINVAL);
+ sc->sc_precision = precision;
+ } else {
+ if (precision != 8)
+ return (EINVAL);
+ sc->sc_precision = precision;
+ }
- if (prec != 8)
- return (EINVAL);
return (0);
}
@@ -335,36 +430,32 @@ int
sbdsp_get_precision(addr)
void *addr;
{
- return (8);
+ register struct sbdsp_softc *sc = addr;
+
+ return (sc->sc_precision);
}
int
-sbdsp_set_channels(addr, chans)
+sbdsp_set_channels(addr, channels)
void *addr;
- int chans;
+ int channels;
{
register struct sbdsp_softc *sc = addr;
if (ISSBPROCLASS(sc)) {
- if (chans != 1 && chans != 2)
+ if (channels != 1 && channels != 2)
return (EINVAL);
- sc->sc_chans = chans;
-
-#if 0
- if (rval = sbdsp_set_in_sr_real(addr, sc->sc_irate))
- 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. */
+ sc->sc_channels = channels;
+ sc->sc_dmadir = SB_DMA_NONE;
+ /*
+ * XXXX
+ * With 2 channels, SBPro can't do more than 22kHz.
+ * No framework to check this.
+ */
} else {
- if (chans != 1)
+ if (channels != 1)
return (EINVAL);
- sc->sc_chans = chans;
+ sc->sc_channels = channels;
}
return (0);
@@ -376,18 +467,59 @@ sbdsp_get_channels(addr)
{
register struct sbdsp_softc *sc = addr;
-#if 0
- /* recording stereo may frob the mixer output */
+ return (sc->sc_channels);
+}
+
+int
+sbdsp_set_ifilter(addr, which)
+ void *addr;
+ int which;
+{
+ register struct sbdsp_softc *sc = addr;
+ int rval, mixval;
+
if (ISSBPROCLASS(sc)) {
- if ((sbdsp_mix_read(sc, SBP_STEREO) & SBP_PLAYMODE_MASK) == SBP_PLAYMODE_STEREO)
- sc->sc_chans = 2;
- else
- sc->sc_chans = 1;
+ mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
+ switch (which) {
+ case 0:
+ mixval |= SBP_FILTER_OFF;
+ break;
+ case SBP_TREBLE_EQ:
+ mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
+ break;
+ case SBP_BASS_EQ:
+ mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
+ break;
+ default:
+ return (EINVAL);
+ }
+ sc->in_filter = mixval & SBP_IFILTER_MASK;
+ sbdsp_mix_write(sc, SBP_INFILTER, mixval);
+ return (0);
} else
- sc->sc_chans = 1;
-#endif
+ return (EINVAL);
+}
- return (sc->sc_chans);
+int
+sbdsp_get_ifilter(addr)
+ void *addr;
+{
+ register struct sbdsp_softc *sc = addr;
+
+ if (ISSBPROCLASS(sc)) {
+ sc->in_filter =
+ sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
+ switch (sc->in_filter) {
+ case SBP_FILTER_ON|SBP_IFILTER_HIGH:
+ return (SBP_TREBLE_EQ);
+ case SBP_FILTER_ON|SBP_IFILTER_LOW:
+ return (SBP_BASS_EQ);
+ case SBP_FILTER_OFF:
+ default:
+ return (0);
+ }
+ } else
+ return (0);
}
int
@@ -455,8 +587,7 @@ sbdsp_set_in_port(addr, port)
if (ISSBPROCLASS(sc)) {
/* record from that port */
sbdsp_mix_write(sc, SBP_RECORD_SOURCE,
- SBP_RECORD_FROM(sbport, SBP_FILTER_OFF,
- SBP_FILTER_HIGH));
+ SBP_RECORD_FROM(sbport, SBP_FILTER_OFF, SBP_IFILTER_HIGH));
/* fetch gain from that port */
sc->gain[port] = sbdsp_mix_read(sc, mixport);
}
@@ -504,13 +635,19 @@ 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_otc > SB_8K || sc->sc_itc > SB_8K) &&
- (blk > NBPG/2 || blk < NBPG/4))
- blk = NBPG/2;
+ if (blk < NBPG/4 || blk > NBPG/2) {
+ if (ISSB16CLASS(sc)) {
+ if (sc->sc_orate > 8000 || sc->sc_irate > 8000)
+ blk = NBPG/2;
+ } else {
+ if (sc->sc_otc > SB_8K || sc->sc_itc < SB_8K)
+ blk = NBPG/2;
+ }
+ }
/* don't try to DMA too much at once, though. */
if (blk > NBPG)
blk = NBPG;
- if (sc->sc_chans == 2)
+ if (sc->sc_channels == 2)
return (blk & ~1); /* must be even to preserve stereo separation */
else
return (blk); /* Anything goes :-) */
@@ -527,6 +664,40 @@ sbdsp_commit_settings(addr)
(adjust the proper channels), number of input channels (hit the
record rate and set mode) */
+ if (ISSBPRO(sc)) {
+ /*
+ * With 2 channels, SBPro can't do more than 22kHz.
+ * Whack the rates down to speed if necessary.
+ * Reset the time constant anyway
+ * because it may have been adjusted with a different number
+ * of channels, which means it might have computed the wrong
+ * mode (low/high speed).
+ */
+ if (sc->sc_channels == 2 &&
+ sbdsp_tctosr(sc, sc->sc_itc) > 22727) {
+ sbdsp_srtotc(sc, 22727, SB_INPUT_RATE,
+ &sc->sc_itc, &sc->sc_imode);
+ } else
+ sbdsp_srtotc(sc, sbdsp_tctosr(sc, sc->sc_itc),
+ SB_INPUT_RATE, &sc->sc_itc,
+ &sc->sc_imode);
+
+ if (sc->sc_channels == 2 &&
+ sbdsp_tctosr(sc, sc->sc_otc) > 22727) {
+ sbdsp_srtotc(sc, 22727, SB_OUTPUT_RATE,
+ &sc->sc_otc, &sc->sc_omode);
+ } else
+ sbdsp_srtotc(sc, sbdsp_tctosr(sc, sc->sc_otc),
+ SB_OUTPUT_RATE, &sc->sc_otc,
+ &sc->sc_omode);
+ }
+ if (ISSB16CLASS(sc) || ISJAZZ16(sc)) {
+ if (sc->encoding == AUDIO_ENCODING_ULAW &&
+ sc->sc_precision == 16) {
+ sc->sc_precision = 8;
+ return EINVAL; /* XXX what should we really do? */
+ }
+ }
/*
* XXX
* Should wait for chip to be idle.
@@ -620,6 +791,24 @@ sbdsp_reset(sc)
return 0;
}
+int
+sbdsp16_wait(iobase)
+ int iobase;
+{
+ register int i;
+
+ for (i = SBDSP_NPOLL; --i >= 0; ) {
+ register u_char x;
+ x = inb(iobase + SBP_DSP_WSTAT);
+ delay(10);
+ if ((x & SB_DSP_BUSY) == 0)
+ continue;
+ return 0;
+ }
+ ++sberr.wdsp;
+ return -1;
+}
+
/*
* Write a byte to the dsp.
* XXX We are at the mercy of the card as we use a
@@ -763,6 +952,24 @@ sbdsp_contdma(addr)
return(0);
}
+int
+sbdsp_setrate(sc, sr, isdac, ratep)
+ register struct sbdsp_softc *sc;
+ int sr;
+ int isdac;
+ int *ratep;
+{
+
+ /*
+ * XXXX
+ * More checks here?
+ */
+ if (sr < 5000 || sr > 44100)
+ return (EINVAL);
+ *ratep = sr;
+ return (0);
+}
+
/*
* Convert a linear sampling rate into the DAC time constant.
* Set *mode to indicate the high/low-speed DMA operation.
@@ -778,8 +985,13 @@ sbdsp_srtotc(sc, sr, isdac, tcp, modep)
int isdac;
int *tcp, *modep;
{
- int tc, mode;
+ int tc, realtc, mode;
+ /*
+ * Don't forget to compute which mode we'll be in based on whether
+ * we need to double the rate for stereo on SBPRO.
+ */
+
if (sr == 0) {
tc = SB_LS_MIN;
mode = SB_ADAC_LS;
@@ -787,13 +999,20 @@ sbdsp_srtotc(sc, sr, isdac, tcp, modep)
}
tc = 256 - (1000000 / sr);
+
+ if (sc->sc_channels == 2 && ISSBPRO(sc))
+ /* compute based on 2x sample rate when needed */
+ realtc = 256 - ( 500000 / sr);
+ else
+ realtc = tc;
if (tc < SB_LS_MIN) {
tc = SB_LS_MIN;
- mode = SB_ADAC_LS;
+ mode = SB_ADAC_LS; /* NB: 2x minimum speed is still low
+ * speed mode. */
goto out;
} else if (isdac) {
- if (tc <= SB_DAC_LS_MAX)
+ if (realtc <= SB_DAC_LS_MAX)
mode = SB_ADAC_LS;
else {
mode = SB_ADAC_HS;
@@ -813,7 +1032,7 @@ sbdsp_srtotc(sc, sr, isdac, tcp, modep)
adc_hs_max = SBCLA_ADC_HS_MAX;
}
- if (tc <= adc_ls_max)
+ if (realtc <= adc_ls_max)
mode = SB_ADAC_LS;
else {
mode = SB_ADAC_HS;
@@ -851,7 +1070,7 @@ sbdsp_tctosr(sc, tc)
}
int
-sbdsp_set_tc(sc, tc)
+sbdsp_set_timeconst(sc, tc)
register struct sbdsp_softc *sc;
int tc;
{
@@ -861,10 +1080,10 @@ sbdsp_set_tc(sc, tc)
* A SBPro in stereo mode uses time constants at double the
* actual rate.
*/
- if (ISSBPRO(sc) && sc->sc_chans == 2)
+ if (ISSBPRO(sc) && sc->sc_channels == 2)
tc = 256 - ((256 - tc) / 2);
- DPRINTF(("sbdsp_set_tc: sc=%p tc=%d\n", sc, tc));
+ DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
iobase = sc->sc_iobase;
if (sbdsp_wdsp(iobase, SB_DSP_TIMECONST) < 0 ||
@@ -889,48 +1108,81 @@ sbdsp_dma_input(addr, p, cc, intr, arg)
if (sbdspdebug > 1)
Dprintf("sbdsp_dma_input: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
#endif
- if (sc->sc_chans == 2 && (cc & 1)) {
+ if (sc->sc_channels == 2 && (cc & 1)) {
DPRINTF(("sbdsp_dma_input: stereo input, odd bytecnt\n"));
return EIO;
}
iobase = sc->sc_iobase;
if (sc->sc_dmadir != SB_DMA_IN) {
- if (ISSBPROCLASS(sc)) {
- if (sc->sc_chans == 2) {
- if (sbdsp_wdsp(iobase, SB_DSP_RECORD_STEREO) < 0)
+ if (ISSBPRO(sc)) {
+ if (sc->sc_channels == 2) {
+ if (ISJAZZ16(sc) && sc->sc_precision == 16) {
+ if (sbdsp_wdsp(iobase,
+ JAZZ16_RECORD_STEREO) < 0) {
+ goto badmode;
+ }
+ } else 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);
+ (sbdsp_mix_read(sc, SBP_INFILTER) &
+ ~SBP_IFILTER_MASK) | SBP_FILTER_OFF);
} else {
- if (sbdsp_wdsp(iobase, SB_DSP_RECORD_MONO) < 0)
+ if (ISJAZZ16(sc) && sc->sc_precision == 16) {
+ if (sbdsp_wdsp(iobase,
+ JAZZ16_RECORD_MONO) < 0)
+ {
+ goto badmode;
+ }
+ } 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);
+ sbdsp_mix_write(sc, SBP_INFILTER,
+ (sbdsp_mix_read(sc, SBP_INFILTER) &
+ ~SBP_IFILTER_MASK) | sc->in_filter);
}
}
- sbdsp_set_tc(sc, sc->sc_itc);
+ if (ISSB16CLASS(sc)) {
+ if (sbdsp_wdsp(iobase, SB_DSP16_INPUTRATE) < 0 ||
+ sbdsp_wdsp(iobase, sc->sc_irate >> 8) < 0 ||
+ sbdsp_wdsp(iobase, sc->sc_irate) < 0)
+ goto giveup;
+ } else
+ sbdsp_set_timeconst(sc, sc->sc_itc);
sc->sc_dmadir = SB_DMA_IN;
}
- isa_dmastart(B_READ, p, cc, sc->sc_drq);
+ isa_dmastart(DMAMODE_READ, p, cc, sc->sc_drq);
sc->sc_intr = intr;
sc->sc_arg = arg;
- sc->dmaflags = B_READ;
+ sc->dmaflags = DMAMODE_READ;
sc->dmaaddr = p;
- sc->dmacnt = --cc; /* DMA controller is strange...? */
-
- if (sc->sc_imode == SB_ADAC_LS) {
+ sc->dmacnt = cc; /* DMA controller is strange...? */
+
+ if ((ISSB16CLASS(sc) && sc->sc_precision == 16) ||
+ (ISJAZZ16(sc) && sc->sc_drq > 3))
+ cc >>= 1;
+ --cc;
+ if (ISSB16CLASS(sc)) {
+ if (sbdsp_wdsp(iobase, sc->sc_precision == 16 ? SB_DSP16_RDMA_16 :
+ SB_DSP16_RDMA_8) < 0 ||
+ sbdsp_wdsp(iobase, (sc->sc_precision == 16 ? 0x10 : 0x00) |
+ (sc->sc_channels == 2 ? 0x20 : 0x00)) < 0 ||
+ sbdsp16_wait(iobase) ||
+ sbdsp_wdsp(iobase, cc) < 0 ||
+ sbdsp_wdsp(iobase, cc >> 8) < 0) {
+ DPRINTF(("sbdsp_dma_input: SB16 DMA start failed\n"));
+ goto giveup;
+ }
+ } else 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) {
DPRINTF(("sbdsp_dma_input: LS DMA start failed\n"));
goto giveup;
}
- }
- else {
+ } else {
if (cc != sc->sc_last_hs_size) {
if (sbdsp_wdsp(iobase, SB_DSP_BLOCKSIZE) < 0 ||
sbdsp_wdsp(iobase, cc) < 0 ||
@@ -953,7 +1205,7 @@ giveup:
badmode:
DPRINTF(("sbdsp_dma_input: can't set %s mode\n",
- sc->sc_chans == 2 ? "stereo" : "mono"));
+ sc->sc_channels == 2 ? "stereo" : "mono"));
return EIO;
}
@@ -972,41 +1224,76 @@ sbdsp_dma_output(addr, p, cc, intr, arg)
if (sbdspdebug > 1)
Dprintf("sbdsp_dma_output: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
#endif
- if (sc->sc_chans == 2 && (cc & 1)) {
+ if (sc->sc_channels == 2 && (cc & 1)) {
DPRINTF(("stereo playback odd bytes (%d)\n", cc));
return EIO;
}
iobase = sc->sc_iobase;
if (sc->sc_dmadir != SB_DMA_OUT) {
- if (ISSBPROCLASS(sc)) {
+ if (ISSBPRO(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));
+ (sc->sc_channels == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
+ if (ISJAZZ16(sc)) {
+ /* Yes, we write the record mode to set
+ 16-bit playback mode. weird, huh? */
+ if (sc->sc_precision == 16) {
+ sbdsp_wdsp(iobase,
+ sc->sc_channels == 2 ?
+ JAZZ16_RECORD_STEREO :
+ JAZZ16_RECORD_MONO);
+ } else {
+ sbdsp_wdsp(iobase,
+ sc->sc_channels == 2 ?
+ SB_DSP_RECORD_STEREO :
+ SB_DSP_RECORD_MONO);
+ }
+ }
}
- sbdsp_set_tc(sc, sc->sc_otc);
+ if (ISSB16CLASS(sc)) {
+ if (sbdsp_wdsp(iobase, SB_DSP16_OUTPUTRATE) < 0 ||
+ sbdsp_wdsp(iobase, sc->sc_orate >> 8) < 0 ||
+ sbdsp_wdsp(iobase, sc->sc_orate) < 0)
+ goto giveup;
+ } else
+ sbdsp_set_timeconst(sc, sc->sc_otc);
sc->sc_dmadir = SB_DMA_OUT;
}
- isa_dmastart(B_WRITE, p, cc, sc->sc_drq);
+ isa_dmastart(DMAMODE_WRITE, p, cc, sc->sc_drq);
sc->sc_intr = intr;
sc->sc_arg = arg;
- sc->dmaflags = B_WRITE;
+ sc->dmaflags = DMAMODE_WRITE;
sc->dmaaddr = p;
- sc->dmacnt = --cc; /* a vagary of how DMA works, apparently. */
-
- if (sc->sc_omode == SB_ADAC_LS) {
+ sc->dmacnt = cc; /* a vagary of how DMA works, apparently. */
+
+ if ((ISSB16CLASS(sc) && sc->sc_precision == 16) ||
+ (ISJAZZ16(sc) && sc->sc_drq > 3))
+ cc >>= 1;
+ --cc;
+ if (ISSB16CLASS(sc)) {
+ if (sbdsp_wdsp(iobase, sc->sc_precision == 16 ? SB_DSP16_WDMA_16 :
+ SB_DSP16_WDMA_8) < 0 ||
+ sbdsp_wdsp(iobase, (sc->sc_precision == 16 ? 0x10 : 0x00) |
+ (sc->sc_channels == 2 ? 0x20 : 0x00)) < 0 ||
+ sbdsp16_wait(iobase) ||
+ sbdsp_wdsp(iobase, cc) < 0 ||
+ sbdsp_wdsp(iobase, cc >> 8) < 0) {
+ DPRINTF(("sbdsp_dma_output: SB16 DMA start failed\n"));
+ goto giveup;
+ }
+ } else 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) {
DPRINTF(("sbdsp_dma_output: LS DMA start failed\n"));
goto giveup;
}
- }
- else {
+ } else {
if (cc != sc->sc_last_hs_size) {
if (sbdsp_wdsp(iobase, SB_DSP_BLOCKSIZE) < 0 ||
sbdsp_wdsp(iobase, cc) < 0 ||
@@ -1046,34 +1333,26 @@ sbdsp_intr(arg)
if (sbdspdebug > 1)
Dprintf("sbdsp_intr: intr=0x%x\n", sc->sc_intr);
#endif
+ if (!isa_dmafinished(sc->sc_drq)) {
+ printf("sbdsp_intr: not finished\n");
+ return 0;
+ }
sc->sc_interrupts++;
/* clear interrupt */
+#ifdef notyet
+ x = sbdsp_mix_read(sc, 0x82);
+ x = inb(sc->sc_iobase + 15);
+#endif
x = inb(sc->sc_iobase + SBP_DSP_RSTAT);
delay(10);
#if 0
- if ((x & SB_DSP_READY) == 0) {
- printf("sbdsp_intr: still busy\n");
- return 0;
- }
-#endif
-#if 0
if (sc->sc_mintr != 0) {
x = sbdsp_rdsp(sc->sc_iobase);
(*sc->sc_mintr)(sc->sc_arg, x);
} else
#endif
if (sc->sc_intr != 0) {
- /*
- * The SBPro used to develop and test this driver often
- * generated dma underruns--it interrupted to signal
- * completion of the DMA input recording block, but the
- * ISA DMA controller didn't think the channel was
- * finished. Maybe this is just a bus speed issue, I dunno,
- * but it seems strange and leads to channel-flipping with
- * stereo recording. Sigh.
- */
- isa_dmadone(sc->dmaflags, sc->dmaaddr, sc->dmacnt,
- sc->sc_drq);
+ isa_dmadone(sc->dmaflags, sc->dmaaddr, sc->dmacnt, sc->sc_drq);
(*sc->sc_intr)(sc->sc_arg);
}
else
@@ -1121,24 +1400,24 @@ sbdsp_midi_output(sc, v)
#endif
u_int
-sbdsp_get_silence(enc)
- int enc;
+sbdsp_get_silence(encoding)
+ int encoding;
{
#define ULAW_SILENCE 0x7f
#define LINEAR_SILENCE 0
- u_int auzero;
+ u_int auzero;
- switch (enc) {
- case AUDIO_ENCODING_ULAW:
- auzero = ULAW_SILENCE;
- break;
- case AUDIO_ENCODING_PCM16:
- default:
- auzero = LINEAR_SILENCE;
- break;
- }
-
- return(auzero);
+ switch (encoding) {
+ case AUDIO_ENCODING_ULAW:
+ auzero = ULAW_SILENCE;
+ break;
+ case AUDIO_ENCODING_PCM16:
+ default:
+ auzero = LINEAR_SILENCE;
+ break;
+ }
+
+ return (auzero);
}
int
@@ -1152,301 +1431,338 @@ sbdsp_setfd(addr, flag)
int
sbdsp_mixer_set_port(addr, cp)
- void *addr;
- mixer_ctrl_t *cp;
+ void *addr;
+ mixer_ctrl_t *cp;
{
- register struct sbdsp_softc *sc = addr;
- int error = 0;
- int src, gain;
- int left, right;
+ register struct sbdsp_softc *sc = addr;
+ int src, gain;
- DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev, cp->un.value.num_channels));
-
- /*
- * Everything is a value except for SBPro special OUTPUT_MODE and
- * RECORD_SOURCE
- */
- if (cp->type != AUDIO_MIXER_VALUE) {
- if (!ISSBPROCLASS(sc) || (cp->dev != SB_OUTPUT_MODE &&
- cp->dev != SB_RECORD_SOURCE))
- return EINVAL;
- }
- else {
+ DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
+ cp->un.value.num_channels));
+
+ if (!ISSBPROCLASS(sc))
+ return EINVAL;
+
/*
- * All the mixer ports are stereo except for the microphone.
- * If we get a single-channel gain value passed in, then we
- * duplicate it to both left and right channels.
- */
- if (cp->un.value.num_channels == 2) {
- left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
- right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
- }
- else
- left = right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
- }
-
- if (ISSBPROCLASS(sc)) {
- /* The _PORT things are all signal inputs to the mixer.
- * Here we are tweaking their mixing level.
- *
- * We can also tweak the output stage volume (MASTER_VOL)
+ * Everything is a value except for SBPro BASS/TREBLE and
+ * RECORD_SOURCE
*/
- gain = sbdsp_stereo_vol(SBP_AGAIN_TO_SBGAIN(left),
- SBP_AGAIN_TO_SBGAIN(right));
- switch(cp->dev) {
- case SB_MIC_PORT:
- src = SBP_MIC_VOL;
- if (cp->un.value.num_channels != 1)
- error = EINVAL;
- else
- /* handle funny microphone gain */
- gain = SBP_AGAIN_TO_MICGAIN(left);
- break;
- case SB_LINE_IN_PORT:
- src = SBP_LINE_VOL;
- break;
- case SB_DAC_PORT:
- src = SBP_DAC_VOL;
- break;
- case SB_FM_PORT:
- src = SBP_FM_VOL;
- break;
- case SB_CD_PORT:
- src = SBP_CD_VOL;
- break;
+ switch (cp->dev) {
case SB_SPEAKER:
- cp->dev = SB_MASTER_VOL;
- case SB_MASTER_VOL:
- src = SBP_MASTER_VOL;
- break;
-#if 0
- case SB_OUTPUT_MODE:
- if (cp->type == AUDIO_MIXER_ENUM)
- return sbdsp_set_channels(addr, cp->un.ord);
- /* fall through...carefully! */
-#endif
+ cp->dev = SB_MASTER_VOL;
+ case SB_MIC_PORT:
+ case SB_LINE_IN_PORT:
+ case SB_DAC_PORT:
+ case SB_FM_PORT:
+ case SB_CD_PORT:
+ case SB_MASTER_VOL:
+ if (cp->type != AUDIO_MIXER_VALUE)
+ return EINVAL;
+
+ /*
+ * All the mixer ports are stereo except for the microphone.
+ * If we get a single-channel gain value passed in, then we
+ * duplicate it to both left and right channels.
+ */
+
+ switch (cp->dev) {
+ case SB_MIC_PORT:
+ if (cp->un.value.num_channels != 1)
+ return EINVAL;
+
+ /* handle funny microphone gain */
+ gain = SBP_AGAIN_TO_MICGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
+ break;
+ case SB_LINE_IN_PORT:
+ case SB_DAC_PORT:
+ case SB_FM_PORT:
+ case SB_CD_PORT:
+ case SB_MASTER_VOL:
+ switch (cp->un.value.num_channels) {
+ case 1:
+ gain = sbdsp_mono_vol(SBP_AGAIN_TO_SBGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]));
+ break;
+ case 2:
+ gain = sbdsp_stereo_vol(SBP_AGAIN_TO_SBGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]),
+ SBP_AGAIN_TO_SBGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]));
+ break;
+ default:
+ return EINVAL;
+ }
+ break;
+ }
+
+ switch (cp->dev) {
+ case SB_MIC_PORT:
+ src = SBP_MIC_VOL;
+ break;
+ case SB_MASTER_VOL:
+ src = SBP_MASTER_VOL;
+ break;
+ case SB_LINE_IN_PORT:
+ src = SBP_LINE_VOL;
+ break;
+ case SB_DAC_PORT:
+ src = SBP_DAC_VOL;
+ break;
+ case SB_FM_PORT:
+ src = SBP_FM_VOL;
+ break;
+ case SB_CD_PORT:
+ src = SBP_CD_VOL;
+ break;
+ }
+
+ sbdsp_mix_write(sc, src, gain);
+ sc->gain[cp->dev] = gain;
+ break;
+
+ case SB_TREBLE:
+ case SB_BASS:
case SB_RECORD_SOURCE:
- if (cp->type == AUDIO_MIXER_ENUM)
- return sbdsp_set_in_port(addr, cp->un.ord);
- /* else fall through: bad input */
- case SB_TREBLE:
- case SB_BASS:
- default:
- error = EINVAL;
- break;
- }
- if (!error)
- sbdsp_mix_write(sc, src, gain);
- }
- else if (cp->dev != SB_MIC_PORT &&
- cp->dev != SB_SPEAKER)
- error = EINVAL;
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+
+ switch (cp->dev) {
+ case SB_TREBLE:
+ return sbdsp_set_ifilter(addr, cp->un.ord ? SBP_TREBLE_EQ : 0);
+ case SB_BASS:
+ return sbdsp_set_ifilter(addr, cp->un.ord ? SBP_BASS_EQ : 0);
+ case SB_RECORD_SOURCE:
+ return sbdsp_set_in_port(addr, cp->un.ord);
+ }
+
+ break;
- if (!error)
- sc->gain[cp->dev] = gain;
+ default:
+ return EINVAL;
+ }
- return(error);
+ return (0);
}
int
sbdsp_mixer_get_port(addr, cp)
- void *addr;
- mixer_ctrl_t *cp;
+ void *addr;
+ mixer_ctrl_t *cp;
{
- register struct sbdsp_softc *sc = addr;
- int error = 0;
- int done = 0;
+ register struct sbdsp_softc *sc = addr;
+ int gain;
- DPRINTF(("sbdsp_mixer_get_port: port=%d", cp->dev));
-
- if (ISSBPROCLASS(sc))
- switch(cp->dev) {
- case SB_MIC_PORT:
- if (cp->un.value.num_channels == 1) {
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
- SBP_MICGAIN_TO_AGAIN(sc->gain[cp->dev]);
- return 0;
- }
- else
+ DPRINTF(("sbdsp_mixer_get_port: port=%d", cp->dev));
+
+ if (!ISSBPROCLASS(sc))
return EINVAL;
- break;
- case SB_LINE_IN_PORT:
- case SB_DAC_PORT:
- case SB_FM_PORT:
- case SB_CD_PORT:
- case SB_MASTER_VOL:
- break;
+
+ switch (cp->dev) {
case SB_SPEAKER:
- cp->dev = SB_MASTER_VOL;
- break;
- default:
- error = EINVAL;
- break;
- }
- else {
- if (cp->un.value.num_channels != 1) /* no stereo on SB classic */
- error = EINVAL;
- else
- switch(cp->dev) {
- case SB_MIC_PORT:
- break;
- case SB_SPEAKER:
+ cp->dev = SB_MASTER_VOL;
+ case SB_MIC_PORT:
+ case SB_LINE_IN_PORT:
+ case SB_DAC_PORT:
+ case SB_FM_PORT:
+ case SB_CD_PORT:
+ case SB_MASTER_VOL:
+ gain = sc->gain[cp->dev];
+
+ switch (cp->dev) {
+ case SB_MIC_PORT:
+ if (cp->un.value.num_channels != 1)
+ return EINVAL;
+
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = SBP_MICGAIN_TO_AGAIN(gain);
+ break;
+ case SB_LINE_IN_PORT:
+ case SB_DAC_PORT:
+ case SB_FM_PORT:
+ case SB_CD_PORT:
+ case SB_MASTER_VOL:
+ switch (cp->un.value.num_channels) {
+ case 1:
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = SBP_SBGAIN_TO_AGAIN(gain);
+ break;
+ case 2:
+ cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = SBP_LEFTGAIN(gain);
+ cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = SBP_RIGHTGAIN(gain);
+ break;
+ default:
+ return EINVAL;
+ }
+ break;
+ }
+
break;
- default:
- error = EINVAL;
+
+ case SB_TREBLE:
+ case SB_BASS:
+ case SB_RECORD_SOURCE:
+ switch (cp->dev) {
+ case SB_TREBLE:
+ cp->un.ord = sbdsp_get_ifilter(addr) == SBP_TREBLE_EQ;
+ return 0;
+ case SB_BASS:
+ cp->un.ord = sbdsp_get_ifilter(addr) == SBP_BASS_EQ;
+ return 0;
+ case SB_RECORD_SOURCE:
+ cp->un.ord = sbdsp_get_in_port(addr);
+ return 0;
+ }
+
break;
- }
- }
- if (error == 0) {
- if (cp->un.value.num_channels == 1) {
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
- SBP_SBGAIN_TO_AGAIN(sc->gain[cp->dev]);
+
+ default:
+ return EINVAL;
}
- else if (cp->un.value.num_channels == 2) {
- cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
- SBP_LEFTGAIN(sc->gain[cp->dev]);
- cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
- SBP_RIGHTGAIN(sc->gain[cp->dev]);
- } else
- return EINVAL;
- }
- return(error);
+
+ return (0);
}
int
sbdsp_mixer_query_devinfo(addr, dip)
- void *addr;
- register mixer_devinfo_t *dip;
+ void *addr;
+ register mixer_devinfo_t *dip;
{
- register struct sbdsp_softc *sc = addr;
- int done = 0;
-
- DPRINTF(("sbdsp_mixer_query_devinfo: index=%d\n", dip->index));
-
- switch (dip->index) {
- case SB_MIC_PORT:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNmicrophone);
- dip->un.v.num_channels = 1;
- strcpy(dip->un.v.units.name, AudioNvolume);
- done = 1;
- break;
- case SB_SPEAKER:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_OUTPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNspeaker);
- dip->un.v.num_channels = 1;
- strcpy(dip->un.v.units.name, AudioNvolume);
- done = 1;
- break;
- case SB_INPUT_CLASS:
- dip->type = AUDIO_MIXER_CLASS;
- dip->mixer_class = SB_INPUT_CLASS;
- dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCInputs);
- done = 1;
- break;
- case SB_OUTPUT_CLASS:
- dip->type = AUDIO_MIXER_CLASS;
- dip->mixer_class = SB_OUTPUT_CLASS;
- dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCOutputs);
- done = 1;
- break;
- }
-
- if (!done) {
- if (ISSBPROCLASS(sc))
- switch(dip->index) {
- case SB_LINE_IN_PORT:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNline);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- break;
- case SB_DAC_PORT:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_OUTPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNdac);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- break;
- case SB_CD_PORT:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNcd);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- break;
- case SB_FM_PORT:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_OUTPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNfmsynth);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- break;
- case SB_MASTER_VOL:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_OUTPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = /*TREBLE, BASS not handled, nor is SB_OUTPUT_MODE*/SB_RECORD_SOURCE;
- strcpy(dip->label.name, AudioNvolume);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- break;
-#if 0
- case SB_OUTPUT_MODE:
- dip->mixer_class = SB_OUTPUT_CLASS;
- dip->type = AUDIO_MIXER_ENUM;
- dip->prev = SB_MASTER_VOL;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNmode);
- dip->un.e.num_mem = 2;
- strcpy(dip->un.e.member[0].label.name, AudioNmono);
- dip->un.e.member[0].ord = 1; /* nchans */
- strcpy(dip->un.e.member[1].label.name, AudioNstereo);
- dip->un.e.member[1].ord = 2; /* nchans */
- break;
-#endif
- case SB_RECORD_SOURCE:
- dip->mixer_class = SB_RECORD_CLASS;
- dip->type = AUDIO_MIXER_ENUM;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNsource);
- dip->un.e.num_mem = 3;
- strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
- dip->un.e.member[0].ord = SB_MIC_PORT;
- strcpy(dip->un.e.member[1].label.name, AudioNcd);
- dip->un.e.member[1].ord = SB_CD_PORT;
- strcpy(dip->un.e.member[2].label.name, AudioNline);
- dip->un.e.member[2].ord = SB_LINE_IN_PORT;
- break;
- case SB_BASS:
- case SB_TREBLE:
- default:
- return ENXIO;
- /*NOTREACHED*/
- }
- else
- return ENXIO;
- }
+ register struct sbdsp_softc *sc = addr;
- DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
+ DPRINTF(("sbdsp_mixer_query_devinfo: index=%d\n", dip->index));
+
+ switch (dip->index) {
+ case SB_MIC_PORT:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNmicrophone);
+ dip->un.v.num_channels = 1;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_SPEAKER:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNspeaker);
+ dip->un.v.num_channels = 1;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
- return 0;
+ case SB_INPUT_CLASS:
+ dip->type = AUDIO_MIXER_CLASS;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->next = dip->prev = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioCInputs);
+ return 0;
+
+ case SB_OUTPUT_CLASS:
+ dip->type = AUDIO_MIXER_CLASS;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ dip->next = dip->prev = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioCOutputs);
+ return 0;
+ }
+
+ if (ISSBPROCLASS(sc)) {
+ switch (dip->index) {
+ case SB_LINE_IN_PORT:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNline);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_DAC_PORT:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNdac);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_CD_PORT:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNcd);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_FM_PORT:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNfmsynth);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_MASTER_VOL:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNvolume);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_RECORD_SOURCE:
+ dip->mixer_class = SB_RECORD_CLASS;
+ dip->type = AUDIO_MIXER_ENUM;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNsource);
+ dip->un.e.num_mem = 3;
+ strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
+ dip->un.e.member[0].ord = SB_MIC_PORT;
+ strcpy(dip->un.e.member[1].label.name, AudioNcd);
+ dip->un.e.member[1].ord = SB_CD_PORT;
+ strcpy(dip->un.e.member[2].label.name, AudioNline);
+ dip->un.e.member[2].ord = SB_LINE_IN_PORT;
+ return 0;
+
+ case SB_BASS:
+ dip->type = AUDIO_MIXER_ENUM;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNbass);
+ dip->un.e.num_mem = 2;
+ strcpy(dip->un.e.member[0].label.name, AudioNoff);
+ dip->un.e.member[0].ord = 0;
+ strcpy(dip->un.e.member[1].label.name, AudioNon);
+ dip->un.e.member[1].ord = 1;
+ return 0;
+
+ case SB_TREBLE:
+ dip->type = AUDIO_MIXER_ENUM;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNtreble);
+ dip->un.e.num_mem = 2;
+ strcpy(dip->un.e.member[0].label.name, AudioNoff);
+ dip->un.e.member[0].ord = 0;
+ strcpy(dip->un.e.member[1].label.name, AudioNon);
+ dip->un.e.member[1].ord = 1;
+ return 0;
+
+ case SB_RECORD_CLASS: /* record source class */
+ dip->type = AUDIO_MIXER_CLASS;
+ dip->mixer_class = SB_RECORD_CLASS;
+ dip->next = dip->prev = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioCRecord);
+ return 0;
+ }
+ }
+
+ return ENXIO;
}