Add support for Spatializer, 3D audio effects embedded in ES1869

and ES1879 to ess(4).

Tested on my old laptop, mobio NX.
This commit is contained in:
nakayama 2014-08-16 13:01:33 +00:00
parent 06c335e708
commit f22f501132
3 changed files with 152 additions and 16 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ess.c,v 1.81 2014/08/15 19:55:23 nakayama Exp $ */
/* $NetBSD: ess.c,v 1.82 2014/08/16 13:01:33 nakayama Exp $ */
/*
* Copyright 1997
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ess.c,v 1.81 2014/08/15 19:55:23 nakayama Exp $");
__KERNEL_RCSID(0, "$NetBSD: ess.c,v 1.82 2014/08/16 13:01:33 nakayama Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -170,7 +170,7 @@ int ess_reset(struct ess_softc *);
void ess_set_gain(struct ess_softc *, int, int);
int ess_set_in_port(struct ess_softc *, int);
int ess_set_in_ports(struct ess_softc *, int);
u_int ess_srtotc(u_int);
u_int ess_srtotc(struct ess_softc *, u_int);
u_int ess_srtofc(u_int);
u_char ess_get_dsp_status(struct ess_softc *);
u_char ess_dsp_read_ready(struct ess_softc *);
@ -994,7 +994,17 @@ essattach(struct ess_softc *sc, int enablejoy)
if (ESS_USE_AUDIO1(sc->sc_model)) {
ess_write_mix_reg(sc, ESS_MREG_ADC_SOURCE, ESS_SOURCE_MIC);
sc->in_port = ESS_SOURCE_MIC;
sc->ndevs = ESS_1788_NDEVS;
if (ESS_IS_ES18X9(sc->sc_model)) {
sc->ndevs = ESS_18X9_NDEVS;
sc->sc_spatializer = 0;
ess_set_mreg_bits(sc, ESS_MREG_MODE,
ESS_MODE_ASYNC_MODE | ESS_MODE_NEWREG);
ess_set_mreg_bits(sc, ESS_MREG_SPATIAL_CTRL,
ESS_SPATIAL_CTRL_RESET);
ess_clear_mreg_bits(sc, ESS_MREG_SPATIAL_CTRL,
ESS_SPATIAL_CTRL_ENABLE | ESS_SPATIAL_CTRL_MONO);
} else
sc->ndevs = ESS_1788_NDEVS;
} else {
/*
* Set hardware record source to use output of the record
@ -1015,6 +1025,14 @@ essattach(struct ess_softc *sc, int enablejoy)
* are set to 50% volume.
*/
for (i = 0; i < sc->ndevs; i++) {
if (ESS_IS_ES18X9(sc->sc_model)) {
switch (i) {
case ESS_SPATIALIZER:
case ESS_SPATIALIZER_ENABLE:
v = 0;
goto skip;
}
}
switch (i) {
case ESS_MIC_PLAY_VOL:
case ESS_LINE_PLAY_VOL:
@ -1031,6 +1049,7 @@ essattach(struct ess_softc *sc, int enablejoy)
v = ESS_4BIT_GAIN(AUDIO_MAX_GAIN / 2);
break;
}
skip:
sc->gain[i][ESS_LEFT] = sc->gain[i][ESS_RIGHT] = v;
ess_set_gain(sc, i, 1);
}
@ -1262,11 +1281,12 @@ ess_set_params(
else
rate = play->sample_rate;
ess_write_x_reg(sc, ESS_XCMD_SAMPLE_RATE, ess_srtotc(rate));
ess_write_x_reg(sc, ESS_XCMD_SAMPLE_RATE, ess_srtotc(sc, rate));
ess_write_x_reg(sc, ESS_XCMD_FILTER_CLOCK, ess_srtofc(rate));
if (!ESS_USE_AUDIO1(sc->sc_model)) {
ess_write_mix_reg(sc, ESS_MREG_SAMPLE_RATE, ess_srtotc(rate));
ess_write_mix_reg(sc, ESS_MREG_SAMPLE_RATE,
ess_srtotc(sc, rate));
ess_write_mix_reg(sc, ESS_MREG_FILTER_CLOCK, ess_srtofc(rate));
}
@ -1781,6 +1801,35 @@ ess_set_port(void *addr, mixer_ctrl_t *cp)
return 0;
}
if (ESS_IS_ES18X9(sc->sc_model)) {
switch (cp->dev) {
case ESS_SPATIALIZER:
if (cp->type != AUDIO_MIXER_VALUE ||
cp->un.value.num_channels != 1)
return EINVAL;
sc->gain[cp->dev][ESS_LEFT] =
sc->gain[cp->dev][ESS_RIGHT] = ESS_6BIT_GAIN(
cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
ess_set_gain(sc, cp->dev, 1);
return 0;
case ESS_SPATIALIZER_ENABLE:
if (cp->type != AUDIO_MIXER_ENUM)
return EINVAL;
sc->sc_spatializer = (cp->un.ord != 0);
if (sc->sc_spatializer)
ess_set_mreg_bits(sc, ESS_MREG_SPATIAL_CTRL,
ESS_SPATIAL_CTRL_ENABLE);
else
ess_clear_mreg_bits(sc, ESS_MREG_SPATIAL_CTRL,
ESS_SPATIAL_CTRL_ENABLE);
return 0;
}
}
if (ESS_USE_AUDIO1(sc->sc_model))
return EINVAL;
@ -1886,6 +1935,23 @@ ess_get_port(void *addr, mixer_ctrl_t *cp)
return 0;
}
if (ESS_IS_ES18X9(sc->sc_model)) {
switch (cp->dev) {
case ESS_SPATIALIZER:
if (cp->un.value.num_channels != 1)
return EINVAL;
cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
sc->gain[cp->dev][ESS_LEFT];
return 0;
case ESS_SPATIALIZER_ENABLE:
cp->un.ord = sc->sc_spatializer;
return 0;
}
}
if (ESS_USE_AUDIO1(sc->sc_model))
return EINVAL;
@ -2108,6 +2174,34 @@ ess_query_devinfo(void *addr, mixer_devinfo_t *dip)
return 0;
}
if (ESS_IS_ES18X9(sc->sc_model)) {
switch (dip->index) {
case ESS_SPATIALIZER:
dip->mixer_class = ESS_OUTPUT_CLASS;
dip->prev = AUDIO_MIXER_LAST;
dip->next = ESS_SPATIALIZER_ENABLE;
strcpy(dip->label.name, AudioNspatial);
dip->type = AUDIO_MIXER_VALUE;
dip->un.v.num_channels = 1;
strcpy(dip->un.v.units.name, "level");
return 0;
case ESS_SPATIALIZER_ENABLE:
dip->mixer_class = ESS_OUTPUT_CLASS;
dip->prev = ESS_SPATIALIZER;
dip->next = AUDIO_MIXER_LAST;
strcpy(dip->label.name, "enable");
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;
return 0;
}
}
if (ESS_USE_AUDIO1(sc->sc_model))
return ENXIO;
@ -2301,6 +2395,16 @@ ess_set_gain(struct ess_softc *sc, int port, int on)
mix = 1;
stereo = 1;
if (ESS_IS_ES18X9(sc->sc_model)) {
switch (port) {
case ESS_SPATIALIZER:
src = ESS_MREG_SPATIAL_LEVEL;
stereo = -1;
goto skip;
case ESS_SPATIALIZER_ENABLE:
return;
}
}
switch (port) {
case ESS_MASTER_VOL:
src = ESS_MREG_VOLUME_MASTER;
@ -2355,6 +2459,7 @@ ess_set_gain(struct ess_softc *sc, int port, int on)
default:
return;
}
skip:
/* 1788 doesn't have a separate recording mixer */
if (ESS_USE_AUDIO1(sc->sc_model) && mix && src > 0x62)
@ -2367,7 +2472,9 @@ ess_set_gain(struct ess_softc *sc, int port, int on)
left = right = 0;
}
if (stereo)
if (stereo == -1)
gain = ESS_SPATIAL_GAIN(left);
else if (stereo)
gain = ESS_STEREO_GAIN(left, right);
else
gain = ESS_MONO_GAIN(left);
@ -2468,15 +2575,22 @@ ess_speaker_off(struct ess_softc *sc)
* Calculate the time constant for the requested sampling rate.
*/
u_int
ess_srtotc(u_int rate)
ess_srtotc(struct ess_softc *sc, u_int rate)
{
u_int tc;
/* The following formulae are from the ESS data sheet. */
if (rate <= 22050)
tc = 128 - 397700L / rate;
else
tc = 256 - 795500L / rate;
if (ESS_IS_ES18X9(sc->sc_model)) {
if ((rate % 8000) != 0)
tc = 128 - 793800L / rate;
else
tc = 256 - 768000L / rate;
} else {
if (rate <= 22050)
tc = 128 - 397700L / rate;
else
tc = 256 - 795500L / rate;
}
return tc;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: essreg.h,v 1.16 2005/12/11 12:22:02 christos Exp $ */
/* $NetBSD: essreg.h,v 1.17 2014/08/16 13:01:33 nakayama Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
@ -33,7 +33,7 @@
*/
/*
** @(#) $RCSfile: essreg.h,v $ $Revision: 1.16 $ (SHARK) $Date: 2005/12/11 12:22:02 $
** @(#) $RCSfile: essreg.h,v $ $Revision: 1.17 $ (SHARK) $Date: 2014/08/16 13:01:33 $
**
**++
**
@ -176,14 +176,17 @@
#define ESS_DRQ2_VALID(chan) ((chan) == 0 || (chan) == 1 || (chan) == 3 || (chan) == 5)
#define ESS_USE_AUDIO1(model) ((model) <= ESS_1879)
#define ESS_IS_ES18X9(model) (((model) == ESS_1869) || ((model) == ESS_1879))
/*
* Macros to manipulate gain values
*/
#define ESS_6BIT_GAIN(x) ((x) & 0xfc)
#define ESS_4BIT_GAIN(x) ((x) & 0xf0)
#define ESS_3BIT_GAIN(x) (((x) & 0xe0) >> 1)
#define ESS_STEREO_GAIN(l, r) ((l) | ((r) >> 4))
#define ESS_MONO_GAIN(x) ((x) >> 4)
#define ESS_SPATIAL_GAIN(x) ((x) >> 2)
#ifdef ESS_AMODE_LOW
/*
@ -268,11 +271,23 @@
#define ESS_MREG_VOLUME_AUXB 0x3A
#define ESS_MREG_VOLUME_PCSPKR 0x3C
#define ESS_MREG_VOLUME_LINE 0x3E
#define ESS_MREG_SPATIAL_CTRL 0x50
#define ESS_SPATIAL_CTRL_MONO 0x02
#define ESS_SPATIAL_CTRL_RESET 0x04
#define ESS_SPATIAL_CTRL_ENABLE 0x08
#define ESS_MREG_SPATIAL_LEVEL 0x52
#define ESS_MREG_VOLUME_LEFT 0x60
#define ESS_MREG_VOLUME_RIGHT 0x62
#define ESS_VOLUME_MUTE 0x40
#define ESS_MREG_VOLUME_CTRL 0x64
#define ESS_MREG_SAMPLE_RATE 0x70 /* sample rate for Audio2 channel */
#define ESS_MREG_MODE 0x71 /* mode for Audio2 channel */
#define ESS_MODE_FM_MIX 0x01
#define ESS_MODE_ASYNC_MODE 0x02
#define ESS_MODE_SCF1_BYPASS 0x04
#define ESS_MODE_SCF2_BYPASS 0x08
#define ESS_MODE_4X_MODE 0x10
#define ESS_MODE_NEWREG 0x20
#define ESS_MREG_FILTER_CLOCK 0x72 /* filter clock for Audio2 channel */
#define ESS_MREG_XFER_COUNTLO 0x74 /* low-byte of DMA transfer size */
#define ESS_MREG_XFER_COUNTHI 0x76 /* high-byte of DMA transfer size */

View File

@ -1,4 +1,4 @@
/* $NetBSD: essvar.h,v 1.26 2011/11/23 23:07:32 jmcneill Exp $ */
/* $NetBSD: essvar.h,v 1.27 2014/08/16 13:01:33 nakayama Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
@ -33,7 +33,7 @@
*/
/*
** @(#) $RCSfile: essvar.h,v $ $Revision: 1.26 $ (SHARK) $Date: 2011/11/23 23:07:32 $
** @(#) $RCSfile: essvar.h,v $ $Revision: 1.27 $ (SHARK) $Date: 2014/08/16 13:01:33 $
**
**++
**
@ -86,6 +86,11 @@
#define ESS_1788_NDEVS 15
#define ESS_SPATIALIZER 15
#define ESS_SPATIALIZER_ENABLE 16
#define ESS_18X9_NDEVS 17
#define ESS_DAC_REC_VOL 15
#define ESS_MIC_REC_VOL 16
#define ESS_LINE_REC_VOL 17
@ -166,6 +171,8 @@ struct ess_softc
u_int sc_version; /* Legacy ES688/ES1688 ID */
u_int sc_spatializer; /* spatializer enable */
/* game port on es1888 */
bus_space_tag_t sc_joy_iot;
bus_space_handle_t sc_joy_ioh;