Audigy [ was Re: ... Terratec EWS88MT ... ]

David O'Brien obrien at FreeBSD.org
Sun Apr 20 18:35:02 PDT 2003


On Sun, Apr 20, 2003 at 05:17:12PM -0700, Orion Hodson wrote:
> /-- "David O'Brien" wrote:
> | On Fri, Feb 21, 2003 at 02:21:42PM -0800, Orion Hodson wrote:
> | > The project has had two drivers submitted for Audigy support in the
> | > past couple of weeks.  I've been holding off looking at them as cg's
> | > really the man for the job.  However, as I've found out today cg's
> | > been ill of late and has plenty of things going on externally at
> | > present.
> | 
> | So how do we move forward?
> 
> Orlando Bassotto, one of the Audigy code submitters, has taken on the task of 

Here is the previously posted Orlando diff, updated for today's
5-CURRENT.  I am able to play mp3's with this patch.
-------------- next part --------------
Index: sys/dev/sound/pci/emu10k1.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sound/pci/emu10k1.c,v
retrieving revision 1.37
diff -u -r1.37 emu10k1.c
--- sys/dev/sound/pci/emu10k1.c	20 Apr 2003 09:07:14 -0000	1.37
+++ sys/dev/sound/pci/emu10k1.c	21 Apr 2003 01:23:22 -0000
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2003 Orlando Bassotto <orlando.bassotto at ieo-research.it>
  * Copyright (c) 1999 Cameron Grant <gandalf at vilnya.demon.co.uk>
  * All rights reserved.
  *
@@ -27,6 +28,8 @@
 #include <dev/sound/pcm/sound.h>
 #include <dev/sound/pcm/ac97.h>
 #include <gnu/dev/sound/pci/emu10k1.h>
+#include <gnu/dev/sound/pci/emu10k1-ac97.h>
+#include <gnu/dev/sound/pci/emu10k1-alsa.h>
 
 #include <pci/pcireg.h>
 #include <pci/pcivar.h>
@@ -39,9 +42,25 @@
 #define	EMU10K1_PCI_ID	0x00021102
 #define	EMU10K2_PCI_ID	0x00041102
 #define	EMU_DEFAULT_BUFSZ	4096
-#define	EMU_CHANS	4
+#define EMU_MAX_CHANS	8
 #undef EMUDEBUG
 
