Date: Sun, 20 Apr 2003 17:45:59 -0700 From: "David O'Brien" <obrien@NUXI.com> To: Orion Hodson <orion@FreeBSD.org> Cc: Dag-Erling Smorgrav <des@ofug.org> Subject: Re: Audigy [ was Re: ... Terratec EWS88MT ... ] Message-ID: <20030421004559.GA67656@dragon.nuxi.com> In-Reply-To: <200304210017.h3L0HCnR040596@puma.icir.org> References: <20030420215557.GD55790@dragon.nuxi.com> <200304210017.h3L0HCnR040596@puma.icir.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--HcAYCG3uE/tztfnV Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Sun, Apr 20, 2003 at 05:17:12PM -0700, Orion Hodson wrote: > /-- "David O'Brien" wrote: > | On Fri, Feb 21, 2003 at 02:21:42PM -0800, Orion Hodson wrote: > | > The project has had two drivers submitted for Audigy support in the > | > past couple of weeks. I've been holding off looking at them as cg's > | > really the man for the job. However, as I've found out today cg's > | > been ill of late and has plenty of things going on externally at > | > present. > | > | So how do we move forward? > > Orlando Bassotto, one of the Audigy code submitters, has taken on the task of > combining the contributions. The latest patch is available at: > > http://mad.ieo-research.it/freebsd/drivers/emu10k1/ I don't want to seem ungrateful for this work, but the problem is, it currently isn't committable. This work is based off of emu10k1.c rev 1.28 from 2002/11/26. Also the diffs should be as minimal as possible. Things like this shouldn't be in the diff: -#define EMU10K1_PCI_ID 0x00021102 -#define EMU10K2_PCI_ID 0x00041102 +#define EMU10K1_PCI_ID 0x00021102 +#define EMU10K2_PCI_ID 0x00041102 emu_rdptr(struct sc_info *sc, int chn, int reg) { - u_int32_t ptr, val, mask, size, offset; + u_int32_t ptr, val, mask, size, offset; These changes are gratiutious. Also emu10k1tone.h is undocumented where it comes from. Until cg has a chance to be active in emu10k1 development again, I'd perfer to see something that doesn't abstract out bits from emu10k1.c into new headers as it makes the diffs larger, and harder to review by those less knowledgeable as cg. At least I'm willing to shepard this work into the CVS repo in such a form. I hope the goal is to get this work committed into the FreeBSD CVS repository. Attached is emu10k-01-March-2003-cvs.tar.bz2 in a reviewable and committable fashion. -- David --HcAYCG3uE/tztfnV Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="audigy1.diff" Index: sys/dev/sound/pci/emu10k1.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/emu10k1.c,v retrieving revision 1.36 diff -u -r1.36 emu10k1.c --- sys/dev/sound/pci/emu10k1.c 20 Apr 2003 08:37:29 -0000 1.36 +++ sys/dev/sound/pci/emu10k1.c 20 Apr 2003 09:05:38 -0000 @@ -27,14 +27,26 @@ #include <dev/sound/pcm/sound.h> #include <dev/sound/pcm/ac97.h> #include <gnu/dev/sound/pci/emu10k1.h> +#include <gnu/dev/sound/pci/emu10k1-ac97.h> #include <pci/pcireg.h> #include <pci/pcivar.h> #include <sys/queue.h> +#include <sys/sysctl.h> +#include "mixer_if.h" SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/emu10k1.c,v 1.36 2003/04/20 08:37:29 obrien Exp $"); -/* -------------------------------------------------------------------- */ +#define EMUPAGESIZE 4096 /* don't change */ +#define MAXREQVOICES 8 +#define MAXPAGES (32768 * 64 / EMUPAGESIZE) /* WAVEOUT_MAXBUFSIZE * NUM_G / EMUPAGESIZE */ +#define RESERVED 0 +#define NUM_MIDI 16 +#define NUM_G 64 /* use all channels */ +#define NUM_FXSENDS 4 + +#define TMEMSIZE 256*1024 +#define TMEMSIZEREG 4 #define EMU10K1_PCI_ID 0x00021102 #define EMU10K2_PCI_ID 0x00041102 @@ -42,6 +54,11 @@ #define EMU_CHANS 4 #undef EMUDEBUG +#define ENABLE 0xffffffff +#define DISABLE 0x00000000 +#define ENV_ON 0x80 +#define ENV_OFF 0x00 + struct emu_memblk { SLIST_ENTRY(emu_memblk) link; void *buf; @@ -87,11 +104,23 @@ struct sc_info *parent; }; +struct sc_waveio { + u_int32_t send_routing[1]; + u_int32_t send_routing2[1]; + u_int32_t send_dcba[3]; + u_int32_t send_hgfe[3]; +}; + +#define ROUTE_PCM0 0 +#define SEND_MONO 0 +#define SEND_LEFT 1 +#define SEND_RIGHT 2 + /* device private data */ struct sc_info { device_t dev; u_int32_t type, rev; - u_int32_t tos_link:1, APS:1; + u_int32_t tos_link:1, APS:1, is_audigy:1; bus_space_tag_t st; bus_space_handle_t sh; @@ -101,6 +130,20 @@ void *ih; struct mtx *lock; + struct ac97_info *codec; + + struct sc_waveio waveio; + unsigned int mchannel_fx; + unsigned int dsp_zero; + unsigned int code_base; + unsigned int code_size; + unsigned int gpr_base; + unsigned int num_gprs; + unsigned int input_base; + unsigned int output_base; + unsigned int opcode_shift; + unsigned int high_operand_shift; + unsigned int bufsz; int timer, timerinterval; int pnum, rnum; @@ -132,7 +175,9 @@ static void emu_wr(struct sc_info *, int, u_int32_t, int); /* -------------------------------------------------------------------- */ +static struct sc_info *ctl_sc_info; +/* Recording formats supported: */ static u_int32_t emu_rfmt_ac97[] = { AFMT_S16_LE, AFMT_STEREO | AFMT_S16_LE, @@ -149,12 +194,14 @@ 0 }; +/* Recording capabilites */ static struct pcmchan_caps emu_reccaps[3] = { {8000, 48000, emu_rfmt_ac97, 0}, {8000, 8000, emu_rfmt_mic, 0}, {48000, 48000, emu_rfmt_efx, 0}, }; +/* Playback formats */ static u_int32_t emu_pfmt[] = { AFMT_U8, AFMT_STEREO | AFMT_U8, @@ -163,10 +210,28 @@ 0 }; +/* Playback capabilites */ static struct pcmchan_caps emu_playcaps = {4000, 48000, emu_pfmt, 0}; static int adcspeed[8] = {48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000}; +/* Mixer */ + +#define MIXER_FX 1 +#define MIXER_AC97 2 + +#define MIXER_PLAYBACKOUNLY 0 +#define MIXER_CANRECORD 0 + +struct emu10k1mixer_entry { + unsigned mixer_source:2; + unsigned is_recording:1; +}; + +static const struct emu10k1mixer_entry emu10k1mixer[SOUND_MIXER_NRDEVICES] = { + [SOUND_MIXER_VOLUME] = {MIXER_FX, MIXER_PLAYBACKOUNLY} +}; + /* -------------------------------------------------------------------- */ /* Hardware */ static u_int32_t @@ -239,10 +304,11 @@ static void emu_wrefx(struct sc_info *sc, unsigned int pc, unsigned int data) { - emu_wrptr(sc, 0, MICROCODEBASE + pc, data); + emu_wrptr(sc, 0, sc->code_base + pc, data); } /* -------------------------------------------------------------------- */ +static void emumix_set_fxvol(struct sc_info *sc, unsigned gpr, int32_t vol); /* ac97 codec */ /* no locking needed */ @@ -259,7 +325,92 @@ emu_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) { struct sc_info *sc = (struct sc_info *)devinfo; + u_int32_t left, right; + + if (sc->is_audigy){ + /* + * hack to always get AC97 sound on Audigy + * should be converted to some kind of AC97 chip emulation + * and present EMU10K2 chip capabilites throuth + * AC97 "extended capabilites" register + */ + switch (regno) { + case 0x02: /* MAIN OUT */ + /* + * MAIN OUT volume on AC97 is alwayz zero + * because AC97 is not connected to outs + * use emumix_setfxvol to set MAIN OUT volume + */ + left = (data & 0x3f00) >> 8; + right = data & 0x003f; + if (data & 0x8000) + left = right = 0x1f; /* mute */ + if (left == 0 && right==0x3f) + break; + left = 100 - left * 100 / (0x1f); /* 4 bit */ + right = 100 - right * 100 / (0x1f); + /* 0x12/0x13 are MAIN volume, controlled by vol */ + emumix_set_fxvol(sc, 0x12, left); + emumix_set_fxvol(sc, 0x13, right); + break; + case 0x18: /* PCM OUT VOL */ + /* + * PCM volume on AC97 should stay muted, + * use emumix_setfxvol to set PCM volume from FX0 + * If PCM volume is muted, then front PCM output is done + * by better 6-ch Philips chip + */ + left = (data & 0x3f00)>>8; + right = data & 0x003f; + if (data & 0x8000) + left=right=0x1f; /* mute */ + if (left == 0 && right==0x3f) + break; + left = 100 - left * 100 / (0x1f); /* 4 bit */ + right = 100 - right * 100 / (0x1f); + /* 0x10/0x11 are PCM controls */ + emumix_set_fxvol(sc, 0x10, left); + emumix_set_fxvol(sc, 0x11, right); + /* */ + data = 0x8000; + break; + case 0x1a: + /* + * PCM recording source is set to "stereo mix" + * (labeled "vol" in mixer) + */ + data = 0x0505; + break; + case 0x1c: /* RECORD GAIN */ + /* + * Record gain on AC97 should stay zero to get AC97 sound + * on AC97_[RL] connectors on EMU10K2 chip + * AC97 on Audigy is not directly connected to any output, + * only to EMU10K2 chip + * Use this control to set AC97 mix volume inside EMU10K2 + * chip + */ + left = (data & 0x3f00)>>8; + right = data & 0x003f; + /* + * rec control is recrding VOLUME, not attenuation + * and 0 IS 0% and 15 IS 100% + */ + if (data & 0x8000) + left = right = 0; /* mute */ + if (left == 0 && right==0x3f) + break; + left = left * 100 / 15; /* 4 bit */ + right = right * 100 / 15; + /* 0x14/0x15 are AC97 controls */ + emumix_set_fxvol(sc, 0x14, left); + emumix_set_fxvol(sc, 0x15, right); + /* */ + data = 0x0000; + break; + }; + }; emu_wr(sc, AC97ADDRESS, regno, 1); emu_wr(sc, AC97DATA, data, 2); return 0; @@ -272,6 +423,80 @@ }; AC97_DECLARE(emu_ac97); +/* Mix */ +/* ------------------------------------------------------------------------- */ + +static int +emumix_init(struct snd_mixer *m) +{ + u_int32_t i, v; + + for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { + if (emu10k1mixer[i].mixer_source) v |= 1 << i; + } + mix_setdevs(m, v); + + for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { + if (emu10k1mixer[i].is_recording) v |= 1 << i; + } + mix_setrecdevs(m, v); + return 0; +} + +static void +emumix_set_fxvol(struct sc_info *sc, unsigned gpr, int32_t vol) +{ + static const int scale = 16; + static const int32_t log2lin[4] = { /* attenuation (dB) */ + 0x7fffffff, /* 0.0 */ + 0x7fffffff * 0.840896415253715, /* 1.5 */ + 0x7fffffff * 0.707106781186548, /* 3.0 */ + 0x7fffffff * 0.594603557501361, /* 4.5 */ + }; + + vol = (100 - vol) * scale / 100; + vol = (vol >= scale) ? 0 : (log2lin[vol & 3] >> (vol >> 2)); + emu_wrptr(sc, 0, sc->gpr_base + gpr, vol); + + return; +} + +static int +emumix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) +{ +#if 0 + struct sc_info *sc = mix_getdevinfo(m); + + if (emu10k1mixer[dev].is_stereo) { + emumix_set_fxvol(sc, sc->gpr_base + emu10k1mixer[dev].gpr, left); + emumix_set_fxvol(sc, sc->gpr_base + emu10k1mixer[dev].gpr+1, right); + } else { + mono = (left>>1) + (right>>1); + emumix_set_fxvol(sc, sc->gpr_base + emu10k1mixer[dev].gpr, mono); + }; +#endif + return 0; +} + +static int +emumix_setrecsrc(struct snd_mixer *m, u_int32_t src) +{ +#if 0 + struct sc_info *sc = mix_getdevinfo(m); +#endif + + return src; +} + +static kobj_method_t emu_mix_methods[] = { + KOBJMETHOD(mixer_init, emumix_init), + KOBJMETHOD(mixer_set, emumix_set), + KOBJMETHOD(mixer_setrecsrc, emumix_setrecsrc), + { 0, 0 } +}; +MIXER_DECLARE(emu_mix); + + /* -------------------------------------------------------------------- */ /* stuff */ static int @@ -487,7 +712,8 @@ emu_vwrite(struct sc_info *sc, struct emu_voice *v) { int s; - int l, r, x, y; + int i; + unsigned int routing[8],amounts[8]; u_int32_t sa, ea, start, val, silent_page; s = (v->stereo ? 1 : 0) + (v->b16 ? 1 : 0); @@ -495,22 +721,44 @@ sa = v->start >> s; ea = v->end >> s; - l = r = x = y = v->vol; + for (i = 0; i < 8; i++) { + routing[i]=i; + amounts[i]=0xff; + }; if (v->stereo) { - l = v->ismaster ? l : 0; - r = v->ismaster ? 0 : r; + if (v->ismaster) { + amounts[0] = amounts[2] = amounts[4] = amounts[6] = 0; + } else { + amounts[1] = amounts[3] = amounts[5] = amounts[7] = 0; + }; + emu_wrptr(sc, v->vnum, CPF, CPF_STEREO_MASK); + } else { + emu_wrptr(sc, v->vnum, CPF, 0); } - emu_wrptr(sc, v->vnum, CPF, v->stereo ? CPF_STEREO_MASK : 0); val = v->stereo ? 28 : 30; val *= v->b16 ? 1 : 2; start = sa + val; - emu_wrptr(sc, v->vnum, FXRT, 0xd01c0000); + if (sc->is_audigy) { + emu_wrptr(sc, v->vnum, A_FXRT1, + routing[3] << 24 | routing[2] << 16 | routing[1] << 8 + | routing[0] << 0); + emu_wrptr(sc, v->vnum, A_FXRT2, + routing[7] << 24 | routing[6] << 16 | routing[5] << 8 + | routing[4] << 0); + emu_wrptr(sc, v->vnum, A_SENDAMOUNTS, + amounts[7] << 24 | amounts[6] << 26 | amounts[5] << 8 + | amounts[4] << 0); + } else { + emu_wrptr(sc, v->vnum, FXRT, + (routing[3] << 12 | routing[2] << 8 | routing[1] << 4 + | routing[0] << 0) << 16); /*0xd01c0000*/ + } - emu_wrptr(sc, v->vnum, PTRX, (x << 8) | r); - emu_wrptr(sc, v->vnum, DSL, ea | (y << 24)); - emu_wrptr(sc, v->vnum, PSST, sa | (l << 24)); + emu_wrptr(sc, v->vnum, PTRX, amounts[3] << 8 | amounts[2] << 0); + emu_wrptr(sc, v->vnum, DSL, ea | amounts[1] << 24); + emu_wrptr(sc, v->vnum, PSST, sa | amounts[0] << 24); emu_wrptr(sc, v->vnum, CCCA, start | (v->b16 ? 0 : CCCA_8BITSELECT)); emu_wrptr(sc, v->vnum, Z1, 0); @@ -599,12 +847,13 @@ static void emu_vdump(struct sc_info *sc, struct emu_voice *v) { - char *regname[] = { "cpf", "ptrx", "cvcf", "vtft", "z2", "z1", "psst", "dsl", - "ccca", "ccr", "clp", "fxrt", "mapa", "mapb", NULL, NULL, - "envvol", "atkhldv", "dcysusv", "lfoval1", - "envval", "atkhldm", "dcysusm", "lfoval2", - "ip", "ifatn", "pefe", "fmmod", "tremfrq", "fmfrq2", - "tempenv" }; + char *regname[] = { + "cpf", "ptrx", "cvcf", "vtft", "z2", "z1", "psst", "dsl", + "ccca", "ccr", "clp", "fxrt", "mapa", "mapb", NULL, NULL, + "envvol", "atkhldv", "dcysusv", "lfoval1", + "envval", "atkhldm", "dcysusm", "lfoval2", + "ip", "ifatn", "pefe", "fmmod", "tremfrq", "fmfrq2", "tempenv" + }; int i, x; printf("voice number %d\n", v->vnum); @@ -621,7 +870,7 @@ } #endif -/* channel interface */ +/* playback channel interface */ static void * emupchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { @@ -757,7 +1006,7 @@ }; CHANNEL_DECLARE(emupchan); -/* channel interface */ +/* recording channel interface */ static void * emurchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { @@ -775,7 +1024,7 @@ ch->num = sc->rnum; switch(sc->rnum) { case 0: - ch->idxreg = ADCIDX; + ch->idxreg = sc->is_audigy ? A_ADCIDX : ADCIDX; ch->basereg = ADCBA; ch->sizereg = ADCBS; ch->setupreg = ADCCR; @@ -889,9 +1138,11 @@ ch->run = 1; emu_wrptr(sc, 0, ch->sizereg, sz); if (ch->num == 0) { - val = ADCCR_LCHANENABLE; + val = sc->is_audigy ? A_ADCCR_LCHANENABLE + : ADCCR_LCHANENABLE; if (ch->fmt & AFMT_STEREO) - val |= ADCCR_RCHANENABLE; + val |= sc->is_audigy ? A_ADCCR_RCHANENABLE + : ADCCR_RCHANENABLE; val |= emu_recval(ch->spd); emu_wrptr(sc, 0, ch->setupreg, 0); emu_wrptr(sc, 0, ch->setupreg, val); @@ -1147,8 +1398,8 @@ static void emu_addefxop(struct sc_info *sc, int op, int z, int w, int x, int y, u_int32_t *pc) { - emu_wrefx(sc, (*pc) * 2, (x << 10) | y); - emu_wrefx(sc, (*pc) * 2 + 1, (op << 20) | (z << 10) | w); + emu_wrefx(sc, (*pc) * 2, (x << sc->high_operand_shift) | y); + emu_wrefx(sc, (*pc) * 2 + 1, (op << sc->opcode_shift) | (z << sc->high_operand_shift) | w); (*pc)++; } @@ -1156,84 +1407,220 @@ emu_initefx(struct sc_info *sc) { int i; - u_int32_t pc = 16; + u_int32_t pc = 0; + +/* code size is in bytes... we write 4-byte (2-word) instructions */ + for (i = 0; i < ((sc->code_size)>>2); i++) { + if (sc->is_audigy) { + emu_addefxop(sc, ACC3, DSP_CONST(0x0), DSP_CONST(0x0), + DSP_CONST(0x0), DSP_CONST(0x0), &pc); + } else { + emu_addefxop(sc, ACC3, DSP_CONST(0x0), DSP_CONST(0x0), + DSP_CONST(0x0), DSP_CONST(0x0), &pc); + } + }; + + pc = 0; + + for (i = 0; i < sc->num_gprs; i++) + emu_wrptr(sc, 0, sc->gpr_base + i, 0); - for (i = 0; i < 512; i++) { - emu_wrefx(sc, i * 2, 0x10040); - emu_wrefx(sc, i * 2 + 1, 0x610040); - } - - for (i = 0; i < 256; i++) - emu_wrptr(sc, 0, FXGPREGBASE + i, 0); - - /* FX-8010 DSP Registers: - FX Bus - 0x000-0x00f : 16 registers - Input - 0x010/0x011 : AC97 Codec (l/r) - 0x012/0x013 : ADC, S/PDIF (l/r) - 0x014/0x015 : Mic(left), Zoom (l/r) - 0x016/0x017 : APS S/PDIF?? (l/r) - Output - 0x020/0x021 : AC97 Output (l/r) - 0x022/0x023 : TOS link out (l/r) - 0x024/0x025 : ??? (l/r) - 0x026/0x027 : LiveDrive Headphone (l/r) - 0x028/0x029 : Rear Channel (l/r) - 0x02a/0x02b : ADC Recording Buffer (l/r) - Constants - 0x040 - 0x044 = 0 - 4 - 0x045 = 0x8, 0x046 = 0x10, 0x047 = 0x20 - 0x048 = 0x100, 0x049 = 0x10000, 0x04a = 0x80000 - 0x04b = 0x10000000, 0x04c = 0x20000000, 0x04d = 0x40000000 - 0x04e = 0x80000000, 0x04f = 0x7fffffff - Temporary Values - 0x056 : Accumulator - 0x058 : Noise source? - 0x059 : Noise source? - General Purpose Registers - 0x100 - 0x1ff - Tank Memory Data Registers - 0x200 - 0x2ff - Tank Memory Address Registers - 0x300 - 0x3ff - */ - - /* Operators: - 0 : z := w + (x * y >> 31) - 4 : z := w + x * y - 6 : z := w + x + y - */ - - /* Routing - this will be configurable in later version */ - - /* GPR[0/1] = FX * 4 + SPDIF-in */ - emu_addefxop(sc, 4, 0x100, 0x12, 0, 0x44, &pc); - emu_addefxop(sc, 4, 0x101, 0x13, 1, 0x44, &pc); - /* GPR[0/1] += APS-input */ - emu_addefxop(sc, 6, 0x100, 0x100, 0x40, sc->APS ? 0x16 : 0x40, &pc); - emu_addefxop(sc, 6, 0x101, 0x101, 0x40, sc->APS ? 0x17 : 0x40, &pc); - /* FrontOut (AC97) = GPR[0/1] */ - emu_addefxop(sc, 6, 0x20, 0x40, 0x40, 0x100, &pc); - emu_addefxop(sc, 6, 0x21, 0x40, 0x41, 0x101, &pc); - /* RearOut = (GPR[0/1] * RearVolume) >> 31 */ - /* RearVolume = GRP[0x10/0x11] */ - emu_addefxop(sc, 0, 0x28, 0x40, 0x110, 0x100, &pc); - emu_addefxop(sc, 0, 0x29, 0x40, 0x111, 0x101, &pc); - /* TOS out = GPR[0/1] */ - emu_addefxop(sc, 6, 0x22, 0x40, 0x40, 0x100, &pc); - emu_addefxop(sc, 6, 0x23, 0x40, 0x40, 0x101, &pc); - /* Mute Out2 */ - emu_addefxop(sc, 6, 0x24, 0x40, 0x40, 0x40, &pc); - emu_addefxop(sc, 6, 0x25, 0x40, 0x40, 0x40, &pc); - /* Mute Out3 */ - emu_addefxop(sc, 6, 0x26, 0x40, 0x40, 0x40, &pc); - emu_addefxop(sc, 6, 0x27, 0x40, 0x40, 0x40, &pc); - /* Input0 (AC97) -> Record */ - emu_addefxop(sc, 6, 0x2a, 0x40, 0x40, 0x10, &pc); - emu_addefxop(sc, 6, 0x2b, 0x40, 0x40, 0x11, &pc); - emu_wrptr(sc, 0, DBG, 0); + if (sc->is_audigy) { + /* GPRs: + 0x00...0x0f - inputs + 0x10...0x1f - volumes + 0x20...0x2f - outs + */ + + emu_wrptr(sc, 0, sc->gpr_base + 0x10, 0x7fffffff); /* PCM */ + emu_wrptr(sc, 0, sc->gpr_base + 0x11, 0x7fffffff); + emu_wrptr(sc, 0, sc->gpr_base + 0x12, 0x7fffffff); /* VOL */ + emu_wrptr(sc, 0, sc->gpr_base + 0x13, 0x7fffffff); + emu_wrptr(sc, 0, sc->gpr_base + 0x14, 0x7fffffff); /* AC97 ("rec" label) */ + emu_wrptr(sc, 0, sc->gpr_base + 0x15, 0x7fffffff); + + /* Routing and volume - this should be configurable in later version */ + + /* GPR[0/1] = FX * controlled by PCM control */ + emu_addefxop(sc, MACS, GPR(0x0), DSP_CONST(0x0), PCM0_L, + GPR(0x10), &pc); + emu_addefxop(sc, MACS, GPR(0x1), DSP_CONST(0x0), PCM0_R, + GPR(0x11), &pc); + /* GPR[2/3] = AC97 * conrolled by AC97 "rec" control */ + emu_addefxop(sc, MACS, GPR(0x2), DSP_CONST(0x0), IN_AC97_L, + GPR(0x14), &pc); + emu_addefxop(sc, MACS, GPR(0x3), DSP_CONST(0x0), IN_AC97_R, + GPR(0x15), &pc); + + /* Main Vol * controlled by VOL control */ + emu_addefxop(sc, ACC3, GPR(0x22), DSP_CONST(0x0), GPR(0x0), + GPR(0x2), &pc); + emu_addefxop(sc, ACC3, GPR(0x23), DSP_CONST(0x0), GPR(0x1), + GPR(0x3), &pc); + emu_addefxop(sc, MACS, GPR(0x20), DSP_CONST(0x0), GPR(0x22), + GPR(0x12), &pc); + emu_addefxop(sc, MACS, GPR(0x21), DSP_CONST(0x0), GPR(0x23), + GPR(0x13), &pc); + + /* FrontOut (AC97) = GPR[10/11] */ + + emu_addefxop(sc, ACC3, OUTP(0x0), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x1), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* TOS out = GPR[0/1] */ + emu_addefxop(sc, ACC3, OUTP(0x2), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x3), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* */ + + emu_addefxop(sc, ACC3, OUTP(0x4), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x5), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* Mute Out3 */ + emu_addefxop(sc, ACC3, OUTP(0x6), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x7), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* RearVolume = GRP[0x10/0x11] */ + emu_addefxop(sc, ACC3, OUTP(0x8), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x9), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* Center / Sub */ + emu_addefxop(sc, ACC3, GPR(0x2A), DSP_CONST(0x0), GPR(0x0), + GPR(0x1), &pc); + emu_addefxop(sc, ACC3, OUTP(0xA), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x2A), &pc); + emu_addefxop(sc, ACC3, OUTP(0xB), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* */ + emu_addefxop(sc, ACC3, OUTP(0xC), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0xD), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* */ + emu_addefxop(sc, ACC3, OUTP(0xE), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0xF), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* */ + emu_addefxop(sc, ACC3, OUTP(0x10), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x11), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* AC97 Rec ? */ + emu_addefxop(sc, ACC3, OUTP(0x12), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x13), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* */ + emu_addefxop(sc, ACC3, OUTP(0x14), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x15), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* ??? */ + emu_addefxop(sc, ACC3, OUTP(0x16), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x17), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* */ + emu_addefxop(sc, ACC3, OUTP(0x18), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x19), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* */ + emu_addefxop(sc, ACC3, OUTP(0x1A), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x1B), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* */ + emu_addefxop(sc, ACC3, OUTP(0x1C), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x1D), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + /* */ + emu_addefxop(sc, ACC3, OUTP(0x1E), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x20), &pc); + emu_addefxop(sc, ACC3, OUTP(0x1F), DSP_CONST(0x0), + DSP_CONST(0x0), GPR(0x21), &pc); + + emu_wrptr(sc,0,A_DBG,0); + } else { + /* FX-8010 DSP Registers: + FX Bus + 0x000-0x00f : 16 registers + Input + 0x010/0x011 : AC97 Codec (l/r) + 0x012/0x013 : ADC, S/PDIF (l/r) + 0x014/0x015 : Mic(left), Zoom (l/r) + 0x016/0x017 : APS S/PDIF?? (l/r) + Output + 0x020/0x021 : AC97 Output (l/r) + 0x022/0x023 : TOS link out (l/r) + 0x024/0x025 : ??? (l/r) + 0x026/0x027 : LiveDrive Headphone (l/r) + 0x028/0x029 : Rear Channel (l/r) + 0x02a/0x02b : ADC Recording Buffer (l/r) + Constants + 0x040 - 0x044 = 0 - 4 + 0x045 = 0x8, 0x046 = 0x10, 0x047 = 0x20 + 0x048 = 0x100, 0x049 = 0x10000, 0x04a = 0x80000 + 0x04b = 0x10000000, 0x04c = 0x20000000, 0x04d = 0x40000000 + 0x04e = 0x80000000, 0x04f = 0x7fffffff + Temporary Values + 0x056 : Accumulator + 0x058 : Noise source? + 0x059 : Noise source? + General Purpose Registers + 0x100 - 0x1ff + Tank Memory Data Registers + 0x200 - 0x2ff + Tank Memory Address Registers + 0x300 - 0x3ff + */ + + /* Operators: + 0 : z := w + (x * y >> 31) + 4 : z := w + x * y + 6 : z := w + x + y + */ + + /* Routing - this will be configurable in later version */ + + /* GPR[0/1] = FX * 4 + SPDIF-in */ + emu_addefxop(sc, 4, 0x100, 0x12, 0, 0x44, &pc); + emu_addefxop(sc, 4, 0x101, 0x13, 1, 0x44, &pc); + /* GPR[0/1] += APS-input */ + emu_addefxop(sc, 6, 0x100, 0x100, 0x40, sc->APS ? 0x16 : 0x40, + &pc); + emu_addefxop(sc, 6, 0x101, 0x101, 0x40, sc->APS ? 0x17 : 0x40, + &pc); + /* FrontOut (AC97) = GPR[0/1] */ + emu_addefxop(sc, 6, 0x20, 0x40, 0x40, 0x100, &pc); + emu_addefxop(sc, 6, 0x21, 0x40, 0x41, 0x101, &pc); + /* RearOut = (GPR[0/1] * RearVolume) >> 31 */ + /* RearVolume = GRP[0x10/0x11] */ + emu_addefxop(sc, 0, 0x28, 0x40, 0x110, 0x100, &pc); + emu_addefxop(sc, 0, 0x29, 0x40, 0x111, 0x101, &pc); + /* TOS out = GPR[0/1] */ + emu_addefxop(sc, 6, 0x22, 0x40, 0x40, 0x100, &pc); + emu_addefxop(sc, 6, 0x23, 0x40, 0x40, 0x101, &pc); + /* Mute Out2 */ + emu_addefxop(sc, 6, 0x24, 0x40, 0x40, 0x40, &pc); + emu_addefxop(sc, 6, 0x25, 0x40, 0x40, 0x40, &pc); + /* Mute Out3 */ + emu_addefxop(sc, 6, 0x26, 0x40, 0x40, 0x40, &pc); + emu_addefxop(sc, 6, 0x27, 0x40, 0x40, 0x40, &pc); + /* Input0 (AC97) -> Record */ + emu_addefxop(sc, 6, 0x2a, 0x40, 0x40, 0x10, &pc); + emu_addefxop(sc, 6, 0x2b, 0x40, 0x40, 0x11, &pc); + + emu_wrptr(sc, 0, DBG, 0); + } } /* Probe and attach the card */ @@ -1260,6 +1647,13 @@ emu_wrptr(sc, 0, SOLEL, 0); emu_wrptr(sc, 0, SOLEH, 0); + /* init phys inputs and outputs */ + if (sc->is_audigy) { + emu_wrptr(sc, 0, SPBYPASS, 0x00); + emu_wrptr(sc, 0, AC97SLOT, + 0x40 | AC97SLOT_CNTR | AC97SLOT_LFE | 0x02 | 0x01); + }; + /* init envelope engine */ for (ch = 0; ch < NUM_G; ch++) { emu_wrptr(sc, ch, DCYSUSV, ENV_OFF); @@ -1267,7 +1661,6 @@ emu_wrptr(sc, ch, VTFT, 0xffff); emu_wrptr(sc, ch, CVCF, 0xffff); emu_wrptr(sc, ch, PTRX, 0); - emu_wrptr(sc, ch, CPF, 0); emu_wrptr(sc, ch, CCR, 0); emu_wrptr(sc, ch, PSST, 0); @@ -1292,6 +1685,17 @@ emu_wrptr(sc, ch, ATKHLDV, 0); emu_wrptr(sc, ch, ENVVOL, 0); emu_wrptr(sc, ch, ENVVAL, 0); + emu_wrptr(sc, ch, CPF, 0); + + if (sc->is_audigy) { + emu_wrptr(sc, ch, 0x4c, 0x0); + emu_wrptr(sc, ch, 0x4d, 0x0); + emu_wrptr(sc, ch, 0x4e, 0x0); + emu_wrptr(sc, ch, 0x4f, 0x0); + emu_wrptr(sc, ch, A_FXRT1, 0x3f3f3f3f); + emu_wrptr(sc, ch, A_FXRT2, 0x3f3f3f3f); + emu_wrptr(sc, ch, A_SENDAMOUNTS, 0x0); + } sc->voice[ch].vnum = ch; sc->voice[ch].slave = NULL; @@ -1365,13 +1769,93 @@ * Lock Sound Memory = 0 * Auto Mute = 1 */ - tmp = HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE; + tmp = HCFG_AUDIOENABLE | HCFG_AUTOMUTE; if (sc->rev >= 6) tmp |= HCFG_JOYENABLE; + if (sc->is_audigy) + tmp |= HCFG_CODECFORMAT_I2S | HCFG_GPOUT0 | HCFG_JOYENABLE; + else + tmp |= HCFG_LOCKTANKCACHE_MASK; emu_wr(sc, HCFG, tmp, 4); +#if 0 + if (0) { /* enable IR for SB Live */ + tmp = emu_rd(sc,HCFG,4); + emu_wr(sc, HCFG, tmp | HCFG_GPOUT2, 4); + DELAY(500); + emu_wr(sc, HCFG, tmp | HCFG_GPOUT1 | HCFG_GPOUT2, 4); + DELAY(500); +/* emu_wr(sc, HCFG, tmp, 4); */ + } +#endif + + tmp = emu_rd(sc, HCFG, 4); + device_printf(sc->dev, "Card Configuration ( 0x%08x )\n",tmp); + device_printf(sc->dev, + "Card Configuration ( & 0xff000000 ) : %s%s%s%s%s%s%s%s\n", + (tmp&0x80000000 ? "[Legacy MPIC] " : ""), + (tmp&0x40000000 ? "[0x40] " : ""), + (tmp&0x20000000 ? "[0x20] " : ""), + (tmp&0x10000000 ? "[0x10] " : ""), + (tmp&0x08000000 ? "[0x08] " : ""), + (tmp&0x04000000 ? "[0x04] " : ""), + (tmp&0x02000000 ? "[0x02] " : ""), + (tmp&0x01000000 ? "[0x01]" : "")); + device_printf(sc->dev, + "Card Configuration ( & 0x00ff0000 ) : %s%s%s%s%s%s%s%s\n", + (tmp&0x00800000 ? "[0x80] " : ""), + (tmp&0x00400000 ? "[0x40] " : ""), + (tmp&0x00200000 ? "[Legacy INT] " : ""), + (tmp&0x00100000 ? "[0x10] " : ""), + (tmp&0x00080000 ? "[0x08] " : ""), + (tmp&0x00040000 ? "[Codec4] " : ""), + (tmp&0x00020000 ? "[Codec2] " : ""), + (tmp&0x00010000 ? "[I2S Codec]" : "")); + device_printf(sc->dev, + "Card Configuration ( & 0x0000ff00 ) : %s%s%s%s%s%s%s%s\n", + (tmp&0x00008000 ? "[0x80] " : ""), + (tmp&0x00004000 ? "[GPINPUT0] " : ""), + (tmp&0x00002000 ? "[GPINPUT1] " : ""), + (tmp&0x00001000 ? "[GPOUT0] " : ""), + (tmp&0x00000800 ? "[GPOUT1] " : ""), + (tmp&0x00000400 ? "[GPOUT2] " : ""), + (tmp&0x00000200 ? "[Joystick] " : ""), + (tmp&0x00000100 ? "[0x01]" : "")); + device_printf(sc->dev, + "Card Configuration ( & 0x000000ff ) : %s%s%s%s%s%s%s%s\n", + (tmp&0x00000080 ? "[0x80] " : ""), + (tmp&0x00000040 ? "[0x40] " : ""), + (tmp&0x00000020 ? "[0x20] " : ""), + (tmp&0x00000010 ? "[AUTOMUTE] " : ""), + (tmp&0x00000008 ? "[LOCKSOUNDCACHE] " : ""), + (tmp&0x00000004 ? "[LOCKTANKCACHE] " : ""), + (tmp&0x00000002 ? "[MUTEBUTTONENABLE] " : ""), + (tmp&0x00000001 ? "[AUDIOENABLE]" : "")); + + if (sc->is_audigy) { + tmp = emu_rd(sc, A_IOCFG, 2); + device_printf(sc->dev, "Audigy Card Configuration ( 0x%04x )\n", + tmp); + device_printf(sc->dev, + "Connectors attached: %s%s%s%s%s%s%s%s\n", + (tmp&0x8000 ? "[Rear Speakers] " : ""), + (tmp&0x4000 ? "[Front Speakers] " : ""), + (tmp&0x2000 ? "[0x20] " : ""), + (tmp&0x1000 ? "[0x10] " : ""), + (tmp&0x0800 ? "[0x08] " : ""), + (tmp&0x0400 ? "[0x04] " : ""), + (tmp&0x0200 ? "[0x02] " : ""), + (tmp&0x0100 ? "[AudigyDrive Phones]" : "")); + emu_wrptr(sc,0, A_SPDIF_SAMPLERATE, A_SPDIF_48000); + } + - /* TOSLink detection */ sc->tos_link = 0; +#if 0 + /* + ALSA Driver stated that this code disbales LiveDrive !!! + */ + /* TOSLink detection */ + tmp = emu_rd(sc, HCFG, 4); if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) { emu_wr(sc, HCFG, tmp | 0x800, 4); @@ -1381,7 +1865,7 @@ emu_wr(sc, HCFG, tmp, 4); } } - +#endif return 0; } @@ -1439,11 +1923,9 @@ case EMU10K1_PCI_ID: s = "Creative EMU10K1"; break; -/* case EMU10K2_PCI_ID: s = "Creative EMU10K2"; break; -*/ default: return ENXIO; } @@ -1466,11 +1948,71 @@ return ENXIO; } + ctl_sc_info = sc; sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); sc->dev = dev; sc->type = pci_get_devid(dev); sc->rev = pci_get_revid(dev); + switch (sc->type) { + case EMU10K1_PCI_ID: + sc->is_audigy = 0; + sc->opcode_shift = 20; + sc->high_operand_shift = 10; + sc->code_base = MICROCODEBASE; + sc->code_size = 512; + sc->gpr_base = FXGPREGBASE; + sc->num_gprs = 0x100; + sc->input_base = 0x10; + sc->output_base = 0x20; + sc->dsp_zero=0x40; + sc->mchannel_fx = 0; + + /* mono voice */ + sc->waveio.send_dcba[SEND_MONO] = 0x0000ffff; + + /* stereo voice */ + /* left */ + sc->waveio.send_dcba[SEND_LEFT] = 0x000000ff; + /* right */ + sc->waveio.send_dcba[SEND_RIGHT] = 0x0000ff00; + + sc->waveio.send_routing[ROUTE_PCM0] = 0x00003210; /* Regular pcm*/ + + break; + case EMU10K2_PCI_ID: + sc->is_audigy = 1; + sc->opcode_shift = 24; + sc->high_operand_shift = 12; + sc->code_base = AUDIGY_CODEBASE; + sc->code_size = 1024; + sc->gpr_base = A_FXGPREGBASE; + sc->num_gprs = 0x200; + sc->input_base = 0x40; + sc->output_base = 0x60; + sc->dsp_zero=0xc0; + sc->mchannel_fx = 8; + /* mono voice */ + + sc->waveio.send_dcba[SEND_MONO] = 0xffffffff; + sc->waveio.send_hgfe[SEND_MONO] = 0x0000ffff; + + /* stereo voice */ + /* left */ + sc->waveio.send_dcba[SEND_LEFT] = 0x00ff00ff; + sc->waveio.send_hgfe[SEND_LEFT] = 0x00007f7f; + /* right */ + sc->waveio.send_dcba[SEND_RIGHT] = 0xff00ff00; + sc->waveio.send_hgfe[SEND_RIGHT] = 0x00007f7f; + + sc->waveio.send_routing[ROUTE_PCM0] = 0x03020100; /* Regular pcm*/ + sc->waveio.send_routing2[ROUTE_PCM0] = 0x07060504; + + break; + default: + return ENXIO; + } + data = pci_read_config(dev, PCIR_COMMAND, 2); data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN); pci_write_config(dev, PCIR_COMMAND, data, 2); @@ -1497,6 +2039,16 @@ goto bad; } + i = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &i, 0, ~0, 1, + RF_ACTIVE | RF_SHAREABLE); + if (!sc->irq || + snd_setup_intr(dev, sc->irq, INTR_MPSAFE, emu_intr, sc, &sc->ih)) { + device_printf(dev, "unable to map interrupt\n"); + goto bad; + } + + if (emu_init(sc) == -1) { device_printf(dev, "unable to initialize the card\n"); goto bad; @@ -1504,15 +2056,20 @@ codec = AC97_CREATE(dev, sc, emu_ac97); if (codec == NULL) goto bad; + sc->codec = codec; gotmic = (ac97_getcaps(codec) & AC97_CAP_MICCHANNEL) ? 1 : 0; if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; +#if 0 + if (mixer_init(dev, &emu_mix_class, sc) == -1) goto bad; +#endif + + emu_wr(sc,AC97ADDRESS,0x18,1); + emu_wr(sc,AC97DATA,(sc->is_audigy) ? 0x8000 : 0x0000,2); + + emu_wr(sc,AC97ADDRESS,AC97_RECORD_GAIN,1); + emu_wr(sc,AC97DATA,0x0000,2); + - i = 0; - sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &i, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); - if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, emu_intr, sc, &sc->ih)) { - device_printf(dev, "unable to map interrupt\n"); - goto bad; - } snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", rman_get_start(sc->reg), rman_get_start(sc->irq)); @@ -1581,6 +2138,46 @@ MODULE_DEPEND(snd_emu10k1, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); MODULE_VERSION(snd_emu10k1, 1); +/* sysctls to RO access to 8010 memory from userland */ +static int +sysctl_hw_snd_emu10k_dump(SYSCTL_HANDLER_ARGS) +{ + int error, i, j, v; + struct sbuf *sb; + + sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); + sbuf_clear(sb); + sbuf_printf(sb, "EMU8010 per-voice dump\n"); + for(v = 0; v < 64; v++) { + sbuf_printf(sb, "voice %04x\n", v); + for(i = 0; i < 0x20; i++) { + sbuf_printf(sb, "%04x", i * 0x4); + for(j = 0; j < 4; j++) + sbuf_printf(sb, " %08x", + emu_rdptr(ctl_sc_info, v, i * 0x4 + j)); + sbuf_printf(sb,"\n"); + }; + }; + sbuf_printf(sb, "EMU8010 memory dump\n"); + for(i = 0; i < 0x200; i++) { + sbuf_printf(sb, "%04x", i * 0x4); + for (j = 0; j < 0x4; j++) + sbuf_printf(sb, " %08x", emu_rdptr(ctl_sc_info, 0, + i * 0x4 + j)); + sbuf_printf(sb,"\n"); + }; + error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); + sbuf_delete(sb); + return error; +} + +SYSCTL_NODE(_hw_snd, OID_AUTO, emu10k, CTLFLAG_RW, 0, "EMU10Kx management"); + +SYSCTL_PROC(_hw_snd_emu10k, OID_AUTO, dump, CTLTYPE_STRING|CTLFLAG_RD, + 0, 0, sysctl_hw_snd_emu10k_dump, "", + "Dump EMU10Kx memory in text"); + + /* dummy driver to silence the joystick device */ static int emujoy_pci_probe(device_t dev) Index: sys/gnu/dev/sound/pci/emu10k1.h =================================================================== RCS file: /home/ncvs/src/sys/gnu/dev/sound/pci/emu10k1.h,v retrieving revision 1.6 diff -u -r1.6 emu10k1.h --- sys/gnu/dev/sound/pci/emu10k1.h 18 Apr 2003 04:13:38 -0000 1.6 +++ sys/gnu/dev/sound/pci/emu10k1.h 20 Apr 2003 07:20:37 -0000 @@ -1,7 +1,7 @@ /* ********************************************************************** * emu10k1.h, derived from 8010.h - * Copyright 1999, 2000 Creative Labs, Inc. + * Copyright 1999-2001 Creative Labs, Inc. * ********************************************************************** * @@ -11,6 +11,8 @@ * November 2, 1999 Alan Cox Cleaned of 8bit chars, DOS * line endings * December 8, 1999 Jon Taylor Added lots of new register info + * May 16, 2001 Daniel Bertrand Added unofficial DBG register info + * Oct-Nov 2001 D.B. Added unofficial Audigy registers * ********************************************************************** * @@ -38,21 +40,14 @@ #ifndef EMU10K1_H #define EMU10K1_H -/* ------------------- DEFINES -------------------- */ +/* +// Driver version: +#define MAJOR_VER 0 +#define MINOR_VER 20 +#define DRIVER_VERSION "0.20a" +*/ -#define EMUPAGESIZE 4096 /* don't change */ -#define MAXREQVOICES 8 -#define MAXPAGES (32768 * 64 / EMUPAGESIZE) /* WAVEOUT_MAXBUFSIZE * NUM_G / EMUPAGESIZE */ -#define RESERVED 0 -#define NUM_MIDI 16 -#define NUM_G 64 /* use all channels */ -#define NUM_FXSENDS 4 - - -#define TMEMSIZE 256*1024 -#define TMEMSIZEREG 4 - -#define IP_TO_CP(ip) ((ip == 0) ? 0 : (((0x00001000uL | (ip & 0x00000FFFL)) << (((ip >> 12) & 0x000FL) + 4)) & 0xFFFF0000uL)) +/* Audigy specify registers are prefixed with 'A_' */ /************************************************************************************************/ /* PCI function 0 registers, address = <val> + PCIBASE0 */ @@ -72,6 +67,11 @@ #define IPR 0x08 /* Global interrupt pending register */ /* Clear pending interrupts by writing a 1 to */ /* the relevant bits and zero to the other bits */ + +/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */ +#define A_IPR_MIDITRANSBUFEMPTY2 0x10000000 /* MIDI UART transmit buffer empty */ +#define A_IPR_MIDIRECVBUFEMPTY2 0x08000000 /* MIDI UART receive buffer empty */ + #define IPR_SAMPLERATETRACKER 0x01000000 /* Sample rate tracker lock status change */ #define IPR_FXDSP 0x00800000 /* Enable FX DSP interrupts */ #define IPR_FORCEINT 0x00400000 /* Force Sound Blaster interrupt */ @@ -96,6 +96,10 @@ /* IP is written with CL set, the bit in CLIPL */ /* or CLIPH corresponding to the CIN value */ /* written will be cleared. */ +#define A_IPR_MIDITRANSBUFEMPTY1 IPR_MIDITRANSBUFEMPTY /* MIDI UART transmit buffer empty */ +#define A_IPR_MIDIRECVBUFEMPTY1 IPR_MIDIRECVBUFEMPTY /* MIDI UART receive buffer empty */ + + #define INTE 0x0c /* Interrupt enable register */ #define INTE_VIRTUALSB_MASK 0xc0000000 /* Virtual Soundblaster I/O port capture */ @@ -123,6 +127,11 @@ /* behavior and possibly random segfaults and */ /* lockups if enabled. */ +/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */ +#define A_INTE_MIDITXENABLE2 0x00020000 /* Enable MIDI transmit-buffer-empty interrupts */ +#define A_INTE_MIDIRXENABLE2 0x00010000 /* Enable MIDI receive-buffer-empty interrupts */ + + #define INTE_SAMPLERATETRACKER 0x00002000 /* Enable sample rate tracker interrupts */ /* NOTE: This bit must always be enabled */ #define INTE_FXDSPENABLE 0x00001000 /* Enable FX DSP interrupts */ @@ -139,6 +148,10 @@ #define INTE_MIDITXENABLE 0x00000002 /* Enable MIDI transmit-buffer-empty interrupts */ #define INTE_MIDIRXENABLE 0x00000001 /* Enable MIDI receive-buffer-empty interrupts */ +/* The next two interrupts are for the midi port on the Audigy (A_MPU2) */ +#define A_INTE_MIDITXENABLE1 INTE_MIDITXENABLE +#define A_INTE_MIDIRXENABLE1 INTE_MIDIRXENABLE + #define WC 0x10 /* Wall Clock register */ #define WC_SAMPLECOUNTER_MASK 0x03FFFFC0 /* Sample periods elapsed since reset */ #define WC_SAMPLECOUNTER 0x14060010 @@ -170,7 +183,12 @@ #define HCFG_CODECFORMAT_I2S 0x00010000 /* I2S CODEC format -- Secondary (Rear) Output */ #define HCFG_GPINPUT0 0x00004000 /* External pin112 */ #define HCFG_GPINPUT1 0x00002000 /* External pin110 */ + #define HCFG_GPOUTPUT_MASK 0x00001c00 /* External pins which may be controlled */ +#define HCFG_GPOUT0 0x00001000 /* set to enable digital out on 5.1 cards */ +#define HCFG_GPOUT1 0x00000800 /* External pin? (IR) */ +#define HCFG_GPOUT2 0x00000400 /* External pin? (IR) */ + #define HCFG_JOYENABLE 0x00000200 /* Internal joystick enable */ #define HCFG_PHASETRACKENABLE 0x00000100 /* Phase tracking enable */ /* 1 = Force all 3 async digital inputs to use */ @@ -178,6 +196,7 @@ #define HCFG_AC3ENABLE_MASK 0x0x0000e0 /* AC3 async input control - Not implemented */ #define HCFG_AC3ENABLE_ZVIDEO 0x00000080 /* Channels 0 and 1 replace ZVIDEO */ #define HCFG_AC3ENABLE_CDSPDIF 0x00000040 /* Channels 0 and 1 replace CDSPDIF */ +#define HCFG_AC3ENABLE_GPSPDIF 0x00000020 /* Channels 0 and 1 replace GPSPDIF */ #define HCFG_AUTOMUTE 0x00000010 /* When set, the async sample rate convertors */ /* will automatically mute their output when */ /* they are not rate-locked to the external */ @@ -186,6 +205,7 @@ /* NOTE: This should generally never be used. */ #define HCFG_LOCKTANKCACHE_MASK 0x00000004 /* 1 = Cancel bustmaster accesses to tankcache */ /* NOTE: This should generally never be used. */ +#define HCFG_LOCKTANKCACHE 0x01020014 #define HCFG_MUTEBUTTONENABLE 0x00000002 /* 1 = Master mute button sets AUDIOENABLE = 0. */ /* NOTE: This is a 'cheap' way to implement a */ /* master mute function on the mute button, and */ @@ -196,6 +216,8 @@ /* Should be set to 1 when the EMU10K1 is */ /* completely initialized. */ +/*For Audigy, MPU port move to 0x70-0x74 ptr register */ + #define MUDATA 0x18 /* MPU401 data register (8 bits) */ #define MUCMD 0x19 /* MPU401 command register (8 bits) */ @@ -207,11 +229,16 @@ #define MUSTAT_IRDYN 0x80 /* 0 = MIDI data or command ACK */ #define MUSTAT_ORDYN 0x40 /* 0 = MUDATA can accept a command or data */ -#define TIMER 0x1a /* Timer terminal count register */ +#define A_IOCFG 0x18 /* GPIO on Audigy card (16bits) */ +#define A_GPINPUT_MASK 0xff00 +#define A_GPOUTPUT_MASK 0x00ff +#define A_IOCFG_GPOUT0 0x0044 /* ? */ + +#define TIMER 0x1a /* Timer terminal count register (16-bit) */ /* NOTE: After the rate is changed, a maximum */ /* of 1024 sample periods should be allowed */ /* before the new rate is guaranteed accurate. */ -#define TIMER_RATE_MASK 0x000003ff /* Timer interrupt rate in sample periods */ +#define TIMER_RATE_MASK 0x03ff /* Timer interrupt rate in sample periods */ /* 0 == 1024 periods, [1..4] are not useful */ #define TIMER_RATE 0x0a00001a @@ -221,54 +248,6 @@ #define AC97ADDRESS_READY 0x80 /* Read-only bit, reflects CODEC READY signal */ #define AC97ADDRESS_ADDRESS 0x7f /* Address of indexed AC97 register */ -/************************************************************************************************/ -/* PCI function 1 registers, address = <val> + PCIBASE1 */ -/************************************************************************************************/ - -#define JOYSTICK1 0x00 /* Analog joystick port register */ -#define JOYSTICK2 0x01 /* Analog joystick port register */ -#define JOYSTICK3 0x02 /* Analog joystick port register */ -#define JOYSTICK4 0x03 /* Analog joystick port register */ -#define JOYSTICK5 0x04 /* Analog joystick port register */ -#define JOYSTICK6 0x05 /* Analog joystick port register */ -#define JOYSTICK7 0x06 /* Analog joystick port register */ -#define JOYSTICK8 0x07 /* Analog joystick port register */ - -/* When writing, any write causes JOYSTICK_COMPARATOR output enable to be pulsed on write. */ -/* When reading, use these bitfields: */ -#define JOYSTICK_BUTTONS 0x0f /* Joystick button data */ -#define JOYSTICK_COMPARATOR 0xf0 /* Joystick comparator data */ - - -/********************************************************************************************************/ -/* AC97 pointer-offset register set, accessed through the AC97ADDRESS and AC97DATA registers */ -/********************************************************************************************************/ - -#define AC97_RESET 0x00 -#define AC97_MASTERVOLUME 0x02 /* Master volume */ -#define AC97_HEADPHONEVOLUME 0x04 /* Headphone volume */ -#define AC97_MASTERVOLUMEMONO 0x06 /* Mast volume mono */ -#define AC97_MASTERTONE 0x08 -#define AC97_PCBEEPVOLUME 0x0a /* PC speaker system beep volume */ -#define AC97_PHONEVOLUME 0x0c -#define AC97_MICVOLUME 0x0e -#define AC97_LINEINVOLUME 0x10 -#define AC97_CDVOLUME 0x12 -#define AC97_VIDEOVOLUME 0x14 -#define AC97_AUXVOLUME 0x16 -#define AC97_PCMOUTVOLUME 0x18 -#define AC97_RECORDSELECT 0x1a -#define AC97_RECORDGAIN 0x1c -#define AC97_RECORDGAINMIC 0x1e -#define AC97_GENERALPURPOSE 0x20 -#define AC97_3DCONTROL 0x22 -#define AC97_MODEMRATE 0x24 -#define AC97_POWERDOWN 0x26 -#define AC97_VENDORID1 0x7c -#define AC97_VENDORID2 0x7e -#define AC97_ZVIDEOVOLUME 0xec -#define AC97_AC3VOLUME 0xed - /********************************************************************************************************/ /* Emu10k1 pointer-offset register set, accessed through the PTR and DATA registers */ /********************************************************************************************************/ @@ -444,6 +423,8 @@ #define TREMFRQ 0x1c /* Tremolo amount and modulation LFO frequency register */ #define TREMFRQ_DEPTH 0x0000ff00 /* Tremolo depth */ /* Signed 2's complement, with +/- 12dB extremes */ +#define TREMFRQ_FREQUENCY 0x000000ff /* Tremolo LFO frequency */ + /* ??Hz steps, maximum of ?? Hz. */ #define FM2FRQ2 0x1d /* Vibrato amount and vibrato LFO frequency register */ #define FM2FRQ2_DEPTH 0x0000ff00 /* Vibrato LFO vibrato depth */ @@ -484,7 +465,12 @@ #define ADCCR_LCHANENABLE 0x00000008 /* Enables left channel for writing to the host */ /* NOTE: To guarantee phase coherency, both channels */ /* must be disabled prior to enabling both channels. */ +#define A_ADCCR_RCHANENABLE 0x00000020 +#define A_ADCCR_LCHANENABLE 0x00000010 + +#define A_ADCCR_SAMPLERATE_MASK 0x0000000F /* Audigy sample rate convertor output rate */ #define ADCCR_SAMPLERATE_MASK 0x00000007 /* Sample rate convertor output rate */ + #define ADCCR_SAMPLERATE_48 0x00000000 /* 48kHz sample rate */ #define ADCCR_SAMPLERATE_44 0x00000001 /* 44.1kHz sample rate */ #define ADCCR_SAMPLERATE_32 0x00000002 /* 32kHz sample rate */ @@ -494,10 +480,16 @@ #define ADCCR_SAMPLERATE_11 0x00000006 /* 11.025kHz sample rate */ #define ADCCR_SAMPLERATE_8 0x00000007 /* 8kHz sample rate */ +#define A_ADCCR_SAMPLERATE_12 0x00000006 /* 12kHz sample rate */ +#define A_ADCCR_SAMPLERATE_11 0x00000007 /* 11.025kHz sample rate */ +#define A_ADCCR_SAMPLERATE_8 0x00000008 /* 8kHz sample rate */ + #define FXWC 0x43 /* FX output write channels register */ /* When set, each bit enables the writing of the */ - /* corresponding FX output channel into host memory */ - + /* corresponding FX output channel (internal registers */ + /* 0x20-0x3f) into host memory. This mode of recording */ + /* is 16bit, 48KHz only. All 32 channels can be enabled */ + /* simultaneously. */ #define TCBS 0x44 /* Tank cache buffer size register */ #define TCBS_MASK 0x00000007 /* Tank cache buffer size field */ #define TCBS_BUFFSIZE_16K 0x00000000 @@ -565,8 +557,25 @@ #define DBG 0x52 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ +/* definitions for debug register - taken from the alsa drivers */ +#define DBG_ZC 0x80000000 /* zero tram counter */ +#define DBG_SATURATION_OCCURED 0x02000000 /* saturation control */ +#define DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */ +#define DBG_SINGLE_STEP 0x00008000 /* single step mode */ +#define DBG_STEP 0x00004000 /* start single step */ +#define DBG_CONDITION_CODE 0x00003e00 /* condition code */ +#define DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */ + + #define REG53 0x53 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ +#define A_DBG 0x53 +#define A_DBG_SINGLE_STEP 0x00020000 /* Set to zero to start dsp */ +#define A_DBG_ZC 0x40000000 /* zero tram counter */ +#define A_DBG_STEP_ADDR 0x000003ff +#define A_DBG_SATURATION_OCCURED 0x20000000 +#define A_DBG_SATURATION_ADDR 0x0ffc0000 + #define SPCS0 0x54 /* SPDIF output Channel Status 0 register */ #define SPCS1 0x55 /* SPDIF output Channel Status 1 register */ @@ -613,6 +622,10 @@ #define SPBYPASS 0x5e /* SPDIF BYPASS mode register */ #define SPBYPASS_ENABLE 0x00000001 /* Enable SPDIF bypass mode */ +#define AC97SLOT 0x5f /* additional AC97 slots enable bits */ +#define AC97SLOT_CNTR 0x10 /* Center enable */ +#define AC97SLOT_LFE 0x20 /* LFE enable */ + #define CDSRCS 0x60 /* CD-ROM Sample Rate Converter status register */ #define GPSRCS 0x61 /* General Purpose SPDIF sample rate cvt status */ @@ -626,10 +639,19 @@ #define SRCS_RATELOCKED 0x01000000 /* Sample rate locked */ #define SRCS_ESTSAMPLERATE 0x0007ffff /* Do not modify this field. */ + +/* Note that these values can vary +/- by a small amount */ +#define SRCS_SPDIFRATE_44 0x0003acd9 +#define SRCS_SPDIFRATE_48 0x00040000 +#define SRCS_SPDIFRATE_96 0x00080000 + #define MICIDX 0x63 /* Microphone recording buffer index register */ #define MICIDX_MASK 0x0000ffff /* 16-bit value */ #define MICIDX_IDX 0x10000063 +#define A_ADCIDX 0x63 +#define A_ADCIDX_IDX 0x10000063 + #define ADCIDX 0x64 /* ADC recording buffer index register */ #define ADCIDX_MASK 0x0000ffff /* 16 bit index field */ #define ADCIDX_IDX 0x10000064 @@ -638,9 +660,50 @@ #define FXIDX_MASK 0x0000ffff /* 16-bit value */ #define FXIDX_IDX 0x10000065 +/* This is the MPU port on the card (via the game port) */ +#define A_MUDATA1 0x70 +#define A_MUCMD1 0x71 +#define A_MUSTAT1 A_MUCMD1 + +/* This is the MPU port on the Audigy Drive */ +#define A_MUDATA2 0x72 +#define A_MUCMD2 0x73 +#define A_MUSTAT2 A_MUCMD2 + +/* The next two are the Audigy equivalent of FXWC */ +/* the Audigy can record any output (16bit, 48kHz, up to 64 channel simultaneously) */ +/* Each bit selects a channel for recording */ +#define A_FXWC1 0x74 /* Selects 0x7f-0x60 for FX recording */ +#define A_FXWC2 0x75 /* Selects 0x9f-0x80 for FX recording */ + +#define A_SPDIF_SAMPLERATE 0x76 /* Set the sample rate of SPDIF output */ +#define A_SPDIF_48000 0x00000080 +#define A_SPDIF_44100 0x00000000 +#define A_SPDIF_96000 0x00000040 + +#define A_FXRT2 0x7c +#define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */ +#define A_FXRT_CHANNELF 0x00003f00 /* Effects send bus number for channel's effects send F */ +#define A_FXRT_CHANNELG 0x003f0000 /* Effects send bus number for channel's effects send G */ +#define A_FXRT_CHANNELH 0x3f000000 /* Effects send bus number for channel's effects send H */ + +#define A_SENDAMOUNTS 0x7d +#define A_FXSENDAMOUNT_E_MASK 0xff000000 +#define A_FXSENDAMOUNT_F_MASK 0x00ff0000 +#define A_FXSENDAMOUNT_G_MASK 0x0000ff00 +#define A_FXSENDAMOUNT_H_MASK 0x000000ff + +/* The send amounts for this one are the same as used with the emu10k1 */ +#define A_FXRT1 0x7e +#define A_FXRT_CHANNELA 0x0000003f +#define A_FXRT_CHANNELB 0x00003f00 +#define A_FXRT_CHANNELC 0x003f0000 +#define A_FXRT_CHANNELD 0x3f000000 + + /* Each FX general purpose register is 32 bits in length, all bits are used */ #define FXGPREGBASE 0x100 /* FX general purpose registers base */ - +#define A_FXGPREGBASE 0x400 /* Audigy GPRs, 0x400 to 0x5ff */ /* Tank audio data is logarithmically compressed down to 16 bits before writing to TRAM and is */ /* decompressed back to 20 bits on a read. There are a total of 160 locations, the last 32 */ /* locations are for external TRAM. */ @@ -665,10 +728,13 @@ #define HIWORD_RESULT_MASK 0x000ffc00 /* Instruction result */ #define HIWORD_OPA_MASK 0x000003ff /* Instruction operand A */ -#define ENABLE 0xffffffff -#define DISABLE 0x00000000 -#define ENV_ON 0x80 -#define ENV_OFF 0x00 +/* Audigy Soundcard have a different instruction format */ +#define AUDIGY_CODEBASE 0x600 +#define A_LOWORD_OPY_MASK 0x000007ff +#define A_LOWORD_OPX_MASK 0x007ff000 +#define A_HIWORD_OPCODE_MASK 0x0f000000 +#define A_HIWORD_RESULT_MASK 0x007ff000 +#define A_HIWORD_OPA_MASK 0x000007ff #endif /* EMU10K1_H */ Index: sys/gnu/dev/sound/pci/emu10k1-ac97.h =================================================================== RCS file: sys/gnu/dev/sound/pci/emu10k1-ac97.h diff -N sys/gnu/dev/sound/pci/emu10k1-ac97.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/gnu/dev/sound/pci/emu10k1-ac97.h 18 Apr 2003 14:08:06 -0000 @@ -0,0 +1,191 @@ +#ifndef _EMU10K1_AC97_H_ +#define _EMU10K1_AC97_H_ + +/*********************************************/ +/* emu10k1-ac97.h, derived from ac97_codec.h */ +/*********************************************/ + +/********************************************************************************************************/ +/* AC97 pointer-offset register set, accessed through the AC97ADDRESS and AC97DATA registers */ +/********************************************************************************************************/ + + + +/* AC97 1.0 */ +#define AC97_RESET 0x0000 /* */ +#define AC97_MASTER_VOL_STEREO 0x0002 /* Line Out */ +#define AC97_HEADPHONE_VOL 0x0004 /* */ +#define AC97_MASTER_VOL_MONO 0x0006 /* TAD Output */ +#define AC97_MASTER_TONE 0x0008 /* */ +#define AC97_PCBEEP_VOL 0x000a /* none */ +#define AC97_PHONE_VOL 0x000c /* TAD Input (mono) */ +#define AC97_MIC_VOL 0x000e /* MIC Input (mono) */ +#define AC97_LINEIN_VOL 0x0010 /* Line Input (stereo) */ +#define AC97_CD_VOL 0x0012 /* CD Input (stereo) */ +#define AC97_VIDEO_VOL 0x0014 /* none */ +#define AC97_AUX_VOL 0x0016 /* Aux Input (stereo) */ +#define AC97_PCMOUT_VOL 0x0018 /* Wave Output (stereo) */ +#define AC97_RECORD_SELECT 0x001a /* */ +#define AC97_RECORD_GAIN 0x001c +#define AC97_RECORD_GAIN_MIC 0x001e +#define AC97_GENERAL_PURPOSE 0x0020 +#define AC97_3D_CONTROL 0x0022 +#define AC97_MODEM_RATE 0x0024 +#define AC97_POWER_CONTROL 0x0026 + +/* AC'97 2.0 */ +#define AC97_EXTENDED_ID 0x0028 /* Extended Audio ID */ +#define AC97_EXTENDED_STATUS 0x002A /* Extended Audio Status */ +#define AC97_PCM_FRONT_DAC_RATE 0x002C /* PCM Front DAC Rate */ +#define AC97_PCM_SURR_DAC_RATE 0x002E /* PCM Surround DAC Rate */ +#define AC97_PCM_LFE_DAC_RATE 0x0030 /* PCM LFE DAC Rate */ +#define AC97_PCM_LR_ADC_RATE 0x0032 /* PCM LR DAC Rate */ +#define AC97_PCM_MIC_ADC_RATE 0x0034 /* PCM MIC ADC Rate */ +#define AC97_CENTER_LFE_MASTER 0x0036 /* Center + LFE Master Volume */ +#define AC97_SURROUND_MASTER 0x0038 /* Surround (Rear) Master Volume */ +#define AC97_RESERVED_3A 0x003A /* Reserved in AC '97 < 2.2 */ + +/* AC'97 2.2 */ +#define AC97_SPDIF_CONTROL 0x003A /* S/PDIF Control */ + +/* range 0x3c-0x58 - MODEM */ +#define AC97_EXTENDED_MODEM_ID 0x003C +#define AC97_EXTEND_MODEM_STAT 0x003E +#define AC97_LINE1_RATE 0x0040 +#define AC97_LINE2_RATE 0x0042 +#define AC97_HANDSET_RATE 0x0044 +#define AC97_LINE1_LEVEL 0x0046 +#define AC97_LINE2_LEVEL 0x0048 +#define AC97_HANDSET_LEVEL 0x004A +#define AC97_GPIO_CONFIG 0x004C +#define AC97_GPIO_POLARITY 0x004E +#define AC97_GPIO_STICKY 0x0050 +#define AC97_GPIO_WAKE_UP 0x0052 +#define AC97_GPIO_STATUS 0x0054 +#define AC97_MISC_MODEM_STAT 0x0056 +#define AC97_RESERVED_58 0x0058 + +/* registers 0x005a - 0x007a are vendor reserved */ + +#define AC97_VENDOR_ID1 0x007c +#define AC97_VENDOR_ID2 0x007e + +/* volume control bit defines */ +#define AC97_MUTE 0x8000 +#define AC97_MICBOOST 0x0040 +#define AC97_LEFTVOL 0x3f00 +#define AC97_RIGHTVOL 0x003f + +/* record mux defines */ +#define AC97_RECMUX_MIC 0x0000 +#define AC97_RECMUX_CD 0x0101 +#define AC97_RECMUX_VIDEO 0x0202 +#define AC97_RECMUX_AUX 0x0303 +#define AC97_RECMUX_LINE 0x0404 +#define AC97_RECMUX_STEREO_MIX 0x0505 +#define AC97_RECMUX_MONO_MIX 0x0606 +#define AC97_RECMUX_PHONE 0x0707 + +/* general purpose register bit defines */ +#define AC97_GP_LPBK 0x0080 /* Loopback mode */ +#define AC97_GP_MS 0x0100 /* Mic Select 0=Mic1, 1=Mic2 */ +#define AC97_GP_MIX 0x0200 /* Mono output select 0=Mix, 1=Mic */ +#define AC97_GP_RLBK 0x0400 /* Remote Loopback - Modem line codec */ +#define AC97_GP_LLBK 0x0800 /* Local Loopback - Modem Line codec */ +#define AC97_GP_LD 0x1000 /* Loudness 1=on */ +#define AC97_GP_3D 0x2000 /* 3D Enhancement 1=on */ +#define AC97_GP_ST 0x4000 /* Stereo Enhancement 1=on */ +#define AC97_GP_POP 0x8000 /* Pcm Out Path, 0=pre 3D, 1=post 3D */ + +/* extended audio status and control bit defines */ +#define AC97_EA_VRA 0x0001 /* Variable bit rate enable bit */ +#define AC97_EA_DRA 0x0002 /* Double-rate audio enable bit */ +#define AC97_EA_SPDIF 0x0004 /* S/PDIF Enable bit */ +#define AC97_EA_VRM 0x0008 /* Variable bit rate for MIC enable bit */ +#define AC97_EA_CDAC 0x0040 /* PCM Center DAC is ready (Read only) */ +#define AC97_EA_SDAC 0x0040 /* PCM Surround DACs are ready (Read only) */ +#define AC97_EA_LDAC 0x0080 /* PCM LFE DAC is ready (Read only) */ +#define AC97_EA_MDAC 0x0100 /* MIC ADC is ready (Read only) */ +#define AC97_EA_SPCV 0x0400 /* S/PDIF configuration valid (Read only) */ +#define AC97_EA_PRI 0x0800 /* Turns the PCM Center DAC off */ +#define AC97_EA_PRJ 0x1000 /* Turns the PCM Surround DACs off */ +#define AC97_EA_PRK 0x2000 /* Turns the PCM LFE DAC off */ +#define AC97_EA_PRL 0x4000 /* Turns the MIC ADC off */ +#define AC97_EA_SLOT_MASK 0xffcf /* Mask for slot assignment bits */ +#define AC97_EA_SPSA_3_4 0x0000 /* Slot assigned to 3 & 4 */ +#define AC97_EA_SPSA_7_8 0x0010 /* Slot assigned to 7 & 8 */ +#define AC97_EA_SPSA_6_9 0x0020 /* Slot assigned to 6 & 9 */ +#define AC97_EA_SPSA_10_11 0x0030 /* Slot assigned to 10 & 11 */ + +/* S/PDIF control bit defines */ +#define AC97_SC_PRO 0x0001 /* Professional status */ +#define AC97_SC_NAUDIO 0x0002 /* Non audio stream */ +#define AC97_SC_COPY 0x0004 /* Copyright status */ +#define AC97_SC_PRE 0x0008 /* Preemphasis status */ +#define AC97_SC_CC_MASK 0x07f0 /* Category Code mask */ +#define AC97_SC_L 0x0800 /* Generation Level status */ +#define AC97_SC_SPSR_MASK 0xcfff /* S/PDIF Sample Rate bits */ +#define AC97_SC_SPSR_44K 0x0000 /* Use 44.1kHz Sample rate */ +#define AC97_SC_SPSR_48K 0x2000 /* Use 48kHz Sample rate */ +#define AC97_SC_SPSR_32K 0x3000 /* Use 32kHz Sample rate */ +#define AC97_SC_DRS 0x4000 /* Double Rate S/PDIF */ +#define AC97_SC_V 0x8000 /* Validity status */ + +/* powerdown control and status bit defines */ + +/* status */ +#define AC97_PWR_MDM 0x0010 /* Modem section ready */ +#define AC97_PWR_REF 0x0008 /* Vref nominal */ +#define AC97_PWR_ANL 0x0004 /* Analog section ready */ +#define AC97_PWR_DAC 0x0002 /* DAC section ready */ +#define AC97_PWR_ADC 0x0001 /* ADC section ready */ + +/* control */ +#define AC97_PWR_PR0 0x0100 /* ADC and Mux powerdown */ +#define AC97_PWR_PR1 0x0200 /* DAC powerdown */ +#define AC97_PWR_PR2 0x0400 /* Output mixer powerdown (Vref on) */ +#define AC97_PWR_PR3 0x0800 /* Output mixer powerdown (Vref off) */ +#define AC97_PWR_PR4 0x1000 /* AC-link powerdown */ +#define AC97_PWR_PR5 0x2000 /* Internal Clk disable */ +#define AC97_PWR_PR6 0x4000 /* HP amp powerdown */ +#define AC97_PWR_PR7 0x8000 /* Modem off - if supported */ + +/* useful power states */ +#define AC97_PWR_D0 0x0000 /* everything on */ +#define AC97_PWR_D1 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR4 +#define AC97_PWR_D2 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4 +#define AC97_PWR_D3 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4 +#define AC97_PWR_ANLOFF AC97_PWR_PR2|AC97_PWR_PR3 /* analog section off */ + +/* Total number of defined registers. */ +#define AC97_REG_CNT 64 + + +/* OSS interface to the ac97s.. */ +#define AC97_STEREO_MASK (SOUND_MASK_VOLUME|SOUND_MASK_PCM|\ + SOUND_MASK_LINE|SOUND_MASK_CD|\ + SOUND_MASK_ALTPCM|SOUND_MASK_IGAIN|\ + SOUND_MASK_LINE1|SOUND_MASK_VIDEO|SOUND_MASK_IMIX) + +#define AC97_SUPPORTED_MASK (AC97_STEREO_MASK | \ + SOUND_MASK_BASS|SOUND_MASK_TREBLE|\ + SOUND_MASK_SPEAKER|SOUND_MASK_MIC|\ + SOUND_MASK_PHONEIN|SOUND_MASK_PHONEOUT) + +#define AC97_RECORD_MASK (SOUND_MASK_MIC|\ + SOUND_MASK_CD|SOUND_MASK_IGAIN|SOUND_MASK_VIDEO|\ + SOUND_MASK_LINE1| SOUND_MASK_LINE|\ + SOUND_MASK_PHONEIN) + +/* original check is not good enough in case FOO is greater than + * SOUND_MIXER_NRDEVICES because the supported_mixers has exactly + * SOUND_MIXER_NRDEVICES elements. + * before matching the given mixer against the bitmask in supported_mixers we + * check if mixer number exceeds maximum allowed size which is as mentioned + * above SOUND_MIXER_NRDEVICES */ +#define supported_mixer(CODEC,FOO) ((FOO >= 0) && \ + (FOO < SOUND_MIXER_NRDEVICES) && \ + (CODEC)->supported_mixers & (1<<FOO) ) + + +#endif /* _EMU10K_AC97_H_ */ --HcAYCG3uE/tztfnV--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030421004559.GA67656>