diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2005-11-30 22:17:48 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2005-11-30 22:17:48 +0000 |
commit | bbcf5faf0d30a3b9e211253fdfe88d9c9aa5cfc4 (patch) | |
tree | 214ab5378be4cf2be92c6987905392bcee747d6c /sys/dev/pci/emuxki.c | |
parent | c2722d71c583089f1efcce5b50bdf2b3872c3b95 (diff) |
- add initial SB Audigy support
- add big-endian support
- fix a few typos
From NetBSD
- use pci_matchbyid()
Known working SB Live's tested by numerous users with no reported regressions;
though no one has stepped up to test out the Audigy support yet.
ok deraadt@
Diffstat (limited to 'sys/dev/pci/emuxki.c')
-rw-r--r-- | sys/dev/pci/emuxki.c | 476 |
1 files changed, 354 insertions, 122 deletions
diff --git a/sys/dev/pci/emuxki.c b/sys/dev/pci/emuxki.c index 605f886f440..8556c05b31d 100644 --- a/sys/dev/pci/emuxki.c +++ b/sys/dev/pci/emuxki.c @@ -1,4 +1,4 @@ -/* $OpenBSD: emuxki.c,v 1.21 2005/11/21 18:16:41 millert Exp $ */ +/* $OpenBSD: emuxki.c,v 1.22 2005/11/30 22:17:46 brad Exp $ */ /* $NetBSD: emuxki.c,v 1.1 2001/10/17 18:39:41 jdolecek Exp $ */ /*- @@ -44,7 +44,7 @@ * - inversed stereo at ac97 codec level * (XXX jdolecek - don't see the problem? maybe because auvia(4) has * it swapped too?) - * - bass disapear when you plug rear jack-in on Cambridge FPS2000 speakers + * - bass disappear when you plug rear jack-in on Cambridge FPS2000 speakers * (and presumably all speakers that support front and rear jack-in) * * TODO: @@ -52,7 +52,7 @@ * - (midi/mpu),joystick support * - Multiple voices play (problem with /dev/audio architecture) * - Multiple sources recording (Pb with audio(4)) - * - Independant modification of each channel's parameters (via mixer ?) + * - Independent modification of each channel's parameters (via mixer ?) * - DSP FX patches (to make fx like chipmunk) */ @@ -123,7 +123,7 @@ void emuxki_voice_dataloc_destroy(struct emuxki_voice *voice); void emuxki_voice_commit_parms(struct emuxki_voice *); void emuxki_voice_recsrc_release(struct emuxki_softc *sc, emuxki_recsrc_t source); int emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source); -int emuxki_recsrc_rate_to_index(int srate); +int emuxki_voice_adc_rate(struct emuxki_voice *); u_int32_t emuxki_voice_curaddr(struct emuxki_voice *); int emuxki_set_vparms(struct emuxki_voice *voice, struct audio_params *p); int emuxki_voice_set_srate(struct emuxki_voice *voice, u_int32_t srate); @@ -136,6 +136,7 @@ struct emuxki_channel *emuxki_channel_new(struct emuxki_voice *voice, u_int8_t n void emuxki_channel_delete(struct emuxki_channel *chan); void emuxki_channel_start(struct emuxki_channel *chan); void emuxki_channel_stop(struct emuxki_channel *chan); +void emuxki_channel_commit_fx(struct emuxki_channel *chan); void emuxki_channel_commit_parms(struct emuxki_channel *chan); void emuxki_channel_set_bufparms(struct emuxki_channel *chan, u_int32_t start, u_int32_t end); void emuxki_channel_set_srate(struct emuxki_channel *chan, u_int32_t srate); @@ -204,6 +205,13 @@ int emuxki_ac97_read(void *, u_int8_t, u_int16_t *); int emuxki_ac97_write(void *, u_int8_t, u_int16_t); void emuxki_ac97_reset(void *); +const struct pci_matchid emuxki_devices[] = { + { PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_SBLIVE }, + { PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_SBLIVE2 }, + { PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_AUDIGY }, + { PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_AUDIGY2 }, +}; + /* * Autoconfig goo. */ @@ -248,16 +256,12 @@ struct audio_hw_if emuxki_hw_if = { emuxki_trigger_input, }; -static const int emuxki_recsrc_adcrates[] = - { 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000, -1 }; #if 0 static const int emuxki_recsrc_intrmasks[EMU_NUMRECSRCS] = { EMU_INTE_MICBUFENABLE, EMU_INTE_ADCBUFENABLE, EMU_INTE_EFXBUFENABLE }; #endif static const u_int32_t emuxki_recsrc_bufaddrreg[EMU_NUMRECSRCS] = { EMU_MICBA, EMU_ADCBA, EMU_FXBA }; -static const u_int32_t emuxki_recsrc_idxreg[EMU_NUMRECSRCS] = - { EMU_RECIDX(EMU_MICIDX), EMU_RECIDX(EMU_ADCIDX), EMU_RECIDX(EMU_FXIDX) }; static const u_int32_t emuxki_recsrc_szreg[EMU_NUMRECSRCS] = { EMU_MICBS, EMU_ADCBS, EMU_FXBS }; static const int emuxki_recbuf_sz[] = { @@ -375,14 +379,29 @@ emuxki_scinit(struct emuxki_softc *sc) if ((err = emuxki_init(sc))) return (err); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG, - EMU_HCFG_AUDIOENABLE | - EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE); + if (sc->sc_type & EMUXKI_AUDIGY2) { + bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG, + EMU_HCFG_AUDIOENABLE | EMU_HCFG_AC3ENABLE_CDSPDIF | + EMU_HCFG_AC3ENABLE_GPSPDIF | EMU_HCFG_AUTOMUTE); + } else if (sc->sc_type & EMUXKI_AUDIGY) { + bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG, + EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE); + } else { + bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG, + EMU_HCFG_AUDIOENABLE | EMU_HCFG_JOYENABLE | + EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE); + } bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE, bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) | EMU_INTE_VOLINCRENABLE | EMU_INTE_VOLDECRENABLE | EMU_INTE_MUTEENABLE); + if (sc->sc_type & EMUXKI_AUDIGY2) { + bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG, + EMU_A_IOCFG_GPOUT0 | + bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG)); + } + /* No multiple voice support for now */ sc->pvoice = sc->rvoice = NULL; @@ -404,14 +423,8 @@ emuxki_ac97_init(struct emuxki_softc *sc) int emuxki_match(struct device *parent, void *match, void *aux) { - struct pci_attach_args *pa = aux; - - if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CREATIVELABS && - (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_SBLIVE || - PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_SBLIVE2)) - return (1); - - return (0); + return (pci_matchbyid((struct pci_attach_args *)aux, emuxki_devices, + sizeof(emuxki_devices)/sizeof(emuxki_devices[0]))); } void @@ -450,10 +463,15 @@ emuxki_attach(struct device *parent, struct device *self, void *aux) } printf(": %s\n", intrstr); - /* XXX it's unknown wheather APS is made from Audigy as well */ + /* XXX it's unknown whether APS is made from Audigy as well */ if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_AUDIGY) { sc->sc_type = EMUXKI_AUDIGY; - strlcpy(sc->sc_audv.name, "Audigy", sizeof sc->sc_audv.name); + if (PCI_REVISION(pa->pa_class) == 0x04) { + sc->sc_type |= EMUXKI_AUDIGY2; + strlcpy(sc->sc_audv.name, "Audigy2", sizeof sc->sc_audv.name); + } else { + strlcpy(sc->sc_audv.name, "Audigy", sizeof sc->sc_audv.name); + } } else if (pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG) == EMU_SUBSYS_APS) { sc->sc_type = EMUXKI_APS; @@ -569,7 +587,9 @@ emuxki_read(struct emuxki_softc *sc, u_int16_t chano, u_int32_t reg) u_int8_t size, offset = 0; int s; - ptr = ((((u_int32_t) reg) << 16) & EMU_PTR_ADDR_MASK) | + ptr = ((((u_int32_t) reg) << 16) & + (sc->sc_type & EMUXKI_AUDIGY ? + EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) | (chano & EMU_PTR_CHNO_MASK); if (reg & 0xff000000) { size = (reg >> 24) & 0x3f; @@ -594,7 +614,9 @@ emuxki_write(struct emuxki_softc *sc, u_int16_t chano, u_int8_t size, offset; int s; - ptr = ((((u_int32_t) reg) << 16) & EMU_PTR_ADDR_MASK) | + ptr = ((((u_int32_t) reg) << 16) & + (sc->sc_type & EMUXKI_AUDIGY ? + EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) | (chano & EMU_PTR_CHNO_MASK); /* BE CAREFUL WITH THAT AXE, EUGENE */ @@ -620,20 +642,33 @@ emuxki_write(struct emuxki_softc *sc, u_int16_t chano, void emuxki_write_micro(struct emuxki_softc *sc, u_int32_t pc, u_int32_t data) { - emuxki_write(sc, 0, EMU_MICROCODEBASE + pc, data); + emuxki_write(sc, 0, + (sc->sc_type & EMUXKI_AUDIGY ? + EMU_A_MICROCODEBASE : EMU_MICROCODEBASE) + pc, + data); } void emuxki_dsp_addop(struct emuxki_softc *sc, u_int16_t *pc, u_int8_t op, u_int16_t r, u_int16_t a, u_int16_t x, u_int16_t y) { - emuxki_write_micro(sc, *pc << 1, - ((x << 10) & EMU_DSP_LOWORD_OPX_MASK) | - (y & EMU_DSP_LOWORD_OPY_MASK)); - emuxki_write_micro(sc, (*pc << 1) + 1, - ((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) | - ((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) | - (a & EMU_DSP_HIWORD_OPA_MASK)); + if (sc->sc_type & EMUXKI_AUDIGY) { + emuxki_write_micro(sc, *pc << 1, + ((x << 12) & EMU_A_DSP_LOWORD_OPX_MASK) | + (y & EMU_A_DSP_LOWORD_OPY_MASK)); + emuxki_write_micro(sc, (*pc << 1) + 1, + ((op << 24) & EMU_A_DSP_HIWORD_OPCODE_MASK) | + ((r << 12) & EMU_A_DSP_HIWORD_RESULT_MASK) | + (a & EMU_A_DSP_HIWORD_OPA_MASK)); + } else { + emuxki_write_micro(sc, *pc << 1, + ((x << 10) & EMU_DSP_LOWORD_OPX_MASK) | + (y & EMU_DSP_LOWORD_OPY_MASK)); + emuxki_write_micro(sc, (*pc << 1) + 1, + ((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) | + ((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) | + (a & EMU_DSP_HIWORD_OPA_MASK)); + } (*pc)++; } @@ -652,43 +687,86 @@ emuxki_initfx(struct emuxki_softc *sc) emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0); } pc = 0; - /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */ - emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, - EMU_DSP_OUTL(EMU_DSP_OUT_AC97), - EMU_DSP_CST(0), - EMU_DSP_FX(0), EMU_DSP_CST(4)); - emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, - EMU_DSP_OUTR(EMU_DSP_OUT_AC97), - EMU_DSP_CST(0), - EMU_DSP_FX(1), EMU_DSP_CST(4)); - - /* Rear channel OUT (l/r) = FX[2/3] * 4 */ + + if (sc->sc_type & EMUXKI_AUDIGY) { + /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */ + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, + EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT), + EMU_A_DSP_CST(0), + EMU_DSP_FX(0), EMU_A_DSP_CST(4)); + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, + EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT), + EMU_A_DSP_CST(0), + EMU_DSP_FX(1), EMU_A_DSP_CST(4)); + + /* Rear channel OUT (l/r) = FX[2/3] * 4 */ +#if 0 + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, + EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_REAR), + EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT), + EMU_DSP_FX(0), EMU_A_DSP_CST(4)); + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, + EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_REAR), + EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT), + EMU_DSP_FX(1), EMU_A_DSP_CST(4)); +#endif + /* ADC recording (l/r) = AC97 In (l/r) */ + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, + EMU_A_DSP_OUTL(EMU_A_DSP_OUT_ADC), + EMU_A_DSP_INL(EMU_DSP_IN_AC97), + EMU_A_DSP_CST(0), EMU_A_DSP_CST(0)); + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, + EMU_A_DSP_OUTR(EMU_A_DSP_OUT_ADC), + EMU_A_DSP_INR(EMU_DSP_IN_AC97), + EMU_A_DSP_CST(0), EMU_A_DSP_CST(0)); + + /* zero out the rest of the microcode */ + while (pc < 512) + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, + EMU_A_DSP_CST(0), EMU_A_DSP_CST(0), + EMU_A_DSP_CST(0), EMU_A_DSP_CST(0)); + + emuxki_write(sc, 0, EMU_A_DBG, 0); /* Is it really necessary ? */ + } else { + /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */ + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, + EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT), + EMU_DSP_CST(0), + EMU_DSP_FX(0), EMU_DSP_CST(4)); + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, + EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT), + EMU_DSP_CST(0), + EMU_DSP_FX(1), EMU_DSP_CST(4)); + + /* Rear channel OUT (l/r) = FX[2/3] * 4 */ #if 0 - emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, - EMU_DSP_OUTL(EMU_DSP_OUT_RCHAN), - EMU_DSP_OUTL(EMU_DSP_OUT_AC97), - EMU_DSP_FX(0), EMU_DSP_CST(4)); - emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, - EMU_DSP_OUTR(EMU_DSP_OUT_RCHAN), - EMU_DSP_OUTR(EMU_DSP_OUT_AC97), - EMU_DSP_FX(1), EMU_DSP_CST(4)); + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, + EMU_DSP_OUTL(EMU_DSP_OUT_AD_REAR), + EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT), + EMU_DSP_FX(0), EMU_DSP_CST(4)); + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, + EMU_DSP_OUTR(EMU_DSP_OUT_AD_REAR), + EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT), + EMU_DSP_FX(1), EMU_DSP_CST(4)); #endif - /* ADC recording (l/r) = AC97 In (l/r) */ - emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, - EMU_DSP_OUTL(EMU_DSP_OUT_ADC), - EMU_DSP_INL(EMU_DSP_IN_AC97), - EMU_DSP_CST(0), EMU_DSP_CST(0)); - emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, - EMU_DSP_OUTR(EMU_DSP_OUT_ADC), - EMU_DSP_INR(EMU_DSP_IN_AC97), - EMU_DSP_CST(0), EMU_DSP_CST(0)); - /* zero out the rest of the microcode */ - while (pc < 512) + /* ADC recording (l/r) = AC97 In (l/r) */ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, - EMU_DSP_CST(0), EMU_DSP_CST(0), + EMU_DSP_OUTL(EMU_DSP_OUT_ADC), + EMU_DSP_INL(EMU_DSP_IN_AC97), EMU_DSP_CST(0), EMU_DSP_CST(0)); + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, + EMU_DSP_OUTR(EMU_DSP_OUT_ADC), + EMU_DSP_INR(EMU_DSP_IN_AC97), + EMU_DSP_CST(0), EMU_DSP_CST(0)); + + /* zero out the rest of the microcode */ + while (pc < 512) + emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, + EMU_DSP_CST(0), EMU_DSP_CST(0), + EMU_DSP_CST(0), EMU_DSP_CST(0)); - emuxki_write(sc, 0, EMU_DBG, 0); /* Is it really necessary ? */ + emuxki_write(sc, 0, EMU_DBG, 0); /* Is it really necessary ? */ + } } int @@ -712,6 +790,11 @@ emuxki_init(struct emuxki_softc *sc) emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE); emuxki_write(sc, 0, EMU_ADCBA, 0); + if(sc->sc_type & EMUXKI_AUDIGY) { + emuxki_write(sc, 0, EMU_SPBYPASS, EMU_SPBYPASS_24_BITS); + emuxki_write(sc, 0, EMU_AC97SLOT, EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE); + } + /* Initialize all channels to stopped and no effects */ for (i = 0; i < EMU_NUMCHAN; i++) { emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0); @@ -754,6 +837,18 @@ emuxki_init(struct emuxki_softc *sc) emuxki_write(sc, 0, EMU_SPCS1, spcs); emuxki_write(sc, 0, EMU_SPCS2, spcs); + if(sc->sc_type & EMUXKI_AUDIGY2) { + emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE, EMU_A2_SPDIF_UNKNOWN); + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_PTR, EMU_A2_SRCSEL); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_DATA, + EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI); + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_PTR, EMU_A2_SRCMULTI); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_DATA, EMU_A2_SRCMULTI_ENABLE_INPUT); + } + + /* Let's play with sound processor */ emuxki_initfx(sc); @@ -783,7 +878,7 @@ emuxki_init(struct emuxki_softc *sc) silentpage = DMAADDR(sc->silentpage) << 1; ptb = KERNADDR(sc->ptb); for (i = 0; i < EMU_MAXPTE; i++) - ptb[i] = silentpage | i; + ptb[i] = htole32(silentpage | i); /* Write PTB address and set TCB to none */ emuxki_write(sc, 0, EMU_PTB, DMAADDR(sc->ptb)); @@ -844,7 +939,12 @@ emuxki_shutdown(struct emuxki_softc *sc) emuxki_write(sc, 0, EMU_MICBA, 0); emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE); emuxki_write(sc, 0, EMU_FXBA, 0); - emuxki_write(sc, 0, EMU_FXWC, 0); + if(sc->sc_type & EMUXKI_AUDIGY) { + emuxki_write(sc, 0, EMU_A_FXWC1, 0); + emuxki_write(sc, 0, EMU_A_FXWC2, 0); + } else { + emuxki_write(sc, 0, EMU_FXWC, 0); + } emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE); emuxki_write(sc, 0, EMU_ADCBA, 0); @@ -903,11 +1003,12 @@ emuxki_pmem_alloc(struct emuxki_softc *sc, size_t size, int type, int flags) numblocks++; for (i = 0; i < EMU_MAXPTE; i++) - if ((ptb[i] & EMU_CHAN_MAP_PTE_MASK) == silentpage) { + if ((letoh32(ptb[i]) & EMU_CHAN_MAP_PTE_MASK) == silentpage) { /* We look for a free PTE */ s = splaudio(); for (j = 0; j < numblocks; j++) - if ((ptb[i + j] & EMU_CHAN_MAP_PTE_MASK) + if ((letoh32(ptb[i + j]) + & EMU_CHAN_MAP_PTE_MASK) != silentpage) break; if (j == numblocks) { @@ -918,9 +1019,8 @@ emuxki_pmem_alloc(struct emuxki_softc *sc, size_t size, int type, int flags) } for (j = 0; j < numblocks; j++) ptb[i + j] = - (((DMAADDR(mem->dmamem) + - j * EMU_PTESIZE)) << 1) - | (i + j); + htole32((((DMAADDR(mem->dmamem) + + j * EMU_PTESIZE)) << 1) | (i + j)); LIST_INSERT_HEAD(&(sc->mem), mem, next); splx(s); return (KERNADDR(mem->dmamem)); @@ -961,11 +1061,22 @@ void emuxki_chanparms_set_defaults(struct emuxki_channel *chan) { chan->fxsend.a.level = chan->fxsend.b.level = - chan->fxsend.c.level = chan->fxsend.d.level = 0xc0; /* not max */ + chan->fxsend.c.level = chan->fxsend.d.level = + /* for audigy */ + chan->fxsend.e.level = chan->fxsend.f.level = + chan->fxsend.g.level = chan->fxsend.h.level = + chan->voice->sc->sc_type & EMUXKI_AUDIGY ? + 0xc0 : 0xff; /* not max */ + chan->fxsend.a.dest = 0x0; chan->fxsend.b.dest = 0x1; chan->fxsend.c.dest = 0x2; chan->fxsend.d.dest = 0x3; + /* for audigy */ + chan->fxsend.e.dest = 0x4; + chan->fxsend.f.dest = 0x5; + chan->fxsend.g.dest = 0x6; + chan->fxsend.h.dest = 0x7; chan->pitch.initial = 0x0000; /* shouldn't it be 0xE000 ? */ chan->pitch.current = 0x0000; /* should it be 0x0400 */ @@ -1046,6 +1157,16 @@ emuxki_channel_set_fxsend(struct emuxki_channel *chan, chan->fxsend.b.dest = fxsend->b.dest; chan->fxsend.c.dest = fxsend->c.dest; chan->fxsend.d.dest = fxsend->d.dest; + + /* for audigy */ + chan->fxsend.e.level = fxsend->e.level; + chan->fxsend.f.level = fxsend->f.level; + chan->fxsend.g.level = fxsend->g.level; + chan->fxsend.h.level = fxsend->h.level; + chan->fxsend.e.dest = fxsend->e.dest; + chan->fxsend.f.dest = fxsend->f.dest; + chan->fxsend.g.dest = fxsend->g.dest; + chan->fxsend.h.dest = fxsend->h.dest; } void @@ -1070,6 +1191,44 @@ emuxki_channel_set_bufparms(struct emuxki_channel *chan, } void +emuxki_channel_commit_fx(struct emuxki_channel *chan) +{ + struct emuxki_softc *sc = chan->voice->sc; + u_int8_t chano = chan->num; + + if(sc->sc_type & EMUXKI_AUDIGY) { + emuxki_write(sc, chano, EMU_A_CHAN_FXRT1, + (chan->fxsend.d.dest << 24) | + (chan->fxsend.c.dest << 16) | + (chan->fxsend.b.dest << 8) | + (chan->fxsend.a.dest)); + emuxki_write(sc, chano, EMU_A_CHAN_FXRT2, + (chan->fxsend.h.dest << 24) | + (chan->fxsend.g.dest << 16) | + (chan->fxsend.f.dest << 8) | + (chan->fxsend.e.dest)); + emuxki_write(sc, chano, EMU_A_CHAN_SENDAMOUNTS, + (chan->fxsend.e.level << 24) | + (chan->fxsend.f.level << 16) | + (chan->fxsend.g.level << 8) | + (chan->fxsend.h.level)); + } else { + emuxki_write(sc, chano, EMU_CHAN_FXRT, + (chan->fxsend.d.dest << 28) | + (chan->fxsend.c.dest << 24) | + (chan->fxsend.b.dest << 20) | + (chan->fxsend.a.dest << 16)); + } + + emuxki_write(sc, chano, 0x10000000 | EMU_CHAN_PTRX, + (chan->fxsend.a.level << 8) | chan->fxsend.b.level); + emuxki_write(sc, chano, EMU_CHAN_DSL, + (chan->fxsend.d.level << 24) | chan->loop.end); + emuxki_write(sc, chano, EMU_CHAN_PSST, + (chan->fxsend.c.level << 24) | chan->loop.start); +} + +void emuxki_channel_commit_parms(struct emuxki_channel *chan) { struct emuxki_voice *voice = chan->voice; @@ -1084,15 +1243,9 @@ emuxki_channel_commit_parms(struct emuxki_channel *chan) s = splaudio(); emuxki_write(sc, chano, EMU_CHAN_CPF_STEREO, voice->stereo); - emuxki_write(sc, chano, EMU_CHAN_FXRT, - (chan->fxsend.d.dest << 28) | (chan->fxsend.c.dest << 24) | - (chan->fxsend.b.dest << 20) | (chan->fxsend.a.dest << 16)); - emuxki_write(sc, chano, 0x10000000 | EMU_CHAN_PTRX, - (chan->fxsend.a.level << 8) | chan->fxsend.b.level); - emuxki_write(sc, chano, EMU_CHAN_DSL, - (chan->fxsend.d.level << 24) | chan->loop.end); - emuxki_write(sc, chano, EMU_CHAN_PSST, - (chan->fxsend.c.level << 24) | chan->loop.start); + + emuxki_channel_commit_fx(chan); + emuxki_write(sc, chano, EMU_CHAN_CCCA, (chan->filter.lowpass_resonance_height << 28) | (chan->filter.interpolation_ROM << 25) | @@ -1202,7 +1355,7 @@ emuxki_channel_stop(struct emuxki_channel *chan) /* * Voices management - * emuxki_voice_dataloc : use(play or rec) independant dataloc union helpers + * emuxki_voice_dataloc : use(play or rec) independent dataloc union helpers * emuxki_voice_channel_* : play part of dataloc union helpers * emuxki_voice_recsrc_* : rec part of dataloc union helpers */ @@ -1262,7 +1415,7 @@ emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source) { if (source < 0 || source >= EMU_NUMRECSRCS) { #ifdef EMUXKI_DEBUG - printf("Tryed to reserve invalid source: %d\n", source); + printf("Tried to reserve invalid source: %d\n", source); #endif return (EINVAL); } @@ -1274,20 +1427,6 @@ emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source) return (0); } -int -emuxki_recsrc_rate_to_index(int srate) -{ - int index; - - for (index = 0; ; index++) { - if (emuxki_recsrc_adcrates[index] == srate) - return (index); - - if (emuxki_recsrc_adcrates[index] < 0) - return (-1); - } -} - /* When calling this function we assume the voice is stopped */ void emuxki_voice_recsrc_release(struct emuxki_softc *sc, emuxki_recsrc_t source) @@ -1412,13 +1551,22 @@ emuxki_voice_set_stereo(struct emuxki_voice *voice, u_int8_t stereo) fxsend.b.dest = 0x1; fxsend.c.dest = 0x2; fxsend.d.dest = 0x3; + /* for audigy */ + fxsend.e.dest = 0x4; + fxsend.f.dest = 0x5; + fxsend.g.dest = 0x6; + fxsend.h.dest = 0x7; if (voice->stereo) { fxsend.a.level = fxsend.c.level = 0xc0; fxsend.b.level = fxsend.d.level = 0x00; + fxsend.e.level = fxsend.g.level = 0xc0; + fxsend.f.level = fxsend.h.level = 0x00; emuxki_channel_set_fxsend(voice->dataloc.chan[0], &fxsend); fxsend.a.level = fxsend.c.level = 0x00; fxsend.b.level = fxsend.d.level = 0xc0; + fxsend.e.level = fxsend.g.level = 0x00; + fxsend.f.level = fxsend.h.level = 0xc0; emuxki_channel_set_fxsend(voice->dataloc.chan[1], &fxsend); } /* No else : default is good for mono */ @@ -1438,9 +1586,13 @@ emuxki_voice_set_srate(struct emuxki_voice *voice, u_int32_t srate) emuxki_channel_set_srate(voice->dataloc.chan[1], srate); } else { - if (emuxki_recsrc_rate_to_index(srate) < 0) + if ((srate < 8000) || (srate > 48000)) return (EINVAL); voice->sample_rate = srate; + if (emuxki_voice_adc_rate(voice) < 0) { + voice->sample_rate = 0; + return (EINVAL); + } } return (0); } @@ -1571,20 +1723,38 @@ emuxki_voice_commit_parms(struct emuxki_voice *voice) u_int32_t emuxki_voice_curaddr(struct emuxki_voice *voice) { + int idxreg = 0; /* XXX different semantics in these cases */ - if (voice->use & EMU_VOICE_USE_PLAY) + if (voice->use & EMU_VOICE_USE_PLAY) { /* returns number of samples (an l/r pair counts 1) */ return (emuxki_read(voice->sc, voice->dataloc.chan[0]->num, EMU_CHAN_CCCA_CURRADDR) - voice->dataloc.chan[0]->loop.start); - else + } else { /* returns number of bytes */ - return (emuxki_read(voice->sc, 0, - emuxki_recsrc_idxreg[voice->dataloc.source]) & - EMU_RECIDX_MASK); - + switch (voice->dataloc.source) { + case EMU_RECSRC_MIC: + idxreg = (voice->sc->sc_type & EMUXKI_AUDIGY) ? + EMU_A_MICIDX : EMU_MICIDX; + break; + case EMU_RECSRC_ADC: + idxreg = (voice->sc->sc_type & EMUXKI_AUDIGY) ? + EMU_A_ADCIDX : EMU_ADCIDX; + break; + case EMU_RECSRC_FX: + idxreg = EMU_FXIDX; + break; + default: +#ifdef EMUXKI_DEBUG + printf("emu: bad recording source!\n"); +#endif + break; + } + return (emuxki_read(voice->sc, 0, EMU_RECIDX(idxreg)) + & EMU_RECIDX_MASK); + } return (0); } @@ -1622,6 +1792,59 @@ emuxki_resched_timer(struct emuxki_softc *sc) splx(s); } +int +emuxki_voice_adc_rate(struct emuxki_voice *voice) +{ + switch(voice->sample_rate) { + case 48000: + return EMU_ADCCR_SAMPLERATE_48; + break; + case 44100: + return EMU_ADCCR_SAMPLERATE_44; + break; + case 32000: + return EMU_ADCCR_SAMPLERATE_32; + break; + case 24000: + return EMU_ADCCR_SAMPLERATE_24; + break; + case 22050: + return EMU_ADCCR_SAMPLERATE_22; + break; + case 16000: + return EMU_ADCCR_SAMPLERATE_16; + break; + case 12000: + if(voice->sc->sc_type & EMUXKI_AUDIGY) + return EMU_A_ADCCR_SAMPLERATE_12; + else { +#ifdef EMUXKI_DEBUG + printf("recording sample_rate not supported : %u\n", voice->sample_rate); +#endif + return (-1); + } + break; + case 11000: + if(voice->sc->sc_type & EMUXKI_AUDIGY) + return EMU_A_ADCCR_SAMPLERATE_11; + else + return EMU_ADCCR_SAMPLERATE_11; + break; + case 8000: + if(voice->sc->sc_type & EMUXKI_AUDIGY) + return EMU_A_ADCCR_SAMPLERATE_8; + else + return EMU_ADCCR_SAMPLERATE_8; + break; + default: +#ifdef EMUXKI_DEBUG + printf("recording sample_rate not supported : %u\n", voice->sample_rate); +#endif + return (-1); + } + return (-1); /* shouldn't get here */ +} + void emuxki_voice_start(struct emuxki_voice *voice, void (*inth) (void *), void *inthparam) @@ -1637,29 +1860,38 @@ emuxki_voice_start(struct emuxki_voice *voice, emuxki_channel_start(voice->dataloc.chan[1]); } else { voice->trigblk = 1; - switch ((int)voice->dataloc.source) { + switch (voice->dataloc.source) { case EMU_RECSRC_ADC: - val = EMU_ADCCR_LCHANENABLE; /* XXX need to program DSP to output L+R * XXX in monaural case? */ - if (voice->stereo) - val |= EMU_ADCCR_RCHANENABLE; - val |= emuxki_recsrc_rate_to_index(voice->sample_rate); - emuxki_write(voice->sc, 0, EMU_ADCCR, 0); - emuxki_write(voice->sc, 0, EMU_ADCCR, val); + if (voice->sc->sc_type & EMUXKI_AUDIGY) { + val = EMU_A_ADCCR_LCHANENABLE; + if (voice->stereo) + val |= EMU_A_ADCCR_RCHANENABLE; + } else { + val = EMU_ADCCR_LCHANENABLE; + if (voice->stereo) + val |= EMU_ADCCR_RCHANENABLE; + } + val |= emuxki_voice_adc_rate(voice); + emuxki_write(voice->sc, 0, EMU_ADCCR, 0); + emuxki_write(voice->sc, 0, EMU_ADCCR, val); break; case EMU_RECSRC_MIC: case EMU_RECSRC_FX: printf("unimplemented\n"); break; + case EMU_RECSRC_NOTSET: + default: + break; } #if 0 /* DMA completion interrupt is useless; use timer */ int s; s = splaudio(); - val = emu_rd(sc, INTE, 4); + val = emu_rd(sc, INTE, 4); val |= emuxki_recsrc_intrmasks[voice->dataloc.source]; - emu_wr(sc, INTE, val, 4); + emu_wr(sc, INTE, val, 4); splx(s); #endif } @@ -1677,7 +1909,7 @@ emuxki_voice_halt(struct emuxki_voice *voice) } else { switch (voice->dataloc.source) { case EMU_RECSRC_ADC: - emuxki_write(voice->sc, 0, EMU_ADCCR, 0); + emuxki_write(voice->sc, 0, EMU_ADCCR, 0); break; case EMU_RECSRC_FX: case EMU_RECSRC_MIC: @@ -1693,9 +1925,9 @@ emuxki_voice_halt(struct emuxki_voice *voice) #if 0 int s; s = splaudio(); - val = emu_rd(sc, INTE, 4); + val = emu_rd(sc, INTE, 4); val &= ~emuxki_recsrc_intrmasks[voice->dataloc.source]; - emu_wr(sc, INTE, val, 4); + emu_wr(sc, INTE, val, 4); splx(s); #endif } @@ -1881,7 +2113,7 @@ emuxki_query_encoding(void *addr, struct audio_encoding *fp) int emuxki_set_vparms(struct emuxki_voice *voice, struct audio_params *p) { - u_int8_t b16, mode; + u_int8_t b16, mode; mode = (voice->use & EMU_VOICE_USE_PLAY) ? AUMODE_PLAY : AUMODE_RECORD; @@ -1973,7 +2205,7 @@ emuxki_set_params(void *addr, int setmode, int usemode, struct audio_params *play, struct audio_params *rec) { struct emuxki_softc *sc = addr; - int mode, error; + int mode, error; struct audio_params *p; for (mode = AUMODE_RECORD; mode != -1; @@ -2068,9 +2300,9 @@ void emuxki_freem(void *addr, void *ptr, int type) { struct emuxki_softc *sc = addr; - int i, s; + int i, s; struct emuxki_mem *mem; - size_t numblocks; + size_t numblocks; u_int32_t *ptb, silentpage; ptb = KERNADDR(sc->ptb); @@ -2086,7 +2318,7 @@ emuxki_freem(void *addr, void *ptr, int type) numblocks++; for (i = 0; i < numblocks; i++) ptb[mem->ptbidx + i] = - silentpage | (mem->ptbidx + i); + htole32(silentpage | (mem->ptbidx + i)); } LIST_REMOVE(mem, next); splx(s); @@ -2175,7 +2407,7 @@ emuxki_trigger_output(void *addr, void *start, void *end, int blksize, struct emuxki_softc *sc = addr; /* No multiple voice support for now */ struct emuxki_voice *voice = sc->pvoice; - int error; + int error; if (voice == NULL) return (ENXIO); @@ -2198,7 +2430,7 @@ emuxki_trigger_input(void *addr, void *start, void *end, int blksize, struct emuxki_softc *sc = addr; /* No multiple voice support for now */ struct emuxki_voice *voice = sc->rvoice; - int error; + int error; if (voice == NULL) return (ENXIO); |