+#define	EMUPAGESIZE	4096	/* don't change */
+#define	MAXREQVOICES	8
+#define	MAXPAGES	(32768 * 64 / EMUPAGESIZE)	/* WAVEOUT_MAXBUFSIZE * NUM_G / EMUPAGESIZE */
+#define	RESERVED	0
+#define	NUM_MIDI	16
+#define	NUM_G		64		/* use all channels */
+#define	NUM_FXSENDS	4
+
+#define	TMEMSIZE	256*1024
+#define	TMEMSIZEREG	4
+
+#define	ENABLE		0xffffffff
+#define	DISABLE		0x00000000
+#define	ENV_ON		0x80
+#define	ENV_OFF		0x00
+
 struct emu_memblk {
 	SLIST_ENTRY(emu_memblk) link;
 	void *buf;
@@ -63,6 +82,8 @@
 	int b16:1, stereo:1, busy:1, running:1, ismaster:1;
 	int speed;
 	int start, end, vol;
+	int fxrt1;	/* FX routing */
+	int fxrt2;	/* FX routing (only for audigy) */
 	u_int32_t buf;
 	struct emu_voice *slave;
 	struct pcm_channel *channel;
@@ -91,7 +112,8 @@
 struct sc_info {
 	device_t	dev;
 	u_int32_t	type, rev;
-	u_int32_t	tos_link:1, APS:1;
+	u_int32_t	tos_link:1, APS:1, audigy:1, audigy2:1;
+	u_int32_t	addrmask;	/* wider if audigy */
 
 	bus_space_tag_t st;
 	bus_space_handle_t sh;
@@ -104,9 +126,10 @@
 	unsigned int bufsz;
 	int timer, timerinterval;
 	int pnum, rnum;
+	int nchans;
 	struct emu_mem mem;
 	struct emu_voice voice[64];
-	struct sc_pchinfo pch[EMU_CHANS];
+	struct sc_pchinfo pch[EMU_MAX_CHANS];
 	struct sc_rchinfo rch[3];
 };
 
@@ -166,6 +189,8 @@
 static struct pcmchan_caps emu_playcaps = {4000, 48000, emu_pfmt, 0};
 
 static int adcspeed[8] = {48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000};
+/* audigy supports 12kHz. */
+static int audigy_adcspeed[9] = {48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
 
 /* -------------------------------------------------------------------- */
 /* Hardware */
@@ -205,7 +230,7 @@
 {
 	u_int32_t ptr, val, mask, size, offset;
 
-	ptr = ((reg << 16) & PTR_ADDRESS_MASK) | (chn & PTR_CHANNELNUM_MASK);
+	ptr = ((reg << 16) & sc->addrmask) | (chn & PTR_CHANNELNUM_MASK);
 	emu_wr(sc, PTR, ptr, 4);
 	val = emu_rd(sc, DATA, 4);
 	if (reg & 0xff000000) {
@@ -223,7 +248,7 @@
 {
 	u_int32_t ptr, mask, size, offset;
 
-	ptr = ((reg << 16) & PTR_ADDRESS_MASK) | (chn & PTR_CHANNELNUM_MASK);
+	ptr = ((reg << 16) & sc->addrmask) | (chn & PTR_CHANNELNUM_MASK);
 	emu_wr(sc, PTR, ptr, 4);
 	if (reg & 0xff000000) {
 		size = (reg >> 24) & 0x3f;
@@ -239,7 +264,8 @@
 static void
 emu_wrefx(struct sc_info *sc, unsigned int pc, unsigned int data)
 {
-	emu_wrptr(sc, 0, MICROCODEBASE + pc, data);
+	pc += sc->audigy ? AUDIGY_CODEBASE : MICROCODEBASE;
+	emu_wrptr(sc, 0, pc, data);
 }
 
 /* -------------------------------------------------------------------- */
@@ -282,7 +308,7 @@
 	int i, tmp, rate;
 
 	rate = 0;
-	for (i = 0; i < EMU_CHANS; i++) {
+	for (i = 0; i < sc->nchans; i++) {
 		pch = &sc->pch[i];
 		if (pch->buffer) {
 			tmp = (pch->spd * sndbuf_getbps(pch->buffer)) / pch->blksz;
@@ -345,6 +371,16 @@
 	return val;
 }
 
+static int
+audigy_recval(int speed) {
+	int val;
+
+	val = 0;
+	while (val < 8 && speed < audigy_adcspeed[val])
+		val++;
+	return val;
+}
+
 static u_int32_t
 emu_rate_to_pitch(u_int32_t rate)
 {
@@ -447,6 +483,20 @@
 	m->vol = 0xff;
 	m->buf = tmp_addr;
 	m->slave = s;
+	if (sc->audigy) {
+		m->fxrt1 = A_FXBUS_PCM_LEFT | A_FXBUS_PCM_RIGHT << 8 |
+			A_FXBUS_PCM_LEFT_REAR << 16 |
+			A_FXBUS_PCM_RIGHT_REAR << 24;
+		m->fxrt2 = A_FXBUS_PCM_CENTER | A_FXBUS_PCM_LFE << 8 |
+			A_FXBUS_MIDI_CHORUS << 16 | 
+			A_FXBUS_MIDI_REVERB << 24;
+	} else {
+		m->fxrt1 = FXBUS_PCM_LEFT | FXBUS_PCM_RIGHT << 4 |
+			FXBUS_MIDI_CHORUS << 8 |
+			FXBUS_MIDI_REVERB << 12;
+		m->fxrt2 = 0;
+	}
+
 	if (s != NULL) {
 		s->start = m->start;
 		s->end = m->end;
@@ -458,6 +508,8 @@
 		s->ismaster = 0;
 		s->vol = m->vol;
 		s->buf = m->buf;
+		s->fxrt1 = m->fxrt1;
+		s->fxrt2 = m->fxrt2;
 		s->slave = NULL;
 	}
 	return 0;
@@ -506,7 +558,13 @@
 	val *= v->b16 ? 1 : 2;
 	start = sa + val;
 
-	emu_wrptr(sc, v->vnum, FXRT, 0xd01c0000);
+	if (sc->audigy) {
+		emu_wrptr(sc, v->vnum, A_FXRT1, v->fxrt1);
+		emu_wrptr(sc, v->vnum, A_FXRT2, v->fxrt2);
+		emu_wrptr(sc, v->vnum, A_SENDAMOUNTS, 0);
+	}
+	else
+		emu_wrptr(sc, v->vnum, FXRT, v->fxrt1 << 16);
 
 	emu_wrptr(sc, v->vnum, PTRX, (x << 8) | r);
 	emu_wrptr(sc, v->vnum, DSL, ea | (y << 24));
@@ -607,6 +665,12 @@
 		"ip", "ifatn", "pefe", "fmmod", "tremfrq", "fmfrq2",
 		"tempenv"
 	};
+	char *regname2[] = {
+		"mudata1", "mustat1", "mudata2", "mustat2",
+		"fxwc1", "fxwc2", "spdrate", NULL, NULL,
+		NULL, NULL, NULL, "fxrt2", "sndamnt", "fxrt1",
+		NULL, NULL
+	};
 	int i, x;
 
 	printf("voice number %d\n", v->vnum);
@@ -619,6 +683,19 @@
 		if (x > 2)
 			x = 0;
 	}
+
+	/* Print out audigy extra registers */
+	if (sc->audigy) {
+		for (i = 0; i <= 0xe; i++) {
+			if (regname2[i] == NULL)
+				continue;
+			printf("%s\t[%08x]", regname2[i], emu_rdptr(sc, v->vnum, i + 0x70));
+			printf("%s", (x == 2)? "\n" : "\t");
+			x++;
+			if (x > 2)
+				x = 0;
+		}
+	}
 	printf("\n\n");
 }
 #endif
@@ -777,7 +854,7 @@
 	ch->num = sc->rnum;
 	switch(sc->rnum) {
 	case 0:
-		ch->idxreg = ADCIDX;
+		ch->idxreg = sc->audigy ? A_ADCIDX : ADCIDX;
 		ch->basereg = ADCBA;
 		ch->sizereg = ADCBS;
 		ch->setupreg = ADCCR;
@@ -826,8 +903,12 @@
 {
 	struct sc_rchinfo *ch = data;
 
-	if (ch->num == 0)
-		speed = adcspeed[emu_recval(speed)];
+	if (ch->num == 0) {
+		if (ch->parent->audigy)
+			speed = audigy_adcspeed[audigy_recval(speed)];
+		else
+			speed = adcspeed[emu_recval(speed)];
+	}
 	if (ch->num == 1)
 		speed = 48000;
 	if (ch->num == 2)
@@ -891,10 +972,18 @@
 		ch->run = 1;
 		emu_wrptr(sc, 0, ch->sizereg, sz);
 		if (ch->num == 0) {
-			val = ADCCR_LCHANENABLE;
-			if (ch->fmt & AFMT_STEREO)
-				val |= ADCCR_RCHANENABLE;
-			val |= emu_recval(ch->spd);
+			if (sc->audigy) {
+				val = A_ADCCR_LCHANENABLE;
+				if (ch->fmt & AFMT_STEREO)
+					val |= A_ADCCR_RCHANENABLE;
+				val |= audigy_recval(ch->spd);
+			} else {
+				val = ADCCR_LCHANENABLE;
+				if (ch->fmt & AFMT_STEREO)
+					val |= ADCCR_RCHANENABLE;
+				val |= emu_recval(ch->spd);
+			}
+
 			emu_wrptr(sc, 0, ch->setupreg, 0);
 			emu_wrptr(sc, 0, ch->setupreg, val);
 		}
@@ -976,7 +1065,7 @@
 		if (stat & IPR_INTERVALTIMER) {
 			ack |= IPR_INTERVALTIMER;
 			x = 0;
-			for (i = 0; i < EMU_CHANS; i++) {
+			for (i = 0; i < sc->nchans; i++) {
 				if (sc->pch[i].run) {
 					x = 1;
 					chn_intr(sc->pch[i].channel);
@@ -1155,11 +1244,174 @@
 }
 
 static void
+audigy_addefxop(struct sc_info *sc, int op, int z, int w, int x, int y, u_int32_t *pc)
+{
+	emu_wrefx(sc, (*pc) * 2, (x << 12) | y);
+	emu_wrefx(sc, (*pc) * 2 + 1, (op << 24) | (z << 12) | w);
+	(*pc)++;
+}
+
+static void
+audigy_initefx(struct sc_info *sc)
+{
+	int i;
+	u_int32_t pc = 0;
+
+	/* skip 0, 0, -1, 0 - NOPs */
+	for (i = 0; i < 512; i++)
+		audigy_addefxop(sc, 0x0f, 0x0c0, 0x0c0, 0x0cf, 0x0c0, &pc);
+
+	for (i = 0; i < 512; i++)
+		emu_wrptr(sc, 0, A_FXGPREGBASE + i, 0x0);
+
+	pc = 16;
+
+	/* stop fx processor */
+	emu_wrptr(sc, 0, A_DBG, A_DBG_SINGLE_STEP);
+
+	/* Audigy 2 (EMU10K2) DSP Registers:
+	   FX Bus
+		0x000-0x00f : 16 registers (???)
+	   Input
+		0x040/0x041 : AC97 Codec (l/r)
+		0x042/0x043 : ADC, S/PDIF (l/r)
+		0x044/0x045 : Optical S/PDIF in (l/r)
+		0x046/0x047 : ???
+		0x048/0x049 : Line/Mic 2 (l/r)
+		0x04a/0x04b : RCA S/PDIF (l/r)
+		0x04c/0x04d : Aux 2 (l/r)
+	   Output
+		0x060/0x061 : Digital Front (l/r)
+		0x062/0x063 : Digital Center/LFE
+		0x064/0x065 : AudigyDrive Heaphone (l/r)
+		0x066/0x067 : Digital Rear (l/r)
+		0x068/0x069 : Analog Front (l/r)
+		0x06a/0x06b : Analog Center/LFE
+		0x06c/0x06d : ???
+		0x06e/0x06f : Analog Rear (l/r)
+		0x070/0x071 : AC97 Output (l/r)
+		0x072/0x073 : ???
+		0x074/0x075 : ???
+		0x076/0x077 : ADC Recording Buffer (l/r)
+	   Constants
+		0x0c0 - 0x0c4 = 0 - 4
+		0x0c5 = 0x8, 0x0c6 = 0x10, 0x0c7 = 0x20
+		0x0c8 = 0x100, 0x0c9 = 0x10000, 0x0ca = 0x80000
+		0x0cb = 0x10000000, 0x0cc = 0x20000000, 0x0cd = 0x40000000
+		0x0ce = 0x80000000, 0x0cf = 0x7fffffff, 0x0d0 = 0xffffffff
+		0x0d1 = 0xfffffffe, 0x0d2 = 0xc0000000, 0x0d3 = 0x41fbbcdc
+		0x0d4 = 0x5a7ef9db, 0x0d5 = 0x00100000, 0x0dc = 0x00000001 (???)
+	   Temporary Values
+		0x0d6 : Accumulator (???)
+		0x0d7 : Condition Register
+		0x0d8 : Noise source
+		0x0d9 : Noise source
+	   Tank Memory Data Registers
+		0x200 - 0x2ff
+	   Tank Memory Address Registers
+		0x300 - 0x3ff
+	   General Purpose Registers
+		0x400 - 0x5ff
+	 */
+
+	/* AC97Output[l/r] = FXBus PCM[l/r] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AC97_L), A_C_00000000,
+			A_C_00000000, A_FXBUS(A_FXBUS_PCM_LEFT), &pc);
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AC97_R), A_C_00000000,
+			A_C_00000000, A_FXBUS(A_FXBUS_PCM_RIGHT), &pc);
+
+	/* GPR[0/1] = RCA S/PDIF[l/r] -- Master volume */
+	audigy_addefxop(sc, iACC3, A_GPR(0), A_C_00000000,
+			A_C_00000000, A_EXTIN(A_EXTIN_RCA_SPDIF_L), &pc);
+	audigy_addefxop(sc, iACC3, A_GPR(1), A_C_00000000,
+			A_C_00000000, A_EXTIN(A_EXTIN_RCA_SPDIF_R), &pc);
+
+	/* GPR[2] = GPR[0] (Left) / 2 + GPR[1] (Right) / 2 -- Central volume */
+	audigy_addefxop(sc, iINTERP, A_GPR(2), A_GPR(1),
+			A_C_40000000, A_GPR(0), &pc);
+
+	/* Headphones[l/r] = GPR[0/1] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_HEADPHONE_L),
+			A_C_00000000, A_C_00000000, A_GPR(0), &pc);
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_HEADPHONE_R),
+			A_C_00000000, A_C_00000000, A_GPR(1), &pc);
+
+	/* Analog Front[l/r] = GPR[0/1] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AFRONT_L), A_C_00000000,
+			A_C_00000000, A_GPR(0), &pc);
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AFRONT_R), A_C_00000000,
+			A_C_00000000, A_GPR(1), &pc);
+
+	/* Digital Front[l/r] = GPR[0/1] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L), A_C_00000000,
+			A_C_00000000, A_GPR(0), &pc);
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_FRONT_R), A_C_00000000,
+			A_C_00000000, A_GPR(1), &pc);
+
+	/* Center and Subwoofer configuration */
+	/* Analog Center = GPR[0] + GPR[2] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ACENTER), A_C_00000000,
+			A_GPR(0), A_GPR(2), &pc);
+	/* Analog Sub = GPR[1] + GPR[2] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ALFE), A_C_00000000,
+			A_GPR(1), A_GPR(2), &pc);
+
+	/* Digital Center = GPR[0] + GPR[2] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_CENTER), A_C_00000000,
+			A_GPR(0), A_GPR(2), &pc);
+	/* Digital Sub = GPR[1] + GPR[2] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_LFE), A_C_00000000,
+			A_GPR(1), A_GPR(2), &pc);
+
+#if 0
+	/* Analog Rear[l/r] = (GPR[0/1] * RearVolume[l/r]) >> 31 */
+	/*   RearVolume = GPR[0x10/0x11] (Will this ever be implemented?) */
+	audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_AREAR_L), A_C_00000000,
+			A_GPR(16), A_GPR(0), &pc);
+	audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_AREAR_R), A_C_00000000,
+			A_GPR(17), A_GPR(1), &pc);
+
+	/* Digital Rear[l/r] = (GPR[0/1] * RearVolume[l/r]) >> 31 */
+	/*   RearVolume = GPR[0x10/0x11] (Will this ever be implemented?) */
+	audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_REAR_L), A_C_00000000,
+			A_GPR(16), A_GPR(0), &pc);
+	audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_REAR_R), A_C_00000000,
+			A_GPR(17), A_GPR(1), &pc);
+#else
+	/* XXX This is just a copy to the channel, since we do not have
+	 *     a patch manager, it is useful for have another output enabled.
+	 */
+
+	/* Analog Rear[l/r] = GPR[0/1] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AREAR_L), A_C_00000000,
+			A_C_00000000, A_GPR(0), &pc);
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AREAR_R), A_C_00000000,
+			A_C_00000000, A_GPR(1), &pc);
+
+	/* Digital Rear[l/r] = GPR[0/1] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_REAR_L), A_C_00000000,
+			A_C_00000000, A_GPR(0), &pc);
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_REAR_R), A_C_00000000,
+			A_C_00000000, A_GPR(1), &pc);
+#endif
+
+	/* ADC Recording buffer[l/r] = AC97Input[l/r] */
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ADC_CAP_L), A_C_00000000,
+			A_C_00000000, A_EXTIN(A_EXTIN_AC97_L), &pc);
+	audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ADC_CAP_R), A_C_00000000,
+			A_C_00000000, A_EXTIN(A_EXTIN_AC97_R), &pc);
+
+	/* resume normal operations */
+	emu_wrptr(sc, 0, A_DBG, 0);
+}
+
+static void
 emu_initefx(struct sc_info *sc)
 {
 	int i;
 	u_int32_t pc = 16;
 
+	/* acc3 0,0,0,0 - NOPs */
 	for (i = 0; i < 512; i++) {
 		emu_wrefx(sc, i * 2, 0x10040);
 		emu_wrefx(sc, i * 2 + 1, 0x610040);
@@ -1175,24 +1427,34 @@
 	     0x010/0x011 : AC97 Codec (l/r)
 	     0x012/0x013 : ADC, S/PDIF (l/r)
 	     0x014/0x015 : Mic(left), Zoom (l/r)
-	     0x016/0x017 : APS S/PDIF?? (l/r)
+	     0x016/0x017 : TOS link in (l/r)
+	     0x018/0x019 : Line/Mic 1 (l/r)
+	     0x01a/0x01b : COAX S/PDIF (l/r)
+	     0x01c/0x01d : Line/Mic 2 (l/r)
 	   Output
 	     0x020/0x021 : AC97 Output (l/r)
 	     0x022/0x023 : TOS link out (l/r)
-	     0x024/0x025 : ??? (l/r)
+	     0x024/0x025 : Center/LFE
 	     0x026/0x027 : LiveDrive Headphone (l/r)
 	     0x028/0x029 : Rear Channel (l/r)
 	     0x02a/0x02b : ADC Recording Buffer (l/r)
+	     0x02c       : Mic Recording Buffer
+	     0x031/0x032 : Analog Center/LFE
 	   Constants
 	     0x040 - 0x044 = 0 - 4
 	     0x045 = 0x8, 0x046 = 0x10, 0x047 = 0x20
 	     0x048 = 0x100, 0x049 = 0x10000, 0x04a = 0x80000
 	     0x04b = 0x10000000, 0x04c = 0x20000000, 0x04d = 0x40000000
-	     0x04e = 0x80000000, 0x04f = 0x7fffffff
+	     0x04e = 0x80000000, 0x04f = 0x7fffffff, 0x050 = 0xffffffff
+	     0x051 = 0xfffffffe, 0x052 = 0xc0000000, 0x053 = 0x41fbbcdc
+	     0x054 = 0x5a7ef9db, 0x055 = 0x00100000
 	   Temporary Values
 	     0x056 : Accumulator
-	     0x058 : Noise source?
-	     0x059 : Noise source?
+	     0x057 : Condition Register
+	     0x058 : Noise source
+	     0x059 : Noise source
+	     0x05a : IRQ Register
+	     0x05b : TRAM Delay Base Address Count
 	   General Purpose Registers
 	     0x100 - 0x1ff
 	   Tank Memory Data Registers
@@ -1201,40 +1463,81 @@
 	     0x300 - 0x3ff
 	     */
 
-	/* Operators:
-	   0 : z := w + (x * y >> 31)
-	   4 : z := w + x * y
-	   6 : z := w + x + y
-	   */
-
 	/* Routing - this will be configurable in later version */
 
 	/* GPR[0/1] = FX * 4 + SPDIF-in */
-	emu_addefxop(sc, 4, 0x100, 0x12, 0, 0x44, &pc);
-	emu_addefxop(sc, 4, 0x101, 0x13, 1, 0x44, &pc);
+	emu_addefxop(sc, iMACINT0, GPR(0), EXTIN(EXTIN_SPDIF_CD_L),
+			FXBUS(FXBUS_PCM_LEFT), C_00000004, &pc);
+	emu_addefxop(sc, iMACINT0, GPR(1), EXTIN(EXTIN_SPDIF_CD_R),
+			FXBUS(FXBUS_PCM_RIGHT), C_00000004, &pc);
+
 	/* GPR[0/1] += APS-input */
-	emu_addefxop(sc, 6, 0x100, 0x100, 0x40, sc->APS ? 0x16 : 0x40, &pc);
-	emu_addefxop(sc, 6, 0x101, 0x101, 0x40, sc->APS ? 0x17 : 0x40, &pc);
+	emu_addefxop(sc, iACC3, GPR(0), GPR(0), C_00000000,
+			sc->APS ? EXTIN(EXTIN_TOSLINK_L) : C_00000000, &pc);
+	emu_addefxop(sc, iACC3, GPR(1), GPR(1), C_00000000,
+			sc->APS ? EXTIN(EXTIN_TOSLINK_R) : C_00000000, &pc);
+
 	/* FrontOut (AC97) = GPR[0/1] */
-	emu_addefxop(sc, 6, 0x20, 0x40, 0x40, 0x100, &pc);
-	emu_addefxop(sc, 6, 0x21, 0x40, 0x41, 0x101, &pc);
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_L), C_00000000,
+			C_00000000, GPR(0), &pc);
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_R), C_00000000,
+			C_00000001, GPR(1), &pc);
+
+	/* GPR[2] = GPR[0] (Left) / 2 + GPR[1] (Right) / 2 -- Central volume */
+	emu_addefxop(sc, iINTERP, GPR(2), GPR(1), C_40000000, GPR(0), &pc);
+
+#if 0
 	/* RearOut = (GPR[0/1] * RearVolume) >> 31 */
