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

David O'Brien obrien at NUXI.com
Sun Apr 20 17:48:00 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 
> combining the contributions.  The latest patch is available at:
> 
> 	http://mad.ieo-research.it/freebsd/drivers/emu10k1/

I don't want to seem ungrateful for this work, but the problem is, it
currently isn't committable.

This work is based off of emu10k1.c rev 1.28 from 2002/11/26.
Also the diffs should be as minimal as possible.  Things like this
shouldn't be in the diff:

    -#define EMU10K1_PCI_ID  0x00021102
    -#define EMU10K2_PCI_ID  0x00041102
    +#define EMU10K1_PCI_ID          0x00021102
    +#define EMU10K2_PCI_ID          0x00041102

     emu_rdptr(struct sc_info *sc, int chn, int reg)
      {
      -        u_int32_t ptr, val, mask, size, offset;
      +        u_int32_t ptr, val, mask, size, offset;


These changes are gratiutious.
Also emu10k1tone.h is undocumented where it comes from.

Until cg has a chance to be active in emu10k1 development again, I'd
perfer to see something that doesn't abstract out bits from emu10k1.c
into new headers as it makes the diffs larger, and harder to review by
those less knowledgeable as cg.  At least I'm willing to shepard this
work into the CVS repo in such a form.

I hope the goal is to get this work committed into the FreeBSD CVS
repository.  Attached is emu10k-01-March-2003-cvs.tar.bz2 in a reviewable
and committable fashion.

-- David
-------------- next part --------------
Index: sys/dev/sound/pci/emu10k1.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sound/pci/emu10k1.c,v
retrieving revision 1.36
diff -u -r1.36 emu10k1.c
--- sys/dev/sound/pci/emu10k1.c	20 Apr 2003 08:37:29 -0000	1.36
+++ sys/dev/sound/pci/emu10k1.c	20 Apr 2003 09:05:38 -0000
@@ -27,14 +27,26 @@
 #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 <pci/pcireg.h>
 #include <pci/pcivar.h>
 #include <sys/queue.h>
+#include <sys/sysctl.h>
+#include "mixer_if.h"
 
 SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/emu10k1.c,v 1.36 2003/04/20 08:37:29 obrien Exp $");
 
-/* -------------------------------------------------------------------- */
+#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	EMU10K1_PCI_ID	0x00021102
 #define	EMU10K2_PCI_ID	0x00041102
@@ -42,6 +54,11 @@
 #define	EMU_CHANS	4
 #undef EMUDEBUG
 
+#define	ENABLE		0xffffffff
+#define	DISABLE		0x00000000
+#define	ENV_ON		0x80
+#define	ENV_OFF		0x00
+
 struct emu_memblk {
 	SLIST_ENTRY(emu_memblk) link;
 	void *buf;
@@ -87,11 +104,23 @@
 	struct sc_info *parent;
 };
 
+struct sc_waveio {
+	u_int32_t send_routing[1];
+	u_int32_t send_routing2[1];
+	u_int32_t send_dcba[3];
+	u_int32_t send_hgfe[3];
+};
+
+#define	ROUTE_PCM0 0
+#define	SEND_MONO 0
+#define	SEND_LEFT 1
+#define	SEND_RIGHT 2
+
 /* device private data */
 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, is_audigy:1;
 
 	bus_space_tag_t st;
 	bus_space_handle_t sh;
@@ -101,6 +130,20 @@
 	void		*ih;
 	struct mtx	*lock;
 
+	struct ac97_info *codec;
+
+	struct sc_waveio waveio;
+	unsigned int mchannel_fx;
+	unsigned int dsp_zero;
+	unsigned int code_base;
+	unsigned int code_size;
+	unsigned int gpr_base;
+	unsigned int num_gprs;
+	unsigned int input_base;
+	unsigned int output_base;
+	unsigned int opcode_shift;
+	unsigned int high_operand_shift;
+
 	unsigned int bufsz;
 	int timer, timerinterval;
 	int pnum, rnum;
@@ -132,7 +175,9 @@
 static void emu_wr(struct sc_info *, int, u_int32_t, int);
 
 /* -------------------------------------------------------------------- */
+static struct sc_info *ctl_sc_info;
 
+/* Recording formats supported: */
 static u_int32_t emu_rfmt_ac97[] = {
 	AFMT_S16_LE,
 	AFMT_STEREO | AFMT_S16_LE,
@@ -149,12 +194,14 @@
 	0
 };
 
+/* Recording capabilites */
 static struct pcmchan_caps emu_reccaps[3] = {
 	{8000, 48000, emu_rfmt_ac97, 0},
 	{8000, 8000, emu_rfmt_mic, 0},
 	{48000, 48000, emu_rfmt_efx, 0},
 };
 
+/* Playback formats */
 static u_int32_t emu_pfmt[] = {
 	AFMT_U8,
 	AFMT_STEREO | AFMT_U8,
@@ -163,10 +210,28 @@
 	0
 };
 
+/* Playback capabilites */
 static struct pcmchan_caps emu_playcaps = {4000, 48000, emu_pfmt, 0};
 
 static int adcspeed[8] = {48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000};
 
+/* Mixer */
+
+#define MIXER_FX 1
+#define MIXER_AC97 2
+
+#define MIXER_PLAYBACKOUNLY 0
+#define MIXER_CANRECORD 0
+
+struct emu10k1mixer_entry {
+	unsigned mixer_source:2;
+	unsigned is_recording:1;
+};
+
+static const struct emu10k1mixer_entry emu10k1mixer[SOUND_MIXER_NRDEVICES] = {
+	[SOUND_MIXER_VOLUME] = {MIXER_FX, MIXER_PLAYBACKOUNLY}
+};
+
 /* -------------------------------------------------------------------- */
 /* Hardware */
 static u_int32_t
@@ -239,10 +304,11 @@
 static void
 emu_wrefx(struct sc_info *sc, unsigned int pc, unsigned int data)
 {
-	emu_wrptr(sc, 0, MICROCODEBASE + pc, data);
+	emu_wrptr(sc, 0, sc->code_base + pc, data);
 }
 
 /* -------------------------------------------------------------------- */
+static void emumix_set_fxvol(struct sc_info *sc, unsigned gpr, int32_t vol);
 /* ac97 codec */
 /* no locking needed */
 
@@ -259,7 +325,92 @@
 emu_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
 {
 	struct sc_info *sc = (struct sc_info *)devinfo;
+	u_int32_t left, right;
+
+	if (sc->is_audigy){
+		/*
+		* hack to always get AC97 sound on Audigy
+		* should be converted to some kind of AC97 chip emulation
+		* and present EMU10K2 chip capabilites throuth
+		* AC97 "extended capabilites" register
+		*/
+		switch (regno) {
+		case 0x02: /* MAIN OUT */
+		/*
+		* MAIN OUT volume on AC97 is alwayz zero
+		* because AC97 is not connected to outs
+		* use emumix_setfxvol to set MAIN OUT volume
+		*/
+			left = (data & 0x3f00) >> 8;
+			right = data & 0x003f;
+			if (data & 0x8000)
+				left = right = 0x1f; /* mute */
+			if (left == 0 && right==0x3f)
+				break;
+			left = 100 - left * 100 / (0x1f); /* 4 bit */
+			right = 100 - right * 100 / (0x1f);
+			/* 0x12/0x13 are MAIN volume, controlled by vol */
+			emumix_set_fxvol(sc, 0x12, left);
+			emumix_set_fxvol(sc, 0x13, right);
 
+			break;
+		case 0x18: /* PCM OUT VOL */
+		/*
+		* PCM volume on AC97 should stay muted,
+		* use emumix_setfxvol to set PCM volume from FX0
+		* If PCM volume is muted, then front PCM output is done
+		* by better 6-ch Philips chip
+		*/
+			left = (data & 0x3f00)>>8;
+			right = data & 0x003f;
+			if (data & 0x8000)
+				left=right=0x1f; /* mute */
+			if (left == 0 && right==0x3f)
+				break;
+			left = 100 - left * 100 / (0x1f); /* 4 bit */
+			right = 100 - right * 100 / (0x1f);
+			/* 0x10/0x11 are PCM controls */
+			emumix_set_fxvol(sc, 0x10, left);
+			emumix_set_fxvol(sc, 0x11, right);
+		/*  */
+			data = 0x8000;
+			break;
+		case 0x1a:
+		/*
+		* PCM recording source is set to "stereo mix"
+		* (labeled "vol" in mixer)
+		*/
+			data = 0x0505;
+			break;
+		case 0x1c: /* RECORD GAIN */
+		/*
+		* Record gain on AC97 should stay zero to get AC97 sound
+		* on AC97_[RL] connectors on EMU10K2 chip
+		* AC97 on Audigy is not directly connected to any output,
+		* only to EMU10K2 chip
+		* Use this control to set AC97 mix volume inside EMU10K2
+		* chip
+		*/
+			left = (data & 0x3f00)>>8;
+			right = data & 0x003f;
+			/*
+			* rec control is recrding VOLUME, not attenuation
+			* and 0  IS 0%  and 15 IS 100%
+			*/
+			if (data & 0x8000)
+				left = right = 0; /* mute */
+			if (left == 0 && right==0x3f)
+				break;
+			left = left * 100 / 15; /* 4 bit */
+			right =  right * 100 / 15;
+			/* 0x14/0x15 are AC97 controls */
+			emumix_set_fxvol(sc, 0x14, left);
+			emumix_set_fxvol(sc, 0x15, right);
+		/*  */
+			data = 0x0000;
+			break;
+		};
+	};
 	emu_wr(sc, AC97ADDRESS, regno, 1);
 	emu_wr(sc, AC97DATA, data, 2);
 	return 0;
@@ -272,6 +423,80 @@
 };
 AC97_DECLARE(emu_ac97);
 
+/* Mix */
+/* ------------------------------------------------------------------------- */
+
+static int
+emumix_init(struct snd_mixer *m)
+{
+	u_int32_t i, v;
+
+	for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+		if (emu10k1mixer[i].mixer_source) v |= 1 << i;
+	}
+	mix_setdevs(m, v);
+
+	for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+		if (emu10k1mixer[i].is_recording) v |= 1 << i;
+	}
+	mix_setrecdevs(m, v);
+	return 0;
+}
+
+static void
+emumix_set_fxvol(struct sc_info *sc, unsigned gpr, int32_t vol)
+{
+	static const int scale = 16;
+	static const int32_t log2lin[4] = {	/* attenuation (dB) */
+		0x7fffffff,			/* 0.0 */
+		0x7fffffff * 0.840896415253715,	/* 1.5 */
+		0x7fffffff * 0.707106781186548,	/* 3.0 */
+		0x7fffffff * 0.594603557501361,	/* 4.5 */
+	};
+
+	vol = (100 - vol) * scale / 100;
+	vol = (vol >= scale) ? 0 : (log2lin[vol & 3] >> (vol >> 2));
+	emu_wrptr(sc, 0, sc->gpr_base + gpr, vol);
+
+	return;
+}
+
+static int
+emumix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
+{
+#if 0
+	struct sc_info *sc = mix_getdevinfo(m);
+
+	if (emu10k1mixer[dev].is_stereo) {
+		emumix_set_fxvol(sc, sc->gpr_base + emu10k1mixer[dev].gpr, left);
+		emumix_set_fxvol(sc, sc->gpr_base + emu10k1mixer[dev].gpr+1, right);
+	} else {
+		mono = (left>>1) + (right>>1);
+		emumix_set_fxvol(sc,  sc->gpr_base + emu10k1mixer[dev].gpr, mono);
+	};
+#endif
+	return 0;
+}
+
+static int
+emumix_setrecsrc(struct snd_mixer *m, u_int32_t src)
+{
+#if 0
+	struct sc_info *sc = mix_getdevinfo(m);
+#endif
+
+	return src;
+}
+
+static kobj_method_t emu_mix_methods[] = {
+	KOBJMETHOD(mixer_init, emumix_init),
+	KOBJMETHOD(mixer_set, emumix_set),
+	KOBJMETHOD(mixer_setrecsrc, emumix_setrecsrc),
+	{ 0, 0 }
+};
+MIXER_DECLARE(emu_mix);
+
+
 /* -------------------------------------------------------------------- */
 /* stuff */
 static int
