Subject: kern/20711: emuxki rear channel and tone control support
To: None <gnats-bugs@gnats.netbsd.org>
From: None <yh@metroweb.co.za>
List: netbsd-bugs
Date: 03/15/2003 12:16:49
>Number: 20711
>Category: kern
>Synopsis: emuxki rear channel and tone control support
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Mar 15 02:59:01 PST 2003
>Closed-Date:
>Last-Modified:
>Originator: Yorick Hardy
>Release: NetBSD 1.6_STABLE
>Organization:
Yorick Hardy
>Environment:
System: NetBSD Yorick 1.6_STABLE NetBSD 1.6_STABLE (YORICK) #276: Mon Mar 3 23:32:23 SAST 2003 yorick@Yorick:/usr/src/sys/arch/i386/compile/YORICK i386
Architecture: i386
Machine: i386
>Description:
The patch below adds rear output (duplicates the front output) as well
as tone control enabled by
options EMUXKI_EFX_TONE
in the kernel configuration file.
>How-To-Repeat:
Not applicable.
>Fix:
Patch against revision 1.20 of emuxki.c, 1.4 of emuxkivar.h and
1.173.2.2 of files.pci in current. The patch creates the file
emuxkitone.h in sys/dev/pci, I guess the NetBSD style copyright
should be added to this file ?
--- sys/dev/pci/emuxki.c.orig Sat Mar 15 11:53:36 2003
+++ sys/dev/pci/emuxki.c Sat Mar 15 11:54:25 2003
@@ -76,9 +76,15 @@
#include <dev/ic/ac97reg.h>
#include <dev/ic/ac97var.h>
+#include "opt_emuxki.h"
+
#include <dev/pci/emuxkireg.h>
#include <dev/pci/emuxkivar.h>
+#ifdef EMUXKI_EFX_TONE
+#include <dev/pci/emuxkitone.h>
+#endif
+
/* autconf goo */
static int emuxki_match(struct device *, struct cfdata *, void *);
static void emuxki_attach(struct device *, struct device *, void *);
@@ -175,6 +181,18 @@
static void emuxki_ac97_reset(void *);
static enum ac97_host_flags emuxki_ac97_flags(void *);
+/* for the moment the following functions are only used for tone control */
+#ifdef EMUXKI_EFX_TONE
+
+/* Biquad recursive filter for the DSP */
+static void emuxki_dsp_fx_rf(struct emuxki_softc *, u_int16_t *,
+ u_int16_t, u_int16_t, u_int16_t, u_int16_t,
+ u_int16_t, u_int16_t, u_int16_t, u_int16_t);
+static void emuxki_dsp_fx_rf_gpr(struct emuxki_softc *, u_int16_t *,
+ u_int16_t, u_int16_t, int [6]);
+
+#endif /* EMUXKI_EFX_TONE */
+
/*
* Autoconfig goo.
*/
@@ -230,6 +248,10 @@
57344, 65536
};
+static int emuxki_allocate_gpr(struct emuxki_softc *sc);
+static void emuxki_dsp_addop(struct emuxki_softc *, u_int16_t *, u_int8_t,
+ u_int16_t, u_int16_t, u_int16_t, u_int16_t);
+
/*
* Dma memory mgmt
*/
@@ -327,6 +349,16 @@
{
int err;
+ sc->nextgpr = 0;
+ sc->dspmixer.rearvol_left = 128;
+ sc->dspmixer.rearvol_right = 128;
+ sc->dspmixer.rearac97_left = 128;
+ sc->dspmixer.rearac97_right = 128;
+ sc->dspmixer.front_bass = emuxki_tone_table_entries/2;
+ sc->dspmixer.front_treble = emuxki_tone_table_entries/2;
+ sc->dspmixer.rear_bass = emuxki_tone_table_entries/2;
+ sc->dspmixer.rear_treble = emuxki_tone_table_entries/2;
+
bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
EMU_HCFG_MUTEBUTTONENABLE);
@@ -353,13 +385,28 @@
static int
emuxki_ac97_init(struct emuxki_softc *sc)
{
+ int i, r;
+ mixer_devinfo_t mdi;
+
sc->hostif.arg = sc;
sc->hostif.attach = emuxki_ac97_attach;
sc->hostif.read = emuxki_ac97_read;
sc->hostif.write = emuxki_ac97_write;
sc->hostif.reset = emuxki_ac97_reset;
sc->hostif.flags = emuxki_ac97_flags;
- return (ac97_attach(&(sc->hostif)));
+ r = ac97_attach(&(sc->hostif));
+
+ if (r) return r;
+
+ r = 0;
+ for (i = 0; r == 0; i++) {
+ mdi.index = i;
+ r = sc->codecif->vtbl->query_devinfo(sc->codecif, &mdi);
+ }
+ /* i-1 failed, so the last device was at i-2 */
+ sc->dspmixer.ac97_lastdevice = i - 2;
+
+ return 0;
}
static int
@@ -592,12 +639,36 @@
(*pc)++;
}
+static int emuxki_allocate_gpr(struct emuxki_softc *sc)
+{
+ if (sc->nextgpr > 255) return -1;
+ return (sc->nextgpr)++;
+}
+
/* init and shutdown */
static void
emuxki_initfx(struct emuxki_softc *sc)
{
u_int16_t pc;
+ int templ, tempr;
+
+ templ = emuxki_allocate_gpr(sc);
+ tempr = emuxki_allocate_gpr(sc);
+
+ /* Allocate DSP mixer registers */
+ sc->dspmixer.gpr_rl = emuxki_allocate_gpr(sc);
+ sc->dspmixer.gpr_rr = emuxki_allocate_gpr(sc);
+ sc->dspmixer.gpr_rac97l = emuxki_allocate_gpr(sc);
+ sc->dspmixer.gpr_rac97r = emuxki_allocate_gpr(sc);
+#ifdef EMUXKI_EFX_TONE
+ for (pc = 0; pc < 6; pc++) {
+ sc->dspmixer.gpr_fbass[pc] = emuxki_allocate_gpr(sc);
+ sc->dspmixer.gpr_ftreble[pc] = emuxki_allocate_gpr(sc);
+ sc->dspmixer.gpr_rbass[pc] = emuxki_allocate_gpr(sc);
+ sc->dspmixer.gpr_rtreble[pc] = emuxki_allocate_gpr(sc);
+ }
+#endif /* EMUXKI_EFX_TONE */
/* Set all GPRs to 0 */
for (pc = 0; pc < 256; pc++)
@@ -606,28 +677,109 @@
emuxki_write(sc, 0, EMU_TANKMEMDATAREGBASE + pc, 0);
emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
}
+
+ /* initialize some GPRs for DSP mixer settings */
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rl),
+ sc->dspmixer.rearvol_left << 23);
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rr),
+ sc->dspmixer.rearvol_right << 23);
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rac97l),
+ sc->dspmixer.rearac97_left << 23);
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rac97r),
+ sc->dspmixer.rearac97_right << 23);
+#ifdef EMUXKI_EFX_TONE
+ for (pc = 0; pc < 6; pc++) {
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_fbass[pc]),
+ emuxki_bass_table[sc->dspmixer.front_bass][pc]);
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_ftreble[pc]),
+ emuxki_treble_table[sc->dspmixer.front_treble][pc]);
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rbass[pc]),
+ emuxki_bass_table[sc->dspmixer.rear_bass][pc]);
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rtreble[pc]),
+ emuxki_treble_table[sc->dspmixer.rear_treble][pc]);
+ }
+#endif /* EMUXKI_EFX_TONE */
+
pc = 0;
/* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
- EMU_DSP_OUTL(EMU_DSP_OUT_AC97),
+ EMU_DSP_GPR(templ),
EMU_DSP_CST(0),
EMU_DSP_FX(0), EMU_DSP_CST(4));
emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
- EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
+ EMU_DSP_GPR(tempr),
EMU_DSP_CST(0),
EMU_DSP_FX(1), EMU_DSP_CST(4));
- /* Rear channel OUT (l/r) = FX[2/3] * 4 */
-#if 0
- emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
- EMU_DSP_OUTL(EMU_DSP_OUT_RCHAN),
+#ifdef EMUXKI_EFX_TONE
+ /* Use the DSP for bass and treble effects on front outputs */
+ emuxki_dsp_fx_rf_gpr(sc, &pc, EMU_DSP_GPR(templ), EMU_DSP_GPR(templ),
+ sc->dspmixer.gpr_fbass);
+ emuxki_dsp_fx_rf_gpr(sc, &pc, EMU_DSP_GPR(templ), EMU_DSP_GPR(templ),
+ sc->dspmixer.gpr_ftreble);
+ emuxki_dsp_fx_rf_gpr(sc, &pc, EMU_DSP_GPR(tempr), EMU_DSP_GPR(tempr),
+ sc->dspmixer.gpr_fbass);
+ emuxki_dsp_fx_rf_gpr(sc, &pc, EMU_DSP_GPR(tempr), EMU_DSP_GPR(tempr),
+ sc->dspmixer.gpr_ftreble);
+#endif /* EMUXKI_EFX_TONE */
+
+ /* Output front (AC97) channels */
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACMV,
EMU_DSP_OUTL(EMU_DSP_OUT_AC97),
+ EMU_DSP_GPR(templ),
+ EMU_DSP_CST(0),
+ EMU_DSP_CST(0));
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACMV,
+ EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
+ EMU_DSP_GPR(tempr),
+ EMU_DSP_CST(0),
+ EMU_DSP_CST(0));
+
+ /*
+ * Rear channel OUT (l/r) = AC97 In (l/r) + FX[2/3] * 4 (for 4 channel)
+ * Rear channel OUT (l/r) = AC97 In (l/r) + FX[0/1] * 4 (for 2 channel)
+ * Begin with 2 channel, 4 channel should be set up on demand
+ * (except it is not implemented yet)
+ */
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+ EMU_DSP_GPR(templ), EMU_DSP_CST(0),
EMU_DSP_FX(0), EMU_DSP_CST(4));
emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
- EMU_DSP_OUTR(EMU_DSP_OUT_RCHAN),
- EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
+ EMU_DSP_GPR(tempr), EMU_DSP_CST(0),
EMU_DSP_FX(1), EMU_DSP_CST(4));
-#endif
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACS,
+ EMU_DSP_GPR(templ), EMU_DSP_GPR(templ),
+ EMU_DSP_INL(EMU_DSP_IN_AC97),
+ EMU_DSP_GPR(sc->dspmixer.gpr_rac97l));
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACS,
+ EMU_DSP_GPR(tempr), EMU_DSP_GPR(tempr),
+ EMU_DSP_INR(EMU_DSP_IN_AC97),
+ EMU_DSP_GPR(sc->dspmixer.gpr_rac97r));
+
+#ifdef EMUXKI_EFX_TONE
+ /* Use the DSP for bass and treble effects on rear outputs */
+ emuxki_dsp_fx_rf_gpr(sc, &pc, EMU_DSP_GPR(templ), EMU_DSP_GPR(templ),
+ sc->dspmixer.gpr_rbass);
+ emuxki_dsp_fx_rf_gpr(sc, &pc, EMU_DSP_GPR(templ), EMU_DSP_GPR(templ),
+ sc->dspmixer.gpr_rtreble);
+ emuxki_dsp_fx_rf_gpr(sc, &pc, EMU_DSP_GPR(tempr), EMU_DSP_GPR(tempr),
+ sc->dspmixer.gpr_rbass);
+ emuxki_dsp_fx_rf_gpr(sc, &pc, EMU_DSP_GPR(tempr), EMU_DSP_GPR(tempr),
+ sc->dspmixer.gpr_rtreble);
+#endif /* EMUXKI_EFX_TONE */
+
+ /* Rear channel volume control */
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACS,
+ EMU_DSP_OUTL(EMU_DSP_OUT_RCHAN),
+ EMU_DSP_CST(0),
+ EMU_DSP_GPR(templ),
+ EMU_DSP_GPR(sc->dspmixer.gpr_rl));
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACS,
+ EMU_DSP_OUTR(EMU_DSP_OUT_RCHAN),
+ EMU_DSP_CST(0),
+ EMU_DSP_GPR(tempr),
+ EMU_DSP_GPR(sc->dspmixer.gpr_rr));
+
/* ADC recording (l/r) = AC97 In (l/r) */
emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
EMU_DSP_OUTL(EMU_DSP_OUT_ADC),
@@ -1980,25 +2132,289 @@
static int
emuxki_set_port(void *addr, mixer_ctrl_t *mctl)
{
+ int r, n, s;
struct emuxki_softc *sc = addr;
+ r = 0;
+ n = mctl->un.value.num_channels;
+ if (mctl->dev == EMUXKI_DSPMIXER_REAR_DEV(sc->dspmixer)) {
+ if (n > 2 || n < 0) return EINVAL;
+ if (n == 2) {
+ if (mctl->un.value.level[0] > 255)
+ mctl->un.value.level[0] = 255;
+ if (mctl->un.value.level[1] > 255)
+ mctl->un.value.level[1] = 255;
+ sc->dspmixer.rearvol_left = mctl->un.value.level[0];
+ sc->dspmixer.rearvol_right = mctl->un.value.level[1];
+ }
+ else {
+ if (mctl->un.value.level[0] > 255)
+ mctl->un.value.level[0] = 255;
+ sc->dspmixer.rearvol_left = mctl->un.value.level[0];
+ sc->dspmixer.rearvol_right = mctl->un.value.level[0];
+ }
+ s = splaudio();
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rl),
+ sc->dspmixer.rearvol_left << 23);
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rr),
+ sc->dspmixer.rearvol_right << 23);
+ splx(s);
+ return 0;
+ }
+
+ if (mctl->dev == EMUXKI_DSPMIXER_REAR_AC97_DEV(sc->dspmixer)) {
+ if (n > 2 || n < 0) return EINVAL;
+ if (n == 2) {
+ if (mctl->un.value.level[0] > 255)
+ mctl->un.value.level[0] = 255;
+ if (mctl->un.value.level[1] > 255)
+ mctl->un.value.level[1] = 255;
+ sc->dspmixer.rearac97_left = mctl->un.value.level[0];
+ sc->dspmixer.rearac97_right = mctl->un.value.level[1];
+ }
+ else {
+ if (mctl->un.value.level[0] > 255)
+ mctl->un.value.level[0] = 255;
+ sc->dspmixer.rearac97_left = mctl->un.value.level[0];
+ sc->dspmixer.rearac97_right = mctl->un.value.level[0];
+ }
+ s = splaudio();
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rac97l),
+ sc->dspmixer.rearac97_left << 23);
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rac97r),
+ sc->dspmixer.rearac97_right << 23);
+ splx(s);
+ return 0;
+ }
+
+#ifdef EMUXKI_EFX_TONE
+ if (mctl->dev == EMUXKI_DSPMIXER_FRONT_BASS_DEV(sc->dspmixer)) {
+ if (n != 1) return EINVAL;
+ if (mctl->un.value.level[0] > 255)
+ mctl->un.value.level[0] = 255;
+ sc->dspmixer.front_bass =
+ (int)(mctl->un.value.level[0]
+ *(emuxki_tone_table_entries - 1))/255;
+ if (sc->dspmixer.front_bass > emuxki_tone_table_entries - 1)
+ sc->dspmixer.front_bass = emuxki_tone_table_entries - 1;
+ if (sc->dspmixer.front_bass < 0)
+ sc->dspmixer.front_bass = 0;
+ n = sc->dspmixer.front_bass;
+ s = splaudio();
+ for (r = 0; r < 6; r++)
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_fbass[r]),
+ emuxki_bass_table[n][r]);
+ splx(s);
+ return 0;
+ }
+
+ if (mctl->dev == EMUXKI_DSPMIXER_FRONT_TREBLE_DEV(sc->dspmixer)) {
+ if (n != 1) return EINVAL;
+ sc->dspmixer.front_treble =
+ (int)(mctl->un.value.level[0]
+ *(emuxki_tone_table_entries - 1))/255;
+ if (sc->dspmixer.front_treble > emuxki_tone_table_entries - 1)
+ sc->dspmixer.front_treble = emuxki_tone_table_entries - 1;
+ if (sc->dspmixer.front_treble < 0)
+ sc->dspmixer.front_treble = 0;
+ n = sc->dspmixer.front_treble;
+ s = splaudio();
+ for (r = 0; r < 6; r++)
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_ftreble[r]),
+ emuxki_treble_table[n][r]);
+ splx(s);
+ return 0;
+ }
+
+ if (mctl->dev == EMUXKI_DSPMIXER_REAR_BASS_DEV(sc->dspmixer)) {
+ if (n != 1) return EINVAL;
+ if (mctl->un.value.level[0] > 255)
+ mctl->un.value.level[0] = 255;
+ sc->dspmixer.rear_bass =
+ (int)(mctl->un.value.level[0]
+ *(emuxki_tone_table_entries - 1))/255;
+ if (sc->dspmixer.rear_bass > emuxki_tone_table_entries - 1)
+ sc->dspmixer.rear_bass = emuxki_tone_table_entries - 1;
+ if (sc->dspmixer.rear_bass < 0)
+ sc->dspmixer.rear_bass = 0;
+ n = sc->dspmixer.rear_bass;
+ s = splaudio();
+ for (r = 0; r < 6; r++)
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rbass[r]),
+ emuxki_bass_table[n][r]);
+ splx(s);
+ return 0;
+ }
+
+ if (mctl->dev == EMUXKI_DSPMIXER_REAR_TREBLE_DEV(sc->dspmixer)) {
+ if (n != 1) return EINVAL;
+ sc->dspmixer.rear_treble =
+ (int)(mctl->un.value.level[0]
+ *(emuxki_tone_table_entries - 1))/255;
+ if (sc->dspmixer.rear_treble > emuxki_tone_table_entries - 1)
+ sc->dspmixer.rear_treble = emuxki_tone_table_entries - 1;
+ if (sc->dspmixer.rear_treble < 0)
+ sc->dspmixer.rear_treble = 0;
+ n = sc->dspmixer.rear_treble;
+ s = splaudio();
+ for (r = 0; r < 6; r++)
+ emuxki_write(sc, 0, EMU_DSP_GPR(sc->dspmixer.gpr_rtreble[r]),
+ emuxki_treble_table[n][r]);
+ splx(s);
+ return 0;
+ }
+#endif /* EMUXKI_EFX_TONE */
+
return sc->codecif->vtbl->mixer_set_port(sc->codecif, mctl);
}
static int
emuxki_get_port(void *addr, mixer_ctrl_t *mctl)
{
+ int n;
struct emuxki_softc *sc = addr;
+ n = mctl->un.value.num_channels;
+ if (mctl->dev == EMUXKI_DSPMIXER_REAR_DEV(sc->dspmixer)) {
+ if (n != 2) return EINVAL;
+ mctl->un.value.level[0] = sc->dspmixer.rearvol_left;
+ mctl->un.value.level[1] = sc->dspmixer.rearvol_right;
+ return 0;
+ }
+
+ if (mctl->dev == EMUXKI_DSPMIXER_REAR_AC97_DEV(sc->dspmixer)) {
+ if (n != 2) return EINVAL;
+ mctl->un.value.level[0] = sc->dspmixer.rearac97_left;
+ mctl->un.value.level[1] = sc->dspmixer.rearac97_right;
+ return 0;
+ }
+
+#ifdef EMUXKI_EFX_TONE
+ if (mctl->dev == EMUXKI_DSPMIXER_FRONT_BASS_DEV(sc->dspmixer)) {
+ if (n != 1) return EINVAL;
+ mctl->un.value.level[0] = sc->dspmixer.front_bass*255
+ /(emuxki_tone_table_entries - 1);
+ return 0;
+ }
+
+ if (mctl->dev == EMUXKI_DSPMIXER_FRONT_TREBLE_DEV(sc->dspmixer)) {
+ if (n != 1) return EINVAL;
+ mctl->un.value.level[0] = sc->dspmixer.front_treble*255
+ /(emuxki_tone_table_entries - 1);
+ return 0;
+ }
+
+ if (mctl->dev == EMUXKI_DSPMIXER_REAR_BASS_DEV(sc->dspmixer)) {
+ if (n != 1) return EINVAL;
+ mctl->un.value.level[0] = sc->dspmixer.rear_bass*255
+ /(emuxki_tone_table_entries - 1);
+ return 0;
+ }
+
+ if (mctl->dev == EMUXKI_DSPMIXER_REAR_TREBLE_DEV(sc->dspmixer)) {
+ if (n != 1) return EINVAL;
+ mctl->un.value.level[0] = sc->dspmixer.rear_treble*255
+ /(emuxki_tone_table_entries - 1);
+ return 0;
+ }
+#endif /* EMUXKI_EFX_TONE */
+
return sc->codecif->vtbl->mixer_get_port(sc->codecif, mctl);
}
static int
emuxki_query_devinfo(void *addr, mixer_devinfo_t *minfo)
{
+ int r;
struct emuxki_softc *sc = addr;
- return sc->codecif->vtbl->query_devinfo(sc->codecif, minfo);
+ r = sc->codecif->vtbl->query_devinfo(sc->codecif, minfo);
+
+ if(minfo->index == EMUXKI_DSPMIXER_EFFECTS_CLASS(sc->dspmixer)) {
+ strcpy(minfo->label.name, "effects");
+ minfo->type = AUDIO_MIXER_CLASS;
+ minfo->mixer_class = EMUXKI_DSPMIXER_EFFECTS_CLASS(sc->dspmixer);
+ minfo->prev = AUDIO_MIXER_LAST;
+ minfo->next = AUDIO_MIXER_LAST;
+ r = 0;
+ }
+
+ if(minfo->index == EMUXKI_DSPMIXER_REAR_DEV(sc->dspmixer)) {
+ strcpy(minfo->label.name, "rear_volume");
+ minfo->type = AUDIO_MIXER_VALUE;
+ minfo->mixer_class = EMUXKI_DSPMIXER_EFFECTS_CLASS(sc->dspmixer);
+ minfo->prev = AUDIO_MIXER_LAST;
+ minfo->next = AUDIO_MIXER_LAST;
+ strcpy(minfo->un.v.units.name, AudioNvolume);
+ minfo->un.v.num_channels = 2;
+ minfo->un.v.delta = 0;
+ r = 0;
+ return 0;
+ }
+
+ if(minfo->index == EMUXKI_DSPMIXER_REAR_AC97_DEV(sc->dspmixer)) {
+ strcpy(minfo->label.name, "rear_ac97");
+ minfo->type = AUDIO_MIXER_VALUE;
+ minfo->mixer_class = EMUXKI_DSPMIXER_EFFECTS_CLASS(sc->dspmixer);
+ minfo->prev = AUDIO_MIXER_LAST;
+ minfo->next = AUDIO_MIXER_LAST;
+ strcpy(minfo->un.v.units.name, AudioNvolume);
+ minfo->un.v.num_channels = 2;
+ minfo->un.v.delta = 0;
+ r = 0;
+ return 0;
+ }
+#ifdef EMUXKI_EFX_TONE
+ if(minfo->index == EMUXKI_DSPMIXER_FRONT_BASS_DEV(sc->dspmixer)) {
+ strcpy(minfo->label.name, "front_bass");
+ minfo->type = AUDIO_MIXER_VALUE;
+ minfo->mixer_class = EMUXKI_DSPMIXER_EFFECTS_CLASS(sc->dspmixer);
+ minfo->prev = AUDIO_MIXER_LAST;
+ minfo->next = AUDIO_MIXER_LAST;
+ strcpy(minfo->un.v.units.name, AudioNbass);
+ minfo->un.v.num_channels = 1;
+ minfo->un.v.delta = 255/49; /* 50 entries in coeff. table */
+ r = 0;
+ }
+
+ if(minfo->index == EMUXKI_DSPMIXER_FRONT_TREBLE_DEV(sc->dspmixer)) {
+ strcpy(minfo->label.name, "front_treble");
+ minfo->type = AUDIO_MIXER_VALUE;
+ minfo->mixer_class = EMUXKI_DSPMIXER_EFFECTS_CLASS(sc->dspmixer);
+ minfo->prev = AUDIO_MIXER_LAST;
+ minfo->next = AUDIO_MIXER_LAST;
+ strcpy(minfo->un.v.units.name, AudioNtreble);
+ minfo->un.v.num_channels = 1;
+ minfo->un.v.delta = 255/49; /* 50 entries in coeff. table */
+ r = 0;
+ }
+
+ if(minfo->index == EMUXKI_DSPMIXER_REAR_BASS_DEV(sc->dspmixer)) {
+ strcpy(minfo->label.name, "rear_bass");
+ minfo->type = AUDIO_MIXER_VALUE;
+ minfo->mixer_class = EMUXKI_DSPMIXER_EFFECTS_CLASS(sc->dspmixer);
+ minfo->prev = AUDIO_MIXER_LAST;
+ minfo->next = AUDIO_MIXER_LAST;
+ strcpy(minfo->un.v.units.name, AudioNbass);
+ minfo->un.v.num_channels = 1;
+ minfo->un.v.delta = 255/49; /* 50 entries in coeff. table */
+ r = 0;
+ }
+
+ if(minfo->index == EMUXKI_DSPMIXER_REAR_TREBLE_DEV(sc->dspmixer)) {
+ strcpy(minfo->label.name, "rear_treble");
+ minfo->type = AUDIO_MIXER_VALUE;
+ minfo->mixer_class = EMUXKI_DSPMIXER_EFFECTS_CLASS(sc->dspmixer);
+ minfo->prev = AUDIO_MIXER_LAST;
+ minfo->next = AUDIO_MIXER_LAST;
+ strcpy(minfo->un.v.units.name, AudioNtreble);
+ minfo->un.v.num_channels = 1;
+ minfo->un.v.delta = 255/49; /* 50 entries in coeff. table */
+ r = 0;
+ }
+#endif /* EMUXKI_EFX_TONE */
+
+ return r;
}
static void *
@@ -2192,6 +2608,7 @@
struct emuxki_softc *sc = arg;
sc->codecif = codecif;
+
return (0);
}
@@ -2233,3 +2650,68 @@
{
return (AC97_HOST_SWAPPED_CHANNELS);
}
+
+
+/* for the moment the following functions are only used for tone control */
+#ifdef EMUXKI_EFX_TONE
+
+/*
+ * Recursive filter:
+ * sc is the device information structure
+ * pc is the counter for the instructions
+ * in and out are the source and target registers
+ * scale,a1,a2,b0,b1,b2 refer to DSP registers
+ *
+ * if y[n] denotes the output sample and x[n] the input sample,
+ * y[n]=scale*(b0*x[n]+b1*x[n-1]+b2*x[n-2]
+ * +a1*y[n-1]+a2*y[n-2])/(2^31-1)
+ * the integer coefficients a1,a2,b0,b1,b2 are in [-2^31+1,2^31-1]
+ * scale is a positive integer
+ */
+static void emuxki_dsp_fx_rf(struct emuxki_softc *sc, u_int16_t *pc,
+ u_int16_t in, u_int16_t out,
+ u_int16_t scale, u_int16_t a1, u_int16_t a2,
+ u_int16_t b0, u_int16_t b1, u_int16_t b2)
+{
+ int x[3], y[3], i;
+ static int accum = -1;
+ static int zero = EMU_DSP_CST(0);
+
+ for (i = 0; i < 3; i++) {
+ x[i] = emuxki_allocate_gpr(sc);
+ if (x[i] < 0) return;
+ x[i] = EMU_DSP_GPR(x[i]);
+ y[i] = emuxki_allocate_gpr(sc);
+ if (y[i] < 0) return;
+ y[i] = EMU_DSP_GPR(y[i]);
+ }
+
+ if(accum < 0)
+ accum = EMU_DSP_GPR(emuxki_allocate_gpr(sc));
+
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_ACC3, x[0], x[1], zero, zero);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_ACC3, x[1], x[2], zero, zero);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_ACC3, x[2], in, zero, zero);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_ACC3, y[0], y[1], zero, zero);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_ACC3, y[1], y[2], zero, zero);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACW, accum, zero, x[0], b2);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACW, accum, accum, x[1], b1);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACW, accum, accum, x[2], b0);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACW, accum, accum, y[0], a2);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACW, y[2], accum, y[1], a1);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACINTS, y[2], zero, y[2], scale);
+ emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACS, out, y[2], zero, zero);
+}
+
+static void emuxki_dsp_fx_rf_gpr(struct emuxki_softc *sc, u_int16_t *pc,
+ u_int16_t in, u_int16_t out, int c[6])
+{
+ emuxki_dsp_fx_rf(sc, pc, in, out, EMU_DSP_GPR(c[0]),
+ EMU_DSP_GPR(c[1]),
+ EMU_DSP_GPR(c[2]),
+ EMU_DSP_GPR(c[3]),
+ EMU_DSP_GPR(c[4]),
+ EMU_DSP_GPR(c[5]));
+}
+
+#endif /* EMUXKI_EFX_TONE */
--- sys/dev/pci/emuxkitone.h.orig Sat Mar 15 11:54:25 2003
+++ sys/dev/pci/emuxkitone.h Sat Mar 15 11:54:25 2003
@@ -0,0 +1,112 @@
+#ifndef _DEV_PCI_EMUXKITONE_H_
+#define _DEV_PCI_EMUXKITONE_H_
+
+static const int emuxki_tone_table_entries = 50;
+
+static const int32_t emuxki_bass_table[50][6]={ /* scale a1 a2 b0 b1 b2 */
+ {2, 2048782164, -976873978, 1043472717, -2049564412, 1006360836},
+ {2, 2051368443, -979393420, 1044976314, -2052111833, 1007415538},
+ {2, 2053863440, -981823939, 1046442520, -2054568940, 1008417742},
+ {2, 2056270164, -984168465, 1047873162, -2056938691, 1009368599},
+ {2, 2058591536, -986429846, 1049270034, -2059223964, 1010269207},
+ {2, 2060830399, -988610849, 1050634908, -2061427554, 1011120610},
+ {2, 2062989512, -990714164, 1051969522, -2063552176, 1011923800},
+ {2, 2065071554, -992742400, 1053275594, -2065600466, 1012679718},
+ {2, 2067079129, -994698093, 1054554815, -2067574981, 1013389248},
+ {2, 2069014760, -996583701, 1055808852, -2069478204, 1014053227},
+ {2, 2070880895, -998401610, 1057039352, -2071312540, 1014672437},
+ {2, 2072679912, -1000154134, 1058247940, -2073080322, 1015247606},
+ {2, 2074414111, -1001843516, 1059436224, -2074783813, 1015779414},
+ {2, 2076085725, -1003471930, 1060605791, -2076425201, 1016268486},
+ {2, 2077696916, -1005041483, 1061758215, -2078006610, 1016715397},
+ {2, 2079249778, -1006554214, 1062895054, -2079530093, 1017120669},
+ {2, 2080746341, -1008012101, 1064017853, -2080997638, 1017484773},
+ {2, 2082188567, -1009417056, 1065128146, -2082411172, 1017808129},
+ {2, 2083578359, -1010770931, 1066227456, -2083772554, 1018091104},
+ {2, 2084917556, -1012075519, 1067317299, -2085083586, 1018334013},
+ {2, 2086207938, -1013332554, 1068399185, -2086346009, 1018537121},
+ {2, 2087451228, -1014543713, 1069474617, -2087561506, 1018700641},
+ {2, 2088649090, -1015710618, 1070545097, -2088731703, 1018824731},
+ {2, 2089803135, -1016834839, 1071612124, -2089858173, 1018909500},
+ {2, 2090914920, -1017917892, 1072677198, -2090942433, 1018955003},
+ {2, 2091985949, -1018961243, 1073741823, -2091985949, 1018961243},
+ {2, 2093017679, -1019966309, 1074807504, -2092990138, 1018928168},
+ {2, 2094011513, -1020934459, 1075875755, -2093956365, 1018855675},
+ {2, 2094968809, -1021867016, 1076948095, -2094885949, 1018743605},
+ {2, 2095890880, -1022765258, 1078026055, -2095780162, 1018591744},
+ {2, 2096778993, -1023630419, 1079111177, -2096640232, 1018399826},
+ {2, 2097634370, -1024463691, 1080205018, -2097467341, 1018167525},
+ {2, 2098458193, -1025266224, 1081309149, -2098262630, 1017894462},
+ {2, 2099251604, -1026039130, 1082425159, -2099027199, 1017580198},
+ {2, 2100015702, -1026783481, 1083554660, -2099762107, 1017224239},
+ {2, 2100751551, -1027500314, 1084699283, -2100468376, 1016826029},
+ {2, 2101460176, -1028190626, 1085860685, -2101146987, 1016384953},
+ {2, 2102142568, -1028855382, 1087040550, -2101798887, 1015900336},
+ {2, 2102799681, -1029495514, 1088240591, -2102424987, 1015371439},
+ {2, 2103432437, -1030111918, 1089462553, -2103026164, 1014797461},
+ {2, 2104041726, -1030705460, 1090708213, -2103603261, 1014177535},
+ {2, 2104628404, -1031276977, 1091979386, -2104157088, 1013510729},
+ {2, 2105193299, -1031827273, 1093277928, -2104688425, 1012796043},
+ {2, 2105737209, -1032357127, 1094605732, -2105198020, 1012032407},
+ {2, 2106260903, -1032867287, 1095964739, -2105686593, 1011218681},
+ {2, 2106765123, -1033358476, 1097356935, -2106154834, 1010353652},
+ {2, 2107250584, -1033831392, 1098784359, -2106603407, 1009436033},
+ {2, 2107717977, -1034286706, 1100249100, -2107032946, 1008464460},
+ {2, 2108167966, -1034725065, 1101753302, -2107444061, 1007437490},
+ {2, 2108601192, -1035147096, 1103299173, -2107837338, 1006353600}
+};
+
+static const int32_t emuxki_treble_table[50][6]={ /* scale a1 a2 b0 b1 b2 */
+ {2, 1217733119, -394221846, 291277632, -71987913, 30940832},
+ {2, 1204185682, -388608968, 306573816, -82226220, 33817513},
+ {2, 1190382846, -382948002, 322711503, -93347029, 36942506},
+ {2, 1176323975, -377241386, 339737545, -105413835, 40335524},
+ {2, 1162008602, -371491640, 357701328, -118494161, 44017694},
+ {2, 1147436433, -365701370, 376654903, -132659780, 48011637},
+ {2, 1132607354, -359873262, 396653113, -147986947, 52341565},
+ {2, 1117521435, -354010079, 417753736, -164556644, 57033375},
+ {2, 1102178940, -348114662, 440017626, -182454831, 62114750},
+ {2, 1086580330, -342189921, 463508861, -201772711, 67615265},
+ {1, 2141452538, -672477675, 976589807, -445214018, 147132995},
+ {1, 2109235266, -660528909, 1028893514, -490120505, 160004281},
+ {1, 2076511026, -648539755, 1084078274, -538482150, 173916251},
+ {1, 2043282446, -636516539, 1142301289, -590529045, 188945495},
+ {1, 2009552611, -624465690, 1203727896, -646504756, 205173586},
+ {1, 1975325074, -612393735, 1268531939, -706666988, 222687357},
+ {1, 1940603868, -600307287, 1336896162, -771288277, 241579181},
+ {1, 1905393517, -588213037, 1409012611, -840656709, 261947265},
+ {1, 1869699047, -576117742, 1485083052, -915076663, 283895953},
+ {1, 1833525998, -564028217, 1565319399, -994869577, 307536043},
+ {1, 1796880433, -551951323, 1649944169, -1080374743, 332985111},
+ {1, 1759768945, -539893955, 1739190934, -1171950127, 360367849},
+ {1, 1722198670, -527863034, 1833304807, -1269973213, 389816416},
+ {1, 1684177295, -515865491, 1932542924, -1374841873, 421470793},
+ {1, 1645713061, -503908259, 2037174960, -1486975271, 455479156},
+ {1, 1606814776, -491998257, 2147483647, -1606814776, 491998257},
+ {2, 783745908, -240071191, 1131882657, -867412459, 265596909},
+ {2, 763877066, -234173747, 1193165221, -935747184, 286620466},
+ {2, 743806129, -228310201, 1257752119, -1008668462, 309162238},
+ {2, 723538653, -222483928, 1325813607, -1086446277, 333319768},
+ {2, 703080485, -216698266, 1397527898, -1169364217, 359195923},
+ {2, 682437766, -210956506, 1473081473, -1257720021, 386899112},
+ {2, 661616927, -205261893, 1552669397, -1351826123, 416543515},
+ {2, 640624690, -199617612, 1636495647, -1452010217, 448249315},
+ {2, 619468066, -194026789, 1724773450, -1558615840, 482142936},
+ {2, 598154352, -188492478, 1817725621, -1672002952, 518357280},
+ {2, 576691126, -183017658, 1915584921, -1792548542, 557031976},
+ {2, 555086245, -177605227, 2018594418, -1920647241, 598313628},
+ {2, 533347839, -172257998, 2127007857, -2056711944, 642356069},
+ {3, 340989537, -111319125, 1494060026, -1467449636, 459547079},
+ {3, 326336201, -107846610, 1574078143, -1569657417, 492917565},
+ {3, 311611157, -104422798, 1658251652, -1678079021, 528466891},
+ {3, 296820508, -101049293, 1746780787, -1793042755, 566318635},
+ {3, 281970510, -97727624, 1839874232, -1914891316, 606602079},
+ {3, 267067570, -94459240, 1937749406, -2043982250, 649452396},
+ {4, 189088676, -68434132, 1530474571, -1635516327, 521258123},
+ {4, 177846888, -66065786, 1611570060, -1744048925, 557568674},
+ {4, 166580416, -63740290, 1696782590, -1858888233, 596136429},
+ {4, 155294447, -61458475, 1786303698, -1980350614, 637081855},
+ {4, 143994247, -59221102, 1880332635, -2108765429, 680530560}
+};
+
+#endif /* _DEV_PCI_EMUXKITONE_H_ */
--- sys/dev/pci/emuxkivar.h.orig Sat Mar 15 11:53:38 2003
+++ sys/dev/pci/emuxkivar.h Sat Mar 15 11:54:25 2003
@@ -222,6 +222,31 @@
};
#endif /* Not yet */
+/* Mixer settings applied at DSP level (i.e. not AC97) */
+struct emuxki_dspmixer {
+ int ac97_lastdevice; /* append devices after the last ac97 device */
+ int rearvol_left, rearvol_right;
+ int rearac97_left, rearac97_right;
+ int gpr_rl, gpr_rr; /* GPRs which store the volume */
+ int gpr_rac97l, gpr_rac97r; /* GPRs which store the volume */
+#ifdef EMUXKI_EFX_TONE
+ int front_bass, front_treble;
+ int rear_bass, rear_treble;
+ int gpr_fbass[6], gpr_ftreble[6]; /* GPRs for filter coefficients */
+ int gpr_rbass[6], gpr_rtreble[6]; /* GPRs for filter coefficients */
+#endif /* EMUXKI_EFX_TONE */
+};
+
+#define EMUXKI_DSPMIXER_EFFECTS_CLASS(dspm) ((dspm).ac97_lastdevice+1)
+#define EMUXKI_DSPMIXER_REAR_DEV(dspm) ((dspm).ac97_lastdevice+2)
+#define EMUXKI_DSPMIXER_REAR_AC97_DEV(dspm) ((dspm).ac97_lastdevice+3)
+#ifdef EMUXKI_EFX_TONE
+#define EMUXKI_DSPMIXER_FRONT_BASS_DEV(dspm) ((dspm).ac97_lastdevice+4)
+#define EMUXKI_DSPMIXER_FRONT_TREBLE_DEV(dspm) ((dspm).ac97_lastdevice+5)
+#define EMUXKI_DSPMIXER_REAR_BASS_DEV(dspm) ((dspm).ac97_lastdevice+6)
+#define EMUXKI_DSPMIXER_REAR_TREBLE_DEV(dspm) ((dspm).ac97_lastdevice+7)
+#endif /* EMUXKI_EFX_TONE */
+
struct emuxki_softc {
struct device sc_dev;
@@ -245,6 +270,14 @@
LIST_HEAD(, emuxki_voice) voices;
/* LIST_HEAD(, emuxki_stream) streams; */
+
+ /*
+ * For allocation of GPR registers,
+ * a bit map would be more flexible for deallocation
+ */
+ u_int8_t nextgpr;
+
+ struct emuxki_dspmixer dspmixer;
u_int8_t timerstate;
#define EMU_TIMER_STATE_ENABLED 1
--- sys/dev/pci/files.pci.orig Sat Mar 15 11:53:44 2003
+++ sys/dev/pci/files.pci Sat Mar 15 11:54:25 2003
@@ -15,6 +15,8 @@
defflag opt_pciide.h PCIIDE_CMD064x_DISABLE PCIIDE_AMD756_ENABLEDMA
PCIIDE_CMD0646U_ENABLEUDMA
+defflag opt_emuxki.h EMUXKI_EFX_TONE
+
device pci {[dev = -1], [function = -1]}
attach pci at pcibus
file dev/pci/pci.c pci needs-flag
>Release-Note:
>Audit-Trail:
>Unformatted: