diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1998-05-08 18:37:27 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1998-05-08 18:37:27 +0000 |
commit | 5d96939538c658040195a46708dd5427601d3050 (patch) | |
tree | 1e1faf4a2171057e1ca93aac2b2ea8a72ab7af05 /sys/dev/isa | |
parent | b7d211a2451c1f0906a61e2e2f40466cc4561b6c (diff) |
Cleaned up AD1848 driver and added driver for Yamaha OPL3-SA3 to tree.
Diffstat (limited to 'sys/dev/isa')
-rw-r--r-- | sys/dev/isa/ad1848.c | 533 | ||||
-rw-r--r-- | sys/dev/isa/ad1848var.h | 90 | ||||
-rw-r--r-- | sys/dev/isa/gus.c | 330 | ||||
-rw-r--r-- | sys/dev/isa/pss.c | 207 | ||||
-rw-r--r-- | sys/dev/isa/wss.c | 212 | ||||
-rw-r--r-- | sys/dev/isa/ym.c | 470 | ||||
-rw-r--r-- | sys/dev/isa/ym_isapnp.c | 126 | ||||
-rw-r--r-- | sys/dev/isa/ymvar.h | 89 |
8 files changed, 1105 insertions, 952 deletions
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 *)); |