1160383Snetchild/*- 2160383Snetchild * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 3172150Sariff * Copyright (c) 2003-2007 Yuriy Tsibizov <yuriy.tsibizov@gfk.ru> 4160383Snetchild * All rights reserved. 5160383Snetchild * 6160383Snetchild * Redistribution and use in source and binary forms, with or without 7160383Snetchild * modification, are permitted provided that the following conditions 8160383Snetchild * are met: 9160383Snetchild * 1. Redistributions of source code must retain the above copyright 10160383Snetchild * notice, this list of conditions and the following disclaimer. 11160383Snetchild * 2. Redistributions in binary form must reproduce the above copyright 12160383Snetchild * notice, this list of conditions and the following disclaimer in the 13160383Snetchild * documentation and/or other materials provided with the distribution. 14160383Snetchild * 15160383Snetchild * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16160383Snetchild * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17160383Snetchild * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18160383Snetchild * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19160383Snetchild * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20160383Snetchild * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21160383Snetchild * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22160383Snetchild * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 23160383Snetchild * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24160383Snetchild * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25160383Snetchild * SUCH DAMAGE. 26160383Snetchild * 27160383Snetchild * $FreeBSD$ 28160383Snetchild */ 29160383Snetchild 30160383Snetchild#include <sys/param.h> 31160383Snetchild#include <sys/types.h> 32160383Snetchild#include <sys/bus.h> 33160383Snetchild#include <machine/bus.h> 34160383Snetchild#include <sys/rman.h> 35160383Snetchild#include <sys/systm.h> 36160383Snetchild#include <sys/sbuf.h> 37160383Snetchild#include <sys/queue.h> 38160383Snetchild#include <sys/lock.h> 39160383Snetchild#include <sys/mutex.h> 40160383Snetchild#include <sys/sysctl.h> 41172150Sariff#include <sys/kdb.h> 42160383Snetchild 43160383Snetchild#include <dev/pci/pcireg.h> 44160383Snetchild#include <dev/pci/pcivar.h> 45160383Snetchild 46160383Snetchild#include <machine/clock.h> /* for DELAY */ 47160383Snetchild 48193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS 49193640Sariff#include "opt_snd.h" 50193640Sariff#endif 51193640Sariff 52160383Snetchild#include <dev/sound/chip.h> 53160383Snetchild#include <dev/sound/pcm/sound.h> 54160383Snetchild#include <dev/sound/pcm/ac97.h> 55160383Snetchild 56229981Spfg#include <dev/sound/pci/emuxkireg.h> 57160383Snetchild#include <dev/sound/pci/emu10kx.h> 58160383Snetchild 59160383Snetchild/* hw flags */ 60160383Snetchild#define HAS_51 0x0001 61160383Snetchild#define HAS_71 0x0002 62160383Snetchild#define HAS_AC97 0x0004 63160383Snetchild 64160383Snetchild#define IS_EMU10K1 0x0008 65160383Snetchild#define IS_EMU10K2 0x0010 66160383Snetchild#define IS_CA0102 0x0020 67160383Snetchild#define IS_CA0108 0x0040 68160383Snetchild#define IS_UNKNOWN 0x0080 69160383Snetchild 70160383Snetchild#define BROKEN_DIGITAL 0x0100 71160383Snetchild#define DIGITAL_ONLY 0x0200 72160383Snetchild 73160383Snetchild#define IS_CARDBUS 0x0400 74160383Snetchild 75160383Snetchild#define MODE_ANALOG 1 76160383Snetchild#define MODE_DIGITAL 2 77160383Snetchild#define SPDIF_MODE_PCM 1 78160383Snetchild#define SPDIF_MODE_AC3 2 79160383Snetchild 80160383Snetchild#define MACS 0x0 81160383Snetchild#define MACS1 0x1 82160383Snetchild#define MACW 0x2 83160383Snetchild#define MACW1 0x3 84160383Snetchild#define MACINTS 0x4 85160383Snetchild#define MACINTW 0x5 86160383Snetchild#define ACC3 0x6 87160383Snetchild#define MACMV 0x7 88160383Snetchild#define ANDXOR 0x8 89160383Snetchild#define TSTNEG 0x9 90160383Snetchild#define LIMIT 0xA 91160383Snetchild#define LIMIT1 0xB 92160383Snetchild#define LOG 0xC 93160383Snetchild#define EXP 0xD 94160383Snetchild#define INTERP 0xE 95160383Snetchild#define SKIP 0xF 96160383Snetchild 97160383Snetchild#define GPR(i) (sc->gpr_base+(i)) 98160383Snetchild#define INP(i) (sc->input_base+(i)) 99160383Snetchild#define OUTP(i) (sc->output_base+(i)) 100160383Snetchild#define FX(i) (i) 101160383Snetchild#define FX2(i) (sc->efxc_base+(i)) 102160383Snetchild#define DSP_CONST(i) (sc->dsp_zero+(i)) 103160383Snetchild 104160383Snetchild#define COND_NORMALIZED DSP_CONST(0x1) 105160383Snetchild#define COND_BORROW DSP_CONST(0x2) 106160383Snetchild#define COND_MINUS DSP_CONST(0x3) 107160383Snetchild#define COND_LESS_ZERO DSP_CONST(0x4) 108160383Snetchild#define COND_EQ_ZERO DSP_CONST(0x5) 109160383Snetchild#define COND_SATURATION DSP_CONST(0x6) 110160383Snetchild#define COND_NEQ_ZERO DSP_CONST(0x8) 111160383Snetchild 112172150Sariff#define DSP_ACCUM DSP_CONST(0x16) 113172150Sariff#define DSP_CCR DSP_CONST(0x17) 114172150Sariff 115160383Snetchild/* Live! Inputs */ 116160383Snetchild#define IN_AC97_L 0x00 117160383Snetchild#define IN_AC97_R 0x01 118160383Snetchild#define IN_AC97 IN_AC97_L 119160383Snetchild#define IN_SPDIF_CD_L 0x02 120160383Snetchild#define IN_SPDIF_CD_R 0x03 121160383Snetchild#define IN_SPDIF_CD IN_SPDIF_CD_L 122160383Snetchild#define IN_ZOOM_L 0x04 123160383Snetchild#define IN_ZOOM_R 0x05 124160383Snetchild#define IN_ZOOM IN_ZOOM_L 125160383Snetchild#define IN_TOSLINK_L 0x06 126160383Snetchild#define IN_TOSLINK_R 0x07 127160383Snetchild#define IN_TOSLINK IN_TOSLINK_L 128160383Snetchild#define IN_LINE1_L 0x08 129160383Snetchild#define IN_LINE1_R 0x09 130160383Snetchild#define IN_LINE1 IN_LINE1_L 131160383Snetchild#define IN_COAX_SPDIF_L 0x0a 132160383Snetchild#define IN_COAX_SPDIF_R 0x0b 133160383Snetchild#define IN_COAX_SPDIF IN_COAX_SPDIF_L 134160383Snetchild#define IN_LINE2_L 0x0c 135160383Snetchild#define IN_LINE2_R 0x0d 136160383Snetchild#define IN_LINE2 IN_LINE2_L 137160383Snetchild#define IN_0E 0x0e 138160383Snetchild#define IN_0F 0x0f 139160383Snetchild 140160383Snetchild/* Outputs */ 141160383Snetchild#define OUT_AC97_L 0x00 142160383Snetchild#define OUT_AC97_R 0x01 143160383Snetchild#define OUT_AC97 OUT_AC97_L 144160383Snetchild#define OUT_A_FRONT OUT_AC97 145160383Snetchild#define OUT_TOSLINK_L 0x02 146160383Snetchild#define OUT_TOSLINK_R 0x03 147160383Snetchild#define OUT_TOSLINK OUT_TOSLINK_L 148160383Snetchild#define OUT_D_CENTER 0x04 149160383Snetchild#define OUT_D_SUB 0x05 150160383Snetchild#define OUT_HEADPHONE_L 0x06 151160383Snetchild#define OUT_HEADPHONE_R 0x07 152160383Snetchild#define OUT_HEADPHONE OUT_HEADPHONE_L 153160383Snetchild#define OUT_REAR_L 0x08 154160383Snetchild#define OUT_REAR_R 0x09 155160383Snetchild#define OUT_REAR OUT_REAR_L 156160383Snetchild#define OUT_ADC_REC_L 0x0a 157160383Snetchild#define OUT_ADC_REC_R 0x0b 158160383Snetchild#define OUT_ADC_REC OUT_ADC_REC_L 159160383Snetchild#define OUT_MIC_CAP 0x0c 160165833Snetchild 161230137Sjoel/* Live! 5.1 Digital, non-standard 5.1 (center & sub) outputs */ 162160383Snetchild#define OUT_A_CENTER 0x11 163160383Snetchild#define OUT_A_SUB 0x12 164160383Snetchild 165160383Snetchild/* Audigy Inputs */ 166160383Snetchild#define A_IN_AC97_L 0x00 167160383Snetchild#define A_IN_AC97_R 0x01 168160383Snetchild#define A_IN_AC97 A_IN_AC97_L 169160383Snetchild#define A_IN_SPDIF_CD_L 0x02 170160383Snetchild#define A_IN_SPDIF_CD_R 0x03 171160383Snetchild#define A_IN_SPDIF_CD A_IN_SPDIF_CD_L 172160383Snetchild#define A_IN_O_SPDIF_L 0x04 173160383Snetchild#define A_IN_O_SPDIF_R 0x05 174160383Snetchild#define A_IN_O_SPDIF A_IN_O_SPDIF_L 175160383Snetchild#define A_IN_LINE2_L 0x08 176160383Snetchild#define A_IN_LINE2_R 0x09 177160383Snetchild#define A_IN_LINE2 A_IN_LINE2_L 178160383Snetchild#define A_IN_R_SPDIF_L 0x0a 179160383Snetchild#define A_IN_R_SPDIF_R 0x0b 180160383Snetchild#define A_IN_R_SPDIF A_IN_R_SPDIF_L 181160383Snetchild#define A_IN_AUX2_L 0x0c 182160383Snetchild#define A_IN_AUX2_R 0x0d 183160383Snetchild#define A_IN_AUX2 A_IN_AUX2_L 184160383Snetchild 185229981Spfg/* Audigy Outputs */ 186160383Snetchild#define A_OUT_D_FRONT_L 0x00 187160383Snetchild#define A_OUT_D_FRONT_R 0x01 188160383Snetchild#define A_OUT_D_FRONT A_OUT_D_FRONT_L 189160383Snetchild#define A_OUT_D_CENTER 0x02 190160383Snetchild#define A_OUT_D_SUB 0x03 191160383Snetchild#define A_OUT_D_SIDE_L 0x04 192160383Snetchild#define A_OUT_D_SIDE_R 0x05 193160383Snetchild#define A_OUT_D_SIDE A_OUT_D_SIDE_L 194160383Snetchild#define A_OUT_D_REAR_L 0x06 195160383Snetchild#define A_OUT_D_REAR_R 0x07 196160383Snetchild#define A_OUT_D_REAR A_OUT_D_REAR_L 197160383Snetchild 198160383Snetchild/* on Audigy Platinum only */ 199160383Snetchild#define A_OUT_HPHONE_L 0x04 200160383Snetchild#define A_OUT_HPHONE_R 0x05 201160383Snetchild#define A_OUT_HPHONE A_OUT_HPHONE_L 202160383Snetchild 203160383Snetchild#define A_OUT_A_FRONT_L 0x08 204160383Snetchild#define A_OUT_A_FRONT_R 0x09 205160383Snetchild#define A_OUT_A_FRONT A_OUT_A_FRONT_L 206160383Snetchild#define A_OUT_A_CENTER 0x0a 207160383Snetchild#define A_OUT_A_SUB 0x0b 208160383Snetchild#define A_OUT_A_SIDE_L 0x0c 209160383Snetchild#define A_OUT_A_SIDE_R 0x0d 210160383Snetchild#define A_OUT_A_SIDE A_OUT_A_SIDE_L 211160383Snetchild#define A_OUT_A_REAR_L 0x0e 212160383Snetchild#define A_OUT_A_REAR_R 0x0f 213160383Snetchild#define A_OUT_A_REAR A_OUT_A_REAR_L 214160383Snetchild#define A_OUT_AC97_L 0x10 215160383Snetchild#define A_OUT_AC97_R 0x11 216160383Snetchild#define A_OUT_AC97 A_OUT_AC97_L 217160383Snetchild#define A_OUT_ADC_REC_L 0x16 218160383Snetchild#define A_OUT_ADC_REC_R 0x17 219160383Snetchild#define A_OUT_ADC_REC A_OUT_ADC_REC_L 220160383Snetchild 221229981Spfg#define EMU_DATA2 0x24 222229981Spfg#define EMU_IPR2 0x28 223229981Spfg#define EMU_INTE2 0x2c 224229981Spfg#define EMU_IPR3 0x38 225229981Spfg#define EMU_INTE3 0x3c 226160383Snetchild 227229981Spfg#define EMU_A2_SRCSel 0x60 228229981Spfg#define EMU_A2_SRCMULTI_ENABLE 0x6e 229229981Spfg 230229981Spfg#define EMU_A_I2S_CAPTURE_96000 0x00000400 231229981Spfg 232229981Spfg#define EMU_A2_MIXER_I2S_ENABLE 0x7B 233229981Spfg#define EMU_A2_MIXER_SPDIF_ENABLE 0x7A 234229981Spfg 235160383Snetchild#define C_FRONT_L 0 236160383Snetchild#define C_FRONT_R 1 237160383Snetchild#define C_REC_L 2 238160383Snetchild#define C_REC_R 3 239160383Snetchild#define C_REAR_L 4 240160383Snetchild#define C_REAR_R 5 241160383Snetchild#define C_CENTER 6 242160383Snetchild#define C_SUB 7 243160383Snetchild#define C_SIDE_L 8 244160383Snetchild#define C_SIDE_R 9 245160383Snetchild#define NUM_CACHES 10 246160383Snetchild 247172150Sariff#define CDSPDIFMUTE 0 248172150Sariff#define ANALOGMUTE 1 249172150Sariff#define NUM_MUTE 2 250165833Snetchild 251160383Snetchild#define EMU_MAX_GPR 512 252160383Snetchild#define EMU_MAX_IRQ_CONSUMERS 32 253160383Snetchild 254160383Snetchildstruct emu_voice { 255160383Snetchild int vnum; 256161055Snetchild unsigned int b16:1, stereo:1, busy:1, running:1, ismaster:1; 257160383Snetchild int speed; 258160383Snetchild int start; 259160383Snetchild int end; 260160383Snetchild int vol; 261160383Snetchild uint32_t buf; 262160383Snetchild void *vbuf; 263160383Snetchild struct emu_voice *slave; 264160383Snetchild uint32_t sa; 265160383Snetchild uint32_t ea; 266172150Sariff uint32_t routing[8]; 267172150Sariff uint32_t amounts[8]; 268160383Snetchild}; 269160383Snetchild 270160383Snetchildstruct emu_memblk { 271160383Snetchild SLIST_ENTRY(emu_memblk) link; 272160383Snetchild void *buf; 273160383Snetchild char owner[16]; 274160383Snetchild bus_addr_t buf_addr; 275160383Snetchild uint32_t pte_start, pte_size; 276160383Snetchild}; 277160383Snetchild 278160383Snetchildstruct emu_mem { 279161054Snetchild uint8_t bmap[EMU_MAXPAGES / 8]; 280160383Snetchild uint32_t *ptb_pages; 281160383Snetchild void *silent_page; 282160383Snetchild bus_addr_t silent_page_addr; 283160383Snetchild bus_addr_t ptb_pages_addr; 284160383Snetchild bus_dma_tag_t dmat; 285172150Sariff struct emu_sc_info *card; 286160383Snetchild SLIST_HEAD(, emu_memblk) blocks; 287160383Snetchild}; 288160383Snetchild 289160383Snetchild/* rm */ 290160383Snetchildstruct emu_rm { 291160383Snetchild struct emu_sc_info *card; 292160383Snetchild struct mtx gpr_lock; 293160383Snetchild signed int allocmap[EMU_MAX_GPR]; 294160383Snetchild int num_gprs; 295160383Snetchild int last_free_gpr; 296160383Snetchild int num_used; 297160383Snetchild}; 298160383Snetchild 299160383Snetchildstruct emu_intr_handler { 300160383Snetchild void* softc; 301160383Snetchild uint32_t intr_mask; 302160383Snetchild uint32_t inte_mask; 303160383Snetchild uint32_t(*irq_func) (void *softc, uint32_t irq); 304160383Snetchild}; 305160383Snetchild 306160383Snetchildstruct emu_sc_info { 307160383Snetchild struct mtx lock; 308160383Snetchild struct mtx rw; /* Hardware exclusive access lock */ 309160383Snetchild 310160383Snetchild /* Hardware and subdevices */ 311160383Snetchild device_t dev; 312165833Snetchild device_t pcm[RT_COUNT]; 313160383Snetchild device_t midi[2]; 314160383Snetchild uint32_t type; 315160383Snetchild uint32_t rev; 316160383Snetchild 317160383Snetchild bus_space_tag_t st; 318160383Snetchild bus_space_handle_t sh; 319160383Snetchild 320160383Snetchild struct cdev *cdev; /* /dev/emu10k character device */ 321160383Snetchild struct mtx emu10kx_lock; 322160383Snetchild int emu10kx_isopen; 323160383Snetchild struct sbuf emu10kx_sbuf; 324160383Snetchild int emu10kx_bufptr; 325160383Snetchild 326160383Snetchild 327160383Snetchild /* Resources */ 328160383Snetchild struct resource *reg; 329160383Snetchild struct resource *irq; 330160383Snetchild void *ih; 331160383Snetchild 332160383Snetchild /* IRQ handlers */ 333160383Snetchild struct emu_intr_handler ihandler[EMU_MAX_IRQ_CONSUMERS]; 334160383Snetchild 335160383Snetchild /* Card HW configuration */ 336172150Sariff unsigned int mode; /* analog / digital */ 337160383Snetchild unsigned int mchannel_fx; 338160383Snetchild unsigned int dsp_zero; 339160383Snetchild unsigned int code_base; 340160383Snetchild unsigned int code_size; 341160383Snetchild unsigned int gpr_base; 342160383Snetchild unsigned int num_gprs; 343160383Snetchild unsigned int input_base; 344160383Snetchild unsigned int output_base; 345160383Snetchild unsigned int efxc_base; 346160383Snetchild unsigned int opcode_shift; 347160383Snetchild unsigned int high_operand_shift; 348160383Snetchild unsigned int address_mask; 349160383Snetchild uint32_t is_emu10k1:1, is_emu10k2, is_ca0102, is_ca0108:1, 350160383Snetchild has_ac97:1, has_51:1, has_71:1, 351172150Sariff enable_ir:1, 352160383Snetchild broken_digital:1, is_cardbus:1; 353160383Snetchild 354172150Sariff signed int mch_disabled, mch_rec, dbg_level; 355172150Sariff signed int num_inputs; 356160383Snetchild unsigned int num_outputs; 357160383Snetchild unsigned int num_fxbuses; 358160383Snetchild unsigned int routing_code_start; 359160383Snetchild unsigned int routing_code_end; 360160383Snetchild 361160383Snetchild /* HW resources */ 362160383Snetchild struct emu_voice voice[NUM_G]; /* Hardware voices */ 363160383Snetchild uint32_t irq_mask[EMU_MAX_IRQ_CONSUMERS]; /* IRQ manager data */ 364160383Snetchild int timer[EMU_MAX_IRQ_CONSUMERS]; /* timer */ 365160383Snetchild int timerinterval; 366160383Snetchild struct emu_rm *rm; 367160383Snetchild struct emu_mem mem; /* memory */ 368160383Snetchild 369160383Snetchild /* Mixer */ 370160383Snetchild int mixer_gpr[NUM_MIXERS]; 371160383Snetchild int mixer_volcache[NUM_MIXERS]; 372160383Snetchild int cache_gpr[NUM_CACHES]; 373172150Sariff int dummy_gpr; 374172150Sariff int mute_gpr[NUM_MUTE]; 375160383Snetchild struct sysctl_ctx_list *ctx; 376160383Snetchild struct sysctl_oid *root; 377160383Snetchild}; 378160383Snetchild 379160383Snetchildstatic void emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error); 380160383Snetchildstatic void* emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr); 381160383Snetchildstatic void emu_free(struct emu_mem *mem, void *dmabuf); 382160383Snetchildstatic void* emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char * owner); 383160383Snetchildstatic int emu_memfree(struct emu_mem *mem, void *membuf); 384160383Snetchildstatic int emu_memstart(struct emu_mem *mem, void *membuf); 385160383Snetchild 386160383Snetchild/* /dev */ 387160383Snetchildstatic int emu10kx_dev_init(struct emu_sc_info *sc); 388160383Snetchildstatic int emu10kx_dev_uninit(struct emu_sc_info *sc); 389160383Snetchildstatic int emu10kx_prepare(struct emu_sc_info *sc, struct sbuf *s); 390160383Snetchild 391160383Snetchildstatic void emumix_set_mode(struct emu_sc_info *sc, int mode); 392160383Snetchildstatic void emumix_set_spdif_mode(struct emu_sc_info *sc, int mode); 393160383Snetchildstatic void emumix_set_fxvol(struct emu_sc_info *sc, unsigned gpr, int32_t vol); 394160383Snetchildstatic void emumix_set_gpr(struct emu_sc_info *sc, unsigned gpr, int32_t val); 395160383Snetchildstatic int sysctl_emu_mixer_control(SYSCTL_HANDLER_ARGS); 396160383Snetchild 397160383Snetchildstatic int emu_rm_init(struct emu_sc_info *sc); 398160383Snetchildstatic int emu_rm_uninit(struct emu_sc_info *sc); 399160383Snetchildstatic int emu_rm_gpr_alloc(struct emu_rm *rm, int count); 400160383Snetchild 401165833Snetchildstatic unsigned int emu_getcard(device_t dev); 402160383Snetchildstatic uint32_t emu_rd_nolock(struct emu_sc_info *sc, unsigned int regno, unsigned int size); 403160383Snetchildstatic void emu_wr_nolock(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size); 404160383Snetchildstatic void emu_wr_cbptr(struct emu_sc_info *sc, uint32_t data); 405160383Snetchild 406160383Snetchildstatic void emu_vstop(struct emu_sc_info *sc, char channel, int enable); 407160383Snetchild 408160383Snetchildstatic void emu_intr(void *p); 409160383Snetchildstatic void emu_wrefx(struct emu_sc_info *sc, unsigned int pc, unsigned int data); 410160383Snetchildstatic void emu_addefxop(struct emu_sc_info *sc, unsigned int op, unsigned int z, unsigned int w, unsigned int x, unsigned int y, uint32_t * pc); 411160383Snetchildstatic void emu_initefx(struct emu_sc_info *sc); 412160383Snetchild 413160383Snetchildstatic int emu_cardbus_init(struct emu_sc_info *sc); 414166919Sariffstatic int emu_init(struct emu_sc_info *sc); 415160383Snetchildstatic int emu_uninit(struct emu_sc_info *sc); 416160383Snetchild 417160383Snetchildstatic int emu_read_ivar(device_t bus __unused, device_t dev, int ivar_index, uintptr_t * result); 418160383Snetchildstatic int emu_write_ivar(device_t bus __unused, device_t dev __unused, 419160383Snetchild int ivar_index, uintptr_t value __unused); 420160383Snetchild 421160383Snetchildstatic int emu_pci_probe(device_t dev); 422160383Snetchildstatic int emu_pci_attach(device_t dev); 423160383Snetchildstatic int emu_pci_detach(device_t dev); 424160383Snetchildstatic int emu_modevent(module_t mod __unused, int cmd, void *data __unused); 425160383Snetchild 426172150Sariff#ifdef SND_EMU10KX_DEBUG 427172150Sariff 428172150Sariff#define EMU_MTX_DEBUG() do { \ 429172150Sariff if (mtx_owned(&sc->rw)) { \ 430172150Sariff printf("RW owned in %s line %d for %s\n", __func__, \ 431172150Sariff __LINE__ , device_get_nameunit(sc->dev)); \ 432172150Sariff printf("rw lock owned: %d\n", mtx_owned(&sc->rw)); \ 433172150Sariff printf("rw lock: value %x thread %x\n", \ 434172150Sariff ((&sc->rw)->mtx_lock & ~MTX_FLAGMASK), \ 435172150Sariff (uintptr_t)curthread); \ 436172150Sariff printf("rw lock: recursed %d\n", mtx_recursed(&sc->rw));\ 437172150Sariff db_show_mtx(&sc->rw); \ 438172150Sariff } \ 439172150Sariff } while (0) 440172150Sariff#else 441172150Sariff#define EMU_MTX_DEBUG() do { \ 442172150Sariff } while (0) 443172150Sariff#endif 444172150Sariff 445172150Sariff#define EMU_RWLOCK() do { \ 446172150Sariff EMU_MTX_DEBUG(); \ 447172150Sariff mtx_lock(&(sc->rw)); \ 448172150Sariff } while (0) 449172150Sariff 450172150Sariff#define EMU_RWUNLOCK() do { \ 451172150Sariff mtx_unlock(&(sc->rw)); \ 452172150Sariff EMU_MTX_DEBUG(); \ 453172150Sariff } while (0) 454172150Sariff 455160383Snetchild/* Supported cards */ 456160383Snetchildstruct emu_hwinfo { 457160383Snetchild uint16_t vendor; 458160383Snetchild uint16_t device; 459160383Snetchild uint16_t subvendor; 460160383Snetchild uint16_t subdevice; 461160383Snetchild char SBcode[8]; 462160383Snetchild char desc[32]; 463160383Snetchild int flags; 464160383Snetchild}; 465160383Snetchild 466160383Snetchildstatic struct emu_hwinfo emu_cards[] = { 467165833Snetchild {0xffff, 0xffff, 0xffff, 0xffff, "BADCRD", "Not a compatible card", 0}, 468160383Snetchild /* 0x0020..0x002f 4.0 EMU10K1 cards */ 469160383Snetchild {0x1102, 0x0002, 0x1102, 0x0020, "CT4850", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 470160383Snetchild {0x1102, 0x0002, 0x1102, 0x0021, "CT4620", "SBLive!", HAS_AC97 | IS_EMU10K1}, 471160383Snetchild {0x1102, 0x0002, 0x1102, 0x002f, "CT????", "SBLive! mainboard implementation", HAS_AC97 | IS_EMU10K1}, 472160383Snetchild 473160383Snetchild /* (range unknown) 5.1 EMU10K1 cards */ 474160383Snetchild {0x1102, 0x0002, 0x1102, 0x100a, "CT????", "SBLive! 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1}, 475160383Snetchild 476160383Snetchild /* 0x80??..0x805? 4.0 EMU10K1 cards */ 477160383Snetchild {0x1102, 0x0002, 0x1102, 0x8022, "CT4780", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 478160383Snetchild {0x1102, 0x0002, 0x1102, 0x8023, "CT4790", "SB PCI512", HAS_AC97 | IS_EMU10K1}, 479160383Snetchild {0x1102, 0x0002, 0x1102, 0x8024, "CT4760", "SBLive!", HAS_AC97 | IS_EMU10K1}, 480160383Snetchild {0x1102, 0x0002, 0x1102, 0x8025, "CT????", "SBLive! Mainboard Implementation", HAS_AC97 | IS_EMU10K1}, 481160383Snetchild {0x1102, 0x0002, 0x1102, 0x8026, "CT4830", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 482160383Snetchild {0x1102, 0x0002, 0x1102, 0x8027, "CT4832", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 483160383Snetchild {0x1102, 0x0002, 0x1102, 0x8028, "CT4760", "SBLive! OEM version", HAS_AC97 | IS_EMU10K1}, 484160383Snetchild {0x1102, 0x0002, 0x1102, 0x8031, "CT4831", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 485160383Snetchild {0x1102, 0x0002, 0x1102, 0x8040, "CT4760", "SBLive!", HAS_AC97 | IS_EMU10K1}, 486160383Snetchild {0x1102, 0x0002, 0x1102, 0x8051, "CT4850", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 487160383Snetchild 488160383Snetchild /* 0x8061..0x???? 5.1 EMU10K1 cards */ 489160383Snetchild {0x1102, 0x0002, 0x1102, 0x8061, "SB????", "SBLive! Player 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1}, 490172150Sariff {0x1102, 0x0002, 0x1102, 0x8062, "CT4830", "SBLive! 1024", HAS_AC97 | HAS_51 | IS_EMU10K1}, 491160383Snetchild {0x1102, 0x0002, 0x1102, 0x8064, "SB????", "SBLive! 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1}, 492160383Snetchild {0x1102, 0x0002, 0x1102, 0x8065, "SB0220", "SBLive! 5.1 Digital", HAS_AC97 | HAS_51 | IS_EMU10K1}, 493160383Snetchild {0x1102, 0x0002, 0x1102, 0x8066, "CT4780", "SBLive! 5.1 Digital", HAS_AC97 | HAS_51 | IS_EMU10K1}, 494160383Snetchild {0x1102, 0x0002, 0x1102, 0x8067, "SB????", "SBLive!", HAS_AC97 | HAS_51 | IS_EMU10K1}, 495160383Snetchild 496160383Snetchild /* Generic SB Live! */ 497160383Snetchild {0x1102, 0x0002, 0x1102, 0x0000, "SB????", "SBLive! (Unknown model)", HAS_AC97 | IS_EMU10K1}, 498160383Snetchild 499160383Snetchild /* 0x0041..0x0043 EMU10K2 (some kind of Audigy) cards */ 500160383Snetchild 501160383Snetchild /* 0x0051..0x0051 5.1 CA0100-IAF cards */ 502160383Snetchild {0x1102, 0x0004, 0x1102, 0x0051, "SB0090", "Audigy", HAS_AC97 | HAS_51 | IS_EMU10K2}, 503160383Snetchild /* ES is CA0100-IDF chip that don't work in digital mode */ 504160383Snetchild {0x1102, 0x0004, 0x1102, 0x0052, "SB0160", "Audigy ES", HAS_AC97 | HAS_71 | IS_EMU10K2 | BROKEN_DIGITAL}, 505160383Snetchild /* 0x0053..0x005C 5.1 CA0101-NAF cards */ 506160383Snetchild {0x1102, 0x0004, 0x1102, 0x0053, "SB0090", "Audigy Player/OEM", HAS_AC97 | HAS_51 | IS_EMU10K2}, 507160383Snetchild {0x1102, 0x0004, 0x1102, 0x0058, "SB0090", "Audigy Player/OEM", HAS_AC97 | HAS_51 | IS_EMU10K2}, 508160383Snetchild 509160383Snetchild /* 0x1002..0x1009 5.1 CA0102-IAT cards */ 510160383Snetchild {0x1102, 0x0004, 0x1102, 0x1002, "SB????", "Audigy 2 Platinum", HAS_51 | IS_CA0102}, 511160383Snetchild {0x1102, 0x0004, 0x1102, 0x1005, "SB????", "Audigy 2 Platinum EX", HAS_51 | IS_CA0102}, 512160383Snetchild {0x1102, 0x0004, 0x1102, 0x1007, "SB0240", "Audigy 2", HAS_AC97 | HAS_51 | IS_CA0102}, 513160383Snetchild 514160383Snetchild /* 0x2001..0x2003 7.1 CA0102-ICT cards */ 515160383Snetchild {0x1102, 0x0004, 0x1102, 0x2001, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102}, 516160383Snetchild {0x1102, 0x0004, 0x1102, 0x2002, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102}, 517165833Snetchild /* XXX No reports about 0x2003 & 0x2004 cards */ 518165833Snetchild {0x1102, 0x0004, 0x1102, 0x2003, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102}, 519165833Snetchild {0x1102, 0x0004, 0x1102, 0x2004, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102}, 520165833Snetchild {0x1102, 0x0004, 0x1102, 0x2005, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102}, 521160383Snetchild 522160383Snetchild /* (range unknown) 7.1 CA0102-xxx Audigy 4 cards */ 523160383Snetchild {0x1102, 0x0004, 0x1102, 0x2007, "SB0380", "Audigy 4 Pro", HAS_AC97 | HAS_71 | IS_CA0102}, 524160383Snetchild 525160383Snetchild /* Generic Audigy or Audigy 2 */ 526160383Snetchild {0x1102, 0x0004, 0x1102, 0x0000, "SB????", "Audigy (Unknown model)", HAS_AC97 | HAS_51 | IS_EMU10K2}, 527160383Snetchild 528160383Snetchild /* We don't support CA0103-DAT (Audigy LS) cards */ 529160383Snetchild /* There is NO CA0104-xxx cards */ 530160383Snetchild /* There is NO CA0105-xxx cards */ 531160383Snetchild /* We don't support CA0106-DAT (SB Live! 24 bit) cards */ 532160383Snetchild /* There is NO CA0107-xxx cards */ 533160383Snetchild 534160383Snetchild /* 0x1000..0x1001 7.1 CA0108-IAT cards */ 535160383Snetchild {0x1102, 0x0008, 0x1102, 0x1000, "SB????", "Audigy 2 LS", HAS_AC97 | HAS_51 | IS_CA0108 | DIGITAL_ONLY}, 536160383Snetchild {0x1102, 0x0008, 0x1102, 0x1001, "SB0400", "Audigy 2 Value", HAS_AC97 | HAS_71 | IS_CA0108 | DIGITAL_ONLY}, 537160383Snetchild {0x1102, 0x0008, 0x1102, 0x1021, "SB0610", "Audigy 4", HAS_AC97 | HAS_71 | IS_CA0108 | DIGITAL_ONLY}, 538160383Snetchild 539160383Snetchild {0x1102, 0x0008, 0x1102, 0x2001, "SB0530", "Audigy 2 ZS CardBus", HAS_AC97 | HAS_71 | IS_CA0108 | IS_CARDBUS}, 540160383Snetchild 541160383Snetchild {0x1102, 0x0008, 0x0000, 0x0000, "SB????", "Audigy 2 Value (Unknown model)", HAS_AC97 | HAS_51 | IS_CA0108}, 542160383Snetchild}; 543160383Snetchild/* Unsupported cards */ 544160383Snetchild 545160383Snetchildstatic struct emu_hwinfo emu_bad_cards[] = { 546160383Snetchild /* APS cards should be possible to support */ 547160383Snetchild {0x1102, 0x0002, 0x1102, 0x4001, "EMUAPS", "E-mu APS", 0}, 548160383Snetchild {0x1102, 0x0002, 0x1102, 0x4002, "EMUAPS", "E-mu APS", 0}, 549160383Snetchild {0x1102, 0x0004, 0x1102, 0x4001, "EMU???", "E-mu 1212m [4001]", 0}, 550160383Snetchild /* Similar-named ("Live!" or "Audigy") cards on different chipsets */ 551160383Snetchild {0x1102, 0x8064, 0x0000, 0x0000, "SB0100", "SBLive! 5.1 OEM", 0}, 552160383Snetchild {0x1102, 0x0006, 0x0000, 0x0000, "SB0200", "DELL OEM SBLive! Value", 0}, 553160383Snetchild {0x1102, 0x0007, 0x0000, 0x0000, "SB0310", "Audigy LS", 0}, 554160383Snetchild}; 555160383Snetchild 556160383Snetchild/* 557160383Snetchild * Get best known information about device. 558160383Snetchild */ 559165833Snetchildstatic unsigned int 560160383Snetchildemu_getcard(device_t dev) 561160383Snetchild{ 562160383Snetchild uint16_t device; 563160383Snetchild uint16_t subdevice; 564160383Snetchild int n_cards; 565165833Snetchild unsigned int thiscard; 566160383Snetchild int i; 567160383Snetchild 568160383Snetchild device = pci_read_config(dev, PCIR_DEVICE, /* bytes */ 2); 569160383Snetchild subdevice = pci_read_config(dev, PCIR_SUBDEV_0, /* bytes */ 2); 570160383Snetchild 571160383Snetchild n_cards = sizeof(emu_cards) / sizeof(struct emu_hwinfo); 572165833Snetchild thiscard = 0; 573165833Snetchild for (i = 1; i < n_cards; i++) { 574160383Snetchild if (device == emu_cards[i].device) { 575160383Snetchild if (subdevice == emu_cards[i].subdevice) { 576160383Snetchild thiscard = i; 577160383Snetchild break; 578160383Snetchild } 579160383Snetchild if (0x0000 == emu_cards[i].subdevice) { 580160383Snetchild thiscard = i; 581172150Sariff /* 582172150Sariff * don't break, we can get more specific card 583172150Sariff * later in the list. 584172150Sariff */ 585160383Snetchild } 586160383Snetchild } 587160383Snetchild } 588160383Snetchild 589160383Snetchild n_cards = sizeof(emu_bad_cards) / sizeof(struct emu_hwinfo); 590160383Snetchild for (i = 0; i < n_cards; i++) { 591160383Snetchild if (device == emu_bad_cards[i].device) { 592160383Snetchild if (subdevice == emu_bad_cards[i].subdevice) { 593165833Snetchild thiscard = 0; 594160383Snetchild break; 595160383Snetchild } 596160383Snetchild if (0x0000 == emu_bad_cards[i].subdevice) { 597165833Snetchild thiscard = 0; 598160383Snetchild break; /* we avoid all this cards */ 599160383Snetchild } 600160383Snetchild } 601160383Snetchild } 602160383Snetchild return (thiscard); 603160383Snetchild} 604160383Snetchild 605160383Snetchild 606160383Snetchild/* 607160383Snetchild * Base hardware interface are 32 (Audigy) or 64 (Audigy2) registers. 608160383Snetchild * Some of them are used directly, some of them provide pointer / data pairs. 609160383Snetchild */ 610160383Snetchildstatic uint32_t 611160383Snetchildemu_rd_nolock(struct emu_sc_info *sc, unsigned int regno, unsigned int size) 612160383Snetchild{ 613160383Snetchild 614160383Snetchild KASSERT(sc != NULL, ("emu_rd: NULL sc")); 615160383Snetchild switch (size) { 616160383Snetchild case 1: 617160383Snetchild return (bus_space_read_1(sc->st, sc->sh, regno)); 618160383Snetchild case 2: 619160383Snetchild return (bus_space_read_2(sc->st, sc->sh, regno)); 620160383Snetchild case 4: 621160383Snetchild return (bus_space_read_4(sc->st, sc->sh, regno)); 622160383Snetchild } 623160383Snetchild return (0xffffffff); 624160383Snetchild} 625160383Snetchild 626160383Snetchildstatic void 627160383Snetchildemu_wr_nolock(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size) 628160383Snetchild{ 629160383Snetchild 630160383Snetchild KASSERT(sc != NULL, ("emu_rd: NULL sc")); 631160383Snetchild switch (size) { 632160383Snetchild case 1: 633160383Snetchild bus_space_write_1(sc->st, sc->sh, regno, data); 634160383Snetchild break; 635160383Snetchild case 2: 636160383Snetchild bus_space_write_2(sc->st, sc->sh, regno, data); 637160383Snetchild break; 638160383Snetchild case 4: 639160383Snetchild bus_space_write_4(sc->st, sc->sh, regno, data); 640160383Snetchild break; 641160383Snetchild } 642160383Snetchild} 643160383Snetchild/* 644229981Spfg * EMU_PTR / EMU_DATA interface. Access to EMU10Kx is made 645160383Snetchild * via (channel, register) pair. Some registers are channel-specific, 646160383Snetchild * some not. 647160383Snetchild */ 648160383Snetchilduint32_t 649160383Snetchildemu_rdptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg) 650160383Snetchild{ 651160383Snetchild uint32_t ptr, val, mask, size, offset; 652160383Snetchild 653229981Spfg ptr = ((reg << 16) & sc->address_mask) | (chn & EMU_PTR_CHNO_MASK); 654172150Sariff 655172150Sariff EMU_RWLOCK(); 656229981Spfg emu_wr_nolock(sc, EMU_PTR, ptr, 4); 657229981Spfg val = emu_rd_nolock(sc, EMU_DATA, 4); 658172150Sariff EMU_RWUNLOCK(); 659172150Sariff 660160383Snetchild /* 661160383Snetchild * XXX Some register numbers has data size and offset encoded in 662160383Snetchild * it to get only part of 32bit register. This use is not described 663160383Snetchild * in register name, be careful! 664160383Snetchild */ 665160383Snetchild if (reg & 0xff000000) { 666160383Snetchild size = (reg >> 24) & 0x3f; 667160383Snetchild offset = (reg >> 16) & 0x1f; 668160383Snetchild mask = ((1 << size) - 1) << offset; 669160383Snetchild val &= mask; 670160383Snetchild val >>= offset; 671160383Snetchild } 672160383Snetchild return (val); 673160383Snetchild} 674160383Snetchild 675160383Snetchildvoid 676160383Snetchildemu_wrptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg, uint32_t data) 677160383Snetchild{ 678160383Snetchild uint32_t ptr, mask, size, offset; 679172150Sariff 680229981Spfg ptr = ((reg << 16) & sc->address_mask) | (chn & EMU_PTR_CHNO_MASK); 681172150Sariff 682172150Sariff EMU_RWLOCK(); 683229981Spfg emu_wr_nolock(sc, EMU_PTR, ptr, 4); 684160383Snetchild /* 685160383Snetchild * XXX Another kind of magic encoding in register number. This can 686160383Snetchild * give you side effect - it will read previous data from register 687160383Snetchild * and change only required bits. 688160383Snetchild */ 689160383Snetchild if (reg & 0xff000000) { 690160383Snetchild size = (reg >> 24) & 0x3f; 691160383Snetchild offset = (reg >> 16) & 0x1f; 692160383Snetchild mask = ((1 << size) - 1) << offset; 693160383Snetchild data <<= offset; 694160383Snetchild data &= mask; 695229981Spfg data |= emu_rd_nolock(sc, EMU_DATA, 4) & ~mask; 696160383Snetchild } 697229981Spfg emu_wr_nolock(sc, EMU_DATA, data, 4); 698172150Sariff EMU_RWUNLOCK(); 699160383Snetchild} 700160383Snetchild/* 701229981Spfg * EMU_A2_PTR / EMU_DATA2 interface. Access to P16v is made 702160383Snetchild * via (channel, register) pair. Some registers are channel-specific, 703160383Snetchild * some not. This interface is supported by CA0102 and CA0108 chips only. 704160383Snetchild */ 705160383Snetchilduint32_t 706160383Snetchildemu_rd_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg) 707160383Snetchild{ 708160383Snetchild uint32_t val; 709160383Snetchild 710172150Sariff /* XXX separate lock? */ 711172150Sariff EMU_RWLOCK(); 712229981Spfg emu_wr_nolock(sc, EMU_A2_PTR, (reg << 16) | chn, 4); 713229981Spfg val = emu_rd_nolock(sc, EMU_DATA2, 4); 714172150Sariff 715172150Sariff EMU_RWUNLOCK(); 716172150Sariff 717160383Snetchild return (val); 718160383Snetchild} 719160383Snetchild 720160383Snetchildvoid 721160383Snetchildemu_wr_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg, uint32_t data) 722160383Snetchild{ 723160383Snetchild 724172150Sariff EMU_RWLOCK(); 725229981Spfg emu_wr_nolock(sc, EMU_A2_PTR, (reg << 16) | chn, 4); 726229981Spfg emu_wr_nolock(sc, EMU_DATA2, data, 4); 727172150Sariff EMU_RWUNLOCK(); 728160383Snetchild} 729160383Snetchild/* 730160383Snetchild * XXX CardBus interface. Not tested on any real hardware. 731160383Snetchild */ 732160383Snetchildstatic void 733160383Snetchildemu_wr_cbptr(struct emu_sc_info *sc, uint32_t data) 734160383Snetchild{ 735160383Snetchild uint32_t val; 736160383Snetchild 737172150Sariff /* 738172150Sariff * 0x38 is IPE3 (CD S/PDIF interrupt pending register) on CA0102. Seems 739160383Snetchild * to be some reg/value accessible kind of config register on CardBus 740172150Sariff * CA0108, with value(?) in top 16 bit, address(?) in low 16 741172150Sariff */ 742172150Sariff 743160383Snetchild val = emu_rd_nolock(sc, 0x38, 4); 744160383Snetchild emu_wr_nolock(sc, 0x38, data, 4); 745160383Snetchild val = emu_rd_nolock(sc, 0x38, 4); 746172150Sariff 747160383Snetchild} 748160383Snetchild 749160383Snetchild/* 750160383Snetchild * Direct hardware register access 751229981Spfg * Assume that it is never used to access EMU_PTR-based registers and can run unlocked. 752160383Snetchild */ 753160383Snetchildvoid 754160383Snetchildemu_wr(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size) 755160383Snetchild{ 756229981Spfg KASSERT(regno != EMU_PTR, ("emu_wr: attempt to write to EMU_PTR")); 757229981Spfg KASSERT(regno != EMU_A2_PTR, ("emu_wr: attempt to write to EMU_A2_PTR")); 758160383Snetchild 759160383Snetchild emu_wr_nolock(sc, regno, data, size); 760160383Snetchild} 761160383Snetchild 762160383Snetchilduint32_t 763160383Snetchildemu_rd(struct emu_sc_info *sc, unsigned int regno, unsigned int size) 764160383Snetchild{ 765160383Snetchild uint32_t rd; 766160383Snetchild 767229981Spfg KASSERT(regno != EMU_DATA, ("emu_rd: attempt to read DATA")); 768229981Spfg KASSERT(regno != EMU_DATA2, ("emu_rd: attempt to read DATA2")); 769172150Sariff 770160383Snetchild rd = emu_rd_nolock(sc, regno, size); 771160383Snetchild return (rd); 772160383Snetchild} 773160383Snetchild 774160383Snetchild/* 775160383Snetchild * Enabling IR MIDI messages is another kind of black magic. It just 776160383Snetchild * has to be made this way. It really do it. 777160383Snetchild */ 778160383Snetchildvoid 779160383Snetchildemu_enable_ir(struct emu_sc_info *sc) 780160383Snetchild{ 781160383Snetchild uint32_t iocfg; 782160383Snetchild 783160383Snetchild if (sc->is_emu10k2 || sc->is_ca0102) { 784229981Spfg iocfg = emu_rd_nolock(sc, EMU_A_IOCFG, 2); 785229981Spfg emu_wr_nolock(sc, EMU_A_IOCFG, iocfg | EMU_A_IOCFG_GPOUT2, 2); 786160383Snetchild DELAY(500); 787229981Spfg emu_wr_nolock(sc, EMU_A_IOCFG, iocfg | EMU_A_IOCFG_GPOUT1 | EMU_A_IOCFG_GPOUT2, 2); 788160383Snetchild DELAY(500); 789229981Spfg emu_wr_nolock(sc, EMU_A_IOCFG, iocfg | EMU_A_IOCFG_GPOUT1, 2); 790160383Snetchild DELAY(100); 791229981Spfg emu_wr_nolock(sc, EMU_A_IOCFG, iocfg, 2); 792160383Snetchild device_printf(sc->dev, "Audigy IR MIDI events enabled.\n"); 793160383Snetchild sc->enable_ir = 1; 794160383Snetchild } 795160383Snetchild if (sc->is_emu10k1) { 796229981Spfg iocfg = emu_rd_nolock(sc, EMU_HCFG, 4); 797229981Spfg emu_wr_nolock(sc, EMU_HCFG, iocfg | EMU_HCFG_GPOUT2, 4); 798160383Snetchild DELAY(500); 799229981Spfg emu_wr_nolock(sc, EMU_HCFG, iocfg | EMU_HCFG_GPOUT1 | EMU_HCFG_GPOUT2, 4); 800160383Snetchild DELAY(100); 801229981Spfg emu_wr_nolock(sc, EMU_HCFG, iocfg, 4); 802160383Snetchild device_printf(sc->dev, "SB Live! IR MIDI events enabled.\n"); 803160383Snetchild sc->enable_ir = 1; 804160383Snetchild } 805160383Snetchild} 806160383Snetchild 807160383Snetchild 808160383Snetchild/* 809230137Sjoel * emu_timer_ - HW timer management 810160383Snetchild */ 811160383Snetchildint 812160383Snetchildemu_timer_create(struct emu_sc_info *sc) 813160383Snetchild{ 814160383Snetchild int i, timer; 815160383Snetchild 816160383Snetchild timer = -1; 817172150Sariff 818172150Sariff mtx_lock(&sc->lock); 819160383Snetchild for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) 820160383Snetchild if (sc->timer[i] == 0) { 821160383Snetchild sc->timer[i] = -1; /* disable it */ 822160383Snetchild timer = i; 823172150Sariff mtx_unlock(&sc->lock); 824160383Snetchild return (timer); 825160383Snetchild } 826172150Sariff mtx_unlock(&sc->lock); 827160383Snetchild 828160383Snetchild return (-1); 829160383Snetchild} 830160383Snetchild 831160383Snetchildint 832160383Snetchildemu_timer_set(struct emu_sc_info *sc, int timer, int delay) 833160383Snetchild{ 834160383Snetchild int i; 835160383Snetchild 836172150Sariff if (timer < 0) 837165833Snetchild return (-1); 838165833Snetchild 839160383Snetchild RANGE(delay, 16, 1024); 840165833Snetchild RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1); 841160383Snetchild 842172150Sariff mtx_lock(&sc->lock); 843160383Snetchild sc->timer[timer] = delay; 844160383Snetchild for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) 845160383Snetchild if (sc->timerinterval > sc->timer[i]) 846160383Snetchild sc->timerinterval = sc->timer[i]; 847160383Snetchild 848172150Sariff /* XXX */ 849229981Spfg emu_wr(sc, EMU_TIMER, sc->timerinterval & 0x03ff, 2); 850172150Sariff mtx_unlock(&sc->lock); 851172150Sariff 852160383Snetchild return (timer); 853160383Snetchild} 854160383Snetchild 855160383Snetchildint 856160383Snetchildemu_timer_enable(struct emu_sc_info *sc, int timer, int go) 857160383Snetchild{ 858160383Snetchild uint32_t x; 859160383Snetchild int ena_int; 860160383Snetchild int i; 861160383Snetchild 862172150Sariff if (timer < 0) 863165833Snetchild return (-1); 864165833Snetchild 865165833Snetchild RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1); 866165833Snetchild 867160383Snetchild mtx_lock(&sc->lock); 868160383Snetchild 869160383Snetchild if ((go == 1) && (sc->timer[timer] < 0)) 870160383Snetchild sc->timer[timer] = -sc->timer[timer]; 871160383Snetchild if ((go == 0) && (sc->timer[timer] > 0)) 872160383Snetchild sc->timer[timer] = -sc->timer[timer]; 873160383Snetchild 874160383Snetchild ena_int = 0; 875160383Snetchild for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) { 876160383Snetchild if (sc->timerinterval > sc->timer[i]) 877160383Snetchild sc->timerinterval = sc->timer[i]; 878160383Snetchild if (sc->timer[i] > 0) 879160383Snetchild ena_int = 1; 880160383Snetchild } 881160383Snetchild 882229981Spfg emu_wr(sc, EMU_TIMER, sc->timerinterval & 0x03ff, 2); 883160383Snetchild 884160383Snetchild if (ena_int == 1) { 885229981Spfg x = emu_rd(sc, EMU_INTE, 4); 886229981Spfg x |= EMU_INTE_INTERTIMERENB; 887229981Spfg emu_wr(sc, EMU_INTE, x, 4); 888160383Snetchild } else { 889229981Spfg x = emu_rd(sc, EMU_INTE, 4); 890229981Spfg x &= ~EMU_INTE_INTERTIMERENB; 891229981Spfg emu_wr(sc, EMU_INTE, x, 4); 892160383Snetchild } 893160383Snetchild mtx_unlock(&sc->lock); 894160383Snetchild return (0); 895160383Snetchild} 896160383Snetchild 897160383Snetchildint 898160383Snetchildemu_timer_clear(struct emu_sc_info *sc, int timer) 899160383Snetchild{ 900172150Sariff if (timer < 0) 901165833Snetchild return (-1); 902165833Snetchild 903165833Snetchild RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1); 904165833Snetchild 905160383Snetchild emu_timer_enable(sc, timer, 0); 906160383Snetchild 907160383Snetchild mtx_lock(&sc->lock); 908160383Snetchild if (sc->timer[timer] != 0) 909160383Snetchild sc->timer[timer] = 0; 910160383Snetchild mtx_unlock(&sc->lock); 911160383Snetchild 912160383Snetchild return (timer); 913160383Snetchild} 914160383Snetchild 915160383Snetchild/* 916230137Sjoel * emu_intr_ - HW interrupt handler management 917160383Snetchild */ 918160383Snetchildint 919160383Snetchildemu_intr_register(struct emu_sc_info *sc, uint32_t inte_mask, uint32_t intr_mask, uint32_t(*func) (void *softc, uint32_t irq), void *isc) 920160383Snetchild{ 921160383Snetchild int i; 922160383Snetchild uint32_t x; 923160383Snetchild 924160383Snetchild mtx_lock(&sc->lock); 925160383Snetchild for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) 926160383Snetchild if (sc->ihandler[i].inte_mask == 0) { 927160383Snetchild sc->ihandler[i].inte_mask = inte_mask; 928160383Snetchild sc->ihandler[i].intr_mask = intr_mask; 929160383Snetchild sc->ihandler[i].softc = isc; 930160383Snetchild sc->ihandler[i].irq_func = func; 931229981Spfg x = emu_rd(sc, EMU_INTE, 4); 932160383Snetchild x |= inte_mask; 933229981Spfg emu_wr(sc, EMU_INTE, x, 4); 934160383Snetchild mtx_unlock(&sc->lock); 935172150Sariff if (sc->dbg_level > 1) 936172150Sariff device_printf(sc->dev, "ihandle %d registered\n", i); 937172150Sariff 938160383Snetchild return (i); 939160383Snetchild } 940160383Snetchild mtx_unlock(&sc->lock); 941172150Sariff if (sc->dbg_level > 1) 942172150Sariff device_printf(sc->dev, "ihandle not registered\n"); 943172150Sariff 944160383Snetchild return (-1); 945160383Snetchild} 946160383Snetchild 947160383Snetchildint 948160383Snetchildemu_intr_unregister(struct emu_sc_info *sc, int hnumber) 949160383Snetchild{ 950160383Snetchild uint32_t x; 951160383Snetchild int i; 952160383Snetchild 953160383Snetchild mtx_lock(&sc->lock); 954160383Snetchild 955160383Snetchild if (sc->ihandler[hnumber].inte_mask == 0) { 956160383Snetchild mtx_unlock(&sc->lock); 957160383Snetchild return (-1); 958160383Snetchild } 959160383Snetchild 960229981Spfg x = emu_rd(sc, EMU_INTE, 4); 961160383Snetchild x &= ~sc->ihandler[hnumber].inte_mask; 962160383Snetchild 963160383Snetchild sc->ihandler[hnumber].inte_mask = 0; 964160383Snetchild sc->ihandler[hnumber].intr_mask = 0; 965160383Snetchild sc->ihandler[hnumber].softc = NULL; 966160383Snetchild sc->ihandler[hnumber].irq_func = NULL; 967160383Snetchild 968229981Spfg /* other interrupt handlers may use this EMU_INTE value */ 969160383Snetchild for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) 970160383Snetchild if (sc->ihandler[i].inte_mask != 0) 971160383Snetchild x |= sc->ihandler[i].inte_mask; 972160383Snetchild 973229981Spfg emu_wr(sc, EMU_INTE, x, 4); 974160383Snetchild 975160383Snetchild mtx_unlock(&sc->lock); 976160383Snetchild return (hnumber); 977160383Snetchild} 978160383Snetchild 979160383Snetchildstatic void 980160383Snetchildemu_intr(void *p) 981160383Snetchild{ 982160383Snetchild struct emu_sc_info *sc = (struct emu_sc_info *)p; 983160383Snetchild uint32_t stat, ack; 984160383Snetchild int i; 985160383Snetchild 986160383Snetchild for (;;) { 987229981Spfg stat = emu_rd(sc, EMU_IPR, 4); 988160383Snetchild ack = 0; 989160383Snetchild if (stat == 0) 990160383Snetchild break; 991229981Spfg emu_wr(sc, EMU_IPR, stat, 4); 992160383Snetchild for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) { 993160383Snetchild if ((((sc->ihandler[i].intr_mask) & stat) != 0) && 994160383Snetchild (((void *)sc->ihandler[i].irq_func) != NULL)) { 995160383Snetchild ack |= sc->ihandler[i].irq_func(sc->ihandler[i].softc, 996160383Snetchild (sc->ihandler[i].intr_mask) & stat); 997160383Snetchild } 998160383Snetchild } 999172150Sariff if (sc->dbg_level > 1) 1000172150Sariff if (stat & (~ack)) 1001172150Sariff device_printf(sc->dev, "Unhandled interrupt: %08x\n", stat & (~ack)); 1002172150Sariff 1003160383Snetchild } 1004160383Snetchild 1005160383Snetchild if ((sc->is_ca0102) || (sc->is_ca0108)) 1006160383Snetchild for (;;) { 1007229981Spfg stat = emu_rd(sc, EMU_IPR2, 4); 1008160383Snetchild ack = 0; 1009160383Snetchild if (stat == 0) 1010160383Snetchild break; 1011229981Spfg emu_wr(sc, EMU_IPR2, stat, 4); 1012172150Sariff if (sc->dbg_level > 1) 1013229981Spfg device_printf(sc->dev, "EMU_IPR2: %08x\n", stat); 1014172150Sariff 1015230137Sjoel break; /* to avoid infinite loop. should be removed 1016160383Snetchild * after completion of P16V interface. */ 1017160383Snetchild } 1018160383Snetchild 1019160383Snetchild if (sc->is_ca0102) 1020160383Snetchild for (;;) { 1021229981Spfg stat = emu_rd(sc, EMU_IPR3, 4); 1022160383Snetchild ack = 0; 1023160383Snetchild if (stat == 0) 1024160383Snetchild break; 1025229981Spfg emu_wr(sc, EMU_IPR3, stat, 4); 1026172150Sariff if (sc->dbg_level > 1) 1027229981Spfg device_printf(sc->dev, "EMU_IPR3: %08x\n", stat); 1028172150Sariff 1029160383Snetchild break; /* to avoid infinite loop. should be removed 1030160383Snetchild * after completion of S/PDIF interface */ 1031160383Snetchild } 1032160383Snetchild} 1033160383Snetchild 1034160383Snetchild 1035160383Snetchild/* 1036160383Snetchild * Get data from private emu10kx structure for PCM buffer allocation. 1037160383Snetchild * Used by PCM code only. 1038160383Snetchild */ 1039160383Snetchildbus_dma_tag_t 1040160383Snetchildemu_gettag(struct emu_sc_info *sc) 1041160383Snetchild{ 1042160383Snetchild return (sc->mem.dmat); 1043160383Snetchild} 1044160383Snetchild 1045160383Snetchildstatic void 1046160383Snetchildemu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error) 1047160383Snetchild{ 1048160383Snetchild bus_addr_t *phys = (bus_addr_t *) arg; 1049160383Snetchild 1050160383Snetchild *phys = error ? 0 : (bus_addr_t) segs->ds_addr; 1051160383Snetchild 1052160383Snetchild if (bootverbose) { 1053160383Snetchild printf("emu10kx: setmap (%lx, %lx), nseg=%d, error=%d\n", 1054160383Snetchild (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len, 1055160383Snetchild nseg, error); 1056160383Snetchild } 1057160383Snetchild} 1058160383Snetchild 1059160383Snetchildstatic void * 1060160383Snetchildemu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr) 1061160383Snetchild{ 1062160383Snetchild void *dmabuf; 1063160383Snetchild bus_dmamap_t map; 1064172150Sariff int error; 1065160383Snetchild 1066160383Snetchild *addr = 0; 1067172150Sariff if ((error = bus_dmamem_alloc(mem->dmat, &dmabuf, BUS_DMA_NOWAIT, &map))) { 1068172150Sariff if (mem->card->dbg_level > 2) 1069172150Sariff device_printf(mem->card->dev, "emu_malloc: failed to alloc DMA map: %d\n", error); 1070160383Snetchild return (NULL); 1071172150Sariff } 1072172150Sariff if ((error = bus_dmamap_load(mem->dmat, map, dmabuf, sz, emu_setmap, addr, 0)) || !*addr) { 1073172150Sariff if (mem->card->dbg_level > 2) 1074172150Sariff device_printf(mem->card->dev, "emu_malloc: failed to load DMA memory: %d\n", error); 1075160383Snetchild return (NULL); 1076172150Sariff } 1077160383Snetchild return (dmabuf); 1078160383Snetchild} 1079160383Snetchild 1080160383Snetchildstatic void 1081160383Snetchildemu_free(struct emu_mem *mem, void *dmabuf) 1082160383Snetchild{ 1083160383Snetchild bus_dmamem_free(mem->dmat, dmabuf, NULL); 1084160383Snetchild} 1085160383Snetchild 1086160383Snetchildstatic void * 1087160383Snetchildemu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char *owner) 1088160383Snetchild{ 1089160383Snetchild uint32_t blksz, start, idx, ofs, tmp, found; 1090160383Snetchild struct emu_memblk *blk; 1091160383Snetchild void *membuf; 1092160383Snetchild 1093160383Snetchild blksz = sz / EMUPAGESIZE; 1094160383Snetchild if (sz > (blksz * EMUPAGESIZE)) 1095160383Snetchild blksz++; 1096172150Sariff if (blksz > EMU_MAX_BUFSZ / EMUPAGESIZE) { 1097172150Sariff if (mem->card->dbg_level > 2) 1098172150Sariff device_printf(mem->card->dev, "emu_memalloc: memory request tool large\n"); 1099161054Snetchild return (NULL); 1100172150Sariff } 1101160383Snetchild /* find a free block in the bitmap */ 1102160383Snetchild found = 0; 1103160383Snetchild start = 1; 1104161054Snetchild while (!found && start + blksz < EMU_MAXPAGES) { 1105160383Snetchild found = 1; 1106160383Snetchild for (idx = start; idx < start + blksz; idx++) 1107160383Snetchild if (mem->bmap[idx >> 3] & (1 << (idx & 7))) 1108160383Snetchild found = 0; 1109160383Snetchild if (!found) 1110160383Snetchild start++; 1111160383Snetchild } 1112172150Sariff if (!found) { 1113172150Sariff if (mem->card->dbg_level > 2) 1114172150Sariff device_printf(mem->card->dev, "emu_memalloc: no free space in bitmap\n"); 1115160383Snetchild return (NULL); 1116172150Sariff } 1117160383Snetchild blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT); 1118172150Sariff if (blk == NULL) { 1119172150Sariff if (mem->card->dbg_level > 2) 1120172150Sariff device_printf(mem->card->dev, "emu_memalloc: buffer allocation failed\n"); 1121160383Snetchild return (NULL); 1122172150Sariff } 1123160383Snetchild bzero(blk, sizeof(*blk)); 1124160383Snetchild membuf = emu_malloc(mem, sz, &blk->buf_addr); 1125160383Snetchild *addr = blk->buf_addr; 1126160383Snetchild if (membuf == NULL) { 1127172150Sariff if (mem->card->dbg_level > 2) 1128172150Sariff device_printf(mem->card->dev, "emu_memalloc: can't setup HW memory\n"); 1129160383Snetchild free(blk, M_DEVBUF); 1130160383Snetchild return (NULL); 1131160383Snetchild } 1132160383Snetchild blk->buf = membuf; 1133160383Snetchild blk->pte_start = start; 1134160383Snetchild blk->pte_size = blksz; 1135160383Snetchild strncpy(blk->owner, owner, 15); 1136160383Snetchild blk->owner[15] = '\0'; 1137160383Snetchild ofs = 0; 1138160383Snetchild for (idx = start; idx < start + blksz; idx++) { 1139160383Snetchild mem->bmap[idx >> 3] |= 1 << (idx & 7); 1140233362Sjhb tmp = (uint32_t) (blk->buf_addr + ofs); 1141160383Snetchild mem->ptb_pages[idx] = (tmp << 1) | idx; 1142160383Snetchild ofs += EMUPAGESIZE; 1143160383Snetchild } 1144160383Snetchild SLIST_INSERT_HEAD(&mem->blocks, blk, link); 1145160383Snetchild return (membuf); 1146160383Snetchild} 1147160383Snetchild 1148160383Snetchildstatic int 1149160383Snetchildemu_memfree(struct emu_mem *mem, void *membuf) 1150160383Snetchild{ 1151160383Snetchild uint32_t idx, tmp; 1152160383Snetchild struct emu_memblk *blk, *i; 1153160383Snetchild 1154160383Snetchild blk = NULL; 1155160383Snetchild SLIST_FOREACH(i, &mem->blocks, link) { 1156160383Snetchild if (i->buf == membuf) 1157160383Snetchild blk = i; 1158160383Snetchild } 1159160383Snetchild if (blk == NULL) 1160160383Snetchild return (EINVAL); 1161160383Snetchild SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link); 1162160383Snetchild emu_free(mem, membuf); 1163160383Snetchild tmp = (uint32_t) (mem->silent_page_addr) << 1; 1164160383Snetchild for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) { 1165160383Snetchild mem->bmap[idx >> 3] &= ~(1 << (idx & 7)); 1166160383Snetchild mem->ptb_pages[idx] = tmp | idx; 1167160383Snetchild } 1168160383Snetchild free(blk, M_DEVBUF); 1169160383Snetchild return (0); 1170160383Snetchild} 1171160383Snetchild 1172160383Snetchildstatic int 1173160383Snetchildemu_memstart(struct emu_mem *mem, void *membuf) 1174160383Snetchild{ 1175160383Snetchild struct emu_memblk *blk, *i; 1176160383Snetchild 1177160383Snetchild blk = NULL; 1178160383Snetchild SLIST_FOREACH(i, &mem->blocks, link) { 1179160383Snetchild if (i->buf == membuf) 1180160383Snetchild blk = i; 1181160383Snetchild } 1182160383Snetchild if (blk == NULL) 1183160383Snetchild return (-1); 1184160383Snetchild return (blk->pte_start); 1185160383Snetchild} 1186160383Snetchild 1187160383Snetchild 1188160383Snetchildstatic uint32_t 1189160383Snetchildemu_rate_to_pitch(uint32_t rate) 1190160383Snetchild{ 1191160383Snetchild static uint32_t logMagTable[128] = { 1192160383Snetchild 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2, 1193160383Snetchild 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5, 1194160383Snetchild 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081, 1195160383Snetchild 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191, 1196160383Snetchild 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, 1197160383Snetchild 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, 1198160383Snetchild 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e, 1199160383Snetchild 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26, 1200160383Snetchild 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d, 1201160383Snetchild 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885, 1202160383Snetchild 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, 1203160383Snetchild 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, 1204160383Snetchild 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, 1205160383Snetchild 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3, 1206160383Snetchild 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83, 1207160383Snetchild 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df 1208160383Snetchild }; 1209160383Snetchild static char logSlopeTable[128] = { 1210160383Snetchild 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58, 1211160383Snetchild 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53, 1212160383Snetchild 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f, 1213160383Snetchild 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b, 1214160383Snetchild 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47, 1215160383Snetchild 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44, 1216160383Snetchild 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41, 1217160383Snetchild 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e, 1218160383Snetchild 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, 1219160383Snetchild 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 1220160383Snetchild 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37, 1221160383Snetchild 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35, 1222160383Snetchild 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34, 1223160383Snetchild 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32, 1224160383Snetchild 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30, 1225160383Snetchild 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f 1226160383Snetchild }; 1227160383Snetchild int i; 1228160383Snetchild 1229160383Snetchild if (rate == 0) 1230160383Snetchild return (0); 1231160383Snetchild rate *= 11185; /* Scale 48000 to 0x20002380 */ 1232160383Snetchild for (i = 31; i > 0; i--) { 1233160383Snetchild if (rate & 0x80000000) { /* Detect leading "1" */ 1234160383Snetchild return (((uint32_t) (i - 15) << 20) + 1235160383Snetchild logMagTable[0x7f & (rate >> 24)] + 1236160383Snetchild (0x7f & (rate >> 17)) * 1237160383Snetchild logSlopeTable[0x7f & (rate >> 24)]); 1238160383Snetchild } 1239160383Snetchild rate <<= 1; 1240160383Snetchild } 1241160383Snetchild /* NOTREACHED */ 1242160383Snetchild return (0); 1243160383Snetchild} 1244160383Snetchild 1245160383Snetchildstatic uint32_t 1246160383Snetchildemu_rate_to_linearpitch(uint32_t rate) 1247160383Snetchild{ 1248160383Snetchild rate = (rate << 8) / 375; 1249160383Snetchild return ((rate >> 1) + (rate & 1)); 1250160383Snetchild} 1251160383Snetchild 1252160383Snetchildstruct emu_voice * 1253160383Snetchildemu_valloc(struct emu_sc_info *sc) 1254160383Snetchild{ 1255160383Snetchild struct emu_voice *v; 1256160383Snetchild int i; 1257160383Snetchild 1258160383Snetchild v = NULL; 1259160383Snetchild mtx_lock(&sc->lock); 1260160383Snetchild for (i = 0; i < NUM_G && sc->voice[i].busy; i++); 1261160383Snetchild if (i < NUM_G) { 1262160383Snetchild v = &sc->voice[i]; 1263160383Snetchild v->busy = 1; 1264160383Snetchild } 1265160383Snetchild mtx_unlock(&sc->lock); 1266160383Snetchild return (v); 1267160383Snetchild} 1268160383Snetchild 1269160383Snetchildvoid 1270160383Snetchildemu_vfree(struct emu_sc_info *sc, struct emu_voice *v) 1271160383Snetchild{ 1272160383Snetchild int i, r; 1273160383Snetchild 1274160383Snetchild mtx_lock(&sc->lock); 1275160383Snetchild for (i = 0; i < NUM_G; i++) { 1276160383Snetchild if (v == &sc->voice[i] && sc->voice[i].busy) { 1277160383Snetchild v->busy = 0; 1278172150Sariff /* 1279172150Sariff * XXX What we should do with mono channels? 1280172150Sariff * See -pcm.c emupchan_init for other side of 1281172150Sariff * this problem 1282172150Sariff */ 1283160383Snetchild if (v->slave != NULL) 1284160383Snetchild r = emu_memfree(&sc->mem, v->vbuf); 1285160383Snetchild } 1286160383Snetchild } 1287160383Snetchild mtx_unlock(&sc->lock); 1288160383Snetchild} 1289160383Snetchild 1290160383Snetchildint 1291160383Snetchildemu_vinit(struct emu_sc_info *sc, struct emu_voice *m, struct emu_voice *s, 1292160383Snetchild uint32_t sz, struct snd_dbuf *b) 1293160383Snetchild{ 1294160383Snetchild void *vbuf; 1295160383Snetchild bus_addr_t tmp_addr; 1296160383Snetchild 1297160383Snetchild vbuf = emu_memalloc(&sc->mem, sz, &tmp_addr, "vinit"); 1298172150Sariff if (vbuf == NULL) { 1299172150Sariff if(sc->dbg_level > 2) 1300172150Sariff device_printf(sc->dev, "emu_memalloc returns NULL in enu_vinit\n"); 1301160383Snetchild return (ENOMEM); 1302172150Sariff } 1303160383Snetchild if (b != NULL) 1304160383Snetchild sndbuf_setup(b, vbuf, sz); 1305160383Snetchild m->start = emu_memstart(&sc->mem, vbuf) * EMUPAGESIZE; 1306172150Sariff if (m->start < 0) { 1307172150Sariff if(sc->dbg_level > 2) 1308172150Sariff device_printf(sc->dev, "emu_memstart returns (-1) in enu_vinit\n"); 1309160383Snetchild emu_memfree(&sc->mem, vbuf); 1310160383Snetchild return (ENOMEM); 1311160383Snetchild } 1312160383Snetchild m->end = m->start + sz; 1313160383Snetchild m->speed = 0; 1314160383Snetchild m->b16 = 0; 1315160383Snetchild m->stereo = 0; 1316160383Snetchild m->running = 0; 1317160383Snetchild m->ismaster = 1; 1318160383Snetchild m->vol = 0xff; 1319160383Snetchild m->buf = tmp_addr; 1320160383Snetchild m->vbuf = vbuf; 1321160383Snetchild m->slave = s; 1322160383Snetchild if (s != NULL) { 1323160383Snetchild s->start = m->start; 1324160383Snetchild s->end = m->end; 1325160383Snetchild s->speed = 0; 1326160383Snetchild s->b16 = 0; 1327160383Snetchild s->stereo = 0; 1328160383Snetchild s->running = 0; 1329160383Snetchild s->ismaster = 0; 1330160383Snetchild s->vol = m->vol; 1331160383Snetchild s->buf = m->buf; 1332160383Snetchild s->vbuf = NULL; 1333160383Snetchild s->slave = NULL; 1334160383Snetchild } 1335160383Snetchild return (0); 1336160383Snetchild} 1337160383Snetchild 1338160383Snetchildvoid 1339160383Snetchildemu_vsetup(struct emu_voice *v, int fmt, int spd) 1340160383Snetchild{ 1341160383Snetchild if (fmt) { 1342160383Snetchild v->b16 = (fmt & AFMT_16BIT) ? 1 : 0; 1343193640Sariff v->stereo = (AFMT_CHANNEL(fmt) > 1) ? 1 : 0; 1344160383Snetchild if (v->slave != NULL) { 1345160383Snetchild v->slave->b16 = v->b16; 1346160383Snetchild v->slave->stereo = v->stereo; 1347160383Snetchild } 1348160383Snetchild } 1349160383Snetchild if (spd) { 1350160383Snetchild v->speed = spd; 1351160383Snetchild if (v->slave != NULL) 1352160383Snetchild v->slave->speed = v->speed; 1353160383Snetchild } 1354160383Snetchild} 1355160383Snetchild 1356160383Snetchildvoid 1357160383Snetchildemu_vroute(struct emu_sc_info *sc, struct emu_route *rt, struct emu_voice *v) 1358160383Snetchild{ 1359160383Snetchild int i; 1360160383Snetchild 1361160383Snetchild for (i = 0; i < 8; i++) { 1362172150Sariff v->routing[i] = rt->routing_left[i]; 1363172150Sariff v->amounts[i] = rt->amounts_left[i]; 1364160383Snetchild } 1365160383Snetchild if ((v->stereo) && (v->ismaster == 0)) 1366160383Snetchild for (i = 0; i < 8; i++) { 1367172150Sariff v->routing[i] = rt->routing_right[i]; 1368172150Sariff v->amounts[i] = rt->amounts_right[i]; 1369160383Snetchild } 1370160383Snetchild 1371160383Snetchild if ((v->stereo) && (v->slave != NULL)) 1372160383Snetchild emu_vroute(sc, rt, v->slave); 1373160383Snetchild} 1374160383Snetchild 1375160383Snetchildvoid 1376160383Snetchildemu_vwrite(struct emu_sc_info *sc, struct emu_voice *v) 1377160383Snetchild{ 1378160383Snetchild int s; 1379172150Sariff uint32_t start, val, silent_page; 1380160383Snetchild 1381160383Snetchild s = (v->stereo ? 1 : 0) + (v->b16 ? 1 : 0); 1382160383Snetchild 1383160383Snetchild v->sa = v->start >> s; 1384160383Snetchild v->ea = v->end >> s; 1385160383Snetchild 1386160383Snetchild 1387160383Snetchild if (v->stereo) { 1388229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CPF, EMU_CHAN_CPF_STEREO_MASK); 1389160383Snetchild } else { 1390229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CPF, 0); 1391160383Snetchild } 1392160383Snetchild val = v->stereo ? 28 : 30; 1393160383Snetchild val *= v->b16 ? 1 : 2; 1394160383Snetchild start = v->sa + val; 1395160383Snetchild 1396172150Sariff if (sc->is_emu10k1) { 1397229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_FXRT, ((v->routing[3] << 12) | 1398172150Sariff (v->routing[2] << 8) | 1399172150Sariff (v->routing[1] << 4) | 1400172150Sariff (v->routing[0] << 0)) << 16); 1401172150Sariff } else { 1402229981Spfg emu_wrptr(sc, v->vnum, EMU_A_CHAN_FXRT1, (v->routing[3] << 24) | 1403172150Sariff (v->routing[2] << 16) | 1404172150Sariff (v->routing[1] << 8) | 1405172150Sariff (v->routing[0] << 0)); 1406229981Spfg emu_wrptr(sc, v->vnum, EMU_A_CHAN_FXRT2, (v->routing[7] << 24) | 1407172150Sariff (v->routing[6] << 16) | 1408172150Sariff (v->routing[5] << 8) | 1409172150Sariff (v->routing[4] << 0)); 1410229981Spfg emu_wrptr(sc, v->vnum, EMU_A_CHAN_SENDAMOUNTS, (v->amounts[7] << 24) | 1411172150Sariff (v->amounts[6] << 26) | 1412172150Sariff (v->amounts[5] << 8) | 1413172150Sariff (v->amounts[4] << 0)); 1414172150Sariff } 1415229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_PTRX, (v->amounts[0] << 8) | (v->amounts[1] << 0)); 1416229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_DSL, v->ea | (v->amounts[3] << 24)); 1417229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_PSST, v->sa | (v->amounts[2] << 24)); 1418160383Snetchild 1419229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CCCA, start | (v->b16 ? 0 : EMU_CHAN_CCCA_8BITSELECT)); 1420229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_Z1, 0); 1421229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_Z2, 0); 1422160383Snetchild 1423229981Spfg silent_page = ((uint32_t) (sc->mem.silent_page_addr) << 1) | EMU_CHAN_MAP_PTI_MASK; 1424229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_MAPA, silent_page); 1425229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_MAPB, silent_page); 1426160383Snetchild 1427229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CVCF, EMU_CHAN_CVCF_CURRFILTER_MASK); 1428229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_VTFT, EMU_CHAN_VTFT_FILTERTARGET_MASK); 1429229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_ATKHLDM, 0); 1430229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_DCYSUSM, EMU_CHAN_DCYSUSM_DECAYTIME_MASK); 1431229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_LFOVAL1, 0x8000); 1432229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_LFOVAL2, 0x8000); 1433229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_FMMOD, 0); 1434229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_TREMFRQ, 0); 1435229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_FM2FRQ2, 0); 1436229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_ENVVAL, 0x8000); 1437160383Snetchild 1438229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_ATKHLDV, EMU_CHAN_ATKHLDV_HOLDTIME_MASK | EMU_CHAN_ATKHLDV_ATTACKTIME_MASK); 1439229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_ENVVOL, 0x8000); 1440160383Snetchild 1441229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_PEFE_FILTERAMOUNT, 0x7f); 1442229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_PEFE_PITCHAMOUNT, 0); 1443160383Snetchild if ((v->stereo) && (v->slave != NULL)) 1444160383Snetchild emu_vwrite(sc, v->slave); 1445160383Snetchild} 1446160383Snetchild 1447160383Snetchildstatic void 1448160383Snetchildemu_vstop(struct emu_sc_info *sc, char channel, int enable) 1449160383Snetchild{ 1450160383Snetchild int reg; 1451160383Snetchild 1452229981Spfg reg = (channel & 0x20) ? EMU_SOLEH : EMU_SOLEL; 1453160383Snetchild channel &= 0x1f; 1454160383Snetchild reg |= 1 << 24; 1455160383Snetchild reg |= channel << 16; 1456160383Snetchild emu_wrptr(sc, 0, reg, enable); 1457160383Snetchild} 1458160383Snetchild 1459160383Snetchildvoid 1460160383Snetchildemu_vtrigger(struct emu_sc_info *sc, struct emu_voice *v, int go) 1461160383Snetchild{ 1462160383Snetchild uint32_t pitch_target, initial_pitch; 1463160383Snetchild uint32_t cra, cs, ccis; 1464160383Snetchild uint32_t sample, i; 1465160383Snetchild 1466160383Snetchild if (go) { 1467160383Snetchild cra = 64; 1468160383Snetchild cs = v->stereo ? 4 : 2; 1469160383Snetchild ccis = v->stereo ? 28 : 30; 1470160383Snetchild ccis *= v->b16 ? 1 : 2; 1471160383Snetchild sample = v->b16 ? 0x00000000 : 0x80808080; 1472160383Snetchild for (i = 0; i < cs; i++) 1473229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CD0 + i, sample); 1474229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CCR_CACHEINVALIDSIZE, 0); 1475229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CCR_READADDRESS, cra); 1476229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CCR_CACHEINVALIDSIZE, ccis); 1477160383Snetchild 1478229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_IFATN, 0xff00); 1479229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_VTFT, 0xffffffff); 1480229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CVCF, 0xffffffff); 1481229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_DCYSUSV, 0x00007f7f); 1482160383Snetchild emu_vstop(sc, v->vnum, 0); 1483160383Snetchild 1484160383Snetchild pitch_target = emu_rate_to_linearpitch(v->speed); 1485160383Snetchild initial_pitch = emu_rate_to_pitch(v->speed) >> 8; 1486229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_PTRX_PITCHTARGET, pitch_target); 1487229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CPF_PITCH, pitch_target); 1488229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_IP, initial_pitch); 1489160383Snetchild } else { 1490229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_PTRX_PITCHTARGET, 0); 1491229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CPF_PITCH, 0); 1492229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_IFATN, 0xffff); 1493229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_VTFT, 0x0000ffff); 1494229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_CVCF, 0x0000ffff); 1495229981Spfg emu_wrptr(sc, v->vnum, EMU_CHAN_IP, 0); 1496160383Snetchild emu_vstop(sc, v->vnum, 1); 1497160383Snetchild } 1498160383Snetchild if ((v->stereo) && (v->slave != NULL)) 1499160383Snetchild emu_vtrigger(sc, v->slave, go); 1500160383Snetchild} 1501160383Snetchild 1502160383Snetchildint 1503160383Snetchildemu_vpos(struct emu_sc_info *sc, struct emu_voice *v) 1504160383Snetchild{ 1505160383Snetchild int s, ptr; 1506160383Snetchild 1507160383Snetchild s = (v->b16 ? 1 : 0) + (v->stereo ? 1 : 0); 1508229981Spfg ptr = (emu_rdptr(sc, v->vnum, EMU_CHAN_CCCA_CURRADDR) - (v->start >> s)) << s; 1509160383Snetchild return (ptr & ~0x0000001f); 1510160383Snetchild} 1511160383Snetchild 1512160383Snetchild 1513160383Snetchild/* fx */ 1514160383Snetchildstatic void 1515160383Snetchildemu_wrefx(struct emu_sc_info *sc, unsigned int pc, unsigned int data) 1516160383Snetchild{ 1517160383Snetchild emu_wrptr(sc, 0, sc->code_base + pc, data); 1518160383Snetchild} 1519160383Snetchild 1520160383Snetchild 1521160383Snetchildstatic void 1522160383Snetchildemu_addefxop(struct emu_sc_info *sc, unsigned int op, unsigned int z, unsigned int w, unsigned int x, unsigned int y, uint32_t * pc) 1523160383Snetchild{ 1524160383Snetchild if ((*pc) + 1 > sc->code_size) { 1525160383Snetchild device_printf(sc->dev, "DSP CODE OVERRUN: attept to write past code_size (pc=%d)\n", (*pc)); 1526160383Snetchild return; 1527160383Snetchild } 1528160383Snetchild emu_wrefx(sc, (*pc) * 2, (x << sc->high_operand_shift) | y); 1529160383Snetchild emu_wrefx(sc, (*pc) * 2 + 1, (op << sc->opcode_shift) | (z << sc->high_operand_shift) | w); 1530160383Snetchild (*pc)++; 1531160383Snetchild} 1532160383Snetchild 1533160383Snetchildstatic int 1534160383Snetchildsysctl_emu_mixer_control(SYSCTL_HANDLER_ARGS) 1535160383Snetchild{ 1536160383Snetchild struct emu_sc_info *sc; 1537160383Snetchild int mixer_id; 1538160383Snetchild int new_vol; 1539160383Snetchild int err; 1540160383Snetchild 1541160383Snetchild sc = arg1; 1542160383Snetchild mixer_id = arg2; 1543160383Snetchild 1544160383Snetchild new_vol = emumix_get_volume(sc, mixer_id); 1545170289Sdwmalone err = sysctl_handle_int(oidp, &new_vol, 0, req); 1546160383Snetchild 1547160383Snetchild if (err || req->newptr == NULL) 1548160383Snetchild return (err); 1549160383Snetchild if (new_vol < 0 || new_vol > 100) 1550160383Snetchild return (EINVAL); 1551160383Snetchild emumix_set_volume(sc, mixer_id, new_vol); 1552160383Snetchild 1553160383Snetchild return (0); 1554160383Snetchild} 1555160383Snetchild 1556160383Snetchildstatic int 1557160383Snetchildemu_addefxmixer(struct emu_sc_info *sc, const char *mix_name, const int mix_id, uint32_t defvolume) 1558160383Snetchild{ 1559160383Snetchild int volgpr; 1560160438Snetchild char sysctl_name[32]; 1561160383Snetchild 1562160383Snetchild volgpr = emu_rm_gpr_alloc(sc->rm, 1); 1563160383Snetchild emumix_set_fxvol(sc, volgpr, defvolume); 1564172150Sariff /* 1565172150Sariff * Mixer controls with NULL mix_name are handled 1566172150Sariff * by AC97 emulation code or PCM mixer. 1567172150Sariff */ 1568160383Snetchild if (mix_name != NULL) { 1569172150Sariff /* 1570172150Sariff * Temporary sysctls should start with underscore, 1571160438Snetchild * see freebsd-current mailing list, emu10kx driver 1572172150Sariff * discussion around 2006-05-24. 1573172150Sariff */ 1574160438Snetchild snprintf(sysctl_name, 32, "_%s", mix_name); 1575160383Snetchild SYSCTL_ADD_PROC(sc->ctx, 1576160383Snetchild SYSCTL_CHILDREN(sc->root), 1577160438Snetchild OID_AUTO, sysctl_name, 1578160383Snetchild CTLTYPE_INT | CTLFLAG_RW, sc, mix_id, 1579172150Sariff sysctl_emu_mixer_control, "I", ""); 1580160383Snetchild } 1581160383Snetchild 1582160383Snetchild return (volgpr); 1583160383Snetchild} 1584160383Snetchild 1585172150Sariffstatic int 1586172150Sariffsysctl_emu_digitalswitch_control(SYSCTL_HANDLER_ARGS) 1587172150Sariff{ 1588172150Sariff struct emu_sc_info *sc; 1589172150Sariff int new_val; 1590172150Sariff int err; 1591172150Sariff 1592172150Sariff sc = arg1; 1593172150Sariff 1594172150Sariff new_val = (sc->mode == MODE_DIGITAL) ? 1 : 0; 1595172150Sariff err = sysctl_handle_int(oidp, &new_val, 0, req); 1596172150Sariff 1597172150Sariff if (err || req->newptr == NULL) 1598172150Sariff return (err); 1599172150Sariff if (new_val < 0 || new_val > 1) 1600172150Sariff return (EINVAL); 1601172150Sariff 1602172150Sariff switch (new_val) { 1603172150Sariff case 0: 1604172150Sariff emumix_set_mode(sc, MODE_ANALOG); 1605172150Sariff break; 1606172150Sariff case 1: 1607172150Sariff emumix_set_mode(sc, MODE_DIGITAL); 1608172150Sariff break; 1609172150Sariff } 1610172150Sariff return (0); 1611172150Sariff} 1612172150Sariff 1613172150Sariffstatic void 1614172150Sariffemu_digitalswitch(struct emu_sc_info *sc) 1615172150Sariff{ 1616172150Sariff /* XXX temporary? */ 1617172150Sariff SYSCTL_ADD_PROC(sc->ctx, 1618172150Sariff SYSCTL_CHILDREN(sc->root), 1619172150Sariff OID_AUTO, "_digital", 1620172150Sariff CTLTYPE_INT | CTLFLAG_RW, sc, 0, 1621172150Sariff sysctl_emu_digitalswitch_control, "I", "Enable digital output"); 1622172150Sariff 1623172150Sariff return; 1624172150Sariff} 1625172150Sariff 1626172150Sariff/* 1627172150Sariff * Allocate cache GPRs that will hold mixed output channels 1628160383Snetchild * and clear it on every DSP run. 1629160383Snetchild */ 1630160383Snetchild#define EFX_CACHE(CACHE_IDX) do { \ 1631160383Snetchild sc->cache_gpr[CACHE_IDX] = emu_rm_gpr_alloc(sc->rm, 1); \ 1632160383Snetchild emu_addefxop(sc, ACC3, \ 1633160383Snetchild GPR(sc->cache_gpr[CACHE_IDX]), \ 1634160383Snetchild DSP_CONST(0), \ 1635160383Snetchild DSP_CONST(0), \ 1636160383Snetchild DSP_CONST(0), \ 1637160383Snetchild &pc); \ 1638160383Snetchild} while (0) 1639160383Snetchild 1640160383Snetchild/* Allocate GPR for volume control and route sound: OUT = OUT + IN * VOL */ 1641160383Snetchild#define EFX_ROUTE(TITLE, INP_NR, IN_GPR_IDX, OUT_CACHE_IDX, DEF) do { \ 1642160383Snetchild sc->mixer_gpr[IN_GPR_IDX] = emu_addefxmixer(sc, TITLE, IN_GPR_IDX, DEF); \ 1643160383Snetchild sc->mixer_volcache[IN_GPR_IDX] = DEF; \ 1644160383Snetchild emu_addefxop(sc, MACS, \ 1645160383Snetchild GPR(sc->cache_gpr[OUT_CACHE_IDX]), \ 1646160383Snetchild GPR(sc->cache_gpr[OUT_CACHE_IDX]), \ 1647160383Snetchild INP_NR, \ 1648160383Snetchild GPR(sc->mixer_gpr[IN_GPR_IDX]), \ 1649160383Snetchild &pc); \ 1650160383Snetchild} while (0) 1651160383Snetchild 1652160383Snetchild/* allocate GPR, OUT = IN * VOL */ 1653172150Sariff#define EFX_OUTPUT(TITLE, OUT_CACHE_IDX, OUT_GPR_IDX, OUTP_NR, DEF) do { \ 1654160383Snetchild sc->mixer_gpr[OUT_GPR_IDX] = emu_addefxmixer(sc, TITLE, OUT_GPR_IDX, DEF); \ 1655160383Snetchild sc->mixer_volcache[OUT_GPR_IDX] = DEF; \ 1656160383Snetchild emu_addefxop(sc, MACS, \ 1657160383Snetchild OUTP(OUTP_NR), \ 1658160383Snetchild DSP_CONST(0), \ 1659160383Snetchild GPR(sc->cache_gpr[OUT_CACHE_IDX]), \ 1660160383Snetchild GPR(sc->mixer_gpr[OUT_GPR_IDX]), \ 1661160383Snetchild &pc); \ 1662160383Snetchild} while (0) 1663160383Snetchild 1664160383Snetchild/* like EFX_OUTPUT, but don't allocate mixer gpr */ 1665172150Sariff#define EFX_OUTPUTD(OUT_CACHE_IDX, OUT_GPR_IDX, OUTP_NR) do { \ 1666160383Snetchild emu_addefxop(sc, MACS, \ 1667160383Snetchild OUTP(OUTP_NR), \ 1668160383Snetchild DSP_CONST(0), \ 1669160383Snetchild GPR(sc->cache_gpr[OUT_CACHE_IDX]), \ 1670160383Snetchild GPR(sc->mixer_gpr[OUT_GPR_IDX]), \ 1671160383Snetchild &pc); \ 1672172150Sariff} while (0) 1673160383Snetchild 1674172150Sariff/* skip next OPCOUNT instructions if FLAG != 0 */ 1675172150Sariff#define EFX_SKIP(OPCOUNT, FLAG_GPR) do { \ 1676172150Sariff emu_addefxop(sc, MACS, \ 1677172150Sariff DSP_CONST(0), \ 1678172150Sariff GPR(sc->mute_gpr[FLAG_GPR]), \ 1679172150Sariff DSP_CONST(0), \ 1680172150Sariff DSP_CONST(0), \ 1681172150Sariff &pc); \ 1682172150Sariff emu_addefxop(sc, SKIP, \ 1683172150Sariff DSP_CCR, \ 1684172150Sariff DSP_CCR, \ 1685172150Sariff COND_NEQ_ZERO, \ 1686172150Sariff OPCOUNT, \ 1687172150Sariff &pc); \ 1688172150Sariff} while (0) 1689165833Snetchild 1690172150Sariff#define EFX_COPY(TO, FROM) do { \ 1691172150Sariff emu_addefxop(sc, ACC3, \ 1692172150Sariff TO, \ 1693165833Snetchild DSP_CONST(0), \ 1694165833Snetchild DSP_CONST(0), \ 1695172150Sariff FROM, \ 1696165833Snetchild &pc); \ 1697165833Snetchild} while (0) 1698165833Snetchild 1699165833Snetchild 1700160383Snetchildstatic void 1701160383Snetchildemu_initefx(struct emu_sc_info *sc) 1702160383Snetchild{ 1703165833Snetchild unsigned int i; 1704160383Snetchild uint32_t pc; 1705160383Snetchild 1706160383Snetchild /* stop DSP */ 1707160383Snetchild if (sc->is_emu10k1) { 1708229981Spfg emu_wrptr(sc, 0, EMU_DBG, EMU_DBG_SINGLE_STEP); 1709160383Snetchild } else { 1710229981Spfg emu_wrptr(sc, 0, EMU_A_DBG, EMU_A_DBG_SINGLE_STEP); 1711160383Snetchild } 1712160383Snetchild 1713160383Snetchild /* code size is in instructions */ 1714160383Snetchild pc = 0; 1715165833Snetchild for (i = 0; i < sc->code_size; i++) { 1716160383Snetchild if (sc->is_emu10k1) { 1717160383Snetchild emu_addefxop(sc, ACC3, DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0x0), &pc); 1718160383Snetchild } else { 1719160383Snetchild emu_addefxop(sc, SKIP, DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0xf), DSP_CONST(0x0), &pc); 1720160383Snetchild } 1721160383Snetchild } 1722160383Snetchild 1723172150Sariff /* allocate GPRs for mute switches (EFX_SKIP). Mute by default */ 1724172150Sariff for (i = 0; i < NUM_MUTE; i++) { 1725172150Sariff sc->mute_gpr[i] = emu_rm_gpr_alloc(sc->rm, 1); 1726172150Sariff emumix_set_gpr(sc, sc->mute_gpr[i], 1); 1727172150Sariff } 1728172150Sariff emu_digitalswitch(sc); 1729172150Sariff 1730160383Snetchild pc = 0; 1731160383Snetchild 1732172150Sariff /* 1733160383Snetchild * DSP code below is not good, because: 1734160383Snetchild * 1. It can be written smaller, if it can use DSP accumulator register 1735160383Snetchild * instead of cache_gpr[]. 1736160383Snetchild * 2. It can be more careful when volume is 100%, because in DSP 1737160383Snetchild * x*0x7fffffff may not be equal to x ! 1738160383Snetchild */ 1739160383Snetchild 1740160383Snetchild /* clean outputs */ 1741165833Snetchild for (i = 0; i < 16 ; i++) { 1742165833Snetchild emu_addefxop(sc, ACC3, OUTP(i), DSP_CONST(0), DSP_CONST(0), DSP_CONST(0), &pc); 1743160383Snetchild } 1744160383Snetchild 1745160383Snetchild 1746160383Snetchild if (sc->is_emu10k1) { 1747160383Snetchild EFX_CACHE(C_FRONT_L); 1748160383Snetchild EFX_CACHE(C_FRONT_R); 1749160383Snetchild EFX_CACHE(C_REC_L); 1750160383Snetchild EFX_CACHE(C_REC_R); 1751160383Snetchild 1752160383Snetchild /* fx0 to front/record, 100%/muted by default */ 1753160383Snetchild EFX_ROUTE("pcm_front_l", FX(0), M_FX0_FRONT_L, C_FRONT_L, 100); 1754160383Snetchild EFX_ROUTE("pcm_front_r", FX(1), M_FX1_FRONT_R, C_FRONT_R, 100); 1755172150Sariff EFX_ROUTE(NULL, FX(0), M_FX0_REC_L, C_REC_L, 0); 1756172150Sariff EFX_ROUTE(NULL, FX(1), M_FX1_REC_R, C_REC_R, 0); 1757160383Snetchild 1758160383Snetchild /* in0, from AC97 codec output */ 1759160383Snetchild EFX_ROUTE("ac97_front_l", INP(IN_AC97_L), M_IN0_FRONT_L, C_FRONT_L, 0); 1760160383Snetchild EFX_ROUTE("ac97_front_r", INP(IN_AC97_R), M_IN0_FRONT_R, C_FRONT_R, 0); 1761160383Snetchild EFX_ROUTE("ac97_rec_l", INP(IN_AC97_L), M_IN0_REC_L, C_REC_L, 0); 1762160383Snetchild EFX_ROUTE("ac97_rec_r", INP(IN_AC97_R), M_IN0_REC_R, C_REC_R, 0); 1763160383Snetchild 1764160383Snetchild /* in1, from CD S/PDIF */ 1765172150Sariff /* XXX EFX_SKIP 4 assumes that each EFX_ROUTE is one DSP op */ 1766172150Sariff EFX_SKIP(4, CDSPDIFMUTE); 1767172150Sariff EFX_ROUTE(NULL, INP(IN_SPDIF_CD_L), M_IN1_FRONT_L, C_FRONT_L, 0); 1768172150Sariff EFX_ROUTE(NULL, INP(IN_SPDIF_CD_R), M_IN1_FRONT_R, C_FRONT_R, 0); 1769172150Sariff EFX_ROUTE(NULL, INP(IN_SPDIF_CD_L), M_IN1_REC_L, C_REC_L, 0); 1770172150Sariff EFX_ROUTE(NULL, INP(IN_SPDIF_CD_R), M_IN1_REC_R, C_REC_R, 0); 1771172150Sariff 1772172150Sariff if (sc->dbg_level > 0) { 1773172150Sariff /* in2, ZoomVide (???) */ 1774172150Sariff EFX_ROUTE("zoom_front_l", INP(IN_ZOOM_L), M_IN2_FRONT_L, C_FRONT_L, 0); 1775172150Sariff EFX_ROUTE("zoom_front_r", INP(IN_ZOOM_R), M_IN2_FRONT_R, C_FRONT_R, 0); 1776172150Sariff EFX_ROUTE("zoom_rec_l", INP(IN_ZOOM_L), M_IN2_REC_L, C_REC_L, 0); 1777172150Sariff EFX_ROUTE("zoom_rec_r", INP(IN_ZOOM_R), M_IN2_REC_R, C_REC_R, 0); 1778172150Sariff } 1779172150Sariff 1780172150Sariff /* in3, TOSLink */ 1781172150Sariff EFX_ROUTE(NULL, INP(IN_TOSLINK_L), M_IN3_FRONT_L, C_FRONT_L, 0); 1782172150Sariff EFX_ROUTE(NULL, INP(IN_TOSLINK_R), M_IN3_FRONT_R, C_FRONT_R, 0); 1783172150Sariff EFX_ROUTE(NULL, INP(IN_TOSLINK_L), M_IN3_REC_L, C_REC_L, 0); 1784172150Sariff EFX_ROUTE(NULL, INP(IN_TOSLINK_R), M_IN3_REC_R, C_REC_R, 0); 1785160383Snetchild /* in4, LineIn */ 1786172150Sariff EFX_ROUTE(NULL, INP(IN_LINE1_L), M_IN4_FRONT_L, C_FRONT_L, 0); 1787172150Sariff EFX_ROUTE(NULL, INP(IN_LINE1_R), M_IN4_FRONT_R, C_FRONT_R, 0); 1788172150Sariff EFX_ROUTE(NULL, INP(IN_LINE1_L), M_IN4_REC_L, C_REC_L, 0); 1789172150Sariff EFX_ROUTE(NULL, INP(IN_LINE1_R), M_IN4_REC_R, C_REC_R, 0); 1790160383Snetchild 1791160383Snetchild /* in5, on-card S/PDIF */ 1792172150Sariff EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_L), M_IN5_FRONT_L, C_FRONT_L, 0); 1793172150Sariff EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_R), M_IN5_FRONT_R, C_FRONT_R, 0); 1794172150Sariff EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_L), M_IN5_REC_L, C_REC_L, 0); 1795172150Sariff EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_R), M_IN5_REC_R, C_REC_R, 0); 1796160383Snetchild 1797160383Snetchild /* in6, Line2 on Live!Drive */ 1798172150Sariff EFX_ROUTE(NULL, INP(IN_LINE2_L), M_IN6_FRONT_L, C_FRONT_L, 0); 1799172150Sariff EFX_ROUTE(NULL, INP(IN_LINE2_R), M_IN6_FRONT_R, C_FRONT_R, 0); 1800172150Sariff EFX_ROUTE(NULL, INP(IN_LINE2_L), M_IN6_REC_L, C_REC_L, 0); 1801172150Sariff EFX_ROUTE(NULL, INP(IN_LINE2_R), M_IN6_REC_R, C_REC_R, 0); 1802172150Sariff 1803172150Sariff if (sc->dbg_level > 0) { 1804172150Sariff /* in7, unknown */ 1805172150Sariff EFX_ROUTE("in7_front_l", INP(0xE), M_IN7_FRONT_L, C_FRONT_L, 0); 1806172150Sariff EFX_ROUTE("in7_front_r", INP(0xF), M_IN7_FRONT_R, C_FRONT_R, 0); 1807172150Sariff EFX_ROUTE("in7_rec_l", INP(0xE), M_IN7_REC_L, C_REC_L, 0); 1808172150Sariff EFX_ROUTE("in7_rec_r", INP(0xF), M_IN7_REC_R, C_REC_R, 0); 1809172150Sariff } 1810172150Sariff 1811172150Sariff /* analog and digital */ 1812160383Snetchild EFX_OUTPUT("master_front_l", C_FRONT_L, M_MASTER_FRONT_L, OUT_AC97_L, 100); 1813160383Snetchild EFX_OUTPUT("master_front_r", C_FRONT_R, M_MASTER_FRONT_R, OUT_AC97_R, 100); 1814172150Sariff /* S/PDIF */ 1815172150Sariff EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, OUT_TOSLINK_L); 1816172150Sariff EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, OUT_TOSLINK_R); 1817172150Sariff /* Headphones */ 1818165833Snetchild EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, OUT_HEADPHONE_L); 1819165833Snetchild EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, OUT_HEADPHONE_R); 1820160383Snetchild 1821160383Snetchild /* rec output to "ADC" */ 1822160383Snetchild EFX_OUTPUT("master_rec_l", C_REC_L, M_MASTER_REC_L, OUT_ADC_REC_L, 100); 1823160383Snetchild EFX_OUTPUT("master_rec_r", C_REC_R, M_MASTER_REC_R, OUT_ADC_REC_R, 100); 1824160383Snetchild 1825172150Sariff if (!(sc->mch_disabled)) { 1826172150Sariff /* 1827172150Sariff * Additional channel volume is controlled by mixer in 1828172150Sariff * emu_dspmixer_set() in -pcm.c 1829172150Sariff */ 1830160383Snetchild 1831172150Sariff /* fx2/3 (pcm1) to rear */ 1832172150Sariff EFX_CACHE(C_REAR_L); 1833172150Sariff EFX_CACHE(C_REAR_R); 1834172150Sariff EFX_ROUTE(NULL, FX(2), M_FX2_REAR_L, C_REAR_L, 100); 1835172150Sariff EFX_ROUTE(NULL, FX(3), M_FX3_REAR_R, C_REAR_R, 100); 1836172150Sariff 1837172150Sariff EFX_OUTPUT(NULL, C_REAR_L, M_MASTER_REAR_L, OUT_REAR_L, 100); 1838172150Sariff EFX_OUTPUT(NULL, C_REAR_R, M_MASTER_REAR_R, OUT_REAR_R, 100); 1839172150Sariff if (sc->has_51) { 1840172150Sariff /* fx4 (pcm2) to center */ 1841172150Sariff EFX_CACHE(C_CENTER); 1842172150Sariff EFX_ROUTE(NULL, FX(4), M_FX4_CENTER, C_CENTER, 100); 1843172150Sariff EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, OUT_D_CENTER, 100); 1844172150Sariff 1845172150Sariff /* XXX in digital mode (default) this should be muted because 1846172150Sariff this output is shared with digital out */ 1847172150Sariff EFX_SKIP(1, ANALOGMUTE); 1848172150Sariff EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, OUT_A_CENTER); 1849172150Sariff 1850172150Sariff /* fx5 (pcm3) to sub */ 1851172150Sariff EFX_CACHE(C_SUB); 1852172150Sariff EFX_ROUTE(NULL, FX(5), M_FX5_SUBWOOFER, C_SUB, 100); 1853172150Sariff EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, OUT_D_SUB, 100); 1854172150Sariff 1855172150Sariff /* XXX in digital mode (default) this should be muted because 1856172150Sariff this output is shared with digital out */ 1857172150Sariff EFX_SKIP(1, ANALOGMUTE); 1858172150Sariff EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, OUT_A_SUB); 1859172150Sariff 1860172150Sariff } 1861172150Sariff } else { 1862172150Sariff /* SND_EMU10KX_MULTICHANNEL_DISABLED */ 1863172150Sariff EFX_OUTPUT(NULL, C_FRONT_L, M_MASTER_REAR_L, OUT_REAR_L, 57); /* 75%*75% */ 1864172150Sariff EFX_OUTPUT(NULL, C_FRONT_R, M_MASTER_REAR_R, OUT_REAR_R, 57); /* 75%*75% */ 1865172150Sariff 1866165833Snetchild#if 0 1867172150Sariff /* XXX 5.1 does not work */ 1868172150Sariff 1869172150Sariff if (sc->has_51) { 1870172150Sariff /* (fx0+fx1)/2 to center */ 1871172150Sariff EFX_CACHE(C_CENTER); 1872172150Sariff emu_addefxop(sc, MACS, 1873172150Sariff GPR(sc->cache_gpr[C_CENTER]), 1874172150Sariff GPR(sc->cache_gpr[C_CENTER]), 1875172150Sariff DSP_CONST(0xd), /* = 1/2 */ 1876172150Sariff GPR(sc->cache_gpr[C_FRONT_L]), 1877172150Sariff &pc); 1878172150Sariff emu_addefxop(sc, MACS, 1879172150Sariff GPR(sc->cache_gpr[C_CENTER]), 1880172150Sariff GPR(sc->cache_gpr[C_CENTER]), 1881172150Sariff DSP_CONST(0xd), /* = 1/2 */ 1882172150Sariff GPR(sc->cache_gpr[C_FRONT_R]), 1883172150Sariff &pc); 1884172150Sariff EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, OUT_D_CENTER, 100); 1885172150Sariff 1886172150Sariff /* XXX in digital mode (default) this should be muted because 1887172150Sariff this output is shared with digital out */ 1888172150Sariff EFX_SKIP(1, ANALOGMUTE); 1889172150Sariff EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, OUT_A_CENTER); 1890172150Sariff 1891172150Sariff /* (fx0+fx1)/2 to sub */ 1892172150Sariff EFX_CACHE(C_SUB); 1893172150Sariff emu_addefxop(sc, MACS, 1894172150Sariff GPR(sc->cache_gpr[C_CENTER]), 1895172150Sariff GPR(sc->cache_gpr[C_CENTER]), 1896172150Sariff DSP_CONST(0xd), /* = 1/2 */ 1897172150Sariff GPR(sc->cache_gpr[C_FRONT_L]), 1898172150Sariff &pc); 1899172150Sariff emu_addefxop(sc, MACS, 1900172150Sariff GPR(sc->cache_gpr[C_CENTER]), 1901172150Sariff GPR(sc->cache_gpr[C_CENTER]), 1902172150Sariff DSP_CONST(0xd), /* = 1/2 */ 1903172150Sariff GPR(sc->cache_gpr[C_FRONT_R]), 1904172150Sariff &pc); 1905172150Sariff /* XXX add lowpass filter here */ 1906172150Sariff 1907172150Sariff EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, OUT_D_SUB, 100); 1908172150Sariff 1909172150Sariff /* XXX in digital mode (default) this should be muted because 1910172150Sariff this output is shared with digital out */ 1911172150Sariff EFX_SKIP(1, ANALOGMUTE); 1912172150Sariff EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, OUT_A_SUB); 1913172150Sariff } 1914165833Snetchild#endif 1915172150Sariff } /* !mch_disabled */ 1916172150Sariff if (sc->mch_rec) { 1917172150Sariff /* 1918172150Sariff * MCH RECORDING , hight 16 slots. On 5.1 cards first 4 slots 1919172150Sariff * are used as outputs and already filled with data 1920172150Sariff */ 1921172150Sariff /* 1922172150Sariff * XXX On Live! cards stream does not begin at zero offset. 1923172150Sariff * It can be HW, driver or sound buffering problem. 1924172150Sariff * Use sync substream (offset 0x3E) to let userland find 1925172150Sariff * correct data. 1926172150Sariff */ 1927165833Snetchild 1928172150Sariff /* 1929172150Sariff * Substream map (in byte offsets, each substream is 2 bytes): 1930172150Sariff * 0x00..0x1E - outputs 1931249587Sgabor * 0x20..0x3E - FX, inputs and sync stream 1932172150Sariff */ 1933172150Sariff 1934172150Sariff /* First 2 channels (offset 0x20,0x22) are empty */ 1935172150Sariff for(i = (sc->has_51 ? 2 : 0); i < 2; i++) 1936172150Sariff EFX_COPY(FX2(i), DSP_CONST(0)); 1937172150Sariff 1938172150Sariff /* PCM Playback monitoring, offset 0x24..0x2A */ 1939172150Sariff for(i = 0; i < 4; i++) 1940172150Sariff EFX_COPY(FX2(i+2), FX(i)); 1941172150Sariff 1942172150Sariff /* Copy of some inputs, offset 0x2C..0x3C */ 1943172150Sariff for(i = 0; i < 9; i++) 1944172150Sariff EFX_COPY(FX2(i+8), INP(i)); 1945172150Sariff 1946172150Sariff /* sync data (0xc0de, offset 0x3E) */ 1947172150Sariff sc->dummy_gpr = emu_rm_gpr_alloc(sc->rm, 1); 1948172150Sariff emumix_set_gpr(sc, sc->dummy_gpr, 0xc0de0000); 1949172150Sariff 1950172150Sariff EFX_COPY(FX2(15), GPR(sc->dummy_gpr)); 1951172150Sariff } /* mch_rec */ 1952160383Snetchild } else /* emu10k2 and later */ { 1953160383Snetchild EFX_CACHE(C_FRONT_L); 1954160383Snetchild EFX_CACHE(C_FRONT_R); 1955160383Snetchild EFX_CACHE(C_REC_L); 1956160383Snetchild EFX_CACHE(C_REC_R); 1957160383Snetchild 1958160383Snetchild /* fx0 to front/record, 100%/muted by default */ 1959160383Snetchild /* 1960160383Snetchild * FRONT_[L|R] is controlled by AC97 emulation in 1961160383Snetchild * emu_ac97_[read|write]_emulation in -pcm.c 1962160383Snetchild */ 1963160383Snetchild EFX_ROUTE(NULL, FX(0), M_FX0_FRONT_L, C_FRONT_L, 100); 1964160383Snetchild EFX_ROUTE(NULL, FX(1), M_FX1_FRONT_R, C_FRONT_R, 100); 1965172150Sariff EFX_ROUTE(NULL, FX(0), M_FX0_REC_L, C_REC_L, 0); 1966172150Sariff EFX_ROUTE(NULL, FX(1), M_FX1_REC_R, C_REC_R, 0); 1967160383Snetchild 1968160383Snetchild /* in0, from AC97 codec output */ 1969172150Sariff EFX_ROUTE(NULL, INP(A_IN_AC97_L), M_IN0_FRONT_L, C_FRONT_L, 100); 1970172150Sariff EFX_ROUTE(NULL, INP(A_IN_AC97_R), M_IN0_FRONT_R, C_FRONT_R, 100); 1971172150Sariff EFX_ROUTE(NULL, INP(A_IN_AC97_L), M_IN0_REC_L, C_REC_L, 0); 1972172150Sariff EFX_ROUTE(NULL, INP(A_IN_AC97_R), M_IN0_REC_R, C_REC_R, 0); 1973160383Snetchild 1974160383Snetchild /* in1, from CD S/PDIF */ 1975172150Sariff EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_L), M_IN1_FRONT_L, C_FRONT_L, 0); 1976172150Sariff EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_R), M_IN1_FRONT_R, C_FRONT_R, 0); 1977172150Sariff EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_L), M_IN1_REC_L, C_REC_L, 0); 1978172150Sariff EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_R), M_IN1_REC_R, C_REC_R, 0); 1979160383Snetchild 1980160383Snetchild /* in2, optical & coax S/PDIF on AudigyDrive*/ 1981165833Snetchild /* XXX Should be muted when GPRSCS valid stream == 0 */ 1982172150Sariff EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_L), M_IN2_FRONT_L, C_FRONT_L, 0); 1983172150Sariff EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_R), M_IN2_FRONT_R, C_FRONT_R, 0); 1984172150Sariff EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_L), M_IN2_REC_L, C_REC_L, 0); 1985172150Sariff EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_R), M_IN2_REC_R, C_REC_R, 0); 1986172150Sariff 1987172150Sariff if (sc->dbg_level > 0) { 1988172150Sariff /* in3, unknown */ 1989172150Sariff EFX_ROUTE("in3_front_l", INP(0x6), M_IN3_FRONT_L, C_FRONT_L, 0); 1990172150Sariff EFX_ROUTE("in3_front_r", INP(0x7), M_IN3_FRONT_R, C_FRONT_R, 0); 1991172150Sariff EFX_ROUTE("in3_rec_l", INP(0x6), M_IN3_REC_L, C_REC_L, 0); 1992172150Sariff EFX_ROUTE("in3_rec_r", INP(0x7), M_IN3_REC_R, C_REC_R, 0); 1993172150Sariff } 1994172150Sariff 1995160383Snetchild /* in4, LineIn 2 on AudigyDrive */ 1996172150Sariff EFX_ROUTE(NULL, INP(A_IN_LINE2_L), M_IN4_FRONT_L, C_FRONT_L, 0); 1997172150Sariff EFX_ROUTE(NULL, INP(A_IN_LINE2_R), M_IN4_FRONT_R, C_FRONT_R, 0); 1998172150Sariff EFX_ROUTE(NULL, INP(A_IN_LINE2_L), M_IN4_REC_L, C_REC_L, 0); 1999172150Sariff EFX_ROUTE(NULL, INP(A_IN_LINE2_R), M_IN4_REC_R, C_REC_R, 0); 2000160383Snetchild 2001160383Snetchild /* in5, on-card S/PDIF */ 2002172150Sariff EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_L), M_IN5_FRONT_L, C_FRONT_L, 0); 2003172150Sariff EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_R), M_IN5_FRONT_R, C_FRONT_R, 0); 2004172150Sariff EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_L), M_IN5_REC_L, C_REC_L, 0); 2005172150Sariff EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_R), M_IN5_REC_R, C_REC_R, 0); 2006160383Snetchild 2007160383Snetchild /* in6, AUX2 on AudigyDrive */ 2008172150Sariff EFX_ROUTE(NULL, INP(A_IN_AUX2_L), M_IN6_FRONT_L, C_FRONT_L, 0); 2009172150Sariff EFX_ROUTE(NULL, INP(A_IN_AUX2_R), M_IN6_FRONT_R, C_FRONT_R, 0); 2010172150Sariff EFX_ROUTE(NULL, INP(A_IN_AUX2_L), M_IN6_REC_L, C_REC_L, 0); 2011172150Sariff EFX_ROUTE(NULL, INP(A_IN_AUX2_R), M_IN6_REC_R, C_REC_R, 0); 2012172150Sariff 2013172150Sariff if (sc->dbg_level > 0) { 2014172150Sariff /* in7, unknown */ 2015172150Sariff EFX_ROUTE("in7_front_l", INP(0xE), M_IN7_FRONT_L, C_FRONT_L, 0); 2016172150Sariff EFX_ROUTE("in7_front_r", INP(0xF), M_IN7_FRONT_R, C_FRONT_R, 0); 2017172150Sariff EFX_ROUTE("in7_rec_l", INP(0xE), M_IN7_REC_L, C_REC_L, 0); 2018172150Sariff EFX_ROUTE("in7_rec_r", INP(0xF), M_IN7_REC_R, C_REC_R, 0); 2019172150Sariff } 2020172150Sariff 2021160383Snetchild /* front output to headphones and alog and digital *front */ 2022160383Snetchild /* volume controlled by AC97 emulation */ 2023160383Snetchild EFX_OUTPUT(NULL, C_FRONT_L, M_MASTER_FRONT_L, A_OUT_A_FRONT_L, 100); 2024160383Snetchild EFX_OUTPUT(NULL, C_FRONT_R, M_MASTER_FRONT_R, A_OUT_A_FRONT_R, 100); 2025160383Snetchild EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_D_FRONT_L); 2026160383Snetchild EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_D_FRONT_R); 2027160383Snetchild EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_HPHONE_L); 2028160383Snetchild EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_HPHONE_R); 2029160383Snetchild 2030160383Snetchild /* rec output to "ADC" */ 2031160383Snetchild /* volume controlled by AC97 emulation */ 2032160383Snetchild EFX_OUTPUT(NULL, C_REC_L, M_MASTER_REC_L, A_OUT_ADC_REC_L, 100); 2033161057Snetchild EFX_OUTPUT(NULL, C_REC_R, M_MASTER_REC_R, A_OUT_ADC_REC_R, 100); 2034160383Snetchild 2035172150Sariff if (!(sc->mch_disabled)) { 2036172150Sariff /* 2037172150Sariff * Additional channel volume is controlled by mixer in 2038172150Sariff * emu_dspmixer_set() in -pcm.c 2039172150Sariff */ 2040160383Snetchild 2041172150Sariff /* fx2/3 (pcm1) to rear */ 2042172150Sariff EFX_CACHE(C_REAR_L); 2043172150Sariff EFX_CACHE(C_REAR_R); 2044172150Sariff EFX_ROUTE(NULL, FX(2), M_FX2_REAR_L, C_REAR_L, 100); 2045172150Sariff EFX_ROUTE(NULL, FX(3), M_FX3_REAR_R, C_REAR_R, 100); 2046160383Snetchild 2047172150Sariff EFX_OUTPUT(NULL, C_REAR_L, M_MASTER_REAR_L, A_OUT_A_REAR_L, 100); 2048172150Sariff EFX_OUTPUT(NULL, C_REAR_R, M_MASTER_REAR_R, A_OUT_A_REAR_R, 100); 2049172150Sariff EFX_OUTPUTD(C_REAR_L, M_MASTER_REAR_L, A_OUT_D_REAR_L); 2050172150Sariff EFX_OUTPUTD(C_REAR_R, M_MASTER_REAR_R, A_OUT_D_REAR_R); 2051172150Sariff 2052172150Sariff /* fx4 (pcm2) to center */ 2053172150Sariff EFX_CACHE(C_CENTER); 2054172150Sariff EFX_ROUTE(NULL, FX(4), M_FX4_CENTER, C_CENTER, 100); 2055172150Sariff EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, A_OUT_D_CENTER, 100); 2056160383Snetchild#if 0 2057172150Sariff /* 2058172150Sariff * XXX in digital mode (default) this should be muted 2059172150Sariff * because this output is shared with digital out 2060172150Sariff */ 2061172150Sariff EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, A_OUT_A_CENTER); 2062160383Snetchild#endif 2063172150Sariff /* fx5 (pcm3) to sub */ 2064172150Sariff EFX_CACHE(C_SUB); 2065172150Sariff EFX_ROUTE(NULL, FX(5), M_FX5_SUBWOOFER, C_SUB, 100); 2066172150Sariff EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, A_OUT_D_SUB, 100); 2067160383Snetchild#if 0 2068172150Sariff /* 2069172150Sariff * XXX in digital mode (default) this should be muted 2070172150Sariff * because this output is shared with digital out 2071172150Sariff */ 2072172150Sariff EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, A_OUT_A_SUB); 2073160383Snetchild#endif 2074172150Sariff if (sc->has_71) { 2075172150Sariff /* XXX this will broke headphones on AudigyDrive */ 2076172150Sariff /* fx6/7 (pcm4) to side */ 2077172150Sariff EFX_CACHE(C_SIDE_L); 2078172150Sariff EFX_CACHE(C_SIDE_R); 2079172150Sariff EFX_ROUTE(NULL, FX(6), M_FX6_SIDE_L, C_SIDE_L, 100); 2080172150Sariff EFX_ROUTE(NULL, FX(7), M_FX7_SIDE_R, C_SIDE_R, 100); 2081172150Sariff EFX_OUTPUT(NULL, C_SIDE_L, M_MASTER_SIDE_L, A_OUT_A_SIDE_L, 100); 2082172150Sariff EFX_OUTPUT(NULL, C_SIDE_R, M_MASTER_SIDE_R, A_OUT_A_SIDE_R, 100); 2083172150Sariff EFX_OUTPUTD(C_SIDE_L, M_MASTER_SIDE_L, A_OUT_D_SIDE_L); 2084172150Sariff EFX_OUTPUTD(C_SIDE_R, M_MASTER_SIDE_R, A_OUT_D_SIDE_R); 2085172150Sariff } 2086172150Sariff } else { /* mch_disabled */ 2087172150Sariff EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_A_REAR_L); 2088172150Sariff EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_A_REAR_R); 2089160383Snetchild 2090172150Sariff EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_D_REAR_L); 2091172150Sariff EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_D_REAR_R); 2092172150Sariff 2093172150Sariff if (sc->has_51) { 2094172150Sariff /* (fx0+fx1)/2 to center */ 2095172150Sariff EFX_CACHE(C_CENTER); 2096172150Sariff emu_addefxop(sc, MACS, 2097172150Sariff GPR(sc->cache_gpr[C_CENTER]), 2098172150Sariff GPR(sc->cache_gpr[C_CENTER]), 2099172150Sariff DSP_CONST(0xd), /* = 1/2 */ 2100172150Sariff GPR(sc->cache_gpr[C_FRONT_L]), 2101172150Sariff &pc); 2102172150Sariff emu_addefxop(sc, MACS, 2103172150Sariff GPR(sc->cache_gpr[C_CENTER]), 2104172150Sariff GPR(sc->cache_gpr[C_CENTER]), 2105172150Sariff DSP_CONST(0xd), /* = 1/2 */ 2106172150Sariff GPR(sc->cache_gpr[C_FRONT_R]), 2107172150Sariff &pc); 2108172150Sariff EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, A_OUT_D_CENTER, 100); 2109172150Sariff 2110172150Sariff /* XXX in digital mode (default) this should be muted because 2111172150Sariff this output is shared with digital out */ 2112172150Sariff EFX_SKIP(1, ANALOGMUTE); 2113172150Sariff EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, A_OUT_A_CENTER); 2114172150Sariff 2115172150Sariff /* (fx0+fx1)/2 to sub */ 2116172150Sariff EFX_CACHE(C_SUB); 2117172150Sariff emu_addefxop(sc, MACS, 2118172150Sariff GPR(sc->cache_gpr[C_SUB]), 2119172150Sariff GPR(sc->cache_gpr[C_SUB]), 2120172150Sariff DSP_CONST(0xd), /* = 1/2 */ 2121172150Sariff GPR(sc->cache_gpr[C_FRONT_L]), 2122172150Sariff &pc); 2123172150Sariff emu_addefxop(sc, MACS, 2124172150Sariff GPR(sc->cache_gpr[C_SUB]), 2125172150Sariff GPR(sc->cache_gpr[C_SUB]), 2126172150Sariff DSP_CONST(0xd), /* = 1/2 */ 2127172150Sariff GPR(sc->cache_gpr[C_FRONT_R]), 2128172150Sariff &pc); 2129172150Sariff /* XXX add lowpass filter here */ 2130172150Sariff 2131172150Sariff EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, A_OUT_D_SUB, 100); 2132172150Sariff 2133172150Sariff /* XXX in digital mode (default) this should be muted because 2134172150Sariff this output is shared with digital out */ 2135172150Sariff EFX_SKIP(1, ANALOGMUTE); 2136172150Sariff EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, A_OUT_A_SUB); 2137172150Sariff } 2138172150Sariff } /* mch_disabled */ 2139172150Sariff if (sc->mch_rec) { 2140172150Sariff /* MCH RECORDING, high 32 slots */ 2141172150Sariff 2142172150Sariff /* 2143172150Sariff * Stream map (in byte offsets): 2144172150Sariff * 0x00..0x3E - outputs 2145172150Sariff * 0x40..0x7E - FX, inputs 2146172150Sariff * each substream is 2 bytes. 2147172150Sariff */ 2148172150Sariff /* 2149172150Sariff * XXX Audigy 2 Value cards (and, possibly, 2150172150Sariff * Audigy 4) write some unknown data in place of 2151172150Sariff * some outputs (offsets 0x20..0x3F) and one 2152172150Sariff * input (offset 0x7E). 2153172150Sariff */ 2154172150Sariff 2155172150Sariff /* PCM Playback monitoring, offsets 0x40..0x5E */ 2156172150Sariff for(i = 0; i < 16; i++) 2157172150Sariff EFX_COPY(FX2(i), FX(i)); 2158172150Sariff 2159172150Sariff /* Copy of all inputs, offsets 0x60..0x7E */ 2160172150Sariff for(i = 0; i < 16; i++) 2161172150Sariff EFX_COPY(FX2(i+16), INP(i)); 2162172150Sariff#if 0 2163172150Sariff /* XXX Audigy seems to work correct and does not need this */ 2164172150Sariff /* sync data (0xc0de), offset 0x7E */ 2165172150Sariff sc->dummy_gpr = emu_rm_gpr_alloc(sc->rm, 1); 2166172150Sariff emumix_set_gpr(sc, sc->dummy_gpr, 0xc0de0000); 2167172150Sariff EFX_COPY(FX2(31), GPR(sc->dummy_gpr)); 2168160383Snetchild#endif 2169172150Sariff } /* mch_rec */ 2170160383Snetchild } 2171160383Snetchild 2172160383Snetchild sc->routing_code_end = pc; 2173160383Snetchild 2174160383Snetchild /* start DSP */ 2175160383Snetchild if (sc->is_emu10k1) { 2176229981Spfg emu_wrptr(sc, 0, EMU_DBG, 0); 2177160383Snetchild } else { 2178229981Spfg emu_wrptr(sc, 0, EMU_A_DBG, 0); 2179160383Snetchild } 2180160383Snetchild} 2181160383Snetchild 2182160383Snetchild/* /dev/em10kx */ 2183160383Snetchildstatic d_open_t emu10kx_open; 2184160383Snetchildstatic d_close_t emu10kx_close; 2185160383Snetchildstatic d_read_t emu10kx_read; 2186160383Snetchild 2187160383Snetchildstatic struct cdevsw emu10kx_cdevsw = { 2188160383Snetchild .d_open = emu10kx_open, 2189160383Snetchild .d_close = emu10kx_close, 2190160383Snetchild .d_read = emu10kx_read, 2191160383Snetchild .d_name = "emu10kx", 2192160383Snetchild .d_version = D_VERSION, 2193160383Snetchild}; 2194160383Snetchild 2195160383Snetchild 2196160383Snetchildstatic int 2197160383Snetchildemu10kx_open(struct cdev *i_dev, int flags __unused, int mode __unused, struct thread *td __unused) 2198160383Snetchild{ 2199160383Snetchild int error; 2200160383Snetchild struct emu_sc_info *sc; 2201160383Snetchild 2202160383Snetchild sc = i_dev->si_drv1; 2203160383Snetchild mtx_lock(&sc->emu10kx_lock); 2204160383Snetchild if (sc->emu10kx_isopen) { 2205160383Snetchild mtx_unlock(&sc->emu10kx_lock); 2206160383Snetchild return (EBUSY); 2207160383Snetchild } 2208160383Snetchild sc->emu10kx_isopen = 1; 2209160383Snetchild mtx_unlock(&sc->emu10kx_lock); 2210160383Snetchild if (sbuf_new(&sc->emu10kx_sbuf, NULL, 4096, 0) == NULL) { 2211160383Snetchild error = ENXIO; 2212160383Snetchild goto out; 2213160383Snetchild } 2214160383Snetchild sc->emu10kx_bufptr = 0; 2215160383Snetchild error = (emu10kx_prepare(sc, &sc->emu10kx_sbuf) > 0) ? 0 : ENOMEM; 2216160383Snetchildout: 2217160383Snetchild if (error) { 2218160383Snetchild mtx_lock(&sc->emu10kx_lock); 2219160383Snetchild sc->emu10kx_isopen = 0; 2220160383Snetchild mtx_unlock(&sc->emu10kx_lock); 2221160383Snetchild } 2222160383Snetchild return (error); 2223160383Snetchild} 2224160383Snetchild 2225160383Snetchildstatic int 2226160383Snetchildemu10kx_close(struct cdev *i_dev, int flags __unused, int mode __unused, struct thread *td __unused) 2227160383Snetchild{ 2228160383Snetchild struct emu_sc_info *sc; 2229160383Snetchild 2230160383Snetchild sc = i_dev->si_drv1; 2231160383Snetchild 2232160383Snetchild mtx_lock(&sc->emu10kx_lock); 2233160383Snetchild if (!(sc->emu10kx_isopen)) { 2234160383Snetchild mtx_unlock(&sc->emu10kx_lock); 2235160383Snetchild return (EBADF); 2236160383Snetchild } 2237160383Snetchild sbuf_delete(&sc->emu10kx_sbuf); 2238160383Snetchild sc->emu10kx_isopen = 0; 2239160383Snetchild mtx_unlock(&sc->emu10kx_lock); 2240160383Snetchild 2241160383Snetchild return (0); 2242160383Snetchild} 2243160383Snetchild 2244160383Snetchildstatic int 2245160383Snetchildemu10kx_read(struct cdev *i_dev, struct uio *buf, int flag __unused) 2246160383Snetchild{ 2247160383Snetchild int l, err; 2248160383Snetchild struct emu_sc_info *sc; 2249160383Snetchild 2250160383Snetchild sc = i_dev->si_drv1; 2251160383Snetchild mtx_lock(&sc->emu10kx_lock); 2252160383Snetchild if (!(sc->emu10kx_isopen)) { 2253160383Snetchild mtx_unlock(&sc->emu10kx_lock); 2254160383Snetchild return (EBADF); 2255160383Snetchild } 2256160383Snetchild mtx_unlock(&sc->emu10kx_lock); 2257160383Snetchild 2258160383Snetchild l = min(buf->uio_resid, sbuf_len(&sc->emu10kx_sbuf) - sc->emu10kx_bufptr); 2259160383Snetchild err = (l > 0) ? uiomove(sbuf_data(&sc->emu10kx_sbuf) + sc->emu10kx_bufptr, l, buf) : 0; 2260160383Snetchild sc->emu10kx_bufptr += l; 2261160383Snetchild 2262160383Snetchild return (err); 2263160383Snetchild} 2264160383Snetchild 2265160383Snetchildstatic int 2266160383Snetchildemu10kx_prepare(struct emu_sc_info *sc, struct sbuf *s) 2267160383Snetchild{ 2268160383Snetchild int i; 2269160383Snetchild 2270160383Snetchild sbuf_printf(s, "FreeBSD EMU10Kx Audio Driver\n"); 2271160383Snetchild sbuf_printf(s, "\nHardware resource usage:\n"); 2272160383Snetchild sbuf_printf(s, "DSP General Purpose Registers: %d used, %d total\n", sc->rm->num_used, sc->rm->num_gprs); 2273160383Snetchild sbuf_printf(s, "DSP Instruction Registers: %d used, %d total\n", sc->routing_code_end, sc->code_size); 2274160383Snetchild sbuf_printf(s, "Card supports"); 2275160383Snetchild if (sc->has_ac97) { 2276160383Snetchild sbuf_printf(s, " AC97 codec"); 2277160383Snetchild } else { 2278160383Snetchild sbuf_printf(s, " NO AC97 codec"); 2279160383Snetchild } 2280160383Snetchild if (sc->has_51) { 2281160383Snetchild if (sc->has_71) 2282160383Snetchild sbuf_printf(s, " and 7.1 output"); 2283160383Snetchild else 2284160383Snetchild sbuf_printf(s, " and 5.1 output"); 2285160383Snetchild } 2286160383Snetchild if (sc->is_emu10k1) 2287160383Snetchild sbuf_printf(s, ", SBLive! DSP code"); 2288160383Snetchild if (sc->is_emu10k2) 2289160383Snetchild sbuf_printf(s, ", Audigy DSP code"); 2290160383Snetchild if (sc->is_ca0102) 2291160383Snetchild sbuf_printf(s, ", Audigy DSP code with Audigy2 hacks"); 2292160383Snetchild if (sc->is_ca0108) 2293160383Snetchild sbuf_printf(s, ", Audigy DSP code with Audigy2Value hacks"); 2294160383Snetchild sbuf_printf(s, "\n"); 2295160383Snetchild if (sc->broken_digital) 2296160383Snetchild sbuf_printf(s, "Digital mode unsupported\n"); 2297160383Snetchild sbuf_printf(s, "\nInstalled devices:\n"); 2298165833Snetchild for (i = 0; i < RT_COUNT; i++) 2299160383Snetchild if (sc->pcm[i] != NULL) 2300160383Snetchild if (device_is_attached(sc->pcm[i])) { 2301160383Snetchild sbuf_printf(s, "%s on %s\n", device_get_desc(sc->pcm[i]), device_get_nameunit(sc->pcm[i])); 2302160383Snetchild } 2303160383Snetchild if (sc->midi[0] != NULL) 2304160383Snetchild if (device_is_attached(sc->midi[0])) { 2305160383Snetchild sbuf_printf(s, "EMU10Kx MIDI Interface\n"); 2306160383Snetchild sbuf_printf(s, "\tOn-card connector on %s\n", device_get_nameunit(sc->midi[0])); 2307160383Snetchild } 2308160383Snetchild if (sc->midi[1] != NULL) 2309160383Snetchild if (device_is_attached(sc->midi[1])) { 2310160383Snetchild sbuf_printf(s, "\tOn-Drive connector on %s\n", device_get_nameunit(sc->midi[1])); 2311160383Snetchild } 2312160383Snetchild if (sc->midi[0] != NULL) 2313160383Snetchild if (device_is_attached(sc->midi[0])) { 2314160383Snetchild sbuf_printf(s, "\tIR reciever MIDI events %s\n", sc->enable_ir ? "enabled" : "disabled"); 2315160383Snetchild } 2316172150Sariff sbuf_printf(s, "Card is in %s mode\n", (sc->mode == MODE_ANALOG) ? "analog" : "digital"); 2317172150Sariff 2318160383Snetchild sbuf_finish(s); 2319160383Snetchild return (sbuf_len(s)); 2320160383Snetchild} 2321160383Snetchild 2322160383Snetchild/* INIT & UNINIT */ 2323160383Snetchildstatic int 2324160383Snetchildemu10kx_dev_init(struct emu_sc_info *sc) 2325160383Snetchild{ 2326160383Snetchild int unit; 2327160383Snetchild 2328172150Sariff mtx_init(&sc->emu10kx_lock, device_get_nameunit(sc->dev), "kxdevlock", 0); 2329160383Snetchild unit = device_get_unit(sc->dev); 2330160383Snetchild 2331193640Sariff sc->cdev = make_dev(&emu10kx_cdevsw, PCMMINOR(unit), UID_ROOT, GID_WHEEL, 0640, "emu10kx%d", unit); 2332160383Snetchild if (sc->cdev != NULL) { 2333160383Snetchild sc->cdev->si_drv1 = sc; 2334160383Snetchild return (0); 2335160383Snetchild } 2336160383Snetchild return (ENXIO); 2337160383Snetchild} 2338160383Snetchild 2339160383Snetchildstatic int 2340160383Snetchildemu10kx_dev_uninit(struct emu_sc_info *sc) 2341160383Snetchild{ 2342160383Snetchild mtx_lock(&sc->emu10kx_lock); 2343160383Snetchild if (sc->emu10kx_isopen) { 2344160383Snetchild mtx_unlock(&sc->emu10kx_lock); 2345160383Snetchild return (EBUSY); 2346160383Snetchild } 2347160383Snetchild if (sc->cdev) 2348160383Snetchild destroy_dev(sc->cdev); 2349160383Snetchild sc->cdev = 0; 2350160383Snetchild 2351160383Snetchild mtx_destroy(&sc->emu10kx_lock); 2352160383Snetchild return (0); 2353160383Snetchild} 2354160383Snetchild 2355160383Snetchild/* resource manager */ 2356160383Snetchildint 2357160383Snetchildemu_rm_init(struct emu_sc_info *sc) 2358160383Snetchild{ 2359160383Snetchild int i; 2360160383Snetchild int maxcount; 2361160383Snetchild struct emu_rm *rm; 2362160383Snetchild 2363160383Snetchild rm = malloc(sizeof(struct emu_rm), M_DEVBUF, M_NOWAIT | M_ZERO); 2364160383Snetchild if (rm == NULL) { 2365160383Snetchild return (ENOMEM); 2366160383Snetchild } 2367160383Snetchild sc->rm = rm; 2368160383Snetchild rm->card = sc; 2369160383Snetchild maxcount = sc->num_gprs; 2370160383Snetchild rm->num_used = 0; 2371172150Sariff mtx_init(&(rm->gpr_lock), device_get_nameunit(sc->dev), "gpr alloc", MTX_DEF); 2372160383Snetchild rm->num_gprs = (maxcount < EMU_MAX_GPR ? maxcount : EMU_MAX_GPR); 2373160383Snetchild for (i = 0; i < rm->num_gprs; i++) 2374160383Snetchild rm->allocmap[i] = 0; 2375172150Sariff /* pre-allocate gpr[0] */ 2376172150Sariff rm->allocmap[0] = 1; 2377172150Sariff rm->last_free_gpr = 1; 2378160383Snetchild 2379160383Snetchild return (0); 2380160383Snetchild} 2381160383Snetchild 2382160383Snetchildint 2383160383Snetchildemu_rm_uninit(struct emu_sc_info *sc) 2384160383Snetchild{ 2385160383Snetchild int i; 2386160383Snetchild 2387172150Sariff if (sc->dbg_level > 1) { 2388172150Sariff mtx_lock(&(sc->rm->gpr_lock)); 2389172150Sariff for (i = 1; i < sc->rm->last_free_gpr; i++) 2390172150Sariff if (sc->rm->allocmap[i] > 0) 2391172150Sariff device_printf(sc->dev, "rm: gpr %d not free before uninit\n", i); 2392172150Sariff mtx_unlock(&(sc->rm->gpr_lock)); 2393172150Sariff } 2394172150Sariff 2395160383Snetchild mtx_destroy(&(sc->rm->gpr_lock)); 2396160383Snetchild free(sc->rm, M_DEVBUF); 2397160383Snetchild return (0); 2398160383Snetchild} 2399160383Snetchild 2400160383Snetchildstatic int 2401160383Snetchildemu_rm_gpr_alloc(struct emu_rm *rm, int count) 2402160383Snetchild{ 2403160383Snetchild int i, j; 2404160383Snetchild int allocated_gpr; 2405160383Snetchild 2406160383Snetchild allocated_gpr = rm->num_gprs; 2407160383Snetchild /* try fast way first */ 2408160383Snetchild mtx_lock(&(rm->gpr_lock)); 2409160383Snetchild if (rm->last_free_gpr + count <= rm->num_gprs) { 2410160383Snetchild allocated_gpr = rm->last_free_gpr; 2411160383Snetchild rm->last_free_gpr += count; 2412160383Snetchild rm->allocmap[allocated_gpr] = count; 2413160383Snetchild for (i = 1; i < count; i++) 2414160383Snetchild rm->allocmap[allocated_gpr + i] = -(count - i); 2415160383Snetchild } else { 2416160383Snetchild /* longer */ 2417160383Snetchild i = 0; 2418160383Snetchild allocated_gpr = rm->num_gprs; 2419160383Snetchild while (i < rm->last_free_gpr - count) { 2420160383Snetchild if (rm->allocmap[i] > 0) { 2421160383Snetchild i += rm->allocmap[i]; 2422160383Snetchild } else { 2423160383Snetchild allocated_gpr = i; 2424160383Snetchild for (j = 1; j < count; j++) { 2425160383Snetchild if (rm->allocmap[i + j] != 0) 2426160383Snetchild allocated_gpr = rm->num_gprs; 2427160383Snetchild } 2428160383Snetchild if (allocated_gpr == i) 2429160383Snetchild break; 2430160383Snetchild } 2431160383Snetchild } 2432160383Snetchild if (allocated_gpr + count < rm->last_free_gpr) { 2433160383Snetchild rm->allocmap[allocated_gpr] = count; 2434160383Snetchild for (i = 1; i < count; i++) 2435160383Snetchild rm->allocmap[allocated_gpr + i] = -(count - i); 2436160383Snetchild 2437160383Snetchild } 2438160383Snetchild } 2439160383Snetchild if (allocated_gpr == rm->num_gprs) 2440160383Snetchild allocated_gpr = (-1); 2441160383Snetchild if (allocated_gpr >= 0) 2442160383Snetchild rm->num_used += count; 2443160383Snetchild mtx_unlock(&(rm->gpr_lock)); 2444160383Snetchild return (allocated_gpr); 2445160383Snetchild} 2446160383Snetchild 2447160383Snetchild/* mixer */ 2448160383Snetchildvoid 2449160383Snetchildemumix_set_mode(struct emu_sc_info *sc, int mode) 2450160383Snetchild{ 2451160383Snetchild uint32_t a_iocfg; 2452160383Snetchild uint32_t hcfg; 2453160383Snetchild uint32_t tmp; 2454160383Snetchild 2455160383Snetchild switch (mode) { 2456160383Snetchild case MODE_DIGITAL: 2457160383Snetchild /* FALLTHROUGH */ 2458160383Snetchild case MODE_ANALOG: 2459160383Snetchild break; 2460160383Snetchild default: 2461160383Snetchild return; 2462160383Snetchild } 2463160383Snetchild 2464229981Spfg hcfg = EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE; 2465160383Snetchild a_iocfg = 0; 2466160383Snetchild 2467160383Snetchild if (sc->rev >= 6) 2468229981Spfg hcfg |= EMU_HCFG_JOYENABLE; 2469160383Snetchild 2470160383Snetchild if (sc->is_emu10k1) 2471229981Spfg hcfg |= EMU_HCFG_LOCKTANKCACHE_MASK; 2472160383Snetchild else 2473229981Spfg hcfg |= EMU_HCFG_CODECFMT_I2S | EMU_HCFG_JOYENABLE; 2474160383Snetchild 2475160383Snetchild 2476160383Snetchild if (mode == MODE_DIGITAL) { 2477160383Snetchild if (sc->broken_digital) { 2478172150Sariff device_printf(sc->dev, "Digital mode is reported as broken on this card.\n"); 2479160383Snetchild } 2480229981Spfg a_iocfg |= EMU_A_IOCFG_GPOUT1; 2481229981Spfg hcfg |= EMU_HCFG_GPOUT0; 2482160383Snetchild } 2483160383Snetchild 2484160383Snetchild if (mode == MODE_ANALOG) 2485160383Snetchild emumix_set_spdif_mode(sc, SPDIF_MODE_PCM); 2486160383Snetchild 2487160383Snetchild if (sc->is_emu10k2) 2488160383Snetchild a_iocfg |= 0x80; /* XXX */ 2489160383Snetchild 2490160383Snetchild if ((sc->is_ca0102) || (sc->is_ca0108)) 2491172150Sariff /* 2492229981Spfg * Setting EMU_A_IOCFG_DISABLE_ANALOG will do opposite things 2493172150Sariff * on diffrerent cards. 2494172150Sariff * "don't disable analog outs" on Audigy 2 (ca0102/ca0108) 2495172150Sariff * "disable analog outs" on Audigy (emu10k2) 2496172150Sariff */ 2497229981Spfg a_iocfg |= EMU_A_IOCFG_DISABLE_ANALOG; 2498160383Snetchild 2499160383Snetchild if (sc->is_ca0108) 2500160383Snetchild a_iocfg |= 0x20; /* XXX */ 2501160383Snetchild 2502172150Sariff /* Mute analog center & subwoofer before mode change */ 2503172150Sariff if (mode == MODE_DIGITAL) 2504172150Sariff emumix_set_gpr(sc, sc->mute_gpr[ANALOGMUTE], 1); 2505172150Sariff 2506229981Spfg emu_wr(sc, EMU_HCFG, hcfg, 4); 2507160383Snetchild 2508160383Snetchild if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) { 2509229981Spfg tmp = emu_rd(sc, EMU_A_IOCFG, 2); 2510160383Snetchild tmp = a_iocfg; 2511229981Spfg emu_wr(sc, EMU_A_IOCFG, tmp, 2); 2512160383Snetchild } 2513160383Snetchild 2514172150Sariff /* Unmute if we have changed mode to analog. */ 2515172150Sariff 2516172150Sariff if (mode == MODE_ANALOG) 2517172150Sariff emumix_set_gpr(sc, sc->mute_gpr[ANALOGMUTE], 0); 2518172150Sariff 2519172150Sariff sc->mode = mode; 2520160383Snetchild} 2521160383Snetchild 2522160383Snetchildvoid 2523160383Snetchildemumix_set_spdif_mode(struct emu_sc_info *sc, int mode) 2524160383Snetchild{ 2525160383Snetchild uint32_t spcs; 2526160383Snetchild 2527160383Snetchild switch (mode) { 2528160383Snetchild case SPDIF_MODE_PCM: 2529160383Snetchild break; 2530160383Snetchild case SPDIF_MODE_AC3: 2531160383Snetchild device_printf(sc->dev, "AC3 mode does not work and disabled\n"); 2532160383Snetchild return; 2533160383Snetchild default: 2534160383Snetchild return; 2535160383Snetchild } 2536160383Snetchild 2537229981Spfg spcs = EMU_SPCS_CLKACCY_1000PPM | EMU_SPCS_SAMPLERATE_48 | 2538229981Spfg EMU_SPCS_CHANNELNUM_LEFT | EMU_SPCS_SOURCENUM_UNSPEC | 2539229981Spfg EMU_SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | 2540229981Spfg EMU_SPCS_EMPHASIS_NONE | EMU_SPCS_COPYRIGHT; 2541160383Snetchild 2542160383Snetchild mode = SPDIF_MODE_PCM; 2543160383Snetchild 2544229981Spfg emu_wrptr(sc, 0, EMU_SPCS0, spcs); 2545229981Spfg emu_wrptr(sc, 0, EMU_SPCS1, spcs); 2546229981Spfg emu_wrptr(sc, 0, EMU_SPCS2, spcs); 2547160383Snetchild} 2548160383Snetchild 2549160383Snetchild#define L2L_POINTS 10 2550160383Snetchild 2551160383Snetchildstatic int l2l_df[L2L_POINTS] = { 2552160383Snetchild 0x572C5CA, /* 100..90 */ 2553160383Snetchild 0x3211625, /* 90..80 */ 2554160383Snetchild 0x1CC1A76, /* 80..70 */ 2555160383Snetchild 0x108428F, /* 70..60 */ 2556160383Snetchild 0x097C70A, /* 60..50 */ 2557160383Snetchild 0x0572C5C, /* 50..40 */ 2558160383Snetchild 0x0321162, /* 40..30 */ 2559160383Snetchild 0x01CC1A7, /* 30..20 */ 2560160383Snetchild 0x0108428, /* 20..10 */ 2561160383Snetchild 0x016493D /* 10..0 */ 2562160383Snetchild}; 2563160383Snetchild 2564160383Snetchildstatic int l2l_f[L2L_POINTS] = { 2565160383Snetchild 0x4984461A, /* 90 */ 2566160383Snetchild 0x2A3968A7, /* 80 */ 2567160383Snetchild 0x18406003, /* 70 */ 2568160383Snetchild 0x0DEDC66D, /* 60 */ 2569160383Snetchild 0x07FFFFFF, /* 50 */ 2570160383Snetchild 0x04984461, /* 40 */ 2571160383Snetchild 0x02A3968A, /* 30 */ 2572160383Snetchild 0x01840600, /* 20 */ 2573160383Snetchild 0x00DEDC66, /* 10 */ 2574160383Snetchild 0x00000000 /* 0 */ 2575160383Snetchild}; 2576160383Snetchild 2577160383Snetchild 2578160383Snetchildstatic int 2579160383Snetchildlog2lin(int log_t) 2580160383Snetchild{ 2581160383Snetchild int lin_t; 2582160383Snetchild int idx, lin; 2583160383Snetchild 2584160383Snetchild if (log_t <= 0) { 2585160383Snetchild lin_t = 0x00000000; 2586160383Snetchild return (lin_t); 2587160383Snetchild } 2588160383Snetchild 2589160383Snetchild if (log_t >= 100) { 2590160383Snetchild lin_t = 0x7fffffff; 2591160383Snetchild return (lin_t); 2592160383Snetchild } 2593160383Snetchild 2594160383Snetchild idx = (L2L_POINTS - 1) - log_t / (L2L_POINTS); 2595160383Snetchild lin = log_t % (L2L_POINTS); 2596160383Snetchild lin_t = l2l_df[idx] * lin + l2l_f[idx]; 2597160383Snetchild return (lin_t); 2598160383Snetchild} 2599160383Snetchild 2600160383Snetchild 2601160383Snetchildvoid 2602160383Snetchildemumix_set_fxvol(struct emu_sc_info *sc, unsigned gpr, int32_t vol) 2603160383Snetchild{ 2604160383Snetchild 2605160383Snetchild vol = log2lin(vol); 2606160383Snetchild emumix_set_gpr(sc, gpr, vol); 2607160383Snetchild} 2608160383Snetchild 2609160383Snetchildvoid 2610160383Snetchildemumix_set_gpr(struct emu_sc_info *sc, unsigned gpr, int32_t val) 2611160383Snetchild{ 2612172150Sariff if (sc->dbg_level > 1) 2613172150Sariff if (gpr == 0) { 2614172150Sariff device_printf(sc->dev, "Zero gpr write access\n"); 2615172150Sariff#ifdef KDB 2616172150Sariff kdb_backtrace(); 2617172150Sariff#endif 2618172150Sariff return; 2619172150Sariff } 2620160383Snetchild 2621160383Snetchild emu_wrptr(sc, 0, GPR(gpr), val); 2622160383Snetchild} 2623160383Snetchild 2624160383Snetchildvoid 2625160383Snetchildemumix_set_volume(struct emu_sc_info *sc, int mixer_idx, int volume) 2626160383Snetchild{ 2627160383Snetchild 2628160383Snetchild RANGE(volume, 0, 100); 2629160383Snetchild if (mixer_idx < NUM_MIXERS) { 2630160383Snetchild sc->mixer_volcache[mixer_idx] = volume; 2631160383Snetchild emumix_set_fxvol(sc, sc->mixer_gpr[mixer_idx], volume); 2632160383Snetchild } 2633160383Snetchild} 2634160383Snetchild 2635160383Snetchildint 2636160383Snetchildemumix_get_volume(struct emu_sc_info *sc, int mixer_idx) 2637160383Snetchild{ 2638160383Snetchild if ((mixer_idx < NUM_MIXERS) && (mixer_idx >= 0)) 2639160383Snetchild return (sc->mixer_volcache[mixer_idx]); 2640160383Snetchild return (-1); 2641160383Snetchild} 2642160383Snetchild 2643160383Snetchild/* Init CardBus part */ 2644160383Snetchildstatic int 2645160383Snetchildemu_cardbus_init(struct emu_sc_info *sc) 2646160383Snetchild{ 2647160383Snetchild 2648160383Snetchild /* 2649229981Spfg * XXX May not need this if we have EMU_IPR3 handler. 2650229981Spfg * Is it a real init calls, or EMU_IPR3 interrupt acknowledgments? 2651160383Snetchild * Looks much like "(data << 16) | register". 2652160383Snetchild */ 2653160383Snetchild emu_wr_cbptr(sc, (0x00d0 << 16) | 0x0000); 2654160383Snetchild emu_wr_cbptr(sc, (0x00d0 << 16) | 0x0001); 2655160383Snetchild emu_wr_cbptr(sc, (0x00d0 << 16) | 0x005f); 2656160383Snetchild emu_wr_cbptr(sc, (0x00d0 << 16) | 0x007f); 2657160383Snetchild 2658160383Snetchild emu_wr_cbptr(sc, (0x0090 << 16) | 0x007f); 2659160383Snetchild 2660160383Snetchild return (0); 2661160383Snetchild} 2662160383Snetchild 2663160383Snetchild/* Probe and attach the card */ 2664160383Snetchildstatic int 2665166919Sariffemu_init(struct emu_sc_info *sc) 2666160383Snetchild{ 2667160383Snetchild uint32_t ch, tmp; 2668160383Snetchild uint32_t spdif_sr; 2669160383Snetchild uint32_t ac97slot; 2670160383Snetchild int def_mode; 2671160383Snetchild int i; 2672160383Snetchild 2673160383Snetchild /* disable audio and lock cache */ 2674229981Spfg emu_wr(sc, EMU_HCFG, EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_MUTEBUTTONENABLE, 4); 2675160383Snetchild 2676160383Snetchild /* reset recording buffers */ 2677229981Spfg emu_wrptr(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE); 2678229981Spfg emu_wrptr(sc, 0, EMU_MICBA, 0); 2679229981Spfg emu_wrptr(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE); 2680229981Spfg emu_wrptr(sc, 0, EMU_FXBA, 0); 2681229981Spfg emu_wrptr(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE); 2682229981Spfg emu_wrptr(sc, 0, EMU_ADCBA, 0); 2683160383Snetchild 2684160383Snetchild /* disable channel interrupt */ 2685229981Spfg emu_wr(sc, EMU_INTE, EMU_INTE_INTERTIMERENB | EMU_INTE_SAMPLERATER | EMU_INTE_PCIERRENABLE, 4); 2686229981Spfg emu_wrptr(sc, 0, EMU_CLIEL, 0); 2687229981Spfg emu_wrptr(sc, 0, EMU_CLIEH, 0); 2688229981Spfg emu_wrptr(sc, 0, EMU_SOLEL, 0); 2689229981Spfg emu_wrptr(sc, 0, EMU_SOLEH, 0); 2690160383Snetchild 2691160383Snetchild /* disable P16V and S/PDIF interrupts */ 2692160383Snetchild if ((sc->is_ca0102) || (sc->is_ca0108)) 2693229981Spfg emu_wr(sc, EMU_INTE2, 0, 4); 2694160383Snetchild 2695160383Snetchild if (sc->is_ca0102) 2696229981Spfg emu_wr(sc, EMU_INTE3, 0, 4); 2697160383Snetchild 2698160383Snetchild /* init phys inputs and outputs */ 2699160383Snetchild ac97slot = 0; 2700160383Snetchild if (sc->has_51) 2701229981Spfg ac97slot = EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE; 2702160383Snetchild if (sc->has_71) 2703229981Spfg ac97slot = EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE | EMU_AC97SLOT_REAR_LEFT | EMU_AC97SLOT_REAR_RIGHT; 2704160383Snetchild if (sc->is_emu10k2) 2705160383Snetchild ac97slot |= 0x40; 2706229981Spfg emu_wrptr(sc, 0, EMU_AC97SLOT, ac97slot); 2707160383Snetchild 2708160383Snetchild if (sc->is_emu10k2) /* XXX for later cards? */ 2709229981Spfg emu_wrptr(sc, 0, EMU_SPBYPASS, 0xf00); /* What will happen if 2710160383Snetchild * we write 1 here? */ 2711160383Snetchild 2712166919Sariff if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(sc->dev), 2713166904Snetchild /* alignment */ 2, /* boundary */ 0, 2714218478Smarius /* lowaddr */ (1U << 31) - 1, /* can only access 0-2gb */ 2715160383Snetchild /* highaddr */ BUS_SPACE_MAXADDR, 2716160383Snetchild /* filter */ NULL, /* filterarg */ NULL, 2717161054Snetchild /* maxsize */ EMU_MAX_BUFSZ, /* nsegments */ 1, /* maxsegz */ 0x3ffff, 2718160383Snetchild /* flags */ 0, /* lockfunc */ busdma_lock_mutex, 2719160383Snetchild /* lockarg */ &Giant, &(sc->mem.dmat)) != 0) { 2720160383Snetchild device_printf(sc->dev, "unable to create dma tag\n"); 2721160383Snetchild bus_dma_tag_destroy(sc->mem.dmat); 2722160383Snetchild return (ENOMEM); 2723160383Snetchild } 2724160383Snetchild 2725172150Sariff sc->mem.card = sc; 2726160383Snetchild SLIST_INIT(&sc->mem.blocks); 2727161054Snetchild sc->mem.ptb_pages = emu_malloc(&sc->mem, EMU_MAXPAGES * sizeof(uint32_t), &sc->mem.ptb_pages_addr); 2728160383Snetchild if (sc->mem.ptb_pages == NULL) 2729160383Snetchild return (ENOMEM); 2730160383Snetchild 2731160383Snetchild sc->mem.silent_page = emu_malloc(&sc->mem, EMUPAGESIZE, &sc->mem.silent_page_addr); 2732160383Snetchild if (sc->mem.silent_page == NULL) { 2733160383Snetchild emu_free(&sc->mem, sc->mem.ptb_pages); 2734160383Snetchild return (ENOMEM); 2735160383Snetchild } 2736160383Snetchild /* Clear page with silence & setup all pointers to this page */ 2737160383Snetchild bzero(sc->mem.silent_page, EMUPAGESIZE); 2738160383Snetchild tmp = (uint32_t) (sc->mem.silent_page_addr) << 1; 2739161054Snetchild for (i = 0; i < EMU_MAXPAGES; i++) 2740160383Snetchild sc->mem.ptb_pages[i] = tmp | i; 2741160383Snetchild 2742160383Snetchild for (ch = 0; ch < NUM_G; ch++) { 2743229981Spfg emu_wrptr(sc, ch, EMU_CHAN_MAPA, tmp | EMU_CHAN_MAP_PTI_MASK); 2744229981Spfg emu_wrptr(sc, ch, EMU_CHAN_MAPB, tmp | EMU_CHAN_MAP_PTI_MASK); 2745160383Snetchild } 2746229981Spfg emu_wrptr(sc, 0, EMU_PTB, (sc->mem.ptb_pages_addr)); 2747229981Spfg emu_wrptr(sc, 0, EMU_TCB, 0); /* taken from original driver */ 2748229981Spfg emu_wrptr(sc, 0, EMU_TCBS, 0); /* taken from original driver */ 2749160383Snetchild 2750160383Snetchild /* init envelope engine */ 2751160383Snetchild for (ch = 0; ch < NUM_G; ch++) { 2752229981Spfg emu_wrptr(sc, ch, EMU_CHAN_DCYSUSV, 0); 2753229981Spfg emu_wrptr(sc, ch, EMU_CHAN_IP, 0); 2754229981Spfg emu_wrptr(sc, ch, EMU_CHAN_VTFT, 0xffff); 2755229981Spfg emu_wrptr(sc, ch, EMU_CHAN_CVCF, 0xffff); 2756229981Spfg emu_wrptr(sc, ch, EMU_CHAN_PTRX, 0); 2757229981Spfg emu_wrptr(sc, ch, EMU_CHAN_CPF, 0); 2758229981Spfg emu_wrptr(sc, ch, EMU_CHAN_CCR, 0); 2759160383Snetchild 2760229981Spfg emu_wrptr(sc, ch, EMU_CHAN_PSST, 0); 2761229981Spfg emu_wrptr(sc, ch, EMU_CHAN_DSL, 0x10); 2762229981Spfg emu_wrptr(sc, ch, EMU_CHAN_CCCA, 0); 2763229981Spfg emu_wrptr(sc, ch, EMU_CHAN_Z1, 0); 2764229981Spfg emu_wrptr(sc, ch, EMU_CHAN_Z2, 0); 2765229981Spfg emu_wrptr(sc, ch, EMU_CHAN_FXRT, 0xd01c0000); 2766160383Snetchild 2767229981Spfg emu_wrptr(sc, ch, EMU_CHAN_ATKHLDM, 0); 2768229981Spfg emu_wrptr(sc, ch, EMU_CHAN_DCYSUSM, 0); 2769229981Spfg emu_wrptr(sc, ch, EMU_CHAN_IFATN, 0xffff); 2770229981Spfg emu_wrptr(sc, ch, EMU_CHAN_PEFE, 0); 2771229981Spfg emu_wrptr(sc, ch, EMU_CHAN_FMMOD, 0); 2772229981Spfg emu_wrptr(sc, ch, EMU_CHAN_TREMFRQ, 24); /* 1 Hz */ 2773229981Spfg emu_wrptr(sc, ch, EMU_CHAN_FM2FRQ2, 24); /* 1 Hz */ 2774229981Spfg emu_wrptr(sc, ch, EMU_CHAN_TEMPENV, 0); 2775160383Snetchild 2776160383Snetchild /*** these are last so OFF prevents writing ***/ 2777229981Spfg emu_wrptr(sc, ch, EMU_CHAN_LFOVAL2, 0); 2778229981Spfg emu_wrptr(sc, ch, EMU_CHAN_LFOVAL1, 0); 2779229981Spfg emu_wrptr(sc, ch, EMU_CHAN_ATKHLDV, 0); 2780229981Spfg emu_wrptr(sc, ch, EMU_CHAN_ENVVOL, 0); 2781229981Spfg emu_wrptr(sc, ch, EMU_CHAN_ENVVAL, 0); 2782160383Snetchild 2783160383Snetchild if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) { 2784160383Snetchild emu_wrptr(sc, ch, 0x4c, 0x0); 2785160383Snetchild emu_wrptr(sc, ch, 0x4d, 0x0); 2786160383Snetchild emu_wrptr(sc, ch, 0x4e, 0x0); 2787160383Snetchild emu_wrptr(sc, ch, 0x4f, 0x0); 2788229981Spfg emu_wrptr(sc, ch, EMU_A_CHAN_FXRT1, 0x3f3f3f3f); 2789229981Spfg emu_wrptr(sc, ch, EMU_A_CHAN_FXRT2, 0x3f3f3f3f); 2790229981Spfg emu_wrptr(sc, ch, EMU_A_CHAN_SENDAMOUNTS, 0x0); 2791160383Snetchild } 2792160383Snetchild } 2793160383Snetchild 2794160383Snetchild emumix_set_spdif_mode(sc, SPDIF_MODE_PCM); 2795160383Snetchild 2796160383Snetchild if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) 2797229981Spfg emu_wrptr(sc, 0, EMU_A_SPDIF_SAMPLERATE, EMU_A_SPDIF_48000); 2798160383Snetchild 2799160383Snetchild /* 2800160383Snetchild * CAxxxx cards needs additional setup: 2801160383Snetchild * 1. Set I2S capture sample rate to 96000 2802160383Snetchild * 2. Disable P16v / P17v proceesing 2803160383Snetchild * 3. Allow EMU10K DSP inputs 2804160383Snetchild */ 2805160383Snetchild if ((sc->is_ca0102) || (sc->is_ca0108)) { 2806160383Snetchild 2807229981Spfg spdif_sr = emu_rdptr(sc, 0, EMU_A_SPDIF_SAMPLERATE); 2808160383Snetchild spdif_sr &= 0xfffff1ff; 2809229981Spfg spdif_sr |= EMU_A_I2S_CAPTURE_96000; 2810229981Spfg emu_wrptr(sc, 0, EMU_A_SPDIF_SAMPLERATE, spdif_sr); 2811160383Snetchild 2812160383Snetchild /* Disable P16v processing */ 2813229981Spfg emu_wr_p16vptr(sc, 0, EMU_A2_SRCSel, 0x14); 2814160383Snetchild 2815160383Snetchild /* Setup P16v/P17v sound routing */ 2816160383Snetchild if (sc->is_ca0102) 2817229981Spfg emu_wr_p16vptr(sc, 0, EMU_A2_SRCMULTI_ENABLE, 0xFF00FF00); 2818160383Snetchild else { 2819229981Spfg emu_wr_p16vptr(sc, 0, EMU_A2_MIXER_I2S_ENABLE, 0xFF000000); 2820229981Spfg emu_wr_p16vptr(sc, 0, EMU_A2_MIXER_SPDIF_ENABLE, 0xFF000000); 2821160383Snetchild 2822229981Spfg tmp = emu_rd(sc, EMU_A_IOCFG, 2); 2823229981Spfg emu_wr(sc, EMU_A_IOCFG, tmp & ~0x8, 2); 2824160383Snetchild } 2825160383Snetchild } 2826160383Snetchild emu_initefx(sc); 2827160383Snetchild 2828160383Snetchild def_mode = MODE_ANALOG; 2829160383Snetchild if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) 2830160383Snetchild def_mode = MODE_DIGITAL; 2831160383Snetchild if (((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) && (sc->broken_digital)) { 2832160383Snetchild device_printf(sc->dev, "Audigy card initialized in analog mode.\n"); 2833160383Snetchild def_mode = MODE_ANALOG; 2834160383Snetchild } 2835160383Snetchild emumix_set_mode(sc, def_mode); 2836160383Snetchild 2837160383Snetchild if (bootverbose) { 2838229981Spfg tmp = emu_rd(sc, EMU_HCFG, 4); 2839160383Snetchild device_printf(sc->dev, "Card Configuration ( 0x%08x )\n", tmp); 2840160383Snetchild device_printf(sc->dev, "Card Configuration ( & 0xff000000 ) : %s%s%s%s%s%s%s%s\n", 2841160383Snetchild (tmp & 0x80000000 ? "[Legacy MPIC] " : ""), 2842160383Snetchild (tmp & 0x40000000 ? "[0x40] " : ""), 2843160383Snetchild (tmp & 0x20000000 ? "[0x20] " : ""), 2844160383Snetchild (tmp & 0x10000000 ? "[0x10] " : ""), 2845160383Snetchild (tmp & 0x08000000 ? "[0x08] " : ""), 2846160383Snetchild (tmp & 0x04000000 ? "[0x04] " : ""), 2847160383Snetchild (tmp & 0x02000000 ? "[0x02] " : ""), 2848160383Snetchild (tmp & 0x01000000 ? "[0x01]" : " ")); 2849160383Snetchild device_printf(sc->dev, "Card Configuration ( & 0x00ff0000 ) : %s%s%s%s%s%s%s%s\n", 2850160383Snetchild (tmp & 0x00800000 ? "[0x80] " : ""), 2851160383Snetchild (tmp & 0x00400000 ? "[0x40] " : ""), 2852160383Snetchild (tmp & 0x00200000 ? "[Legacy INT] " : ""), 2853160383Snetchild (tmp & 0x00100000 ? "[0x10] " : ""), 2854160383Snetchild (tmp & 0x00080000 ? "[0x08] " : ""), 2855160383Snetchild (tmp & 0x00040000 ? "[Codec4] " : ""), 2856160383Snetchild (tmp & 0x00020000 ? "[Codec2] " : ""), 2857160383Snetchild (tmp & 0x00010000 ? "[I2S Codec]" : " ")); 2858160383Snetchild device_printf(sc->dev, "Card Configuration ( & 0x0000ff00 ) : %s%s%s%s%s%s%s%s\n", 2859160383Snetchild (tmp & 0x00008000 ? "[0x80] " : ""), 2860160383Snetchild (tmp & 0x00004000 ? "[GPINPUT0] " : ""), 2861160383Snetchild (tmp & 0x00002000 ? "[GPINPUT1] " : ""), 2862160383Snetchild (tmp & 0x00001000 ? "[GPOUT0] " : ""), 2863160383Snetchild (tmp & 0x00000800 ? "[GPOUT1] " : ""), 2864160383Snetchild (tmp & 0x00000400 ? "[GPOUT2] " : ""), 2865160383Snetchild (tmp & 0x00000200 ? "[Joystick] " : ""), 2866160383Snetchild (tmp & 0x00000100 ? "[0x01]" : " ")); 2867160383Snetchild device_printf(sc->dev, "Card Configuration ( & 0x000000ff ) : %s%s%s%s%s%s%s%s\n", 2868160383Snetchild (tmp & 0x00000080 ? "[0x80] " : ""), 2869160383Snetchild (tmp & 0x00000040 ? "[0x40] " : ""), 2870160383Snetchild (tmp & 0x00000020 ? "[0x20] " : ""), 2871160383Snetchild (tmp & 0x00000010 ? "[AUTOMUTE] " : ""), 2872160383Snetchild (tmp & 0x00000008 ? "[LOCKSOUNDCACHE] " : ""), 2873160383Snetchild (tmp & 0x00000004 ? "[LOCKTANKCACHE] " : ""), 2874160383Snetchild (tmp & 0x00000002 ? "[MUTEBUTTONENABLE] " : ""), 2875160383Snetchild (tmp & 0x00000001 ? "[AUDIOENABLE]" : " ")); 2876160383Snetchild 2877160383Snetchild if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) { 2878229981Spfg tmp = emu_rd(sc, EMU_A_IOCFG, 2); 2879160383Snetchild device_printf(sc->dev, "Audigy Card Configuration ( 0x%04x )\n", tmp); 2880160383Snetchild device_printf(sc->dev, "Audigy Card Configuration ( & 0xff00 )"); 2881160383Snetchild printf(" : %s%s%s%s%s%s%s%s\n", 2882160383Snetchild (tmp & 0x8000 ? "[Rear Speakers] " : ""), 2883160383Snetchild (tmp & 0x4000 ? "[Front Speakers] " : ""), 2884160383Snetchild (tmp & 0x2000 ? "[0x20] " : ""), 2885160383Snetchild (tmp & 0x1000 ? "[0x10] " : ""), 2886160383Snetchild (tmp & 0x0800 ? "[0x08] " : ""), 2887160383Snetchild (tmp & 0x0400 ? "[0x04] " : ""), 2888160383Snetchild (tmp & 0x0200 ? "[0x02] " : ""), 2889160383Snetchild (tmp & 0x0100 ? "[AudigyDrive Phones]" : " ")); 2890160383Snetchild device_printf(sc->dev, "Audigy Card Configuration ( & 0x00ff )"); 2891160383Snetchild printf(" : %s%s%s%s%s%s%s%s\n", 2892160383Snetchild (tmp & 0x0080 ? "[0x80] " : ""), 2893160383Snetchild (tmp & 0x0040 ? "[Mute AnalogOut] " : ""), 2894160383Snetchild (tmp & 0x0020 ? "[0x20] " : ""), 2895160383Snetchild (tmp & 0x0010 ? "[0x10] " : ""), 2896160383Snetchild (tmp & 0x0008 ? "[0x08] " : ""), 2897160383Snetchild (tmp & 0x0004 ? "[GPOUT0] " : ""), 2898160383Snetchild (tmp & 0x0002 ? "[GPOUT1] " : ""), 2899160383Snetchild (tmp & 0x0001 ? "[GPOUT2]" : " ")); 2900160383Snetchild } /* is_emu10k2 or ca* */ 2901160383Snetchild } /* bootverbose */ 2902160383Snetchild return (0); 2903160383Snetchild} 2904160383Snetchild 2905160383Snetchildstatic int 2906160383Snetchildemu_uninit(struct emu_sc_info *sc) 2907160383Snetchild{ 2908160383Snetchild uint32_t ch; 2909160383Snetchild struct emu_memblk *blk; 2910160383Snetchild 2911229981Spfg emu_wr(sc, EMU_INTE, 0, 4); 2912160383Snetchild for (ch = 0; ch < NUM_G; ch++) 2913229981Spfg emu_wrptr(sc, ch, EMU_CHAN_DCYSUSV, 0); 2914160383Snetchild for (ch = 0; ch < NUM_G; ch++) { 2915229981Spfg emu_wrptr(sc, ch, EMU_CHAN_VTFT, 0); 2916229981Spfg emu_wrptr(sc, ch, EMU_CHAN_CVCF, 0); 2917229981Spfg emu_wrptr(sc, ch, EMU_CHAN_PTRX, 0); 2918229981Spfg emu_wrptr(sc, ch, EMU_CHAN_CPF, 0); 2919160383Snetchild } 2920160383Snetchild 2921160383Snetchild /* disable audio and lock cache */ 2922229981Spfg emu_wr(sc, EMU_HCFG, EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_MUTEBUTTONENABLE, 4); 2923160383Snetchild 2924229981Spfg emu_wrptr(sc, 0, EMU_PTB, 0); 2925160383Snetchild /* reset recording buffers */ 2926229981Spfg emu_wrptr(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE); 2927229981Spfg emu_wrptr(sc, 0, EMU_MICBA, 0); 2928229981Spfg emu_wrptr(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE); 2929229981Spfg emu_wrptr(sc, 0, EMU_FXBA, 0); 2930229981Spfg emu_wrptr(sc, 0, EMU_FXWC, 0); 2931229981Spfg emu_wrptr(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE); 2932229981Spfg emu_wrptr(sc, 0, EMU_ADCBA, 0); 2933229981Spfg emu_wrptr(sc, 0, EMU_TCB, 0); 2934229981Spfg emu_wrptr(sc, 0, EMU_TCBS, 0); 2935160383Snetchild 2936160383Snetchild /* disable channel interrupt */ 2937229981Spfg emu_wrptr(sc, 0, EMU_CLIEL, 0); 2938229981Spfg emu_wrptr(sc, 0, EMU_CLIEH, 0); 2939229981Spfg emu_wrptr(sc, 0, EMU_SOLEL, 0); 2940229981Spfg emu_wrptr(sc, 0, EMU_SOLEH, 0); 2941160383Snetchild 2942160383Snetchild if (!SLIST_EMPTY(&sc->mem.blocks)) 2943160383Snetchild device_printf(sc->dev, "warning: memblock list not empty\n"); 2944160383Snetchild 2945160383Snetchild SLIST_FOREACH(blk, &sc->mem.blocks, link) 2946160383Snetchild if (blk != NULL) 2947160383Snetchild device_printf(sc->dev, "lost %d for %s\n", blk->pte_size, blk->owner); 2948160383Snetchild 2949160383Snetchild emu_free(&sc->mem, sc->mem.ptb_pages); 2950160383Snetchild emu_free(&sc->mem, sc->mem.silent_page); 2951160383Snetchild 2952160383Snetchild return (0); 2953160383Snetchild} 2954160383Snetchild 2955160383Snetchildstatic int 2956160383Snetchildemu_read_ivar(device_t bus, device_t dev, int ivar_index, uintptr_t * result) 2957160383Snetchild{ 2958160383Snetchild struct sndcard_func *func = device_get_ivars(dev); 2959160383Snetchild struct emu_sc_info *sc = device_get_softc(bus); 2960160383Snetchild 2961172150Sariff if (func==NULL) 2962172150Sariff return (ENOMEM); 2963172150Sariff if (sc == NULL) 2964172150Sariff return (ENOMEM); 2965172150Sariff 2966160383Snetchild switch (ivar_index) { 2967160383Snetchild case EMU_VAR_FUNC: 2968160383Snetchild *result = func->func; 2969160383Snetchild break; 2970160383Snetchild case EMU_VAR_ROUTE: 2971172150Sariff if (func->varinfo == NULL) 2972172150Sariff return (ENOMEM); 2973160383Snetchild *result = ((struct emu_pcminfo *)func->varinfo)->route; 2974160383Snetchild break; 2975160383Snetchild case EMU_VAR_ISEMU10K1: 2976160383Snetchild *result = sc->is_emu10k1; 2977160383Snetchild break; 2978172150Sariff case EMU_VAR_MCH_DISABLED: 2979172150Sariff *result = sc->mch_disabled; 2980172150Sariff break; 2981172150Sariff case EMU_VAR_MCH_REC: 2982172150Sariff *result = sc->mch_rec; 2983172150Sariff break; 2984160383Snetchild default: 2985160383Snetchild return (ENOENT); 2986160383Snetchild } 2987160383Snetchild 2988160383Snetchild return (0); 2989160383Snetchild} 2990160383Snetchild 2991160383Snetchildstatic int 2992160383Snetchildemu_write_ivar(device_t bus __unused, device_t dev __unused, 2993160383Snetchild int ivar_index, uintptr_t value __unused) 2994160383Snetchild{ 2995160383Snetchild 2996160383Snetchild switch (ivar_index) { 2997160383Snetchild case 0: 2998160383Snetchild return (EINVAL); 2999160383Snetchild 3000160383Snetchild default: 3001160383Snetchild return (ENOENT); 3002160383Snetchild } 3003160383Snetchild} 3004160383Snetchild 3005160383Snetchildstatic int 3006160383Snetchildemu_pci_probe(device_t dev) 3007160383Snetchild{ 3008160383Snetchild struct sbuf *s; 3009165833Snetchild unsigned int thiscard = 0; 3010160383Snetchild uint16_t vendor; 3011160383Snetchild 3012160383Snetchild vendor = pci_read_config(dev, PCIR_DEVVENDOR, /* bytes */ 2); 3013160383Snetchild if (vendor != 0x1102) 3014160383Snetchild return (ENXIO); /* Not Creative */ 3015160383Snetchild 3016160383Snetchild thiscard = emu_getcard(dev); 3017165833Snetchild if (thiscard == 0) 3018160383Snetchild return (ENXIO); 3019160383Snetchild 3020160383Snetchild s = sbuf_new(NULL, NULL, 4096, 0); 3021160383Snetchild if (s == NULL) 3022160383Snetchild return (ENOMEM); 3023160383Snetchild sbuf_printf(s, "Creative %s [%s]", emu_cards[thiscard].desc, emu_cards[thiscard].SBcode); 3024160383Snetchild sbuf_finish(s); 3025160383Snetchild 3026160383Snetchild device_set_desc_copy(dev, sbuf_data(s)); 3027172150Sariff 3028172150Sariff sbuf_delete(s); 3029172150Sariff 3030160383Snetchild return (BUS_PROBE_DEFAULT); 3031160383Snetchild} 3032160383Snetchild 3033160383Snetchild 3034160383Snetchildstatic int 3035160383Snetchildemu_pci_attach(device_t dev) 3036160383Snetchild{ 3037160383Snetchild struct sndcard_func *func; 3038160383Snetchild struct emu_sc_info *sc; 3039160383Snetchild struct emu_pcminfo *pcminfo; 3040172150Sariff#if 0 3041172150Sariff struct emu_midiinfo *midiinfo; 3042172150Sariff#endif 3043160383Snetchild int i; 3044160383Snetchild int device_flags; 3045160383Snetchild char status[255]; 3046160383Snetchild int error = ENXIO; 3047172150Sariff int unit; 3048160383Snetchild 3049160383Snetchild sc = device_get_softc(dev); 3050172150Sariff unit = device_get_unit(dev); 3051160383Snetchild 3052172150Sariff /* Get configuration */ 3053172150Sariff 3054172150Sariff sc->ctx = device_get_sysctl_ctx(dev); 3055172150Sariff if (sc->ctx == NULL) 3056172150Sariff goto bad; 3057172150Sariff sc->root = device_get_sysctl_tree(dev); 3058172150Sariff if (sc->root == NULL) 3059172150Sariff goto bad; 3060172150Sariff 3061172150Sariff if (resource_int_value("emu10kx", unit, "multichannel_disabled", &(sc->mch_disabled))) 3062172150Sariff RANGE(sc->mch_disabled, 0, 1); 3063172150Sariff SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 3064172150Sariff SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 3065172150Sariff OID_AUTO, "multichannel_disabled", CTLFLAG_RD, &(sc->mch_disabled), 0, "Multichannel playback setting"); 3066172150Sariff 3067172150Sariff if (resource_int_value("emu10kx", unit, "multichannel_recording", &(sc->mch_rec))) 3068172150Sariff RANGE(sc->mch_rec, 0, 1); 3069172150Sariff SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 3070172150Sariff SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 3071172150Sariff OID_AUTO, "multichannel_recording", CTLFLAG_RD, &(sc->mch_rec), 0, "Multichannel recording setting"); 3072172150Sariff 3073172150Sariff if (resource_int_value("emu10kx", unit, "debug", &(sc->dbg_level))) 3074172150Sariff RANGE(sc->mch_rec, 0, 2); 3075172150Sariff SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 3076172150Sariff SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 3077172150Sariff OID_AUTO, "debug", CTLFLAG_RW, &(sc->dbg_level), 0, "Debug level"); 3078172150Sariff 3079160383Snetchild /* Fill in the softc. */ 3080172150Sariff mtx_init(&sc->lock, device_get_nameunit(dev), "bridge conf", MTX_DEF); 3081172150Sariff mtx_init(&sc->rw, device_get_nameunit(dev), "exclusive io", MTX_DEF); 3082160383Snetchild sc->dev = dev; 3083160383Snetchild sc->type = pci_get_devid(dev); 3084160383Snetchild sc->rev = pci_get_revid(dev); 3085160383Snetchild sc->enable_ir = 0; 3086160383Snetchild sc->has_ac97 = 0; 3087160383Snetchild sc->has_51 = 0; 3088160383Snetchild sc->has_71 = 0; 3089160383Snetchild sc->broken_digital = 0; 3090160383Snetchild sc->is_emu10k1 = 0; 3091160383Snetchild sc->is_emu10k2 = 0; 3092160383Snetchild sc->is_ca0102 = 0; 3093160383Snetchild sc->is_ca0108 = 0; 3094160383Snetchild sc->is_cardbus = 0; 3095160383Snetchild 3096160383Snetchild device_flags = emu_cards[emu_getcard(dev)].flags; 3097160383Snetchild if (device_flags & HAS_51) 3098160383Snetchild sc->has_51 = 1; 3099160383Snetchild if (device_flags & HAS_71) { 3100160383Snetchild sc->has_51 = 1; 3101160383Snetchild sc->has_71 = 1; 3102160383Snetchild } 3103160383Snetchild if (device_flags & IS_EMU10K1) 3104160383Snetchild sc->is_emu10k1 = 1; 3105160383Snetchild if (device_flags & IS_EMU10K2) 3106160383Snetchild sc->is_emu10k2 = 1; 3107160383Snetchild if (device_flags & IS_CA0102) 3108160383Snetchild sc->is_ca0102 = 1; 3109160383Snetchild if (device_flags & IS_CA0108) 3110160383Snetchild sc->is_ca0108 = 1; 3111160383Snetchild if ((sc->is_emu10k2) && (sc->rev == 4)) { 3112160383Snetchild sc->is_emu10k2 = 0; 3113160383Snetchild sc->is_ca0102 = 1; /* for unknown Audigy 2 cards */ 3114160383Snetchild } 3115160383Snetchild if ((sc->is_ca0102 == 1) || (sc->is_ca0108 == 1)) 3116160383Snetchild if (device_flags & IS_CARDBUS) 3117160383Snetchild sc->is_cardbus = 1; 3118160383Snetchild 3119160383Snetchild if ((sc->is_emu10k1 + sc->is_emu10k2 + sc->is_ca0102 + sc->is_ca0108) != 1) { 3120160383Snetchild device_printf(sc->dev, "Unable to detect HW chipset\n"); 3121160383Snetchild goto bad; 3122160383Snetchild } 3123160383Snetchild if (device_flags & BROKEN_DIGITAL) 3124160383Snetchild sc->broken_digital = 1; 3125160383Snetchild if (device_flags & HAS_AC97) 3126160383Snetchild sc->has_ac97 = 1; 3127160383Snetchild 3128160383Snetchild sc->opcode_shift = 0; 3129160383Snetchild if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) { 3130160383Snetchild sc->opcode_shift = 24; 3131160383Snetchild sc->high_operand_shift = 12; 3132172150Sariff 3133172150Sariff /* DSP map */ 3134165833Snetchild /* sc->fx_base = 0x0 */ 3135160383Snetchild sc->input_base = 0x40; 3136165833Snetchild /* sc->p16vinput_base = 0x50; */ 3137160383Snetchild sc->output_base = 0x60; 3138160383Snetchild sc->efxc_base = 0x80; 3139165833Snetchild /* sc->output32h_base = 0xa0; */ 3140165833Snetchild /* sc->output32l_base = 0xb0; */ 3141160383Snetchild sc->dsp_zero = 0xc0; 3142165833Snetchild /* 0xe0...0x100 are unknown */ 3143165833Snetchild /* sc->tram_base = 0x200 */ 3144165833Snetchild /* sc->tram_addr_base = 0x300 */ 3145229981Spfg sc->gpr_base = EMU_A_FXGPREGBASE; 3146165833Snetchild sc->num_gprs = 0x200; 3147229981Spfg sc->code_base = EMU_A_MICROCODEBASE; 3148165833Snetchild sc->code_size = 0x800 / 2; /* 0x600-0xdff, 2048 words, 3149165833Snetchild * 1024 instructions */ 3150165833Snetchild 3151160383Snetchild sc->mchannel_fx = 8; 3152160383Snetchild sc->num_fxbuses = 16; 3153160383Snetchild sc->num_inputs = 8; 3154160383Snetchild sc->num_outputs = 16; 3155229981Spfg sc->address_mask = EMU_A_PTR_ADDR_MASK; 3156160383Snetchild } 3157160383Snetchild if (sc->is_emu10k1) { 3158172150Sariff sc->has_51 = 0; /* We don't support 5.1 sound on SB Live! 5.1 */ 3159160383Snetchild sc->opcode_shift = 20; 3160160383Snetchild sc->high_operand_shift = 10; 3161229981Spfg sc->code_base = EMU_MICROCODEBASE; 3162160383Snetchild sc->code_size = 0x400 / 2; /* 0x400-0x7ff, 1024 words, 3163160383Snetchild * 512 instructions */ 3164229981Spfg sc->gpr_base = EMU_FXGPREGBASE; 3165160383Snetchild sc->num_gprs = 0x100; 3166160383Snetchild sc->input_base = 0x10; 3167160383Snetchild sc->output_base = 0x20; 3168172150Sariff /* 3169172150Sariff * XXX 5.1 Analog outputs are inside efxc address space! 3170242692Skevlo * They use output+0x11/+0x12 (=efxc+1/+2). 3171165833Snetchild * Don't use this efx registers for recording on SB Live! 5.1! 3172165833Snetchild */ 3173160383Snetchild sc->efxc_base = 0x30; 3174160383Snetchild sc->dsp_zero = 0x40; 3175160383Snetchild sc->mchannel_fx = 0; 3176160383Snetchild sc->num_fxbuses = 8; 3177160383Snetchild sc->num_inputs = 8; 3178160383Snetchild sc->num_outputs = 16; 3179229981Spfg sc->address_mask = EMU_PTR_ADDR_MASK; 3180160383Snetchild } 3181160383Snetchild if (sc->opcode_shift == 0) 3182160383Snetchild goto bad; 3183160383Snetchild 3184160383Snetchild pci_enable_busmaster(dev); 3185160383Snetchild 3186160383Snetchild i = PCIR_BAR(0); 3187160383Snetchild sc->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &i, RF_ACTIVE); 3188160383Snetchild if (sc->reg == NULL) { 3189160383Snetchild device_printf(dev, "unable to map register space\n"); 3190160383Snetchild goto bad; 3191160383Snetchild } 3192160383Snetchild sc->st = rman_get_bustag(sc->reg); 3193160383Snetchild sc->sh = rman_get_bushandle(sc->reg); 3194160383Snetchild 3195160383Snetchild for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) 3196160383Snetchild sc->timer[i] = 0; /* disable it */ 3197160383Snetchild 3198160383Snetchild i = 0; 3199160383Snetchild sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE | RF_SHAREABLE); 3200193640Sariff if ((sc->irq == NULL) || bus_setup_intr(dev, sc->irq, INTR_MPSAFE | INTR_TYPE_AV, 3201193640Sariff#if __FreeBSD_version >= 700031 3202193640Sariff NULL, 3203193640Sariff#endif 3204193640Sariff emu_intr, sc, &sc->ih)) { 3205160383Snetchild device_printf(dev, "unable to map interrupt\n"); 3206160383Snetchild goto bad; 3207160383Snetchild } 3208160383Snetchild if (emu_rm_init(sc) != 0) { 3209160383Snetchild device_printf(dev, "unable to create resource manager\n"); 3210160383Snetchild goto bad; 3211160383Snetchild } 3212160383Snetchild if (sc->is_cardbus) 3213160383Snetchild if (emu_cardbus_init(sc) != 0) { 3214160383Snetchild device_printf(dev, "unable to initialize CardBus interface\n"); 3215160383Snetchild goto bad; 3216160383Snetchild } 3217172150Sariff if (emu_init(sc) != 0) { 3218160383Snetchild device_printf(dev, "unable to initialize the card\n"); 3219160383Snetchild goto bad; 3220160383Snetchild } 3221172150Sariff if (emu10kx_dev_init(sc) != 0) { 3222160383Snetchild device_printf(dev, "unable to create control device\n"); 3223160383Snetchild goto bad; 3224160383Snetchild } 3225160383Snetchild snprintf(status, 255, "rev %d at io 0x%lx irq %ld", sc->rev, rman_get_start(sc->reg), rman_get_start(sc->irq)); 3226160383Snetchild 3227160383Snetchild /* Voices */ 3228160383Snetchild for (i = 0; i < NUM_G; i++) { 3229160383Snetchild sc->voice[i].vnum = i; 3230160383Snetchild sc->voice[i].slave = NULL; 3231160383Snetchild sc->voice[i].busy = 0; 3232160383Snetchild sc->voice[i].ismaster = 0; 3233160383Snetchild sc->voice[i].running = 0; 3234160383Snetchild sc->voice[i].b16 = 0; 3235160383Snetchild sc->voice[i].stereo = 0; 3236160383Snetchild sc->voice[i].speed = 0; 3237160383Snetchild sc->voice[i].start = 0; 3238160383Snetchild sc->voice[i].end = 0; 3239160383Snetchild } 3240160383Snetchild 3241160383Snetchild /* PCM Audio */ 3242172150Sariff for (i = 0; i < RT_COUNT; i++) 3243172150Sariff sc->pcm[i] = NULL; 3244172150Sariff 3245160383Snetchild /* FRONT */ 3246160383Snetchild func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 3247160383Snetchild if (func == NULL) { 3248160383Snetchild error = ENOMEM; 3249160383Snetchild goto bad; 3250160383Snetchild } 3251160383Snetchild pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 3252160383Snetchild if (pcminfo == NULL) { 3253160383Snetchild error = ENOMEM; 3254160383Snetchild goto bad; 3255160383Snetchild } 3256160383Snetchild pcminfo->card = sc; 3257160383Snetchild pcminfo->route = RT_FRONT; 3258160383Snetchild 3259160383Snetchild func->func = SCF_PCM; 3260160383Snetchild func->varinfo = pcminfo; 3261160383Snetchild sc->pcm[RT_FRONT] = device_add_child(dev, "pcm", -1); 3262160383Snetchild device_set_ivars(sc->pcm[RT_FRONT], func); 3263165833Snetchild 3264172150Sariff if (!(sc->mch_disabled)) { 3265172150Sariff /* REAR */ 3266160383Snetchild func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 3267160383Snetchild if (func == NULL) { 3268160383Snetchild error = ENOMEM; 3269160383Snetchild goto bad; 3270160383Snetchild } 3271160383Snetchild pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 3272160383Snetchild if (pcminfo == NULL) { 3273160383Snetchild error = ENOMEM; 3274160383Snetchild goto bad; 3275160383Snetchild } 3276160383Snetchild pcminfo->card = sc; 3277172150Sariff pcminfo->route = RT_REAR; 3278160383Snetchild 3279160383Snetchild func->func = SCF_PCM; 3280160383Snetchild func->varinfo = pcminfo; 3281172150Sariff sc->pcm[RT_REAR] = device_add_child(dev, "pcm", -1); 3282172150Sariff device_set_ivars(sc->pcm[RT_REAR], func); 3283172150Sariff if (sc->has_51) { 3284172150Sariff /* CENTER */ 3285172150Sariff func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 3286172150Sariff if (func == NULL) { 3287172150Sariff error = ENOMEM; 3288172150Sariff goto bad; 3289172150Sariff } 3290172150Sariff pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 3291172150Sariff if (pcminfo == NULL) { 3292172150Sariff error = ENOMEM; 3293172150Sariff goto bad; 3294172150Sariff } 3295172150Sariff pcminfo->card = sc; 3296172150Sariff pcminfo->route = RT_CENTER; 3297172150Sariff 3298172150Sariff func->func = SCF_PCM; 3299172150Sariff func->varinfo = pcminfo; 3300172150Sariff sc->pcm[RT_CENTER] = device_add_child(dev, "pcm", -1); 3301172150Sariff device_set_ivars(sc->pcm[RT_CENTER], func); 3302172150Sariff /* SUB */ 3303172150Sariff func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 3304172150Sariff if (func == NULL) { 3305172150Sariff error = ENOMEM; 3306172150Sariff goto bad; 3307172150Sariff } 3308172150Sariff pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 3309172150Sariff if (pcminfo == NULL) { 3310172150Sariff error = ENOMEM; 3311172150Sariff goto bad; 3312172150Sariff } 3313172150Sariff pcminfo->card = sc; 3314172150Sariff pcminfo->route = RT_SUB; 3315172150Sariff 3316172150Sariff func->func = SCF_PCM; 3317172150Sariff func->varinfo = pcminfo; 3318172150Sariff sc->pcm[RT_SUB] = device_add_child(dev, "pcm", -1); 3319172150Sariff device_set_ivars(sc->pcm[RT_SUB], func); 3320160383Snetchild } 3321172150Sariff if (sc->has_71) { 3322172150Sariff /* SIDE */ 3323172150Sariff func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 3324172150Sariff if (func == NULL) { 3325172150Sariff error = ENOMEM; 3326172150Sariff goto bad; 3327172150Sariff } 3328172150Sariff pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 3329172150Sariff if (pcminfo == NULL) { 3330172150Sariff error = ENOMEM; 3331172150Sariff goto bad; 3332172150Sariff } 3333172150Sariff pcminfo->card = sc; 3334172150Sariff pcminfo->route = RT_SIDE; 3335172150Sariff 3336172150Sariff func->func = SCF_PCM; 3337172150Sariff func->varinfo = pcminfo; 3338172150Sariff sc->pcm[RT_SIDE] = device_add_child(dev, "pcm", -1); 3339172150Sariff device_set_ivars(sc->pcm[RT_SIDE], func); 3340160383Snetchild } 3341172150Sariff } /* mch_disabled */ 3342160383Snetchild 3343172150Sariff if (sc->mch_rec) { 3344160383Snetchild func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 3345160383Snetchild if (func == NULL) { 3346160383Snetchild error = ENOMEM; 3347160383Snetchild goto bad; 3348160383Snetchild } 3349160383Snetchild pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 3350160383Snetchild if (pcminfo == NULL) { 3351160383Snetchild error = ENOMEM; 3352160383Snetchild goto bad; 3353160383Snetchild } 3354160383Snetchild pcminfo->card = sc; 3355172150Sariff pcminfo->route = RT_MCHRECORD; 3356160383Snetchild 3357160383Snetchild func->func = SCF_PCM; 3358160383Snetchild func->varinfo = pcminfo; 3359172150Sariff sc->pcm[RT_MCHRECORD] = device_add_child(dev, "pcm", -1); 3360172150Sariff device_set_ivars(sc->pcm[RT_MCHRECORD], func); 3361172150Sariff } /*mch_rec */ 3362165833Snetchild 3363172150Sariff for (i = 0; i < 2; i++) 3364172150Sariff sc->midi[i] = NULL; 3365165833Snetchild 3366172150Sariff /* MIDI has some memory mangament and (possible) locking problems */ 3367172150Sariff#if 0 3368160383Snetchild /* Midi Interface 1: Live!, Audigy, Audigy 2 */ 3369160383Snetchild if ((sc->is_emu10k1) || (sc->is_emu10k2) || (sc->is_ca0102)) { 3370160383Snetchild func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 3371160383Snetchild if (func == NULL) { 3372160383Snetchild error = ENOMEM; 3373160383Snetchild goto bad; 3374160383Snetchild } 3375172150Sariff midiinfo = malloc(sizeof(struct emu_midiinfo), M_DEVBUF, M_NOWAIT | M_ZERO); 3376172150Sariff if (midiinfo == NULL) { 3377160383Snetchild error = ENOMEM; 3378160383Snetchild goto bad; 3379160383Snetchild } 3380172150Sariff midiinfo->card = sc; 3381160383Snetchild if (sc->is_emu10k2 || (sc->is_ca0102)) { 3382229981Spfg midiinfo->port = EMU_A_MUDATA1; 3383172150Sariff midiinfo->portnr = 1; 3384160383Snetchild } 3385160383Snetchild if (sc->is_emu10k1) { 3386172150Sariff midiinfo->port = MUDATA; 3387172150Sariff midiinfo->portnr = 1; 3388160383Snetchild } 3389160383Snetchild func->func = SCF_MIDI; 3390172150Sariff func->varinfo = midiinfo; 3391160383Snetchild sc->midi[0] = device_add_child(dev, "midi", -1); 3392160383Snetchild device_set_ivars(sc->midi[0], func); 3393160383Snetchild } 3394160383Snetchild /* Midi Interface 2: Audigy, Audigy 2 (on AudigyDrive) */ 3395160383Snetchild if (sc->is_emu10k2 || (sc->is_ca0102)) { 3396160383Snetchild func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 3397160383Snetchild if (func == NULL) { 3398160383Snetchild error = ENOMEM; 3399160383Snetchild goto bad; 3400160383Snetchild } 3401172150Sariff midiinfo = malloc(sizeof(struct emu_midiinfo), M_DEVBUF, M_NOWAIT | M_ZERO); 3402172150Sariff if (midiinfo == NULL) { 3403160383Snetchild error = ENOMEM; 3404160383Snetchild goto bad; 3405160383Snetchild } 3406172150Sariff midiinfo->card = sc; 3407160383Snetchild 3408229981Spfg midiinfo->port = EMU_A_MUDATA2; 3409172150Sariff midiinfo->portnr = 2; 3410160383Snetchild 3411160383Snetchild func->func = SCF_MIDI; 3412172150Sariff func->varinfo = midiinfo; 3413160383Snetchild sc->midi[1] = device_add_child(dev, "midi", -1); 3414160383Snetchild device_set_ivars(sc->midi[1], func); 3415160383Snetchild } 3416172150Sariff#endif 3417160383Snetchild return (bus_generic_attach(dev)); 3418160383Snetchild 3419160383Snetchildbad: 3420160383Snetchild /* XXX can we just call emu_pci_detach here? */ 3421160383Snetchild if (sc->cdev) 3422160383Snetchild emu10kx_dev_uninit(sc); 3423160383Snetchild if (sc->rm != NULL) 3424160383Snetchild emu_rm_uninit(sc); 3425160383Snetchild if (sc->reg) 3426160383Snetchild bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg); 3427160383Snetchild if (sc->ih) 3428160383Snetchild bus_teardown_intr(dev, sc->irq, sc->ih); 3429160383Snetchild if (sc->irq) 3430160383Snetchild bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); 3431172150Sariff mtx_destroy(&sc->rw); 3432160383Snetchild mtx_destroy(&sc->lock); 3433160383Snetchild return (error); 3434160383Snetchild} 3435160383Snetchild 3436160383Snetchildstatic int 3437160383Snetchildemu_pci_detach(device_t dev) 3438160383Snetchild{ 3439160383Snetchild struct emu_sc_info *sc; 3440172150Sariff struct sndcard_func *func; 3441160383Snetchild int devcount, i; 3442160383Snetchild device_t *childlist; 3443160383Snetchild int r = 0; 3444160383Snetchild 3445160383Snetchild sc = device_get_softc(dev); 3446172150Sariff 3447165833Snetchild for (i = 0; i < RT_COUNT; i++) { 3448172150Sariff if (sc->pcm[i] != NULL) { 3449172150Sariff func = device_get_ivars(sc->pcm[i]); 3450172150Sariff if (func != NULL && func->func == SCF_PCM) { 3451172150Sariff device_set_ivars(sc->pcm[i], NULL); 3452172150Sariff free(func->varinfo, M_DEVBUF); 3453172150Sariff free(func, M_DEVBUF); 3454172150Sariff } 3455160383Snetchild r = device_delete_child(dev, sc->pcm[i]); 3456172150Sariff if (r) return (r); 3457172150Sariff } 3458160383Snetchild } 3459172150Sariff 3460172150Sariff if (sc->midi[0] != NULL) { 3461172150Sariff func = device_get_ivars(sc->midi[0]); 3462172150Sariff if (func != NULL && func->func == SCF_MIDI) { 3463172150Sariff device_set_ivars(sc->midi[0], NULL); 3464172150Sariff free(func->varinfo, M_DEVBUF); 3465172150Sariff free(func, M_DEVBUF); 3466172150Sariff } 3467160383Snetchild r = device_delete_child(dev, sc->midi[0]); 3468172150Sariff if (r) return (r); 3469172150Sariff } 3470172150Sariff 3471172150Sariff if (sc->midi[1] != NULL) { 3472172150Sariff func = device_get_ivars(sc->midi[1]); 3473172150Sariff if (func != NULL && func->func == SCF_MIDI) { 3474172150Sariff device_set_ivars(sc->midi[1], NULL); 3475172150Sariff free(func->varinfo, M_DEVBUF); 3476172150Sariff free(func, M_DEVBUF); 3477172150Sariff } 3478160383Snetchild r = device_delete_child(dev, sc->midi[1]); 3479172150Sariff if (r) return (r); 3480172150Sariff } 3481172150Sariff 3482172150Sariff if (device_get_children(dev, &childlist, &devcount) == 0) 3483172150Sariff for (i = 0; i < devcount - 1; i++) { 3484172150Sariff device_printf(dev, "removing stale child %d (unit %d)\n", i, device_get_unit(childlist[i])); 3485172150Sariff func = device_get_ivars(childlist[i]); 3486172150Sariff if (func != NULL && (func->func == SCF_MIDI || func->func == SCF_PCM)) { 3487172150Sariff device_set_ivars(childlist[i], NULL); 3488172150Sariff free(func->varinfo, M_DEVBUF); 3489172150Sariff free(func, M_DEVBUF); 3490172150Sariff } 3491172150Sariff device_delete_child(dev, childlist[i]); 3492172150Sariff } 3493172150Sariff if (childlist != NULL) 3494172150Sariff free(childlist, M_TEMP); 3495172150Sariff 3496172150Sariff r = emu10kx_dev_uninit(sc); 3497160383Snetchild if (r) 3498160383Snetchild return (r); 3499160383Snetchild 3500160383Snetchild /* shutdown chip */ 3501160383Snetchild emu_uninit(sc); 3502160383Snetchild emu_rm_uninit(sc); 3503169246Sariff 3504169246Sariff if (sc->mem.dmat) 3505169246Sariff bus_dma_tag_destroy(sc->mem.dmat); 3506169246Sariff 3507160383Snetchild if (sc->reg) 3508160383Snetchild bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg); 3509160383Snetchild bus_teardown_intr(dev, sc->irq, sc->ih); 3510160383Snetchild bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); 3511172150Sariff mtx_destroy(&sc->rw); 3512160383Snetchild mtx_destroy(&sc->lock); 3513172150Sariff 3514160383Snetchild return (bus_generic_detach(dev)); 3515160383Snetchild} 3516160383Snetchild/* add suspend, resume */ 3517160383Snetchildstatic device_method_t emu_methods[] = { 3518160383Snetchild /* Device interface */ 3519160383Snetchild DEVMETHOD(device_probe, emu_pci_probe), 3520160383Snetchild DEVMETHOD(device_attach, emu_pci_attach), 3521160383Snetchild DEVMETHOD(device_detach, emu_pci_detach), 3522160383Snetchild /* Bus methods */ 3523160383Snetchild DEVMETHOD(bus_read_ivar, emu_read_ivar), 3524160383Snetchild DEVMETHOD(bus_write_ivar, emu_write_ivar), 3525160383Snetchild 3526246128Ssbz DEVMETHOD_END 3527160383Snetchild}; 3528160383Snetchild 3529160383Snetchild 3530160383Snetchildstatic driver_t emu_driver = { 3531160383Snetchild "emu10kx", 3532160383Snetchild emu_methods, 3533160383Snetchild sizeof(struct emu_sc_info), 3534160383Snetchild NULL, 3535160383Snetchild 0, 3536160383Snetchild NULL 3537160383Snetchild}; 3538160383Snetchild 3539160383Snetchildstatic int 3540160383Snetchildemu_modevent(module_t mod __unused, int cmd, void *data __unused) 3541160383Snetchild{ 3542160383Snetchild int err = 0; 3543160383Snetchild 3544160383Snetchild switch (cmd) { 3545160383Snetchild case MOD_LOAD: 3546160383Snetchild break; /* Success */ 3547160383Snetchild 3548160383Snetchild case MOD_UNLOAD: 3549160383Snetchild case MOD_SHUTDOWN: 3550160383Snetchild 3551160383Snetchild /* XXX Should we check state of pcm & midi subdevices here? */ 3552160383Snetchild 3553160383Snetchild break; /* Success */ 3554160383Snetchild 3555160383Snetchild default: 3556160383Snetchild err = EINVAL; 3557160383Snetchild break; 3558160383Snetchild } 3559160383Snetchild 3560160383Snetchild return (err); 3561160383Snetchild 3562160383Snetchild} 3563160383Snetchild 3564160383Snetchildstatic devclass_t emu_devclass; 3565160383Snetchild 3566160383SnetchildDRIVER_MODULE(snd_emu10kx, pci, emu_driver, emu_devclass, emu_modevent, NULL); 3567160383SnetchildMODULE_VERSION(snd_emu10kx, SND_EMU10KX_PREFVER); 3568