-	/*   RearVolume = GRP[0x10/0x11] */
-	emu_addefxop(sc, 0, 0x28, 0x40, 0x110, 0x100, &pc);
-	emu_addefxop(sc, 0, 0x29, 0x40, 0x111, 0x101, &pc);
-	/* TOS out = GPR[0/1] */
-	emu_addefxop(sc, 6, 0x22, 0x40, 0x40, 0x100, &pc);
-	emu_addefxop(sc, 6, 0x23, 0x40, 0x40, 0x101, &pc);
-	/* Mute Out2 */
-	emu_addefxop(sc, 6, 0x24, 0x40, 0x40, 0x40, &pc);
-	emu_addefxop(sc, 6, 0x25, 0x40, 0x40, 0x40, &pc);
-	/* Mute Out3 */
-	emu_addefxop(sc, 6, 0x26, 0x40, 0x40, 0x40, &pc);
-	emu_addefxop(sc, 6, 0x27, 0x40, 0x40, 0x40, &pc);
-	/* Input0 (AC97) -> Record */
-	emu_addefxop(sc, 6, 0x2a, 0x40, 0x40, 0x10, &pc);
-	emu_addefxop(sc, 6, 0x2b, 0x40, 0x40, 0x11, &pc);
+	/*   RearVolume = GPR[0x10/0x11] */
+	emu_addefxop(sc, iMAC0, EXTOUT(EXTOUT_REAR_L), C_00000000,
+			GPR(16), GPR(0), &pc);
+	emu_addefxop(sc, iMAC0, EXTOUT(EXTOUT_REAR_R), C_00000000,
+			GPR(17), GPR(1), &pc);
+#else
+	/* XXX This is just a copy to the channel, since we do not have
+	 *     a patch manager, it is useful for have another output enabled.
+	 */
+
+	/* Rear[l/r] = GPR[0/1] */
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_REAR_L), C_00000000,
+			C_00000000, GPR(0), &pc);
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_REAR_R), C_00000000,
+			C_00000000, GPR(1), &pc);
+#endif
 
+	/* TOS out[l/r] = GPR[0/1] */
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_TOSLINK_L), C_00000000,
+			C_00000000, GPR(0), &pc);
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_TOSLINK_R), C_00000000,
+			C_00000000, GPR(1), &pc);
+
+	/* Center and Subwoofer configuration */
+	/* Analog Center = GPR[0] + GPR[2] */
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ACENTER), C_00000000,
+			GPR(0), GPR(2), &pc);
+	/* Analog Sub = GPR[1] + GPR[2] */
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ALFE), C_00000000,
+			GPR(1), GPR(2), &pc);
+	/* Digital Center = GPR[0] + GPR[2] */
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_CENTER), C_00000000,
+			GPR(0), GPR(2), &pc);
+	/* Digital Sub = GPR[1] + GPR[2] */
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_LFE), C_00000000,
+			GPR(1), GPR(2), &pc);
+
+	/* Headphones[l/r] = GPR[0/1] */
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_HEADPHONE_L), C_00000000,
+			C_00000000, GPR(0), &pc);
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_HEADPHONE_R), C_00000000,
+			C_00000000, GPR(1), &pc);
+
+	/* ADC Recording buffer[l/r] = AC97Input[l/r] */
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ADC_CAP_L), C_00000000,
+			C_00000000, EXTIN(EXTIN_AC97_L), &pc);
+	emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ADC_CAP_R), C_00000000,
+			C_00000000, EXTIN(EXTIN_AC97_R), &pc);
+
+	/* resume normal operations */
 	emu_wrptr(sc, 0, DBG, 0);
 }
 
@@ -1244,6 +1547,9 @@
 {
 	u_int32_t spcs, ch, tmp, i;
 
+	/* enable additional AC97 slots */
+	emu_wrptr(sc, 0, AC97SLOT, AC97SLOT_CNTR | AC97SLOT_LFE);
+
 	/* disable audio and lock cache */
 	emu_wr(sc, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, 4);
 
@@ -1262,6 +1568,12 @@
 	emu_wrptr(sc, 0, SOLEL, 0);
 	emu_wrptr(sc, 0, SOLEH, 0);
 
+	/* wonder what these do... */
+	if (sc->audigy) {
+		emu_wrptr(sc, 0, SPBYPASS, 0xf00);
+		emu_wrptr(sc, 0, AC97SLOT, 0x3);
+	}
+
 	/* init envelope engine */
 	for (ch = 0; ch < NUM_G; ch++) {
 		emu_wrptr(sc, ch, DCYSUSV, ENV_OFF);
@@ -1295,6 +1607,18 @@
 		emu_wrptr(sc, ch, ENVVOL, 0);
 		emu_wrptr(sc, ch, ENVVAL, 0);
 
+		if (sc->audigy) {
+			/* audigy cards need this to initialize correctly */
+			emu_wrptr(sc, ch, 0x4c, 0);
+			emu_wrptr(sc, ch, 0x4d, 0);
+			emu_wrptr(sc, ch, 0x4e, 0);
+			emu_wrptr(sc, ch, 0x4f, 0);
+			/* set default routing */
+			emu_wrptr(sc, ch, A_FXRT1, 0x03020100);
+			emu_wrptr(sc, ch, A_FXRT2, 0x3f3f3f3f);
+			emu_wrptr(sc, ch, A_SENDAMOUNTS, 0);
+		}
+
 		sc->voice[ch].vnum = ch;
 		sc->voice[ch].slave = NULL;
 		sc->voice[ch].busy = 0;
@@ -1331,7 +1655,26 @@
 	emu_wrptr(sc, 0, SPCS1, spcs);
 	emu_wrptr(sc, 0, SPCS2, spcs);
 
-	emu_initefx(sc);
+	if (!sc->audigy)
+		emu_initefx(sc);
+	else if (sc->audigy2) {	/* Audigy 2 */
+		/* from ALSA initialization code: */
+
+		/* Hack for Alice3 to work independent of haP16V driver */
+		u_int32_t tmp;
+
+		/* Setup SRCMulti_I2S SamplingRate */
+		tmp = emu_rdptr(sc, 0, A_SPDIF_SAMPLERATE) & 0xfffff1ff;
+		emu_wrptr(sc, 0, A_SPDIF_SAMPLERATE, tmp | 0x400);
+
+		/* Setup SRCSel (Enable SPDIF, I2S SRCMulti) */
+		emu_wr(sc, 0x20, 0x00600000, 4);
+		emu_wr(sc, 0x24, 0x00000014, 4);
+
+		/* Setup SRCMulti Input Audio Enable */
+		emu_wr(sc, 0x20, 0x006e0000, 4);
+		emu_wr(sc, 0x24, 0xff00ff00, 4);
+	}
 
 	SLIST_INIT(&sc->mem.blocks);
 	sc->mem.ptb_pages = emu_malloc(sc, MAXPAGES * sizeof(u_int32_t), &sc->mem.ptb_pages_addr);
@@ -1361,26 +1704,69 @@
 	/* emu_memalloc(sc, EMUPAGESIZE); */
 	/*
 	 *  Hokay, now enable the AUD bit
+	 *
+	 *  Audigy
+	 *   Enable Audio = 0 (enabled after fx processor initialization)
+	 *   Mute Disable Audio = 0
+	 *   Joystick = 1
+	 *
+	 *  Audigy 2
+	 *   Enable Audio = 1
+	 *   Mute Disable Audio = 0
+	 *   Joystick = 1
+	 *   GP S/PDIF AC3 Enable = 1
+	 *   CD S/PDIF AC3 Enable = 1
+	 *
+	 *  EMU10K1
 	 *   Enable Audio = 1
 	 *   Mute Disable Audio = 0
 	 *   Lock Tank Memory = 1
 	 *   Lock Sound Memory = 0
 	 *   Auto Mute = 1
 	 */
-	tmp = HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE;
-	if (sc->rev >= 6)
-		tmp |= HCFG_JOYENABLE;
-	emu_wr(sc, HCFG, tmp, 4);
-
-	/* TOSLink detection */
-	sc->tos_link = 0;
-	tmp = emu_rd(sc, HCFG, 4);
-	if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
-		emu_wr(sc, HCFG, tmp | 0x800, 4);
-		DELAY(50);
-		if (tmp != (emu_rd(sc, HCFG, 4) & ~0x800)) {
-			sc->tos_link = 1;
-			emu_wr(sc, HCFG, tmp, 4);
+
+	if (sc->audigy) {
+		tmp = HCFG_AUTOMUTE | HCFG_JOYENABLE;
+		if (sc->audigy2)	/* Audigy 2 */
+			tmp = HCFG_AUDIOENABLE | HCFG_AC3ENABLE_CDSPDIF |
+			    HCFG_AC3ENABLE_GPSPDIF;
+		emu_wr(sc, HCFG, tmp, 4);
+
+		audigy_initefx(sc);
+
+		/* from ALSA initialization code: */
+
+		/* enable audio and disable both audio/digital outputs */
+		emu_wr(sc, HCFG, emu_rd(sc, HCFG, 4) | HCFG_AUDIOENABLE, 4);
+		emu_wr(sc, A_IOCFG, emu_rd(sc, A_IOCFG, 4) & ~A_IOCFG_GPOUT_AD,
+		    4);
+		if (sc->audigy2) {	/* Audigy 2 */
+			/* Unmute Analog.
+			 * Set GPO6 to 1 for Apollo. This has to be done after
+			 * init Alice3 I2SOut beyond 48kHz.
+			 * So, sequence is important.
+			 */
+			emu_wr(sc, A_IOCFG,
+			    emu_rd(sc, A_IOCFG, 4) | A_IOCFG_GPOUT_A, 4);
+		}
+	} else {
+		/* EMU10K1 initialization code */
+		tmp = HCFG_AUDIOENABLE | HCFG_AUTOMUTE | HCFG_LOCKTANKCACHE;
+		if (sc->rev >= 6)
+			tmp |= HCFG_JOYENABLE;
+
+		emu_wr(sc, HCFG, tmp, 4);
+
+		/* TOSLink detection */
+		sc->tos_link = 0;
+		tmp = emu_rd(sc, HCFG, 4);
+		if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
+			emu_wr(sc, HCFG, tmp | HCFG_GPOUT1, 4);
+			DELAY(50);
+			if (tmp != (emu_rd(sc, HCFG, 4) & ~HCFG_GPOUT1)) {
+				sc->tos_link = 1;
+				emu_wr(sc, HCFG, tmp, 4);
+			}
 		}
 	}
 
@@ -1402,6 +1788,10 @@
 		emu_wrptr(sc, ch, CPF, 0);
 	}
 
+	if (sc->audigy) {	/* stop fx processor */
+		emu_wrptr(sc, 0, A_DBG, A_DBG_SINGLE_STEP);
+	}
+
 	/* disable audio and lock cache */
 	emu_wr(sc, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, 4);
 
@@ -1441,11 +1831,14 @@
 	case EMU10K1_PCI_ID:
 		s = "Creative EMU10K1";
 		break;
-/*
+
 	case EMU10K2_PCI_ID:
-		s = "Creative EMU10K2";
+		if (pci_get_revid(dev) == 0x04)
+			s = "Creative Audigy 2 (EMU10K2)";
+		else
+			s = "Creative Audigy (EMU10K2)";
 		break;
-*/
+
 	default:
 		return ENXIO;
 	}