@@ -487,7 +712,8 @@
 emu_vwrite(struct sc_info *sc, struct emu_voice *v)
 {
 	int s;
-	int l, r, x, y;
+	int i;
+	unsigned int routing[8],amounts[8];
 	u_int32_t sa, ea, start, val, silent_page;
 
 	s = (v->stereo ? 1 : 0) + (v->b16 ? 1 : 0);
@@ -495,22 +721,44 @@
 	sa = v->start >> s;
 	ea = v->end >> s;
 
-	l = r = x = y = v->vol;
+	for (i = 0; i < 8; i++) {
+		routing[i]=i;
+		amounts[i]=0xff;
+	};
 	if (v->stereo) {
-		l = v->ismaster ? l : 0;
-		r = v->ismaster ? 0 : r;
+		if (v->ismaster) {
+			amounts[0] = amounts[2] = amounts[4] = amounts[6] = 0;
+		} else {
+			amounts[1] = amounts[3] = amounts[5] = amounts[7] = 0;
+		};
+		emu_wrptr(sc, v->vnum, CPF, CPF_STEREO_MASK);
+	} else {
+		emu_wrptr(sc, v->vnum, CPF, 0);
 	}
 
-	emu_wrptr(sc, v->vnum, CPF, v->stereo ? CPF_STEREO_MASK : 0);
 	val = v->stereo ? 28 : 30;
 	val *= v->b16 ? 1 : 2;
 	start = sa + val;
 
-	emu_wrptr(sc, v->vnum, FXRT, 0xd01c0000);
+	if (sc->is_audigy) {
+		emu_wrptr(sc, v->vnum, A_FXRT1,
+		    routing[3] << 24 | routing[2] << 16 | routing[1] << 8
+		    | routing[0] << 0);
+		emu_wrptr(sc, v->vnum, A_FXRT2,
+		    routing[7] << 24 | routing[6] << 16 | routing[5] << 8
+		    | routing[4] << 0);
+		emu_wrptr(sc, v->vnum, A_SENDAMOUNTS,
+		    amounts[7] << 24 | amounts[6] << 26 | amounts[5] << 8
+		    | amounts[4] << 0);
+	} else {
+		emu_wrptr(sc, v->vnum, FXRT,
+		    (routing[3] << 12 | routing[2] << 8 | routing[1] << 4
+		    | routing[0] << 0) << 16); /*0xd01c0000*/
+	}
 
-	emu_wrptr(sc, v->vnum, PTRX, (x << 8) | r);
-	emu_wrptr(sc, v->vnum, DSL, ea | (y << 24));
-	emu_wrptr(sc, v->vnum, PSST, sa | (l << 24));
+	emu_wrptr(sc, v->vnum, PTRX, amounts[3] << 8 | amounts[2] << 0);
+	emu_wrptr(sc, v->vnum, DSL, ea | amounts[1] << 24);
+	emu_wrptr(sc, v->vnum, PSST, sa | amounts[0] << 24);
 	emu_wrptr(sc, v->vnum, CCCA, start | (v->b16 ? 0 : CCCA_8BITSELECT));
 
 	emu_wrptr(sc, v->vnum, Z1, 0);
@@ -599,12 +847,13 @@
 static void
 emu_vdump(struct sc_info *sc, struct emu_voice *v)
 {
-	char *regname[] = { "cpf", "ptrx", "cvcf", "vtft", "z2", "z1", "psst", "dsl",
-			    "ccca", "ccr", "clp", "fxrt", "mapa", "mapb", NULL, NULL,
-			    "envvol", "atkhldv", "dcysusv", "lfoval1",
-			    "envval", "atkhldm", "dcysusm", "lfoval2",
-			    "ip", "ifatn", "pefe", "fmmod", "tremfrq", "fmfrq2",
-			    "tempenv" };
+	char *regname[] = {
+		"cpf", "ptrx", "cvcf", "vtft", "z2", "z1", "psst", "dsl",
+		"ccca", "ccr", "clp", "fxrt", "mapa", "mapb", NULL, NULL,
+		"envvol", "atkhldv", "dcysusv", "lfoval1",
+		"envval", "atkhldm", "dcysusm", "lfoval2",
+		"ip", "ifatn", "pefe", "fmmod", "tremfrq", "fmfrq2", "tempenv"
+	};
 	int i, x;
 
 	printf("voice number %d\n", v->vnum);
@@ -621,7 +870,7 @@
 }
 #endif
 
-/* channel interface */
+/* playback channel interface */
 static void *
 emupchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
 {
@@ -757,7 +1006,7 @@
 };
 CHANNEL_DECLARE(emupchan);
 
-/* channel interface */
+/* recording channel interface */
 static void *
 emurchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
 {
@@ -775,7 +1024,7 @@
 	ch->num = sc->rnum;
 	switch(sc->rnum) {
 	case 0:
-		ch->idxreg = ADCIDX;
+		ch->idxreg = sc->is_audigy ? A_ADCIDX : ADCIDX;
 		ch->basereg = ADCBA;
 		ch->sizereg = ADCBS;
 		ch->setupreg = ADCCR;
@@ -889,9 +1138,11 @@
 		ch->run = 1;
 		emu_wrptr(sc, 0, ch->sizereg, sz);
 		if (ch->num == 0) {
-			val = ADCCR_LCHANENABLE;
+			val = sc->is_audigy ? A_ADCCR_LCHANENABLE
+			    : ADCCR_LCHANENABLE;
 			if (ch->fmt & AFMT_STEREO)
-				val |= ADCCR_RCHANENABLE;
+				val |= sc->is_audigy ? A_ADCCR_RCHANENABLE
+				    : ADCCR_RCHANENABLE;
 			val |= emu_recval(ch->spd);
 			emu_wrptr(sc, 0, ch->setupreg, 0);
 			emu_wrptr(sc, 0, ch->setupreg, val);
@@ -1147,8 +1398,8 @@
 static void
 emu_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 << 10) | y);
-	emu_wrefx(sc, (*pc) * 2 + 1, (op << 20) | (z << 10) | w);
+	emu_wrefx(sc, (*pc) * 2, (x << sc->high_operand_shift) | y);
+	emu_wrefx(sc, (*pc) * 2 + 1, (op << sc->opcode_shift) | (z << sc->high_operand_shift) | w);
 	(*pc)++;
 }
 
@@ -1156,84 +1407,220 @@
 emu_initefx(struct sc_info *sc)
 {
 	int i;
-	u_int32_t pc = 16;
+	u_int32_t pc = 0;
+
+/* code size is in bytes... we write 4-byte (2-word) instructions */
+	for (i = 0; i < ((sc->code_size)>>2); i++) {
+		if (sc->is_audigy) {
+			emu_addefxop(sc, ACC3, DSP_CONST(0x0), DSP_CONST(0x0),
+			    DSP_CONST(0x0), DSP_CONST(0x0), &pc);
+		} else {
+			emu_addefxop(sc, ACC3, DSP_CONST(0x0), DSP_CONST(0x0),
+			    DSP_CONST(0x0), DSP_CONST(0x0), &pc);
+		}
+	};
+
+	pc = 0;
+
+	for (i = 0; i < sc->num_gprs; i++)
+		emu_wrptr(sc, 0, sc->gpr_base + i, 0);
 
-	for (i = 0; i < 512; i++) {
-		emu_wrefx(sc, i * 2, 0x10040);
-		emu_wrefx(sc, i * 2 + 1, 0x610040);
-	}
-
-	for (i = 0; i < 256; i++)
-		emu_wrptr(sc, 0, FXGPREGBASE + i, 0);
-
-	/* FX-8010 DSP Registers:
-	   FX Bus
-	     0x000-0x00f : 16 registers
-	   Input
-	     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)
-	   Output
-	     0x020/0x021 : AC97 Output (l/r)
-	     0x022/0x023 : TOS link out (l/r)
-	     0x024/0x025 : ??? (l/r)
-	     0x026/0x027 : LiveDrive Headphone (l/r)
-	     0x028/0x029 : Rear Channel (l/r)
-	     0x02a/0x02b : ADC Recording Buffer (l/r)
-	   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
-	   Temporary Values
-	     0x056 : Accumulator
-	     0x058 : Noise source?
-	     0x059 : Noise source?
-	   General Purpose Registers
-	     0x100 - 0x1ff
-	   Tank Memory Data Registers
-	     0x200 - 0x2ff
-	   Tank Memory Address Registers
-	     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);
-	/* 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);
-	/* FrontOut (AC97) = GPR[0/1] */
-	emu_addefxop(sc, 6, 0x20, 0x40, 0x40, 0x100, &pc);
-	emu_addefxop(sc, 6, 0x21, 0x40, 0x41, 0x101, &pc);
-	/* 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);
 
-	emu_wrptr(sc, 0, DBG, 0);
+	if (sc->is_audigy) {
+		/* GPRs:
+		0x00...0x0f - inputs
+		0x10...0x1f - volumes
+		0x20...0x2f - outs
+		*/
+
+		emu_wrptr(sc, 0, sc->gpr_base + 0x10, 0x7fffffff); /* PCM */
+		emu_wrptr(sc, 0, sc->gpr_base + 0x11, 0x7fffffff);
+		emu_wrptr(sc, 0, sc->gpr_base + 0x12, 0x7fffffff); /* VOL */
+		emu_wrptr(sc, 0, sc->gpr_base + 0x13, 0x7fffffff);
+		emu_wrptr(sc, 0, sc->gpr_base + 0x14, 0x7fffffff); /* AC97 ("rec" label) */
+		emu_wrptr(sc, 0, sc->gpr_base + 0x15, 0x7fffffff);
+
+		/* Routing and volume - this should be configurable in later version */
+
+		/* GPR[0/1] = FX * controlled by PCM control */
+		emu_addefxop(sc, MACS, GPR(0x0), DSP_CONST(0x0), PCM0_L,
+		    GPR(0x10), &pc);
+		emu_addefxop(sc, MACS, GPR(0x1), DSP_CONST(0x0), PCM0_R,
+		    GPR(0x11), &pc);
+		/* GPR[2/3] = AC97 * conrolled by AC97 "rec" control */
+		emu_addefxop(sc, MACS, GPR(0x2), DSP_CONST(0x0), IN_AC97_L,
+		    GPR(0x14), &pc);
+		emu_addefxop(sc, MACS, GPR(0x3), DSP_CONST(0x0), IN_AC97_R,
+		    GPR(0x15), &pc);
+
+		/* Main Vol * controlled by VOL control */
+		emu_addefxop(sc, ACC3, GPR(0x22), DSP_CONST(0x0), GPR(0x0),
+		    GPR(0x2), &pc);
+		emu_addefxop(sc, ACC3, GPR(0x23), DSP_CONST(0x0), GPR(0x1),
+		    GPR(0x3), &pc);
+		emu_addefxop(sc, MACS, GPR(0x20), DSP_CONST(0x0), GPR(0x22),
+		    GPR(0x12), &pc);
+		emu_addefxop(sc, MACS, GPR(0x21), DSP_CONST(0x0), GPR(0x23),
+		    GPR(0x13), &pc);
+
+		/* FrontOut (AC97) = GPR[10/11] */
+
+		emu_addefxop(sc, ACC3, OUTP(0x0), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x1), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/* TOS out = GPR[0/1] */
+		emu_addefxop(sc, ACC3, OUTP(0x2), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x3), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/*  */
+
+		emu_addefxop(sc, ACC3, OUTP(0x4), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x5), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/* Mute Out3 */
+		emu_addefxop(sc, ACC3, OUTP(0x6), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x7), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/*   RearVolume = GRP[0x10/0x11] */
+		emu_addefxop(sc, ACC3, OUTP(0x8), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x9), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/* Center / Sub */
+		emu_addefxop(sc, ACC3, GPR(0x2A), DSP_CONST(0x0), GPR(0x0),
+		    GPR(0x1), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0xA), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x2A), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0xB), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/*  */
+		emu_addefxop(sc, ACC3, OUTP(0xC), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0xD), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/*  */
+		emu_addefxop(sc, ACC3, OUTP(0xE), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0xF), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/*  */
+		emu_addefxop(sc, ACC3, OUTP(0x10), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x11), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/* AC97 Rec ?  */
+		emu_addefxop(sc, ACC3, OUTP(0x12), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x13), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/*  */
+		emu_addefxop(sc, ACC3, OUTP(0x14), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x15), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/* ??? */
+		emu_addefxop(sc, ACC3, OUTP(0x16), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x17), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/*  */
+		emu_addefxop(sc, ACC3, OUTP(0x18), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x19), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/*  */
+		emu_addefxop(sc, ACC3, OUTP(0x1A), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x1B), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/*  */
+		emu_addefxop(sc, ACC3, OUTP(0x1C), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x1D), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+		/*  */
+		emu_addefxop(sc, ACC3, OUTP(0x1E), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x20), &pc);
+		emu_addefxop(sc, ACC3, OUTP(0x1F), DSP_CONST(0x0),
+		    DSP_CONST(0x0), GPR(0x21), &pc);
+
+		emu_wrptr(sc,0,A_DBG,0);
+	} else {
+		/* FX-8010 DSP Registers:
+		   FX Bus
+		     0x000-0x00f : 16 registers
+		   Input
+		     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)
+		   Output
+		     0x020/0x021 : AC97 Output (l/r)
+		     0x022/0x023 : TOS link out (l/r)
+		     0x024/0x025 : ??? (l/r)
+		     0x026/0x027 : LiveDrive Headphone (l/r)
+		     0x028/0x029 : Rear Channel (l/r)
+		     0x02a/0x02b : ADC Recording Buffer (l/r)
+		   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
+		   Temporary Values
+		     0x056 : Accumulator
+		     0x058 : Noise source?
+		     0x059 : Noise source?
+		   General Purpose Registers
+		     0x100 - 0x1ff
+		   Tank Memory Data Registers
+		     0x200 - 0x2ff
+		   Tank Memory Address Registers
+		     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);
+		/* 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);
+		/* FrontOut (AC97) = GPR[0/1] */
+		emu_addefxop(sc, 6, 0x20, 0x40, 0x40, 0x100, &pc);
+		emu_addefxop(sc, 6, 0x21, 0x40, 0x41, 0x101, &pc);
+		/* 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);
+
+		emu_wrptr(sc, 0, DBG, 0);
+	}
 }
 
 /* Probe and attach the card */
@@ -1260,6 +1647,13 @@
 	emu_wrptr(sc, 0, SOLEL, 0);
 	emu_wrptr(sc, 0, SOLEH, 0);
 
+	/* init phys inputs and outputs */
+	if (sc->is_audigy) {
+		emu_wrptr(sc, 0, SPBYPASS, 0x00);
+		emu_wrptr(sc, 0, AC97SLOT,
+		    0x40 | AC97SLOT_CNTR | AC97SLOT_LFE | 0x02 | 0x01);
+	};
+
 	/* init envelope engine */
 	for (ch = 0; ch < NUM_G; ch++) {
 		emu_wrptr(sc, ch, DCYSUSV, ENV_OFF);
@@ -1267,7 +1661,6 @@
 		emu_wrptr(sc, ch, VTFT, 0xffff);
 		emu_wrptr(sc, ch, CVCF, 0xffff);
 		emu_wrptr(sc, ch, PTRX, 0);
-		emu_wrptr(sc, ch, CPF, 0);
 		emu_wrptr(sc, ch, CCR, 0);
 
 		emu_wrptr(sc, ch, PSST, 0);
@@ -1292,6 +1685,17 @@
 		emu_wrptr(sc, ch, ATKHLDV, 0);
 		emu_wrptr(sc, ch, ENVVOL, 0);
 		emu_wrptr(sc, ch, ENVVAL, 0);
+		emu_wrptr(sc, ch, CPF, 0);
+
+		if (sc->is_audigy) {
+			emu_wrptr(sc, ch, 0x4c, 0x0);
+			emu_wrptr(sc, ch, 0x4d, 0x0);
+			emu_wrptr(sc, ch, 0x4e, 0x0);
+			emu_wrptr(sc, ch, 0x4f, 0x0);
+			emu_wrptr(sc, ch, A_FXRT1, 0x3f3f3f3f);
+			emu_wrptr(sc, ch, A_FXRT2, 0x3f3f3f3f);
+			emu_wrptr(sc, ch, A_SENDAMOUNTS, 0x0);
+		}
 
 		sc->voice[ch].vnum = ch;
 		sc->voice[ch].slave = NULL;
@@ -1365,13 +1769,93 @@
 	 *   Lock Sound Memory = 0
 	 *   Auto Mute = 1
 	 */
-	tmp = HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE;
+	tmp = HCFG_AUDIOENABLE | HCFG_AUTOMUTE;
 	if (sc->rev >= 6)
 		tmp |= HCFG_JOYENABLE;
+	if (sc->is_audigy)
+		tmp |= HCFG_CODECFORMAT_I2S | HCFG_GPOUT0 | HCFG_JOYENABLE;
+	else
+		tmp |= HCFG_LOCKTANKCACHE_MASK;
 	emu_wr(sc, HCFG, tmp, 4);
+#if 0
+	if (0) {	/* enable IR for SB Live */
+		tmp = emu_rd(sc,HCFG,4);
+		emu_wr(sc, HCFG, tmp | HCFG_GPOUT2, 4);
+		DELAY(500);
+		emu_wr(sc, HCFG, tmp | HCFG_GPOUT1 | HCFG_GPOUT2, 4);
+		DELAY(500);
+/*		emu_wr(sc, HCFG, tmp, 4); */
+	}
+#endif
+
+	tmp = emu_rd(sc, HCFG, 4);
+	device_printf(sc->dev, "Card Configuration (   0x%08x )\n",tmp);
+	device_printf(sc->dev,
+	    "Card Configuration ( & 0xff000000 ) : %s%s%s%s%s%s%s%s\n",
+	    (tmp&0x80000000 ? "[Legacy MPIC] " : ""),
+	    (tmp&0x40000000 ? "[0x40] " : ""),
+	    (tmp&0x20000000 ? "[0x20] " : ""),
+	    (tmp&0x10000000 ? "[0x10] " : ""),
+	    (tmp&0x08000000 ? "[0x08] " : ""),
+	    (tmp&0x04000000 ? "[0x04] " : ""),
+	    (tmp&0x02000000 ? "[0x02] " : ""),
+	    (tmp&0x01000000 ? "[0x01]" : ""));
+	device_printf(sc->dev,
+	    "Card Configuration ( & 0x00ff0000 ) : %s%s%s%s%s%s%s%s\n",
+	    (tmp&0x00800000 ? "[0x80] " : ""),
+	    (tmp&0x00400000 ? "[0x40] " : ""),
+	    (tmp&0x00200000 ? "[Legacy INT] " : ""),
+	    (tmp&0x00100000 ? "[0x10] " : ""),
+	    (tmp&0x00080000 ? "[0x08] " : ""),
+	    (tmp&0x00040000 ? "[Codec4] " : ""),
+	    (tmp&0x00020000 ? "[Codec2] " : ""),
+	    (tmp&0x00010000 ? "[I2S Codec]" : ""));
+	device_printf(sc->dev,
+	    "Card Configuration ( & 0x0000ff00 ) : %s%s%s%s%s%s%s%s\n",
+	    (tmp&0x00008000 ? "[0x80] " : ""),
+	    (tmp&0x00004000 ? "[GPINPUT0] " : ""),
+	    (tmp&0x00002000 ? "[GPINPUT1] " : ""),
+	    (tmp&0x00001000 ? "[GPOUT0] " : ""),
+	    (tmp&0x00000800 ? "[GPOUT1] " : ""),
+	    (tmp&0x00000400 ? "[GPOUT2] " : ""),
+	    (tmp&0x00000200 ? "[Joystick] " : ""),
+	    (tmp&0x00000100 ? "[0x01]" : ""));
+	device_printf(sc->dev,
+	    "Card Configuration ( & 0x000000ff ) : %s%s%s%s%s%s%s%s\n",
+	    (tmp&0x00000080 ? "[0x80] " : ""),
+	    (tmp&0x00000040 ? "[0x40] " : ""),
+	    (tmp&0x00000020 ? "[0x20] " : ""),
+	    (tmp&0x00000010 ? "[AUTOMUTE] " : ""),
+	    (tmp&0x00000008 ? "[LOCKSOUNDCACHE] " : ""),
+	    (tmp&0x00000004 ? "[LOCKTANKCACHE] " : ""),
+	    (tmp&0x00000002 ? "[MUTEBUTTONENABLE] " : ""),
+	    (tmp&0x00000001 ? "[AUDIOENABLE]" : ""));
+
+	if (sc->is_audigy) {
+		tmp = emu_rd(sc, A_IOCFG, 2);
+		device_printf(sc->dev, "Audigy Card Configuration ( 0x%04x )\n",
+		    tmp);
+		device_printf(sc->dev,
+		    "Connectors attached: %s%s%s%s%s%s%s%s\n",
+		    (tmp&0x8000 ? "[Rear Speakers] " : ""),
+		    (tmp&0x4000 ? "[Front Speakers] " : ""),
+		    (tmp&0x2000 ? "[0x20] " : ""),
+		    (tmp&0x1000 ? "[0x10] " : ""),
+		    (tmp&0x0800 ? "[0x08] " : ""),
+		    (tmp&0x0400 ? "[0x04] " : ""),
+		    (tmp&0x0200 ? "[0x02] " : ""),
+		    (tmp&0x0100 ? "[AudigyDrive Phones]" : ""));
+		emu_wrptr(sc,0, A_SPDIF_SAMPLERATE, A_SPDIF_48000);
+	}
+
 
-	/* TOSLink detection */
 	sc->tos_link = 0;
+#if  0
+	/*
+	ALSA Driver stated that this code disbales LiveDrive !!!
+	*/
+	/* TOSLink detection */
+
 	tmp = emu_rd(sc, HCFG, 4);
 	if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
 		emu_wr(sc, HCFG, tmp | 0x800, 4);
@@ -1381,7 +1865,7 @@
 			emu_wr(sc, HCFG, tmp, 4);
 		}
 	}
-
+#endif
 	return 0;
 }
 
@@ -1439,11 +1923,9 @@
 	case EMU10K1_PCI_ID:
 		s = "Creative EMU10K1";
 		break;
-/*
 	case EMU10K2_PCI_ID:
 		s = "Creative EMU10K2";
 		break;
-*/
 	default:
 		return ENXIO;
 	}
@@ -1466,11 +1948,71 @@
 		return ENXIO;
 	}
 
+	ctl_sc_info = sc;
 	sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
 	sc->dev = dev;
 	sc->type = pci_get_devid(dev);
 	sc->rev = pci_get_revid(dev);
 
+	switch (sc->type) {
+	case EMU10K1_PCI_ID:
+		sc->is_audigy = 0;
+		sc->opcode_shift = 20;
+		sc->high_operand_shift = 10;
+		sc->code_base = MICROCODEBASE;
+		sc->code_size = 512;
+		sc->gpr_base = FXGPREGBASE;
+		sc->num_gprs = 0x100;
+		sc->input_base = 0x10;
+		sc->output_base = 0x20;
+		sc->dsp_zero=0x40;
+		sc->mchannel_fx = 0;
+
+		/* mono voice */
+		sc->waveio.send_dcba[SEND_MONO] = 0x0000ffff;
+
+		/* stereo voice */
+		/* left */
+		sc->waveio.send_dcba[SEND_LEFT] = 0x000000ff;
+		/* right */
+		sc->waveio.send_dcba[SEND_RIGHT] = 0x0000ff00;
+
+		sc->waveio.send_routing[ROUTE_PCM0] = 0x00003210; /* Regular pcm*/
+
+		break;
+	case EMU10K2_PCI_ID:
+		sc->is_audigy = 1;
+		sc->opcode_shift = 24;
+		sc->high_operand_shift = 12;
+		sc->code_base = AUDIGY_CODEBASE;
+		sc->code_size = 1024;
+		sc->gpr_base = A_FXGPREGBASE;
+		sc->num_gprs = 0x200;
+		sc->input_base = 0x40;
+		sc->output_base = 0x60;
+		sc->dsp_zero=0xc0;
+		sc->mchannel_fx = 8;
+		/* mono voice */
+
+		sc->waveio.send_dcba[SEND_MONO] = 0xffffffff;
+		sc->waveio.send_hgfe[SEND_MONO] = 0x0000ffff;
+
+		/* stereo voice */
+		/* left */
+		sc->waveio.send_dcba[SEND_LEFT] = 0x00ff00ff;
+		sc->waveio.send_hgfe[SEND_LEFT] = 0x00007f7f;
+		/* right */
+		sc->waveio.send_dcba[SEND_RIGHT] = 0xff00ff00;
+		sc->waveio.send_hgfe[SEND_RIGHT] = 0x00007f7f;
+
+		sc->waveio.send_routing[ROUTE_PCM0] = 0x03020100; /* Regular pcm*/
+		sc->waveio.send_routing2[ROUTE_PCM0] = 0x07060504;
+
+		break;
+	default:
+		return ENXIO;
+	}
+
 	data = pci_read_config(dev, PCIR_COMMAND, 2);
 	data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
 	pci_write_config(dev, PCIR_COMMAND, data, 2);
@@ -1497,6 +2039,16 @@
 		goto bad;
 	}
 
+	i = 0;
+	sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &i, 0, ~0, 1,
+	    RF_ACTIVE | RF_SHAREABLE);
+	if (!sc->irq ||
+	    snd_setup_intr(dev, sc->irq, INTR_MPSAFE, emu_intr, sc, &sc->ih)) {
+		device_printf(dev, "unable to map interrupt\n");
+		goto bad;
+	}
+
+
 	if (emu_init(sc) == -1) {
 		device_printf(dev, "unable to initialize the card\n");
 		goto bad;
@@ -1504,15 +2056,20 @@
 
 	codec = AC97_CREATE(dev, sc, emu_ac97);
 	if (codec == NULL) goto bad;
+	sc->codec = codec;
 	gotmic = (ac97_getcaps(codec) & AC97_CAP_MICCHANNEL) ? 1 : 0;
 	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
+#if 0
+	if (mixer_init(dev, &emu_mix_class, sc) == -1) goto bad;
+#endif
+
+	emu_wr(sc,AC97ADDRESS,0x18,1);
+	emu_wr(sc,AC97DATA,(sc->is_audigy) ? 0x8000 : 0x0000,2);
+
+	emu_wr(sc,AC97ADDRESS,AC97_RECORD_GAIN,1);
+	emu_wr(sc,AC97DATA,0x0000,2);
+
 
-	i = 0;
-	sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &i, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
-	if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, emu_intr, sc, &sc->ih)) {
-		device_printf(dev, "unable to map interrupt\n");
-		goto bad;
-	}
 
 	snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", rman_get_start(sc->reg), rman_get_start(sc->irq));
 
@@ -1581,6 +2138,46 @@
 MODULE_DEPEND(snd_emu10k1, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
 MODULE_VERSION(snd_emu10k1, 1);
 
+/* sysctls to RO access to 8010 memory from userland */
+static int
+sysctl_hw_snd_emu10k_dump(SYSCTL_HANDLER_ARGS)
+{
+	int error, i, j, v;
+	struct sbuf *sb;
+
+	sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
+	sbuf_clear(sb);
+	sbuf_printf(sb, "EMU8010 per-voice dump\n");
+	for(v = 0; v < 64; v++) {
+		sbuf_printf(sb, "voice %04x\n", v);
+		for(i = 0; i < 0x20; i++) {
+			sbuf_printf(sb, "%04x", i * 0x4);
+			for(j = 0; j < 4; j++)
+				sbuf_printf(sb, " %08x",
+				    emu_rdptr(ctl_sc_info, v, i * 0x4 + j));
+			sbuf_printf(sb,"\n");
+		};
+	};
+	sbuf_printf(sb, "EMU8010 memory dump\n");
+	for(i = 0; i < 0x200; i++) {
+		sbuf_printf(sb, "%04x", i * 0x4);
+		for (j = 0; j < 0x4; j++)
+			sbuf_printf(sb, " %08x", emu_rdptr(ctl_sc_info, 0,
+			    i * 0x4 + j));
+		sbuf_printf(sb,"\n");
+	};
+	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
+	sbuf_delete(sb);
+	return error;
+}
+
+SYSCTL_NODE(_hw_snd, OID_AUTO, emu10k, CTLFLAG_RW, 0, "EMU10Kx management");
+
+SYSCTL_PROC(_hw_snd_emu10k, OID_AUTO, dump, CTLTYPE_STRING|CTLFLAG_RD,
+	0, 0, sysctl_hw_snd_emu10k_dump, "",
+	"Dump EMU10Kx memory in text");
+
+
 /* dummy driver to silence the joystick device */
 static int
 emujoy_pci_probe(device_t dev)

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_ */



More information about the freebsd-multimedia mailing list