1178481Sjb/*- 2178481Sjb * Copyright (c) 2004 David O'Brien <obrien@FreeBSD.org> 3178481Sjb * Copyright (c) 2003 Orlando Bassotto <orlando.bassotto@ieo-research.it> 4178481Sjb * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 5178481Sjb * All rights reserved. 6178481Sjb * 7178481Sjb * Redistribution and use in source and binary forms, with or without 8178481Sjb * modification, are permitted provided that the following conditions 9178481Sjb * are met: 10178481Sjb * 1. Redistributions of source code must retain the above copyright 11178481Sjb * notice, this list of conditions and the following disclaimer. 12178481Sjb * 2. Redistributions in binary form must reproduce the above copyright 13178481Sjb * notice, this list of conditions and the following disclaimer in the 14178481Sjb * documentation and/or other materials provided with the distribution. 15178481Sjb * 16178481Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17178481Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18178481Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19178481Sjb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20178481Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21178481Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22210767Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23178481Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 24178481Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25178481Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26178481Sjb * SUCH DAMAGE. 27178481Sjb */ 28178481Sjb 29178481Sjb#ifdef HAVE_KERNEL_OPTION_HEADERS 30178481Sjb#include "opt_snd.h" 31178481Sjb#endif 32178481Sjb 33178481Sjb#include <dev/sound/pcm/sound.h> 34178481Sjb#include <dev/sound/pcm/ac97.h> 35178481Sjb#include <dev/sound/pci/emuxkireg.h> 36178481Sjb 37178481Sjb#include <dev/pci/pcireg.h> 38178481Sjb#include <dev/pci/pcivar.h> 39178481Sjb#include <sys/queue.h> 40178481Sjb 41178481Sjb#include <dev/sound/midi/mpu401.h> 42178481Sjb#include "mpufoi_if.h" 43178481Sjb 44178481SjbSND_DECLARE_FILE("$FreeBSD$"); 45178481Sjb 46178481Sjb/* -------------------------------------------------------------------- */ 47178481Sjb 48178481Sjb#define NUM_G 64 /* use all channels */ 49178481Sjb#define WAVEOUT_MAXBUFSIZE 32768 50249656Sed#define EMUPAGESIZE 4096 /* don't change */ 51178481Sjb#define EMUMAXPAGES (WAVEOUT_MAXBUFSIZE * NUM_G / EMUPAGESIZE) 52178481Sjb#define EMU10K1_PCI_ID 0x00021102 /* 1102 => Creative Labs Vendor ID */ 53178481Sjb#define EMU10K2_PCI_ID 0x00041102 54178481Sjb#define EMU10K3_PCI_ID 0x00081102 55253678Spfg#define EMU_DEFAULT_BUFSZ 4096 56253661Spfg#define EMU_MAX_CHANS 8 57178481Sjb#define EMU_CHANS 4 58178481Sjb 59178481Sjb#define MAXREQVOICES 8 60178481Sjb#define RESERVED 0 61178481Sjb#define NUM_MIDI 16 62178481Sjb#define NUM_FXSENDS 4 63178481Sjb 64178481Sjb#define TMEMSIZE 256*1024 65178481Sjb#define TMEMSIZEREG 4 66178481Sjb 67233407Sgonzo#define ENABLE 0xffffffff 68233407Sgonzo#define DISABLE 0x00000000 69233407Sgonzo#define ENV_ON EMU_CHAN_DCYSUSV_CHANNELENABLE_MASK 70233407Sgonzo#define ENV_OFF 0x00 /* XXX: should this be 1? */ 71233407Sgonzo 72233407Sgonzo#define EMU_A_IOCFG_GPOUT_A 0x40 73233407Sgonzo#define EMU_A_IOCFG_GPOUT_D 0x04 74233407Sgonzo#define EMU_A_IOCFG_GPOUT_AD (EMU_A_IOCFG_GPOUT_A|EMU_A_IOCFG_GPOUT_D) /* EMU_A_IOCFG_GPOUT0 */ 75233407Sgonzo 76233407Sgonzo#define EMU_HCFG_GPOUT1 0x00000800 77233407Sgonzo 78233407Sgonzo/* instruction set */ 79178481Sjb#define iACC3 0x06 80178481Sjb#define iMACINT0 0x04 81178546Sjb#define iINTERP 0x0e 82178481Sjb 83178481Sjb#define C_00000000 0x40 84178481Sjb#define C_00000001 0x41 85178481Sjb#define C_00000004 0x44 86178481Sjb#define C_40000000 0x4d 87178481Sjb/* Audigy constants */ 88178481Sjb#define A_C_00000000 0xc0 89178481Sjb#define A_C_40000000 0xcd 90178481Sjb 91178481Sjb/* GPRs */ 92178481Sjb#define FXBUS(x) (0x00 + (x)) 93178546Sjb#define EXTIN(x) (0x10 + (x)) 94178481Sjb#define EXTOUT(x) (0x20 + (x)) 95178481Sjb 96178481Sjb#define GPR(x) (EMU_FXGPREGBASE + (x)) 97178481Sjb#define A_EXTIN(x) (0x40 + (x)) 98178481Sjb#define A_FXBUS(x) (0x00 + (x)) 99178481Sjb#define A_EXTOUT(x) (0x60 + (x)) 100178481Sjb#define A_GPR(x) (EMU_A_FXGPREGBASE + (x)) 101178481Sjb 102178481Sjb/* FX buses */ 103178481Sjb#define FXBUS_PCM_LEFT 0x00 104178546Sjb#define FXBUS_PCM_RIGHT 0x01 105178481Sjb#define FXBUS_MIDI_LEFT 0x04 106178481Sjb#define FXBUS_MIDI_RIGHT 0x05 107178481Sjb#define FXBUS_MIDI_REVERB 0x0c 108178481Sjb#define FXBUS_MIDI_CHORUS 0x0d 109178481Sjb 110178481Sjb/* Inputs */ 111178481Sjb#define EXTIN_AC97_L 0x00 112178481Sjb#define EXTIN_AC97_R 0x01 113178481Sjb#define EXTIN_SPDIF_CD_L 0x02 114178481Sjb#define EXTIN_SPDIF_CD_R 0x03 115178546Sjb#define EXTIN_TOSLINK_L 0x06 116178481Sjb#define EXTIN_TOSLINK_R 0x07 117178481Sjb#define EXTIN_COAX_SPDIF_L 0x0a 118178481Sjb#define EXTIN_COAX_SPDIF_R 0x0b 119178481Sjb/* Audigy Inputs */ 120178481Sjb#define A_EXTIN_AC97_L 0x00 121178481Sjb#define A_EXTIN_AC97_R 0x01 122178481Sjb 123178546Sjb/* Outputs */ 124178481Sjb#define EXTOUT_AC97_L 0x00 125178481Sjb#define EXTOUT_AC97_R 0x01 126178481Sjb#define EXTOUT_TOSLINK_L 0x02 127178481Sjb#define EXTOUT_TOSLINK_R 0x03 128178481Sjb#define EXTOUT_AC97_CENTER 0x04 129178546Sjb#define EXTOUT_AC97_LFE 0x05 130178546Sjb#define EXTOUT_HEADPHONE_L 0x06 131178481Sjb#define EXTOUT_HEADPHONE_R 0x07 132178481Sjb#define EXTOUT_REAR_L 0x08 133178481Sjb#define EXTOUT_REAR_R 0x09 134178481Sjb#define EXTOUT_ADC_CAP_L 0x0a 135178481Sjb#define EXTOUT_ADC_CAP_R 0x0b 136178481Sjb#define EXTOUT_ACENTER 0x11 137178481Sjb#define EXTOUT_ALFE 0x12 138178481Sjb/* Audigy Outputs */ 139178481Sjb#define A_EXTOUT_FRONT_L 0x00 140178481Sjb#define A_EXTOUT_FRONT_R 0x01 141178481Sjb#define A_EXTOUT_CENTER 0x02 142178546Sjb#define A_EXTOUT_LFE 0x03 143178481Sjb#define A_EXTOUT_HEADPHONE_L 0x04 144178481Sjb#define A_EXTOUT_HEADPHONE_R 0x05 145178481Sjb#define A_EXTOUT_REAR_L 0x06 146178481Sjb#define A_EXTOUT_REAR_R 0x07 147178481Sjb#define A_EXTOUT_AFRONT_L 0x08 148178546Sjb#define A_EXTOUT_AFRONT_R 0x09 149178481Sjb#define A_EXTOUT_ACENTER 0x0a 150178546Sjb#define A_EXTOUT_ALFE 0x0b 151178546Sjb#define A_EXTOUT_AREAR_L 0x0e 152178481Sjb#define A_EXTOUT_AREAR_R 0x0f 153178481Sjb#define A_EXTOUT_AC97_L 0x10 154178481Sjb#define A_EXTOUT_AC97_R 0x11 155178481Sjb#define A_EXTOUT_ADC_CAP_L 0x16 156178481Sjb#define A_EXTOUT_ADC_CAP_R 0x17 157233407Sgonzo 158233407Sgonzostruct emu_memblk { 159233407Sgonzo SLIST_ENTRY(emu_memblk) link; 160233407Sgonzo void *buf; 161233407Sgonzo bus_addr_t buf_addr; 162178481Sjb u_int32_t pte_start, pte_size; 163178481Sjb}; 164178481Sjb 165178481Sjbstruct emu_mem { 166178481Sjb u_int8_t bmap[EMUMAXPAGES / 8]; 167178481Sjb u_int32_t *ptb_pages; 168178481Sjb void *silent_page; 169178481Sjb bus_addr_t silent_page_addr; 170178481Sjb bus_addr_t ptb_pages_addr; 171178481Sjb SLIST_HEAD(, emu_memblk) blocks; 172178481Sjb}; 173178481Sjb 174233407Sgonzostruct emu_voice { 175233407Sgonzo int vnum; 176233407Sgonzo unsigned int b16:1, stereo:1, busy:1, running:1, ismaster:1; 177233407Sgonzo int speed; 178178481Sjb int start, end, vol; 179178481Sjb int fxrt1; /* FX routing */ 180178481Sjb int fxrt2; /* FX routing (only for audigy) */ 181178481Sjb u_int32_t buf; 182178481Sjb struct emu_voice *slave; 183178481Sjb struct pcm_channel *channel; 184178481Sjb}; 185178481Sjb 186178481Sjbstruct sc_info; 187178481Sjb 188178481Sjb/* channel registers */ 189178481Sjbstruct sc_pchinfo { 190178481Sjb int spd, fmt, blksz, run; 191178481Sjb struct emu_voice *master, *slave; 192178481Sjb struct snd_dbuf *buffer; 193178481Sjb struct pcm_channel *channel; 194178481Sjb struct sc_info *parent; 195178481Sjb}; 196178481Sjb 197178481Sjbstruct sc_rchinfo { 198210767Srpaulo int spd, fmt, run, blksz, num; 199210767Srpaulo u_int32_t idxreg, basereg, sizereg, setupreg, irqmask; 200210767Srpaulo struct snd_dbuf *buffer; 201210767Srpaulo struct pcm_channel *channel; 202210767Srpaulo struct sc_info *parent; 203210767Srpaulo}; 204178481Sjb 205178481Sjb/* device private data */ 206233407Sgonzostruct sc_info { 207233407Sgonzo device_t dev; 208233407Sgonzo u_int32_t type, rev; 209233407Sgonzo u_int32_t tos_link:1, APS:1, audigy:1, audigy2:1; 210233407Sgonzo u_int32_t addrmask; /* wider if audigy */ 211233407Sgonzo 212178481Sjb bus_space_tag_t st; 213178481Sjb bus_space_handle_t sh; 214178481Sjb bus_dma_tag_t parent_dmat; 215178481Sjb 216233407Sgonzo struct resource *reg, *irq; 217233407Sgonzo void *ih; 218233407Sgonzo struct mtx *lock; 219233407Sgonzo 220233407Sgonzo unsigned int bufsz; 221178481Sjb int timer, timerinterval; 222178481Sjb int pnum, rnum; 223178481Sjb int nchans; 224178481Sjb struct emu_mem mem; 225178481Sjb struct emu_voice voice[64]; 226178481Sjb struct sc_pchinfo pch[EMU_MAX_CHANS]; 227178481Sjb struct sc_rchinfo rch[3]; 228178481Sjb struct mpu401 *mpu; 229178481Sjb mpu401_intr_t *mpu_intr; 230178481Sjb int mputx; 231178481Sjb}; 232178481Sjb 233178481Sjb/* -------------------------------------------------------------------- */ 234178481Sjb 235178481Sjb/* 236178481Sjb * prototypes 237178481Sjb */ 238178481Sjb 239178481Sjb/* stuff */ 240178481Sjbstatic int emu_init(struct sc_info *); 241178481Sjbstatic void emu_intr(void *); 242178481Sjbstatic void *emu_malloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr); 243178481Sjbstatic void *emu_memalloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr); 244178481Sjbstatic int emu_memfree(struct sc_info *sc, void *buf); 245233407Sgonzostatic int emu_memstart(struct sc_info *sc, void *buf); 246233407Sgonzo#ifdef EMUDEBUG 247233407Sgonzostatic void emu_vdump(struct sc_info *sc, struct emu_voice *v); 248233407Sgonzo#endif 249233407Sgonzo 250233407Sgonzo/* talk to the card */ 251233407Sgonzostatic u_int32_t emu_rd(struct sc_info *, int, int); 252178481Sjbstatic void emu_wr(struct sc_info *, int, u_int32_t, int); 253178481Sjb 254178481Sjb/* -------------------------------------------------------------------- */ 255178481Sjb 256178481Sjbstatic u_int32_t emu_rfmt_ac97[] = { 257233407Sgonzo SND_FORMAT(AFMT_S16_LE, 1, 0), 258233407Sgonzo SND_FORMAT(AFMT_S16_LE, 2, 0), 259233407Sgonzo 0 260233407Sgonzo}; 261233407Sgonzo 262233407Sgonzostatic u_int32_t emu_rfmt_mic[] = { 263233407Sgonzo SND_FORMAT(AFMT_U8, 1, 0), 264178481Sjb 0 265178481Sjb}; 266178481Sjb 267178481Sjbstatic u_int32_t emu_rfmt_efx[] = { 268178481Sjb SND_FORMAT(AFMT_S16_LE, 2, 0), 269178481Sjb 0 270178481Sjb}; 271178481Sjb 272178481Sjbstatic struct pcmchan_caps emu_reccaps[3] = { 273233407Sgonzo {8000, 48000, emu_rfmt_ac97, 0}, 274233407Sgonzo {8000, 8000, emu_rfmt_mic, 0}, 275233407Sgonzo {48000, 48000, emu_rfmt_efx, 0}, 276233407Sgonzo}; 277233407Sgonzo 278233407Sgonzostatic u_int32_t emu_pfmt[] = { 279178481Sjb SND_FORMAT(AFMT_U8, 1, 0), 280178481Sjb SND_FORMAT(AFMT_U8, 2, 0), 281178481Sjb SND_FORMAT(AFMT_S16_LE, 1, 0), 282178481Sjb SND_FORMAT(AFMT_S16_LE, 2, 0), 283178546Sjb 0 284178481Sjb}; 285178546Sjb 286178546Sjbstatic struct pcmchan_caps emu_playcaps = {4000, 48000, emu_pfmt, 0}; 287178481Sjb 288178481Sjbstatic int adcspeed[8] = {48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000}; 289178481Sjb/* audigy supports 12kHz. */ 290178481Sjbstatic int audigy_adcspeed[9] = { 291178481Sjb 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 292178481Sjb}; 293178481Sjb 294178481Sjb/* -------------------------------------------------------------------- */ 295178481Sjb/* Hardware */ 296178481Sjbstatic u_int32_t 297178481Sjbemu_rd(struct sc_info *sc, int regno, int size) 298178481Sjb{ 299178481Sjb switch (size) { 300178481Sjb case 1: 301178481Sjb return bus_space_read_1(sc->st, sc->sh, regno); 302178481Sjb case 2: 303178481Sjb return bus_space_read_2(sc->st, sc->sh, regno); 304178481Sjb case 4: 305178481Sjb return bus_space_read_4(sc->st, sc->sh, regno); 306178481Sjb default: 307178481Sjb return 0xffffffff; 308178481Sjb } 309178481Sjb} 310178481Sjb 311178481Sjbstatic void 312178481Sjbemu_wr(struct sc_info *sc, int regno, u_int32_t data, int size) 313178481Sjb{ 314178481Sjb switch (size) { 315178481Sjb case 1: 316178481Sjb bus_space_write_1(sc->st, sc->sh, regno, data); 317178481Sjb break; 318178481Sjb case 2: 319178481Sjb bus_space_write_2(sc->st, sc->sh, regno, data); 320178481Sjb break; 321178481Sjb case 4: 322178481Sjb bus_space_write_4(sc->st, sc->sh, regno, data); 323178481Sjb break; 324178481Sjb } 325178481Sjb} 326178481Sjb 327178481Sjbstatic u_int32_t 328178481Sjbemu_rdptr(struct sc_info *sc, int chn, int reg) 329178481Sjb{ 330178481Sjb u_int32_t ptr, val, mask, size, offset; 331178481Sjb 332178481Sjb ptr = ((reg << 16) & sc->addrmask) | (chn & EMU_PTR_CHNO_MASK); 333178481Sjb emu_wr(sc, EMU_PTR, ptr, 4); 334178481Sjb val = emu_rd(sc, EMU_DATA, 4); 335178481Sjb if (reg & 0xff000000) { 336178481Sjb size = (reg >> 24) & 0x3f; 337178481Sjb offset = (reg >> 16) & 0x1f; 338178481Sjb mask = ((1 << size) - 1) << offset; 339178481Sjb val &= mask; 340178481Sjb val >>= offset; 341178481Sjb } 342178481Sjb return val; 343178481Sjb} 344178481Sjb 345178481Sjbstatic void 346178481Sjbemu_wrptr(struct sc_info *sc, int chn, int reg, u_int32_t data) 347178481Sjb{ 348178481Sjb u_int32_t ptr, mask, size, offset; 349178481Sjb 350178481Sjb ptr = ((reg << 16) & sc->addrmask) | (chn & EMU_PTR_CHNO_MASK); 351178481Sjb emu_wr(sc, EMU_PTR, ptr, 4); 352178481Sjb if (reg & 0xff000000) { 353233407Sgonzo size = (reg >> 24) & 0x3f; 354233407Sgonzo offset = (reg >> 16) & 0x1f; 355233407Sgonzo mask = ((1 << size) - 1) << offset; 356178481Sjb data <<= offset; 357178481Sjb data &= mask; 358178481Sjb data |= emu_rd(sc, EMU_DATA, 4) & ~mask; 359178481Sjb } 360178481Sjb emu_wr(sc, EMU_DATA, data, 4); 361178481Sjb} 362178481Sjb 363178481Sjbstatic void 364178481Sjbemu_wrefx(struct sc_info *sc, unsigned int pc, unsigned int data) 365178481Sjb{ 366178481Sjb pc += sc->audigy ? EMU_A_MICROCODEBASE : EMU_MICROCODEBASE; 367178481Sjb emu_wrptr(sc, 0, pc, data); 368178481Sjb} 369178481Sjb 370178481Sjb/* -------------------------------------------------------------------- */ 371178481Sjb/* ac97 codec */ 372233407Sgonzo/* no locking needed */ 373233407Sgonzo 374233407Sgonzostatic int 375233407Sgonzoemu_rdcd(kobj_t obj, void *devinfo, int regno) 376233407Sgonzo{ 377178481Sjb struct sc_info *sc = (struct sc_info *)devinfo; 378178481Sjb 379178481Sjb emu_wr(sc, EMU_AC97ADDR, regno, 1); 380178481Sjb return emu_rd(sc, EMU_AC97DATA, 2); 381178481Sjb} 382178481Sjb 383178481Sjbstatic int 384178481Sjbemu_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) 385210767Srpaulo{ 386210767Srpaulo struct sc_info *sc = (struct sc_info *)devinfo; 387210767Srpaulo 388210767Srpaulo emu_wr(sc, EMU_AC97ADDR, regno, 1); 389210767Srpaulo emu_wr(sc, EMU_AC97DATA, data, 2); 390178481Sjb return 0; 391178481Sjb} 392178481Sjb 393178481Sjbstatic kobj_method_t emu_ac97_methods[] = { 394178481Sjb KOBJMETHOD(ac97_read, emu_rdcd), 395178481Sjb KOBJMETHOD(ac97_write, emu_wrcd), 396178481Sjb KOBJMETHOD_END 397178481Sjb}; 398178481SjbAC97_DECLARE(emu_ac97); 399178481Sjb 400178481Sjb/* -------------------------------------------------------------------- */ 401178481Sjb/* stuff */ 402178481Sjbstatic int 403178481Sjbemu_settimer(struct sc_info *sc) 404178481Sjb{ 405178481Sjb struct sc_pchinfo *pch; 406233407Sgonzo struct sc_rchinfo *rch; 407233407Sgonzo int i, tmp, rate; 408233407Sgonzo 409233407Sgonzo rate = 0; 410233407Sgonzo for (i = 0; i < sc->nchans; i++) { 411178481Sjb pch = &sc->pch[i]; 412178481Sjb if (pch->buffer) { 413178481Sjb tmp = (pch->spd * sndbuf_getalign(pch->buffer)) 414178481Sjb / pch->blksz; 415178481Sjb if (tmp > rate) 416178481Sjb rate = tmp; 417178481Sjb } 418178481Sjb } 419178481Sjb 420178481Sjb for (i = 0; i < 3; i++) { 421178481Sjb rch = &sc->rch[i]; 422178481Sjb if (rch->buffer) { 423178481Sjb tmp = (rch->spd * sndbuf_getalign(rch->buffer)) 424178481Sjb / rch->blksz; 425233407Sgonzo if (tmp > rate) 426233407Sgonzo rate = tmp; 427233407Sgonzo } 428233407Sgonzo } 429233407Sgonzo RANGE(rate, 48, 9600); 430233407Sgonzo sc->timerinterval = 48000 / rate; 431233407Sgonzo emu_wr(sc, EMU_TIMER, sc->timerinterval & 0x03ff, 2); 432233407Sgonzo 433178481Sjb return sc->timerinterval; 434178481Sjb} 435178481Sjb 436178481Sjbstatic int 437178481Sjbemu_enatimer(struct sc_info *sc, int go) 438178481Sjb{ 439178481Sjb u_int32_t x; 440178481Sjb if (go) { 441178481Sjb if (sc->timer++ == 0) { 442207578Skan x = emu_rd(sc, EMU_INTE, 4); 443207578Skan x |= EMU_INTE_INTERTIMERENB; 444207578Skan emu_wr(sc, EMU_INTE, x, 4); 445207578Skan } 446207578Skan } else { 447207578Skan sc->timer = 0; 448178481Sjb x = emu_rd(sc, EMU_INTE, 4); 449178481Sjb x &= ~EMU_INTE_INTERTIMERENB; 450178481Sjb emu_wr(sc, EMU_INTE, x, 4); 451207578Skan } 452178481Sjb return 0; 453178481Sjb} 454178481Sjb 455233407Sgonzostatic void 456233407Sgonzoemu_enastop(struct sc_info *sc, char channel, int enable) 457233407Sgonzo{ 458233407Sgonzo int reg = (channel & 0x20) ? EMU_SOLEH : EMU_SOLEL; 459233407Sgonzo channel &= 0x1f; 460233407Sgonzo reg |= 1 << 24; 461178481Sjb reg |= channel << 16; 462207578Skan emu_wrptr(sc, 0, reg, enable); 463178481Sjb} 464178481Sjb 465178481Sjbstatic int 466178481Sjbemu_recval(int speed) { 467178481Sjb int val; 468178481Sjb 469178481Sjb val = 0; 470178481Sjb while (val < 7 && speed < adcspeed[val]) 471178481Sjb val++; 472178481Sjb return val; 473178481Sjb} 474178481Sjb 475178481Sjbstatic int 476178481Sjbaudigy_recval(int speed) { 477178481Sjb int val; 478178481Sjb 479178481Sjb val = 0; 480178481Sjb while (val < 8 && speed < audigy_adcspeed[val]) 481178481Sjb val++; 482178481Sjb return val; 483178481Sjb} 484178481Sjb 485178481Sjbstatic u_int32_t 486178481Sjbemu_rate_to_pitch(u_int32_t rate) 487178481Sjb{ 488178481Sjb static u_int32_t logMagTable[128] = { 489178481Sjb 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2, 490178481Sjb 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5, 491210767Srpaulo 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081, 492210767Srpaulo 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191, 493210767Srpaulo 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, 494210767Srpaulo 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, 495280201Smarkj 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e, 496210767Srpaulo 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26, 497210767Srpaulo 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d, 498210767Srpaulo 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885, 499178481Sjb 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, 500178481Sjb 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, 501178481Sjb 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, 502178546Sjb 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3, 503178481Sjb 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83, 504233407Sgonzo 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df 505233407Sgonzo }; 506233407Sgonzo static char logSlopeTable[128] = { 507233407Sgonzo 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58, 508233407Sgonzo 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53, 509178481Sjb 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f, 510178481Sjb 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b, 511178481Sjb 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47, 512178481Sjb 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44, 513178481Sjb 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41, 514178481Sjb 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e, 515178481Sjb 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, 516178481Sjb 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 517178481Sjb 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37, 518178481Sjb 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35, 519178481Sjb 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34, 520178481Sjb 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32, 521178481Sjb 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30, 522178481Sjb 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f 523178481Sjb }; 524178481Sjb int i; 525178481Sjb 526178481Sjb if (rate == 0) 527178481Sjb return 0; /* Bail out if no leading "1" */ 528178481Sjb rate *= 11185; /* Scale 48000 to 0x20002380 */ 529178481Sjb for (i = 31; i > 0; i--) { 530178481Sjb if (rate & 0x80000000) { /* Detect leading "1" */ 531178481Sjb return (((u_int32_t) (i - 15) << 20) + 532178481Sjb logMagTable[0x7f & (rate >> 24)] + 533178481Sjb (0x7f & (rate >> 17)) * 534178481Sjb logSlopeTable[0x7f & (rate >> 24)]); 535178481Sjb } 536178481Sjb rate <<= 1; 537178481Sjb } 538178481Sjb 539178481Sjb return 0; /* Should never reach this point */ 540178481Sjb} 541178481Sjb 542178481Sjbstatic u_int32_t 543178481Sjbemu_rate_to_linearpitch(u_int32_t rate) 544178481Sjb{ 545178481Sjb rate = (rate << 8) / 375; 546178481Sjb return (rate >> 1) + (rate & 1); 547178481Sjb} 548178481Sjb 549178481Sjbstatic struct emu_voice * 550178481Sjbemu_valloc(struct sc_info *sc) 551178481Sjb{ 552178481Sjb struct emu_voice *v; 553178481Sjb int i; 554178481Sjb 555178481Sjb v = NULL; 556178481Sjb for (i = 0; i < 64 && sc->voice[i].busy; i++); 557178481Sjb if (i < 64) { 558178481Sjb v = &sc->voice[i]; 559178481Sjb v->busy = 1; 560178481Sjb } 561178481Sjb return v; 562178481Sjb} 563178481Sjb 564178481Sjbstatic int 565178481Sjbemu_vinit(struct sc_info *sc, struct emu_voice *m, struct emu_voice *s, 566178481Sjb u_int32_t sz, struct snd_dbuf *b) 567178481Sjb{ 568178481Sjb void *buf; 569178481Sjb bus_addr_t tmp_addr; 570178481Sjb 571178481Sjb buf = emu_memalloc(sc, sz, &tmp_addr); 572178546Sjb if (buf == NULL) 573178481Sjb return -1; 574178481Sjb if (b != NULL) 575178481Sjb sndbuf_setup(b, buf, sz); 576178481Sjb m->start = emu_memstart(sc, buf) * EMUPAGESIZE; 577178481Sjb m->end = m->start + sz; 578178481Sjb m->channel = NULL; 579178546Sjb m->speed = 0; 580178481Sjb m->b16 = 0; 581178481Sjb m->stereo = 0; 582178481Sjb m->running = 0; 583178481Sjb m->ismaster = 1; 584178481Sjb m->vol = 0xff; 585178481Sjb m->buf = tmp_addr; 586178481Sjb m->slave = s; 587178481Sjb if (sc->audigy) { 588178481Sjb m->fxrt1 = FXBUS_MIDI_CHORUS | FXBUS_PCM_RIGHT << 8 | 589178481Sjb FXBUS_PCM_LEFT << 16 | FXBUS_MIDI_REVERB << 24; 590178481Sjb m->fxrt2 = 0x3f3f3f3f; /* No effects on second route */ 591178481Sjb } else { 592178481Sjb m->fxrt1 = FXBUS_MIDI_CHORUS | FXBUS_PCM_RIGHT << 4 | 593178481Sjb FXBUS_PCM_LEFT << 8 | FXBUS_MIDI_REVERB << 12; 594178481Sjb m->fxrt2 = 0; 595178481Sjb } 596178481Sjb 597178481Sjb if (s != NULL) { 598178481Sjb s->start = m->start; 599178481Sjb s->end = m->end; 600178481Sjb s->channel = NULL; 601178481Sjb s->speed = 0; 602178481Sjb s->b16 = 0; 603178481Sjb s->stereo = 0; 604178481Sjb s->running = 0; 605178481Sjb s->ismaster = 0; 606178481Sjb s->vol = m->vol; 607178481Sjb s->buf = m->buf; 608178481Sjb s->fxrt1 = m->fxrt1; 609178481Sjb s->fxrt2 = m->fxrt2; 610178481Sjb s->slave = NULL; 611178481Sjb } 612178481Sjb return 0; 613178481Sjb} 614178481Sjb 615178481Sjbstatic void 616178481Sjbemu_vsetup(struct sc_pchinfo *ch) 617178481Sjb{ 618178481Sjb struct emu_voice *v = ch->master; 619178481Sjb 620178481Sjb if (ch->fmt) { 621178481Sjb v->b16 = (ch->fmt & AFMT_16BIT) ? 1 : 0; 622178481Sjb v->stereo = (AFMT_CHANNEL(ch->fmt) > 1) ? 1 : 0; 623178481Sjb if (v->slave != NULL) { 624178481Sjb v->slave->b16 = v->b16; 625178481Sjb v->slave->stereo = v->stereo; 626178481Sjb } 627178481Sjb } 628178481Sjb if (ch->spd) { 629178481Sjb v->speed = ch->spd; 630178481Sjb if (v->slave != NULL) 631178481Sjb v->slave->speed = v->speed; 632178481Sjb } 633178481Sjb} 634178481Sjb 635178481Sjbstatic void 636178481Sjbemu_vwrite(struct sc_info *sc, struct emu_voice *v) 637178481Sjb{ 638178481Sjb int s; 639178481Sjb int l, r, x, y; 640178481Sjb u_int32_t sa, ea, start, val, silent_page; 641178546Sjb 642178481Sjb s = (v->stereo ? 1 : 0) + (v->b16 ? 1 : 0); 643178481Sjb 644178481Sjb sa = v->start >> s; 645178481Sjb ea = v->end >> s; 646178481Sjb 647178481Sjb l = r = x = y = v->vol; 648178481Sjb if (v->stereo) { 649178481Sjb l = v->ismaster ? l : 0; 650178481Sjb r = v->ismaster ? 0 : r; 651178481Sjb } 652178481Sjb 653178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CPF, v->stereo ? EMU_CHAN_CPF_STEREO_MASK : 0); 654178481Sjb val = v->stereo ? 28 : 30; 655178481Sjb val *= v->b16 ? 1 : 2; 656178481Sjb start = sa + val; 657178481Sjb 658178481Sjb if (sc->audigy) { 659178481Sjb emu_wrptr(sc, v->vnum, EMU_A_CHAN_FXRT1, v->fxrt1); 660178481Sjb emu_wrptr(sc, v->vnum, EMU_A_CHAN_FXRT2, v->fxrt2); 661178481Sjb emu_wrptr(sc, v->vnum, EMU_A_CHAN_SENDAMOUNTS, 0); 662178481Sjb } 663178481Sjb else 664178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_FXRT, v->fxrt1 << 16); 665178481Sjb 666178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_PTRX, (x << 8) | r); 667178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_DSL, ea | (y << 24)); 668178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_PSST, sa | (l << 24)); 669178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CCCA, start | (v->b16 ? 0 : EMU_CHAN_CCCA_8BITSELECT)); 670178481Sjb 671178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_Z1, 0); 672178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_Z2, 0); 673178481Sjb 674178481Sjb silent_page = ((u_int32_t)(sc->mem.silent_page_addr) << 1) 675178481Sjb | EMU_CHAN_MAP_PTI_MASK; 676178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_MAPA, silent_page); 677178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_MAPB, silent_page); 678178481Sjb 679178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CVCF, EMU_CHAN_CVCF_CURRFILTER_MASK); 680178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_VTFT, EMU_CHAN_VTFT_FILTERTARGET_MASK); 681178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_ATKHLDM, 0); 682178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_DCYSUSM, EMU_CHAN_DCYSUSM_DECAYTIME_MASK); 683178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_LFOVAL1, 0x8000); 684178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_LFOVAL2, 0x8000); 685178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_FMMOD, 0); 686178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_TREMFRQ, 0); 687178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_FM2FRQ2, 0); 688178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_ENVVAL, 0x8000); 689178481Sjb 690178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_ATKHLDV, 691178481Sjb EMU_CHAN_ATKHLDV_HOLDTIME_MASK | EMU_CHAN_ATKHLDV_ATTACKTIME_MASK); 692178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_ENVVOL, 0x8000); 693178481Sjb 694178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_PEFE_FILTERAMOUNT, 0x7f); 695178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_PEFE_PITCHAMOUNT, 0); 696178481Sjb 697178481Sjb if (v->slave != NULL) 698178481Sjb emu_vwrite(sc, v->slave); 699178481Sjb} 700178481Sjb 701178481Sjbstatic void 702233407Sgonzoemu_vtrigger(struct sc_info *sc, struct emu_voice *v, int go) 703233407Sgonzo{ 704233407Sgonzo u_int32_t pitch_target, initial_pitch; 705178481Sjb u_int32_t cra, cs, ccis; 706178481Sjb u_int32_t sample, i; 707178481Sjb 708178481Sjb if (go) { 709178481Sjb cra = 64; 710178481Sjb cs = v->stereo ? 4 : 2; 711178481Sjb ccis = v->stereo ? 28 : 30; 712178481Sjb ccis *= v->b16 ? 1 : 2; 713178481Sjb sample = v->b16 ? 0x00000000 : 0x80808080; 714178481Sjb 715178481Sjb for (i = 0; i < cs; i++) 716178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CD0 + i, sample); 717178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CCR_CACHEINVALIDSIZE, 0); 718178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CCR_READADDRESS, cra); 719178546Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CCR_CACHEINVALIDSIZE, ccis); 720178481Sjb 721178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_IFATN, 0xff00); 722178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_VTFT, 0xffffffff); 723178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CVCF, 0xffffffff); 724178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_DCYSUSV, 0x00007f7f); 725178481Sjb emu_enastop(sc, v->vnum, 0); 726178481Sjb 727178481Sjb pitch_target = emu_rate_to_linearpitch(v->speed); 728178481Sjb initial_pitch = emu_rate_to_pitch(v->speed) >> 8; 729178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_PTRX_PITCHTARGET, pitch_target); 730178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CPF_PITCH, pitch_target); 731178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_IP, initial_pitch); 732178481Sjb } else { 733178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_PTRX_PITCHTARGET, 0); 734178546Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CPF_PITCH, 0); 735178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_IFATN, 0xffff); 736178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_VTFT, 0x0000ffff); 737178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_CVCF, 0x0000ffff); 738178481Sjb emu_wrptr(sc, v->vnum, EMU_CHAN_IP, 0); 739178481Sjb emu_enastop(sc, v->vnum, 1); 740178481Sjb } 741233407Sgonzo if (v->slave != NULL) 742233407Sgonzo emu_vtrigger(sc, v->slave, go); 743233407Sgonzo} 744233407Sgonzo 745233407Sgonzostatic int 746233407Sgonzoemu_vpos(struct sc_info *sc, struct emu_voice *v) 747233407Sgonzo{ 748233407Sgonzo int s, ptr; 749233407Sgonzo 750233407Sgonzo s = (v->b16 ? 1 : 0) + (v->stereo ? 1 : 0); 751233407Sgonzo ptr = (emu_rdptr(sc, v->vnum, EMU_CHAN_CCCA_CURRADDR) - (v->start >> s)) << s; 752233407Sgonzo return ptr & ~0x0000001f; 753178481Sjb} 754178481Sjb 755178481Sjb#ifdef EMUDEBUG 756178481Sjbstatic void 757178481Sjbemu_vdump(struct sc_info *sc, struct emu_voice *v) 758178481Sjb{ 759178481Sjb char *regname[] = { 760178481Sjb "cpf", "ptrx", "cvcf", "vtft", "z2", "z1", "psst", "dsl", 761178481Sjb "ccca", "ccr", "clp", "fxrt", "mapa", "mapb", NULL, NULL, 762178481Sjb "envvol", "atkhldv", "dcysusv", "lfoval1", 763178481Sjb "envval", "atkhldm", "dcysusm", "lfoval2", 764178481Sjb "ip", "ifatn", "pefe", "fmmod", "tremfrq", "fmfrq2", 765178481Sjb "tempenv" 766178481Sjb }; 767178546Sjb char *regname2[] = { 768178481Sjb "mudata1", "mustat1", "mudata2", "mustat2", 769178481Sjb "fxwc1", "fxwc2", "spdrate", NULL, NULL, 770178481Sjb NULL, NULL, NULL, "fxrt2", "sndamnt", "fxrt1", 771178481Sjb NULL, NULL 772178481Sjb }; 773178481Sjb int i, x; 774178481Sjb 775178481Sjb printf("voice number %d\n", v->vnum); 776178481Sjb for (i = 0, x = 0; i <= 0x1e; i++) { 777178481Sjb if (regname[i] == NULL) 778178481Sjb continue; 779178481Sjb printf("%s\t[%08x]", regname[i], emu_rdptr(sc, v->vnum, i)); 780178481Sjb printf("%s", (x == 2) ? "\n" : "\t"); 781178481Sjb x++; 782178481Sjb if (x > 2) 783178481Sjb x = 0; 784178481Sjb } 785178481Sjb 786178481Sjb /* Print out audigy extra registers */ 787178546Sjb if (sc->audigy) { 788178546Sjb for (i = 0; i <= 0xe; i++) { 789178481Sjb if (regname2[i] == NULL) 790178481Sjb continue; 791178481Sjb printf("%s\t[%08x]", regname2[i], 792178481Sjb emu_rdptr(sc, v->vnum, i + 0x70)); 793178481Sjb printf("%s", (x == 2)? "\n" : "\t"); 794178481Sjb x++; 795178481Sjb if (x > 2) 796178481Sjb x = 0; 797178481Sjb } 798178481Sjb } 799178481Sjb printf("\n\n"); 800178481Sjb} 801178481Sjb#endif 802178481Sjb 803178481Sjb/* channel interface */ 804178481Sjbstatic void * 805178481Sjbemupchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 806178481Sjb struct pcm_channel *c, int dir) 807178481Sjb{ 808178481Sjb struct sc_info *sc = devinfo; 809178481Sjb struct sc_pchinfo *ch; 810178481Sjb void *r; 811178481Sjb 812178481Sjb KASSERT(dir == PCMDIR_PLAY, ("emupchan_init: bad direction")); 813178481Sjb ch = &sc->pch[sc->pnum++]; 814178481Sjb ch->buffer = b; 815178481Sjb ch->parent = sc; 816178481Sjb ch->channel = c; 817178481Sjb ch->blksz = sc->bufsz / 2; 818178481Sjb ch->fmt = SND_FORMAT(AFMT_U8, 1, 0); 819178481Sjb ch->spd = 8000; 820178481Sjb snd_mtxlock(sc->lock); 821178481Sjb ch->master = emu_valloc(sc); 822178481Sjb ch->slave = emu_valloc(sc); 823178481Sjb snd_mtxunlock(sc->lock); 824178481Sjb r = (emu_vinit(sc, ch->master, ch->slave, sc->bufsz, ch->buffer)) 825178481Sjb ? NULL : ch; 826178481Sjb 827178481Sjb return r; 828178481Sjb} 829178481Sjb 830178481Sjbstatic int 831178481Sjbemupchan_free(kobj_t obj, void *data) 832178481Sjb{ 833178481Sjb struct sc_pchinfo *ch = data; 834178481Sjb struct sc_info *sc = ch->parent; 835178481Sjb int r; 836178481Sjb 837178481Sjb snd_mtxlock(sc->lock); 838178481Sjb r = emu_memfree(sc, sndbuf_getbuf(ch->buffer)); 839178481Sjb snd_mtxunlock(sc->lock); 840178481Sjb 841178481Sjb return r; 842178481Sjb} 843178481Sjb 844178481Sjbstatic int 845178481Sjbemupchan_setformat(kobj_t obj, void *data, u_int32_t format) 846178481Sjb{ 847178481Sjb struct sc_pchinfo *ch = data; 848178481Sjb 849178481Sjb ch->fmt = format; 850178481Sjb return 0; 851178481Sjb} 852178481Sjb 853178481Sjbstatic u_int32_t 854178481Sjbemupchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 855178481Sjb{ 856178481Sjb struct sc_pchinfo *ch = data; 857178546Sjb 858178481Sjb ch->spd = speed; 859178546Sjb return ch->spd; 860178481Sjb} 861178546Sjb 862178481Sjbstatic u_int32_t 863178481Sjbemupchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 864178481Sjb{ 865178481Sjb struct sc_pchinfo *ch = data; 866178481Sjb struct sc_info *sc = ch->parent; 867178481Sjb int irqrate, blksz; 868178481Sjb 869178481Sjb ch->blksz = blocksize; 870178481Sjb snd_mtxlock(sc->lock); 871178481Sjb emu_settimer(sc); 872178481Sjb irqrate = 48000 / sc->timerinterval; 873178481Sjb snd_mtxunlock(sc->lock); 874178481Sjb blksz = (ch->spd * sndbuf_getalign(ch->buffer)) / irqrate; 875178481Sjb return blocksize; 876178481Sjb} 877178481Sjb 878178481Sjbstatic int 879178481Sjbemupchan_trigger(kobj_t obj, void *data, int go) 880178481Sjb{ 881178481Sjb struct sc_pchinfo *ch = data; 882178481Sjb struct sc_info *sc = ch->parent; 883178481Sjb 884178481Sjb if (!PCMTRIG_COMMON(go)) 885178481Sjb return 0; 886178481Sjb 887178481Sjb snd_mtxlock(sc->lock); 888178481Sjb if (go == PCMTRIG_START) { 889178481Sjb emu_vsetup(ch); 890178481Sjb emu_vwrite(sc, ch->master); 891178481Sjb emu_settimer(sc); 892178481Sjb emu_enatimer(sc, 1); 893178481Sjb#ifdef EMUDEBUG 894178481Sjb printf("start [%d bit, %s, %d hz]\n", 895178481Sjb ch->master->b16 ? 16 : 8, 896178481Sjb ch->master->stereo ? "stereo" : "mono", 897178481Sjb ch->master->speed); 898178481Sjb emu_vdump(sc, ch->master); 899178481Sjb emu_vdump(sc, ch->slave); 900178481Sjb#endif 901178481Sjb } 902178481Sjb ch->run = (go == PCMTRIG_START) ? 1 : 0; 903178481Sjb emu_vtrigger(sc, ch->master, ch->run); 904178481Sjb snd_mtxunlock(sc->lock); 905178546Sjb return 0; 906178546Sjb} 907178481Sjb 908178481Sjbstatic u_int32_t 909178481Sjbemupchan_getptr(kobj_t obj, void *data) 910178481Sjb{ 911178481Sjb struct sc_pchinfo *ch = data; 912178481Sjb struct sc_info *sc = ch->parent; 913178481Sjb int r; 914178481Sjb 915178481Sjb snd_mtxlock(sc->lock); 916178481Sjb r = emu_vpos(sc, ch->master); 917178481Sjb snd_mtxunlock(sc->lock); 918178481Sjb 919178481Sjb return r; 920178481Sjb} 921178481Sjb 922178481Sjbstatic struct pcmchan_caps * 923178481Sjbemupchan_getcaps(kobj_t obj, void *data) 924178481Sjb{ 925178481Sjb return &emu_playcaps; 926178481Sjb} 927178481Sjb 928178481Sjbstatic kobj_method_t emupchan_methods[] = { 929178481Sjb KOBJMETHOD(channel_init, emupchan_init), 930178481Sjb KOBJMETHOD(channel_free, emupchan_free), 931178481Sjb KOBJMETHOD(channel_setformat, emupchan_setformat), 932178481Sjb KOBJMETHOD(channel_setspeed, emupchan_setspeed), 933178481Sjb KOBJMETHOD(channel_setblocksize, emupchan_setblocksize), 934178481Sjb KOBJMETHOD(channel_trigger, emupchan_trigger), 935178481Sjb KOBJMETHOD(channel_getptr, emupchan_getptr), 936178481Sjb KOBJMETHOD(channel_getcaps, emupchan_getcaps), 937178481Sjb KOBJMETHOD_END 938178481Sjb}; 939178481SjbCHANNEL_DECLARE(emupchan); 940178481Sjb 941178481Sjb/* channel interface */ 942178481Sjbstatic void * 943178481Sjbemurchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 944178481Sjb struct pcm_channel *c, int dir) 945178481Sjb{ 946178481Sjb struct sc_info *sc = devinfo; 947178481Sjb struct sc_rchinfo *ch; 948178481Sjb 949178481Sjb KASSERT(dir == PCMDIR_REC, ("emurchan_init: bad direction")); 950178481Sjb ch = &sc->rch[sc->rnum]; 951178481Sjb ch->buffer = b; 952178481Sjb ch->parent = sc; 953178546Sjb ch->channel = c; 954178546Sjb ch->blksz = sc->bufsz / 2; 955178481Sjb ch->fmt = SND_FORMAT(AFMT_U8, 1, 0); 956178481Sjb ch->spd = 8000; 957178481Sjb ch->num = sc->rnum; 958178481Sjb switch(sc->rnum) { 959178481Sjb case 0: 960178481Sjb ch->idxreg = sc->audigy ? EMU_A_ADCIDX : EMU_ADCIDX; 961178481Sjb ch->basereg = EMU_ADCBA; 962178481Sjb ch->sizereg = EMU_ADCBS; 963178481Sjb ch->setupreg = EMU_ADCCR; 964178481Sjb ch->irqmask = EMU_INTE_ADCBUFENABLE; 965178481Sjb break; 966178546Sjb 967178546Sjb case 1: 968178481Sjb ch->idxreg = EMU_FXIDX; 969178481Sjb ch->basereg = EMU_FXBA; 970178481Sjb ch->sizereg = EMU_FXBS; 971178481Sjb ch->setupreg = EMU_FXWC; 972178481Sjb ch->irqmask = EMU_INTE_EFXBUFENABLE; 973178481Sjb break; 974178481Sjb 975178481Sjb case 2: 976178481Sjb ch->idxreg = EMU_MICIDX; 977178481Sjb ch->basereg = EMU_MICBA; 978178481Sjb ch->sizereg = EMU_MICBS; 979178481Sjb ch->setupreg = 0; 980178481Sjb ch->irqmask = EMU_INTE_MICBUFENABLE; 981178481Sjb break; 982178481Sjb } 983178481Sjb sc->rnum++; 984178481Sjb if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0) 985178481Sjb return NULL; 986178546Sjb else { 987178546Sjb snd_mtxlock(sc->lock); 988178481Sjb emu_wrptr(sc, 0, ch->basereg, sndbuf_getbufaddr(ch->buffer)); 989178481Sjb emu_wrptr(sc, 0, ch->sizereg, 0); /* off */ 990178481Sjb snd_mtxunlock(sc->lock); 991178481Sjb return ch; 992178481Sjb } 993178481Sjb} 994178481Sjb 995178481Sjbstatic int 996178481Sjbemurchan_setformat(kobj_t obj, void *data, u_int32_t format) 997178481Sjb{ 998178481Sjb struct sc_rchinfo *ch = data; 999178481Sjb 1000178481Sjb ch->fmt = format; 1001178481Sjb return 0; 1002178481Sjb} 1003178481Sjb 1004178481Sjbstatic u_int32_t 1005178481Sjbemurchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 1006178481Sjb{ 1007178481Sjb struct sc_rchinfo *ch = data; 1008178481Sjb 1009178481Sjb if (ch->num == 0) { 1010178481Sjb if (ch->parent->audigy) 1011178481Sjb speed = audigy_adcspeed[audigy_recval(speed)]; 1012178481Sjb else 1013178481Sjb speed = adcspeed[emu_recval(speed)]; 1014178481Sjb } 1015178481Sjb if (ch->num == 1) 1016178481Sjb speed = 48000; 1017178481Sjb if (ch->num == 2) 1018178481Sjb speed = 8000; 1019178481Sjb ch->spd = speed; 1020178481Sjb return ch->spd; 1021178481Sjb} 1022178481Sjb 1023178481Sjbstatic u_int32_t 1024178481Sjbemurchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 1025178481Sjb{ 1026178481Sjb struct sc_rchinfo *ch = data; 1027178481Sjb struct sc_info *sc = ch->parent; 1028178481Sjb int irqrate, blksz; 1029178481Sjb 1030178481Sjb ch->blksz = blocksize; 1031178481Sjb snd_mtxlock(sc->lock); 1032178481Sjb emu_settimer(sc); 1033178481Sjb irqrate = 48000 / sc->timerinterval; 1034178481Sjb snd_mtxunlock(sc->lock); 1035178481Sjb blksz = (ch->spd * sndbuf_getalign(ch->buffer)) / irqrate; 1036178481Sjb return blocksize; 1037178481Sjb} 1038178481Sjb 1039178481Sjb/* semantic note: must start at beginning of buffer */ 1040178481Sjbstatic int 1041178481Sjbemurchan_trigger(kobj_t obj, void *data, int go) 1042178481Sjb{ 1043178481Sjb struct sc_rchinfo *ch = data; 1044178481Sjb struct sc_info *sc = ch->parent; 1045178481Sjb u_int32_t val, sz; 1046178481Sjb 1047178546Sjb if (!PCMTRIG_COMMON(go)) 1048178546Sjb return 0; 1049178481Sjb 1050178481Sjb switch(sc->bufsz) { 1051178481Sjb case 4096: 1052178481Sjb sz = EMU_RECBS_BUFSIZE_4096; 1053178481Sjb break; 1054178481Sjb 1055178481Sjb case 8192: 1056178481Sjb sz = EMU_RECBS_BUFSIZE_8192; 1057210767Srpaulo break; 1058178481Sjb 1059178481Sjb case 16384: 1060178481Sjb sz = EMU_RECBS_BUFSIZE_16384; 1061178481Sjb break; 1062178481Sjb 1063178481Sjb case 32768: 1064178481Sjb sz = EMU_RECBS_BUFSIZE_32768; 1065178481Sjb break; 1066178481Sjb 1067178481Sjb case 65536: 1068178481Sjb sz = EMU_RECBS_BUFSIZE_65536; 1069178481Sjb break; 1070178481Sjb 1071178481Sjb default: 1072178546Sjb sz = EMU_RECBS_BUFSIZE_4096; 1073178546Sjb } 1074178481Sjb 1075178481Sjb snd_mtxlock(sc->lock); 1076178481Sjb switch(go) { 1077178481Sjb case PCMTRIG_START: 1078178481Sjb ch->run = 1; 1079178481Sjb emu_wrptr(sc, 0, ch->sizereg, sz); 1080178481Sjb if (ch->num == 0) { 1081178481Sjb if (sc->audigy) { 1082178481Sjb val = EMU_A_ADCCR_LCHANENABLE; 1083178481Sjb if (AFMT_CHANNEL(ch->fmt) > 1) 1084178481Sjb val |= EMU_A_ADCCR_RCHANENABLE; 1085178481Sjb val |= audigy_recval(ch->spd); 1086178481Sjb } else { 1087178481Sjb val = EMU_ADCCR_LCHANENABLE; 1088178481Sjb if (AFMT_CHANNEL(ch->fmt) > 1) 1089178481Sjb val |= EMU_ADCCR_RCHANENABLE; 1090178481Sjb val |= emu_recval(ch->spd); 1091178481Sjb } 1092178481Sjb 1093178481Sjb emu_wrptr(sc, 0, ch->setupreg, 0); 1094178481Sjb emu_wrptr(sc, 0, ch->setupreg, val); 1095178481Sjb } 1096178481Sjb val = emu_rd(sc, EMU_INTE, 4); 1097178481Sjb val |= ch->irqmask; 1098178481Sjb emu_wr(sc, EMU_INTE, val, 4); 1099178546Sjb break; 1100178546Sjb 1101178481Sjb case PCMTRIG_STOP: 1102178481Sjb case PCMTRIG_ABORT: 1103178481Sjb ch->run = 0; 1104178481Sjb emu_wrptr(sc, 0, ch->sizereg, 0); 1105178481Sjb if (ch->setupreg) 1106178481Sjb emu_wrptr(sc, 0, ch->setupreg, 0); 1107178481Sjb val = emu_rd(sc, EMU_INTE, 4); 1108178481Sjb val &= ~ch->irqmask; 1109178481Sjb emu_wr(sc, EMU_INTE, val, 4); 1110178481Sjb break; 1111178481Sjb 1112178481Sjb case PCMTRIG_EMLDMAWR: 1113178481Sjb case PCMTRIG_EMLDMARD: 1114178481Sjb default: 1115178481Sjb break; 1116178481Sjb } 1117178481Sjb snd_mtxunlock(sc->lock); 1118178481Sjb 1119178481Sjb return 0; 1120178546Sjb} 1121178546Sjb 1122178481Sjbstatic u_int32_t 1123178481Sjbemurchan_getptr(kobj_t obj, void *data) 1124178481Sjb{ 1125178481Sjb struct sc_rchinfo *ch = data; 1126178481Sjb struct sc_info *sc = ch->parent; 1127178481Sjb int r; 1128178481Sjb 1129178481Sjb snd_mtxlock(sc->lock); 1130178481Sjb r = emu_rdptr(sc, 0, ch->idxreg) & 0x0000ffff; 1131178481Sjb snd_mtxunlock(sc->lock); 1132178481Sjb 1133178481Sjb return r; 1134178481Sjb} 1135178481Sjb 1136178481Sjbstatic struct pcmchan_caps * 1137178481Sjbemurchan_getcaps(kobj_t obj, void *data) 1138178546Sjb{ 1139178546Sjb struct sc_rchinfo *ch = data; 1140178481Sjb 1141178481Sjb return &emu_reccaps[ch->num]; 1142178481Sjb} 1143178481Sjb 1144178481Sjbstatic kobj_method_t emurchan_methods[] = { 1145178481Sjb KOBJMETHOD(channel_init, emurchan_init), 1146178481Sjb KOBJMETHOD(channel_setformat, emurchan_setformat), 1147178481Sjb KOBJMETHOD(channel_setspeed, emurchan_setspeed), 1148253661Spfg KOBJMETHOD(channel_setblocksize, emurchan_setblocksize), 1149253661Spfg KOBJMETHOD(channel_trigger, emurchan_trigger), 1150253661Spfg KOBJMETHOD(channel_getptr, emurchan_getptr), 1151253661Spfg KOBJMETHOD(channel_getcaps, emurchan_getcaps), 1152178481Sjb KOBJMETHOD_END 1153178481Sjb}; 1154178481SjbCHANNEL_DECLARE(emurchan); 1155178481Sjb 1156178546Sjbstatic unsigned char 1157178546Sjbemu_mread(struct mpu401 *arg, void *sc, int reg) 1158178481Sjb{ 1159178481Sjb unsigned int d; 1160178481Sjb 1161178481Sjb d = emu_rd((struct sc_info *)sc, 0x18 + reg, 1); 1162178481Sjb return d; 1163178481Sjb} 1164178481Sjb 1165178481Sjbstatic void 1166178481Sjbemu_mwrite(struct mpu401 *arg, void *sc, int reg, unsigned char b) 1167178481Sjb{ 1168253661Spfg 1169253661Spfg emu_wr((struct sc_info *)sc, 0x18 + reg, b, 1); 1170253661Spfg} 1171253661Spfg 1172178481Sjbstatic int 1173178481Sjbemu_muninit(struct mpu401 *arg, void *cookie) 1174178481Sjb{ 1175178481Sjb struct sc_info *sc = cookie; 1176178481Sjb 1177178481Sjb snd_mtxlock(sc->lock); 1178178481Sjb sc->mpu_intr = 0; 1179178481Sjb snd_mtxunlock(sc->lock); 1180178481Sjb 1181178481Sjb return 0; 1182178481Sjb} 1183178481Sjb 1184178546Sjbstatic kobj_method_t emu_mpu_methods[] = { 1185178546Sjb KOBJMETHOD(mpufoi_read, emu_mread), 1186178481Sjb KOBJMETHOD(mpufoi_write, emu_mwrite), 1187178481Sjb KOBJMETHOD(mpufoi_uninit, emu_muninit), 1188178481Sjb KOBJMETHOD_END 1189178481Sjb}; 1190178481Sjb 1191178481Sjbstatic DEFINE_CLASS(emu_mpu, emu_mpu_methods, 0); 1192178481Sjb 1193178481Sjbstatic void 1194178481Sjbemu_intr2(void *p) 1195178481Sjb{ 1196178481Sjb struct sc_info *sc = (struct sc_info *)p; 1197178481Sjb 1198178481Sjb if (sc->mpu_intr) 1199178481Sjb (sc->mpu_intr)(sc->mpu); 1200178481Sjb} 1201178481Sjb 1202178481Sjbstatic void 1203178481Sjbemu_midiattach(struct sc_info *sc) 1204178481Sjb{ 1205178481Sjb int i; 1206178481Sjb 1207178481Sjb i = emu_rd(sc, EMU_INTE, 4); 1208178481Sjb i |= EMU_INTE_MIDIRXENABLE; 1209178481Sjb emu_wr(sc, EMU_INTE, i, 4); 1210178481Sjb 1211178481Sjb sc->mpu = mpu401_init(&emu_mpu_class, sc, emu_intr2, &sc->mpu_intr); 1212178481Sjb} 1213178481Sjb/* -------------------------------------------------------------------- */ 1214178481Sjb/* The interrupt handler */ 1215178481Sjb 1216178481Sjbstatic void 1217178481Sjbemu_intr(void *data) 1218178481Sjb{ 1219178481Sjb struct sc_info *sc = data; 1220178546Sjb u_int32_t stat, ack, i, x; 1221178546Sjb 1222178481Sjb snd_mtxlock(sc->lock); 1223178481Sjb while (1) { 1224178481Sjb stat = emu_rd(sc, EMU_IPR, 4); 1225178481Sjb if (stat == 0) 1226178481Sjb break; 1227178481Sjb ack = 0; 1228178481Sjb 1229178546Sjb /* process irq */ 1230178546Sjb if (stat & EMU_IPR_INTERVALTIMER) 1231178481Sjb ack |= EMU_IPR_INTERVALTIMER; 1232178481Sjb 1233178481Sjb if (stat & (EMU_IPR_ADCBUFFULL | EMU_IPR_ADCBUFHALFFULL)) 1234178481Sjb ack |= stat & (EMU_IPR_ADCBUFFULL | EMU_IPR_ADCBUFHALFFULL); 1235178481Sjb 1236178481Sjb if (stat & (EMU_IPR_EFXBUFFULL | EMU_IPR_EFXBUFHALFFULL)) 1237178481Sjb ack |= stat & (EMU_IPR_EFXBUFFULL | EMU_IPR_EFXBUFHALFFULL); 1238178481Sjb 1239178481Sjb if (stat & (EMU_IPR_MICBUFFULL | EMU_IPR_MICBUFHALFFULL)) 1240178481Sjb ack |= stat & (EMU_IPR_MICBUFFULL | EMU_IPR_MICBUFHALFFULL); 1241178481Sjb 1242178481Sjb if (stat & EMU_PCIERROR) { 1243178481Sjb ack |= EMU_PCIERROR; 1244178481Sjb device_printf(sc->dev, "pci error\n"); 1245178481Sjb /* we still get an nmi with ecc ram even if we ack this */ 1246178481Sjb } 1247178481Sjb if (stat & EMU_IPR_RATETRCHANGE) { 1248178481Sjb ack |= EMU_IPR_RATETRCHANGE; 1249178481Sjb#ifdef EMUDEBUG 1250178481Sjb device_printf(sc->dev, 1251178481Sjb "sample rate tracker lock status change\n"); 1252178481Sjb#endif 1253178481Sjb } 1254178481Sjb 1255178481Sjb if (stat & EMU_IPR_MIDIRECVBUFE) 1256178481Sjb if (sc->mpu_intr) { 1257178481Sjb (sc->mpu_intr)(sc->mpu); 1258178481Sjb ack |= EMU_IPR_MIDIRECVBUFE | EMU_IPR_MIDITRANSBUFE; 1259178481Sjb } 1260178481Sjb if (stat & ~ack) 1261178481Sjb device_printf(sc->dev, "dodgy irq: %x (harmless)\n", 1262178481Sjb stat & ~ack); 1263178481Sjb 1264178481Sjb emu_wr(sc, EMU_IPR, stat, 4); 1265178481Sjb 1266178481Sjb if (ack) { 1267178481Sjb snd_mtxunlock(sc->lock); 1268178481Sjb 1269178481Sjb if (ack & EMU_IPR_INTERVALTIMER) { 1270178481Sjb x = 0; 1271178481Sjb for (i = 0; i < sc->nchans; i++) { 1272178481Sjb if (sc->pch[i].run) { 1273178481Sjb x = 1; 1274178481Sjb chn_intr(sc->pch[i].channel); 1275178481Sjb } 1276178481Sjb } 1277178481Sjb if (x == 0) 1278178481Sjb emu_enatimer(sc, 0); 1279178481Sjb } 1280178481Sjb 1281178481Sjb 1282178481Sjb if (ack & (EMU_IPR_ADCBUFFULL | EMU_IPR_ADCBUFHALFFULL)) { 1283178481Sjb if (sc->rch[0].channel) 1284178481Sjb chn_intr(sc->rch[0].channel); 1285178481Sjb } 1286178481Sjb if (ack & (EMU_IPR_EFXBUFFULL | EMU_IPR_EFXBUFHALFFULL)) { 1287253661Spfg if (sc->rch[1].channel) 1288253661Spfg chn_intr(sc->rch[1].channel); 1289178481Sjb } 1290178481Sjb if (ack & (EMU_IPR_MICBUFFULL | EMU_IPR_MICBUFHALFFULL)) { 1291178481Sjb if (sc->rch[2].channel) 1292178481Sjb chn_intr(sc->rch[2].channel); 1293178481Sjb } 1294178481Sjb 1295178481Sjb snd_mtxlock(sc->lock); 1296178481Sjb } 1297178481Sjb } 1298178481Sjb snd_mtxunlock(sc->lock); 1299178481Sjb} 1300178481Sjb 1301178481Sjb/* -------------------------------------------------------------------- */ 1302178481Sjb 1303178481Sjbstatic void 1304178481Sjbemu_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1305178481Sjb{ 1306178481Sjb bus_addr_t *phys = arg; 1307178481Sjb 1308178481Sjb *phys = error ? 0 : (bus_addr_t)segs->ds_addr; 1309178481Sjb 1310178481Sjb if (bootverbose) { 1311178481Sjb printf("emu: setmap (%lx, %lx), nseg=%d, error=%d\n", 1312178481Sjb (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len, 1313178481Sjb nseg, error); 1314178481Sjb } 1315178481Sjb} 1316178481Sjb 1317178481Sjbstatic void * 1318178481Sjbemu_malloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr) 1319178481Sjb{ 1320178481Sjb void *buf; 1321178481Sjb bus_dmamap_t map; 1322178481Sjb 1323178481Sjb *addr = 0; 1324178481Sjb if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map)) 1325178481Sjb return NULL; 1326178481Sjb if (bus_dmamap_load(sc->parent_dmat, map, buf, sz, emu_setmap, addr, 0) 1327178481Sjb || !*addr) 1328178481Sjb return NULL; 1329178481Sjb return buf; 1330178481Sjb} 1331178481Sjb 1332178546Sjbstatic void 1333178481Sjbemu_free(struct sc_info *sc, void *buf) 1334178481Sjb{ 1335178481Sjb bus_dmamem_free(sc->parent_dmat, buf, NULL); 1336178481Sjb} 1337178481Sjb 1338178481Sjbstatic void * 1339178481Sjbemu_memalloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr) 1340178481Sjb{ 1341178481Sjb u_int32_t blksz, start, idx, ofs, tmp, found; 1342178481Sjb struct emu_mem *mem = &sc->mem; 1343178481Sjb struct emu_memblk *blk; 1344178481Sjb void *buf; 1345178481Sjb 1346178481Sjb blksz = sz / EMUPAGESIZE; 1347178481Sjb if (sz > (blksz * EMUPAGESIZE)) 1348178481Sjb blksz++; 1349178481Sjb /* find a free block in the bitmap */ 1350178481Sjb found = 0; 1351178481Sjb start = 1; 1352178481Sjb while (!found && start + blksz < EMUMAXPAGES) { 1353178481Sjb found = 1; 1354178481Sjb for (idx = start; idx < start + blksz; idx++) 1355178481Sjb if (mem->bmap[idx >> 3] & (1 << (idx & 7))) 1356178481Sjb found = 0; 1357178481Sjb if (!found) 1358178481Sjb start++; 1359178481Sjb } 1360178481Sjb if (!found) 1361178546Sjb return NULL; 1362178546Sjb blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT); 1363178481Sjb if (blk == NULL) 1364178481Sjb return NULL; 1365178481Sjb buf = emu_malloc(sc, sz, &blk->buf_addr); 1366178481Sjb *addr = blk->buf_addr; 1367178481Sjb if (buf == NULL) { 1368178481Sjb free(blk, M_DEVBUF); 1369178481Sjb return NULL; 1370178481Sjb } 1371178481Sjb blk->buf = buf; 1372178481Sjb blk->pte_start = start; 1373178481Sjb blk->pte_size = blksz; 1374178481Sjb#ifdef EMUDEBUG 1375178481Sjb printf("buf %p, pte_start %d, pte_size %d\n", blk->buf, 1376178481Sjb blk->pte_start, blk->pte_size); 1377178481Sjb#endif 1378178481Sjb ofs = 0; 1379178481Sjb for (idx = start; idx < start + blksz; idx++) { 1380178481Sjb mem->bmap[idx >> 3] |= 1 << (idx & 7); 1381178481Sjb tmp = (uint32_t)(blk->buf_addr + ofs); 1382178481Sjb#ifdef EMUDEBUG 1383178481Sjb printf("pte[%d] -> %x phys, %x virt\n", idx, tmp, 1384178481Sjb ((u_int32_t)buf) + ofs); 1385178481Sjb#endif 1386178481Sjb mem->ptb_pages[idx] = (tmp << 1) | idx; 1387178481Sjb ofs += EMUPAGESIZE; 1388178481Sjb } 1389178481Sjb SLIST_INSERT_HEAD(&mem->blocks, blk, link); 1390178481Sjb return buf; 1391178481Sjb} 1392178481Sjb 1393178481Sjbstatic int 1394178481Sjbemu_memfree(struct sc_info *sc, void *buf) 1395178481Sjb{ 1396 u_int32_t idx, tmp; 1397 struct emu_mem *mem = &sc->mem; 1398 struct emu_memblk *blk, *i; 1399 1400 blk = NULL; 1401 SLIST_FOREACH(i, &mem->blocks, link) { 1402 if (i->buf == buf) 1403 blk = i; 1404 } 1405 if (blk == NULL) 1406 return EINVAL; 1407 SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link); 1408 emu_free(sc, buf); 1409 tmp = (u_int32_t)(sc->mem.silent_page_addr) << 1; 1410 for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) { 1411 mem->bmap[idx >> 3] &= ~(1 << (idx & 7)); 1412 mem->ptb_pages[idx] = tmp | idx; 1413 } 1414 free(blk, M_DEVBUF); 1415 return 0; 1416} 1417 1418static int 1419emu_memstart(struct sc_info *sc, void *buf) 1420{ 1421 struct emu_mem *mem = &sc->mem; 1422 struct emu_memblk *blk, *i; 1423 1424 blk = NULL; 1425 SLIST_FOREACH(i, &mem->blocks, link) { 1426 if (i->buf == buf) 1427 blk = i; 1428 } 1429 if (blk == NULL) 1430 return -EINVAL; 1431 return blk->pte_start; 1432} 1433 1434static void 1435emu_addefxop(struct sc_info *sc, int op, int z, int w, int x, int y, 1436 u_int32_t *pc) 1437{ 1438 emu_wrefx(sc, (*pc) * 2, (x << 10) | y); 1439 emu_wrefx(sc, (*pc) * 2 + 1, (op << 20) | (z << 10) | w); 1440 (*pc)++; 1441} 1442 1443static void 1444audigy_addefxop(struct sc_info *sc, int op, int z, int w, int x, int y, 1445 u_int32_t *pc) 1446{ 1447 emu_wrefx(sc, (*pc) * 2, (x << 12) | y); 1448 emu_wrefx(sc, (*pc) * 2 + 1, (op << 24) | (z << 12) | w); 1449 (*pc)++; 1450} 1451 1452static void 1453audigy_initefx(struct sc_info *sc) 1454{ 1455 int i; 1456 u_int32_t pc = 0; 1457 1458 /* skip 0, 0, -1, 0 - NOPs */ 1459 for (i = 0; i < 512; i++) 1460 audigy_addefxop(sc, 0x0f, 0x0c0, 0x0c0, 0x0cf, 0x0c0, &pc); 1461 1462 for (i = 0; i < 512; i++) 1463 emu_wrptr(sc, 0, EMU_A_FXGPREGBASE + i, 0x0); 1464 1465 pc = 16; 1466 1467 /* stop fx processor */ 1468 emu_wrptr(sc, 0, EMU_A_DBG, EMU_A_DBG_SINGLE_STEP); 1469 1470 /* Audigy 2 (EMU10K2) DSP Registers: 1471 FX Bus 1472 0x000-0x00f : 16 registers (?) 1473 Input 1474 0x040/0x041 : AC97 Codec (l/r) 1475 0x042/0x043 : ADC, S/PDIF (l/r) 1476 0x044/0x045 : Optical S/PDIF in (l/r) 1477 0x046/0x047 : ? 1478 0x048/0x049 : Line/Mic 2 (l/r) 1479 0x04a/0x04b : RCA S/PDIF (l/r) 1480 0x04c/0x04d : Aux 2 (l/r) 1481 Output 1482 0x060/0x061 : Digital Front (l/r) 1483 0x062/0x063 : Digital Center/LFE 1484 0x064/0x065 : AudigyDrive Heaphone (l/r) 1485 0x066/0x067 : Digital Rear (l/r) 1486 0x068/0x069 : Analog Front (l/r) 1487 0x06a/0x06b : Analog Center/LFE 1488 0x06c/0x06d : ? 1489 0x06e/0x06f : Analog Rear (l/r) 1490 0x070/0x071 : AC97 Output (l/r) 1491 0x072/0x073 : ? 1492 0x074/0x075 : ? 1493 0x076/0x077 : ADC Recording Buffer (l/r) 1494 Constants 1495 0x0c0 - 0x0c4 = 0 - 4 1496 0x0c5 = 0x8, 0x0c6 = 0x10, 0x0c7 = 0x20 1497 0x0c8 = 0x100, 0x0c9 = 0x10000, 0x0ca = 0x80000 1498 0x0cb = 0x10000000, 0x0cc = 0x20000000, 0x0cd = 0x40000000 1499 0x0ce = 0x80000000, 0x0cf = 0x7fffffff, 0x0d0 = 0xffffffff 1500 0x0d1 = 0xfffffffe, 0x0d2 = 0xc0000000, 0x0d3 = 0x41fbbcdc 1501 0x0d4 = 0x5a7ef9db, 0x0d5 = 0x00100000, 0x0dc = 0x00000001 (?) 1502 Temporary Values 1503 0x0d6 : Accumulator (?) 1504 0x0d7 : Condition Register 1505 0x0d8 : Noise source 1506 0x0d9 : Noise source 1507 Tank Memory Data Registers 1508 0x200 - 0x2ff 1509 Tank Memory Address Registers 1510 0x300 - 0x3ff 1511 General Purpose Registers 1512 0x400 - 0x5ff 1513 */ 1514 1515 /* AC97Output[l/r] = FXBus PCM[l/r] */ 1516 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AC97_L), A_C_00000000, 1517 A_C_00000000, A_FXBUS(FXBUS_PCM_LEFT), &pc); 1518 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AC97_R), A_C_00000000, 1519 A_C_00000000, A_FXBUS(FXBUS_PCM_RIGHT), &pc); 1520 1521 /* GPR[0/1] = RCA S/PDIF[l/r] -- Master volume */ 1522 audigy_addefxop(sc, iACC3, A_GPR(0), A_C_00000000, 1523 A_C_00000000, A_EXTIN(EXTIN_COAX_SPDIF_L), &pc); 1524 audigy_addefxop(sc, iACC3, A_GPR(1), A_C_00000000, 1525 A_C_00000000, A_EXTIN(EXTIN_COAX_SPDIF_R), &pc); 1526 1527 /* GPR[2] = GPR[0] (Left) / 2 + GPR[1] (Right) / 2 -- Central volume */ 1528 audigy_addefxop(sc, iINTERP, A_GPR(2), A_GPR(1), 1529 A_C_40000000, A_GPR(0), &pc); 1530 1531 /* Headphones[l/r] = GPR[0/1] */ 1532 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_HEADPHONE_L), 1533 A_C_00000000, A_C_00000000, A_GPR(0), &pc); 1534 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_HEADPHONE_R), 1535 A_C_00000000, A_C_00000000, A_GPR(1), &pc); 1536 1537 /* Analog Front[l/r] = GPR[0/1] */ 1538 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AFRONT_L), A_C_00000000, 1539 A_C_00000000, A_GPR(0), &pc); 1540 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AFRONT_R), A_C_00000000, 1541 A_C_00000000, A_GPR(1), &pc); 1542 1543 /* Digital Front[l/r] = GPR[0/1] */ 1544 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L), A_C_00000000, 1545 A_C_00000000, A_GPR(0), &pc); 1546 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_FRONT_R), A_C_00000000, 1547 A_C_00000000, A_GPR(1), &pc); 1548 1549 /* Center and Subwoofer configuration */ 1550 /* Analog Center = GPR[0] + GPR[2] */ 1551 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ACENTER), A_C_00000000, 1552 A_GPR(0), A_GPR(2), &pc); 1553 /* Analog Sub = GPR[1] + GPR[2] */ 1554 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ALFE), A_C_00000000, 1555 A_GPR(1), A_GPR(2), &pc); 1556 1557 /* Digital Center = GPR[0] + GPR[2] */ 1558 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_CENTER), A_C_00000000, 1559 A_GPR(0), A_GPR(2), &pc); 1560 /* Digital Sub = GPR[1] + GPR[2] */ 1561 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_LFE), A_C_00000000, 1562 A_GPR(1), A_GPR(2), &pc); 1563 1564#if 0 1565 /* Analog Rear[l/r] = (GPR[0/1] * RearVolume[l/r]) >> 31 */ 1566 /* RearVolume = GPR[0x10/0x11] (Will this ever be implemented?) */ 1567 audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_AREAR_L), A_C_00000000, 1568 A_GPR(16), A_GPR(0), &pc); 1569 audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_AREAR_R), A_C_00000000, 1570 A_GPR(17), A_GPR(1), &pc); 1571 1572 /* Digital Rear[l/r] = (GPR[0/1] * RearVolume[l/r]) >> 31 */ 1573 /* RearVolume = GPR[0x10/0x11] (Will this ever be implemented?) */ 1574 audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_REAR_L), A_C_00000000, 1575 A_GPR(16), A_GPR(0), &pc); 1576 audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_REAR_R), A_C_00000000, 1577 A_GPR(17), A_GPR(1), &pc); 1578#else 1579 /* XXX This is just a copy to the channel, since we do not have 1580 * a patch manager, it is useful for have another output enabled. 1581 */ 1582 1583 /* Analog Rear[l/r] = GPR[0/1] */ 1584 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AREAR_L), A_C_00000000, 1585 A_C_00000000, A_GPR(0), &pc); 1586 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AREAR_R), A_C_00000000, 1587 A_C_00000000, A_GPR(1), &pc); 1588 1589 /* Digital Rear[l/r] = GPR[0/1] */ 1590 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_REAR_L), A_C_00000000, 1591 A_C_00000000, A_GPR(0), &pc); 1592 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_REAR_R), A_C_00000000, 1593 A_C_00000000, A_GPR(1), &pc); 1594#endif 1595 1596 /* ADC Recording buffer[l/r] = AC97Input[l/r] */ 1597 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ADC_CAP_L), A_C_00000000, 1598 A_C_00000000, A_EXTIN(A_EXTIN_AC97_L), &pc); 1599 audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ADC_CAP_R), A_C_00000000, 1600 A_C_00000000, A_EXTIN(A_EXTIN_AC97_R), &pc); 1601 1602 /* resume normal operations */ 1603 emu_wrptr(sc, 0, EMU_A_DBG, 0); 1604} 1605 1606static void 1607emu_initefx(struct sc_info *sc) 1608{ 1609 int i; 1610 u_int32_t pc = 16; 1611 1612 /* acc3 0,0,0,0 - NOPs */ 1613 for (i = 0; i < 512; i++) { 1614 emu_wrefx(sc, i * 2, 0x10040); 1615 emu_wrefx(sc, i * 2 + 1, 0x610040); 1616 } 1617 1618 for (i = 0; i < 256; i++) 1619 emu_wrptr(sc, 0, EMU_FXGPREGBASE + i, 0); 1620 1621 /* FX-8010 DSP Registers: 1622 FX Bus 1623 0x000-0x00f : 16 registers 1624 Input 1625 0x010/0x011 : AC97 Codec (l/r) 1626 0x012/0x013 : ADC, S/PDIF (l/r) 1627 0x014/0x015 : Mic(left), Zoom (l/r) 1628 0x016/0x017 : TOS link in (l/r) 1629 0x018/0x019 : Line/Mic 1 (l/r) 1630 0x01a/0x01b : COAX S/PDIF (l/r) 1631 0x01c/0x01d : Line/Mic 2 (l/r) 1632 Output 1633 0x020/0x021 : AC97 Output (l/r) 1634 0x022/0x023 : TOS link out (l/r) 1635 0x024/0x025 : Center/LFE 1636 0x026/0x027 : LiveDrive Headphone (l/r) 1637 0x028/0x029 : Rear Channel (l/r) 1638 0x02a/0x02b : ADC Recording Buffer (l/r) 1639 0x02c : Mic Recording Buffer 1640 0x031/0x032 : Analog Center/LFE 1641 Constants 1642 0x040 - 0x044 = 0 - 4 1643 0x045 = 0x8, 0x046 = 0x10, 0x047 = 0x20 1644 0x048 = 0x100, 0x049 = 0x10000, 0x04a = 0x80000 1645 0x04b = 0x10000000, 0x04c = 0x20000000, 0x04d = 0x40000000 1646 0x04e = 0x80000000, 0x04f = 0x7fffffff, 0x050 = 0xffffffff 1647 0x051 = 0xfffffffe, 0x052 = 0xc0000000, 0x053 = 0x41fbbcdc 1648 0x054 = 0x5a7ef9db, 0x055 = 0x00100000 1649 Temporary Values 1650 0x056 : Accumulator 1651 0x057 : Condition Register 1652 0x058 : Noise source 1653 0x059 : Noise source 1654 0x05a : IRQ Register 1655 0x05b : TRAM Delay Base Address Count 1656 General Purpose Registers 1657 0x100 - 0x1ff 1658 Tank Memory Data Registers 1659 0x200 - 0x2ff 1660 Tank Memory Address Registers 1661 0x300 - 0x3ff 1662 */ 1663 1664 /* Routing - this will be configurable in later version */ 1665 1666 /* GPR[0/1] = FX * 4 + SPDIF-in */ 1667 emu_addefxop(sc, iMACINT0, GPR(0), EXTIN(EXTIN_SPDIF_CD_L), 1668 FXBUS(FXBUS_PCM_LEFT), C_00000004, &pc); 1669 emu_addefxop(sc, iMACINT0, GPR(1), EXTIN(EXTIN_SPDIF_CD_R), 1670 FXBUS(FXBUS_PCM_RIGHT), C_00000004, &pc); 1671 1672 /* GPR[0/1] += APS-input */ 1673 emu_addefxop(sc, iACC3, GPR(0), GPR(0), C_00000000, 1674 sc->APS ? EXTIN(EXTIN_TOSLINK_L) : C_00000000, &pc); 1675 emu_addefxop(sc, iACC3, GPR(1), GPR(1), C_00000000, 1676 sc->APS ? EXTIN(EXTIN_TOSLINK_R) : C_00000000, &pc); 1677 1678 /* FrontOut (AC97) = GPR[0/1] */ 1679 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_L), C_00000000, 1680 C_00000000, GPR(0), &pc); 1681 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_R), C_00000000, 1682 C_00000001, GPR(1), &pc); 1683 1684 /* GPR[2] = GPR[0] (Left) / 2 + GPR[1] (Right) / 2 -- Central volume */ 1685 emu_addefxop(sc, iINTERP, GPR(2), GPR(1), C_40000000, GPR(0), &pc); 1686 1687#if 0 1688 /* RearOut = (GPR[0/1] * RearVolume) >> 31 */ 1689 /* RearVolume = GPR[0x10/0x11] */ 1690 emu_addefxop(sc, iMAC0, EXTOUT(EXTOUT_REAR_L), C_00000000, 1691 GPR(16), GPR(0), &pc); 1692 emu_addefxop(sc, iMAC0, EXTOUT(EXTOUT_REAR_R), C_00000000, 1693 GPR(17), GPR(1), &pc); 1694#else 1695 /* XXX This is just a copy to the channel, since we do not have 1696 * a patch manager, it is useful for have another output enabled. 1697 */ 1698 1699 /* Rear[l/r] = GPR[0/1] */ 1700 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_REAR_L), C_00000000, 1701 C_00000000, GPR(0), &pc); 1702 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_REAR_R), C_00000000, 1703 C_00000000, GPR(1), &pc); 1704#endif 1705 1706 /* TOS out[l/r] = GPR[0/1] */ 1707 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_TOSLINK_L), C_00000000, 1708 C_00000000, GPR(0), &pc); 1709 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_TOSLINK_R), C_00000000, 1710 C_00000000, GPR(1), &pc); 1711 1712 /* Center and Subwoofer configuration */ 1713 /* Analog Center = GPR[0] + GPR[2] */ 1714 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ACENTER), C_00000000, 1715 GPR(0), GPR(2), &pc); 1716 /* Analog Sub = GPR[1] + GPR[2] */ 1717 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ALFE), C_00000000, 1718 GPR(1), GPR(2), &pc); 1719 /* Digital Center = GPR[0] + GPR[2] */ 1720 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_CENTER), C_00000000, 1721 GPR(0), GPR(2), &pc); 1722 /* Digital Sub = GPR[1] + GPR[2] */ 1723 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_LFE), C_00000000, 1724 GPR(1), GPR(2), &pc); 1725 1726 /* Headphones[l/r] = GPR[0/1] */ 1727 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_HEADPHONE_L), C_00000000, 1728 C_00000000, GPR(0), &pc); 1729 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_HEADPHONE_R), C_00000000, 1730 C_00000000, GPR(1), &pc); 1731 1732 /* ADC Recording buffer[l/r] = AC97Input[l/r] */ 1733 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ADC_CAP_L), C_00000000, 1734 C_00000000, EXTIN(EXTIN_AC97_L), &pc); 1735 emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ADC_CAP_R), C_00000000, 1736 C_00000000, EXTIN(EXTIN_AC97_R), &pc); 1737 1738 /* resume normal operations */ 1739 emu_wrptr(sc, 0, EMU_DBG, 0); 1740} 1741 1742/* Probe and attach the card */ 1743static int 1744emu_init(struct sc_info *sc) 1745{ 1746 u_int32_t spcs, ch, tmp, i; 1747 1748 if (sc->audigy) { 1749 /* enable additional AC97 slots */ 1750 emu_wrptr(sc, 0, EMU_AC97SLOT, EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE); 1751 } 1752 1753 /* disable audio and lock cache */ 1754 emu_wr(sc, EMU_HCFG, 1755 EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_MUTEBUTTONENABLE, 1756 4); 1757 1758 /* reset recording buffers */ 1759 emu_wrptr(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE); 1760 emu_wrptr(sc, 0, EMU_MICBA, 0); 1761 emu_wrptr(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE); 1762 emu_wrptr(sc, 0, EMU_FXBA, 0); 1763 emu_wrptr(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE); 1764 emu_wrptr(sc, 0, EMU_ADCBA, 0); 1765 1766 /* disable channel interrupt */ 1767 emu_wr(sc, EMU_INTE, 1768 EMU_INTE_INTERTIMERENB | EMU_INTE_SAMPLERATER | EMU_INTE_PCIERRENABLE, 1769 4); 1770 emu_wrptr(sc, 0, EMU_CLIEL, 0); 1771 emu_wrptr(sc, 0, EMU_CLIEH, 0); 1772 emu_wrptr(sc, 0, EMU_SOLEL, 0); 1773 emu_wrptr(sc, 0, EMU_SOLEH, 0); 1774 1775 /* wonder what these do... */ 1776 if (sc->audigy) { 1777 emu_wrptr(sc, 0, EMU_SPBYPASS, 0xf00); 1778 emu_wrptr(sc, 0, EMU_AC97SLOT, 0x3); 1779 } 1780 1781 /* init envelope engine */ 1782 for (ch = 0; ch < NUM_G; ch++) { 1783 emu_wrptr(sc, ch, EMU_CHAN_DCYSUSV, ENV_OFF); 1784 emu_wrptr(sc, ch, EMU_CHAN_IP, 0); 1785 emu_wrptr(sc, ch, EMU_CHAN_VTFT, 0xffff); 1786 emu_wrptr(sc, ch, EMU_CHAN_CVCF, 0xffff); 1787 emu_wrptr(sc, ch, EMU_CHAN_PTRX, 0); 1788 emu_wrptr(sc, ch, EMU_CHAN_CPF, 0); 1789 emu_wrptr(sc, ch, EMU_CHAN_CCR, 0); 1790 1791 emu_wrptr(sc, ch, EMU_CHAN_PSST, 0); 1792 emu_wrptr(sc, ch, EMU_CHAN_DSL, 0x10); 1793 emu_wrptr(sc, ch, EMU_CHAN_CCCA, 0); 1794 emu_wrptr(sc, ch, EMU_CHAN_Z1, 0); 1795 emu_wrptr(sc, ch, EMU_CHAN_Z2, 0); 1796 emu_wrptr(sc, ch, EMU_CHAN_FXRT, 0xd01c0000); 1797 1798 emu_wrptr(sc, ch, EMU_CHAN_ATKHLDM, 0); 1799 emu_wrptr(sc, ch, EMU_CHAN_DCYSUSM, 0); 1800 emu_wrptr(sc, ch, EMU_CHAN_IFATN, 0xffff); 1801 emu_wrptr(sc, ch, EMU_CHAN_PEFE, 0); 1802 emu_wrptr(sc, ch, EMU_CHAN_FMMOD, 0); 1803 emu_wrptr(sc, ch, EMU_CHAN_TREMFRQ, 24); /* 1 Hz */ 1804 emu_wrptr(sc, ch, EMU_CHAN_FM2FRQ2, 24); /* 1 Hz */ 1805 emu_wrptr(sc, ch, EMU_CHAN_TEMPENV, 0); 1806 1807 /*** these are last so OFF prevents writing ***/ 1808 emu_wrptr(sc, ch, EMU_CHAN_LFOVAL2, 0); 1809 emu_wrptr(sc, ch, EMU_CHAN_LFOVAL1, 0); 1810 emu_wrptr(sc, ch, EMU_CHAN_ATKHLDV, 0); 1811 emu_wrptr(sc, ch, EMU_CHAN_ENVVOL, 0); 1812 emu_wrptr(sc, ch, EMU_CHAN_ENVVAL, 0); 1813 1814 if (sc->audigy) { 1815 /* audigy cards need this to initialize correctly */ 1816 emu_wrptr(sc, ch, 0x4c, 0); 1817 emu_wrptr(sc, ch, 0x4d, 0); 1818 emu_wrptr(sc, ch, 0x4e, 0); 1819 emu_wrptr(sc, ch, 0x4f, 0); 1820 /* set default routing */ 1821 emu_wrptr(sc, ch, EMU_A_CHAN_FXRT1, 0x03020100); 1822 emu_wrptr(sc, ch, EMU_A_CHAN_FXRT2, 0x3f3f3f3f); 1823 emu_wrptr(sc, ch, EMU_A_CHAN_SENDAMOUNTS, 0); 1824 } 1825 1826 sc->voice[ch].vnum = ch; 1827 sc->voice[ch].slave = NULL; 1828 sc->voice[ch].busy = 0; 1829 sc->voice[ch].ismaster = 0; 1830 sc->voice[ch].running = 0; 1831 sc->voice[ch].b16 = 0; 1832 sc->voice[ch].stereo = 0; 1833 sc->voice[ch].speed = 0; 1834 sc->voice[ch].start = 0; 1835 sc->voice[ch].end = 0; 1836 sc->voice[ch].channel = NULL; 1837 } 1838 sc->pnum = sc->rnum = 0; 1839 1840 /* 1841 * Init to 0x02109204 : 1842 * Clock accuracy = 0 (1000ppm) 1843 * Sample Rate = 2 (48kHz) 1844 * Audio Channel = 1 (Left of 2) 1845 * Source Number = 0 (Unspecified) 1846 * Generation Status = 1 (Original for Cat Code 12) 1847 * Cat Code = 12 (Digital Signal Mixer) 1848 * Mode = 0 (Mode 0) 1849 * Emphasis = 0 (None) 1850 * CP = 1 (Copyright unasserted) 1851 * AN = 0 (Audio data) 1852 * P = 0 (Consumer) 1853 */ 1854 spcs = EMU_SPCS_CLKACCY_1000PPM | EMU_SPCS_SAMPLERATE_48 | 1855 EMU_SPCS_CHANNELNUM_LEFT | EMU_SPCS_SOURCENUM_UNSPEC | 1856 EMU_SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | 1857 EMU_SPCS_EMPHASIS_NONE | EMU_SPCS_COPYRIGHT; 1858 emu_wrptr(sc, 0, EMU_SPCS0, spcs); 1859 emu_wrptr(sc, 0, EMU_SPCS1, spcs); 1860 emu_wrptr(sc, 0, EMU_SPCS2, spcs); 1861 1862 if (!sc->audigy) 1863 emu_initefx(sc); 1864 else if (sc->audigy2) { /* Audigy 2 */ 1865 /* from ALSA initialization code: */ 1866 1867 /* Hack for Alice3 to work independent of haP16V driver */ 1868 u_int32_t tmp; 1869 1870 /* Setup SRCMulti_I2S SamplingRate */ 1871 tmp = emu_rdptr(sc, 0, EMU_A_SPDIF_SAMPLERATE) & 0xfffff1ff; 1872 emu_wrptr(sc, 0, EMU_A_SPDIF_SAMPLERATE, tmp | 0x400); 1873 1874 /* Setup SRCSel (Enable SPDIF, I2S SRCMulti) */ 1875 emu_wr(sc, 0x20, 0x00600000, 4); 1876 emu_wr(sc, 0x24, 0x00000014, 4); 1877 1878 /* Setup SRCMulti Input Audio Enable */ 1879 emu_wr(sc, 0x20, 0x006e0000, 4); 1880 emu_wr(sc, 0x24, 0xff00ff00, 4); 1881 } 1882 1883 SLIST_INIT(&sc->mem.blocks); 1884 sc->mem.ptb_pages = emu_malloc(sc, EMUMAXPAGES * sizeof(u_int32_t), 1885 &sc->mem.ptb_pages_addr); 1886 if (sc->mem.ptb_pages == NULL) 1887 return -1; 1888 1889 sc->mem.silent_page = emu_malloc(sc, EMUPAGESIZE, 1890 &sc->mem.silent_page_addr); 1891 if (sc->mem.silent_page == NULL) { 1892 emu_free(sc, sc->mem.ptb_pages); 1893 return -1; 1894 } 1895 /* Clear page with silence & setup all pointers to this page */ 1896 bzero(sc->mem.silent_page, EMUPAGESIZE); 1897 tmp = (u_int32_t)(sc->mem.silent_page_addr) << 1; 1898 for (i = 0; i < EMUMAXPAGES; i++) 1899 sc->mem.ptb_pages[i] = tmp | i; 1900 1901 emu_wrptr(sc, 0, EMU_PTB, (sc->mem.ptb_pages_addr)); 1902 emu_wrptr(sc, 0, EMU_TCB, 0); /* taken from original driver */ 1903 emu_wrptr(sc, 0, EMU_TCBS, 0); /* taken from original driver */ 1904 1905 for (ch = 0; ch < NUM_G; ch++) { 1906 emu_wrptr(sc, ch, EMU_CHAN_MAPA, tmp | EMU_CHAN_MAP_PTI_MASK); 1907 emu_wrptr(sc, ch, EMU_CHAN_MAPB, tmp | EMU_CHAN_MAP_PTI_MASK); 1908 } 1909 1910 /* emu_memalloc(sc, EMUPAGESIZE); */ 1911 /* 1912 * Hokay, now enable the AUD bit 1913 * 1914 * Audigy 1915 * Enable Audio = 0 (enabled after fx processor initialization) 1916 * Mute Disable Audio = 0 1917 * Joystick = 1 1918 * 1919 * Audigy 2 1920 * Enable Audio = 1 1921 * Mute Disable Audio = 0 1922 * Joystick = 1 1923 * GP S/PDIF AC3 Enable = 1 1924 * CD S/PDIF AC3 Enable = 1 1925 * 1926 * EMU10K1 1927 * Enable Audio = 1 1928 * Mute Disable Audio = 0 1929 * Lock Tank Memory = 1 1930 * Lock Sound Memory = 0 1931 * Auto Mute = 1 1932 */ 1933 1934 if (sc->audigy) { 1935 tmp = EMU_HCFG_AUTOMUTE | EMU_HCFG_JOYENABLE; 1936 if (sc->audigy2) /* Audigy 2 */ 1937 tmp = EMU_HCFG_AUDIOENABLE | EMU_HCFG_AC3ENABLE_CDSPDIF | 1938 EMU_HCFG_AC3ENABLE_GPSPDIF; 1939 emu_wr(sc, EMU_HCFG, tmp, 4); 1940 1941 audigy_initefx(sc); 1942 1943 /* from ALSA initialization code: */ 1944 1945 /* enable audio and disable both audio/digital outputs */ 1946 emu_wr(sc, EMU_HCFG, emu_rd(sc, EMU_HCFG, 4) | EMU_HCFG_AUDIOENABLE, 4); 1947 emu_wr(sc, EMU_A_IOCFG, emu_rd(sc, EMU_A_IOCFG, 4) & ~EMU_A_IOCFG_GPOUT_AD, 1948 4); 1949 if (sc->audigy2) { /* Audigy 2 */ 1950 /* Unmute Analog. 1951 * Set GPO6 to 1 for Apollo. This has to be done after 1952 * init Alice3 I2SOut beyond 48kHz. 1953 * So, sequence is important. 1954 */ 1955 emu_wr(sc, EMU_A_IOCFG, 1956 emu_rd(sc, EMU_A_IOCFG, 4) | EMU_A_IOCFG_GPOUT_A, 4); 1957 } 1958 } else { 1959 /* EMU10K1 initialization code */ 1960 tmp = EMU_HCFG_AUDIOENABLE | EMU_HCFG_LOCKTANKCACHE_MASK 1961 | EMU_HCFG_AUTOMUTE; 1962 if (sc->rev >= 6) 1963 tmp |= EMU_HCFG_JOYENABLE; 1964 1965 emu_wr(sc, EMU_HCFG, tmp, 4); 1966 1967 /* TOSLink detection */ 1968 sc->tos_link = 0; 1969 tmp = emu_rd(sc, EMU_HCFG, 4); 1970 if (tmp & (EMU_HCFG_GPINPUT0 | EMU_HCFG_GPINPUT1)) { 1971 emu_wr(sc, EMU_HCFG, tmp | EMU_HCFG_GPOUT1, 4); 1972 DELAY(50); 1973 if (tmp != (emu_rd(sc, EMU_HCFG, 4) & ~EMU_HCFG_GPOUT1)) { 1974 sc->tos_link = 1; 1975 emu_wr(sc, EMU_HCFG, tmp, 4); 1976 } 1977 } 1978 } 1979 1980 return 0; 1981} 1982 1983static int 1984emu_uninit(struct sc_info *sc) 1985{ 1986 u_int32_t ch; 1987 1988 emu_wr(sc, EMU_INTE, 0, 4); 1989 for (ch = 0; ch < NUM_G; ch++) 1990 emu_wrptr(sc, ch, EMU_CHAN_DCYSUSV, ENV_OFF); 1991 for (ch = 0; ch < NUM_G; ch++) { 1992 emu_wrptr(sc, ch, EMU_CHAN_VTFT, 0); 1993 emu_wrptr(sc, ch, EMU_CHAN_CVCF, 0); 1994 emu_wrptr(sc, ch, EMU_CHAN_PTRX, 0); 1995 emu_wrptr(sc, ch, EMU_CHAN_CPF, 0); 1996 } 1997 1998 if (sc->audigy) { /* stop fx processor */ 1999 emu_wrptr(sc, 0, EMU_A_DBG, EMU_A_DBG_SINGLE_STEP); 2000 } 2001 2002 /* disable audio and lock cache */ 2003 emu_wr(sc, EMU_HCFG, 2004 EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_MUTEBUTTONENABLE, 2005 4); 2006 2007 emu_wrptr(sc, 0, EMU_PTB, 0); 2008 /* reset recording buffers */ 2009 emu_wrptr(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE); 2010 emu_wrptr(sc, 0, EMU_MICBA, 0); 2011 emu_wrptr(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE); 2012 emu_wrptr(sc, 0, EMU_FXBA, 0); 2013 emu_wrptr(sc, 0, EMU_FXWC, 0); 2014 emu_wrptr(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE); 2015 emu_wrptr(sc, 0, EMU_ADCBA, 0); 2016 emu_wrptr(sc, 0, EMU_TCB, 0); 2017 emu_wrptr(sc, 0, EMU_TCBS, 0); 2018 2019 /* disable channel interrupt */ 2020 emu_wrptr(sc, 0, EMU_CLIEL, 0); 2021 emu_wrptr(sc, 0, EMU_CLIEH, 0); 2022 emu_wrptr(sc, 0, EMU_SOLEL, 0); 2023 emu_wrptr(sc, 0, EMU_SOLEH, 0); 2024 2025 /* init envelope engine */ 2026 if (!SLIST_EMPTY(&sc->mem.blocks)) 2027 device_printf(sc->dev, "warning: memblock list not empty\n"); 2028 emu_free(sc, sc->mem.ptb_pages); 2029 emu_free(sc, sc->mem.silent_page); 2030 2031 if(sc->mpu) 2032 mpu401_uninit(sc->mpu); 2033 return 0; 2034} 2035 2036static int 2037emu_pci_probe(device_t dev) 2038{ 2039 char *s = NULL; 2040 2041 switch (pci_get_devid(dev)) { 2042 case EMU10K1_PCI_ID: 2043 s = "Creative EMU10K1"; 2044 break; 2045 2046 case EMU10K2_PCI_ID: 2047 if (pci_get_revid(dev) == 0x04) 2048 s = "Creative Audigy 2 (EMU10K2)"; 2049 else 2050 s = "Creative Audigy (EMU10K2)"; 2051 break; 2052 2053 case EMU10K3_PCI_ID: 2054 s = "Creative Audigy 2 (EMU10K3)"; 2055 break; 2056 2057 default: 2058 return ENXIO; 2059 } 2060 2061 device_set_desc(dev, s); 2062 return BUS_PROBE_LOW_PRIORITY; 2063} 2064 2065static int 2066emu_pci_attach(device_t dev) 2067{ 2068 struct ac97_info *codec = NULL; 2069 struct sc_info *sc; 2070 int i, gotmic; 2071 char status[SND_STATUSLEN]; 2072 2073 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 2074 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_emu10k1 softc"); 2075 sc->dev = dev; 2076 sc->type = pci_get_devid(dev); 2077 sc->rev = pci_get_revid(dev); 2078 sc->audigy = sc->type == EMU10K2_PCI_ID || sc->type == EMU10K3_PCI_ID; 2079 sc->audigy2 = (sc->audigy && sc->rev == 0x04); 2080 sc->nchans = sc->audigy ? 8 : 4; 2081 sc->addrmask = sc->audigy ? EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK; 2082 2083 pci_enable_busmaster(dev); 2084 2085 i = PCIR_BAR(0); 2086 sc->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &i, RF_ACTIVE); 2087 if (sc->reg == NULL) { 2088 device_printf(dev, "unable to map register space\n"); 2089 goto bad; 2090 } 2091 sc->st = rman_get_bustag(sc->reg); 2092 sc->sh = rman_get_bushandle(sc->reg); 2093 2094 sc->bufsz = pcm_getbuffersize(dev, 4096, EMU_DEFAULT_BUFSZ, 65536); 2095 2096 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, 2097 /*boundary*/0, 2098 /*lowaddr*/(1U << 31) - 1, /* can only access 0-2gb */ 2099 /*highaddr*/BUS_SPACE_MAXADDR, 2100 /*filter*/NULL, /*filterarg*/NULL, 2101 /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, 2102 /*flags*/0, /*lockfunc*/busdma_lock_mutex, 2103 /*lockarg*/&Giant, &sc->parent_dmat) != 0) { 2104 device_printf(dev, "unable to create dma tag\n"); 2105 goto bad; 2106 } 2107 2108 if (emu_init(sc) == -1) { 2109 device_printf(dev, "unable to initialize the card\n"); 2110 goto bad; 2111 } 2112 2113 codec = AC97_CREATE(dev, sc, emu_ac97); 2114 if (codec == NULL) goto bad; 2115 gotmic = (ac97_getcaps(codec) & AC97_CAP_MICCHANNEL) ? 1 : 0; 2116 if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; 2117 2118 emu_midiattach(sc); 2119 2120 i = 0; 2121 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, 2122 RF_ACTIVE | RF_SHAREABLE); 2123 if (!sc->irq || 2124 snd_setup_intr(dev, sc->irq, INTR_MPSAFE, emu_intr, sc, &sc->ih)) { 2125 device_printf(dev, "unable to map interrupt\n"); 2126 goto bad; 2127 } 2128 2129 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s", 2130 rman_get_start(sc->reg), rman_get_start(sc->irq), 2131 PCM_KLDSTRING(snd_emu10k1)); 2132 2133 if (pcm_register(dev, sc, sc->nchans, gotmic ? 3 : 2)) goto bad; 2134 for (i = 0; i < sc->nchans; i++) 2135 pcm_addchan(dev, PCMDIR_PLAY, &emupchan_class, sc); 2136 for (i = 0; i < (gotmic ? 3 : 2); i++) 2137 pcm_addchan(dev, PCMDIR_REC, &emurchan_class, sc); 2138 2139 pcm_setstatus(dev, status); 2140 2141 return 0; 2142 2143bad: 2144 if (codec) ac97_destroy(codec); 2145 if (sc->reg) bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg); 2146 if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); 2147 if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); 2148 if (sc->parent_dmat) bus_dma_tag_destroy(sc->parent_dmat); 2149 if (sc->lock) snd_mtxfree(sc->lock); 2150 free(sc, M_DEVBUF); 2151 return ENXIO; 2152} 2153 2154static int 2155emu_pci_detach(device_t dev) 2156{ 2157 int r; 2158 struct sc_info *sc; 2159 2160 r = pcm_unregister(dev); 2161 if (r) 2162 return r; 2163 2164 sc = pcm_getdevinfo(dev); 2165 /* shutdown chip */ 2166 emu_uninit(sc); 2167 2168 bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg); 2169 bus_teardown_intr(dev, sc->irq, sc->ih); 2170 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); 2171 bus_dma_tag_destroy(sc->parent_dmat); 2172 snd_mtxfree(sc->lock); 2173 free(sc, M_DEVBUF); 2174 2175 return 0; 2176} 2177 2178/* add suspend, resume */ 2179static device_method_t emu_methods[] = { 2180 /* Device interface */ 2181 DEVMETHOD(device_probe, emu_pci_probe), 2182 DEVMETHOD(device_attach, emu_pci_attach), 2183 DEVMETHOD(device_detach, emu_pci_detach), 2184 2185 DEVMETHOD_END 2186}; 2187 2188static driver_t emu_driver = { 2189 "pcm", 2190 emu_methods, 2191 PCM_SOFTC_SIZE, 2192}; 2193 2194DRIVER_MODULE(snd_emu10k1, pci, emu_driver, pcm_devclass, NULL, NULL); 2195MODULE_DEPEND(snd_emu10k1, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 2196MODULE_VERSION(snd_emu10k1, 1); 2197MODULE_DEPEND(snd_emu10k1, midi, 1, 1, 1); 2198 2199/* dummy driver to silence the joystick device */ 2200static int 2201emujoy_pci_probe(device_t dev) 2202{ 2203 char *s = NULL; 2204 2205 switch (pci_get_devid(dev)) { 2206 case 0x70021102: 2207 s = "Creative EMU10K1 Joystick"; 2208 device_quiet(dev); 2209 break; 2210 case 0x70031102: 2211 s = "Creative EMU10K2 Joystick"; 2212 device_quiet(dev); 2213 break; 2214 } 2215 2216 if (s) device_set_desc(dev, s); 2217 return s ? -1000 : ENXIO; 2218} 2219 2220static int 2221emujoy_pci_attach(device_t dev) 2222{ 2223 2224 return 0; 2225} 2226 2227static int 2228emujoy_pci_detach(device_t dev) 2229{ 2230 2231 return 0; 2232} 2233 2234static device_method_t emujoy_methods[] = { 2235 DEVMETHOD(device_probe, emujoy_pci_probe), 2236 DEVMETHOD(device_attach, emujoy_pci_attach), 2237 DEVMETHOD(device_detach, emujoy_pci_detach), 2238 2239 DEVMETHOD_END 2240}; 2241 2242static driver_t emujoy_driver = { 2243 "emujoy", 2244 emujoy_methods, 2245 1 /* no softc */ 2246}; 2247 2248static devclass_t emujoy_devclass; 2249 2250DRIVER_MODULE(emujoy, pci, emujoy_driver, emujoy_devclass, NULL, NULL); 2251