@@ -1472,6 +1865,10 @@
 	sc->dev = dev;
 	sc->type = pci_get_devid(dev);
 	sc->rev = pci_get_revid(dev);
+	sc->audigy = (sc->type == EMU10K2_PCI_ID);
+	sc->audigy2 = (sc->audigy && sc->rev == 0x04);
+	sc->nchans = sc->audigy ? 8 : 4;
+	sc->addrmask = sc->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
 
 	data = pci_read_config(dev, PCIR_COMMAND, 2);
 	data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
@@ -1518,8 +1915,8 @@
 
 	snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", rman_get_start(sc->reg), rman_get_start(sc->irq));
 
-	if (pcm_register(dev, sc, EMU_CHANS, gotmic ? 3 : 2)) goto bad;
-	for (i = 0; i < EMU_CHANS; i++)
+	if (pcm_register(dev, sc, sc->nchans, gotmic ? 3 : 2)) goto bad;
+	for (i = 0; i < sc->nchans; i++)
 		pcm_addchan(dev, PCMDIR_PLAY, &emupchan_class, sc);
 	for (i = 0; i < (gotmic ? 3 : 2); i++)
 		pcm_addchan(dev, PCMDIR_REC, &emurchan_class, sc);

Index: sys/gnu/dev/sound/pci/emu10k1.h
===================================================================
RCS file: /home/ncvs/src/sys/gnu/dev/sound/pci/emu10k1.h,v
retrieving revision 1.6
diff -u -r1.6 emu10k1.h
--- sys/gnu/dev/sound/pci/emu10k1.h	18 Apr 2003 04:13:38 -0000	1.6
+++ sys/gnu/dev/sound/pci/emu10k1.h	20 Apr 2003 07:20:37 -0000
@@ -1,7 +1,7 @@
 /*
  **********************************************************************
  *     emu10k1.h, derived from 8010.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
+ *     Copyright 1999-2001 Creative Labs, Inc.
  *
  **********************************************************************
  *
@@ -11,6 +11,8 @@
  *     November 2, 1999     Alan Cox	    Cleaned of 8bit chars, DOS
  *					    line endings
  *     December 8, 1999     Jon Taylor	    Added lots of new register info
+ *     May 16, 2001         Daniel Bertrand Added unofficial DBG register info
+ *     Oct-Nov 2001         D.B.            Added unofficial Audigy registers 
  *
  **********************************************************************
  *
@@ -38,21 +40,14 @@
 #ifndef EMU10K1_H
 #define EMU10K1_H
 
-/* ------------------- DEFINES -------------------- */
+/*
+// Driver version:
+#define MAJOR_VER 0
+#define MINOR_VER 20
+#define DRIVER_VERSION "0.20a"
+*/
 
-#define EMUPAGESIZE	4096	/* don't change */
-#define MAXREQVOICES	8
-#define MAXPAGES	(32768 * 64 / EMUPAGESIZE)	/* WAVEOUT_MAXBUFSIZE * NUM_G / EMUPAGESIZE */
-#define RESERVED	0
-#define NUM_MIDI	16
-#define NUM_G		64		/* use all channels */
-#define NUM_FXSENDS	4
-
-
-#define TMEMSIZE	256*1024
-#define TMEMSIZEREG	4
-
-#define IP_TO_CP(ip) ((ip == 0) ? 0 : (((0x00001000uL | (ip & 0x00000FFFL)) << (((ip >> 12) & 0x000FL) + 4)) & 0xFFFF0000uL))
+/* Audigy specify registers are prefixed with 'A_' */
 
 /************************************************************************************************/
 /* PCI function 0 registers, address = <val> + PCIBASE0						*/
@@ -72,6 +67,11 @@
 #define IPR			0x08		/* Global interrupt pending register		*/
 						/* Clear pending interrupts by writing a 1 to	*/
 						/* the relevant bits and zero to the other bits	*/
+
+/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/
+#define A_IPR_MIDITRANSBUFEMPTY2	0x10000000	/* MIDI UART transmit buffer empty		*/
+#define A_IPR_MIDIRECVBUFEMPTY2	0x08000000	/* MIDI UART receive buffer empty		*/
+
 #define IPR_SAMPLERATETRACKER	0x01000000	/* Sample rate tracker lock status change	*/
 #define IPR_FXDSP		0x00800000	/* Enable FX DSP interrupts			*/
 #define IPR_FORCEINT		0x00400000	/* Force Sound Blaster interrupt		*/
@@ -96,6 +96,10 @@
 						/* IP is written with CL set, the bit in CLIPL	*/
 						/* or CLIPH corresponding to the CIN value 	*/
 						/* written will be cleared.			*/
+#define A_IPR_MIDITRANSBUFEMPTY1	IPR_MIDITRANSBUFEMPTY	/* MIDI UART transmit buffer empty		*/
+#define A_IPR_MIDIRECVBUFEMPTY1	IPR_MIDIRECVBUFEMPTY	/* MIDI UART receive buffer empty		*/
+
+
 
 #define INTE			0x0c		/* Interrupt enable register			*/
 #define INTE_VIRTUALSB_MASK	0xc0000000	/* Virtual Soundblaster I/O port capture	*/
@@ -123,6 +127,11 @@
 						/* behavior and possibly random segfaults and	*/
 						/* lockups if enabled.				*/
 
+/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/
+#define A_INTE_MIDITXENABLE2	0x00020000	/* Enable MIDI transmit-buffer-empty interrupts	*/
+#define A_INTE_MIDIRXENABLE2	0x00010000	/* Enable MIDI receive-buffer-empty interrupts	*/
+
+
 #define INTE_SAMPLERATETRACKER	0x00002000	/* Enable sample rate tracker interrupts	*/
 						/* NOTE: This bit must always be enabled       	*/
 #define INTE_FXDSPENABLE	0x00001000	/* Enable FX DSP interrupts			*/
@@ -139,6 +148,10 @@
 #define INTE_MIDITXENABLE	0x00000002	/* Enable MIDI transmit-buffer-empty interrupts	*/
 #define INTE_MIDIRXENABLE	0x00000001	/* Enable MIDI receive-buffer-empty interrupts	*/
 
+/* The next two interrupts are for the midi port on the Audigy (A_MPU2)	*/
+#define A_INTE_MIDITXENABLE1  	INTE_MIDITXENABLE
+#define A_INTE_MIDIRXENABLE1	INTE_MIDIRXENABLE
+
 #define WC			0x10		/* Wall Clock register				*/
 #define WC_SAMPLECOUNTER_MASK	0x03FFFFC0	/* Sample periods elapsed since reset		*/
 #define WC_SAMPLECOUNTER	0x14060010
@@ -170,7 +183,12 @@
 #define HCFG_CODECFORMAT_I2S	0x00010000	/* I2S CODEC format -- Secondary (Rear) Output	*/
 #define HCFG_GPINPUT0		0x00004000	/* External pin112				*/
 #define HCFG_GPINPUT1		0x00002000	/* External pin110				*/
+
 #define HCFG_GPOUTPUT_MASK	0x00001c00	/* External pins which may be controlled	*/
+#define HCFG_GPOUT0		0x00001000	/* set to enable digital out on 5.1 cards	*/
+#define HCFG_GPOUT1		0x00000800	/* External pin? (IR)				*/
+#define HCFG_GPOUT2		0x00000400	/* External pin? (IR)				*/
+
 #define HCFG_JOYENABLE      	0x00000200	/* Internal joystick enable    			*/
 #define HCFG_PHASETRACKENABLE	0x00000100	/* Phase tracking enable			*/
 						/* 1 = Force all 3 async digital inputs to use	*/
@@ -178,6 +196,7 @@
 #define HCFG_AC3ENABLE_MASK	0x0x0000e0	/* AC3 async input control - Not implemented	*/
 #define HCFG_AC3ENABLE_ZVIDEO	0x00000080	/* Channels 0 and 1 replace ZVIDEO		*/
 #define HCFG_AC3ENABLE_CDSPDIF	0x00000040	/* Channels 0 and 1 replace CDSPDIF		*/
+#define HCFG_AC3ENABLE_GPSPDIF  0x00000020      /* Channels 0 and 1 replace GPSPDIF             */
 #define HCFG_AUTOMUTE		0x00000010	/* When set, the async sample rate convertors	*/
 						/* will automatically mute their output when	*/
 						/* they are not rate-locked to the external	*/
@@ -186,6 +205,7 @@
 						/* NOTE: This should generally never be used.  	*/
 #define HCFG_LOCKTANKCACHE_MASK	0x00000004	/* 1 = Cancel bustmaster accesses to tankcache	*/
 						/* NOTE: This should generally never be used.  	*/
+#define HCFG_LOCKTANKCACHE	0x01020014
 #define HCFG_MUTEBUTTONENABLE	0x00000002	/* 1 = Master mute button sets AUDIOENABLE = 0.	*/
 						/* NOTE: This is a 'cheap' way to implement a	*/
 						/* master mute function on the mute button, and	*/
@@ -196,6 +216,8 @@
 						/* Should be set to 1 when the EMU10K1 is	*/
 						/* completely initialized.			*/
 
+/*For Audigy, MPU port move to 0x70-0x74 ptr register */
+
 #define MUDATA			0x18		/* MPU401 data register (8 bits)       		*/
 
 #define MUCMD			0x19		/* MPU401 command register (8 bits)    		*/
@@ -207,11 +229,16 @@
 #define MUSTAT_IRDYN		0x80		/* 0 = MIDI data or command ACK			*/
 #define MUSTAT_ORDYN		0x40		/* 0 = MUDATA can accept a command or data	*/
 
-#define TIMER			0x1a		/* Timer terminal count register		*/
+#define A_IOCFG			0x18		/* GPIO on Audigy card (16bits)			*/
+#define A_GPINPUT_MASK		0xff00
+#define A_GPOUTPUT_MASK		0x00ff
+#define A_IOCFG_GPOUT0		0x0044		/* ? */
+
+#define TIMER			0x1a		/* Timer terminal count register (16-bit)	*/
 						/* NOTE: After the rate is changed, a maximum	*/
 						/* of 1024 sample periods should be allowed	*/
 						/* before the new rate is guaranteed accurate.	*/
-#define TIMER_RATE_MASK		0x000003ff	/* Timer interrupt rate in sample periods	*/
+#define TIMER_RATE_MASK		0x03ff		/* Timer interrupt rate in sample periods	*/
 						/* 0 == 1024 periods, [1..4] are not useful	*/
 #define TIMER_RATE		0x0a00001a
 
@@ -221,54 +248,6 @@
 #define AC97ADDRESS_READY	0x80		/* Read-only bit, reflects CODEC READY signal	*/
 #define AC97ADDRESS_ADDRESS	0x7f		/* Address of indexed AC97 register		*/
 
-/************************************************************************************************/
-/* PCI function 1 registers, address = <val> + PCIBASE1						*/
-/************************************************************************************************/
-
-#define JOYSTICK1		0x00		/* Analog joystick port register		*/
-#define JOYSTICK2		0x01		/* Analog joystick port register		*/
-#define JOYSTICK3		0x02		/* Analog joystick port register		*/
-#define JOYSTICK4		0x03		/* Analog joystick port register		*/
-#define JOYSTICK5		0x04		/* Analog joystick port register		*/
-#define JOYSTICK6		0x05		/* Analog joystick port register		*/
-#define JOYSTICK7		0x06		/* Analog joystick port register		*/
-#define JOYSTICK8		0x07		/* Analog joystick port register		*/
-
-/* When writing, any write causes JOYSTICK_COMPARATOR output enable to be pulsed on write.	*/
-/* When reading, use these bitfields: */
-#define JOYSTICK_BUTTONS	0x0f		/* Joystick button data				*/
-#define JOYSTICK_COMPARATOR	0xf0		/* Joystick comparator data			*/
-
-
-/********************************************************************************************************/
-/* AC97 pointer-offset register set, accessed through the AC97ADDRESS and AC97DATA registers		*/
-/********************************************************************************************************/
-
-#define AC97_RESET		0x00
-#define AC97_MASTERVOLUME	0x02		/* Master volume					*/
-#define AC97_HEADPHONEVOLUME	0x04		/* Headphone volume					*/
-#define AC97_MASTERVOLUMEMONO	0x06		/* Mast volume mono					*/
-#define AC97_MASTERTONE		0x08
-#define AC97_PCBEEPVOLUME	0x0a		/* PC speaker system beep volume			*/
-#define AC97_PHONEVOLUME	0x0c
-#define AC97_MICVOLUME		0x0e
-#define AC97_LINEINVOLUME	0x10
-#define AC97_CDVOLUME		0x12
-#define AC97_VIDEOVOLUME	0x14
-#define AC97_AUXVOLUME		0x16
-#define AC97_PCMOUTVOLUME	0x18
-#define AC97_RECORDSELECT	0x1a
-#define AC97_RECORDGAIN		0x1c
-#define AC97_RECORDGAINMIC	0x1e
-#define AC97_GENERALPURPOSE	0x20
-#define AC97_3DCONTROL		0x22
-#define AC97_MODEMRATE		0x24
-#define AC97_POWERDOWN		0x26
-#define AC97_VENDORID1		0x7c
-#define AC97_VENDORID2		0x7e
-#define AC97_ZVIDEOVOLUME	0xec
-#define AC97_AC3VOLUME		0xed
-
 /********************************************************************************************************/
 /* Emu10k1 pointer-offset register set, accessed through the PTR and DATA registers			*/
 /********************************************************************************************************/
@@ -444,6 +423,8 @@
 #define TREMFRQ 		0x1c		/* Tremolo amount and modulation LFO frequency register	*/
 #define TREMFRQ_DEPTH		0x0000ff00	/* Tremolo depth					*/
 						/* Signed 2's complement, with +/- 12dB extremes	*/
+#define TREMFRQ_FREQUENCY	0x000000ff	/* Tremolo LFO frequency				*/
+						/* ??Hz steps, maximum of ?? Hz.			*/
 
 #define FM2FRQ2 		0x1d		/* Vibrato amount and vibrato LFO frequency register	*/
 #define FM2FRQ2_DEPTH		0x0000ff00	/* Vibrato LFO vibrato depth				*/
@@ -484,7 +465,12 @@
 #define ADCCR_LCHANENABLE	0x00000008	/* Enables left channel for writing to the host		*/
 						/* NOTE: To guarantee phase coherency, both channels	*/
 						/* must be disabled prior to enabling both channels.	*/
+#define A_ADCCR_RCHANENABLE	0x00000020
+#define A_ADCCR_LCHANENABLE	0x00000010
+
+#define A_ADCCR_SAMPLERATE_MASK 0x0000000F      /* Audigy sample rate convertor output rate		*/
 #define ADCCR_SAMPLERATE_MASK	0x00000007	/* Sample rate convertor output rate			*/
+
 #define ADCCR_SAMPLERATE_48	0x00000000	/* 48kHz sample rate					*/
 #define ADCCR_SAMPLERATE_44	0x00000001	/* 44.1kHz sample rate					*/
 #define ADCCR_SAMPLERATE_32	0x00000002	/* 32kHz sample rate					*/
@@ -494,10 +480,16 @@
 #define ADCCR_SAMPLERATE_11	0x00000006	/* 11.025kHz sample rate				*/
 #define ADCCR_SAMPLERATE_8	0x00000007	/* 8kHz sample rate					*/
 
+#define A_ADCCR_SAMPLERATE_12	0x00000006	/* 12kHz sample rate					*/
+#define A_ADCCR_SAMPLERATE_11	0x00000007	/* 11.025kHz sample rate				*/
+#define A_ADCCR_SAMPLERATE_8	0x00000008	/* 8kHz sample rate					*/
+
 #define FXWC			0x43		/* FX output write channels register			*/
 						/* When set, each bit enables the writing of the	*/
-						/* corresponding FX output channel into host memory	*/
-
+						/* corresponding FX output channel (internal registers  */
+						/* 0x20-0x3f) into host memory. This mode of recording	*/
+						/* is 16bit, 48KHz only. All 32	channels can be enabled */
+						/* simultaneously.					*/
 #define TCBS			0x44		/* Tank cache buffer size register			*/
 #define TCBS_MASK		0x00000007	/* Tank cache buffer size field				*/
 #define TCBS_BUFFSIZE_16K	0x00000000
@@ -565,8 +557,25 @@
 
 #define DBG			0x52		/* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
 
+/* definitions for debug register - taken from the alsa drivers */
+#define DBG_ZC                  0x80000000      /* zero tram counter */
+#define DBG_SATURATION_OCCURED  0x02000000      /* saturation control */
+#define DBG_SATURATION_ADDR     0x01ff0000      /* saturation address */
+#define DBG_SINGLE_STEP         0x00008000      /* single step mode */
+#define DBG_STEP                0x00004000      /* start single step */
+#define DBG_CONDITION_CODE      0x00003e00      /* condition code */
+#define DBG_SINGLE_STEP_ADDR    0x000001ff      /* single step address */
+
+
 #define REG53			0x53		/* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
 
+#define A_DBG			 0x53
+#define A_DBG_SINGLE_STEP	 0x00020000	/* Set to zero to start dsp */
+#define A_DBG_ZC		 0x40000000	/* zero tram counter */
+#define A_DBG_STEP_ADDR		 0x000003ff
+#define A_DBG_SATURATION_OCCURED 0x20000000
+#define A_DBG_SATURATION_ADDR	 0x0ffc0000
+
 #define SPCS0			0x54		/* SPDIF output Channel Status 0 register	*/
 
 #define SPCS1			0x55		/* SPDIF output Channel Status 1 register	*/
@@ -613,6 +622,10 @@
 #define SPBYPASS		0x5e		/* SPDIF BYPASS mode register			*/
 #define SPBYPASS_ENABLE		0x00000001	/* Enable SPDIF bypass mode			*/
 
+#define AC97SLOT		0x5f		/* additional AC97 slots enable bits */
+#define AC97SLOT_CNTR		0x10		/* Center enable */
+#define AC97SLOT_LFE		0x20		/* LFE enable */
+
 #define CDSRCS			0x60		/* CD-ROM Sample Rate Converter status register	*/
 
 #define GPSRCS			0x61		/* General Purpose SPDIF sample rate cvt status */
@@ -626,10 +639,19 @@
 #define SRCS_RATELOCKED		0x01000000	/* Sample rate locked				*/
 #define SRCS_ESTSAMPLERATE	0x0007ffff	/* Do not modify this field.			*/
 
+
+/* Note that these values can vary +/- by a small amount                                        */
+#define SRCS_SPDIFRATE_44	0x0003acd9
+#define SRCS_SPDIFRATE_48	0x00040000
+#define SRCS_SPDIFRATE_96	0x00080000
+
 #define MICIDX                  0x63            /* Microphone recording buffer index register   */
 #define MICIDX_MASK             0x0000ffff      /* 16-bit value                                 */
 #define MICIDX_IDX		0x10000063
 
+#define A_ADCIDX		0x63
+#define A_ADCIDX_IDX		0x10000063
+
 #define ADCIDX			0x64		/* ADC recording buffer index register		*/
 #define ADCIDX_MASK		0x0000ffff	/* 16 bit index field				*/
 #define ADCIDX_IDX		0x10000064
@@ -638,9 +660,50 @@
 #define FXIDX_MASK		0x0000ffff	/* 16-bit value					*/
 #define FXIDX_IDX		0x10000065
 
+/* This is the MPU port on the card (via the game port)						*/
+#define A_MUDATA1		0x70
+#define A_MUCMD1		0x71
+#define A_MUSTAT1		A_MUCMD1
+
+/* This is the MPU port on the Audigy Drive 							*/
+#define A_MUDATA2		0x72
+#define A_MUCMD2		0x73
+#define A_MUSTAT2		A_MUCMD2	
+
+/* The next two are the Audigy equivalent of FXWC						*/
+/* the Audigy can record any output (16bit, 48kHz, up to 64 channel simultaneously) 		*/
+/* Each bit selects a channel for recording */
+#define A_FXWC1			0x74            /* Selects 0x7f-0x60 for FX recording           */
+#define A_FXWC2			0x75		/* Selects 0x9f-0x80 for FX recording           */
+
+#define A_SPDIF_SAMPLERATE	0x76		/* Set the sample rate of SPDIF output		*/
+#define A_SPDIF_48000		0x00000080
+#define A_SPDIF_44100		0x00000000
+#define A_SPDIF_96000		0x00000040
+
+#define A_FXRT2			0x7c
+#define A_FXRT_CHANNELE		0x0000003f	/* Effects send bus number for channel's effects send E	*/
+#define A_FXRT_CHANNELF		0x00003f00	/* Effects send bus number for channel's effects send F	*/
+#define A_FXRT_CHANNELG		0x003f0000	/* Effects send bus number for channel's effects send G	*/
+#define A_FXRT_CHANNELH		0x3f000000	/* Effects send bus number for channel's effects send H	*/
+
+#define A_SENDAMOUNTS		0x7d
+#define A_FXSENDAMOUNT_E_MASK	0xff000000
+#define A_FXSENDAMOUNT_F_MASK	0x00ff0000
+#define A_FXSENDAMOUNT_G_MASK	0x0000ff00
+#define A_FXSENDAMOUNT_H_MASK	0x000000ff
+
+/* The send amounts for this one are the same as used with the emu10k1 */
+#define A_FXRT1			0x7e
+#define A_FXRT_CHANNELA		0x0000003f
+#define A_FXRT_CHANNELB		0x00003f00
+#define A_FXRT_CHANNELC		0x003f0000
+#define A_FXRT_CHANNELD		0x3f000000
+
+
 /* Each FX general purpose register is 32 bits in length, all bits are used			*/
 #define FXGPREGBASE		0x100		/* FX general purpose registers base       	*/
