summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>1998-05-08 18:37:27 +0000
committerConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>1998-05-08 18:37:27 +0000
commit5d96939538c658040195a46708dd5427601d3050 (patch)
tree1e1faf4a2171057e1ca93aac2b2ea8a72ab7af05 /sys
parentb7d211a2451c1f0906a61e2e2f40466cc4561b6c (diff)
Cleaned up AD1848 driver and added driver for Yamaha OPL3-SA3 to tree.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/opl3sa3.h32
-rw-r--r--sys/dev/isa/ad1848.c533
-rw-r--r--sys/dev/isa/ad1848var.h90
-rw-r--r--sys/dev/isa/gus.c330
-rw-r--r--sys/dev/isa/pss.c207
-rw-r--r--sys/dev/isa/wss.c212
-rw-r--r--sys/dev/isa/ym.c470
-rw-r--r--sys/dev/isa/ym_isapnp.c126
-rw-r--r--sys/dev/isa/ymvar.h89
9 files changed, 1137 insertions, 952 deletions
diff --git a/sys/dev/ic/opl3sa3.h b/sys/dev/ic/opl3sa3.h
new file mode 100644
index 00000000000..89f22809e79
--- /dev/null
+++ b/sys/dev/ic/opl3sa3.h
@@ -0,0 +1,32 @@
+/* $OpenBSD: opl3sa3.h,v 1.1 1998/05/08 18:37:26 csapuntz Exp $ */
+
+/*
+ * Copyright (c) 1998 Constantine Sapuntzakis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#define SA3_LCH 0x7
+#define SA3_RCH 0x8
+#define SA3_MIC 0x9
diff --git a/sys/dev/isa/ad1848.c b/sys/dev/isa/ad1848.c
index 2e3e495d4cf..c421a510bee 100644
--- a/sys/dev/isa/ad1848.c
+++ b/sys/dev/isa/ad1848.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ad1848.c,v 1.10 1998/04/26 21:02:38 provos Exp $ */
+/* $OpenBSD: ad1848.c,v 1.11 1998/05/08 18:37:18 csapuntz Exp $ */
/* $NetBSD: ad1848.c,v 1.45 1998/01/30 02:02:38 augustss Exp $ */
/*
@@ -138,8 +138,8 @@ static int ad1848_init_values[] = {
0, /* unused */
0, /* IRQ status */
0, /* unused */
- /* Mono input (mic) Control */
- MONO_INPUT_MUTE|ATTEN_6, /* mute mic by default */
+ /* Mono input (a.k.a speaker) (mic) Control */
+ MONO_INPUT_MUTE|ATTEN_6, /* mute speaker by default */
0, /* unused */
0, /* record format */
0, /* Crystal Clock Select */
@@ -566,16 +566,16 @@ ad1848_attach(sc)
/* Set default gains */
(void) ad1848_set_rec_gain(sc, &vol_mid);
- (void) ad1848_set_out_gain(sc, &vol_mid);
- (void) ad1848_set_mon_gain(sc, &vol_0);
- (void) ad1848_set_aux1_gain(sc, &vol_mid); /* CD volume */
+ (void) ad1848_set_channel_gain(sc, AD1848_DAC_CHANNEL, &vol_mid);
+ (void) ad1848_set_channel_gain(sc, AD1848_MONITOR_CHANNEL, &vol_0);
+ (void) ad1848_set_channel_gain(sc, AD1848_AUX1_CHANNEL, &vol_mid); /* CD volume */
if (sc->mode == 2) {
- /* aux1 was really the DAC output */
- (void) ad1848_set_aux2_gain(sc, &vol_mid); /* CD volume */
- (void) cs4231_set_linein_gain(sc, &vol_mid);
- (void) cs4231_set_mono_gain(sc, &vol_0); /* mic */
+ (void) ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_mid); /* CD volume */
+ (void) ad1848_set_channel_gain(sc, AD1848_LINE_CHANNEL, &vol_mid);
+ (void) ad1848_set_channel_gain(sc, AD1848_MONO_CHANNEL, &vol_0);
+ sc->mute[AD1848_MONO_CHANNEL] = MUTE_ALL;
} else
- (void) ad1848_set_aux2_gain(sc, &vol_0);
+ (void) ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_0);
/* Set default port */
(void) ad1848_set_rec_port(sc, MIC_IN_PORT);
@@ -587,128 +587,161 @@ ad1848_attach(sc)
/*
* Various routines to interface to higher level audio driver
*/
-int
-ad1848_set_rec_gain(sc, gp)
- struct ad1848_softc *sc;
- struct ad1848_volume *gp;
+struct ad1848_mixerinfo {
+ int left_reg;
+ int right_reg;
+ int atten_bits;
+ int atten_mask;
+} mixer_channel_info[] =
+{ { SP_LEFT_AUX2_CONTROL, SP_RIGHT_AUX2_CONTROL, AUX_INPUT_ATTEN_BITS,
+ AUX_INPUT_ATTEN_MASK },
+ { SP_LEFT_AUX1_CONTROL, SP_RIGHT_AUX1_CONTROL, AUX_INPUT_ATTEN_BITS,
+ AUX_INPUT_ATTEN_MASK },
+ { SP_LEFT_OUTPUT_CONTROL, SP_RIGHT_OUTPUT_CONTROL,
+ OUTPUT_ATTEN_BITS, OUTPUT_ATTEN_MASK },
+ { CS_LEFT_LINE_CONTROL, CS_RIGHT_LINE_CONTROL, LINE_INPUT_ATTEN_BITS,
+ LINE_INPUT_ATTEN_MASK },
+ { CS_MONO_IO_CONTROL, 0, MONO_INPUT_ATTEN_BITS, MONO_INPUT_ATTEN_MASK },
+ { SP_DIGITAL_MIX, 0, OUTPUT_ATTEN_BITS, MIX_ATTEN_MASK }
+};
+
+/*
+ * This function doesn't set the mute flags but does use them.
+ * The mute flags reflect the mutes that have been applied by the user.
+ * However, the driver occasionally wants to mute devices (e.g. when chaing
+ * sampling rate). These operations should not affect the mute flags.
+ */
+
+void
+ad1848_mute_channel(sc, device, mute)
+ struct ad1848_softc *sc;
+ int device;
+ int mute;
{
- u_char reg, gain;
-
- DPRINTF(("ad1848_set_rec_gain: %d:%d\n", gp->left, gp->right));
+ u_char reg;
- sc->rec_gain = *gp;
+ reg = ad_read(sc, mixer_channel_info[device].left_reg);
- gain = (gp->left * GAIN_22_5)/AUDIO_MAX_GAIN;
- reg = ad_read(sc, SP_LEFT_INPUT_CONTROL);
- reg &= INPUT_GAIN_MASK;
- ad_write(sc, SP_LEFT_INPUT_CONTROL, (gain&0x0f)|reg);
+ if (mute & MUTE_LEFT) {
+ if (device == AD1848_MONITOR_CHANNEL)
+ ad_write(sc, mixer_channel_info[device].left_reg, reg & 0xFE);
+ else
+ ad_write(sc, mixer_channel_info[device].left_reg, reg | 0x80);
+ } else if (!(sc->mute[device] & MUTE_LEFT)) {
+ if (device == AD1848_MONITOR_CHANNEL)
+ ad_write(sc, mixer_channel_info[device].left_reg, reg | 0x01);
+ else
+ ad_write(sc, mixer_channel_info[device].left_reg, reg & ~0x80);
+ }
- gain = (gp->right * GAIN_22_5)/AUDIO_MAX_GAIN;
- reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL);
- reg &= INPUT_GAIN_MASK;
- ad_write(sc, SP_RIGHT_INPUT_CONTROL, (gain&0x0f)|reg);
+ if (!mixer_channel_info[device].right_reg) {
+ return;
+ }
- return(0);
-}
+ reg = ad_read(sc, mixer_channel_info[device].right_reg);
-int
-ad1848_get_rec_gain(sc, gp)
- struct ad1848_softc *sc;
- struct ad1848_volume *gp;
-{
- *gp = sc->rec_gain;
- return(0);
+ if (mute & MUTE_RIGHT)
+ ad_write(sc, mixer_channel_info[device].right_reg, reg | 0x80);
+ else if (!(sc->mute[device] & MUTE_RIGHT)) {
+ ad_write(sc, mixer_channel_info[device].right_reg, reg & ~0x80);
+ }
}
+
int
-ad1848_set_out_gain(sc, gp)
+ad1848_set_channel_gain(sc, device, gp)
struct ad1848_softc *sc;
+ int device;
struct ad1848_volume *gp;
{
+ struct ad1848_mixerinfo *info = &mixer_channel_info[device];
u_char reg;
u_int atten;
-
- DPRINTF(("ad1848_set_out_gain: %d:%d\n", gp->left, gp->right));
- sc->out_gain = *gp;
+ sc->gains[device] = *gp;
- atten = ((AUDIO_MAX_GAIN - gp->left) * OUTPUT_ATTEN_BITS)/AUDIO_MAX_GAIN;
- reg = ad_read(sc, SP_LEFT_OUTPUT_CONTROL);
- reg &= OUTPUT_ATTEN_MASK;
- ad_write(sc, SP_LEFT_OUTPUT_CONTROL, (atten&0x3f)|reg);
+ atten = ((AUDIO_MAX_GAIN - gp->left) * info->atten_bits)/AUDIO_MAX_GAIN;
- atten = ((AUDIO_MAX_GAIN - gp->right) * OUTPUT_ATTEN_BITS)/AUDIO_MAX_GAIN;
- reg = ad_read(sc, SP_RIGHT_OUTPUT_CONTROL);
- reg &= OUTPUT_ATTEN_MASK;
- ad_write(sc, SP_RIGHT_OUTPUT_CONTROL, (atten&0x3f)|reg);
+ reg = ad_read(sc, info->left_reg) & (info->atten_mask);
+ if (device == AD1848_MONITOR_CHANNEL)
+ reg |= ((atten & info->atten_bits) << 2);
+ else
+ reg |= ((atten & info->atten_bits));
- return(0);
-}
+ ad_write(sc, info->left_reg, reg);
+
+ if (!info->right_reg)
+ return (0);
+
+ atten = ((AUDIO_MAX_GAIN - gp->right) * info->atten_bits)/AUDIO_MAX_GAIN;
+ reg = ad_read(sc, info->right_reg);
+ reg &= (info->atten_mask);
+ ad_write(sc, info->right_reg, (atten& info->atten_bits)|reg);
-int
-ad1848_get_out_gain(sc, gp)
- struct ad1848_softc *sc;
- struct ad1848_volume *gp;
-{
- *gp = sc->out_gain;
return(0);
}
+
int
-ad1848_set_mon_gain(sc, gp) /* monitor gain */
+ad1848_get_device_gain(sc, device, gp)
struct ad1848_softc *sc;
+ int device;
struct ad1848_volume *gp;
{
- u_char reg;
- u_int atten;
-
- DPRINTF(("ad1848_set_mon_gain: %d\n", gp->left));
-
- sc->mon_gain = *gp;
-
- atten = ((AUDIO_MAX_GAIN - gp->left) * OUTPUT_ATTEN_BITS)/AUDIO_MAX_GAIN;
- reg = ad_read(sc, SP_DIGITAL_MIX);
- reg &= MIX_ATTEN_MASK;
- ad_write(sc, SP_DIGITAL_MIX, (atten&OUTPUT_ATTEN_BITS)|reg);
+ *gp = sc->gains[device];
return(0);
}
int
-ad1848_get_mon_gain(sc, gp)
+ad1848_get_rec_gain(sc, gp)
struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
- *gp = sc->mon_gain;
+ *gp = sc->rec_gain;
return(0);
}
int
-cs4231_set_mono_gain(sc, gp)
+ad1848_set_rec_gain(sc, gp)
struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
- u_char reg, oreg;
- u_int atten;
+ u_char reg, gain;
- DPRINTF(("cs4231_set_mono_gain: %d\n", gp->left));
+ DPRINTF(("ad1848_set_rec_gain: %d:%d\n", gp->left, gp->right));
+
+ sc->rec_gain = *gp;
- sc->mono_gain = *gp;
+ gain = (gp->left * GAIN_22_5)/AUDIO_MAX_GAIN;
+ reg = ad_read(sc, SP_LEFT_INPUT_CONTROL);
+ reg &= INPUT_GAIN_MASK;
+ ad_write(sc, SP_LEFT_INPUT_CONTROL, (gain&0x0f)|reg);
+
+ gain = (gp->right * GAIN_22_5)/AUDIO_MAX_GAIN;
+ reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL);
+ reg &= INPUT_GAIN_MASK;
+ ad_write(sc, SP_RIGHT_INPUT_CONTROL, (gain&0x0f)|reg);
- atten = ((AUDIO_MAX_GAIN - gp->left) * MONO_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN;
- oreg = reg = ad_read(sc, CS_MONO_IO_CONTROL);
- reg &= MONO_INPUT_ATTEN_MASK;
- ad_write(sc, CS_MONO_IO_CONTROL, (atten&MONO_INPUT_ATTEN_BITS)|reg);
- DPRINTF(("cs4231_set_mono_gain: was:%x\n", oreg));
return(0);
}
-int
-cs4231_get_mono_gain(sc, gp)
- struct ad1848_softc *sc;
- struct ad1848_volume *gp;
+
+void
+ad1848_mute_monitor(addr, mute)
+ void *addr;
+ int mute;
{
- *gp = sc->mono_gain;
- return(0);
+ struct ad1848_softc *sc = addr;
+
+ DPRINTF(("ad1848_mute_monitor: %smuting\n", mute ? "" : "un"));
+ if (sc->mode == 2) {
+ ad1848_mute_channel(sc, AD1848_DAC_CHANNEL, mute ? MUTE_ALL : 0);
+ ad1848_mute_channel(sc, AD1848_MONO_CHANNEL, mute ? MUTE_MONO : 0);
+ ad1848_mute_channel(sc, AD1848_LINE_CHANNEL, mute ? MUTE_ALL : 0);
+ }
+
+ ad1848_mute_channel(sc, AD1848_AUX2_CHANNEL, mute ? MUTE_ALL : 0);
+ ad1848_mute_channel(sc, AD1848_AUX1_CHANNEL, mute ? MUTE_ALL : 0);
}
int
@@ -745,228 +778,170 @@ ad1848_get_mic_gain(sc, gp)
return(0);
}
-void
-ad1848_mute_monitor(addr, mute)
- void *addr;
- int mute;
-{
- struct ad1848_softc *sc = addr;
- DPRINTF(("ad1848_mute_monitor: %smuting\n", mute ? "" : "un"));
- if (sc->mode == 2) {
- cs4231_mute_monitor(sc, mute);
- cs4231_mute_mono(sc, mute);
- cs4231_mute_line(sc, mute);
- }
-
- ad1848_mute_aux1(sc, mute);
- ad1848_mute_aux2(sc, mute);
-}
+static ad1848_devmap_t *ad1848_mixer_find_dev __P((ad1848_devmap_t *, int, mixer_ctrl_t *));
-void
-cs4231_mute_monitor(sc, mute)
- struct ad1848_softc *sc;
- int mute;
-{
- u_char reg;
- if (mute) {
- DPRINTF(("cs4231_mute_monitor: muting\n"));
- reg = ad_read(sc, SP_LEFT_OUTPUT_CONTROL);
- ad_write(sc, SP_LEFT_OUTPUT_CONTROL, OUTPUT_MUTE|reg);
- reg = ad_read(sc, SP_RIGHT_OUTPUT_CONTROL);
- ad_write(sc, SP_RIGHT_OUTPUT_CONTROL, OUTPUT_MUTE|reg);
- } else if (!sc->mon_mute) {
- DPRINTF(("cs4231_mute_monitor: unmuting\n"));
- reg = ad_read(sc, SP_LEFT_OUTPUT_CONTROL);
- ad_write(sc, SP_LEFT_OUTPUT_CONTROL, reg & ~OUTPUT_MUTE);
- reg = ad_read(sc, SP_RIGHT_OUTPUT_CONTROL);
- ad_write(sc, SP_RIGHT_OUTPUT_CONTROL, reg & ~OUTPUT_MUTE);
- }
-}
+static ad1848_devmap_t *
+ad1848_mixer_find_dev(map, cnt, cp)
+ ad1848_devmap_t *map;
+ int cnt;
+ mixer_ctrl_t *cp;
-void
-cs4231_mute_mono(sc, mute)
- struct ad1848_softc *sc;
- int mute;
{
- u_char reg;
- if (mute) {
- DPRINTF(("cs4231_mute_mono: muting\n"));
- reg = ad_read(sc, CS_MONO_IO_CONTROL);
- ad_write(sc, CS_MONO_IO_CONTROL, MONO_INPUT_MUTE|reg);
- } else if (!sc->mono_mute) {
- DPRINTF(("cs4231_mute_mono: unmuting\n"));
- reg = ad_read(sc, CS_MONO_IO_CONTROL);
- ad_write(sc, CS_MONO_IO_CONTROL, reg & ~MONO_INPUT_MUTE);
- }
-}
+ int idx;
-void
-cs4231_mute_line(sc, mute)
- struct ad1848_softc *sc;
- int mute;
-{
- u_char reg;
- if (mute) {
- DPRINTF(("cs4231_mute_line: muting\n"));
- reg = ad_read(sc, CS_LEFT_LINE_CONTROL);
- ad_write(sc, CS_LEFT_LINE_CONTROL, LINE_INPUT_MUTE|reg);
- reg = ad_read(sc, CS_RIGHT_LINE_CONTROL);
- ad_write(sc, CS_RIGHT_LINE_CONTROL, LINE_INPUT_MUTE|reg);
- } else if (!sc->line_mute) {
- DPRINTF(("cs4231_mute_line: unmuting\n"));
- reg = ad_read(sc, CS_LEFT_LINE_CONTROL);
- ad_write(sc, CS_LEFT_LINE_CONTROL, reg & ~LINE_INPUT_MUTE);
- reg = ad_read(sc, CS_RIGHT_LINE_CONTROL);
- ad_write(sc, CS_RIGHT_LINE_CONTROL, reg & ~LINE_INPUT_MUTE);
- }
+ for (idx = 0; idx < cnt; idx++) {
+ if (map[idx].id == cp->dev) {
+ return (&map[idx]);
+ }
+ }
+ return (NULL);
}
-void
-ad1848_mute_aux1(sc, mute)
- struct ad1848_softc *sc;
- int mute;
+int
+ad1848_mixer_get_port(ac, map, cnt, cp)
+ struct ad1848_softc *ac;
+ struct ad1848_devmap *map;
+ int cnt;
+ mixer_ctrl_t *cp;
{
- u_char reg;
- if (mute) {
- DPRINTF(("ad1848_mute_aux1: muting\n"));
- reg = ad_read(sc, SP_LEFT_AUX1_CONTROL);
- ad_write(sc, SP_LEFT_AUX1_CONTROL, AUX_INPUT_MUTE|reg);
- reg = ad_read(sc, SP_RIGHT_AUX1_CONTROL);
- ad_write(sc, SP_RIGHT_AUX1_CONTROL, AUX_INPUT_MUTE|reg);
- } else if (!sc->aux1_mute) {
- DPRINTF(("ad1848_mute_aux1: unmuting\n"));
- reg = ad_read(sc, SP_LEFT_AUX1_CONTROL);
- ad_write(sc, SP_LEFT_AUX1_CONTROL, reg & ~AUX_INPUT_MUTE);
- reg = ad_read(sc, SP_RIGHT_AUX1_CONTROL);
- ad_write(sc, SP_RIGHT_AUX1_CONTROL, reg & ~AUX_INPUT_MUTE);
- }
-}
+ ad1848_devmap_t *entry;
+ struct ad1848_volume vol;
+ int error = EINVAL;
+ int dev;
-void
-ad1848_mute_aux2(sc, mute)
- struct ad1848_softc *sc;
- int mute;
-{
- u_char reg;
- if (mute) {
- DPRINTF(("ad1848_mute_aux2: muting\n"));
- reg = ad_read(sc, SP_LEFT_AUX2_CONTROL);
- ad_write(sc, SP_LEFT_AUX2_CONTROL, AUX_INPUT_MUTE|reg);
- reg = ad_read(sc, SP_RIGHT_AUX2_CONTROL);
- ad_write(sc, SP_RIGHT_AUX2_CONTROL, AUX_INPUT_MUTE|reg);
- } else if (!sc->aux2_mute) {
- DPRINTF(("ad1848_mute_aux2: unmuting\n"));
- reg = ad_read(sc, SP_LEFT_AUX2_CONTROL);
- ad_write(sc, SP_LEFT_AUX2_CONTROL, reg & ~AUX_INPUT_MUTE);
- reg = ad_read(sc, SP_RIGHT_AUX2_CONTROL);
- ad_write(sc, SP_RIGHT_AUX2_CONTROL, reg & ~AUX_INPUT_MUTE);
- }
-}
+ if (!(entry = ad1848_mixer_find_dev(map, cnt, cp)))
+ return (ENXIO);
-int
-ad1848_set_aux1_gain(sc, gp)
- struct ad1848_softc *sc;
- struct ad1848_volume *gp;
-{
- u_char reg;
- u_int atten;
-
- DPRINTF(("ad1848_set_aux1_gain: %d:%d\n", gp->left, gp->right));
-
- sc->aux1_gain = *gp;
+ dev = entry->dev;
- atten = ((AUDIO_MAX_GAIN - gp->left) * AUX_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN;
- reg = ad_read(sc, SP_LEFT_AUX1_CONTROL);
- reg &= ~(AUX_INPUT_ATTEN_BITS);
- ad_write(sc, SP_LEFT_AUX1_CONTROL, (atten&0x1f)|reg);
+ switch (entry->kind) {
+ case AD1848_KIND_LVL:
+ if (cp->type != AUDIO_MIXER_VALUE)
+ break;
- atten = ((AUDIO_MAX_GAIN - gp->right) * AUX_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN;
- reg = ad_read(sc, SP_RIGHT_AUX1_CONTROL);
- reg &= ~(AUX_INPUT_ATTEN_BITS);
- ad_write(sc, SP_RIGHT_AUX1_CONTROL, (atten&0x1f)|reg);
+ if (dev < AD1848_AUX2_CHANNEL ||
+ dev > AD1848_MONITOR_CHANNEL)
+ break;
- return(0);
-}
+ if (cp->un.value.num_channels != 1 &&
+ mixer_channel_info[dev].right_reg == 0)
+ break;
-int
-ad1848_get_aux1_gain(sc, gp)
- struct ad1848_softc *sc;
- struct ad1848_volume *gp;
-{
- *gp = sc->aux1_gain;
- return(0);
-}
+ error = ad1848_get_device_gain(ac, dev, &vol);
+ if (!error)
+ ad1848_from_vol(cp, &vol);
-int
-cs4231_set_linein_gain(sc, gp)
- struct ad1848_softc *sc;
- struct ad1848_volume *gp;
-{
- u_char reg, oregl, oregr;
- u_int atten;
-
- DPRINTF(("ad1848_set_linein_gain: %d:%d\n", gp->left, gp->right));
-
- sc->line_gain = *gp;
+ break;
- atten = ((AUDIO_MAX_GAIN - gp->left) * LINE_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN;
- oregl = reg = ad_read(sc, CS_LEFT_LINE_CONTROL);
- reg &= ~(LINE_INPUT_ATTEN_BITS);
- ad_write(sc, CS_LEFT_LINE_CONTROL, (atten&LINE_INPUT_ATTEN_BITS)|reg);
+ case AD1848_KIND_MUTE:
+ if (cp->type != AUDIO_MIXER_ENUM) break;
- atten = ((AUDIO_MAX_GAIN - gp->right) * LINE_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN;
- oregr = reg = ad_read(sc, CS_RIGHT_LINE_CONTROL);
- reg &= ~(LINE_INPUT_ATTEN_BITS);
- ad_write(sc, CS_RIGHT_LINE_CONTROL, (atten&LINE_INPUT_ATTEN_BITS)|reg);
+ cp->un.ord = ac->mute[dev] ? 1 : 0;
+ error = 0;
+ break;
- DPRINTF(("ad1848_set_linein_gain: was %x:%x\n", oregl, oregr));
- return(0);
-}
+ case AD1848_KIND_RECORDGAIN:
+ if (cp->type != AUDIO_MIXER_VALUE) break;
-int
-cs4231_get_linein_gain(sc, gp)
- struct ad1848_softc *sc;
- struct ad1848_volume *gp;
-{
- *gp = sc->line_gain;
- return(0);
+ error = ad1848_get_rec_gain(ac, &vol);
+ if (!error)
+ ad1848_from_vol(cp, &vol);
+
+ break;
+
+ case AD1848_KIND_MICGAIN:
+ if (cp->type != AUDIO_MIXER_VALUE) break;
+
+ error = ad1848_get_mic_gain(ac, &vol);
+ if (!error)
+ ad1848_from_vol(cp, &vol);
+
+ break;
+
+ case AD1848_KIND_RECORDSOURCE:
+ if (cp->type != AUDIO_MIXER_ENUM) break;
+ cp->un.ord = ad1848_get_rec_port(ac);
+ error = 0;
+ break;
+ default:
+ printf ("Invalid kind\n");
+ break;
+ }
+
+ return (error);
}
-int
-ad1848_set_aux2_gain(sc, gp)
- struct ad1848_softc *sc;
- struct ad1848_volume *gp;
+int
+ad1848_mixer_set_port(ac, map, cnt, cp)
+ struct ad1848_softc *ac;
+ struct ad1848_devmap *map;
+ int cnt;
+ mixer_ctrl_t *cp;
{
- u_char reg;
- u_int atten;
+ ad1848_devmap_t *entry;
+ struct ad1848_volume vol;
+ int error = EINVAL;
+ int dev;
+
+ if (!(entry = ad1848_mixer_find_dev(map, cnt, cp)))
+ return (ENXIO);
+
+ dev = entry->dev;
+
+ switch (entry->kind) {
+ case AD1848_KIND_LVL:
+ if (cp->type != AUDIO_MIXER_VALUE)
+ break;
+
+ if (dev < AD1848_AUX2_CHANNEL ||
+ dev > AD1848_MONITOR_CHANNEL)
+ break;
+
+ if (cp->un.value.num_channels != 1 &&
+ mixer_channel_info[dev].right_reg == 0)
+ break;
- DPRINTF(("ad1848_set_aux2_gain: %d:%d\n", gp->left, gp->right));
-
- sc->aux2_gain = *gp;
+ ad1848_to_vol(cp, &vol);
+ error = ad1848_set_channel_gain(ac, dev, &vol);
+ break;
- atten = ((AUDIO_MAX_GAIN - gp->left) * AUX_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN;
- reg = ad_read(sc, SP_LEFT_AUX2_CONTROL);
- reg &= ~(AUX_INPUT_ATTEN_BITS);
- ad_write(sc, SP_LEFT_AUX2_CONTROL, (atten&0x1f)|reg);
+ case AD1848_KIND_MUTE:
+ if (cp->type != AUDIO_MIXER_ENUM) break;
+
+ ac->mute[dev] = (cp->un.ord ? MUTE_ALL : 0);
+ ad1848_mute_channel(ac, dev, ac->mute[dev]);
+ error = 0;
+ break;
- atten = ((AUDIO_MAX_GAIN - gp->right) * AUX_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN;
- reg = ad_read(sc, SP_RIGHT_AUX2_CONTROL);
- reg &= ~(AUX_INPUT_ATTEN_BITS);
- ad_write(sc, SP_RIGHT_AUX2_CONTROL, (atten&0x1f)|reg);
+ case AD1848_KIND_RECORDGAIN:
+ if (cp->type != AUDIO_MIXER_VALUE) break;
- return(0);
-}
+ ad1848_to_vol(cp, &vol);
+ error = ad1848_set_rec_gain(ac, &vol);
+ break;
-int
-ad1848_get_aux2_gain(sc, gp)
- struct ad1848_softc *sc;
- struct ad1848_volume *gp;
-{
- *gp = sc->aux2_gain;
- return 0;
+ case AD1848_KIND_MICGAIN:
+ if (cp->type != AUDIO_MIXER_VALUE) break;
+
+ ad1848_to_vol(cp, &vol);
+ error = ad1848_set_mic_gain(ac, &vol);
+ break;
+
+ case AD1848_KIND_RECORDSOURCE:
+ if (cp->type != AUDIO_MIXER_ENUM) break;
+
+ error = ad1848_set_rec_port(ac, cp->un.ord);
+ break;
+ default:
+ printf ("Invalid kind\n");
+ break;
+ }
+
+ return (error);
}
+
int
ad1848_query_encoding(addr, fp)
void *addr;
diff --git a/sys/dev/isa/ad1848var.h b/sys/dev/isa/ad1848var.h
index b5fdaf67365..f7f02a0a5a0 100644
--- a/sys/dev/isa/ad1848var.h
+++ b/sys/dev/isa/ad1848var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ad1848var.h,v 1.6 1998/04/26 21:02:39 provos Exp $ */
+/* $OpenBSD: ad1848var.h,v 1.7 1998/05/08 18:37:20 csapuntz Exp $ */
/* $NetBSD: ad1848var.h,v 1.22 1998/01/19 22:18:26 augustss Exp $ */
/*
@@ -75,14 +75,17 @@ struct ad1848_softc {
int sc_recdrq; /* record/capture DMA */
/* We keep track of these */
- struct ad1848_volume rec_gain, aux1_gain, aux2_gain, out_gain, mon_gain, line_gain, mono_gain;
+ struct ad1848_volume gains[6];
+
+ struct ad1848_volume rec_gain;
int rec_port; /* recording port */
/* ad1848 */
u_char MCE_bit;
char mic_gain_on; /* CS4231 only */
- char mono_mute, aux1_mute, aux2_mute, line_mute, mon_mute;
+ char mute[6];
+
char *chip_name;
int mode;
@@ -101,6 +104,21 @@ struct ad1848_softc {
int sc_iobase;
};
+#define MUTE_LEFT 1
+#define MUTE_RIGHT 2
+#define MUTE_ALL (MUTE_LEFT | MUTE_RIGHT)
+#define MUTE_MONO MUTE_ALL
+
+/* Don't change this ordering without seriously looking around.
+ These are indexes into mute[] array and into a register information
+ array */
+#define AD1848_AUX2_CHANNEL 0
+#define AD1848_AUX1_CHANNEL 1
+#define AD1848_DAC_CHANNEL 2
+#define AD1848_LINE_CHANNEL 3
+#define AD1848_MONO_CHANNEL 4
+#define AD1848_MONITOR_CHANNEL 5 /* Doesn't seem to be on all later chips */
+
/*
* Ad1848 ports
*/
@@ -110,6 +128,59 @@ struct ad1848_softc {
#define DAC_IN_PORT 3
#ifdef _KERNEL
+
+#define AD1848_KIND_LVL 0
+#define AD1848_KIND_MUTE 1
+#define AD1848_KIND_RECORDGAIN 2
+#define AD1848_KIND_MICGAIN 3
+#define AD1848_KIND_RECORDSOURCE 4
+
+typedef struct ad1848_devmap {
+ int id;
+ int kind;
+ int dev;
+} ad1848_devmap_t;
+
+static __inline int ad1848_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
+static __inline int ad1848_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
+
+static __inline int
+ad1848_to_vol(cp, vol)
+ mixer_ctrl_t *cp;
+ struct ad1848_volume *vol;
+{
+ if (cp->un.value.num_channels == 1) {
+ vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+ return(1);
+ }
+ else if (cp->un.value.num_channels == 2) {
+ vol->left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
+ vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
+ return(1);
+ }
+ return(0);
+}
+
+static __inline int
+ad1848_from_vol(cp, vol)
+ mixer_ctrl_t *cp;
+ struct ad1848_volume *vol;
+{
+ if (cp->un.value.num_channels == 1) {
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left;
+ return(1);
+ }
+ else if (cp->un.value.num_channels == 2) {
+ cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left;
+ cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right;
+ return(1);
+ }
+ return(0);
+}
+
+
+int ad1848_mixer_get_port __P((struct ad1848_softc *, ad1848_devmap_t *, int cnt, mixer_ctrl_t *));
+int ad1848_mixer_set_port __P((struct ad1848_softc *, ad1848_devmap_t *, int, mixer_ctrl_t *));
int ad1848_mapprobe __P((struct ad1848_softc *, int));
int ad1848_probe __P((struct ad1848_softc *));
void ad1848_unmap __P((struct ad1848_softc *));
@@ -140,21 +211,14 @@ int ad1848_intr __P((void *));
int ad1848_set_rec_port __P((struct ad1848_softc *, int));
int ad1848_get_rec_port __P((struct ad1848_softc *));
-int ad1848_set_aux1_gain __P((struct ad1848_softc *, struct ad1848_volume *));
-int ad1848_get_aux1_gain __P((struct ad1848_softc *, struct ad1848_volume *));
-int ad1848_set_aux2_gain __P((struct ad1848_softc *, struct ad1848_volume *));
-int ad1848_get_aux2_gain __P((struct ad1848_softc *, struct ad1848_volume *));
-int ad1848_set_out_gain __P((struct ad1848_softc *, struct ad1848_volume *));
-int ad1848_get_out_gain __P((struct ad1848_softc *, struct ad1848_volume *));
+int ad1848_set_channel_gain __P((struct ad1848_softc *, int, struct ad1848_volume *));
+int ad1848_get_device_gain __P((struct ad1848_softc *, int, struct ad1848_volume *));
int ad1848_set_rec_gain __P((struct ad1848_softc *, struct ad1848_volume *));
int ad1848_get_rec_gain __P((struct ad1848_softc *, struct ad1848_volume *));
-int ad1848_set_mon_gain __P((struct ad1848_softc *, struct ad1848_volume *));
-int ad1848_get_mon_gain __P((struct ad1848_softc *, struct ad1848_volume *));
/* Note: The mic pre-MUX gain is not a variable gain, it's 20dB or 0dB */
int ad1848_set_mic_gain __P((struct ad1848_softc *, struct ad1848_volume *));
int ad1848_get_mic_gain __P((struct ad1848_softc *, struct ad1848_volume *));
-void ad1848_mute_aux1 __P((struct ad1848_softc *, int /* onoff */));
-void ad1848_mute_aux2 __P((struct ad1848_softc *, int /* onoff */));
+void ad1848_mute_channel __P((struct ad1848_softc *, int device, int mute));
void *ad1848_malloc __P((void *, unsigned long, int, int));
void ad1848_free __P((void *, void *, int));
diff --git a/sys/dev/isa/gus.c b/sys/dev/isa/gus.c
index eb01c44a1a8..6ba8eaa4046 100644
--- a/sys/dev/isa/gus.c
+++ b/sys/dev/isa/gus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gus.c,v 1.14 1998/04/26 21:02:41 provos Exp $ */
+/* $OpenBSD: gus.c,v 1.15 1998/05/08 18:37:21 csapuntz Exp $ */
/* $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
/*-
@@ -428,9 +428,6 @@ STATIC void gusics_mic_mute __P((struct ics2101_softc *, int));
STATIC void gusics_linein_mute __P((struct ics2101_softc *, int));
STATIC void gusics_cd_mute __P((struct ics2101_softc *, int));
-STATIC __inline int gus_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
-STATIC __inline int gus_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
-
void stereo_dmaintr __P((void *));
/*
@@ -1067,11 +1064,11 @@ gusopen(addr, flags)
if (HAS_CODEC(sc)) {
ad1848_open(&sc->sc_codec, flags);
- sc->sc_codec.aux1_mute = 0;
- ad1848_mute_aux1(&sc->sc_codec, 0); /* turn on DAC output */
+ sc->sc_codec.mute[AD1848_AUX1_CHANNEL] = 0;
+ ad1848_mute_channel(&sc->sc_codec, AD1848_AUX1_CHANNEL, 0); /* turn on DAC output */
if (flags & FREAD) {
- sc->sc_codec.mono_mute = 0;
- cs4231_mute_mono(&sc->sc_codec, 0);
+ sc->sc_codec.mute[AD1848_MONO_CHANNEL] = 0;
+ ad1848_mute_channel(&sc->sc_codec, AD1848_MONO_CHANNEL, 0);
}
} else if (flags & FREAD) {
/* enable/unmute the microphone */
@@ -1299,8 +1296,8 @@ gusmax_close(addr)
struct ad1848_softc *ac = addr;
struct gus_softc *sc = ac->parent;
#if 0
- ac->aux1_mute = 1;
- ad1848_mute_aux1(ac, 1); /* turn off DAC output */
+ ac->mute[AD1848_AUX1_CHANNEL] = MUTE_ALL;
+ ad1848_mute_channel(ac, MUTE_ALL); /* turn off DAC output */
#endif
ad1848_close(ac);
gusclose(sc);
@@ -3131,39 +3128,24 @@ gus_halt_in_dma(addr)
return 0;
}
-STATIC __inline int
-gus_to_vol(cp, vol)
- mixer_ctrl_t *cp;
- struct ad1848_volume *vol;
-{
- if (cp->un.value.num_channels == 1) {
- vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
- return(1);
- }
- else if (cp->un.value.num_channels == 2) {
- vol->left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
- vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
- return(1);
- }
- return(0);
-}
-STATIC __inline int
-gus_from_vol(cp, vol)
- mixer_ctrl_t *cp;
- struct ad1848_volume *vol;
-{
- if (cp->un.value.num_channels == 1) {
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left;
- return(1);
- }
- else if (cp->un.value.num_channels == 2) {
- cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left;
- cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right;
- return(1);
- }
- return(0);
-}
+static ad1848_devmap_t gusmapping[] = {
+ {GUSMAX_DAC_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL},
+ {GUSMAX_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL},
+ {GUSMAX_MONO_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL},
+ {GUSMAX_CD_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL},
+ {GUSMAX_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL},
+ {GUSMAX_OUT_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL},
+ {GUSMAX_DAC_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL},
+ {GUSMAX_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL},
+ {GUSMAX_MONO_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL},
+ {GUSMAX_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL},
+ {GUSMAX_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL},
+ {GUSMAX_REC_LVL, AD1848_KIND_RECORDGAIN, -1},
+ {GUSMAX_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
+};
+
+static int nummap = sizeof(gusmapping) / sizeof(gusmapping[0]);
STATIC int
gusmax_mixer_get_port(addr, cp)
@@ -3173,72 +3155,14 @@ gusmax_mixer_get_port(addr, cp)
struct ad1848_softc *ac = addr;
struct gus_softc *sc = ac->parent;
struct ad1848_volume vol;
- int error = EINVAL;
+ int error = ad1848_mixer_get_port(ac, gusmapping, nummap, cp);
- DPRINTF(("gusmax_mixer_get_port: port=%d\n", cp->dev));
-
- switch (cp->dev) {
-#if 0 /* use mono level instead */
- case GUSMAX_MIC_IN_LVL: /* Microphone */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_mic_gain(ac, &vol);
- if (!error)
- gus_from_vol(cp, &vol);
- }
- break;
-#endif
-
- case GUSMAX_DAC_LVL: /* dac out */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_aux1_gain(ac, &vol);
- if (!error)
- gus_from_vol(cp, &vol);
- }
- break;
+ if (error != ENXIO)
+ return (error);
- case GUSMAX_LINE_IN_LVL: /* line in */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = cs4231_get_linein_gain(ac, &vol);
- if (!error)
- gus_from_vol(cp, &vol);
- }
- break;
-
- case GUSMAX_MONO_LVL: /* mono */
- if (cp->type == AUDIO_MIXER_VALUE &&
- cp->un.value.num_channels == 1) {
- error = cs4231_get_mono_gain(ac, &vol);
- if (!error)
- gus_from_vol(cp, &vol);
- }
- break;
-
- case GUSMAX_CD_LVL: /* CD */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_aux2_gain(ac, &vol);
- if (!error)
- gus_from_vol(cp, &vol);
- }
- break;
-
- case GUSMAX_MONITOR_LVL: /* monitor level */
- if (cp->type == AUDIO_MIXER_VALUE &&
- cp->un.value.num_channels == 1) {
- error = ad1848_get_mon_gain(ac, &vol);
- if (!error)
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
- vol.left;
- }
- break;
-
- case GUSMAX_OUT_LVL: /* output level */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_out_gain(ac, &vol);
- if (!error)
- gus_from_vol(cp, &vol);
- }
- break;
+ error = EINVAL;
+ switch (cp->dev) {
case GUSMAX_SPEAKER_LVL: /* fake speaker for mute naming */
if (cp->type == AUDIO_MIXER_VALUE) {
if (sc->sc_mixcontrol & GUSMASK_LINE_OUT)
@@ -3246,43 +3170,7 @@ gusmax_mixer_get_port(addr, cp)
else
vol.left = vol.right = AUDIO_MIN_GAIN;
error = 0;
- gus_from_vol(cp, &vol);
- }
- break;
-
- case GUSMAX_LINE_IN_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = ac->line_mute;
- error = 0;
- }
- break;
-
-
- case GUSMAX_DAC_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = ac->aux1_mute;
- error = 0;
- }
- break;
-
- case GUSMAX_CD_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = ac->aux2_mute;
- error = 0;
- }
- break;
-
- case GUSMAX_MONO_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = ac->mono_mute;
- error = 0;
- }
- break;
-
- case GUSMAX_MONITOR_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = ac->mon_mute;
- error = 0;
+ ad1848_from_vol(cp, &vol);
}
break;
@@ -3292,22 +3180,6 @@ gusmax_mixer_get_port(addr, cp)
error = 0;
}
break;
-
- case GUSMAX_REC_LVL: /* record level */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_rec_gain(ac, &vol);
- if (!error)
- gus_from_vol(cp, &vol);
- }
- break;
-
- case GUSMAX_RECORD_SOURCE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = ad1848_get_rec_port(ac);
- error = 0;
- }
- break;
-
default:
error = ENXIO;
break;
@@ -3384,7 +3256,7 @@ gus_mixer_get_port(addr, cp)
if (cp->type == AUDIO_MIXER_VALUE) {
vol.left = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
vol.right = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_RIGHT];
- if (gus_from_vol(cp, &vol))
+ if (ad1848_from_vol(cp, &vol))
error = 0;
}
break;
@@ -3393,7 +3265,7 @@ gus_mixer_get_port(addr, cp)
if (cp->type == AUDIO_MIXER_VALUE) {
vol.left = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
vol.right = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_RIGHT];
- if (gus_from_vol(cp, &vol))
+ if (ad1848_from_vol(cp, &vol))
error = 0;
}
break;
@@ -3402,7 +3274,7 @@ gus_mixer_get_port(addr, cp)
if (cp->type == AUDIO_MIXER_VALUE) {
vol.left = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
vol.right = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_RIGHT];
- if (gus_from_vol(cp, &vol))
+ if (ad1848_from_vol(cp, &vol))
error = 0;
}
break;
@@ -3412,7 +3284,7 @@ gus_mixer_get_port(addr, cp)
if (cp->type == AUDIO_MIXER_VALUE) {
vol.left = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_LEFT];
vol.right = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_RIGHT];
- if (gus_from_vol(cp, &vol))
+ if (ad1848_from_vol(cp, &vol))
error = 0;
}
break;
@@ -3421,7 +3293,7 @@ gus_mixer_get_port(addr, cp)
if (cp->type == AUDIO_MIXER_VALUE) {
vol.left = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
vol.right = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_RIGHT];
- if (gus_from_vol(cp, &vol))
+ if (ad1848_from_vol(cp, &vol))
error = 0;
}
break;
@@ -3494,70 +3366,18 @@ gusmax_mixer_set_port(addr, cp)
struct ad1848_softc *ac = addr;
struct gus_softc *sc = ac->parent;
struct ad1848_volume vol;
- int error = EINVAL;
+ int error = ad1848_mixer_set_port(ac, gusmapping, nummap, cp);
+ if (error != ENXIO)
+ return (error);
+
DPRINTF(("gusmax_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
switch (cp->dev) {
-#if 0
- case GUSMAX_MIC_IN_LVL: /* Microphone */
- if (cp->type == AUDIO_MIXER_VALUE &&
- cp->un.value.num_channels == 1) {
- /* XXX enable/disable pre-MUX fixed gain */
- if (gus_to_vol(cp, &vol))
- error = ad1848_set_mic_gain(ac, &vol);
- }
- break;
-#endif
-
- case GUSMAX_DAC_LVL: /* dac out */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (gus_to_vol(cp, &vol))
- error = ad1848_set_aux1_gain(ac, &vol);
- }
- break;
-
- case GUSMAX_LINE_IN_LVL: /* line in */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (gus_to_vol(cp, &vol))
- error = cs4231_set_linein_gain(ac, &vol);
- }
- break;
-
- case GUSMAX_MONO_LVL: /* mic/mono in */
- if (cp->type == AUDIO_MIXER_VALUE &&
- cp->un.value.num_channels == 1) {
- if (gus_to_vol(cp, &vol))
- error = cs4231_set_mono_gain(ac, &vol);
- }
- break;
-
- case GUSMAX_CD_LVL: /* CD: AUX2 */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (gus_to_vol(cp, &vol))
- error = ad1848_set_aux2_gain(ac, &vol);
- }
- break;
-
- case GUSMAX_MONITOR_LVL:
- if (cp->type == AUDIO_MIXER_VALUE &&
- cp->un.value.num_channels == 1) {
- vol.left = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
- error = ad1848_set_mon_gain(ac, &vol);
- }
- break;
-
- case GUSMAX_OUT_LVL: /* output volume */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (gus_to_vol(cp, &vol))
- error = ad1848_set_out_gain(ac, &vol);
- }
- break;
-
case GUSMAX_SPEAKER_LVL:
if (cp->type == AUDIO_MIXER_VALUE &&
cp->un.value.num_channels == 1) {
- if (gus_to_vol(cp, &vol)) {
+ if (ad1848_to_vol(cp, &vol)) {
gus_speaker_ctl(sc, vol.left > AUDIO_MIN_GAIN ?
SPKR_ON : SPKR_OFF);
error = 0;
@@ -3565,53 +3385,6 @@ gusmax_mixer_set_port(addr, cp)
}
break;
- case GUSMAX_LINE_IN_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- ac->line_mute = cp->un.ord ? 1 : 0;
- DPRINTF(("line mute %d\n", cp->un.ord));
- cs4231_mute_line(ac, ac->line_mute);
- gus_linein_ctl(sc, ac->line_mute ? SPKR_OFF : SPKR_ON);
- error = 0;
- }
- break;
-
- case GUSMAX_DAC_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- ac->aux1_mute = cp->un.ord ? 1 : 0;
- DPRINTF(("dac mute %d\n", cp->un.ord));
- ad1848_mute_aux1(ac, ac->aux1_mute);
- error = 0;
- }
- break;
-
- case GUSMAX_CD_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- ac->aux2_mute = cp->un.ord ? 1 : 0;
- DPRINTF(("cd mute %d\n", cp->un.ord));
- ad1848_mute_aux2(ac, ac->aux2_mute);
- error = 0;
- }
- break;
-
- case GUSMAX_MONO_MUTE: /* Microphone */
- if (cp->type == AUDIO_MIXER_ENUM) {
- ac->mono_mute = cp->un.ord ? 1 : 0;
- DPRINTF(("mono mute %d\n", cp->un.ord));
- cs4231_mute_mono(ac, ac->mono_mute);
- gus_mic_ctl(sc, ac->mono_mute ? SPKR_OFF : SPKR_ON);
- error = 0;
- }
- break;
-
- case GUSMAX_MONITOR_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- ac->mon_mute = cp->un.ord ? 1 : 0;
- DPRINTF(("mono mute %d\n", cp->un.ord));
- cs4231_mute_monitor(ac, ac->mon_mute);
- error = 0;
- }
- break;
-
case GUSMAX_SPEAKER_MUTE:
if (cp->type == AUDIO_MIXER_ENUM) {
gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
@@ -3619,19 +3392,6 @@ gusmax_mixer_set_port(addr, cp)
}
break;
- case GUSMAX_REC_LVL: /* record level */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (gus_to_vol(cp, &vol))
- error = ad1848_set_rec_gain(ac, &vol);
- }
- break;
-
- case GUSMAX_RECORD_SOURCE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- error = ad1848_set_rec_port(ac, cp->un.ord);
- }
- break;
-
default:
return ENXIO;
/*NOTREACHED*/
@@ -3705,7 +3465,7 @@ gus_mixer_set_port(addr, cp)
case GUSICS_MASTER_LVL:
if (cp->type == AUDIO_MIXER_VALUE) {
- if (gus_to_vol(cp, &vol)) {
+ if (ad1848_to_vol(cp, &vol)) {
ics2101_mix_attenuate(ic,
GUSMIX_CHAN_MASTER,
ICSMIX_LEFT,
@@ -3721,7 +3481,7 @@ gus_mixer_set_port(addr, cp)
case GUSICS_MIC_IN_LVL: /* Microphone */
if (cp->type == AUDIO_MIXER_VALUE) {
- if (gus_to_vol(cp, &vol)) {
+ if (ad1848_to_vol(cp, &vol)) {
ics2101_mix_attenuate(ic,
GUSMIX_CHAN_MIC,
ICSMIX_LEFT,
@@ -3737,7 +3497,7 @@ gus_mixer_set_port(addr, cp)
case GUSICS_LINE_IN_LVL: /* line in */
if (cp->type == AUDIO_MIXER_VALUE) {
- if (gus_to_vol(cp, &vol)) {
+ if (ad1848_to_vol(cp, &vol)) {
ics2101_mix_attenuate(ic,
GUSMIX_CHAN_LINE,
ICSMIX_LEFT,
@@ -3754,7 +3514,7 @@ gus_mixer_set_port(addr, cp)
case GUSICS_CD_LVL:
if (cp->type == AUDIO_MIXER_VALUE) {
- if (gus_to_vol(cp, &vol)) {
+ if (ad1848_to_vol(cp, &vol)) {
ics2101_mix_attenuate(ic,
GUSMIX_CHAN_CD,
ICSMIX_LEFT,
@@ -3770,7 +3530,7 @@ gus_mixer_set_port(addr, cp)
case GUSICS_DAC_LVL: /* dac out */
if (cp->type == AUDIO_MIXER_VALUE) {
- if (gus_to_vol(cp, &vol)) {
+ if (ad1848_to_vol(cp, &vol)) {
ics2101_mix_attenuate(ic,
GUSMIX_CHAN_DAC,
ICSMIX_LEFT,
diff --git a/sys/dev/isa/pss.c b/sys/dev/isa/pss.c
index c2bf800b640..8f907a9c456 100644
--- a/sys/dev/isa/pss.c
+++ b/sys/dev/isa/pss.c
@@ -1,12 +1,12 @@
-/* $OpenBSD: pss.c,v 1.13 1998/04/26 21:02:55 provos Exp $ */
+/* $OpenBSD: pss.c,v 1.14 1998/05/08 18:37:22 csapuntz Exp $ */
/* $NetBSD: pss.c,v 1.38 1998/01/12 09:43:44 thorpej Exp $ */
/*
* Copyright (c) 1994 John Brezak
* Copyright (c) 1991-1993 Regents of the University of California.
- * All rights reserved.
+ * All rightOAs reserved.
*
- * Redistribution and use in source and binary forms, with or without
+x * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
@@ -213,9 +213,6 @@ int pss_get_master_mode __P((struct pss_softc *, u_int *));
int pss_get_treble __P((struct pss_softc *, u_char *));
int pss_get_bass __P((struct pss_softc *, u_char *));
-static int pss_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
-static int pss_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
-
#ifdef AUDIO_DEBUG
void wss_dump_regs __P((struct ad1848_softc *));
#endif
@@ -1134,39 +1131,6 @@ pcdattach(parent, self, aux)
}
#endif /* notyet */
-static int
-pss_to_vol(cp, vol)
- mixer_ctrl_t *cp;
- struct ad1848_volume *vol;
-{
- if (cp->un.value.num_channels == 1) {
- vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
- return(1);
- }
- else if (cp->un.value.num_channels == 2) {
- vol->left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
- vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
- return(1);
- }
- return(0);
-}
-
-static int
-pss_from_vol(cp, vol)
- mixer_ctrl_t *cp;
- struct ad1848_volume *vol;
-{
- if (cp->un.value.num_channels == 1) {
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left;
- return(1);
- }
- else if (cp->un.value.num_channels == 2) {
- cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left;
- cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right;
- return(1);
- }
- return(0);
-}
int
pss_set_master_gain(sc, gp)
@@ -1362,6 +1326,20 @@ pss_getdev(addr, retp)
return 0;
}
+static ad1848_devmap_t mappings[] = {
+{ PSS_MIC_IN_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
+{ PSS_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
+{ PSS_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
+{ PSS_MON_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
+{ PSS_MIC_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
+{ PSS_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
+{ PSS_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL },
+{ PSS_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
+{ PSS_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
+};
+
+static int nummap = sizeof(mappings) / sizeof(mappings[0]);
+
int
pss_mixer_set_port(addr, cp)
void *addr;
@@ -1370,81 +1348,15 @@ pss_mixer_set_port(addr, cp)
struct ad1848_softc *ac = addr;
struct pss_softc *sc = ac->parent;
struct ad1848_volume vol;
- int error = EINVAL;
+ int error = ad1848_mixer_set_port(ac, mappings, nummap, cp);
- DPRINTF(("pss_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
+ if (error != ENXIO)
+ return (error);
switch (cp->dev) {
- case PSS_MIC_IN_LVL: /* Microphone */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (pss_to_vol(cp, &vol))
- error = ad1848_set_aux2_gain(ac, &vol);
- }
- break;
-
- case PSS_MIC_IN_MUTE: /* Microphone */
- if (cp->type == AUDIO_MIXER_ENUM) {
- sc->mic_mute = cp->un.ord;
- DPRINTF(("mic mute %d\n", cp->un.ord));
- ad1848_mute_aux2(ac, cp->un.ord);
- error = 0;
- }
- break;
-
- case PSS_LINE_IN_LVL: /* linein/CD */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (pss_to_vol(cp, &vol))
- error = ad1848_set_aux1_gain(ac, &vol);
- }
- break;
-
- case PSS_LINE_IN_MUTE: /* linein/CD */
- if (cp->type == AUDIO_MIXER_ENUM) {
- sc->cd_mute = cp->un.ord;
- DPRINTF(("CD mute %d\n", cp->un.ord));
- ad1848_mute_aux1(ac, cp->un.ord);
- error = 0;
- }
- break;
-
- case PSS_DAC_LVL: /* dac out */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (pss_to_vol(cp, &vol))
- error = ad1848_set_out_gain(ac, &vol);
- }
- break;
-
- case PSS_DAC_MUTE: /* dac out */
- if (cp->type == AUDIO_MIXER_ENUM) {
- sc->dac_mute = cp->un.ord;
- DPRINTF(("DAC mute %d\n", cp->un.ord));
- error = 0;
- }
- break;
-
- case PSS_REC_LVL: /* record level */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (pss_to_vol(cp, &vol))
- error = ad1848_set_rec_gain(ac, &vol);
- }
- break;
-
- case PSS_RECORD_SOURCE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- error = ad1848_set_rec_port(ac, cp->un.ord);
- }
- break;
-
- case PSS_MON_LVL:
- if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) {
- vol.left = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
- error = ad1848_set_mon_gain(ac, &vol);
- }
- break;
-
case PSS_MASTER_VOL: /* master volume */
if (cp->type == AUDIO_MIXER_VALUE) {
- if (pss_to_vol(cp, &vol))
+ if (ad1848_to_vol(cp, &vol))
error = pss_set_master_gain(sc, &vol);
}
break;
@@ -1481,84 +1393,19 @@ pss_mixer_get_port(addr, cp)
struct pss_softc *sc = ac->parent;
struct ad1848_volume vol;
u_char eq;
- int error = EINVAL;
-
- DPRINTF(("pss_mixer_get_port: port=%d\n", cp->dev));
-
- switch (cp->dev) {
- case PSS_MIC_IN_LVL: /* Microphone */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_aux2_gain(ac, &vol);
- if (!error)
- pss_from_vol(cp, &vol);
- }
- break;
+ int error = ad1848_mixer_get_port(ac, mappings, nummap, cp);
- case PSS_MIC_IN_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = sc->mic_mute;
- error = 0;
- }
- break;
-
- case PSS_LINE_IN_LVL: /* linein/CD */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_aux1_gain(ac, &vol);
- if (!error)
- pss_from_vol(cp, &vol);
- }
- break;
+ if (error != ENXIO)
+ return (error);
- case PSS_LINE_IN_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = sc->cd_mute;
- error = 0;
- }
- break;
-
- case PSS_DAC_LVL: /* dac out */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_out_gain(ac, &vol);
- if (!error)
- pss_from_vol(cp, &vol);
- }
- break;
-
- case PSS_DAC_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = sc->dac_mute;
- error = 0;
- }
- break;
-
- case PSS_REC_LVL: /* record level */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_rec_gain(ac, &vol);
- if (!error)
- pss_from_vol(cp, &vol);
- }
- break;
-
- case PSS_RECORD_SOURCE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = ad1848_get_rec_port(ac);
- error = 0;
- }
- break;
-
- case PSS_MON_LVL: /* monitor level */
- if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) {
- error = ad1848_get_mon_gain(ac, &vol);
- if (!error)
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol.left;
- }
- break;
+ error = EINVAL;
+ switch (cp->dev) {
case PSS_MASTER_VOL: /* master volume */
if (cp->type == AUDIO_MIXER_VALUE) {
error = pss_get_master_gain(sc, &vol);
if (!error)
- pss_from_vol(cp, &vol);
+ ad1848_from_vol(cp, &vol);
}
break;
diff --git a/sys/dev/isa/wss.c b/sys/dev/isa/wss.c
index e14338bdd44..147298bf6a5 100644
--- a/sys/dev/isa/wss.c
+++ b/sys/dev/isa/wss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wss.c,v 1.15 1998/04/26 21:03:03 provos Exp $ */
+/* $OpenBSD: wss.c,v 1.16 1998/05/08 18:37:24 csapuntz Exp $ */
/* $NetBSD: wss.c,v 1.42 1998/01/19 22:18:23 augustss Exp $ */
/*
@@ -81,9 +81,6 @@ int wss_mixer_set_port __P((void *, mixer_ctrl_t *));
int wss_mixer_get_port __P((void *, mixer_ctrl_t *));
int wss_query_devinfo __P((void *, mixer_devinfo_t *));
-static int wss_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
-static int wss_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
-
/*
* Define our interface to the higher level audio driver.
*/
@@ -157,40 +154,6 @@ wssattach(sc)
audio_attach_mi(&wss_hw_if, 0, &sc->sc_ad1848, &sc->sc_dev);
}
-static int
-wss_to_vol(cp, vol)
- mixer_ctrl_t *cp;
- struct ad1848_volume *vol;
-{
- if (cp->un.value.num_channels == 1) {
- vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
- return(1);
- }
- else if (cp->un.value.num_channels == 2) {
- vol->left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
- vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
- return(1);
- }
- return(0);
-}
-
-static int
-wss_from_vol(cp, vol)
- mixer_ctrl_t *cp;
- struct ad1848_volume *vol;
-{
- if (cp->un.value.num_channels == 1) {
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left;
- return(1);
- }
- else if (cp->un.value.num_channels == 2) {
- cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left;
- cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right;
- return(1);
- }
- return(0);
-}
-
int
wss_getdev(addr, retp)
void *addr;
@@ -200,90 +163,28 @@ wss_getdev(addr, retp)
return 0;
}
+static ad1848_devmap_t mappings[] = {
+{ WSS_MIC_IN_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
+{ WSS_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
+{ WSS_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
+{ WSS_MON_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
+{ WSS_MIC_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
+{ WSS_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
+{ WSS_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL },
+{ WSS_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
+{ WSS_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
+};
+
+static int nummap = sizeof(mappings) / sizeof(mappings[0]);
+
int
wss_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
struct ad1848_softc *ac = addr;
- struct wss_softc *sc = ac->parent;
- struct ad1848_volume vol;
- int error = EINVAL;
-
- DPRINTF(("wss_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
-
- switch (cp->dev) {
- case WSS_MIC_IN_LVL: /* Microphone */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (wss_to_vol(cp, &vol))
- error = ad1848_set_aux2_gain(ac, &vol);
- }
- break;
-
- case WSS_MIC_IN_MUTE: /* Microphone */
- if (cp->type == AUDIO_MIXER_ENUM) {
- sc->mic_mute = cp->un.ord;
- DPRINTF(("mic mute %d\n", cp->un.ord));
- error = 0;
- }
- break;
-
- case WSS_LINE_IN_LVL: /* linein/CD */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (wss_to_vol(cp, &vol))
- error = ad1848_set_aux1_gain(ac, &vol);
- }
- break;
-
- case WSS_LINE_IN_MUTE: /* linein/CD */
- if (cp->type == AUDIO_MIXER_ENUM) {
- sc->cd_mute = cp->un.ord;
- DPRINTF(("CD mute %d\n", cp->un.ord));
- error = 0;
- }
- break;
-
- case WSS_DAC_LVL: /* dac out */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (wss_to_vol(cp, &vol))
- error = ad1848_set_out_gain(ac, &vol);
- }
- break;
-
- case WSS_DAC_MUTE: /* dac out */
- if (cp->type == AUDIO_MIXER_ENUM) {
- sc->dac_mute = cp->un.ord;
- DPRINTF(("DAC mute %d\n", cp->un.ord));
- error = 0;
- }
- break;
-
- case WSS_REC_LVL: /* record level */
- if (cp->type == AUDIO_MIXER_VALUE) {
- if (wss_to_vol(cp, &vol))
- error = ad1848_set_rec_gain(ac, &vol);
- }
- break;
-
- case WSS_RECORD_SOURCE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- error = ad1848_set_rec_port(ac, cp->un.ord);
- }
- break;
- case WSS_MON_LVL:
- if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) {
- vol.left = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
- error = ad1848_set_mon_gain(ac, &vol);
- }
- break;
-
- default:
- return ENXIO;
- /*NOTREACHED*/
- }
-
- return 0;
+ return (ad1848_mixer_set_port(ac, mappings, nummap, cp));
}
int
@@ -292,87 +193,8 @@ wss_mixer_get_port(addr, cp)
mixer_ctrl_t *cp;
{
struct ad1848_softc *ac = addr;
- struct wss_softc *sc = ac->parent;
- struct ad1848_volume vol;
- int error = EINVAL;
-
- DPRINTF(("wss_mixer_get_port: port=%d\n", cp->dev));
-
- switch (cp->dev) {
- case WSS_MIC_IN_LVL: /* Microphone */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_aux2_gain(ac, &vol);
- if (!error)
- wss_from_vol(cp, &vol);
- }
- break;
-
- case WSS_MIC_IN_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = sc->mic_mute;
- error = 0;
- }
- break;
-
- case WSS_LINE_IN_LVL: /* linein/CD */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_aux1_gain(ac, &vol);
- if (!error)
- wss_from_vol(cp, &vol);
- }
- break;
-
- case WSS_LINE_IN_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = sc->cd_mute;
- error = 0;
- }
- break;
-
- case WSS_DAC_LVL: /* dac out */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_out_gain(ac, &vol);
- if (!error)
- wss_from_vol(cp, &vol);
- }
- break;
-
- case WSS_DAC_MUTE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = sc->dac_mute;
- error = 0;
- }
- break;
-
- case WSS_REC_LVL: /* record level */
- if (cp->type == AUDIO_MIXER_VALUE) {
- error = ad1848_get_rec_gain(ac, &vol);
- if (!error)
- wss_from_vol(cp, &vol);
- }
- break;
-
- case WSS_RECORD_SOURCE:
- if (cp->type == AUDIO_MIXER_ENUM) {
- cp->un.ord = ad1848_get_rec_port(ac);
- error = 0;
- }
- break;
-
- case WSS_MON_LVL: /* monitor level */
- if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) {
- error = ad1848_get_mon_gain(ac, &vol);
- if (!error)
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol.left;
- }
- break;
-
- default:
- error = ENXIO;
- break;
- }
- return(error);
+ return (ad1848_mixer_get_port(ac, mappings, nummap, cp));
}
int
diff --git a/sys/dev/isa/ym.c b/sys/dev/isa/ym.c
new file mode 100644
index 00000000000..e752bf3c902
--- /dev/null
+++ b/sys/dev/isa/ym.c
@@ -0,0 +1,470 @@
+/* $OpenBSD: ym.c,v 1.1 1998/05/08 18:37:25 csapuntz Exp $ */
+
+
+/*
+ * Copyright (c) 1998 Constantine Sapuntzakis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/pio.h>
+
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+
+#include <dev/ic/ad1848reg.h>
+#include <dev/isa/ad1848var.h>
+#include <dev/ic/opl3sa3.h>
+#include <dev/isa/ymvar.h>
+
+
+int ym_getdev __P((void *, struct audio_device *));
+int ym_mixer_set_port __P((void *, mixer_ctrl_t *));
+int ym_mixer_get_port __P((void *, mixer_ctrl_t *));
+int ym_query_devinfo __P((void *, mixer_devinfo_t *));
+
+static void ym_mute __P((struct ym_softc *, int, int));
+static void ym_set_master_gain __P((struct ym_softc *, struct ad1848_volume *));
+static void ym_set_mic_gain __P((struct ym_softc *, struct ad1848_volume *));
+
+
+
+struct audio_hw_if ym_hw_if = {
+ ad1848_open,
+ ad1848_close,
+ NULL,
+ ad1848_query_encoding,
+ ad1848_set_params,
+ ad1848_round_blocksize,
+ ad1848_commit_settings,
+ ad1848_dma_init_output,
+ ad1848_dma_init_input,
+ ad1848_dma_output,
+ ad1848_dma_input,
+ ad1848_halt_out_dma,
+ ad1848_halt_in_dma,
+ NULL,
+ ym_getdev,
+ NULL,
+ ym_mixer_set_port,
+ ym_mixer_get_port,
+ ym_query_devinfo,
+ ad1848_malloc,
+ ad1848_free,
+ ad1848_round,
+ ad1848_mappage,
+ ad1848_get_props,
+};
+
+
+struct cfdriver ym_cd = {
+ NULL, "ym", DV_DULL
+};
+
+struct audio_device ym_device = {
+ "ym,ad1848",
+ "",
+ "ym"
+};
+
+static __inline int ym_read __P((struct ym_softc *, int));
+static __inline void ym_write __P((struct ym_softc *, int, int));
+
+void
+ym_attach(sc)
+ struct ym_softc *sc;
+
+{
+ struct ad1848_volume vol_mid = {220, 220};
+ struct ad1848_volume vol_0 = {0, 0};
+
+ sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->ym_irq, IST_EDGE, IPL_AUDIO,
+ ad1848_intr, &sc->sc_ad1848, sc->sc_dev.dv_xname);
+
+ ad1848_attach(&sc->sc_ad1848);
+ sc->sc_ad1848.parent = sc;
+
+ /* Establish chip in well known mode */
+ ym_set_master_gain(sc, &vol_mid);
+ ym_set_mic_gain(sc, &vol_0);
+ sc->master_mute = 0;
+ ym_mute(sc, SA3_LCH, sc->master_mute);
+ ym_mute(sc, SA3_RCH, sc->master_mute);
+
+ sc->mic_mute = 1;
+ ym_mute(sc, SA3_MIC, sc->mic_mute);
+
+ audio_attach_mi(&ym_hw_if, 0, &sc->sc_ad1848, &sc->sc_dev);
+}
+
+static __inline int
+ym_read(sc, reg)
+ struct ym_softc *sc;
+ int reg;
+{
+ bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, 0x1d);
+ bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, (reg & 0xff));
+ return (bus_space_read_1(sc->sc_iot, sc->sc_controlioh, 1));
+}
+
+static __inline void
+ym_write(sc, reg, data)
+ struct ym_softc *sc;
+ int reg;
+ int data;
+{
+ bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, 0x1d);
+ bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, (reg & 0xff));
+ bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 1, (data & 0xff));
+}
+
+
+
+int
+ym_getdev(addr, retp)
+ void *addr;
+ struct audio_device *retp;
+{
+ *retp = ym_device;
+ return 0;
+}
+
+
+static ad1848_devmap_t mappings[] = {
+{ YM_MIDI_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
+{ YM_CD_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
+{ YM_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
+{ YM_LINE_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL },
+{ YM_SPEAKER_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
+{ YM_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL },
+{ YM_MIDI_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
+{ YM_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
+{ YM_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL },
+{ YM_LINE_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL },
+{ YM_SPEAKER_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL },
+{ YM_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL },
+{ YM_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
+{ YM_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
+};
+
+static int nummap = sizeof(mappings) / sizeof(mappings[0]);
+
+
+static void
+ym_mute(sc, left_reg, mute)
+ struct ym_softc *sc;
+ int left_reg;
+ int mute;
+
+{
+ u_char reg;
+
+ if (mute) {
+ reg = ym_read(sc, left_reg);
+ ym_write (sc, left_reg, reg | 0x80);
+ } else {
+ reg = ym_read(sc, left_reg);
+ ym_write (sc, left_reg, reg & ~0x80);
+ }
+}
+
+#define MIC_ATTEN_BITS 0x1f
+#define MASTER_ATTEN_BITS 0x0f
+
+
+static void
+ym_set_master_gain(sc, vol)
+ struct ym_softc *sc;
+ struct ad1848_volume *vol;
+{
+ u_char reg;
+ u_int atten;
+
+ sc->master_gain = *vol;
+
+ atten = ((AUDIO_MAX_GAIN - vol->left) * MASTER_ATTEN_BITS)/AUDIO_MAX_GAIN;
+
+ reg = ym_read(sc, SA3_LCH);
+
+ reg &= ~(MASTER_ATTEN_BITS);
+ reg |= atten;
+
+ ym_write (sc, SA3_LCH, reg);
+
+ atten = ((AUDIO_MAX_GAIN - vol->right) * MASTER_ATTEN_BITS)/AUDIO_MAX_GAIN;
+
+ reg = ym_read(sc, SA3_RCH) & ~(MASTER_ATTEN_BITS);
+ reg |= atten;
+
+ ym_write (sc, SA3_RCH, reg);
+}
+
+static void
+ym_set_mic_gain(sc, vol)
+ struct ym_softc *sc;
+ struct ad1848_volume *vol;
+{
+ u_char reg;
+ u_int atten;
+
+ sc->mic_gain = *vol;
+
+ atten = ((AUDIO_MAX_GAIN - vol->left) * MIC_ATTEN_BITS)/AUDIO_MAX_GAIN;
+
+ reg = ym_read(sc, SA3_MIC) & ~(MIC_ATTEN_BITS);
+ reg |= atten;
+
+ ym_write (sc, SA3_MIC, reg);
+}
+
+int
+ym_mixer_set_port(addr, cp)
+ void *addr;
+ mixer_ctrl_t *cp;
+{
+ struct ad1848_softc *ac = addr;
+ struct ym_softc *sc = ac->parent;
+ struct ad1848_volume vol;
+ int error = ad1848_mixer_set_port(ac, mappings, nummap, cp);
+
+ if (error != ENXIO)
+ return (error);
+
+ error = 0;
+
+ switch (cp->dev) {
+ case YM_OUTPUT_LVL:
+ ad1848_to_vol(cp, &vol);
+ ym_set_master_gain(sc, &vol);
+ break;
+
+ case YM_OUTPUT_MUTE:
+ sc->master_mute = (cp->un.ord != 0);
+ ym_mute(sc, SA3_LCH, sc->master_mute);
+ ym_mute(sc, SA3_RCH, sc->master_mute);
+ break;
+
+ case YM_MIC_LVL:
+ if (cp->un.value.num_channels != 1)
+ error = EINVAL;
+
+ ad1848_to_vol(cp, &vol);
+ ym_set_mic_gain(sc, &vol);
+ break;
+
+ case YM_MIC_MUTE:
+ sc->mic_mute = (cp->un.ord != 0);
+ ym_mute(sc, SA3_MIC, sc->mic_mute);
+ break;
+
+ default:
+ return ENXIO;
+ /*NOTREACHED*/
+ }
+
+ return (error);
+}
+
+int
+ym_mixer_get_port(addr, cp)
+ void *addr;
+ mixer_ctrl_t *cp;
+{
+ struct ad1848_softc *ac = addr;
+ struct ym_softc *sc = ac->parent;
+
+ int error = ad1848_mixer_get_port(ac, mappings, nummap, cp);
+
+ if (error != ENXIO)
+ return (error);
+
+ error = 0;
+
+ switch (cp->dev) {
+ case YM_OUTPUT_LVL:
+ ad1848_from_vol(cp, &sc->master_gain);
+ break;
+
+ case YM_OUTPUT_MUTE:
+ cp->un.ord = sc->master_mute;
+ break;
+
+ case YM_MIC_LVL:
+ if (cp->un.value.num_channels != 1)
+ error = EINVAL;
+
+ ad1848_from_vol(cp, &sc->mic_gain);
+ break;
+
+ case YM_MIC_MUTE:
+ cp->un.ord = sc->mic_mute;
+ break;
+
+ default:
+ error = ENXIO;
+ break;
+ }
+
+ return(error);
+}
+
+static char *mixer_classes[] = { AudioCinputs, AudioCrecord, AudioCoutputs,
+ AudioCmonitor };
+
+int
+ym_query_devinfo(addr, dip)
+ void *addr;
+ mixer_devinfo_t *dip;
+{
+ static char *mixer_port_names[] = { AudioNmidi, AudioNcd, AudioNdac,
+ AudioNline, AudioNspeaker,
+ AudioNmicrophone,
+ AudioNmonitor};
+
+ dip->next = dip->prev = AUDIO_MIXER_LAST;
+
+ switch(dip->index) {
+ case YM_INPUT_CLASS: /* input class descriptor */
+ case YM_OUTPUT_CLASS:
+ case YM_MONITOR_CLASS:
+ case YM_RECORD_CLASS:
+ dip->type = AUDIO_MIXER_CLASS;
+ dip->mixer_class = dip->index;
+ strcpy(dip->label.name,
+ mixer_classes[dip->index - YM_INPUT_CLASS]);
+ break;
+
+ case YM_MIDI_LVL:
+ case YM_CD_LVL:
+ case YM_DAC_LVL:
+ case YM_LINE_LVL:
+ case YM_SPEAKER_LVL:
+ case YM_MIC_LVL:
+ case YM_MONITOR_LVL:
+ dip->type = AUDIO_MIXER_VALUE;
+ if (dip->index == YM_MONITOR_LVL)
+ dip->mixer_class = YM_MONITOR_CLASS;
+ else
+ dip->mixer_class = YM_INPUT_CLASS;
+
+ dip->next = dip->index + 7;
+
+ strcpy(dip->label.name,mixer_port_names[dip->index - YM_MIDI_LVL]);
+
+ if (dip->index == YM_SPEAKER_LVL ||
+ dip->index == YM_MIC_LVL)
+ dip->un.v.num_channels = 1;
+ else
+ dip->un.v.num_channels = 2;
+
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ break;
+
+ case YM_MIDI_MUTE:
+ case YM_CD_MUTE:
+ case YM_DAC_MUTE:
+ case YM_LINE_MUTE:
+ case YM_SPEAKER_MUTE:
+ case YM_MIC_MUTE:
+ case YM_MONITOR_MUTE:
+ if (dip->index == YM_MONITOR_MUTE)
+ dip->mixer_class = YM_MONITOR_CLASS;
+ else
+ dip->mixer_class = YM_INPUT_CLASS;
+ dip->type = AUDIO_MIXER_ENUM;
+ dip->prev = dip->index - 7;
+mute:
+ strcpy(dip->label.name, AudioNmute);
+ 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 YM_OUTPUT_LVL:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = YM_OUTPUT_CLASS;
+ dip->next = YM_OUTPUT_MUTE;
+ strcpy(dip->label.name, AudioNmaster);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ break;
+
+ case YM_OUTPUT_MUTE:
+ dip->mixer_class = YM_OUTPUT_CLASS;
+ dip->type = AUDIO_MIXER_ENUM;
+ dip->prev = YM_OUTPUT_LVL;
+ goto mute;
+
+ case YM_REC_LVL: /* record level */
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = YM_RECORD_CLASS;
+ dip->next = YM_RECORD_SOURCE;
+ strcpy(dip->label.name, AudioNrecord);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ break;
+
+
+ case YM_RECORD_SOURCE:
+ dip->mixer_class = YM_RECORD_CLASS;
+ dip->type = AUDIO_MIXER_ENUM;
+ dip->prev = YM_REC_LVL;
+ strcpy(dip->label.name, AudioNsource);
+ dip->un.e.num_mem = 4;
+ strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
+ dip->un.e.member[0].ord = MIC_IN_PORT;
+ strcpy(dip->un.e.member[1].label.name, AudioNline);
+ dip->un.e.member[1].ord = LINE_IN_PORT;
+ strcpy(dip->un.e.member[2].label.name, AudioNdac);
+ dip->un.e.member[2].ord = DAC_IN_PORT;
+ strcpy(dip->un.e.member[3].label.name, AudioNcd);
+ dip->un.e.member[3].ord = AUX1_IN_PORT;
+ break;
+
+ default:
+ return ENXIO;
+ /*NOTREACHED*/
+ }
+
+ return 0;
+}
diff --git a/sys/dev/isa/ym_isapnp.c b/sys/dev/isa/ym_isapnp.c
new file mode 100644
index 00000000000..b0f41d1affb
--- /dev/null
+++ b/sys/dev/isa/ym_isapnp.c
@@ -0,0 +1,126 @@
+/* $OpenBSD: ym_isapnp.c,v 1.1 1998/05/08 18:37:25 csapuntz Exp $ */
+
+
+/*
+ * Copyright (c) 1991-1993 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Driver for the Yamaha OPL3-SA3 chipset. This is found on many laptops
+ * and Pentium (II) motherboards.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+
+#include <dev/ic/ad1848reg.h>
+#include <dev/isa/ad1848var.h>
+
+#include <dev/ic/cs4231reg.h>
+#include <dev/isa/cs4231var.h>
+
+#include <dev/isa/wssreg.h>
+#include <dev/isa/ymvar.h>
+
+int ym_isapnp_match __P((struct device *, void *, void *));
+void ym_isapnp_attach __P((struct device *, struct device *, void *));
+
+struct cfattach ym_isapnp_ca = {
+ sizeof(struct ym_softc), ym_isapnp_match, ym_isapnp_attach
+};
+
+
+/*
+ * Probe / attach routines.
+ */
+
+/*
+ * Probe for the soundblaster hardware.
+ */
+int
+ym_isapnp_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+
+ return 1;
+}
+
+/*
+ * Attach hardware to driver, attach hardware driver to audio
+ * pseudo-device driver.
+ */
+void
+ym_isapnp_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct ym_softc *sc = (struct ym_softc *)self;
+ struct isa_attach_args *ia = aux;
+
+ if (ia->ipa_nio < 5) {
+ printf ("Insufficient I/O ports... not really attached\n");
+ return;
+ }
+
+ sc->sc_iot = ia->ia_iot;
+ sc->sc_ioh = ia->ipa_io[1].h;
+ sc->sc_ic = ia->ia_ic;
+
+ sc->ym_irq = ia->ipa_irq[0].num;
+ sc->ym_drq = ia->ipa_drq[0].num;
+ sc->ym_recdrq = ia->ipa_drq[1].num;
+
+ sc->sc_controlioh = ia->ipa_io[4].h;
+
+ sc->sc_ad1848.sc_iobase = ia->ipa_io[1].base + WSS_CODEC;
+ sc->sc_ad1848.sc_isa = parent->dv_parent;
+ sc->sc_ad1848.sc_iot = sc->sc_iot;
+ sc->sc_ad1848.sc_iooffs = WSS_CODEC;
+ sc->sc_ad1848.mode = 2;
+ sc->sc_ad1848.MCE_bit = MODE_CHANGE_ENABLE;
+
+ ym_attach(sc);
+}
+
diff --git a/sys/dev/isa/ymvar.h b/sys/dev/isa/ymvar.h
new file mode 100644
index 00000000000..6981dd46e8c
--- /dev/null
+++ b/sys/dev/isa/ymvar.h
@@ -0,0 +1,89 @@
+/* $OpenBSD: ymvar.h,v 1.1 1998/05/08 18:37:25 csapuntz Exp $ */
+/* $NetBSD: wssvar.h,v 1.1 1998/01/19 22:18:25 augustss Exp $ */
+
+/*
+ * Copyright (c) 1994 John Brezak
+ * Copyright (c) 1991-1993 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Mixer devices
+ */
+#define YM_MIDI_LVL 0
+#define YM_CD_LVL 1
+#define YM_DAC_LVL 2
+#define YM_LINE_LVL 3
+#define YM_SPEAKER_LVL 4
+#define YM_MIC_LVL 5
+#define YM_MONITOR_LVL 6
+#define YM_MIDI_MUTE 7
+#define YM_CD_MUTE 8
+#define YM_DAC_MUTE 9
+#define YM_LINE_MUTE 10
+#define YM_SPEAKER_MUTE 11
+#define YM_MIC_MUTE 12
+#define YM_MONITOR_MUTE 13
+
+#define YM_REC_LVL 14
+#define YM_RECORD_SOURCE 15
+
+#define YM_OUTPUT_LVL 16
+#define YM_OUTPUT_MUTE 17
+
+/* Classes - don't change this without looking at mixer_classes array */
+#define YM_INPUT_CLASS 18
+#define YM_RECORD_CLASS 19
+#define YM_OUTPUT_CLASS 20
+#define YM_MONITOR_CLASS 21
+
+
+struct ym_softc {
+ struct device sc_dev; /* base device */
+ struct isadev sc_id; /* ISA device */
+ void *sc_ih; /* interrupt vectoring */
+ bus_space_tag_t sc_iot; /* tag */
+ bus_space_handle_t sc_ioh; /* handle */
+ isa_chipset_tag_t sc_ic;
+
+ bus_space_handle_t sc_controlioh;
+
+ struct ad1848_softc sc_ad1848;
+#define ym_irq sc_ad1848.sc_irq
+#define ym_drq sc_ad1848.sc_drq
+#define ym_recdrq sc_ad1848.sc_recdrq
+
+ int master_mute, mic_mute;
+ struct ad1848_volume mic_gain, master_gain;
+};
+
+void ym_attach __P((struct ym_softc *));