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 * Copyright (c) 1999 Cameron Grant * All rights reserved. * @@ -27,6 +28,9 @@ #include #include #include +#include +#include +#include #include #include @@ -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 -#include /* AC97 1.0 */ #define AC97_RESET 0x0000 // @@ -180,66 +187,5 @@ (FOO < SOUND_MIXER_NRDEVICES) && \ (CODEC)->supported_mixers & (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 = + 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 = + 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 */