-
+#define A_FXGPREGBASE		0x400		/* Audigy GPRs, 0x400 to 0x5ff			*/
 /* Tank audio data is logarithmically compressed down to 16 bits before writing to TRAM and is	*/
 /* decompressed back to 20 bits on a read.  There are a total of 160 locations, the last 32	*/
 /* locations are for external TRAM. 								*/
@@ -665,10 +728,13 @@
 #define HIWORD_RESULT_MASK	0x000ffc00	/* Instruction result				*/
 #define HIWORD_OPA_MASK		0x000003ff	/* Instruction operand A			*/
 
-#define ENABLE 			0xffffffff
-#define DISABLE 		0x00000000
 
-#define ENV_ON			0x80
-#define ENV_OFF			0x00
+/* Audigy Soundcard have a different instruction format */
+#define AUDIGY_CODEBASE		0x600
+#define A_LOWORD_OPY_MASK	0x000007ff		
+#define A_LOWORD_OPX_MASK	0x007ff000
+#define A_HIWORD_OPCODE_MASK	0x0f000000
+#define A_HIWORD_RESULT_MASK	0x007ff000
+#define A_HIWORD_OPA_MASK	0x000007ff
 
 #endif /* EMU10K1_H */

Index: sys/gnu/dev/sound/pci/emu10k1-ac97.h
===================================================================
RCS file: sys/gnu/dev/sound/pci/emu10k1-ac97.h
diff -N sys/gnu/dev/sound/pci/emu10k1-ac97.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/gnu/dev/sound/pci/emu10k1-ac97.h	18 Apr 2003 14:08:06 -0000
@@ -0,0 +1,191 @@
+#ifndef _EMU10K1_AC97_H_
+#define _EMU10K1_AC97_H_
+
+/*********************************************/
+/* emu10k1-ac97.h, derived from ac97_codec.h */
+/*********************************************/
+
+/********************************************************************************************************/
+/* AC97 pointer-offset register set, accessed through the AC97ADDRESS and AC97DATA registers           */
+/********************************************************************************************************/
+
+
+
+/* AC97 1.0 */
+#define  AC97_RESET               0x0000      /* */
+#define  AC97_MASTER_VOL_STEREO   0x0002      /* Line Out */
+#define  AC97_HEADPHONE_VOL       0x0004      /* */ 
+#define  AC97_MASTER_VOL_MONO     0x0006      /* TAD Output */
+#define  AC97_MASTER_TONE         0x0008      /* */
+#define  AC97_PCBEEP_VOL          0x000a      /* none */
+#define  AC97_PHONE_VOL           0x000c      /* TAD Input (mono) */
+#define  AC97_MIC_VOL             0x000e      /* MIC Input (mono) */
+#define  AC97_LINEIN_VOL          0x0010      /* Line Input (stereo) */
+#define  AC97_CD_VOL              0x0012      /* CD Input (stereo) */
+#define  AC97_VIDEO_VOL           0x0014      /* none */
+#define  AC97_AUX_VOL             0x0016      /* Aux Input (stereo) */
+#define  AC97_PCMOUT_VOL          0x0018      /* Wave Output (stereo) */
+#define  AC97_RECORD_SELECT       0x001a      /* */
+#define  AC97_RECORD_GAIN         0x001c
+#define  AC97_RECORD_GAIN_MIC     0x001e
+#define  AC97_GENERAL_PURPOSE     0x0020
+#define  AC97_3D_CONTROL          0x0022
+#define  AC97_MODEM_RATE          0x0024
+#define  AC97_POWER_CONTROL       0x0026
+
+/* AC'97 2.0 */
+#define AC97_EXTENDED_ID          0x0028       /* Extended Audio ID */
+#define AC97_EXTENDED_STATUS      0x002A       /* Extended Audio Status */
+#define AC97_PCM_FRONT_DAC_RATE   0x002C       /* PCM Front DAC Rate */
+#define AC97_PCM_SURR_DAC_RATE    0x002E       /* PCM Surround DAC Rate */
+#define AC97_PCM_LFE_DAC_RATE     0x0030       /* PCM LFE DAC Rate */
+#define AC97_PCM_LR_ADC_RATE      0x0032       /* PCM LR DAC Rate */
+#define AC97_PCM_MIC_ADC_RATE     0x0034       /* PCM MIC ADC Rate */
+#define AC97_CENTER_LFE_MASTER    0x0036       /* Center + LFE Master Volume */
+#define AC97_SURROUND_MASTER      0x0038       /* Surround (Rear) Master Volume */
+#define AC97_RESERVED_3A          0x003A       /* Reserved in AC '97 < 2.2 */
+
+/* AC'97 2.2 */
+#define AC97_SPDIF_CONTROL        0x003A       /* S/PDIF Control */
+
+/* range 0x3c-0x58 - MODEM */
+#define AC97_EXTENDED_MODEM_ID    0x003C
+#define AC97_EXTEND_MODEM_STAT    0x003E
+#define AC97_LINE1_RATE           0x0040
+#define AC97_LINE2_RATE           0x0042
+#define AC97_HANDSET_RATE         0x0044
+#define AC97_LINE1_LEVEL          0x0046
+#define AC97_LINE2_LEVEL          0x0048
+#define AC97_HANDSET_LEVEL        0x004A
+#define AC97_GPIO_CONFIG          0x004C
+#define AC97_GPIO_POLARITY        0x004E
+#define AC97_GPIO_STICKY          0x0050
+#define AC97_GPIO_WAKE_UP         0x0052
+#define AC97_GPIO_STATUS          0x0054
+#define AC97_MISC_MODEM_STAT      0x0056
+#define AC97_RESERVED_58          0x0058
+
+/* registers 0x005a - 0x007a are vendor reserved */
+
+#define AC97_VENDOR_ID1           0x007c
+#define AC97_VENDOR_ID2           0x007e
+
+/* volume control bit defines */
+#define AC97_MUTE                 0x8000
+#define AC97_MICBOOST             0x0040
+#define AC97_LEFTVOL              0x3f00
+#define AC97_RIGHTVOL             0x003f
+
+/* record mux defines */
+#define AC97_RECMUX_MIC           0x0000
+#define AC97_RECMUX_CD            0x0101
+#define AC97_RECMUX_VIDEO         0x0202
+#define AC97_RECMUX_AUX           0x0303
+#define AC97_RECMUX_LINE          0x0404
+#define AC97_RECMUX_STEREO_MIX    0x0505
+#define AC97_RECMUX_MONO_MIX      0x0606
+#define AC97_RECMUX_PHONE         0x0707
+
+/* general purpose register bit defines */
+#define AC97_GP_LPBK              0x0080       /* Loopback mode */
+#define AC97_GP_MS                0x0100       /* Mic Select 0=Mic1, 1=Mic2 */
+#define AC97_GP_MIX               0x0200       /* Mono output select 0=Mix, 1=Mic */
+#define AC97_GP_RLBK              0x0400       /* Remote Loopback - Modem line codec */
+#define AC97_GP_LLBK              0x0800       /* Local Loopback - Modem Line codec */
+#define AC97_GP_LD                0x1000       /* Loudness 1=on */
+#define AC97_GP_3D                0x2000       /* 3D Enhancement 1=on */
+#define AC97_GP_ST                0x4000       /* Stereo Enhancement 1=on */
+#define AC97_GP_POP               0x8000       /* Pcm Out Path, 0=pre 3D, 1=post 3D */
+
+/* extended audio status and control bit defines */
+#define AC97_EA_VRA               0x0001       /* Variable bit rate enable bit */
+#define AC97_EA_DRA               0x0002       /* Double-rate audio enable bit */
+#define AC97_EA_SPDIF             0x0004       /* S/PDIF Enable bit */
+#define AC97_EA_VRM               0x0008       /* Variable bit rate for MIC enable bit */
+#define AC97_EA_CDAC              0x0040       /* PCM Center DAC is ready (Read only) */
+#define AC97_EA_SDAC              0x0040       /* PCM Surround DACs are ready (Read only) */
+#define AC97_EA_LDAC              0x0080       /* PCM LFE DAC is ready (Read only) */
+#define AC97_EA_MDAC              0x0100       /* MIC ADC is ready (Read only) */
+#define AC97_EA_SPCV              0x0400       /* S/PDIF configuration valid (Read only) */
+#define AC97_EA_PRI               0x0800       /* Turns the PCM Center DAC off */
+#define AC97_EA_PRJ               0x1000       /* Turns the PCM Surround DACs off */
+#define AC97_EA_PRK               0x2000       /* Turns the PCM LFE DAC off */
+#define AC97_EA_PRL               0x4000       /* Turns the MIC ADC off */
+#define AC97_EA_SLOT_MASK         0xffcf       /* Mask for slot assignment bits */
+#define AC97_EA_SPSA_3_4          0x0000       /* Slot assigned to 3 & 4 */
+#define AC97_EA_SPSA_7_8          0x0010       /* Slot assigned to 7 & 8 */
+#define AC97_EA_SPSA_6_9          0x0020       /* Slot assigned to 6 & 9 */
+#define AC97_EA_SPSA_10_11        0x0030       /* Slot assigned to 10 & 11 */
+
+/* S/PDIF control bit defines */
+#define AC97_SC_PRO               0x0001       /* Professional status */
+#define AC97_SC_NAUDIO            0x0002       /* Non audio stream */
+#define AC97_SC_COPY              0x0004       /* Copyright status */
+#define AC97_SC_PRE               0x0008       /* Preemphasis status */
+#define AC97_SC_CC_MASK           0x07f0       /* Category Code mask */
+#define AC97_SC_L                 0x0800       /* Generation Level status */
+#define AC97_SC_SPSR_MASK         0xcfff       /* S/PDIF Sample Rate bits */
+#define AC97_SC_SPSR_44K          0x0000       /* Use 44.1kHz Sample rate */
+#define AC97_SC_SPSR_48K          0x2000       /* Use 48kHz Sample rate */
+#define AC97_SC_SPSR_32K          0x3000       /* Use 32kHz Sample rate */
+#define AC97_SC_DRS               0x4000       /* Double Rate S/PDIF */
+#define AC97_SC_V                 0x8000       /* Validity status */
+
+/* powerdown control and status bit defines */
+
+/* status */
+#define AC97_PWR_MDM              0x0010       /* Modem section ready */
+#define AC97_PWR_REF              0x0008       /* Vref nominal */
+#define AC97_PWR_ANL              0x0004       /* Analog section ready */
+#define AC97_PWR_DAC              0x0002       /* DAC section ready */
+#define AC97_PWR_ADC              0x0001       /* ADC section ready */
+
+/* control */
+#define AC97_PWR_PR0              0x0100       /* ADC and Mux powerdown */
+#define AC97_PWR_PR1              0x0200       /* DAC powerdown */
+#define AC97_PWR_PR2              0x0400       /* Output mixer powerdown (Vref on) */
+#define AC97_PWR_PR3              0x0800       /* Output mixer powerdown (Vref off) */
+#define AC97_PWR_PR4              0x1000       /* AC-link powerdown */
+#define AC97_PWR_PR5              0x2000       /* Internal Clk disable */
+#define AC97_PWR_PR6              0x4000       /* HP amp powerdown */
+#define AC97_PWR_PR7              0x8000       /* Modem off - if supported */
+
+/* useful power states */
+#define AC97_PWR_D0               0x0000      /* everything on */
+#define AC97_PWR_D1              AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR4
+#define AC97_PWR_D2              AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4
+#define AC97_PWR_D3              AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4
+#define AC97_PWR_ANLOFF          AC97_PWR_PR2|AC97_PWR_PR3  /* analog section off */
+
+/* Total number of defined registers.  */
+#define AC97_REG_CNT 64
+
+
+/* OSS interface to the ac97s.. */
+#define AC97_STEREO_MASK (SOUND_MASK_VOLUME|SOUND_MASK_PCM|\
+	SOUND_MASK_LINE|SOUND_MASK_CD|\
+	SOUND_MASK_ALTPCM|SOUND_MASK_IGAIN|\
+	SOUND_MASK_LINE1|SOUND_MASK_VIDEO|SOUND_MASK_IMIX)
+
+#define AC97_SUPPORTED_MASK (AC97_STEREO_MASK | \
+	SOUND_MASK_BASS|SOUND_MASK_TREBLE|\
+	SOUND_MASK_SPEAKER|SOUND_MASK_MIC|\
+	SOUND_MASK_PHONEIN|SOUND_MASK_PHONEOUT)
+
+#define AC97_RECORD_MASK (SOUND_MASK_MIC|\
+	SOUND_MASK_CD|SOUND_MASK_IGAIN|SOUND_MASK_VIDEO|\
+	SOUND_MASK_LINE1| SOUND_MASK_LINE|\
+	SOUND_MASK_PHONEIN)
+
+/* original check is not good enough in case FOO is greater than
+ * SOUND_MIXER_NRDEVICES because the supported_mixers has exactly
+ * SOUND_MIXER_NRDEVICES elements.
+ * before matching the given mixer against the bitmask in supported_mixers we
+ * check if mixer number exceeds maximum allowed size which is as mentioned
+ * above SOUND_MIXER_NRDEVICES */
+#define supported_mixer(CODEC,FOO) ((FOO >= 0) && \
+                                    (FOO < SOUND_MIXER_NRDEVICES) && \
+                                    (CODEC)->supported_mixers & (1<<FOO) )
+
+
+#endif /* _EMU10K_AC97_H_ */

