Subject: port-i386/1687: SoundBlaster driver mixer needs some help; input filter modes
To: None <gnats-bugs@gnats.netbsd.org>
From: John Kohl <jtk@kolvir.arlington.ma.us>
List: netbsd-bugs
Date: 10/24/1995 22:02:00
>Number: 1687
>Category: port-i386
>Synopsis: SoundBlaster driver mixer needs some help; input filter modes
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Oct 24 22:50:01 1995
>Last-Modified:
>Originator: John Kohl
>Organization:
NetBSD Kernel Hackers `R` Us
>Release: NetBSD-current, 1995/10/24
>Environment:
System: NetBSD pattern 1.1_ALPHA NetBSD 1.1_ALPHA (PATTERN) #195: Sun Oct 22 13:31:09 EDT 1995 jtk@pattern:/u1/NetBSD-current/src/sys/arch/i386/compile/PATTERN i386
>Description:
The SoundBlaster driver doesn't quite do the right thing with
the mixer ioctls, leading programs to conclude it has far fewer
adjustable parameters than it really does.
>How-To-Repeat:
Try to run xmixer on a SBPro system.
>Fix:
Here's a patch to rework the mixer device ordering, and add the ability
to tweak the high & low band input filter settings.
===================================================================
RCS file: RCS/sbdsp.c,v
retrieving revision 1.1
diff -c -r1.1 sbdsp.c
*** sbdsp.c 1995/10/24 23:28:32 1.1
--- sbdsp.c 1995/10/25 01:47:51
***************
*** 162,172 ****
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_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);
}
printf(": dsp v%d.%02d\n",
SBVER_MAJOR(sc->sc_model), SBVER_MINOR(sc->sc_model));
--- 162,173 ----
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/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));
***************
*** 398,403 ****
--- 399,457 ----
}
int
+ sbdsp_set_ifilter(addr, which)
+ void *addr;
+ int which;
+ {
+ register struct sbdsp_softc *sc = addr;
+ int rval, mixval;
+
+ if (ISSBPROCLASS(sc)) {
+ mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
+ switch (which) {
+ default:
+ return EINVAL;
+ 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;
+ }
+ sc->in_filter = mixval & SBP_IFILTER_MASK;
+ sbdsp_mix_write(sc, SBP_INFILTER, mixval);
+ return(0);
+ } else {
+ return(EINVAL);
+ }
+ }
+
+ 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_OFF:
+ default:
+ return 0;
+ case SBP_FILTER_ON|SBP_IFILTER_HIGH:
+ return SBP_TREBLE_EQ;
+ case SBP_FILTER_ON|SBP_IFILTER_LOW:
+ return SBP_BASS_EQ;
+ }
+ } else
+ return 0;
+ }
+
+ int
sbdsp_set_out_port(addr, port)
void *addr;
int port;
***************
*** 466,472 ****
/* record from that port */
sbdsp_mix_write(sc, SBP_RECORD_SOURCE,
SBP_RECORD_FROM(sbport, SBP_FILTER_OFF,
! SBP_FILTER_HIGH));
/* fetch gain from that port */
sc->gain[port] = sbdsp_mix_read(sc, mixport);
}
--- 520,526 ----
/* record from that port */
sbdsp_mix_write(sc, SBP_RECORD_SOURCE,
SBP_RECORD_FROM(sbport, SBP_FILTER_OFF,
! SBP_IFILTER_HIGH));
/* fetch gain from that port */
sc->gain[port] = sbdsp_mix_read(sc, mixport);
}
***************
*** 959,965 ****
sbdsp_mix_write(sc, SBP_STEREO,
sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK);
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)
--- 1013,1019 ----
sbdsp_mix_write(sc, SBP_STEREO,
sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK);
sbdsp_mix_write(sc, SBP_INFILTER,
! (sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK) | SBP_FILTER_OFF);
}
else {
if (sbdsp_wdsp(iobase, SB_DSP_RECORD_MONO) < 0)
***************
*** 967,975 ****
sbdsp_mix_write(sc, SBP_STEREO,
sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK);
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_dmain_inprogress = 1;
sc->sc_last_hsr_size = 0; /* restarting */
--- 1021,1027 ----
sbdsp_mix_write(sc, SBP_STEREO,
sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK);
sbdsp_mix_write(sc, SBP_INFILTER,
! (sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK) | sc->in_filter);
}
sc->sc_dmain_inprogress = 1;
sc->sc_last_hsr_size = 0; /* restarting */
***************
*** 1230,1241 ****
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 {
--- 1282,1294 ----
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 BASS/TREBLE and
* RECORD_SOURCE
*/
if (cp->type != AUDIO_MIXER_VALUE) {
! if (!ISSBPROCLASS(sc) || (cp->dev != SB_RECORD_SOURCE &&
! cp->dev != SB_BASS &&
! cp->dev != SB_TREBLE))
return EINVAL;
}
else {
***************
*** 1244,1254 ****
* 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];
}
--- 1297,1307 ----
* 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];
}
***************
*** 1286,1303 ****
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
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;
--- 1339,1360 ----
case SB_MASTER_VOL:
src = SBP_MASTER_VOL;
break;
! case SB_TREBLE:
! if (cp->type == AUDIO_MIXER_ENUM) {
! return sbdsp_set_ifilter(addr, cp->un.ord ? SBP_TREBLE_EQ : 0);
! }
! error = EINVAL;
! break;
! case SB_BASS:
! if (cp->type == AUDIO_MIXER_ENUM) {
! return sbdsp_set_ifilter(addr, cp->un.ord ? SBP_BASS_EQ : 0);
! }
! error = EINVAL;
! break;
case SB_RECORD_SOURCE:
if (cp->type == AUDIO_MIXER_ENUM)
return sbdsp_set_in_port(addr, cp->un.ord);
/* else fall through: bad input */
default:
error = EINVAL;
break;
***************
*** 1327,1339 ****
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
return EINVAL;
break;
--- 1384,1396 ----
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
return EINVAL;
break;
***************
*** 1346,1351 ****
--- 1403,1420 ----
case SB_SPEAKER:
cp->dev = SB_MASTER_VOL;
break;
+ case SB_TREBLE:
+ if (sbdsp_get_ifilter(sc) == SBP_TREBLE_EQ)
+ cp->un.ord = 1;
+ else
+ cp->un.ord = 0;
+ return 0;
+ case SB_BASS:
+ if (sbdsp_get_ifilter(sc) == SBP_BASS_EQ)
+ cp->un.ord = 1;
+ else
+ cp->un.ord = 0;
+ return 0;
default:
error = EINVAL;
break;
***************
*** 1353,1359 ****
else {
if (cp->un.value.num_channels != 1) /* no stereo on SB classic */
error = EINVAL;
! else
switch(cp->dev) {
case SB_MIC_PORT:
break;
--- 1422,1428 ----
else {
if (cp->un.value.num_channels != 1) /* no stereo on SB classic */
error = EINVAL;
! else
switch(cp->dev) {
case SB_MIC_PORT:
break;
***************
*** 1441,1447 ****
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);
--- 1510,1516 ----
break;
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);
***************
*** 1459,1465 ****
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);
--- 1528,1534 ----
break;
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);
***************
*** 1470,1494 ****
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;
--- 1539,1549 ----
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);
break;
case SB_RECORD_SOURCE:
dip->mixer_class = SB_RECORD_CLASS;
dip->type = AUDIO_MIXER_ENUM;
***************
*** 1504,1510 ****
--- 1559,1595 ----
dip->un.e.member[2].ord = SB_LINE_IN_PORT;
break;
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, 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;
+ break;
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, 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;
+ break;
+
+ 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);
+ break;
+
default:
return ENXIO;
/*NOTREACHED*/
===================================================================
RCS file: RCS/sbdspvar.h,v
retrieving revision 1.1
diff -c -r1.1 sbdspvar.h
*** sbdspvar.h 1995/10/24 23:38:25 1.1
--- sbdspvar.h 1995/10/25 02:00:07
***************
*** 36,59 ****
#define SB_MIC_PORT 0
#define SB_SPEAKER 1
! #define SB_LINE_IN_PORT 2
! #define SB_DAC_PORT 3
! #define SB_FM_PORT 4
! #define SB_CD_PORT 5
! #define SB_MASTER_VOL 6
! #define SB_TREBLE 7
! #define SB_BASS 8
! #define SB_NDEVS 9
! #define SB_OUTPUT_MODE 9
#define SB_SPKR_MONO 0
! #define SB_SPKR_STEREO 1
! #define SB_RECORD_SOURCE 10
! #define SB_INPUT_CLASS 11
! #define SB_OUTPUT_CLASS 12
! #define SB_RECORD_CLASS 13
/*
--- 36,61 ----
#define SB_MIC_PORT 0
#define SB_SPEAKER 1
! #define SB_INPUT_CLASS 2
! #define SB_OUTPUT_CLASS 3
! #define SB_LINE_IN_PORT 4
! #define SB_DAC_PORT 5
! #define SB_FM_PORT 6
! #define SB_CD_PORT 7
! #define SB_MASTER_VOL 8
! #define SB_TREBLE 9
! #define SB_BASS 10
! #define SB_NDEVS 11 /* XXX include classes above for
! contiguous number space on
! original SB */
! /*#define SB_OUTPUT_MODE 9
#define SB_SPKR_MONO 0
! #define SB_SPKR_STEREO 1*/
! #define SB_RECORD_SOURCE 11
! #define SB_RECORD_CLASS 12
/*
***************
*** 93,98 ****
--- 95,101 ----
u_int out_port; /* output port */
u_int in_port; /* input port */
+ u_int in_filter; /* one of SB_TREBLE_EQ, SB_BASS_EQ, 0 */
u_int spkr_state; /* non-null is on */
***************
*** 156,161 ****
--- 159,166 ----
int sbdsp_get_precision __P((void *));
int sbdsp_set_channels __P((void *, int));
int sbdsp_get_channels __P((void *));
+ int sbdsp_set_ifilter __P((void *, int));
+ int sbdsp_get_ifilter __P((void *));
int sbdsp_round_blocksize __P((void *, int));
int sbdsp_set_out_port __P((void *, int));
int sbdsp_get_out_port __P((void *));
>Audit-Trail:
>Unformatted: