What is the actual status of Audigy2 support in 5.1-CURRENT?
David O'Brien
obrien at freebsd.org
Mon Aug 18 11:00:39 PDT 2003
On Mon, Aug 18, 2003 at 11:08:07AM -0400, Tom Parquette wrote:
> I would like to get an Audigy2 Platnum card working on my AMD dual
> processor system. I'm 5.1-CURRENT but I tend to hang back a little.
> I have "device pcm" and "device sbc" in the kernel. When the system
> didn't figure out the card I added "device firewire" "device sbp" and
> "device fwe" to the kernel to see if the probes could figure out the
> firewire interface.
I don't think you need device sbc -- I use only modules:
Id Refs Address Size Name
1 43 0xc0100000 31609c kernel.ko
5 1 0xc0440000 88b4 snd_emu10k1.ko
6 2 0xc0449000 1d13c snd_pcm.ko
15 1 0xc0504000 14934 firewire.ko
I use this uncommitted patch (I haven't been able to test it against
older SB Live! 128 cards):
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 7 Jun 2003 21:19:50 -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,9 @@
#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 <dev/sound/pci/emu10k1.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
@@ -39,9 +43,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 +83,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 +113,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 +127,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 +190,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 +231,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 +249,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 +265,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 +309,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 +372,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 +484,16 @@
m->vol = 0xff;
m->buf = tmp_addr;
m->slave = s;
+ if (sc->audigy) {
+ m->fxrt1 = FXBUS_MIDI_CHORUS | FXBUS_PCM_LEFT << 8 |
+ FXBUS_PCM_RIGHT << 16 | FXBUS_MIDI_REVERB << 24;
+ m->fxrt2 = 0x3f3f3f3f; /* No effects on second route */
+ } else {
+ m->fxrt1 = FXBUS_MIDI_CHORUS | FXBUS_PCM_LEFT << 4 |
+ FXBUS_PCM_RIGHT << 8 | FXBUS_MIDI_REVERB << 12;
+ m->fxrt2 = 0;
+ }
+
if (s != NULL) {
s->start = m->start;
s->end = m->end;
@@ -458,6 +505,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 +555,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 +662,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 +680,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 +851,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 +900,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 +969,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 +1062,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 +1241,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(FXBUS_PCM_LEFT), &pc);
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AC97_R), A_C_00000000,
+ A_C_00000000, A_FXBUS(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 +1424,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 +1460,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 +1544,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 +1565,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 +1604,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 +1652,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 +1701,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 +1785,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 +1828,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 +1862,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 +1912,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/dev/sound/pci/emu10k1.h
===================================================================
RCS file: sys/dev/sound/pci/emu10k1.h
diff -N sys/dev/sound/pci/emu10k1.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/dev/sound/pci/emu10k1.h 23 Jun 2003 01:58:32 -0000
@@ -0,0 +1,17 @@
+/***********************************************************************
+ *
+ * Date Author Summary of changes
+ * ---- ------ ------------------
+ * February 10, 2003 Orlando Bassotto Added Audigy registers
+ * and opcode macros from
+ * ALSA project emu10k1.h.
+ **********************************************************************/
+
+#ifndef _EMU10K1_H_
+#define _EMU10K1_H_
+
+#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)
+
+#endif /* _EMU10K1_H_ */
Index: sys/gnu/dev/sound/pci/emu10k1-ac97.h
===================================================================
RCS file: /home/ncvs/src/sys/gnu/dev/sound/pci/emu10k1-ac97.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 emu10k1-ac97.h
--- sys/gnu/dev/sound/pci/emu10k1-ac97.h 21 Apr 2003 02:27:52 -0000 1.1.1.1
+++ sys/gnu/dev/sound/pci/emu10k1-ac97.h 7 Jun 2003 19:32:38 -0000
@@ -1,8 +1,15 @@
-#ifndef _AC97_CODEC_H_
-#define _AC97_CODEC_H_
+#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 */
+/********************************************************************************************************/
+
-#include <linux/types.h>
-#include <linux/soundcard.h>
/* AC97 1.0 */
#define AC97_RESET 0x0000 //
@@ -180,66 +187,5 @@
(FOO < SOUND_MIXER_NRDEVICES) && \
(CODEC)->supported_mixers & (1<<FOO) )
-struct ac97_codec {
- /* AC97 controller connected with */
- void *private_data;
-
- char *name;
- int id;
- int dev_mixer;
- int type;
-
- struct ac97_ops *codec_ops;
-
- /* controller specific lower leverl ac97 accessing routines */
- u16 (*codec_read) (struct ac97_codec *codec, u8 reg);
- void (*codec_write) (struct ac97_codec *codec, u8 reg, u16 val);
-
- /* Wait for codec-ready. Ok to sleep here. */
- void (*codec_wait) (struct ac97_codec *codec);
-
- /* OSS mixer masks */
- int modcnt;
- int supported_mixers;
- int stereo_mixers;
- int record_sources;
-
- int bit_resolution;
-
- /* OSS mixer interface */
- int (*read_mixer) (struct ac97_codec *codec, int oss_channel);
- void (*write_mixer)(struct ac97_codec *codec, int oss_channel,
- unsigned int left, unsigned int right);
- int (*recmask_io) (struct ac97_codec *codec, int rw, int mask);
- int (*mixer_ioctl)(struct ac97_codec *codec, unsigned int cmd, unsigned long arg);
-
- /* saved OSS mixer states */
- unsigned int mixer_state[SOUND_MIXER_NRDEVICES];
-
- /* Software Modem interface */
- int (*modem_ioctl)(struct ac97_codec *codec, unsigned int cmd, unsigned long arg);
-};
-
-/*
- * Operation structures for each known AC97 chip
- */
-
-struct ac97_ops
-{
- /* Initialise */
- int (*init)(struct ac97_codec *c);
- /* Amplifier control */
- int (*amplifier)(struct ac97_codec *codec, int on);
- /* Digital mode control */
- int (*digital)(struct ac97_codec *codec, int format);
-};
-
-extern int ac97_read_proc (char *page_out, char **start, off_t off,
- int count, int *eof, void *data);
-extern int ac97_probe_codec(struct ac97_codec *);
-extern unsigned int ac97_set_adc_rate(struct ac97_codec *codec, unsigned int rate);
-extern unsigned int ac97_set_dac_rate(struct ac97_codec *codec, unsigned int rate);
-extern int ac97_save_state(struct ac97_codec *codec);
-extern int ac97_restore_state(struct ac97_codec *codec);
-#endif /* _AC97_CODEC_H_ */
+#endif /* _EMU10K_AC97_H_ */
Index: sys/gnu/dev/sound/pci/emu10k1-alsa.h
===================================================================
RCS file: /home/ncvs/src/sys/gnu/dev/sound/pci/emu10k1-alsa.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 emu10k1-alsa.h
--- sys/gnu/dev/sound/pci/emu10k1-alsa.h 7 Jun 2003 20:54:30 -0000 1.1.1.1
+++ sys/gnu/dev/sound/pci/emu10k1-alsa.h 7 Jun 2003 21:24:48 -0000
@@ -71,9 +71,12 @@
/* channel number of the register to be */
/* accessed. For non per-channel registers the */
/* value should be set to zero. */
+#endif /* __KERNEL__ */
+
#define PTR_ADDRESS_MASK 0x07ff0000 /* Register index */
-#define A_PTR_ADDRESS_MASK 0x0fff0000
+#define A_PTR_ADDRESS_MASK 0x0fff0000 /* Audigy register index */
+#ifdef __KERNEL__
#define DATA 0x04 /* Indexed register set data register */
#define IPR 0x08 /* Global interrupt pending register */
@@ -1284,41 +1287,6 @@
#define EMU10K1_GRP_TRANSLATION_BASS 2
#define EMU10K1_GRP_TRANSLATION_TREBLE 3
#define EMU10K1_GPR_TRANSLATION_ONOFF 4
-
-typedef struct {
- snd_ctl_elem_id_t id; /* full control ID definition */
- unsigned int vcount; /* visible count */
- unsigned int count; /* count of GPR (1..16) */
- unsigned char gpr[32]; /* GPR number(s) */
- unsigned int value[32]; /* initial values */
- unsigned int min; /* minimum range */
- unsigned int max; /* maximum range */
- unsigned int translation; /* translation type (EMU10K1_GRP_TRANSLATION*) */
-} emu10k1_fx8010_control_gpr_t;
-
-typedef struct {
- char name[128];
-
- unsigned long gpr_valid[0x100/(sizeof(unsigned long)*8)]; /* bitmask of valid initializers */
- unsigned int gpr_map[0x100]; /* initializers */
-
- unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
- emu10k1_fx8010_control_gpr_t *gpr_add_controls; /* GPR controls to add/replace */
-
- unsigned int gpr_del_control_count; /* count of GPR controls to remove */
- snd_ctl_elem_id_t *gpr_del_controls; /* IDs of GPR controls to remove */
-
- unsigned int gpr_list_control_count; /* count of GPR controls to list */
- unsigned int gpr_list_control_total; /* total count of GPR controls */
- emu10k1_fx8010_control_gpr_t *gpr_list_controls; /* listed GPR controls */
-
- unsigned long tram_valid[0xa0/(sizeof(unsigned long)*8)]; /* bitmask of valid initializers */
- unsigned int tram_data_map[0xa0]; /* data initializers */
- unsigned int tram_addr_map[0xa0]; /* map initializers */
-
- unsigned long code_valid[512/(sizeof(unsigned long)*8)]; /* bitmask of valid instructions */
- unsigned int code[512][2]; /* one instruction - 64 bits */
-} emu10k1_fx8010_code_t;
typedef struct {
unsigned int address; /* 31.bit == 1 -> external TRAM */
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 7 Jun 2003 20:14:00 -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,13 @@
#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 +66,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 +95,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 +126,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 +147,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 +182,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 +195,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 +204,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 +215,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 +228,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 +247,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 +422,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 +464,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 +479,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 +556,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 +621,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 +638,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 +659,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 +727,14 @@
#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 */
More information about the freebsd-current
mailing list