Index: sys/gnu/dev/sound/pci/emu10k1-alsa.h
===================================================================
RCS file: sys/gnu/dev/sound/pci/emu10k1-alsa.h
diff -N sys/gnu/dev/sound/pci/emu10k1-alsa.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/gnu/dev/sound/pci/emu10k1-alsa.h	21 Apr 2003 01:22:58 -0000
@@ -0,0 +1,322 @@
+/***********************************************************************
+ *
+ *     Date		    Author	     Summary of changes
+ *     ----		    ------	     ------------------
+ *     February 10, 2003    Orlando Bassotto Added Audigy registers
+ *                                           and opcode macros from
+ *                                           ALSA project emu10k1.h.
+ **********************************************************************/
+
+#define A_PTR_ADDRESS_MASK	0x0fff0000	/* Audigy register index			*/
+
+/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/
+#define A_IPR_MIDITRANSBUFEMPTY2 0x10000000	/* MIDI UART transmit buffer empty		*/
+#define A_IPR_MIDIRECVBUFEMPTY2 0x08000000	/* MIDI UART receive buffer empty		*/
+
+/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU2)			*/
+#define A_IPR_MIDITRANSBUFEMPTY1 IPR_MIDITRANSBUFEMPTY /* MIDI UART transmit buffer empty	*/
+#define A_IPR_MIDIRECVBUFEMPTY1 IPR_MIDIRECVBUFEMPTY /* MIDI UART receive buffer empty		*/
+
+/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/ 
+#define A_INTE_MIDITXENABLE2	0x00020000	/* Enable MIDI transmit-buffer-empty interrupts	*/
+#define A_INTE_MIDIRXENABLE2	0x00010000	/* Enable MIDI receive-buffer-empty interrupts	*/
+ 
+/* The next two interrupts are for the midi port on the Audigy (A_MPU2)				*/
+#define A_INTE_MIDITXENABLE1	INTE_MIDITXENABLE
+#define A_INTE_MIDIRXENABLE1	INTE_MIDIRXENABLE
+
+#define HCFG_GPOUT0		0x00001000	/* set to enable digital out on 5.1 cards	*/
+#define HCFG_GPOUT1		0x00000800	/* External pin (IR)				*/
+#define HCFG_GPOUT2		0x00000400	/* External pin (IR)				*/
+
+#define HCFG_AC3ENABLE_GPSPDIF	0x00000020    	/* Channels 0 and 1 replace GPSPDIF	          	*/
+ 
+#define A_IOCFG			0x18		/* GPIO on Audigy card (16bits)			*/
+#define A_IOCFG_GPOUT_MASK	0x00ff
+#define A_IOCFG_GPOUT_D		0x04		/* Digital Output				*/
+#define A_IOCFG_GPOUT_A		0x40		/* Analog Output				*/
+#define A_IOCFG_GPOUT_AD	(A_IOCFG_GPOUT_A|A_IOCFG_GPOUT_D)
+#define A_IOCFG_GPINPUT_MASK	0xff00
+
+#define TIMER			0x1a		/* Timer terminal count register (16-bit)	*/
+ 						/* NOTE: After the rate is changed, a maximum	*/
+ 						/* of 1024 sample periods should be allowed	*/
+ 						/* before the new rate is guaranteed accurate.	*/
+#define A_ADCCR_RCHANENABLE	0x00000020
+#define A_ADCCR_LCHANENABLE	0x00000010
+
+#define A_ADCCR_SAMPLERATE_MASK	0x0000000F	/* Audigy sample rate convertor output rate		*/
+ 
+#define A_ADCCR_SAMPLERATE_12	0x00000006	/* 12kHz sample rate					*/
+#define A_ADCCR_SAMPLERATE_11	0x00000007	/* 11.025kHz sample rate				*/
+#define A_ADCCR_SAMPLERATE_8	0x00000008	/* 8kHz sample rate					*/
+
+/* definitions for debug register - taken from the alsa drivers */
+#define DBG_ZC			0x80000000	/* zero tram counter */
+#define DBG_SATURATION_OCCURED	0x02000000	/* saturation control */
+#define DBG_SATURATION_ADDR	0x01ff0000	/* saturation address */
+#define DBG_SINGLE_STEP		0x00008000	/* single step mode */
+#define DBG_STEP		0x00004000	/* start single step */
+#define DBG_CONDITION_CODE	0x00003e00	/* condition code */
+#define DBG_SINGLE_STEP_ADDR	0x000001ff	/* single step address */
+
+#define A_DBG			 0x53
+#define A_DBG_SINGLE_STEP	 0x00020000	/* Set to zero to start dsp */
+#define A_DBG_ZC		 0x40000000	/* zero tram counter */
+#define A_DBG_STEP_ADDR		 0x000003ff
+#define A_DBG_SATURATION_OCCURED 0x20000000
+#define A_DBG_SATURATION_ADDR	 0x0ffc0000
+ 
+#define AC97SLOT		0x5f		/* additional AC97 slots enable bits */
+#define AC97SLOT_CNTR		0x10		/* Center enable */
+#define AC97SLOT_LFE		0x20		/* LFE enable */
+
+/* Note that these values can vary +/- by a small amount					*/
+#define SRCS_SPDIFRATE_44	0x0003acd9
+#define SRCS_SPDIFRATE_48	0x00040000
+#define SRCS_SPDIFRATE_96	0x00080000
+ 
+#define A_ADCIDX		0x63
+#define A_ADCIDX_IDX		0x10000063
+ 
+/* This is the MPU port on the card (via the game port)						*/
+#define A_MUDATA1		0x70
+#define A_MUCMD1		0x71
+#define A_MUSTAT1		A_MUCMD1
+
+/* This is the MPU port on the Audigy Drive							*/
+#define A_MUDATA2		0x72
+#define A_MUCMD2		0x73
+#define A_MUSTAT2		A_MUCMD2
+
+/* The next two are the Audigy equivalent of FXWC						*/
+/* the Audigy can record any output (16bit, 48kHz, up to 64 channel simultaneously)		*/
+/* Each bit selects a channel for recording */
+#define A_FXWC1			0x74		/* Selects 0x7f-0x60 for FX recording		*/
+#define A_FXWC2			0x75		/* Selects 0x9f-0x80 for FX recording		*/
+
+#define A_SPDIF_SAMPLERATE	0x76		/* Set the sample rate of SPDIF output		*/
+#define A_SPDIF_48000		0x00000080
+#define A_SPDIF_44100		0x00000000
+#define A_SPDIF_96000		0x00000040
+
+#define A_FXRT2			0x7c
+#define A_FXRT_CHANNELE		0x0000003f	/* Effects send bus number for channel's effects send E	*/
+#define A_FXRT_CHANNELF		0x00003f00	/* Effects send bus number for channel's effects send F	*/
+#define A_FXRT_CHANNELG		0x003f0000	/* Effects send bus number for channel's effects send G	*/
+#define A_FXRT_CHANNELH		0x3f000000	/* Effects send bus number for channel's effects send H	*/
+
+#define A_SENDAMOUNTS		0x7d
+#define A_FXSENDAMOUNT_E_MASK	0xff000000
+#define A_FXSENDAMOUNT_F_MASK	0x00ff0000
+#define A_FXSENDAMOUNT_G_MASK	0x0000ff00
+#define A_FXSENDAMOUNT_H_MASK	0x000000ff
+
+/* The send amounts for this one are the same as used with the emu10k1 */
+#define A_FXRT1			0x7e
+#define A_FXRT_CHANNELA		0x0000003f
+#define A_FXRT_CHANNELB		0x00003f00
+#define A_FXRT_CHANNELC		0x003f0000
+#define A_FXRT_CHANNELD		0x3f000000
+
+#define A_FXGPREGBASE		0x400		/* Audigy GPRs, 0x400 to 0x5ff			*/
+
+/* Audigy Soundcard have a different instruction format */
+#define AUDIGY_CODEBASE		0x600
+#define A_LOWORD_OPY_MASK	0x000007ff
+#define A_LOWORD_OPX_MASK	0x007ff000
+#define A_HIWORD_OPCODE_MASK	0x0f000000
+#define A_HIWORD_RESULT_MASK	0x007ff000
+#define A_HIWORD_OPA_MASK	0x000007ff
+
+/* Opcodes macros -- Based on ALSA emu10k1.h */
+
+/* FX8010/EMU10K1/EMU10K2 Instruction set */
+#define iMAC0			0x00		/* R = A + (X * Y >> 31)   ; saturation */
+#define iMAC1			0x01		/* R = A + (-X * Y >> 31)  ; saturation */
+#define iMAC2			0x02		/* R = A + (X * Y >> 31)   ; wraparound */
+#define iMAC3			0x03		/* R = A + (-X * Y >> 31)  ; wraparound */
+#define iMACINT0		0x04		/* R = A + X * Y	   ; saturation */
+#define iMACINT1		0x05		/* R = A + X * Y	   ; wraparound (31-bit) */
+#define iACC3			0x06		/* R = A + X + Y	   ; saturation */
+#define iMACMV			0x07		/* R = A, acc += X * Y >> 31 */
+#define iANDXOR			0x08		/* R = (A & X) ^ Y */
+#define iTSTNEG			0x09		/* R = (A >= Y) ? X : ~X */
+#define iLIMITGE		0x0a		/* R = (A >= Y) ? X : Y */
+#define iLIMITLT		0x0b		/* R = (A < Y) ? X : Y */
+#define iLOG			0x0c		/* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
+#define iEXP			0x0d		/* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
+#define iINTERP			0x0e		/* R = A + (X * (Y - A) >> 31)  ; saturation */
+#define iSKIP			0x0f		/* R = A (cc_reg), X (count), Y (cc_test) */
+
+/* FX8010 opcode macros */
+#define FXBUS(x)		(0x00 + (x))	/* x = 0x00 - 0x0f */
+#define EXTIN(x)		(0x10 + (x))	/* x = 0x00 - 0x0f */
+#define EXTOUT(x)		(0x20 + (x))	/* x = 0x00 - 0x0f */
+#define GPR(x)			(FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
+#define ITRAM_DATA(x)		(TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_DATA(x)		(TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+#define ITRAM_ADDR(x)		(TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_ADDR(x)		(TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+
+/* FX8010 Constants */
+#define C_00000000		0x40
+#define C_00000001		0x41
+#define C_00000002		0x42
+#define C_00000003		0x43
+#define C_00000004		0x44
+#define C_00000008		0x45
+#define C_00000010		0x46
+#define C_00000020		0x47
+#define C_00000100		0x48
+#define C_00010000		0x49
+#define C_00080000		0x4a
+#define C_10000000		0x4b
+#define C_20000000		0x4c
+#define C_40000000		0x4d
+#define C_80000000		0x4e
+#define C_7fffffff		0x4f
+#define C_ffffffff		0x50
+#define C_fffffffe		0x51
+#define C_c0000000		0x52
+#define C_4f1bbcdc		0x53
+#define C_5a7ef9db		0x54
+#define C_00100000		0x55		/* ?? */
+
+/* FX8010 FX Send Bus Registers */
+#define FXBUS_PCM_LEFT		0x00
+#define FXBUS_PCM_RIGHT		0x01
+#define FXBUS_PCM_LEFT_REAR	0x02
+#define FXBUS_PCM_RIGHT_REAR	0x03
+#define FXBUS_MIDI_LEFT		0x04
+#define FXBUS_MIDI_RIGHT	0x05
+#define FXBUS_PCM_CENTER	0x06
+#define FXBUS_PCM_LFE		0x07
+#define FXBUS_MIDI_REVERB	0x0c
+#define FXBUS_MIDI_CHORUS	0x0d
+
+/* FX8010 GPRs */
+#define GPR_ACCU		0x56		/* ACCUM, accumulator */
+#define GPR_COND		0x57		/* CCR, condition register */
+#define GPR_NOISE0		0x58		/* noise source */
+#define GPR_NOISE1		0x59		/* noise source */
+#define GPR_IRQ			0x5a		/* IRQ register */
+#define GPR_DBAC		0x5b		/* TRAM Delay Base Address Counter */
+
+/* FX8010 Inputs */
+#define EXTIN_AC97_L		0x00		/* AC'97 capture channel - left */
+#define EXTIN_AC97_R		0x01		/* AC'97 capture channel - right */
+#define EXTIN_SPDIF_CD_L	0x02		/* internal S/PDIF CD - onboard - left */
+#define EXTIN_SPDIF_CD_R	0x03		/* internal S/PDIF CD - onboard - right */
+#define EXTIN_ZOOM_L		0x04		/* Zoom Video I2S - left */
+#define EXTIN_ZOOM_R		0x05		/* Zoom Video I2S - right */
+#define EXTIN_TOSLINK_L		0x06		/* LiveDrive - TOSLink Optical - left */
+#define EXTIN_TOSLINK_R		0x07		/* LiveDrive - TOSLink Optical - right */
+#define EXTIN_LINE1_L		0x08		/* LiveDrive - Line/Mic 1 - left */
+#define EXTIN_LINE1_R		0x09		/* LiveDrive - Line/Mic 1 - right */
+#define EXTIN_COAX_SPDIF_L	0x0a		/* LiveDrive - Coaxial S/PDIF - left */
+#define EXTIN_COAX_SPDIF_R	0x0b		/* LiveDrive - Coaxial S/PDIF - right */
+#define EXTIN_LINE2_L		0x0c		/* LiveDrive - Line/Mic 2 - left */
+#define EXTIN_LINE2_R		0x0d		/* LiveDrive - Line/Mic 2 - right */
+
+/* FX8010 Outputs */
+#define EXTOUT_AC97_L		0x00		/* AC'97 playback channel - left */
+#define EXTOUT_AC97_R		0x01		/* AC'97 playback channel - right */
+#define EXTOUT_TOSLINK_L	0x02		/* LiveDrive - TOSLink Optical - left */
+#define EXTOUT_TOSLINK_R	0x03		/* LiveDrive - TOSLink Optical - right */
+#define EXTOUT_CENTER		0x04		/* SB Live 5.1 - center */
+#define EXTOUT_LFE		0x05 		/* SB Live 5.1 - LFE */
+#define EXTOUT_HEADPHONE_L	0x06		/* LiveDrive - Headphone - left */
+#define EXTOUT_HEADPHONE_R	0x07		/* LiveDrive - Headphone - right */
+#define EXTOUT_REAR_L		0x08		/* Rear channel - left */
+#define EXTOUT_REAR_R		0x09		/* Rear channel - right */
+#define EXTOUT_ADC_CAP_L	0x0a		/* ADC Capture buffer - left */
+#define EXTOUT_ADC_CAP_R	0x0b		/* ADC Capture buffer - right */
+#define EXTOUT_MIC_CAP		0x0c		/* MIC Capture buffer */
+#define EXTOUT_ACENTER		0x11		/* Analog Center */
+#define EXTOUT_ALFE		0x12		/* Analog LFE */
+
+/* Audigy opcode macros */
+#define A_FXBUS(x)		((x) + 0x00)
+#define A_EXTIN(x)		((x) + 0x40)
+#define A_EXTOUT(x)		((x) + 0x60)
+#define A_GPR(x)		((x) + A_FXGPREGBASE)
+
+/* Audigy constants */
+#define A_C_00000000		0xc0
+#define A_C_00000001		0xc1
+#define A_C_00000002		0xc2
+#define A_C_00000003		0xc3
+#define A_C_00000004		0xc4
+#define A_C_00000008		0xc5
+#define A_C_00000010		0xc6
+#define A_C_00000020		0xc7
+#define A_C_00000100		0xc8
+#define A_C_00010000		0xc9
+#define A_C_00000800		0xca
+#define A_C_10000000		0xcb
+#define A_C_20000000		0xcc
+#define A_C_40000000		0xcd
+#define A_C_80000000		0xce
+#define A_C_7fffffff		0xcf
+#define A_C_ffffffff		0xd0
+#define A_C_fffffffe		0xd1
+#define A_C_c0000000		0xd2
+#define A_C_4f1bbcdc		0xd3
+#define A_C_5a7ef9db		0xd4
+#define A_C_00100000		0xd5
+
+/* Audigy FX Send Bus Registers */
+#define A_FXBUS_PCM_LEFT	FXBUS_PCM_LEFT
+#define A_FXBUS_PCM_RIGHT	FXBUS_PCM_RIGHT
+#define A_FXBUS_PCM_LEFT_REAR	FXBUS_PCM_LEFT_REAR
+#define A_FXBUS_PCM_RIGHT_REAR	FXBUS_PCM_RIGHT_REAR
+#define A_FXBUS_MIDI_LEFT	FXBUS_MIDI_LEFT
+#define A_FXBUS_MIDI_RIGHT	FXBUS_MIDI_RIGHT
+#define A_FXBUS_PCM_CENTER	FXBUS_PCM_CENTER
+#define A_FXBUS_PCM_LFE		FXBUS_PCM_LFE
+#define A_FXBUS_MIDI_REVERB	FXBUS_MIDI_REVERB
+#define A_FXBUS_MIDI_CHORUS	FXBUS_MIDI_CHORUS
+
+#define A_GPR_ACCU		0xd6 		/* 0xd6 = 0x7fffffff  (?) ACCUM? */
+#define A_GPR_COND		0xd7		/* 0xd7 = 0x0000000   CCR */
+#define A_GPR_NOISE0		0xd8		/* 0xd8 = noise1 */
+#define A_GPR_NOISE1		0xd9		/* 0xd9 = noise2 */
+#define A_GPR_IRQ		0xda		/* IRQ register */
+#define A_GPR_DBAC		0xdb		/* TRAM Delay Base Address Counter */
+
+/* Audigy Inputs */
+#define A_EXTIN_AC97_L		0x00		/* AC'97 capture channel - left */
+#define A_EXTIN_AC97_R		0x01		/* AC'97 capture channel - right */
+#define A_EXTIN_SPDIF_CD_L	0x02		/* digital CD left */
+#define A_EXTIN_SPDIF_CD_R	0x03		/* digital CD left */
+#define A_EXTIN_OPT_SPDIF_L	0x04		/* audigy drive Optical SPDIF - left */
+#define A_EXTIN_OPT_SPDIF_R	0x05		/*                              right */ 
+#define A_EXTIN_LINE2_L		0x08		/* audigy drive line2/mic2 - left */
+#define A_EXTIN_LINE2_R		0x09		/*                           right */
+#define A_EXTIN_RCA_SPDIF_L	0x0a		/* audigy drive RCA SPDIF - left */
+#define A_EXTIN_RCA_SPDIF_R	0x0b		/*                          right */
+#define A_EXTIN_AUX2_L		0x0c		/* audigy drive aux2 - left */
+#define A_EXTIN_AUX2_R		0x0d		/*                   - right */
+
+/* Audigy Outputs */
+#define A_EXTOUT_FRONT_L	0x00		/* digital front left */
+#define A_EXTOUT_FRONT_R	0x01		/*               right */
+#define A_EXTOUT_CENTER		0x02		/* digital front center */
+#define A_EXTOUT_LFE		0x03		/* digital front lfe */
+#define A_EXTOUT_HEADPHONE_L	0x04		/* headphone audigy drive left */
+#define A_EXTOUT_HEADPHONE_R	0x05		/*                        right */
+#define A_EXTOUT_REAR_L		0x06		/* digital rear left */
+#define A_EXTOUT_REAR_R		0x07		/*              right */
+#define A_EXTOUT_AFRONT_L	0x08		/* analog front left */
+#define A_EXTOUT_AFRONT_R	0x09		/*              right */
+#define A_EXTOUT_ACENTER	0x0a		/* analog center */
+#define A_EXTOUT_ALFE		0x0b		/* analog LFE */
+/* 0x0c ?? */
+/* 0x0d ?? */
+#define A_EXTOUT_AREAR_L	0x0e		/* analog rear left */
+#define A_EXTOUT_AREAR_R	0x0f		/*             right */
+#define A_EXTOUT_AC97_L		0x10		/* AC97 left (front) */
+#define A_EXTOUT_AC97_R		0x11		/*      right */
+#define A_EXTOUT_ADC_CAP_L	0x16		/* ADC capture buffer left */
+#define A_EXTOUT_ADC_CAP_R	0x17		/*                    right */



More information about the freebsd-multimedia mailing list