General mixer initialization improvements around the MONO_IN/MONO_OUT/

PreAmp register, including a new MONO_IN mixer stage bypass mixer control;
inspired by (and fixing) PR kern/18342 from Stephen Ma.
This commit is contained in:
kleink 2004-05-25 21:38:11 +00:00
parent b4f8e35755
commit d42e56f0d5
2 changed files with 118 additions and 35 deletions

View File

@ -1,7 +1,7 @@
/* $NetBSD: eso.c,v 1.33 2004/02/17 17:39:55 kleink Exp $ */
/* $NetBSD: eso.c,v 1.34 2004/05/25 21:38:11 kleink Exp $ */
/*
* Copyright (c) 1999, 2000 Klaus J. Klein
* Copyright (c) 1999, 2000, 2004 Klaus J. Klein
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: eso.c,v 1.33 2004/02/17 17:39:55 kleink Exp $");
__KERNEL_RCSID(0, "$NetBSD: eso.c,v 1.34 2004/05/25 21:38:11 kleink Exp $");
#include "mpu.h"
@ -163,8 +163,10 @@ 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 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_recsrc __P((struct eso_softc *, unsigned int));
static int eso_set_monooutsrc __P((struct eso_softc *, unsigned int));
static int eso_set_monoinbypass __P((struct eso_softc *, unsigned int));
static int eso_set_preamp __P((struct eso_softc *, unsigned int));
static void eso_write_cmd __P((struct eso_softc *, uint8_t));
static void eso_write_ctlreg __P((struct eso_softc *, uint8_t, uint8_t));
static void eso_write_mixreg __P((struct eso_softc *, uint8_t, uint8_t));
@ -284,9 +286,10 @@ eso_attach(parent, self, aux)
eso_write_mixreg(sc, ESO_MIXREG_MVCTL, mvctl);
/* Set mixer regs to something reasonable, needs work. */
sc->sc_recsrc = ESO_MIXREG_ERS_LINE;
sc->sc_monooutsrc = ESO_MIXREG_MPM_MOMUTE;
sc->sc_recmon = sc->sc_spatializer = sc->sc_mvmute = 0;
eso_set_monooutsrc(sc, ESO_MIXREG_MPM_MOMUTE);
eso_set_monoinbypass(sc, 0);
eso_set_preamp(sc, 1);
for (idx = 0; idx < ESO_NGAINDEVS; idx++) {
int v;
@ -1071,6 +1074,12 @@ eso_set_port(hdl, cp)
return (eso_set_monooutsrc(sc, cp->un.ord));
case ESO_MONOIN_BYPASS:
if (cp->type != AUDIO_MIXER_ENUM)
return (EINVAL);
return (eso_set_monoinbypass(sc, cp->un.ord));
case ESO_RECORD_MONITOR:
if (cp->type != AUDIO_MIXER_ENUM)
return (EINVAL);
@ -1095,16 +1104,7 @@ eso_set_port(hdl, cp)
if (cp->type != AUDIO_MIXER_ENUM)
return (EINVAL);
sc->sc_preamp = (cp->un.ord != 0);
tmp = eso_read_mixreg(sc, ESO_MIXREG_MPM);
tmp &= ~ESO_MIXREG_MPM_RESV0;
if (sc->sc_preamp)
tmp |= ESO_MIXREG_MPM_PREAMP;
else
tmp &= ~ESO_MIXREG_MPM_PREAMP;
eso_write_mixreg(sc, ESO_MIXREG_MPM, tmp);
break;
return (eso_set_preamp(sc, cp->un.ord));
default:
return (EINVAL);
@ -1182,6 +1182,10 @@ eso_get_port(hdl, cp)
cp->un.ord = sc->sc_monooutsrc;
break;
case ESO_MONOIN_BYPASS:
cp->un.ord = sc->sc_monoinbypass;
break;
case ESO_SPATIALIZER_ENABLE:
cp->un.ord = sc->sc_spatializer;
break;
@ -1338,6 +1342,25 @@ eso_query_devinfo(hdl, dip)
strcpy(dip->un.e.member[2].label.name, AudioNmixerout);
dip->un.e.member[2].ord = ESO_MIXREG_MPM_MOREC;
break;
case ESO_MONOIN_BYPASS:
dip->mixer_class = ESO_MONOIN_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
strcpy(dip->label.name, "bypass");
dip->type = AUDIO_MIXER_ENUM;
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 ESO_MONOIN_CLASS:
dip->mixer_class = ESO_MONOIN_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
strcpy(dip->label.name, "mono_in");
dip->type = AUDIO_MIXER_CLASS;
break;
case ESO_SPATIALIZER:
dip->mixer_class = ESO_OUTPUT_CLASS;
dip->prev = AUDIO_MIXER_LAST;
@ -1846,6 +1869,32 @@ eso_trigger_input(hdl, start, end, blksize, intr, arg, param)
return (0);
}
/*
* Mixer utility functions.
*/
static int
eso_set_recsrc(sc, recsrc)
struct eso_softc *sc;
unsigned int recsrc;
{
mixer_devinfo_t di;
int i;
di.index = ESO_RECORD_SOURCE;
if (eso_query_devinfo(sc, &di) != 0)
panic("eso_set_recsrc: eso_query_devinfo failed");
for (i = 0; i < di.un.e.num_mem; i++) {
if (recsrc == di.un.e.member[i].ord) {
eso_write_mixreg(sc, ESO_MIXREG_ERS, recsrc);
sc->sc_recsrc = recsrc;
return (0);
}
}
return (EINVAL);
}
static int
eso_set_monooutsrc(sc, monooutsrc)
struct eso_softc *sc;
@ -1874,21 +1923,52 @@ eso_set_monooutsrc(sc, monooutsrc)
}
static int
eso_set_recsrc(sc, recsrc)
eso_set_monoinbypass(sc, monoinbypass)
struct eso_softc *sc;
unsigned int recsrc;
unsigned int monoinbypass;
{
mixer_devinfo_t di;
int i;
uint8_t mpm;
di.index = ESO_RECORD_SOURCE;
di.index = ESO_MONOIN_BYPASS;
if (eso_query_devinfo(sc, &di) != 0)
panic("eso_set_recsrc: eso_query_devinfo failed");
panic("eso_set_monoinbypass: eso_query_devinfo failed");
for (i = 0; i < di.un.e.num_mem; i++) {
if (recsrc == di.un.e.member[i].ord) {
eso_write_mixreg(sc, ESO_MIXREG_ERS, recsrc);
sc->sc_recsrc = recsrc;
if (monoinbypass == di.un.e.member[i].ord) {
mpm = eso_read_mixreg(sc, ESO_MIXREG_MPM);
mpm &= ~(ESO_MIXREG_MPM_MOMASK | ESO_MIXREG_MPM_RESV0);
mpm |= (monoinbypass ? ESO_MIXREG_MPM_MIBYPASS : 0);
eso_write_mixreg(sc, ESO_MIXREG_MPM, mpm);
sc->sc_monoinbypass = monoinbypass;
return (0);
}
}
return (EINVAL);
}
static int
eso_set_preamp(sc, preamp)
struct eso_softc *sc;
unsigned int preamp;
{
mixer_devinfo_t di;
int i;
uint8_t mpm;
di.index = ESO_MIC_PREAMP;
if (eso_query_devinfo(sc, &di) != 0)
panic("eso_set_preamp: eso_query_devinfo failed");
for (i = 0; i < di.un.e.num_mem; i++) {
if (preamp == di.un.e.member[i].ord) {
mpm = eso_read_mixreg(sc, ESO_MIXREG_MPM);
mpm &= ~(ESO_MIXREG_MPM_PREAMP | ESO_MIXREG_MPM_RESV0);
mpm |= (preamp ? ESO_MIXREG_MPM_PREAMP : 0);
eso_write_mixreg(sc, ESO_MIXREG_MPM, mpm);
sc->sc_preamp = preamp;
return (0);
}
}

View File

@ -1,7 +1,7 @@
/* $NetBSD: esovar.h,v 1.4 2000/03/22 14:37:43 kleink Exp $ */
/* $NetBSD: esovar.h,v 1.5 2004/05/25 21:38:11 kleink Exp $ */
/*
* Copyright (c) 1999, 2000 Klaus J. Klein
* Copyright (c) 1999, 2000, 2004 Klaus J. Klein
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -66,17 +66,19 @@
/* Other, non-gain related mixer identifiers */
#define ESO_RECORD_SOURCE 18
#define ESO_MONOOUT_SOURCE 19
#define ESO_RECORD_MONITOR 20
#define ESO_MIC_PREAMP 21
#define ESO_SPATIALIZER_ENABLE 22
#define ESO_MASTER_MUTE 23
#define ESO_MONOIN_BYPASS 20
#define ESO_RECORD_MONITOR 21
#define ESO_MIC_PREAMP 22
#define ESO_SPATIALIZER_ENABLE 23
#define ESO_MASTER_MUTE 24
/* Classes of the above */
#define ESO_INPUT_CLASS 24
#define ESO_OUTPUT_CLASS 25
#define ESO_MICROPHONE_CLASS 26
#define ESO_MONITOR_CLASS 27
#define ESO_RECORD_CLASS 28
#define ESO_INPUT_CLASS 25
#define ESO_OUTPUT_CLASS 26
#define ESO_MICROPHONE_CLASS 27
#define ESO_MONITOR_CLASS 28
#define ESO_RECORD_CLASS 29
#define ESO_MONOIN_CLASS 30
/*
@ -136,6 +138,7 @@ struct eso_softc {
#define ESO_RIGHT 1
unsigned int sc_recsrc; /* record source selection */
unsigned int sc_monooutsrc; /* MONO_OUT source selection */
unsigned int sc_monoinbypass;/* MONO_IN bypass enable */
unsigned int sc_recmon; /* record monitor setting */
unsigned int sc_preamp; /* microphone preamp */
unsigned int sc_spatializer; /* spatializer enable */