diff options
| author | nakayama <nakayama@NetBSD.org> | 2014-08-16 13:01:33 +0000 |
|---|---|---|
| committer | nakayama <nakayama@NetBSD.org> | 2014-08-16 13:01:33 +0000 |
| commit | ed053ac5b423cb2e14cd2cb7248d1cdccbe9585d (patch) | |
| tree | edb6b1d2b459dde714c1f56a2b586f33fe7b75c7 /sys/dev/isa | |
| parent | 845e72816434df1262286a1f5e3bf35b24d57e07 (diff) | |
Add support for Spatializer, 3D audio effects embedded in ES1869
and ES1879 to ess(4).
Tested on my old laptop, mobio NX.
Diffstat (limited to 'sys/dev/isa')
| -rw-r--r-- | sys/dev/isa/ess.c | 138 | ||||
| -rw-r--r-- | sys/dev/isa/essreg.h | 19 | ||||
| -rw-r--r-- | sys/dev/isa/essvar.h | 11 |
3 files changed, 152 insertions, 16 deletions
diff --git a/sys/dev/isa/ess.c b/sys/dev/isa/ess.c index 3e4816e571b..e242edc5094 100644 --- a/sys/dev/isa/ess.c +++ b/sys/dev/isa/ess.c @@ -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; } diff --git a/sys/dev/isa/essreg.h b/sys/dev/isa/essreg.h index 878ed3a22a7..32e57e085c3 100644 --- a/sys/dev/isa/essreg.h +++ b/sys/dev/isa/essreg.h @@ -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 */ diff --git a/sys/dev/isa/essvar.h b/sys/dev/isa/essvar.h index f5917433bc5..5b1a02a08c4 100644 --- a/sys/dev/isa/essvar.h +++ b/sys/dev/isa/essvar.h @@ -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; |
