NetBSD Problem Report #20711

Received: (qmail 2608 invoked by uid 605); 15 Mar 2003 10:58:09 -0000
Message-Id: <200303151016.h2FAGn001526@Yorick.>
Date: Sat, 15 Mar 2003 12:16:49 +0200 (SAST)
From: yh@metroweb.co.za
Sender: gnats-bugs-owner@netbsd.org
Reply-To: yh@metroweb.co.za
To: gnats-bugs@gnats.netbsd.org
Subject: emuxki rear channel and tone control support
X-Send-Pr-Version: 3.95

>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 10:59:01 +0000 2003
>Closed-Date:    
>Last-Modified:  Tue Aug 24 12:52:00 +0000 2004
>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:

From: Yorick Hardy <yh@metroweb.co.za>
To: gnats-bugs@netbsd.org
Cc:  
Subject: Re: kern/20711
Date: Thu, 27 Mar 2003 20:50:48 +0200

 Fix a conditional compile for tone.

 -- 
 Yorick Hardy


 --- sys/dev/pci/emuxki.c.orig	Thu Mar 27 10:59:55 2003
 +++ sys/dev/pci/emuxki.c	Thu Mar 27 10:59:59 2003
 @@ -354,10 +354,12 @@
  	sc->dspmixer.rearvol_right = 128;
  	sc->dspmixer.rearac97_left = 128;
  	sc->dspmixer.rearac97_right = 128;
 +#ifdef EMUXKI_EFX_TONE
  	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;
 +#endif /* EMUXKI_EFX_TONE */

  	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
  		EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |

From: Yorick Hardy <yh@metroweb.co.za>
To: gnats-bugs@netbsd.org
Cc: yh@metroweb.co.za
Subject: Re: kern/20711
Date: Fri, 28 Mar 2003 17:01:15 +0200

 Use the MACMV instruction to implement the filter, since it
 fits (was designed for ?) this purpose very well.

 -- 
 Yorick Hardy

 --- sys/dev/pci/emuxki.c.orig	Fri Mar 28 16:16:42 2003
 +++ sys/dev/pci/emuxki.c	Fri Mar 28 16:17:41 2003
 @@ -2675,11 +2675,11 @@
  			     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);
 +	int x[2], y[2], i;
 +	int zero = EMU_DSP_CST(0);
 +	int acc = EMU_DSP_HWR_ACC;

 -	for (i = 0; i < 3; i++) {
 +	for (i = 0; i < 2; i++) {
  		x[i] = emuxki_allocate_gpr(sc);
  		if (x[i] < 0) return;
  		x[i] = EMU_DSP_GPR(x[i]);
 @@ -2688,21 +2688,17 @@
  		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);
 +        /* acc  = b2 * x[0]; */
 +	emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACS,    zero, zero, x[0],    b2);
 +        /* acc += b1 * x[1] + b0 * x[2] + a2 * y[0] + a1 * y[1]; */
 +	emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACMV,   x[0], x[1], x[1],    b1);
 +	emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACMV,   x[1],   in,   in,    b0);
 +	emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACMV,   zero, zero, y[0],    a2);
 +	emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACMV,   y[0], y[1], y[1],    a1);
 +	/* y[2] = acc >> 31; y[2] *= scale; */
 +	emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACS,    y[1],  acc, zero,  zero);
 +	emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACINTS, y[1], zero, y[1], scale);
 +	emuxki_dsp_addop(sc, pc, EMU_DSP_OP_MACS,     out, y[1], zero,  zero);
  }

  static void emuxki_dsp_fx_rf_gpr(struct emuxki_softc *sc, u_int16_t *pc,

From: Yorick Hardy <yha@na.rau.ac.za>
To: gnats-bugs@NetBSD.org
Cc:  
Subject: Re: kern/20711
Date: Tue, 24 Aug 2004 13:57:58 +0200

 Updated patch for NetBSD 2.0_BETA, fixed warnings.

 -- 
 Yorick Hardy                                      

 --- sys/dev/pci/files.pci.orig	2004-07-14 11:07:05.000000000 +0200
 +++ sys/dev/pci/files.pci	2004-08-07 16:51:17.000000000 +0200
 @@ -17,6 +17,8 @@

  defflag	opt_pcn.h	PCN_NO_PROM

 +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
 --- sys/dev/pci/emuxki.c.orig	2004-04-05 22:29:50.000000000 +0200
 +++ sys/dev/pci/emuxki.c	2004-08-07 18:50:08.000000000 +0200
 @@ -75,8 +75,14 @@
  #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

  /* autoconf goo */
  static int  emuxki_match(struct device *, struct cfdata *, void *);
 @@ -174,6 +180,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.
   */
 @@ -229,6 +247,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
   */
 @@ -326,6 +348,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);
 @@ -352,13 +384,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
 @@ -593,12 +640,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++)
 @@ -607,28 +678,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),
 @@ -1995,25 +2147,273 @@
  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) {
 +			sc->dspmixer.rearvol_left = mctl->un.value.level[0];
 +			sc->dspmixer.rearvol_right = mctl->un.value.level[1];
 +		}
 +		else {
 +			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) {
 +			sc->dspmixer.rearac97_left = mctl->un.value.level[0];
 +			sc->dspmixer.rearac97_right = mctl->un.value.level[1];
 +		}
 +		else {
 +			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;
 +		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;
 +		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 *
 @@ -2205,6 +2605,7 @@
  	struct emuxki_softc *sc = arg;

  	sc->codecif = codecif;
 +
  	return (0);
  }

 @@ -2246,3 +2647,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	2004-08-07 16:43:44.000000000 +0200
 +++ sys/dev/pci/emuxkitone.h	2004-08-07 16:43:44.000000000 +0200
 @@ -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	2003-05-03 20:11:34.000000000 +0200
 +++ sys/dev/pci/emuxkivar.h	2004-08-07 16:43:45.000000000 +0200
 @@ -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;

 @@ -246,6 +271,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

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.