Add support code to have the Hardware Volume Control interact with the

software mixer Master Volume state in a defined way by lazily updating the
latter if input from the former was processed.
This commit is contained in:
kleink 1999-12-10 19:13:00 +00:00
parent 486d64de0f
commit c88b5146dc
2 changed files with 59 additions and 5 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: eso.c,v 1.13 1999/12/03 22:34:28 kleink Exp $ */ /* $NetBSD: eso.c,v 1.14 1999/12/10 19:13:00 kleink Exp $ */
/* /*
* Copyright (c) 1999 Klaus J. Klein * Copyright (c) 1999 Klaus J. Klein
@ -156,6 +156,7 @@ static const char * const eso_rev2model[] = {
static uint8_t eso_read_ctlreg __P((struct eso_softc *, uint8_t)); static uint8_t eso_read_ctlreg __P((struct eso_softc *, uint8_t));
static uint8_t eso_read_mixreg __P((struct eso_softc *, uint8_t)); static uint8_t eso_read_mixreg __P((struct eso_softc *, uint8_t));
static uint8_t eso_read_rdr __P((struct eso_softc *)); static uint8_t eso_read_rdr __P((struct eso_softc *));
static void eso_reload_master_vol __P((struct eso_softc *));
static int eso_reset __P((struct eso_softc *)); static int eso_reset __P((struct eso_softc *));
static void eso_set_gain __P((struct eso_softc *, unsigned int)); static void eso_set_gain __P((struct eso_softc *, unsigned int));
static int eso_set_monooutsrc __P((struct eso_softc *, unsigned int)); static int eso_set_monooutsrc __P((struct eso_softc *, unsigned int));
@ -258,13 +259,20 @@ eso_attach(parent, self, aux)
/* Enable the relevant (DMA) interrupts. */ /* Enable the relevant (DMA) interrupts. */
bus_space_write_1(sc->sc_iot, sc->sc_ioh, ESO_IO_IRQCTL, bus_space_write_1(sc->sc_iot, sc->sc_ioh, ESO_IO_IRQCTL,
ESO_IO_IRQCTL_A1IRQ | ESO_IO_IRQCTL_A2IRQ | ESO_IO_IRQCTL_MPUIRQ); ESO_IO_IRQCTL_A1IRQ | ESO_IO_IRQCTL_A2IRQ | ESO_IO_IRQCTL_HVIRQ |
ESO_IO_IRQCTL_MPUIRQ);
/* Set up A1's sample rate generator for new-style parameters. */ /* Set up A1's sample rate generator for new-style parameters. */
a2mode = eso_read_mixreg(sc, ESO_MIXREG_A2MODE); a2mode = eso_read_mixreg(sc, ESO_MIXREG_A2MODE);
a2mode |= ESO_MIXREG_A2MODE_NEWA1 | ESO_MIXREG_A2MODE_ASYNC; a2mode |= ESO_MIXREG_A2MODE_NEWA1 | ESO_MIXREG_A2MODE_ASYNC;
eso_write_mixreg(sc, ESO_MIXREG_A2MODE, a2mode); eso_write_mixreg(sc, ESO_MIXREG_A2MODE, a2mode);
/* Slave Master Volume to Hardware Volume Control Counter, unask IRQ. */
mvctl = eso_read_mixreg(sc, ESO_MIXREG_MVCTL);
mvctl &= ~ESO_MIXREG_MVCTL_SPLIT;
mvctl |= ESO_MIXREG_MVCTL_HVIRQM;
eso_write_mixreg(sc, ESO_MIXREG_MVCTL, mvctl);
/* Set mixer regs to something reasonable, needs work. */ /* Set mixer regs to something reasonable, needs work. */
sc->sc_recsrc = ESO_MIXREG_ERS_LINE; sc->sc_recsrc = ESO_MIXREG_ERS_LINE;
sc->sc_monooutsrc = ESO_MIXREG_MPM_MOMUTE; sc->sc_monooutsrc = ESO_MIXREG_MPM_MOMUTE;
@ -513,7 +521,7 @@ eso_intr(hdl)
/* If it wasn't ours, that's all she wrote. */ /* If it wasn't ours, that's all she wrote. */
if ((irqctl & (ESO_IO_IRQCTL_A1IRQ | ESO_IO_IRQCTL_A2IRQ | if ((irqctl & (ESO_IO_IRQCTL_A1IRQ | ESO_IO_IRQCTL_A2IRQ |
ESO_IO_IRQCTL_MPUIRQ)) == 0) ESO_IO_IRQCTL_HVIRQ | ESO_IO_IRQCTL_MPUIRQ)) == 0)
return (0); return (0);
if (irqctl & ESO_IO_IRQCTL_A1IRQ) { if (irqctl & ESO_IO_IRQCTL_A1IRQ) {
@ -540,6 +548,19 @@ eso_intr(hdl)
wakeup(&sc->sc_pintr); wakeup(&sc->sc_pintr);
} }
if (irqctl & ESO_IO_IRQCTL_HVIRQ) {
/* Clear interrupt. */
eso_write_mixreg(sc, ESO_MIXREG_CHVIR, ESO_MIXREG_CHVIR_CHVIR);
/*
* Raise a flag to cause a lazy update of the in-softc gain
* values the next time the software mixer is read to keep
* interrupt service cost low. ~0 cannot occur otherwise
* as the master volume has a precision of 6 bits only.
*/
sc->sc_gain[ESO_MASTER_VOL][ESO_LEFT] = (uint8_t)~0;
}
#if NMPU > 0 #if NMPU > 0
if ((irqctl & ESO_IO_IRQCTL_MPUIRQ) && sc->sc_mpudev != NULL) if ((irqctl & ESO_IO_IRQCTL_MPUIRQ) && sc->sc_mpudev != NULL)
mpu_intr(sc->sc_mpudev); mpu_intr(sc->sc_mpudev);
@ -1069,13 +1090,17 @@ eso_get_port(hdl, cp)
struct eso_softc *sc = hdl; struct eso_softc *sc = hdl;
switch (cp->dev) { switch (cp->dev) {
case ESO_MASTER_VOL:
/* Reload from mixer after hardware volume control use. */
if (sc->sc_gain[cp->dev][ESO_LEFT] == (uint8_t)~0)
eso_reload_master_vol(sc);
/* FALLTHROUGH */
case ESO_DAC_PLAY_VOL: case ESO_DAC_PLAY_VOL:
case ESO_MIC_PLAY_VOL: case ESO_MIC_PLAY_VOL:
case ESO_LINE_PLAY_VOL: case ESO_LINE_PLAY_VOL:
case ESO_SYNTH_PLAY_VOL: case ESO_SYNTH_PLAY_VOL:
case ESO_CD_PLAY_VOL: case ESO_CD_PLAY_VOL:
case ESO_AUXB_PLAY_VOL: case ESO_AUXB_PLAY_VOL:
case ESO_MASTER_VOL:
case ESO_RECORD_VOL: case ESO_RECORD_VOL:
case ESO_DAC_REC_VOL: case ESO_DAC_REC_VOL:
case ESO_MIC_REC_VOL: case ESO_MIC_REC_VOL:
@ -1135,6 +1160,9 @@ eso_get_port(hdl, cp)
break; break;
case ESO_MASTER_MUTE: case ESO_MASTER_MUTE:
/* Reload from mixer after hardware volume control use. */
if (sc->sc_gain[cp->dev][ESO_LEFT] == (uint8_t)~0)
eso_reload_master_vol(sc);
cp->un.ord = sc->sc_mvmute; cp->un.ord = sc->sc_mvmute;
break; break;
@ -1812,6 +1840,26 @@ eso_set_recsrc(sc, recsrc)
return (EINVAL); return (EINVAL);
} }
/*
* Reload Master Volume and Mute values in softc from mixer; used when
* those have previously been invalidated by use of hardware volume controls.
*/
static void
eso_reload_master_vol(sc)
struct eso_softc *sc;
{
uint8_t mv;
mv = eso_read_mixreg(sc, ESO_MIXREG_LMVM);
sc->sc_gain[ESO_MASTER_VOL][ESO_LEFT] =
(mv & ~ESO_MIXREG_LMVM_MUTE) << 2;
mv = eso_read_mixreg(sc, ESO_MIXREG_LMVM);
sc->sc_gain[ESO_MASTER_VOL][ESO_RIGHT] =
(mv & ~ESO_MIXREG_RMVM_MUTE) << 2;
/* Currently both channels are muted simultaneously; either is OK. */
sc->sc_mvmute = (mv & ESO_MIXREG_RMVM_MUTE) != 0;
}
static void static void
eso_set_gain(sc, port) eso_set_gain(sc, port)
struct eso_softc *sc; struct eso_softc *sc;

View File

@ -1,4 +1,4 @@
/* $NetBSD: esoreg.h,v 1.4 1999/12/10 16:50:52 kleink Exp $ */ /* $NetBSD: esoreg.h,v 1.5 1999/12/10 19:13:00 kleink Exp $ */
/* /*
* Copyright (c) 1999 Klaus J. Klein * Copyright (c) 1999 Klaus J. Klein
@ -142,10 +142,16 @@
#define ESO_MIXREG_SPATLVL 0x52 /* Spatializer Level */ #define ESO_MIXREG_SPATLVL 0x52 /* Spatializer Level */
#define ESO_MIXREG_LMVM 0x60 /* Left Master Volume and Mute */ #define ESO_MIXREG_LMVM 0x60 /* Left Master Volume and Mute */
#define ESO_MIXREG_LMVM_MUTE 0x40 /* Mute enable */ #define ESO_MIXREG_LMVM_MUTE 0x40 /* Mute enable */
#define ESO_MIXREG_LHVCC 0x61 /* Left Hardware Volume Control Ctr */
#define ESO_MIXREG_RMVM 0x62 /* Right Master Volume and Mute */ #define ESO_MIXREG_RMVM 0x62 /* Right Master Volume and Mute */
#define ESO_MIXREG_RMVM_MUTE 0x40 /* Mute enable */ #define ESO_MIXREG_RMVM_MUTE 0x40 /* Mute enable */
#define ESO_MIXREG_RHVCC 0x63 /* Left Hardware Volume Control Ctr */
#define ESO_MIXREG_MVCTL 0x64 /* Master Volume Control */ #define ESO_MIXREG_MVCTL 0x64 /* Master Volume Control */
#define ESO_MIXREG_MVCTL_HVIRQM 0x02 /* Hardware Volume Control intr mask */
#define ESO_MIXREG_MVCTL_MPUIRQM 0x40 /* MPU-401 interrupt unmask */ #define ESO_MIXREG_MVCTL_MPUIRQM 0x40 /* MPU-401 interrupt unmask */
#define ESO_MIXREG_MVCTL_SPLIT 0x80 /* Split xHVCC/xMVM registers */
#define ESO_MIXREG_CHVIR 0x66 /* Clear Hardware Volume IRQ */
#define ESO_MIXREG_CHVIR_CHVIR 0x00 /* Any value will do */
#define ESO_MIXREG_RVR_MIC 0x68 /* Record mixer: Microphone */ #define ESO_MIXREG_RVR_MIC 0x68 /* Record mixer: Microphone */
#define ESO_MIXREG_RVR_A2 0x69 /* Record mixer: Audio 2 */ #define ESO_MIXREG_RVR_A2 0x69 /* Record mixer: Audio 2 */
#define ESO_MIXREG_RVR_CD 0x6a /* Record mixer: AuxA/CD */ #define ESO_MIXREG_RVR_CD 0x6a /* Record mixer: AuxA/CD */