diff options
author | cg <cg@FreeBSD.org> | 2000-04-02 07:41:17 +0000 |
---|---|---|
committer | cg <cg@FreeBSD.org> | 2000-04-02 07:41:17 +0000 |
commit | d45e1e2b8b3d88e925564212283fb9072a911a32 (patch) | |
tree | e5d2074e092d7d1128bf29cfa7c18a9c1e62565d | |
parent | b12b58a3f627d8fba10ff539c700be8642e15752 (diff) | |
download | FreeBSD-src-d45e1e2b8b3d88e925564212283fb9072a911a32.zip FreeBSD-src-d45e1e2b8b3d88e925564212283fb9072a911a32.tar.gz |
unfinished sblive driver, playback/mixer only for now - not enabled in
conf/files
i don't seem to be clearing the cache right resulting in a short initial
burst of noise, despite doing the same as creative and alsa. i'm committing
now so more eyes can pore over the code.
-rw-r--r-- | sys/dev/sound/pci/emu10k1.c | 1170 | ||||
-rw-r--r-- | sys/dev/sound/pci/emu10k1.h | 666 | ||||
-rw-r--r-- | sys/gnu/dev/sound/pci/emu10k1.h | 666 |
3 files changed, 2502 insertions, 0 deletions
diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c new file mode 100644 index 0000000..b9bb854 --- /dev/null +++ b/sys/dev/sound/pci/emu10k1.c @@ -0,0 +1,1170 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "pci.h" +#include "pcm.h" + +#include <dev/sound/pcm/sound.h> +#include <dev/sound/pcm/ac97.h> +#include <dev/sound/pci/emu10k1.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> +#include <sys/queue.h> + +/* -------------------------------------------------------------------- */ + +#define EMU10K1_PCI_ID 0x00021102 +#define EMU_BUFFSIZE 16384 +#define EMUDEBUG + +struct emu_memblk { + SLIST_ENTRY(emu_memblk) link; + void *buf; + u_int32_t pte_start, pte_size; +}; + +struct emu_mem { + u_int8_t bmap[MAXPAGES / 8]; + volatile u_int32_t *ptb_pages; + void *silent_page; + SLIST_HEAD(, emu_memblk) blocks; +}; + +struct emu_voice { + int vnum; + int b16:1, stereo:1, busy:1, running:1, master:1; + int speed; + int start, end; + struct emu_voice *slave; + pcm_channel *channel; +}; + +struct sc_info; + +/* channel registers */ +struct sc_chinfo { + int spd, dir, fmt; + struct emu_voice *master, *slave; + snd_dbuf *buffer; + pcm_channel *channel; + struct sc_info *parent; +}; + +/* device private data */ +struct sc_info { + device_t dev; + u_int32_t type, rev; + u_int32_t tos_link:1, APS:1; + + bus_space_tag_t st; + bus_space_handle_t sh; + bus_dma_tag_t parent_dmat; + + struct resource *reg, *irq; + int regtype, regid, irqid; + void *ih; + + struct emu_mem mem; + struct emu_voice voice[64]; + struct sc_chinfo pch, rch; +}; + +/* -------------------------------------------------------------------- */ + +/* + * prototypes + */ + +/* channel interface */ +static void *emuchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); +static int emuchan_setdir(void *data, int dir); +static int emuchan_setformat(void *data, u_int32_t format); +static int emuchan_setspeed(void *data, u_int32_t speed); +static int emuchan_setblocksize(void *data, u_int32_t blocksize); +static int emuchan_trigger(void *data, int go); +static int emuchan_getptr(void *data); +static pcmchan_caps *emuchan_getcaps(void *data); + +/* talk to the codec - called from ac97.c */ +static u_int32_t emu_rdcd(void *, int); +static void emu_wrcd(void *, int, u_int32_t); + +/* stuff */ +static int emu_init(struct sc_info *); +static void emu_intr(void *); +static void *emu_malloc(struct sc_info *sc, u_int32_t sz); +static void *emu_memalloc(struct sc_info *sc, u_int32_t sz); +#ifdef notyet +static int emu_memfree(struct sc_info *sc, void *buf); +#endif +static int emu_memstart(struct sc_info *sc, void *buf); + +/* talk to the card */ +static u_int32_t emu_rd(struct sc_info *, int, int); +static void emu_wr(struct sc_info *, int, u_int32_t, int); + +/* -------------------------------------------------------------------- */ + +static pcmchan_caps emu_reccaps = { + 4000, 48000, + AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE +}; + +static pcmchan_caps emu_playcaps = { + 4000, 48000, + AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE +}; + +static pcm_channel emu_chantemplate = { + emuchan_init, + emuchan_setdir, + emuchan_setformat, + emuchan_setspeed, + emuchan_setblocksize, + emuchan_trigger, + emuchan_getptr, + emuchan_getcaps, +}; + +/* -------------------------------------------------------------------- */ +/* Hardware */ +static u_int32_t +emu_rd(struct sc_info *sc, int regno, int size) +{ + switch (size) { + case 1: + return bus_space_read_1(sc->st, sc->sh, regno); + case 2: + return bus_space_read_2(sc->st, sc->sh, regno); + case 4: + return bus_space_read_4(sc->st, sc->sh, regno); + default: + return 0xffffffff; + } +} + +static void +emu_wr(struct sc_info *sc, int regno, u_int32_t data, int size) +{ + switch (size) { + case 1: + bus_space_write_1(sc->st, sc->sh, regno, data); + break; + case 2: + bus_space_write_2(sc->st, sc->sh, regno, data); + break; + case 4: + bus_space_write_4(sc->st, sc->sh, regno, data); + break; + } +} + +static u_int32_t +emu_rdptr(struct sc_info *sc, int chn, int reg) +{ + u_int32_t ptr, val, mask, size, offset; + + ptr = ((reg << 16) & PTR_ADDRESS_MASK) | (chn & PTR_CHANNELNUM_MASK); + emu_wr(sc, PTR, ptr, 4); + val = emu_rd(sc, DATA, 4); + if (reg & 0xff000000) { + size = (reg >> 24) & 0x3f; + offset = (reg >> 16) & 0x1f; + mask = ((1 << size) - 1) << offset; + val &= mask; + val >>= offset; + } + return val; +} + +static void +emu_wrptr(struct sc_info *sc, int chn, int reg, u_int32_t data) +{ + u_int32_t ptr, mask, size, offset; + + ptr = ((reg << 16) & PTR_ADDRESS_MASK) | (chn & PTR_CHANNELNUM_MASK); + emu_wr(sc, PTR, ptr, 4); + if (reg & 0xff000000) { + size = (reg >> 24) & 0x3f; + offset = (reg >> 16) & 0x1f; + mask = ((1 << size) - 1) << offset; + data <<= offset; + data &= mask; + data |= emu_rd(sc, DATA, 4) & ~mask; + } + emu_wr(sc, DATA, data, 4); +} + +static void +emu_wrefx(struct sc_info *sc, unsigned int pc, unsigned int data) +{ + emu_wrptr(sc, 0, MICROCODEBASE + pc, data); +} + +/* playback channel interrupts */ +static u_int32_t +emu_testint(struct sc_info *sc, char channel) +{ + int reg = (channel & 0x20)? CLIPH : CLIPL; + channel &= 0x1f; + reg |= 1 << 24; + reg |= channel << 16; + return emu_rdptr(sc, 0, reg); +} + +static void +emu_clrint(struct sc_info *sc, char channel) +{ + int reg = (channel & 0x20)? CLIPH : CLIPL; + channel &= 0x1f; + reg |= 1 << 24; + reg |= channel << 16; + emu_wrptr(sc, 0, reg, 1); +} + +static void +emu_enaint(struct sc_info *sc, char channel, int enable) +{ + int reg = (channel & 0x20)? CLIEH : CLIEL; + channel &= 0x1f; + reg |= 1 << 24; + reg |= channel << 16; + emu_wrptr(sc, 0, reg, enable); +} + +static void +emu_enastop(struct sc_info *sc, char channel, int enable) +{ + int reg = (channel & 0x20)? SOLEH : SOLEL; + channel &= 0x1f; + reg |= 1 << 24; + reg |= channel << 16; + emu_wrptr(sc, 0, reg, enable); +} + +/* ac97 codec */ +static u_int32_t +emu_rdcd(void *devinfo, int regno) +{ + struct sc_info *sc = (struct sc_info *)devinfo; + + emu_wr(sc, AC97ADDRESS, regno, 1); + return emu_rd(sc, AC97DATA, 2); +} + +static void +emu_wrcd(void *devinfo, int regno, u_int32_t data) +{ + struct sc_info *sc = (struct sc_info *)devinfo; + + emu_wr(sc, AC97ADDRESS, regno, 1); + emu_wr(sc, AC97DATA, data, 2); +} + +static u_int32_t +emu_rate_to_pitch(u_int32_t rate) +{ + static u_int32_t logMagTable[128] = { + 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2, + 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5, + 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081, + 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191, + 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, + 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, + 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e, + 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26, + 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d, + 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885, + 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, + 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, + 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, + 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3, + 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83, + 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df + }; + static char logSlopeTable[128] = { + 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58, + 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53, + 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f, + 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b, + 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47, + 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44, + 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41, + 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e, + 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, + 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37, + 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35, + 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f + }; + int i; + + if (rate == 0) + return 0; /* Bail out if no leading "1" */ + rate *= 11185; /* Scale 48000 to 0x20002380 */ + for (i = 31; i > 0; i--) { + if (rate & 0x80000000) { /* Detect leading "1" */ + return (((u_int32_t) (i - 15) << 20) + + logMagTable[0x7f & (rate >> 24)] + + (0x7f & (rate >> 17)) * + logSlopeTable[0x7f & (rate >> 24)]); + } + rate <<= 1; + } + + return 0; /* Should never reach this point */ +} + +static struct emu_voice * +emu_valloc(struct sc_info *sc) +{ + struct emu_voice *v; + int i; + + v = NULL; + for (i = 0; i < 64 && sc->voice[i].busy; i++); + if (i < 64) { + v = &sc->voice[i]; + v->busy = 1; + } + return v; +} + +static int +emu_vinit(struct sc_info *sc, struct emu_voice *m, struct emu_voice *s, + u_int32_t sz, pcm_channel *c) +{ + void *buf; + + buf = emu_memalloc(sc, sz); + if (buf == NULL) + return -1; + m->start = emu_memstart(sc, buf) * EMUPAGESIZE; + m->end = m->start + sz - 1; + m->channel = c; + m->speed = 0; + m->b16 = 0; + m->stereo = 0; + m->running = 0; + m->master = 1; + m->slave = s; + if (s != NULL) { + s->start = m->start; + s->end = m->end; + s->channel = NULL; + s->speed = 0; + s->b16 = 0; + s->stereo = 0; + s->running = 0; + s->master = 0; + s->slave = NULL; + } + if (c != NULL) { + c->buffer.buf = buf; + c->buffer.bufsize = sz; + } + return 0; +} + +static void +emu_vsetup(struct sc_chinfo *ch) +{ + struct emu_voice *v = ch->master; + + if (ch->fmt) { + v->b16 = (ch->fmt & AFMT_16BIT)? 1 : 0; + v->stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; + if (v->slave != NULL) { + v->slave->b16 = v->b16; + v->slave->stereo = v->stereo; + } + } + if (ch->spd) { + v->speed = ch->spd; + if (v->slave != NULL) + v->slave->speed = v->speed; + } +} + +static void +emu_vwrite(struct sc_info *sc, struct emu_voice *v) +{ + int s, l, r, p; + u_int32_t sa, ea, start = 0, val = 0, v2 = 0, sample, silent_page; + + s = (v->stereo? 1 : 0) + (v->b16? 1 : 0); + sa = v->start >> s; + ea = v->end >> s; + l = r = 255; + if (v->stereo) { + l = v->master? l : 0; + r = v->master? 0 : r; + } + p = emu_rate_to_pitch(v->speed) >> 8; + + emu_wrptr(sc, v->vnum, DCYSUSV, ENV_OFF); + emu_wrptr(sc, v->vnum, VTFT, VTFT_FILTERTARGET_MASK); + emu_wrptr(sc, v->vnum, CVCF, CVCF_CURRENTFILTER_MASK); + emu_wrptr(sc, v->vnum, FXRT, 0xd01c0000); + + emu_wrptr(sc, v->vnum, PTRX, (0xff << 8) | r); + if (v->master) { + val = 0x20; + if (v->stereo) { + val <<= 1; + emu_wrptr(sc, v->vnum, CPF, CPF_STEREO_MASK); + emu_wrptr(sc, v->slave->vnum, CPF, CPF_STEREO_MASK); + } else + emu_wrptr(sc, v->vnum, CPF, 0); + sample = 0x80808080; + if (v->b16) + sample = 0; + else + val <<= 1; + val -= 4; + /* + * mono 8bit: val = 0x3c + * stereo 8bit: val = 0x7c + * mono 16bit: val = 0x1c + * stereo 16bit: val = 0x3c + */ + if (v->stereo) { + v2 = 0x3c << 16; + emu_wrptr(sc, v->vnum, CCR, v2); + emu_wrptr(sc, v->slave->vnum, CCR, val << 16); + emu_wrptr(sc, v->slave->vnum, CDE, sample); + emu_wrptr(sc, v->slave->vnum, CDF, sample); + start = sa + val / 2; + } else { + v2 = 0x1c << 16; + emu_wrptr(sc, v->vnum, CCR, v2); + emu_wrptr(sc, v->vnum, CDE, sample); + emu_wrptr(sc, v->vnum, CDF, sample); + start = sa + val; + } + val <<= 25; + val |= v2; + /* + * mono 8bit: val = 0x781c0000 + * stereo 8bit: val = 0xf83c0000 + * mono 16bit: val = 0x381c0000 + * stereo 16bit: val = 0x783c0000 + */ + start |= CCCA_INTERPROM_0; + } + printf("val = 0x%x\n", val); + emu_wrptr(sc, v->vnum, DSL, ea); + emu_wrptr(sc, v->vnum, PSST, sa | (l << 24)); + emu_wrptr(sc, v->vnum, CCCA, start | (v->b16? 0 : CCCA_8BITSELECT)); + + emu_wrptr(sc, v->vnum, Z1, 0); + emu_wrptr(sc, v->vnum, Z2, 0); + + silent_page = ((u_int32_t)vtophys(sc->mem.silent_page) << 1) | MAP_PTI_MASK; + emu_wrptr(sc, v->vnum, MAPA, silent_page); + emu_wrptr(sc, v->vnum, MAPB, silent_page); + + emu_vdump(sc, v); + if (v->master) + emu_wrptr(sc, v->vnum, CCR, val); + + emu_wrptr(sc, v->vnum, ATKHLDV, ATKHLDV_HOLDTIME_MASK | ATKHLDV_ATTACKTIME_MASK); + emu_wrptr(sc, v->vnum, LFOVAL1, 0x8000); + emu_wrptr(sc, v->vnum, ATKHLDM, 0); + emu_wrptr(sc, v->vnum, DCYSUSM, DCYSUSM_DECAYTIME_MASK); + emu_wrptr(sc, v->vnum, LFOVAL2, 0x8000); + emu_wrptr(sc, v->vnum, IP, p); + emu_wrptr(sc, v->vnum, PEFE, 0x7f); + emu_wrptr(sc, v->vnum, FMMOD, 0); + emu_wrptr(sc, v->vnum, TREMFRQ, 0); + emu_wrptr(sc, v->vnum, FM2FRQ2, 0); + emu_wrptr(sc, v->vnum, ENVVAL, 0xbfff); + emu_wrptr(sc, v->vnum, ENVVOL, 0xbfff); + emu_wrptr(sc, v->vnum, IFATN, IFATN_FILTERCUTOFF_MASK); +} + +#define IP_TO_CP(ip) ((ip == 0) ? 0 : (((0x00001000uL | (ip & 0x00000FFFL)) << (((ip >> 12) & 0x000FL) + 4)) & 0xFFFF0000uL)) +static void +emu_vtrigger(struct sc_info *sc, struct emu_voice *v, int go) +{ + u_int32_t pitch_target; + if (go) { + pitch_target = IP_TO_CP((emu_rate_to_pitch(v->speed) >> 8)) >> 16; + emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, pitch_target); + emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, pitch_target); + emu_wrptr(sc, v->vnum, VTFT, 0xffff); + emu_wrptr(sc, v->vnum, CVCF, 0xffff); + emu_enastop(sc, v->vnum, 0); + if (v->master) + emu_enaint(sc, v->vnum, 1); + emu_wrptr(sc, v->vnum, DCYSUSV, ENV_ON | 0x00007f7f); + } else { + emu_wrptr(sc, v->vnum, IFATN, 0xffff); + emu_wrptr(sc, v->vnum, IP, 0); + emu_wrptr(sc, v->vnum, VTFT, 0xffff); + emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, 0); + emu_enaint(sc, v->vnum, 0); + } +} + +static int +emu_vpos(struct sc_info *sc, struct emu_voice *v) +{ + int s; + s = (v->b16? 1 : 0) + (v->stereo? 1 : 0); + return ((emu_rdptr(sc, v->vnum, CCCA) >> s) - v->start); +} + +#ifdef EMUDEBUG +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" }; + int i, x; + + printf("voice number %d\n", v->vnum); + for (i = 0, x = 0; i <= 0x1e; i++) { + if (regname[i] == NULL) + continue; + printf("%s\t[%08x]", regname[i], emu_rdptr(sc, v->vnum, i)); + printf("%s", (x == 2)? "\n" : "\t"); + x++; + if (x > 2) + x = 0; + } + printf("\n\n"); +} +#endif + +/* channel interface */ +void * +emuchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) +{ + struct sc_info *sc = devinfo; + struct sc_chinfo *ch; + + ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; + ch->buffer = b; + ch->parent = sc; + ch->channel = c; + ch->master = emu_valloc(sc); + ch->slave = emu_valloc(sc); + if (emu_vinit(sc, ch->master, ch->slave, EMU_BUFFSIZE, ch->channel)) + return NULL; + else + return ch; +} + +static int +emuchan_setdir(void *data, int dir) +{ + struct sc_chinfo *ch = data; + + ch->dir = dir; + return 0; +} + +static int +emuchan_setformat(void *data, u_int32_t format) +{ + struct sc_chinfo *ch = data; + + ch->fmt = format; + return 0; +} + +static int +emuchan_setspeed(void *data, u_int32_t speed) +{ + struct sc_chinfo *ch = data; + + ch->spd = speed; + return ch->spd; +} + +static int +emuchan_setblocksize(void *data, u_int32_t blocksize) +{ + return blocksize; +} + +static int +emuchan_trigger(void *data, int go) +{ + struct sc_chinfo *ch = data; + struct sc_info *sc = ch->parent; + + if (go == PCMTRIG_EMLDMAWR) return 0; + if (go == PCMTRIG_START) { + emu_vsetup(ch); + emu_vwrite(sc, ch->master); + emu_vwrite(sc, ch->slave); +#ifdef EMUDEBUG + printf("start [%d bit, %s, %d hz]\n", + ch->master->b16? 16 : 8, + ch->master->stereo? "stereo" : "mono", + ch->master->speed); + emu_vdump(sc, ch->master); + emu_vdump(sc, ch->slave); +#endif + } + emu_vtrigger(sc, ch->master, (go == PCMTRIG_START)? 1 : 0); + emu_vtrigger(sc, ch->slave, (go == PCMTRIG_START)? 1 : 0); + return 0; +} + +static int +emuchan_getptr(void *data) +{ + struct sc_chinfo *ch = data; + struct sc_info *sc = ch->parent; + + return emu_vpos(sc, ch->master); +} + +static pcmchan_caps * +emuchan_getcaps(void *data) +{ + struct sc_chinfo *ch = data; + + return (ch->dir == PCMDIR_PLAY)? &emu_playcaps : &emu_reccaps; +} + +/* The interrupt handler */ +static void +emu_intr(void *p) +{ + struct sc_info *sc = (struct sc_info *)p; + u_int32_t stat, i; + + do { + stat = emu_rd(sc, IPR, 4); + + /* process irq */ + for (i = 0; i < 64; i++) { + if (emu_testint(sc, i)) { + if (sc->voice[i].channel) + chn_intr(sc->voice[i].channel); + emu_clrint(sc, i); + } + } + + emu_wr(sc, IPR, stat, 4); + } while (stat); +} + +/* -------------------------------------------------------------------- */ + +static void * +emu_malloc(struct sc_info *sc, u_int32_t sz) +{ + void *buf; + bus_dmamap_t map; + + if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map)) + return NULL; + return buf; +} + +#ifdef notyet +static void +emu_free(struct sc_info *sc, void *buf) +{ + bus_dmamem_free(sc->parent_dmat, buf, NULL); +} +#endif + +static void * +emu_memalloc(struct sc_info *sc, u_int32_t sz) +{ + u_int32_t blksz, start, idx, ofs, tmp, found; + struct emu_mem *mem = &sc->mem; + struct emu_memblk *blk; + void *buf; + + blksz = sz / EMUPAGESIZE; + if (sz > (blksz * EMUPAGESIZE)) + blksz++; + /* find a free block in the bitmap */ + found = 0; + start = 0; + while (!found && start + blksz < MAXPAGES) { + found = 1; + for (idx = start; idx < start + blksz; idx++) + if (mem->bmap[idx >> 3] & (1 << (idx & 7))) + found = 0; + if (!found) + start++; + } + if (!found) + return NULL; + blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT); + if (blk == NULL) + return NULL; + buf = emu_malloc(sc, sz); + if (buf == NULL) { + free(blk, M_DEVBUF); + return NULL; + } + blk->buf = buf; + blk->pte_start = start; + blk->pte_size = blksz; + /* printf("buf %p, pte_start %d, pte_size %d\n", blk->buf, blk->pte_start, blk->pte_size); */ + ofs = 0; + for (idx = start; idx < start + blksz; idx++) { + mem->bmap[idx >> 3] |= 1 << (idx & 7); + tmp = (u_int32_t)vtophys((u_int8_t *)buf + ofs); + /* printf("pte[%d] -> %x phys, %x virt\n", idx, tmp, ((u_int32_t)buf) + ofs); */ + mem->ptb_pages[idx] = (tmp << 1); /* | idx; */ + ofs += EMUPAGESIZE; + } + SLIST_INSERT_HEAD(&mem->blocks, blk, link); + return buf; +} + +#ifdef notyet +static int +emu_memfree(struct sc_info *sc, void *buf) +{ + u_int32_t idx, tmp; + struct emu_mem *mem = &sc->mem; + struct emu_memblk *blk, *i; + + blk = NULL; + SLIST_FOREACH(i, &mem->blocks, link) { + if (i->buf == buf) + blk = i; + } + if (blk == NULL) + return EINVAL; + SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link); + emu_free(sc, buf); + tmp = (u_int32_t)vtophys(sc->mem.silent_page) << 1; + for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) { + mem->bmap[idx >> 3] &= ~(1 << (idx & 7)); + mem->ptb_pages[idx] = tmp | idx; + } + free(blk, M_DEVBUF); + return 0; +} +#endif + +static int +emu_memstart(struct sc_info *sc, void *buf) +{ + struct emu_mem *mem = &sc->mem; + struct emu_memblk *blk, *i; + + blk = NULL; + SLIST_FOREACH(i, &mem->blocks, link) { + if (i->buf == buf) + blk = i; + } + if (blk == NULL) + return -EINVAL; + return blk->pte_start; +} + +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); + (*pc)++; +} + +static void +emu_initefx(struct sc_info *sc) +{ + int i; + u_int32_t pc = 16; + + 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); +} + +/* Probe and attach the card */ +static int +emu_init(struct sc_info *sc) +{ + u_int32_t spcs, ch, tmp, i; + + /* disable audio and lock cache */ + emu_wr(sc, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE | HCFG_MUTEBUTTONENABLE, 4); + + /* reset recording buffers */ + emu_wrptr(sc, 0, MICBS, 0); + emu_wrptr(sc, 0, MICBA, 0); + emu_wrptr(sc, 0, FXBS, 0); + emu_wrptr(sc, 0, FXBA, 0); + emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE); + emu_wrptr(sc, 0, ADCBA, 0); + + /* disable channel interrupt */ + emu_wr(sc, INTE, DISABLE, 4); + emu_wrptr(sc, 0, CLIEL, 0); + emu_wrptr(sc, 0, CLIEH, 0); + emu_wrptr(sc, 0, SOLEL, 0); + emu_wrptr(sc, 0, SOLEH, 0); + + /* init envelope engine */ + for (ch = 0; ch < NUM_G; ch++) { + emu_wrptr(sc, ch, DCYSUSV, ENV_OFF); + emu_wrptr(sc, ch, IP, 0); + 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); + emu_wrptr(sc, ch, DSL, 0x10); + emu_wrptr(sc, ch, CCCA, 0); + emu_wrptr(sc, ch, Z1, 0); + emu_wrptr(sc, ch, Z2, 0); + emu_wrptr(sc, ch, FXRT, 0xd01c0000); + + emu_wrptr(sc, ch, ATKHLDM, 0); + emu_wrptr(sc, ch, DCYSUSM, 0); + emu_wrptr(sc, ch, IFATN, 0xffff); + emu_wrptr(sc, ch, PEFE, 0); + emu_wrptr(sc, ch, FMMOD, 0); + emu_wrptr(sc, ch, TREMFRQ, 24); /* 1 Hz */ + emu_wrptr(sc, ch, FM2FRQ2, 24); /* 1 Hz */ + emu_wrptr(sc, ch, TEMPENV, 0); + + /*** these are last so OFF prevents writing ***/ + emu_wrptr(sc, ch, LFOVAL2, 0); + emu_wrptr(sc, ch, LFOVAL1, 0); + emu_wrptr(sc, ch, ATKHLDV, 0); + emu_wrptr(sc, ch, ENVVOL, 0); + emu_wrptr(sc, ch, ENVVAL, 0); + + sc->voice[ch].vnum = ch; + sc->voice[ch].slave = NULL; + sc->voice[ch].busy = 0; + sc->voice[ch].running = 0; + sc->voice[ch].b16 = 0; + sc->voice[ch].stereo = 0; + sc->voice[ch].speed = 0; + sc->voice[ch].start = 0; + sc->voice[ch].end = 0; + sc->voice[ch].channel = NULL; + } + + /* + * Init to 0x02109204 : + * Clock accuracy = 0 (1000ppm) + * Sample Rate = 2 (48kHz) + * Audio Channel = 1 (Left of 2) + * Source Number = 0 (Unspecified) + * Generation Status = 1 (Original for Cat Code 12) + * Cat Code = 12 (Digital Signal Mixer) + * Mode = 0 (Mode 0) + * Emphasis = 0 (None) + * CP = 1 (Copyright unasserted) + * AN = 0 (Audio data) + * P = 0 (Consumer) + */ + spcs = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | + SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | + SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | + SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; + emu_wrptr(sc, 0, SPCS0, spcs); + emu_wrptr(sc, 0, SPCS1, spcs); + emu_wrptr(sc, 0, SPCS2, spcs); + + emu_initefx(sc); + + sc->mem.silent_page = emu_malloc(sc, EMUPAGESIZE); + if (sc->mem.silent_page == NULL) + return -1; + /* Clear page with silence & setup all pointers to this page */ + bzero(sc->mem.silent_page, EMUPAGESIZE); + + sc->mem.ptb_pages = emu_malloc(sc, MAXPAGES * sizeof(u_int32_t)); + if (sc->mem.ptb_pages == NULL) + return -1; + tmp = (u_int32_t)vtophys(sc->mem.silent_page) << 1; + for (i = 0; i < MAXPAGES; i++) + sc->mem.ptb_pages[i] = tmp | i; + emu_wrptr(sc, 0, PTB, vtophys(sc->mem.ptb_pages)); + emu_wrptr(sc, 0, TCB, 0); /* taken from original driver */ + emu_wrptr(sc, 0, TCBS, 4); /* taken from original driver */ + + for (ch = 0; ch < NUM_G; ch++) { + emu_wrptr(sc, ch, MAPA, tmp | MAP_PTI_MASK); + emu_wrptr(sc, ch, MAPB, tmp | MAP_PTI_MASK); + } + + /* emu_memalloc(sc, EMUPAGESIZE); */ + /* + * Hokay, now enable the AUD bit + * Enable Audio = 1 + * Mute Disable Audio = 0 + * Lock Tank Memory = 1 + * Lock Sound Memory = 0 + * Auto Mute = 1 + */ + tmp = HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE | 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); + } + } + + SLIST_INIT(&sc->mem.blocks); + + return 0; +} + +static int +emu_pci_probe(device_t dev) +{ + char *s = NULL; + + switch (pci_get_devid(dev)) { + case EMU10K1_PCI_ID: + s = "Creative EMU10K1"; + break; + } + + if (s) device_set_desc(dev, s); + return s? 0 : ENXIO; +} + +static int +emu_pci_attach(device_t dev) +{ + snddev_info *d; + u_int32_t data; + struct sc_info *sc; + struct ac97_info *codec; + int i, mapped; + char status[SND_STATUSLEN]; + + d = device_get_softc(dev); + if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { + device_printf(dev, "cannot allocate softc\n"); + return ENXIO; + } + + bzero(sc, sizeof(*sc)); + sc->type = pci_get_devid(dev); + sc->rev = pci_get_revid(dev); + + data = pci_read_config(dev, PCIR_COMMAND, 2); + data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); + pci_write_config(dev, PCIR_COMMAND, data, 2); + data = pci_read_config(dev, PCIR_COMMAND, 2); + + mapped = 0; + /* Xemu dfr: is this strictly necessary? */ + for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) { + sc->regid = PCIR_MAPS + i*4; + sc->regtype = SYS_RES_MEMORY; + sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, + 0, ~0, 1, RF_ACTIVE); + if (!sc->reg) { + sc->regtype = SYS_RES_IOPORT; + sc->reg = bus_alloc_resource(dev, sc->regtype, + &sc->regid, 0, ~0, 1, + RF_ACTIVE); + } + if (sc->reg) { + sc->st = rman_get_bustag(sc->reg); + sc->sh = rman_get_bushandle(sc->reg); + mapped++; + } + } + + if (mapped == 0) { + device_printf(dev, "unable to map register space\n"); + goto bad; + } + + if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, + /*lowaddr*/1 << 31, /* can only access 0-2gb */ + /*highaddr*/BUS_SPACE_MAXADDR, + /*filter*/NULL, /*filterarg*/NULL, + /*maxsize*/262144, /*nsegments*/1, /*maxsegz*/0x3ffff, + /*flags*/0, &sc->parent_dmat) != 0) { + device_printf(dev, "unable to create dma tag\n"); + goto bad; + } + + if (emu_init(sc) == -1) { + device_printf(dev, "unable to initialize the card\n"); + goto bad; + } + + codec = ac97_create(dev, sc, NULL, emu_rdcd, emu_wrcd); + if (codec == NULL) goto bad; + if (mixer_init(d, &ac97_mixer, codec) == -1) goto bad; + + sc->irqid = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, + 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); + if (!sc->irq || + bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, emu_intr, sc, &sc->ih)) { + device_printf(dev, "unable to map interrupt\n"); + goto bad; + } + + snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld", + (sc->regtype == SYS_RES_IOPORT)? "io" : "memory", + rman_get_start(sc->reg), rman_get_start(sc->irq)); + + if (pcm_register(dev, sc, 1, 0)) goto bad; + pcm_addchan(dev, PCMDIR_PLAY, &emu_chantemplate, sc); + /* pcm_addchan(dev, PCMDIR_REC, &emu_chantemplate, sc); */ + + pcm_setstatus(dev, status); + + return 0; + +bad: + if (sc->reg) bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); + if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); + if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); + free(sc, M_DEVBUF); + return ENXIO; +} + +static device_method_t emu_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, emu_pci_probe), + DEVMETHOD(device_attach, emu_pci_attach), + + { 0, 0 } +}; + +static driver_t emu_driver = { + "pcm", + emu_methods, + sizeof(snddev_info), +}; + +static devclass_t pcm_devclass; + +DRIVER_MODULE(emu, pci, emu_driver, pcm_devclass, 0, 0); diff --git a/sys/dev/sound/pci/emu10k1.h b/sys/dev/sound/pci/emu10k1.h new file mode 100644 index 0000000..69a1df6 --- /dev/null +++ b/sys/dev/sound/pci/emu10k1.h @@ -0,0 +1,666 @@ +/* + ********************************************************************** + * emu10k1.h, derived from 8010.h + * Copyright 1999, 2000 Creative Labs, Inc. + * + ********************************************************************** + * + * Date Author Summary of changes + * ---- ------ ------------------ + * October 20, 1999 Bertrand Lee base code release + * November 2, 1999 Alan Cox Cleaned of 8bit chars, DOS + * line endings + * December 8, 1999 Jon Taylor Added lots of new register info + * + ********************************************************************** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + * + ********************************************************************** + * $FreeBSD$ + */ + + +#ifndef _8010_H +#define _8010_H + +/* ------------------- DEFINES -------------------- */ + +#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)) + +/************************************************************************************************/ +/* PCI function 0 registers, address = <val> + PCIBASE0 */ +/************************************************************************************************/ + +#define PTR 0x00 /* Indexed register set pointer register */ + /* NOTE: The CHANNELNUM and ADDRESS words can */ + /* be modified independently of each other. */ +#define PTR_CHANNELNUM_MASK 0x0000003f /* For each per-channel register, indicates the */ + /* channel number of the register to be */ + /* accessed. For non per-channel registers the */ + /* value should be set to zero. */ +#define PTR_ADDRESS_MASK 0x07ff0000 /* Register index */ + +#define DATA 0x04 /* Indexed register set data register */ + +#define IPR 0x08 /* Global interrupt pending register */ + /* Clear pending interrupts by writing a 1 to */ + /* the relevant bits and zero to the other bits */ +#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 */ +#define IPR_PCIERROR 0x00200000 /* PCI bus error */ +#define IPR_VOLINCR 0x00100000 /* Volume increment button pressed */ +#define IPR_VOLDECR 0x00080000 /* Volume decrement button pressed */ +#define IPR_MUTE 0x00040000 /* Mute button pressed */ +#define IPR_MICBUFFULL 0x00020000 /* Microphone buffer full */ +#define IPR_MICBUFHALFFULL 0x00010000 /* Microphone buffer half full */ +#define IPR_ADCBUFFULL 0x00008000 /* ADC buffer full */ +#define IPR_ADCBUFHALFFULL 0x00004000 /* ADC buffer half full */ +#define IPR_EFXBUFFULL 0x00002000 /* Effects buffer full */ +#define IPR_EFXBUFHALFFULL 0x00001000 /* Effects buffer half full */ +#define IPR_GPSPDIFSTATUSCHANGE 0x00000800 /* GPSPDIF channel status change */ +#define IPR_CDROMSTATUSCHANGE 0x00000400 /* CD-ROM channel status change */ +#define IPR_INTERVALTIMER 0x00000200 /* Interval timer terminal count */ +#define IPR_MIDITRANSBUFEMPTY 0x00000100 /* MIDI UART transmit buffer empty */ +#define IPR_MIDIRECVBUFEMPTY 0x00000080 /* MIDI UART receive buffer empty */ +#define IPR_CHANNELLOOP 0x00000040 /* One or more channel loop interrupts pending */ +#define IPR_CHANNELNUMBERMASK 0x0000003f /* When IPR_CHANNELLOOP is set, indicates the */ + /* Highest set channel in CLIPL or CLIPH. When */ + /* IP is written with CL set, the bit in CLIPL */ + /* or CLIPH corresponding to the CIN value */ + /* written will be cleared. */ + +#define INTE 0x0c /* Interrupt enable register */ +#define INTE_VIRTUALSB_MASK 0xc0000000 /* Virtual Soundblaster I/O port capture */ +#define INTE_VIRTUALSB_220 0x00000000 /* Capture at I/O base address 0x220-0x22f */ +#define INTE_VIRTUALSB_240 0x40000000 /* Capture at I/O base address 0x240 */ +#define INTE_VIRTUALSB_260 0x80000000 /* Capture at I/O base address 0x260 */ +#define INTE_VIRTUALSB_280 0xc0000000 /* Capture at I/O base address 0x280 */ +#define INTE_VIRTUALMPU_MASK 0x30000000 /* Virtual MPU I/O port capture */ +#define INTE_VIRTUALMPU_300 0x00000000 /* Capture at I/O base address 0x300-0x301 */ +#define INTE_VIRTUALMPU_310 0x10000000 /* Capture at I/O base address 0x310 */ +#define INTE_VIRTUALMPU_320 0x20000000 /* Capture at I/O base address 0x320 */ +#define INTE_VIRTUALMPU_330 0x30000000 /* Capture at I/O base address 0x330 */ +#define INTE_MASTERDMAENABLE 0x08000000 /* Master DMA emulation at 0x000-0x00f */ +#define INTE_SLAVEDMAENABLE 0x04000000 /* Slave DMA emulation at 0x0c0-0x0df */ +#define INTE_MASTERPICENABLE 0x02000000 /* Master PIC emulation at 0x020-0x021 */ +#define INTE_SLAVEPICENABLE 0x01000000 /* Slave PIC emulation at 0x0a0-0x0a1 */ +#define INTE_VSBENABLE 0x00800000 /* Enable virtual Soundblaster */ +#define INTE_ADLIBENABLE 0x00400000 /* Enable AdLib emulation at 0x388-0x38b */ +#define INTE_MPUENABLE 0x00200000 /* Enable virtual MPU */ +#define INTE_FORCEINT 0x00100000 /* Continuously assert INTAN */ + +#define INTE_MRHANDENABLE 0x00080000 /* Enable the "Mr. Hand" logic */ + /* NOTE: There is no reason to use this under */ + /* Linux, and it will cause odd hardware */ + /* behavior and possibly random segfaults and */ + /* lockups if enabled. */ + +#define INTE_SAMPLERATETRACKER 0x00002000 /* Enable sample rate tracker interrupts */ + /* NOTE: This bit must always be enabled */ +#define INTE_FXDSPENABLE 0x00001000 /* Enable FX DSP interrupts */ +#define INTE_PCIERRORENABLE 0x00000800 /* Enable PCI bus error interrupts */ +#define INTE_VOLINCRENABLE 0x00000400 /* Enable volume increment button interrupts */ +#define INTE_VOLDECRENABLE 0x00000200 /* Enable volume decrement button interrupts */ +#define INTE_MUTEENABLE 0x00000100 /* Enable mute button interrupts */ +#define INTE_MICBUFENABLE 0x00000080 /* Enable microphone buffer interrupts */ +#define INTE_ADCBUFENABLE 0x00000040 /* Enable ADC buffer interrupts */ +#define INTE_EFXBUFENABLE 0x00000020 /* Enable Effects buffer interrupts */ +#define INTE_GPSPDIFENABLE 0x00000010 /* Enable GPSPDIF status interrupts */ +#define INTE_CDSPDIFENABLE 0x00000008 /* Enable CDSPDIF status interrupts */ +#define INTE_INTERVALTIMERENB 0x00000004 /* Enable interval timer interrupts */ +#define INTE_MIDITXENABLE 0x00000002 /* Enable MIDI transmit-buffer-empty interrupts */ +#define INTE_MIDIRXENABLE 0x00000001 /* Enable MIDI receive-buffer-empty interrupts */ + +#define WC 0x10 /* Wall Clock register */ +#define WC_SAMPLECOUNTER_MASK 0x03FFFFC0 /* Sample periods elapsed since reset */ +#define WC_SAMPLECOUNTER 0x14060010 +#define WC_CURRENTCHANNEL 0x0000003F /* Channel [0..63] currently being serviced */ + /* NOTE: Each channel takes 1/64th of a sample */ + /* period to be serviced. */ + +#define HCFG 0x14 /* Hardware config register */ + /* NOTE: There is no reason to use the legacy */ + /* SoundBlaster emulation stuff described below */ + /* under Linux, and all kinds of weird hardware */ + /* behavior can result if you try. Don't. */ +#define HCFG_LEGACYFUNC_MASK 0xe0000000 /* Legacy function number */ +#define HCFG_LEGACYFUNC_MPU 0x00000000 /* Legacy MPU */ +#define HCFG_LEGACYFUNC_SB 0x40000000 /* Legacy SB */ +#define HCFG_LEGACYFUNC_AD 0x60000000 /* Legacy AD */ +#define HCFG_LEGACYFUNC_MPIC 0x80000000 /* Legacy MPIC */ +#define HCFG_LEGACYFUNC_MDMA 0xa0000000 /* Legacy MDMA */ +#define HCFG_LEGACYFUNC_SPCI 0xc0000000 /* Legacy SPCI */ +#define HCFG_LEGACYFUNC_SDMA 0xe0000000 /* Legacy SDMA */ +#define HCFG_IOCAPTUREADDR 0x1f000000 /* The 4 LSBs of the captured I/O address. */ +#define HCFG_LEGACYWRITE 0x00800000 /* 1 = write, 0 = read */ +#define HCFG_LEGACYWORD 0x00400000 /* 1 = word, 0 = byte */ +#define HCFG_LEGACYINT 0x00200000 /* 1 = legacy event captured. Write 1 to clear. */ + /* NOTE: The rest of the bits in this register */ + /* _are_ relevant under Linux. */ +#define HCFG_CODECFORMAT_MASK 0x00070000 /* CODEC format */ +#define HCFG_CODECFORMAT_AC97 0x00000000 /* AC97 CODEC format -- Primary Output */ +#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_JOYENABLE 0x00000200 /* Internal joystick enable */ +#define HCFG_PHASETRACKENABLE 0x00000100 /* Phase tracking enable */ + /* 1 = Force all 3 async digital inputs to use */ + /* the same async sample rate tracker (ZVIDEO) */ +#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_AUTOMUTE 0x00000010 /* When set, the async sample rate convertors */ + /* will automatically mute their output when */ + /* they are not rate-locked to the external */ + /* async audio source */ +#define HCFG_LOCKSOUNDCACHE 0x00000008 /* 1 = Cancel bustmaster accesses to soundcache */ + /* NOTE: This should generally never be used. */ +#define HCFG_LOCKTANKCACHE 0x00000004 /* 1 = Cancel bustmaster accesses to tankcache */ + /* NOTE: This should generally never be used. */ +#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 */ + /* in general should not be used unless a more */ + /* sophisticated master mute function has not */ + /* been written. */ +#define HCFG_AUDIOENABLE 0x00000001 /* 0 = CODECs transmit zero-valued samples */ + /* Should be set to 1 when the EMU10K1 is */ + /* completely initialized. */ + +#define MUDATA 0x18 /* MPU401 data register (8 bits) */ + +#define MUCMD 0x19 /* MPU401 command register (8 bits) */ +#define MUCMD_RESET 0xff /* RESET command */ +#define MUCMD_ENTERUARTMODE 0x3f /* Enter_UART_mode command */ + /* NOTE: All other commands are ignored */ + +#define MUSTAT MUCMD /* MPU401 status register (8 bits) */ +#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 */ + /* 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 */ + /* 0 == 1024 periods, [1..4] are not useful */ +#define TIMER_RATE 0x0a00001a + +#define AC97DATA 0x1c /* AC97 register set data register (16 bit) */ + +#define AC97ADDRESS 0x1e /* AC97 register set address register (8 bit) */ +#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_GENERALPUPOSE 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 */ +/********************************************************************************************************/ + +#define CPF 0x00 /* Current pitch and fraction register */ +#define CPF_CURRENTPITCH_MASK 0xffff0000 /* Current pitch (linear, 0x4000 == unity pitch shift) */ +#define CPF_CURRENTPITCH 0x10100000 +#define CPF_STEREO_MASK 0x00008000 /* 1 = Even channel interleave, odd channel locked */ +#define CPF_STOP_MASK 0x00004000 /* 1 = Current pitch forced to 0 */ +#define CPF_FRACADDRESS_MASK 0x00003fff /* Linear fractional address of the current channel */ + +#define PTRX 0x01 /* Pitch target and send A/B amounts register */ +#define PTRX_PITCHTARGET_MASK 0xffff0000 /* Pitch target of specified channel */ +#define PTRX_PITCHTARGET 0x10100001 +#define PTRX_FXSENDAMOUNT_A_MASK 0x0000ff00 /* Linear level of channel output sent to FX send bus A */ +#define PTRX_FXSENDAMOUNT_A 0x08080001 +#define PTRX_FXSENDAMOUNT_B_MASK 0x000000ff /* Linear level of channel output sent to FX send bus B */ +#define PTRX_FXSENDAMOUNT_B 0x08000001 + +#define CVCF 0x02 /* Current volume and filter cutoff register */ +#define CVCF_CURRENTVOL_MASK 0xffff0000 /* Current linear volume of specified channel */ +#define CVCF_CURRENTVOL 0x10100002 +#define CVCF_CURRENTFILTER_MASK 0x0000ffff /* Current filter cutoff frequency of specified channel */ +#define CVCF_CURRENTFILTER 0x10000002 + +#define VTFT 0x03 /* Volume target and filter cutoff target register */ +#define VTFT_VOLUMETARGET_MASK 0xffff0000 /* Volume target of specified channel */ +#define VTFT_FILTERTARGET_MASK 0x0000ffff /* Filter cutoff target of specified channel */ + +#define Z1 0x05 /* Filter delay memory 1 register */ + +#define Z2 0x04 /* Filter delay memory 2 register */ + +#define PSST 0x06 /* Send C amount and loop start address register */ +#define PSST_FXSENDAMOUNT_C_MASK 0xff000000 /* Linear level of channel output sent to FX send bus C */ + +#define PSST_FXSENDAMOUNT_C 0x08180006 + +#define PSST_LOOPSTARTADDR_MASK 0x00ffffff /* Loop start address of the specified channel */ +#define PSST_LOOPSTARTADDR 0x18000006 + +#define DSL 0x07 /* Send D amount and loop start address register */ +#define DSL_FXSENDAMOUNT_D_MASK 0xff000000 /* Linear level of channel output sent to FX send bus D */ + +#define DSL_FXSENDAMOUNT_D 0x08180007 + +#define DSL_LOOPENDADDR_MASK 0x00ffffff /* Loop end address of the specified channel */ +#define DSL_LOOPENDADDR 0x18000007 + +#define CCCA 0x08 /* Filter Q, interp. ROM, byte size, cur. addr register */ +#define CCCA_RESONANCE 0xf0000000 /* Lowpass filter resonance (Q) height */ +#define CCCA_INTERPROMMASK 0x0e000000 /* Selects passband of interpolation ROM */ + /* 1 == full band, 7 == lowpass */ + /* ROM 0 is used when pitch shifting downward or less */ + /* then 3 semitones upward. Increasingly higher ROM */ + /* numbers are used, typically in steps of 3 semitones, */ + /* as upward pitch shifting is performed. */ +#define CCCA_INTERPROM_0 0x00000000 /* Select interpolation ROM 0 */ +#define CCCA_INTERPROM_1 0x02000000 /* Select interpolation ROM 1 */ +#define CCCA_INTERPROM_2 0x04000000 /* Select interpolation ROM 2 */ +#define CCCA_INTERPROM_3 0x06000000 /* Select interpolation ROM 3 */ +#define CCCA_INTERPROM_4 0x08000000 /* Select interpolation ROM 4 */ +#define CCCA_INTERPROM_5 0x0a000000 /* Select interpolation ROM 5 */ +#define CCCA_INTERPROM_6 0x0c000000 /* Select interpolation ROM 6 */ +#define CCCA_INTERPROM_7 0x0e000000 /* Select interpolation ROM 7 */ +#define CCCA_8BITSELECT 0x01000000 /* 1 = Sound memory for this channel uses 8-bit samples */ +#define CCCA_CURRADDR_MASK 0x00ffffff /* Current address of the selected channel */ +#define CCCA_CURRADDR 0x18000008 + +#define CCR 0x09 /* Cache control register */ +#define CCR_CACHEINVALIDSIZE 0xfe000000 /* Number of invalid samples cache for this channel */ +#define CCR_CACHELOOPFLAG 0x01000000 /* 1 = Cache has a loop service pending */ +#define CCR_INTERLEAVEDSAMPLES 0x00800000 /* 1 = A cache service will fetch interleaved samples */ +#define CCR_WORDSIZEDSAMPLES 0x00400000 /* 1 = A cache service will fetch word sized samples */ +#define CCR_READADDRESS_MASK 0x003f0000 /* Location of cache just beyond current cache service */ +#define CCR_LOOPINVALSIZE 0x0000fe00 /* Number of invalid samples in cache prior to loop */ + /* NOTE: This is valid only if CACHELOOPFLAG is set */ +#define CCR_LOOPFLAG 0x00000100 /* Set for a single sample period when a loop occurs */ +#define CCR_CACHELOOPADDRHI 0x000000ff /* DSL_LOOPSTARTADDR's hi byte if CACHELOOPFLAG is set */ + +#define CLP 0x0a /* Cache loop register (valid if CCR_CACHELOOPFLAG = 1) */ + /* NOTE: This register is normally not used */ +#define CLP_CACHELOOPADDR 0x0000ffff /* Cache loop address (DSL_LOOPSTARTADDR [0..15]) */ + +#define FXRT 0x0b /* Effects send routing register */ + /* NOTE: It is illegal to assign the same routing to */ + /* two effects sends. */ +#define FXRT_CHANNELA 0x000f0000 /* Effects send bus number for channel's effects send A */ +#define FXRT_CHANNELB 0x00f00000 /* Effects send bus number for channel's effects send B */ +#define FXRT_CHANNELC 0x0f000000 /* Effects send bus number for channel's effects send C */ +#define FXRT_CHANNELD 0xf0000000 /* Effects send bus number for channel's effects send D */ + +#define MAPA 0x0c /* Cache map A */ + +#define MAPB 0x0d /* Cache map B */ + +#define MAP_PTE_MASK 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ +#define MAP_PTI_MASK 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ + +#define ENVVOL 0x10 /* Volume envelope register */ +#define ENVVOL_MASK 0x0000ffff /* Current value of volume envelope state variable */ + /* 0x8000-n == 666*n usec delay */ + +#define ATKHLDV 0x11 /* Volume envelope hold and attack register */ +#define ATKHLDV_PHASE0 0x00008000 /* 0 = Begin attack phase */ +#define ATKHLDV_HOLDTIME_MASK 0x00007f00 /* Envelope hold time (127-n == n*88.2msec) */ +#define ATKHLDV_ATTACKTIME_MASK 0x0000007f /* Envelope attack time, log encoded */ + /* 0 = infinite, 1 = 10.9msec, ... 0x7f = 5.5msec */ + +#define DCYSUSV 0x12 /* Volume envelope sustain and decay register */ +#define DCYSUSV_PHASE1_MASK 0x00008000 /* 0 = Begin attack phase, 1 = begin release phase */ +#define DCYSUSV_SUSTAINLEVEL_MASK 0x00007f00 /* 127 = full, 0 = off, 0.75dB increments */ +#define DCYSUSV_CHANNELENABLE_MASK 0x00000080 /* 1 = Inhibit envelope engine from writing values in */ + /* this channel and from writing to pitch, filter and */ + /* volume targets. */ +#define DCYSUSV_DECAYTIME_MASK 0x0000007f /* Volume envelope decay time, log encoded */ + /* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec */ + +#define LFOVAL1 0x13 /* Modulation LFO value */ +#define LFOVAL_MASK 0x0000ffff /* Current value of modulation LFO state variable */ + /* 0x8000-n == 666*n usec delay */ + +#define ENVVAL 0x14 /* Modulation envelope register */ +#define ENVVAL_MASK 0x0000ffff /* Current value of modulation envelope state variable */ + /* 0x8000-n == 666*n usec delay */ + +#define ATKHLDM 0x15 /* Modulation envelope hold and attack register */ +#define ATKHLDM_PHASE0 0x00008000 /* 0 = Begin attack phase */ +#define ATKHLDM_HOLDTIME 0x00007f00 /* Envelope hold time (127-n == n*42msec) */ +#define ATKHLDM_ATTACKTIME 0x0000007f /* Envelope attack time, log encoded */ + /* 0 = infinite, 1 = 11msec, ... 0x7f = 5.5msec */ + +#define DCYSUSM 0x16 /* Modulation envelope decay and sustain register */ +#define DCYSUSM_PHASE1_MASK 0x00008000 /* 0 = Begin attack phase, 1 = begin release phase */ +#define DCYSUSM_SUSTAINLEVEL_MASK 0x00007f00 /* 127 = full, 0 = off, 0.75dB increments */ +#define DCYSUSM_DECAYTIME_MASK 0x0000007f /* Envelope decay time, log encoded */ + /* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec */ + +#define LFOVAL2 0x17 /* Vibrato LFO register */ +#define LFOVAL2_MASK 0x0000ffff /* Current value of vibrato LFO state variable */ + /* 0x8000-n == 666*n usec delay */ + +#define IP 0x18 /* Initial pitch register */ +#define IP_MASK 0x0000ffff /* Exponential initial pitch shift */ + /* 4 bits of octave, 12 bits of fractional octave */ +#define IP_UNITY 0x0000e000 /* Unity pitch shift */ + +#define IFATN 0x19 /* Initial filter cutoff and attenuation register */ +#define IFATN_FILTERCUTOFF_MASK 0x0000ff00 /* Initial filter cutoff frequency in exponential units */ + /* 6 most significant bits are semitones */ + /* 2 least significant bits are fractions */ +#define IFATN_FILTERCUTOFF 0x08080019 +#define IFATN_ATTENUATION_MASK 0x000000ff /* Initial attenuation in 0.375dB steps */ +#define IFATN_ATTENUATION 0x08000019 + + +#define PEFE 0x1a /* Pitch envelope and filter envelope amount register */ +#define PEFE_PITCHAMOUNT_MASK 0x0000ff00 /* Pitch envlope amount */ + /* Signed 2's complement, +/- one octave peak extremes */ +#define PEFE_PITCHAMOUNT 0x0808001a +#define PEFE_FILTERAMOUNT_MASK 0x000000ff /* Filter envlope amount */ + /* Signed 2's complement, +/- six octaves peak extremes */ +#define PEFE_FILTERAMOUNT 0x0800001a +#define FMMOD 0x1b /* Vibrato/filter modulation from LFO register */ +#define FMMOD_MODVIBRATO 0x0000ff00 /* Vibrato LFO modulation depth */ + /* Signed 2's complement, +/- one octave extremes */ +#define FMMOD_MOFILTER 0x000000ff /* Filter LFO modulation depth */ + /* Signed 2's complement, +/- three octave extremes */ + + +#define TREMFRQ 0x1c /* Tremolo amount and modulation LFO frequency register */ +#define TREMFRQ_DEPTH 0x0000ff00 /* Tremolo depth */ + /* Signed 2's complement, with +/- 12dB extremes */ + +#define FM2FRQ2 0x1d /* Vibrato amount and vibrato LFO frequency register */ +#define FM2FRQ2_DEPTH 0x0000ff00 /* Vibrato LFO vibrato depth */ + /* Signed 2's complement, +/- one octave extremes */ +#define FM2FRQ2_FREQUENCY 0x000000ff /* Vibrato LFO frequency */ + /* 0.039Hz steps, maximum of 9.85 Hz. */ + +#define TEMPENV 0x1e /* Tempory envelope register */ +#define TEMPENV_MASK 0x0000ffff /* 16-bit value */ + /* NOTE: All channels contain internal variables; do */ + /* not write to these locations. */ + +#define CD0 0x20 /* Cache data 0 register */ +#define CD1 0x21 /* Cache data 1 register */ +#define CD2 0x22 /* Cache data 2 register */ +#define CD3 0x23 /* Cache data 3 register */ +#define CD4 0x24 /* Cache data 4 register */ +#define CD5 0x25 /* Cache data 5 register */ +#define CD6 0x26 /* Cache data 6 register */ +#define CD7 0x27 /* Cache data 7 register */ +#define CD8 0x28 /* Cache data 8 register */ +#define CD9 0x29 /* Cache data 9 register */ +#define CDA 0x2a /* Cache data A register */ +#define CDB 0x2b /* Cache data B register */ +#define CDC 0x2c /* Cache data C register */ +#define CDD 0x2d /* Cache data D register */ +#define CDE 0x2e /* Cache data E register */ +#define CDF 0x2f /* Cache data F register */ + +#define PTB 0x40 /* Page table base register */ +#define PTB_MASK 0xfffff000 /* Physical address of the page table in host memory */ + +#define TCB 0x41 /* Tank cache base register */ +#define TCB_MASK 0xfffff000 /* Physical address of the bottom of host based TRAM */ + +#define ADCCR 0x42 /* ADC sample rate/stereo control register */ +#define ADCCR_RCHANENABLE 0x00000010 /* Enables right channel for writing to the host */ +#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 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 */ +#define ADCCR_SAMPLERATE_24 0x00000003 /* 24kHz sample rate */ +#define ADCCR_SAMPLERATE_22 0x00000004 /* 22.05kHz sample rate */ +#define ADCCR_SAMPLERATE_16 0x00000005 /* 16kHz sample rate */ +#define ADCCR_SAMPLERATE_11 0x00000006 /* 11.025kHz sample rate */ +#define ADCCR_SAMPLERATE_8 0x00000007 /* 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 */ + +#define TCBS 0x44 /* Tank cache buffer size register */ +#define TCBS_MASK 0x00000007 /* Tank cache buffer size field */ +#define TCBS_BUFFSIZE_16K 0x00000000 +#define TCBS_BUFFSIZE_32K 0x00000001 +#define TCBS_BUFFSIZE_64K 0x00000002 +#define TCBS_BUFFSIZE_128K 0x00000003 +#define TCBS_BUFFSIZE_256K 0x00000004 +#define TCBS_BUFFSIZE_512K 0x00000005 +#define TCBS_BUFFSIZE_1024K 0x00000006 +#define TCBS_BUFFSIZE_2048K 0x00000007 + +#define MICBA 0x45 /* AC97 microphone buffer address register */ +#define MICBA_MASK 0xfffff000 /* 20 bit base address */ + +#define ADCBA 0x46 /* ADC buffer address register */ +#define ADCBA_MASK 0xfffff000 /* 20 bit base address */ + +#define FXBA 0x47 /* FX Buffer Address */ +#define FXBA_MASK 0xfffff000 /* 20 bit base address */ + +#define MICBS 0x49 /* Microphone buffer size register */ + +#define ADCBS 0x4a /* ADC buffer size register */ + +#define FXBS 0x4b /* FX buffer size register */ + +/* The following mask values define the size of the ADC, MIX and FX buffers in bytes */ +#define ADCBS_BUFSIZE_NONE 0x00000000 +#define ADCBS_BUFSIZE_384 0x00000001 +#define ADCBS_BUFSIZE_448 0x00000002 +#define ADCBS_BUFSIZE_512 0x00000003 +#define ADCBS_BUFSIZE_640 0x00000004 +#define ADCBS_BUFSIZE_768 0x00000005 +#define ADCBS_BUFSIZE_896 0x00000006 +#define ADCBS_BUFSIZE_1024 0x00000007 +#define ADCBS_BUFSIZE_1280 0x00000008 +#define ADCBS_BUFSIZE_1536 0x00000009 +#define ADCBS_BUFSIZE_1792 0x0000000a +#define ADCBS_BUFSIZE_2048 0x0000000b +#define ADCBS_BUFSIZE_2560 0x0000000c +#define ADCBS_BUFSIZE_3072 0x0000000d +#define ADCBS_BUFSIZE_3584 0x0000000e +#define ADCBS_BUFSIZE_4096 0x0000000f +#define ADCBS_BUFSIZE_5120 0x00000010 +#define ADCBS_BUFSIZE_6144 0x00000011 +#define ADCBS_BUFSIZE_7168 0x00000012 +#define ADCBS_BUFSIZE_8192 0x00000013 +#define ADCBS_BUFSIZE_10240 0x00000014 +#define ADCBS_BUFSIZE_12288 0x00000015 +#define ADCBS_BUFSIZE_14366 0x00000016 +#define ADCBS_BUFSIZE_16384 0x00000017 +#define ADCBS_BUFSIZE_20480 0x00000018 +#define ADCBS_BUFSIZE_24576 0x00000019 +#define ADCBS_BUFSIZE_28672 0x0000001a +#define ADCBS_BUFSIZE_32768 0x0000001b +#define ADCBS_BUFSIZE_40960 0x0000001c +#define ADCBS_BUFSIZE_49152 0x0000001d +#define ADCBS_BUFSIZE_57344 0x0000001e +#define ADCBS_BUFSIZE_65536 0x0000001f + + +#define CDCS 0x50 /* CD-ROM digital channel status register */ + +#define GPSCS 0x51 /* General Purpose SPDIF channel status register*/ + +#define DBG 0x52 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ + +#define REG53 0x53 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ + +#define SPCS0 0x54 /* SPDIF output Channel Status 0 register */ + +#define SPCS1 0x55 /* SPDIF output Channel Status 1 register */ + +#define SPCS2 0x56 /* SPDIF output Channel Status 2 register */ + +#define SPCS_CLKACCYMASK 0x30000000 /* Clock accuracy */ +#define SPCS_CLKACCY_1000PPM 0x00000000 /* 1000 parts per million */ +#define SPCS_CLKACCY_50PPM 0x10000000 /* 50 parts per million */ +#define SPCS_CLKACCY_VARIABLE 0x20000000 /* Variable accuracy */ +#define SPCS_SAMPLERATEMASK 0x0f000000 /* Sample rate */ +#define SPCS_SAMPLERATE_44 0x00000000 /* 44.1kHz sample rate */ +#define SPCS_SAMPLERATE_48 0x02000000 /* 48kHz sample rate */ +#define SPCS_SAMPLERATE_32 0x03000000 /* 32kHz sample rate */ +#define SPCS_CHANNELNUMMASK 0x00f00000 /* Channel number */ +#define SPCS_CHANNELNUM_UNSPEC 0x00000000 /* Unspecified channel number */ +#define SPCS_CHANNELNUM_LEFT 0x00100000 /* Left channel */ +#define SPCS_CHANNELNUM_RIGHT 0x00200000 /* Right channel */ +#define SPCS_SOURCENUMMASK 0x000f0000 /* Source number */ +#define SPCS_SOURCENUM_UNSPEC 0x00000000 /* Unspecified source number */ +#define SPCS_GENERATIONSTATUS 0x00008000 /* Originality flag (see IEC-958 spec) */ +#define SPCS_CATEGORYCODEMASK 0x00007f00 /* Category code (see IEC-958 spec) */ +#define SPCS_MODEMASK 0x000000c0 /* Mode (see IEC-958 spec) */ +#define SPCS_EMPHASISMASK 0x00000038 /* Emphasis */ +#define SPCS_EMPHASIS_NONE 0x00000000 /* No emphasis */ +#define SPCS_EMPHASIS_50_15 0x00000008 /* 50/15 usec 2 channel */ +#define SPCS_COPYRIGHT 0x00000004 /* Copyright asserted flag -- do not modify */ +#define SPCS_NOTAUDIODATA 0x00000002 /* 0 = Digital audio, 1 = not audio */ +#define SPCS_PROFESSIONAL 0x00000001 /* 0 = Consumer (IEC-958), 1 = pro (AES3-1992) */ + +/* The 32-bit CLIx and SOLx registers all have one bit per channel control/status */ +#define CLIEL 0x58 /* Channel loop interrupt enable low register */ + +#define CLIEH 0x59 /* Channel loop interrupt enable high register */ + +#define CLIPL 0x5a /* Channel loop interrupt pending low register */ + +#define CLIPH 0x5b /* Channel loop interrupt pending high register */ + +#define SOLEL 0x5c /* Stop on loop enable low register */ + +#define SOLEH 0x5d /* Stop on loop enable high register */ + +#define SPBYPASS 0x5e /* SPDIF BYPASS mode register */ +#define SPBYPASS_ENABLE 0x00000001 /* Enable SPDIF bypass mode */ + +#define CDSRCS 0x60 /* CD-ROM Sample Rate Converter status register */ + +#define GPSRCS 0x61 /* General Purpose SPDIF sample rate cvt status */ + +#define ZVSRCS 0x62 /* ZVideo sample rate converter status */ + /* NOTE: This one has no SPDIFLOCKED field */ + /* Assumes sample lock */ + +/* These three bitfields apply to CDSRCS, GPSRCS, and (except as noted) ZVSRCS. */ +#define SRCS_SPDIFLOCKED 0x02000000 /* SPDIF stream locked */ +#define SRCS_RATELOCKED 0x01000000 /* Sample rate locked */ +#define SRCS_ESTSAMPLERATE 0x0007ffff /* Do not modify this field. */ + +#define MICIDX 0x63 /* Microphone recording buffer index register */ +#define MICIDX_MASK 0x0000ffff /* 16-bit value */ +#define MICIDX_IDX 0x10000063 + +#define ADCIDX 0x64 /* ADC recording buffer index register */ +#define ADCIDX_MASK 0x0000ffff /* 16 bit index field */ +#define ADCIDX_IDX 0x10000064 + +#define FXIDX 0x65 /* FX recording buffer index register */ +#define FXIDX_MASK 0x0000ffff /* 16-bit value */ +#define FXIDX_IDX 0x10000065 + +/* Each FX general purpose register is 32 bits in length, all bits are used */ +#define FXGPREGBASE 0x100 /* FX general purpose registers base */ + +/* 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. */ +#define TANKMEMDATAREGBASE 0x200 /* Tank memory data registers base */ +#define TANKMEMDATAREG_MASK 0x000fffff /* 20 bit tank audio data field */ + +/* Combined address field and memory opcode or flag field. 160 locations, last 32 are external */ +#define TANKMEMADDRREGBASE 0x300 /* Tank memory address registers base */ +#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */ +#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */ +#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */ +#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */ +#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */ + +#define MICROCODEBASE 0x400 /* Microcode data base address */ + +/* Each DSP microcode instruction is mapped into 2 doublewords */ +/* NOTE: When writing, always write the LO doubleword first. Reads can be in either order. */ +#define LOWORD_OPX_MASK 0x000ffc00 /* Instruction operand X */ +#define LOWORD_OPY_MASK 0x000003ff /* Instruction operand Y */ +#define HIWORD_OPCODE_MASK 0x00f00000 /* Instruction opcode */ +#define HIWORD_RESULT_MASK 0x000ffc00 /* Instruction result */ +#define HIWORD_OPA_MASK 0x000003ff /* Instruction operand A */ + +#endif /* _8010_H */ diff --git a/sys/gnu/dev/sound/pci/emu10k1.h b/sys/gnu/dev/sound/pci/emu10k1.h new file mode 100644 index 0000000..69a1df6 --- /dev/null +++ b/sys/gnu/dev/sound/pci/emu10k1.h @@ -0,0 +1,666 @@ +/* + ********************************************************************** + * emu10k1.h, derived from 8010.h + * Copyright 1999, 2000 Creative Labs, Inc. + * + ********************************************************************** + * + * Date Author Summary of changes + * ---- ------ ------------------ + * October 20, 1999 Bertrand Lee base code release + * November 2, 1999 Alan Cox Cleaned of 8bit chars, DOS + * line endings + * December 8, 1999 Jon Taylor Added lots of new register info + * + ********************************************************************** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + * + ********************************************************************** + * $FreeBSD$ + */ + + +#ifndef _8010_H +#define _8010_H + +/* ------------------- DEFINES -------------------- */ + +#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)) + +/************************************************************************************************/ +/* PCI function 0 registers, address = <val> + PCIBASE0 */ +/************************************************************************************************/ + +#define PTR 0x00 /* Indexed register set pointer register */ + /* NOTE: The CHANNELNUM and ADDRESS words can */ + /* be modified independently of each other. */ +#define PTR_CHANNELNUM_MASK 0x0000003f /* For each per-channel register, indicates the */ + /* channel number of the register to be */ + /* accessed. For non per-channel registers the */ + /* value should be set to zero. */ +#define PTR_ADDRESS_MASK 0x07ff0000 /* Register index */ + +#define DATA 0x04 /* Indexed register set data register */ + +#define IPR 0x08 /* Global interrupt pending register */ + /* Clear pending interrupts by writing a 1 to */ + /* the relevant bits and zero to the other bits */ +#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 */ +#define IPR_PCIERROR 0x00200000 /* PCI bus error */ +#define IPR_VOLINCR 0x00100000 /* Volume increment button pressed */ +#define IPR_VOLDECR 0x00080000 /* Volume decrement button pressed */ +#define IPR_MUTE 0x00040000 /* Mute button pressed */ +#define IPR_MICBUFFULL 0x00020000 /* Microphone buffer full */ +#define IPR_MICBUFHALFFULL 0x00010000 /* Microphone buffer half full */ +#define IPR_ADCBUFFULL 0x00008000 /* ADC buffer full */ +#define IPR_ADCBUFHALFFULL 0x00004000 /* ADC buffer half full */ +#define IPR_EFXBUFFULL 0x00002000 /* Effects buffer full */ +#define IPR_EFXBUFHALFFULL 0x00001000 /* Effects buffer half full */ +#define IPR_GPSPDIFSTATUSCHANGE 0x00000800 /* GPSPDIF channel status change */ +#define IPR_CDROMSTATUSCHANGE 0x00000400 /* CD-ROM channel status change */ +#define IPR_INTERVALTIMER 0x00000200 /* Interval timer terminal count */ +#define IPR_MIDITRANSBUFEMPTY 0x00000100 /* MIDI UART transmit buffer empty */ +#define IPR_MIDIRECVBUFEMPTY 0x00000080 /* MIDI UART receive buffer empty */ +#define IPR_CHANNELLOOP 0x00000040 /* One or more channel loop interrupts pending */ +#define IPR_CHANNELNUMBERMASK 0x0000003f /* When IPR_CHANNELLOOP is set, indicates the */ + /* Highest set channel in CLIPL or CLIPH. When */ + /* IP is written with CL set, the bit in CLIPL */ + /* or CLIPH corresponding to the CIN value */ + /* written will be cleared. */ + +#define INTE 0x0c /* Interrupt enable register */ +#define INTE_VIRTUALSB_MASK 0xc0000000 /* Virtual Soundblaster I/O port capture */ +#define INTE_VIRTUALSB_220 0x00000000 /* Capture at I/O base address 0x220-0x22f */ +#define INTE_VIRTUALSB_240 0x40000000 /* Capture at I/O base address 0x240 */ +#define INTE_VIRTUALSB_260 0x80000000 /* Capture at I/O base address 0x260 */ +#define INTE_VIRTUALSB_280 0xc0000000 /* Capture at I/O base address 0x280 */ +#define INTE_VIRTUALMPU_MASK 0x30000000 /* Virtual MPU I/O port capture */ +#define INTE_VIRTUALMPU_300 0x00000000 /* Capture at I/O base address 0x300-0x301 */ +#define INTE_VIRTUALMPU_310 0x10000000 /* Capture at I/O base address 0x310 */ +#define INTE_VIRTUALMPU_320 0x20000000 /* Capture at I/O base address 0x320 */ +#define INTE_VIRTUALMPU_330 0x30000000 /* Capture at I/O base address 0x330 */ +#define INTE_MASTERDMAENABLE 0x08000000 /* Master DMA emulation at 0x000-0x00f */ +#define INTE_SLAVEDMAENABLE 0x04000000 /* Slave DMA emulation at 0x0c0-0x0df */ +#define INTE_MASTERPICENABLE 0x02000000 /* Master PIC emulation at 0x020-0x021 */ +#define INTE_SLAVEPICENABLE 0x01000000 /* Slave PIC emulation at 0x0a0-0x0a1 */ +#define INTE_VSBENABLE 0x00800000 /* Enable virtual Soundblaster */ +#define INTE_ADLIBENABLE 0x00400000 /* Enable AdLib emulation at 0x388-0x38b */ +#define INTE_MPUENABLE 0x00200000 /* Enable virtual MPU */ +#define INTE_FORCEINT 0x00100000 /* Continuously assert INTAN */ + +#define INTE_MRHANDENABLE 0x00080000 /* Enable the "Mr. Hand" logic */ + /* NOTE: There is no reason to use this under */ + /* Linux, and it will cause odd hardware */ + /* behavior and possibly random segfaults and */ + /* lockups if enabled. */ + +#define INTE_SAMPLERATETRACKER 0x00002000 /* Enable sample rate tracker interrupts */ + /* NOTE: This bit must always be enabled */ +#define INTE_FXDSPENABLE 0x00001000 /* Enable FX DSP interrupts */ +#define INTE_PCIERRORENABLE 0x00000800 /* Enable PCI bus error interrupts */ +#define INTE_VOLINCRENABLE 0x00000400 /* Enable volume increment button interrupts */ +#define INTE_VOLDECRENABLE 0x00000200 /* Enable volume decrement button interrupts */ +#define INTE_MUTEENABLE 0x00000100 /* Enable mute button interrupts */ +#define INTE_MICBUFENABLE 0x00000080 /* Enable microphone buffer interrupts */ +#define INTE_ADCBUFENABLE 0x00000040 /* Enable ADC buffer interrupts */ +#define INTE_EFXBUFENABLE 0x00000020 /* Enable Effects buffer interrupts */ +#define INTE_GPSPDIFENABLE 0x00000010 /* Enable GPSPDIF status interrupts */ +#define INTE_CDSPDIFENABLE 0x00000008 /* Enable CDSPDIF status interrupts */ +#define INTE_INTERVALTIMERENB 0x00000004 /* Enable interval timer interrupts */ +#define INTE_MIDITXENABLE 0x00000002 /* Enable MIDI transmit-buffer-empty interrupts */ +#define INTE_MIDIRXENABLE 0x00000001 /* Enable MIDI receive-buffer-empty interrupts */ + +#define WC 0x10 /* Wall Clock register */ +#define WC_SAMPLECOUNTER_MASK 0x03FFFFC0 /* Sample periods elapsed since reset */ +#define WC_SAMPLECOUNTER 0x14060010 +#define WC_CURRENTCHANNEL 0x0000003F /* Channel [0..63] currently being serviced */ + /* NOTE: Each channel takes 1/64th of a sample */ + /* period to be serviced. */ + +#define HCFG 0x14 /* Hardware config register */ + /* NOTE: There is no reason to use the legacy */ + /* SoundBlaster emulation stuff described below */ + /* under Linux, and all kinds of weird hardware */ + /* behavior can result if you try. Don't. */ +#define HCFG_LEGACYFUNC_MASK 0xe0000000 /* Legacy function number */ +#define HCFG_LEGACYFUNC_MPU 0x00000000 /* Legacy MPU */ +#define HCFG_LEGACYFUNC_SB 0x40000000 /* Legacy SB */ +#define HCFG_LEGACYFUNC_AD 0x60000000 /* Legacy AD */ +#define HCFG_LEGACYFUNC_MPIC 0x80000000 /* Legacy MPIC */ +#define HCFG_LEGACYFUNC_MDMA 0xa0000000 /* Legacy MDMA */ +#define HCFG_LEGACYFUNC_SPCI 0xc0000000 /* Legacy SPCI */ +#define HCFG_LEGACYFUNC_SDMA 0xe0000000 /* Legacy SDMA */ +#define HCFG_IOCAPTUREADDR 0x1f000000 /* The 4 LSBs of the captured I/O address. */ +#define HCFG_LEGACYWRITE 0x00800000 /* 1 = write, 0 = read */ +#define HCFG_LEGACYWORD 0x00400000 /* 1 = word, 0 = byte */ +#define HCFG_LEGACYINT 0x00200000 /* 1 = legacy event captured. Write 1 to clear. */ + /* NOTE: The rest of the bits in this register */ + /* _are_ relevant under Linux. */ +#define HCFG_CODECFORMAT_MASK 0x00070000 /* CODEC format */ +#define HCFG_CODECFORMAT_AC97 0x00000000 /* AC97 CODEC format -- Primary Output */ +#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_JOYENABLE 0x00000200 /* Internal joystick enable */ +#define HCFG_PHASETRACKENABLE 0x00000100 /* Phase tracking enable */ + /* 1 = Force all 3 async digital inputs to use */ + /* the same async sample rate tracker (ZVIDEO) */ +#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_AUTOMUTE 0x00000010 /* When set, the async sample rate convertors */ + /* will automatically mute their output when */ + /* they are not rate-locked to the external */ + /* async audio source */ +#define HCFG_LOCKSOUNDCACHE 0x00000008 /* 1 = Cancel bustmaster accesses to soundcache */ + /* NOTE: This should generally never be used. */ +#define HCFG_LOCKTANKCACHE 0x00000004 /* 1 = Cancel bustmaster accesses to tankcache */ + /* NOTE: This should generally never be used. */ +#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 */ + /* in general should not be used unless a more */ + /* sophisticated master mute function has not */ + /* been written. */ +#define HCFG_AUDIOENABLE 0x00000001 /* 0 = CODECs transmit zero-valued samples */ + /* Should be set to 1 when the EMU10K1 is */ + /* completely initialized. */ + +#define MUDATA 0x18 /* MPU401 data register (8 bits) */ + +#define MUCMD 0x19 /* MPU401 command register (8 bits) */ +#define MUCMD_RESET 0xff /* RESET command */ +#define MUCMD_ENTERUARTMODE 0x3f /* Enter_UART_mode command */ + /* NOTE: All other commands are ignored */ + +#define MUSTAT MUCMD /* MPU401 status register (8 bits) */ +#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 */ + /* 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 */ + /* 0 == 1024 periods, [1..4] are not useful */ +#define TIMER_RATE 0x0a00001a + +#define AC97DATA 0x1c /* AC97 register set data register (16 bit) */ + +#define AC97ADDRESS 0x1e /* AC97 register set address register (8 bit) */ +#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_GENERALPUPOSE 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 */ +/********************************************************************************************************/ + +#define CPF 0x00 /* Current pitch and fraction register */ +#define CPF_CURRENTPITCH_MASK 0xffff0000 /* Current pitch (linear, 0x4000 == unity pitch shift) */ +#define CPF_CURRENTPITCH 0x10100000 +#define CPF_STEREO_MASK 0x00008000 /* 1 = Even channel interleave, odd channel locked */ +#define CPF_STOP_MASK 0x00004000 /* 1 = Current pitch forced to 0 */ +#define CPF_FRACADDRESS_MASK 0x00003fff /* Linear fractional address of the current channel */ + +#define PTRX 0x01 /* Pitch target and send A/B amounts register */ +#define PTRX_PITCHTARGET_MASK 0xffff0000 /* Pitch target of specified channel */ +#define PTRX_PITCHTARGET 0x10100001 +#define PTRX_FXSENDAMOUNT_A_MASK 0x0000ff00 /* Linear level of channel output sent to FX send bus A */ +#define PTRX_FXSENDAMOUNT_A 0x08080001 +#define PTRX_FXSENDAMOUNT_B_MASK 0x000000ff /* Linear level of channel output sent to FX send bus B */ +#define PTRX_FXSENDAMOUNT_B 0x08000001 + +#define CVCF 0x02 /* Current volume and filter cutoff register */ +#define CVCF_CURRENTVOL_MASK 0xffff0000 /* Current linear volume of specified channel */ +#define CVCF_CURRENTVOL 0x10100002 +#define CVCF_CURRENTFILTER_MASK 0x0000ffff /* Current filter cutoff frequency of specified channel */ +#define CVCF_CURRENTFILTER 0x10000002 + +#define VTFT 0x03 /* Volume target and filter cutoff target register */ +#define VTFT_VOLUMETARGET_MASK 0xffff0000 /* Volume target of specified channel */ +#define VTFT_FILTERTARGET_MASK 0x0000ffff /* Filter cutoff target of specified channel */ + +#define Z1 0x05 /* Filter delay memory 1 register */ + +#define Z2 0x04 /* Filter delay memory 2 register */ + +#define PSST 0x06 /* Send C amount and loop start address register */ +#define PSST_FXSENDAMOUNT_C_MASK 0xff000000 /* Linear level of channel output sent to FX send bus C */ + +#define PSST_FXSENDAMOUNT_C 0x08180006 + +#define PSST_LOOPSTARTADDR_MASK 0x00ffffff /* Loop start address of the specified channel */ +#define PSST_LOOPSTARTADDR 0x18000006 + +#define DSL 0x07 /* Send D amount and loop start address register */ +#define DSL_FXSENDAMOUNT_D_MASK 0xff000000 /* Linear level of channel output sent to FX send bus D */ + +#define DSL_FXSENDAMOUNT_D 0x08180007 + +#define DSL_LOOPENDADDR_MASK 0x00ffffff /* Loop end address of the specified channel */ +#define DSL_LOOPENDADDR 0x18000007 + +#define CCCA 0x08 /* Filter Q, interp. ROM, byte size, cur. addr register */ +#define CCCA_RESONANCE 0xf0000000 /* Lowpass filter resonance (Q) height */ +#define CCCA_INTERPROMMASK 0x0e000000 /* Selects passband of interpolation ROM */ + /* 1 == full band, 7 == lowpass */ + /* ROM 0 is used when pitch shifting downward or less */ + /* then 3 semitones upward. Increasingly higher ROM */ + /* numbers are used, typically in steps of 3 semitones, */ + /* as upward pitch shifting is performed. */ +#define CCCA_INTERPROM_0 0x00000000 /* Select interpolation ROM 0 */ +#define CCCA_INTERPROM_1 0x02000000 /* Select interpolation ROM 1 */ +#define CCCA_INTERPROM_2 0x04000000 /* Select interpolation ROM 2 */ +#define CCCA_INTERPROM_3 0x06000000 /* Select interpolation ROM 3 */ +#define CCCA_INTERPROM_4 0x08000000 /* Select interpolation ROM 4 */ +#define CCCA_INTERPROM_5 0x0a000000 /* Select interpolation ROM 5 */ +#define CCCA_INTERPROM_6 0x0c000000 /* Select interpolation ROM 6 */ +#define CCCA_INTERPROM_7 0x0e000000 /* Select interpolation ROM 7 */ +#define CCCA_8BITSELECT 0x01000000 /* 1 = Sound memory for this channel uses 8-bit samples */ +#define CCCA_CURRADDR_MASK 0x00ffffff /* Current address of the selected channel */ +#define CCCA_CURRADDR 0x18000008 + +#define CCR 0x09 /* Cache control register */ +#define CCR_CACHEINVALIDSIZE 0xfe000000 /* Number of invalid samples cache for this channel */ +#define CCR_CACHELOOPFLAG 0x01000000 /* 1 = Cache has a loop service pending */ +#define CCR_INTERLEAVEDSAMPLES 0x00800000 /* 1 = A cache service will fetch interleaved samples */ +#define CCR_WORDSIZEDSAMPLES 0x00400000 /* 1 = A cache service will fetch word sized samples */ +#define CCR_READADDRESS_MASK 0x003f0000 /* Location of cache just beyond current cache service */ +#define CCR_LOOPINVALSIZE 0x0000fe00 /* Number of invalid samples in cache prior to loop */ + /* NOTE: This is valid only if CACHELOOPFLAG is set */ +#define CCR_LOOPFLAG 0x00000100 /* Set for a single sample period when a loop occurs */ +#define CCR_CACHELOOPADDRHI 0x000000ff /* DSL_LOOPSTARTADDR's hi byte if CACHELOOPFLAG is set */ + +#define CLP 0x0a /* Cache loop register (valid if CCR_CACHELOOPFLAG = 1) */ + /* NOTE: This register is normally not used */ +#define CLP_CACHELOOPADDR 0x0000ffff /* Cache loop address (DSL_LOOPSTARTADDR [0..15]) */ + +#define FXRT 0x0b /* Effects send routing register */ + /* NOTE: It is illegal to assign the same routing to */ + /* two effects sends. */ +#define FXRT_CHANNELA 0x000f0000 /* Effects send bus number for channel's effects send A */ +#define FXRT_CHANNELB 0x00f00000 /* Effects send bus number for channel's effects send B */ +#define FXRT_CHANNELC 0x0f000000 /* Effects send bus number for channel's effects send C */ +#define FXRT_CHANNELD 0xf0000000 /* Effects send bus number for channel's effects send D */ + +#define MAPA 0x0c /* Cache map A */ + +#define MAPB 0x0d /* Cache map B */ + +#define MAP_PTE_MASK 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ +#define MAP_PTI_MASK 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ + +#define ENVVOL 0x10 /* Volume envelope register */ +#define ENVVOL_MASK 0x0000ffff /* Current value of volume envelope state variable */ + /* 0x8000-n == 666*n usec delay */ + +#define ATKHLDV 0x11 /* Volume envelope hold and attack register */ +#define ATKHLDV_PHASE0 0x00008000 /* 0 = Begin attack phase */ +#define ATKHLDV_HOLDTIME_MASK 0x00007f00 /* Envelope hold time (127-n == n*88.2msec) */ +#define ATKHLDV_ATTACKTIME_MASK 0x0000007f /* Envelope attack time, log encoded */ + /* 0 = infinite, 1 = 10.9msec, ... 0x7f = 5.5msec */ + +#define DCYSUSV 0x12 /* Volume envelope sustain and decay register */ +#define DCYSUSV_PHASE1_MASK 0x00008000 /* 0 = Begin attack phase, 1 = begin release phase */ +#define DCYSUSV_SUSTAINLEVEL_MASK 0x00007f00 /* 127 = full, 0 = off, 0.75dB increments */ +#define DCYSUSV_CHANNELENABLE_MASK 0x00000080 /* 1 = Inhibit envelope engine from writing values in */ + /* this channel and from writing to pitch, filter and */ + /* volume targets. */ +#define DCYSUSV_DECAYTIME_MASK 0x0000007f /* Volume envelope decay time, log encoded */ + /* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec */ + +#define LFOVAL1 0x13 /* Modulation LFO value */ +#define LFOVAL_MASK 0x0000ffff /* Current value of modulation LFO state variable */ + /* 0x8000-n == 666*n usec delay */ + +#define ENVVAL 0x14 /* Modulation envelope register */ +#define ENVVAL_MASK 0x0000ffff /* Current value of modulation envelope state variable */ + /* 0x8000-n == 666*n usec delay */ + +#define ATKHLDM 0x15 /* Modulation envelope hold and attack register */ +#define ATKHLDM_PHASE0 0x00008000 /* 0 = Begin attack phase */ +#define ATKHLDM_HOLDTIME 0x00007f00 /* Envelope hold time (127-n == n*42msec) */ +#define ATKHLDM_ATTACKTIME 0x0000007f /* Envelope attack time, log encoded */ + /* 0 = infinite, 1 = 11msec, ... 0x7f = 5.5msec */ + +#define DCYSUSM 0x16 /* Modulation envelope decay and sustain register */ +#define DCYSUSM_PHASE1_MASK 0x00008000 /* 0 = Begin attack phase, 1 = begin release phase */ +#define DCYSUSM_SUSTAINLEVEL_MASK 0x00007f00 /* 127 = full, 0 = off, 0.75dB increments */ +#define DCYSUSM_DECAYTIME_MASK 0x0000007f /* Envelope decay time, log encoded */ + /* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec */ + +#define LFOVAL2 0x17 /* Vibrato LFO register */ +#define LFOVAL2_MASK 0x0000ffff /* Current value of vibrato LFO state variable */ + /* 0x8000-n == 666*n usec delay */ + +#define IP 0x18 /* Initial pitch register */ +#define IP_MASK 0x0000ffff /* Exponential initial pitch shift */ + /* 4 bits of octave, 12 bits of fractional octave */ +#define IP_UNITY 0x0000e000 /* Unity pitch shift */ + +#define IFATN 0x19 /* Initial filter cutoff and attenuation register */ +#define IFATN_FILTERCUTOFF_MASK 0x0000ff00 /* Initial filter cutoff frequency in exponential units */ + /* 6 most significant bits are semitones */ + /* 2 least significant bits are fractions */ +#define IFATN_FILTERCUTOFF 0x08080019 +#define IFATN_ATTENUATION_MASK 0x000000ff /* Initial attenuation in 0.375dB steps */ +#define IFATN_ATTENUATION 0x08000019 + + +#define PEFE 0x1a /* Pitch envelope and filter envelope amount register */ +#define PEFE_PITCHAMOUNT_MASK 0x0000ff00 /* Pitch envlope amount */ + /* Signed 2's complement, +/- one octave peak extremes */ +#define PEFE_PITCHAMOUNT 0x0808001a +#define PEFE_FILTERAMOUNT_MASK 0x000000ff /* Filter envlope amount */ + /* Signed 2's complement, +/- six octaves peak extremes */ +#define PEFE_FILTERAMOUNT 0x0800001a +#define FMMOD 0x1b /* Vibrato/filter modulation from LFO register */ +#define FMMOD_MODVIBRATO 0x0000ff00 /* Vibrato LFO modulation depth */ + /* Signed 2's complement, +/- one octave extremes */ +#define FMMOD_MOFILTER 0x000000ff /* Filter LFO modulation depth */ + /* Signed 2's complement, +/- three octave extremes */ + + +#define TREMFRQ 0x1c /* Tremolo amount and modulation LFO frequency register */ +#define TREMFRQ_DEPTH 0x0000ff00 /* Tremolo depth */ + /* Signed 2's complement, with +/- 12dB extremes */ + +#define FM2FRQ2 0x1d /* Vibrato amount and vibrato LFO frequency register */ +#define FM2FRQ2_DEPTH 0x0000ff00 /* Vibrato LFO vibrato depth */ + /* Signed 2's complement, +/- one octave extremes */ +#define FM2FRQ2_FREQUENCY 0x000000ff /* Vibrato LFO frequency */ + /* 0.039Hz steps, maximum of 9.85 Hz. */ + +#define TEMPENV 0x1e /* Tempory envelope register */ +#define TEMPENV_MASK 0x0000ffff /* 16-bit value */ + /* NOTE: All channels contain internal variables; do */ + /* not write to these locations. */ + +#define CD0 0x20 /* Cache data 0 register */ +#define CD1 0x21 /* Cache data 1 register */ +#define CD2 0x22 /* Cache data 2 register */ +#define CD3 0x23 /* Cache data 3 register */ +#define CD4 0x24 /* Cache data 4 register */ +#define CD5 0x25 /* Cache data 5 register */ +#define CD6 0x26 /* Cache data 6 register */ +#define CD7 0x27 /* Cache data 7 register */ +#define CD8 0x28 /* Cache data 8 register */ +#define CD9 0x29 /* Cache data 9 register */ +#define CDA 0x2a /* Cache data A register */ +#define CDB 0x2b /* Cache data B register */ +#define CDC 0x2c /* Cache data C register */ +#define CDD 0x2d /* Cache data D register */ +#define CDE 0x2e /* Cache data E register */ +#define CDF 0x2f /* Cache data F register */ + +#define PTB 0x40 /* Page table base register */ +#define PTB_MASK 0xfffff000 /* Physical address of the page table in host memory */ + +#define TCB 0x41 /* Tank cache base register */ +#define TCB_MASK 0xfffff000 /* Physical address of the bottom of host based TRAM */ + +#define ADCCR 0x42 /* ADC sample rate/stereo control register */ +#define ADCCR_RCHANENABLE 0x00000010 /* Enables right channel for writing to the host */ +#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 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 */ +#define ADCCR_SAMPLERATE_24 0x00000003 /* 24kHz sample rate */ +#define ADCCR_SAMPLERATE_22 0x00000004 /* 22.05kHz sample rate */ +#define ADCCR_SAMPLERATE_16 0x00000005 /* 16kHz sample rate */ +#define ADCCR_SAMPLERATE_11 0x00000006 /* 11.025kHz sample rate */ +#define ADCCR_SAMPLERATE_8 0x00000007 /* 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 */ + +#define TCBS 0x44 /* Tank cache buffer size register */ +#define TCBS_MASK 0x00000007 /* Tank cache buffer size field */ +#define TCBS_BUFFSIZE_16K 0x00000000 +#define TCBS_BUFFSIZE_32K 0x00000001 +#define TCBS_BUFFSIZE_64K 0x00000002 +#define TCBS_BUFFSIZE_128K 0x00000003 +#define TCBS_BUFFSIZE_256K 0x00000004 +#define TCBS_BUFFSIZE_512K 0x00000005 +#define TCBS_BUFFSIZE_1024K 0x00000006 +#define TCBS_BUFFSIZE_2048K 0x00000007 + +#define MICBA 0x45 /* AC97 microphone buffer address register */ +#define MICBA_MASK 0xfffff000 /* 20 bit base address */ + +#define ADCBA 0x46 /* ADC buffer address register */ +#define ADCBA_MASK 0xfffff000 /* 20 bit base address */ + +#define FXBA 0x47 /* FX Buffer Address */ +#define FXBA_MASK 0xfffff000 /* 20 bit base address */ + +#define MICBS 0x49 /* Microphone buffer size register */ + +#define ADCBS 0x4a /* ADC buffer size register */ + +#define FXBS 0x4b /* FX buffer size register */ + +/* The following mask values define the size of the ADC, MIX and FX buffers in bytes */ +#define ADCBS_BUFSIZE_NONE 0x00000000 +#define ADCBS_BUFSIZE_384 0x00000001 +#define ADCBS_BUFSIZE_448 0x00000002 +#define ADCBS_BUFSIZE_512 0x00000003 +#define ADCBS_BUFSIZE_640 0x00000004 +#define ADCBS_BUFSIZE_768 0x00000005 +#define ADCBS_BUFSIZE_896 0x00000006 +#define ADCBS_BUFSIZE_1024 0x00000007 +#define ADCBS_BUFSIZE_1280 0x00000008 +#define ADCBS_BUFSIZE_1536 0x00000009 +#define ADCBS_BUFSIZE_1792 0x0000000a +#define ADCBS_BUFSIZE_2048 0x0000000b +#define ADCBS_BUFSIZE_2560 0x0000000c +#define ADCBS_BUFSIZE_3072 0x0000000d +#define ADCBS_BUFSIZE_3584 0x0000000e +#define ADCBS_BUFSIZE_4096 0x0000000f +#define ADCBS_BUFSIZE_5120 0x00000010 +#define ADCBS_BUFSIZE_6144 0x00000011 +#define ADCBS_BUFSIZE_7168 0x00000012 +#define ADCBS_BUFSIZE_8192 0x00000013 +#define ADCBS_BUFSIZE_10240 0x00000014 +#define ADCBS_BUFSIZE_12288 0x00000015 +#define ADCBS_BUFSIZE_14366 0x00000016 +#define ADCBS_BUFSIZE_16384 0x00000017 +#define ADCBS_BUFSIZE_20480 0x00000018 +#define ADCBS_BUFSIZE_24576 0x00000019 +#define ADCBS_BUFSIZE_28672 0x0000001a +#define ADCBS_BUFSIZE_32768 0x0000001b +#define ADCBS_BUFSIZE_40960 0x0000001c +#define ADCBS_BUFSIZE_49152 0x0000001d +#define ADCBS_BUFSIZE_57344 0x0000001e +#define ADCBS_BUFSIZE_65536 0x0000001f + + +#define CDCS 0x50 /* CD-ROM digital channel status register */ + +#define GPSCS 0x51 /* General Purpose SPDIF channel status register*/ + +#define DBG 0x52 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ + +#define REG53 0x53 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ + +#define SPCS0 0x54 /* SPDIF output Channel Status 0 register */ + +#define SPCS1 0x55 /* SPDIF output Channel Status 1 register */ + +#define SPCS2 0x56 /* SPDIF output Channel Status 2 register */ + +#define SPCS_CLKACCYMASK 0x30000000 /* Clock accuracy */ +#define SPCS_CLKACCY_1000PPM 0x00000000 /* 1000 parts per million */ +#define SPCS_CLKACCY_50PPM 0x10000000 /* 50 parts per million */ +#define SPCS_CLKACCY_VARIABLE 0x20000000 /* Variable accuracy */ +#define SPCS_SAMPLERATEMASK 0x0f000000 /* Sample rate */ +#define SPCS_SAMPLERATE_44 0x00000000 /* 44.1kHz sample rate */ +#define SPCS_SAMPLERATE_48 0x02000000 /* 48kHz sample rate */ +#define SPCS_SAMPLERATE_32 0x03000000 /* 32kHz sample rate */ +#define SPCS_CHANNELNUMMASK 0x00f00000 /* Channel number */ +#define SPCS_CHANNELNUM_UNSPEC 0x00000000 /* Unspecified channel number */ +#define SPCS_CHANNELNUM_LEFT 0x00100000 /* Left channel */ +#define SPCS_CHANNELNUM_RIGHT 0x00200000 /* Right channel */ +#define SPCS_SOURCENUMMASK 0x000f0000 /* Source number */ +#define SPCS_SOURCENUM_UNSPEC 0x00000000 /* Unspecified source number */ +#define SPCS_GENERATIONSTATUS 0x00008000 /* Originality flag (see IEC-958 spec) */ +#define SPCS_CATEGORYCODEMASK 0x00007f00 /* Category code (see IEC-958 spec) */ +#define SPCS_MODEMASK 0x000000c0 /* Mode (see IEC-958 spec) */ +#define SPCS_EMPHASISMASK 0x00000038 /* Emphasis */ +#define SPCS_EMPHASIS_NONE 0x00000000 /* No emphasis */ +#define SPCS_EMPHASIS_50_15 0x00000008 /* 50/15 usec 2 channel */ +#define SPCS_COPYRIGHT 0x00000004 /* Copyright asserted flag -- do not modify */ +#define SPCS_NOTAUDIODATA 0x00000002 /* 0 = Digital audio, 1 = not audio */ +#define SPCS_PROFESSIONAL 0x00000001 /* 0 = Consumer (IEC-958), 1 = pro (AES3-1992) */ + +/* The 32-bit CLIx and SOLx registers all have one bit per channel control/status */ +#define CLIEL 0x58 /* Channel loop interrupt enable low register */ + +#define CLIEH 0x59 /* Channel loop interrupt enable high register */ + +#define CLIPL 0x5a /* Channel loop interrupt pending low register */ + +#define CLIPH 0x5b /* Channel loop interrupt pending high register */ + +#define SOLEL 0x5c /* Stop on loop enable low register */ + +#define SOLEH 0x5d /* Stop on loop enable high register */ + +#define SPBYPASS 0x5e /* SPDIF BYPASS mode register */ +#define SPBYPASS_ENABLE 0x00000001 /* Enable SPDIF bypass mode */ + +#define CDSRCS 0x60 /* CD-ROM Sample Rate Converter status register */ + +#define GPSRCS 0x61 /* General Purpose SPDIF sample rate cvt status */ + +#define ZVSRCS 0x62 /* ZVideo sample rate converter status */ + /* NOTE: This one has no SPDIFLOCKED field */ + /* Assumes sample lock */ + +/* These three bitfields apply to CDSRCS, GPSRCS, and (except as noted) ZVSRCS. */ +#define SRCS_SPDIFLOCKED 0x02000000 /* SPDIF stream locked */ +#define SRCS_RATELOCKED 0x01000000 /* Sample rate locked */ +#define SRCS_ESTSAMPLERATE 0x0007ffff /* Do not modify this field. */ + +#define MICIDX 0x63 /* Microphone recording buffer index register */ +#define MICIDX_MASK 0x0000ffff /* 16-bit value */ +#define MICIDX_IDX 0x10000063 + +#define ADCIDX 0x64 /* ADC recording buffer index register */ +#define ADCIDX_MASK 0x0000ffff /* 16 bit index field */ +#define ADCIDX_IDX 0x10000064 + +#define FXIDX 0x65 /* FX recording buffer index register */ +#define FXIDX_MASK 0x0000ffff /* 16-bit value */ +#define FXIDX_IDX 0x10000065 + +/* Each FX general purpose register is 32 bits in length, all bits are used */ +#define FXGPREGBASE 0x100 /* FX general purpose registers base */ + +/* 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. */ +#define TANKMEMDATAREGBASE 0x200 /* Tank memory data registers base */ +#define TANKMEMDATAREG_MASK 0x000fffff /* 20 bit tank audio data field */ + +/* Combined address field and memory opcode or flag field. 160 locations, last 32 are external */ +#define TANKMEMADDRREGBASE 0x300 /* Tank memory address registers base */ +#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */ +#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */ +#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */ +#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */ +#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */ + +#define MICROCODEBASE 0x400 /* Microcode data base address */ + +/* Each DSP microcode instruction is mapped into 2 doublewords */ +/* NOTE: When writing, always write the LO doubleword first. Reads can be in either order. */ +#define LOWORD_OPX_MASK 0x000ffc00 /* Instruction operand X */ +#define LOWORD_OPY_MASK 0x000003ff /* Instruction operand Y */ +#define HIWORD_OPCODE_MASK 0x00f00000 /* Instruction opcode */ +#define HIWORD_RESULT_MASK 0x000ffc00 /* Instruction result */ +#define HIWORD_OPA_MASK 0x000003ff /* Instruction operand A */ + +#endif /* _8010_H */ |