1d056fa04SAlexander Leidinger /*- 2d056fa04SAlexander Leidinger * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 3d056fa04SAlexander Leidinger * Copyright (c) 2003-2006 Yuriy Tsibizov <yuriy.tsibizov@gfk.ru> 4d056fa04SAlexander Leidinger * All rights reserved. 5d056fa04SAlexander Leidinger * 6d056fa04SAlexander Leidinger * Redistribution and use in source and binary forms, with or without 7d056fa04SAlexander Leidinger * modification, are permitted provided that the following conditions 8d056fa04SAlexander Leidinger * are met: 9d056fa04SAlexander Leidinger * 1. Redistributions of source code must retain the above copyright 10d056fa04SAlexander Leidinger * notice, this list of conditions and the following disclaimer. 11d056fa04SAlexander Leidinger * 2. Redistributions in binary form must reproduce the above copyright 12d056fa04SAlexander Leidinger * notice, this list of conditions and the following disclaimer in the 13d056fa04SAlexander Leidinger * documentation and/or other materials provided with the distribution. 14d056fa04SAlexander Leidinger * 15d056fa04SAlexander Leidinger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16d056fa04SAlexander Leidinger * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17d056fa04SAlexander Leidinger * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18d056fa04SAlexander Leidinger * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19d056fa04SAlexander Leidinger * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20d056fa04SAlexander Leidinger * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21d056fa04SAlexander Leidinger * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22d056fa04SAlexander Leidinger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 23d056fa04SAlexander Leidinger * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24d056fa04SAlexander Leidinger * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25d056fa04SAlexander Leidinger * SUCH DAMAGE. 26d056fa04SAlexander Leidinger * 27d056fa04SAlexander Leidinger * $FreeBSD$ 28d056fa04SAlexander Leidinger */ 29d056fa04SAlexander Leidinger 30d056fa04SAlexander Leidinger #include <sys/param.h> 31d056fa04SAlexander Leidinger #include <sys/types.h> 32d056fa04SAlexander Leidinger #include <sys/bus.h> 33d056fa04SAlexander Leidinger #include <machine/bus.h> 34d056fa04SAlexander Leidinger #include <sys/rman.h> 35d056fa04SAlexander Leidinger #include <sys/systm.h> 36d056fa04SAlexander Leidinger #include <sys/sbuf.h> 37d056fa04SAlexander Leidinger #include <sys/queue.h> 38d056fa04SAlexander Leidinger #include <sys/lock.h> 39d056fa04SAlexander Leidinger #include <sys/mutex.h> 40d056fa04SAlexander Leidinger #include <sys/sysctl.h> 41d056fa04SAlexander Leidinger 42d056fa04SAlexander Leidinger #include <dev/pci/pcireg.h> 43d056fa04SAlexander Leidinger #include <dev/pci/pcivar.h> 44d056fa04SAlexander Leidinger 45d056fa04SAlexander Leidinger #include <machine/clock.h> /* for DELAY */ 46d056fa04SAlexander Leidinger 47d056fa04SAlexander Leidinger #include <dev/sound/chip.h> 48d056fa04SAlexander Leidinger #include <dev/sound/pcm/sound.h> 49d056fa04SAlexander Leidinger #include <dev/sound/pcm/ac97.h> 50d056fa04SAlexander Leidinger 51d056fa04SAlexander Leidinger #include "opt_emu10kx.h" 52d056fa04SAlexander Leidinger #include <dev/sound/pci/emu10kx.h> 53d056fa04SAlexander Leidinger 54d056fa04SAlexander Leidinger /* hw flags */ 55d056fa04SAlexander Leidinger #define HAS_51 0x0001 56d056fa04SAlexander Leidinger #define HAS_71 0x0002 57d056fa04SAlexander Leidinger #define HAS_AC97 0x0004 58d056fa04SAlexander Leidinger 59d056fa04SAlexander Leidinger #define IS_EMU10K1 0x0008 60d056fa04SAlexander Leidinger #define IS_EMU10K2 0x0010 61d056fa04SAlexander Leidinger #define IS_CA0102 0x0020 62d056fa04SAlexander Leidinger #define IS_CA0108 0x0040 63d056fa04SAlexander Leidinger #define IS_UNKNOWN 0x0080 64d056fa04SAlexander Leidinger 65d056fa04SAlexander Leidinger #define BROKEN_DIGITAL 0x0100 66d056fa04SAlexander Leidinger #define DIGITAL_ONLY 0x0200 67d056fa04SAlexander Leidinger 68d056fa04SAlexander Leidinger #define IS_CARDBUS 0x0400 69d056fa04SAlexander Leidinger 70d056fa04SAlexander Leidinger #define MODE_ANALOG 1 71d056fa04SAlexander Leidinger #define MODE_DIGITAL 2 72d056fa04SAlexander Leidinger #define SPDIF_MODE_PCM 1 73d056fa04SAlexander Leidinger #define SPDIF_MODE_AC3 2 74d056fa04SAlexander Leidinger 75d056fa04SAlexander Leidinger #define MACS 0x0 76d056fa04SAlexander Leidinger #define MACS1 0x1 77d056fa04SAlexander Leidinger #define MACW 0x2 78d056fa04SAlexander Leidinger #define MACW1 0x3 79d056fa04SAlexander Leidinger #define MACINTS 0x4 80d056fa04SAlexander Leidinger #define MACINTW 0x5 81d056fa04SAlexander Leidinger #define ACC3 0x6 82d056fa04SAlexander Leidinger #define MACMV 0x7 83d056fa04SAlexander Leidinger #define ANDXOR 0x8 84d056fa04SAlexander Leidinger #define TSTNEG 0x9 85d056fa04SAlexander Leidinger #define LIMIT 0xA 86d056fa04SAlexander Leidinger #define LIMIT1 0xB 87d056fa04SAlexander Leidinger #define LOG 0xC 88d056fa04SAlexander Leidinger #define EXP 0xD 89d056fa04SAlexander Leidinger #define INTERP 0xE 90d056fa04SAlexander Leidinger #define SKIP 0xF 91d056fa04SAlexander Leidinger 92d056fa04SAlexander Leidinger #define GPR(i) (sc->gpr_base+(i)) 93d056fa04SAlexander Leidinger #define INP(i) (sc->input_base+(i)) 94d056fa04SAlexander Leidinger #define OUTP(i) (sc->output_base+(i)) 95d056fa04SAlexander Leidinger #define FX(i) (i) 96d056fa04SAlexander Leidinger #define FX2(i) (sc->efxc_base+(i)) 97d056fa04SAlexander Leidinger #define DSP_CONST(i) (sc->dsp_zero+(i)) 98d056fa04SAlexander Leidinger 99d056fa04SAlexander Leidinger #define COND_NORMALIZED DSP_CONST(0x1) 100d056fa04SAlexander Leidinger #define COND_BORROW DSP_CONST(0x2) 101d056fa04SAlexander Leidinger #define COND_MINUS DSP_CONST(0x3) 102d056fa04SAlexander Leidinger #define COND_LESS_ZERO DSP_CONST(0x4) 103d056fa04SAlexander Leidinger #define COND_EQ_ZERO DSP_CONST(0x5) 104d056fa04SAlexander Leidinger #define COND_SATURATION DSP_CONST(0x6) 105d056fa04SAlexander Leidinger #define COND_NEQ_ZERO DSP_CONST(0x8) 106d056fa04SAlexander Leidinger 107d056fa04SAlexander Leidinger /* Live! Inputs */ 108d056fa04SAlexander Leidinger #define IN_AC97_L 0x00 109d056fa04SAlexander Leidinger #define IN_AC97_R 0x01 110d056fa04SAlexander Leidinger #define IN_AC97 IN_AC97_L 111d056fa04SAlexander Leidinger #define IN_SPDIF_CD_L 0x02 112d056fa04SAlexander Leidinger #define IN_SPDIF_CD_R 0x03 113d056fa04SAlexander Leidinger #define IN_SPDIF_CD IN_SPDIF_CD_L 114d056fa04SAlexander Leidinger #define IN_ZOOM_L 0x04 115d056fa04SAlexander Leidinger #define IN_ZOOM_R 0x05 116d056fa04SAlexander Leidinger #define IN_ZOOM IN_ZOOM_L 117d056fa04SAlexander Leidinger #define IN_TOSLINK_L 0x06 118d056fa04SAlexander Leidinger #define IN_TOSLINK_R 0x07 119d056fa04SAlexander Leidinger #define IN_TOSLINK IN_TOSLINK_L 120d056fa04SAlexander Leidinger #define IN_LINE1_L 0x08 121d056fa04SAlexander Leidinger #define IN_LINE1_R 0x09 122d056fa04SAlexander Leidinger #define IN_LINE1 IN_LINE1_L 123d056fa04SAlexander Leidinger #define IN_COAX_SPDIF_L 0x0a 124d056fa04SAlexander Leidinger #define IN_COAX_SPDIF_R 0x0b 125d056fa04SAlexander Leidinger #define IN_COAX_SPDIF IN_COAX_SPDIF_L 126d056fa04SAlexander Leidinger #define IN_LINE2_L 0x0c 127d056fa04SAlexander Leidinger #define IN_LINE2_R 0x0d 128d056fa04SAlexander Leidinger #define IN_LINE2 IN_LINE2_L 129d056fa04SAlexander Leidinger #define IN_0E 0x0e 130d056fa04SAlexander Leidinger #define IN_0F 0x0f 131d056fa04SAlexander Leidinger 132d056fa04SAlexander Leidinger /* Outputs */ 133d056fa04SAlexander Leidinger #define OUT_AC97_L 0x00 134d056fa04SAlexander Leidinger #define OUT_AC97_R 0x01 135d056fa04SAlexander Leidinger #define OUT_AC97 OUT_AC97_L 136d056fa04SAlexander Leidinger #define OUT_A_FRONT OUT_AC97 137d056fa04SAlexander Leidinger #define OUT_TOSLINK_L 0x02 138d056fa04SAlexander Leidinger #define OUT_TOSLINK_R 0x03 139d056fa04SAlexander Leidinger #define OUT_TOSLINK OUT_TOSLINK_L 140d056fa04SAlexander Leidinger #define OUT_D_CENTER 0x04 141d056fa04SAlexander Leidinger #define OUT_D_SUB 0x05 142d056fa04SAlexander Leidinger #define OUT_HEADPHONE_L 0x06 143d056fa04SAlexander Leidinger #define OUT_HEADPHONE_R 0x07 144d056fa04SAlexander Leidinger #define OUT_HEADPHONE OUT_HEADPHONE_L 145d056fa04SAlexander Leidinger #define OUT_REAR_L 0x08 146d056fa04SAlexander Leidinger #define OUT_REAR_R 0x09 147d056fa04SAlexander Leidinger #define OUT_REAR OUT_REAR_L 148d056fa04SAlexander Leidinger #define OUT_ADC_REC_L 0x0a 149d056fa04SAlexander Leidinger #define OUT_ADC_REC_R 0x0b 150d056fa04SAlexander Leidinger #define OUT_ADC_REC OUT_ADC_REC_L 151d056fa04SAlexander Leidinger #define OUT_MIC_CAP 0x0c 152d056fa04SAlexander Leidinger #define OUT_A_CENTER 0x11 153d056fa04SAlexander Leidinger #define OUT_A_SUB 0x12 154d056fa04SAlexander Leidinger 155d056fa04SAlexander Leidinger /* Audigy Inputs */ 156d056fa04SAlexander Leidinger #define A_IN_AC97_L 0x00 157d056fa04SAlexander Leidinger #define A_IN_AC97_R 0x01 158d056fa04SAlexander Leidinger #define A_IN_AC97 A_IN_AC97_L 159d056fa04SAlexander Leidinger #define A_IN_SPDIF_CD_L 0x02 160d056fa04SAlexander Leidinger #define A_IN_SPDIF_CD_R 0x03 161d056fa04SAlexander Leidinger #define A_IN_SPDIF_CD A_IN_SPDIF_CD_L 162d056fa04SAlexander Leidinger #define A_IN_O_SPDIF_L 0x04 163d056fa04SAlexander Leidinger #define A_IN_O_SPDIF_R 0x05 164d056fa04SAlexander Leidinger #define A_IN_O_SPDIF A_IN_O_SPDIF_L 165d056fa04SAlexander Leidinger #define A_IN_LINE2_L 0x08 166d056fa04SAlexander Leidinger #define A_IN_LINE2_R 0x09 167d056fa04SAlexander Leidinger #define A_IN_LINE2 A_IN_LINE2_L 168d056fa04SAlexander Leidinger #define A_IN_R_SPDIF_L 0x0a 169d056fa04SAlexander Leidinger #define A_IN_R_SPDIF_R 0x0b 170d056fa04SAlexander Leidinger #define A_IN_R_SPDIF A_IN_R_SPDIF_L 171d056fa04SAlexander Leidinger #define A_IN_AUX2_L 0x0c 172d056fa04SAlexander Leidinger #define A_IN_AUX2_R 0x0d 173d056fa04SAlexander Leidinger #define A_IN_AUX2 A_IN_AUX2_L 174d056fa04SAlexander Leidinger 175d056fa04SAlexander Leidinger /* Audigiy Outputs */ 176d056fa04SAlexander Leidinger #define A_OUT_D_FRONT_L 0x00 177d056fa04SAlexander Leidinger #define A_OUT_D_FRONT_R 0x01 178d056fa04SAlexander Leidinger #define A_OUT_D_FRONT A_OUT_D_FRONT_L 179d056fa04SAlexander Leidinger #define A_OUT_D_CENTER 0x02 180d056fa04SAlexander Leidinger #define A_OUT_D_SUB 0x03 181d056fa04SAlexander Leidinger #define A_OUT_D_SIDE_L 0x04 182d056fa04SAlexander Leidinger #define A_OUT_D_SIDE_R 0x05 183d056fa04SAlexander Leidinger #define A_OUT_D_SIDE A_OUT_D_SIDE_L 184d056fa04SAlexander Leidinger #define A_OUT_D_REAR_L 0x06 185d056fa04SAlexander Leidinger #define A_OUT_D_REAR_R 0x07 186d056fa04SAlexander Leidinger #define A_OUT_D_REAR A_OUT_D_REAR_L 187d056fa04SAlexander Leidinger 188d056fa04SAlexander Leidinger /* on Audigy Platinum only */ 189d056fa04SAlexander Leidinger #define A_OUT_HPHONE_L 0x04 190d056fa04SAlexander Leidinger #define A_OUT_HPHONE_R 0x05 191d056fa04SAlexander Leidinger #define A_OUT_HPHONE A_OUT_HPHONE_L 192d056fa04SAlexander Leidinger 193d056fa04SAlexander Leidinger #define A_OUT_A_FRONT_L 0x08 194d056fa04SAlexander Leidinger #define A_OUT_A_FRONT_R 0x09 195d056fa04SAlexander Leidinger #define A_OUT_A_FRONT A_OUT_A_FRONT_L 196d056fa04SAlexander Leidinger #define A_OUT_A_CENTER 0x0a 197d056fa04SAlexander Leidinger #define A_OUT_A_SUB 0x0b 198d056fa04SAlexander Leidinger #define A_OUT_A_SIDE_L 0x0c 199d056fa04SAlexander Leidinger #define A_OUT_A_SIDE_R 0x0d 200d056fa04SAlexander Leidinger #define A_OUT_A_SIDE A_OUT_A_SIDE_L 201d056fa04SAlexander Leidinger #define A_OUT_A_REAR_L 0x0e 202d056fa04SAlexander Leidinger #define A_OUT_A_REAR_R 0x0f 203d056fa04SAlexander Leidinger #define A_OUT_A_REAR A_OUT_A_REAR_L 204d056fa04SAlexander Leidinger #define A_OUT_AC97_L 0x10 205d056fa04SAlexander Leidinger #define A_OUT_AC97_R 0x11 206d056fa04SAlexander Leidinger #define A_OUT_AC97 A_OUT_AC97_L 207d056fa04SAlexander Leidinger #define A_OUT_ADC_REC_L 0x16 208d056fa04SAlexander Leidinger #define A_OUT_ADC_REC_R 0x17 209d056fa04SAlexander Leidinger #define A_OUT_ADC_REC A_OUT_ADC_REC_L 210d056fa04SAlexander Leidinger 211d056fa04SAlexander Leidinger #include "emu10k1-alsa%diked.h" 212d056fa04SAlexander Leidinger #include "p16v-alsa%diked.h" 213d056fa04SAlexander Leidinger #include "p17v-alsa%diked.h" 214d056fa04SAlexander Leidinger 215d056fa04SAlexander Leidinger #define C_FRONT_L 0 216d056fa04SAlexander Leidinger #define C_FRONT_R 1 217d056fa04SAlexander Leidinger #define C_REC_L 2 218d056fa04SAlexander Leidinger #define C_REC_R 3 219d056fa04SAlexander Leidinger #define C_REAR_L 4 220d056fa04SAlexander Leidinger #define C_REAR_R 5 221d056fa04SAlexander Leidinger #define C_CENTER 6 222d056fa04SAlexander Leidinger #define C_SUB 7 223d056fa04SAlexander Leidinger #define C_SIDE_L 8 224d056fa04SAlexander Leidinger #define C_SIDE_R 9 225d056fa04SAlexander Leidinger #define NUM_CACHES 10 226d056fa04SAlexander Leidinger 227d056fa04SAlexander Leidinger #define EMU_MAX_GPR 512 228d056fa04SAlexander Leidinger #define EMU_MAX_IRQ_CONSUMERS 32 229d056fa04SAlexander Leidinger 230d056fa04SAlexander Leidinger struct emu_voice { 231d056fa04SAlexander Leidinger int vnum; 232d056fa04SAlexander Leidinger int b16:1, stereo:1, busy:1, running:1, ismaster:1; 233d056fa04SAlexander Leidinger int speed; 234d056fa04SAlexander Leidinger int start; 235d056fa04SAlexander Leidinger int end; 236d056fa04SAlexander Leidinger int vol; 237d056fa04SAlexander Leidinger uint32_t buf; 238d056fa04SAlexander Leidinger void *vbuf; 239d056fa04SAlexander Leidinger struct emu_voice *slave; 240d056fa04SAlexander Leidinger uint32_t sa; 241d056fa04SAlexander Leidinger uint32_t ea; 242d056fa04SAlexander Leidinger }; 243d056fa04SAlexander Leidinger 244d056fa04SAlexander Leidinger struct emu_memblk { 245d056fa04SAlexander Leidinger SLIST_ENTRY(emu_memblk) link; 246d056fa04SAlexander Leidinger void *buf; 247d056fa04SAlexander Leidinger char owner[16]; 248d056fa04SAlexander Leidinger bus_addr_t buf_addr; 249d056fa04SAlexander Leidinger uint32_t pte_start, pte_size; 250d056fa04SAlexander Leidinger }; 251d056fa04SAlexander Leidinger 252d056fa04SAlexander Leidinger struct emu_mem { 253d056fa04SAlexander Leidinger uint8_t bmap[MAXPAGES / 8]; 254d056fa04SAlexander Leidinger uint32_t *ptb_pages; 255d056fa04SAlexander Leidinger void *silent_page; 256d056fa04SAlexander Leidinger bus_addr_t silent_page_addr; 257d056fa04SAlexander Leidinger bus_addr_t ptb_pages_addr; 258d056fa04SAlexander Leidinger bus_dma_tag_t dmat; 259d056fa04SAlexander Leidinger SLIST_HEAD(, emu_memblk) blocks; 260d056fa04SAlexander Leidinger }; 261d056fa04SAlexander Leidinger 262d056fa04SAlexander Leidinger /* rm */ 263d056fa04SAlexander Leidinger struct emu_rm { 264d056fa04SAlexander Leidinger struct emu_sc_info *card; 265d056fa04SAlexander Leidinger struct mtx gpr_lock; 266d056fa04SAlexander Leidinger signed int allocmap[EMU_MAX_GPR]; 267d056fa04SAlexander Leidinger int num_gprs; 268d056fa04SAlexander Leidinger int last_free_gpr; 269d056fa04SAlexander Leidinger int num_used; 270d056fa04SAlexander Leidinger }; 271d056fa04SAlexander Leidinger 272d056fa04SAlexander Leidinger struct emu_intr_handler { 273d056fa04SAlexander Leidinger void* softc; 274d056fa04SAlexander Leidinger uint32_t intr_mask; 275d056fa04SAlexander Leidinger uint32_t inte_mask; 276d056fa04SAlexander Leidinger uint32_t(*irq_func) (void *softc, uint32_t irq); 277d056fa04SAlexander Leidinger }; 278d056fa04SAlexander Leidinger 279d056fa04SAlexander Leidinger struct emu_sc_info { 280d056fa04SAlexander Leidinger struct mtx lock; 281d056fa04SAlexander Leidinger struct mtx rw; /* Hardware exclusive access lock */ 282d056fa04SAlexander Leidinger 283d056fa04SAlexander Leidinger /* Hardware and subdevices */ 284d056fa04SAlexander Leidinger device_t dev; 285d056fa04SAlexander Leidinger device_t pcm[5]; 286d056fa04SAlexander Leidinger device_t midi[2]; 287d056fa04SAlexander Leidinger uint32_t type; 288d056fa04SAlexander Leidinger uint32_t rev; 289d056fa04SAlexander Leidinger 290d056fa04SAlexander Leidinger bus_space_tag_t st; 291d056fa04SAlexander Leidinger bus_space_handle_t sh; 292d056fa04SAlexander Leidinger 293d056fa04SAlexander Leidinger struct cdev *cdev; /* /dev/emu10k character device */ 294d056fa04SAlexander Leidinger struct mtx emu10kx_lock; 295d056fa04SAlexander Leidinger int emu10kx_isopen; 296d056fa04SAlexander Leidinger struct sbuf emu10kx_sbuf; 297d056fa04SAlexander Leidinger int emu10kx_bufptr; 298d056fa04SAlexander Leidinger 299d056fa04SAlexander Leidinger 300d056fa04SAlexander Leidinger /* Resources */ 301d056fa04SAlexander Leidinger struct resource *reg; 302d056fa04SAlexander Leidinger struct resource *irq; 303d056fa04SAlexander Leidinger void *ih; 304d056fa04SAlexander Leidinger 305d056fa04SAlexander Leidinger /* IRQ handlers */ 306d056fa04SAlexander Leidinger struct emu_intr_handler ihandler[EMU_MAX_IRQ_CONSUMERS]; 307d056fa04SAlexander Leidinger 308d056fa04SAlexander Leidinger /* Card HW configuration */ 309d056fa04SAlexander Leidinger unsigned int mchannel_fx; 310d056fa04SAlexander Leidinger unsigned int dsp_zero; 311d056fa04SAlexander Leidinger unsigned int code_base; 312d056fa04SAlexander Leidinger unsigned int code_size; 313d056fa04SAlexander Leidinger unsigned int gpr_base; 314d056fa04SAlexander Leidinger unsigned int num_gprs; 315d056fa04SAlexander Leidinger unsigned int input_base; 316d056fa04SAlexander Leidinger unsigned int output_base; 317d056fa04SAlexander Leidinger unsigned int efxc_base; 318d056fa04SAlexander Leidinger unsigned int opcode_shift; 319d056fa04SAlexander Leidinger unsigned int high_operand_shift; 320d056fa04SAlexander Leidinger unsigned int address_mask; 321d056fa04SAlexander Leidinger uint32_t is_emu10k1:1, is_emu10k2, is_ca0102, is_ca0108:1, 322d056fa04SAlexander Leidinger has_ac97:1, has_51:1, has_71:1, 323d056fa04SAlexander Leidinger enable_ir:1, enable_debug:1, 324d056fa04SAlexander Leidinger broken_digital:1, is_cardbus:1; 325d056fa04SAlexander Leidinger 326d056fa04SAlexander Leidinger unsigned int num_inputs; 327d056fa04SAlexander Leidinger unsigned int num_outputs; 328d056fa04SAlexander Leidinger unsigned int num_fxbuses; 329d056fa04SAlexander Leidinger unsigned int routing_code_start; 330d056fa04SAlexander Leidinger unsigned int routing_code_end; 331d056fa04SAlexander Leidinger 332d056fa04SAlexander Leidinger /* HW resources */ 333d056fa04SAlexander Leidinger struct emu_voice voice[NUM_G]; /* Hardware voices */ 334d056fa04SAlexander Leidinger uint32_t irq_mask[EMU_MAX_IRQ_CONSUMERS]; /* IRQ manager data */ 335d056fa04SAlexander Leidinger int timer[EMU_MAX_IRQ_CONSUMERS]; /* timer */ 336d056fa04SAlexander Leidinger int timerinterval; 337d056fa04SAlexander Leidinger struct emu_rm *rm; 338d056fa04SAlexander Leidinger struct emu_mem mem; /* memory */ 339d056fa04SAlexander Leidinger int bufsz; 340d056fa04SAlexander Leidinger 341d056fa04SAlexander Leidinger /* Mixer */ 342d056fa04SAlexander Leidinger int mixer_gpr[NUM_MIXERS]; 343d056fa04SAlexander Leidinger int mixer_volcache[NUM_MIXERS]; 344d056fa04SAlexander Leidinger int cache_gpr[NUM_CACHES]; 345d056fa04SAlexander Leidinger struct sysctl_ctx_list *ctx; 346d056fa04SAlexander Leidinger struct sysctl_oid *root; 347d056fa04SAlexander Leidinger }; 348d056fa04SAlexander Leidinger 349d056fa04SAlexander Leidinger static void emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error); 350d056fa04SAlexander Leidinger static void* emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr); 351d056fa04SAlexander Leidinger static void emu_free(struct emu_mem *mem, void *dmabuf); 352d056fa04SAlexander Leidinger static void* emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char * owner); 353d056fa04SAlexander Leidinger static int emu_memfree(struct emu_mem *mem, void *membuf); 354d056fa04SAlexander Leidinger static int emu_memstart(struct emu_mem *mem, void *membuf); 355d056fa04SAlexander Leidinger 356d056fa04SAlexander Leidinger /* /dev */ 357d056fa04SAlexander Leidinger static int emu10kx_dev_init(struct emu_sc_info *sc); 358d056fa04SAlexander Leidinger static int emu10kx_dev_uninit(struct emu_sc_info *sc); 359d056fa04SAlexander Leidinger static int emu10kx_prepare(struct emu_sc_info *sc, struct sbuf *s); 360d056fa04SAlexander Leidinger 361d056fa04SAlexander Leidinger static void emumix_set_mode(struct emu_sc_info *sc, int mode); 362d056fa04SAlexander Leidinger static void emumix_set_spdif_mode(struct emu_sc_info *sc, int mode); 363d056fa04SAlexander Leidinger static void emumix_set_fxvol(struct emu_sc_info *sc, unsigned gpr, int32_t vol); 364d056fa04SAlexander Leidinger static void emumix_set_gpr(struct emu_sc_info *sc, unsigned gpr, int32_t val); 365d056fa04SAlexander Leidinger static int sysctl_emu_mixer_control(SYSCTL_HANDLER_ARGS); 366d056fa04SAlexander Leidinger 367d056fa04SAlexander Leidinger static int emu_rm_init(struct emu_sc_info *sc); 368d056fa04SAlexander Leidinger static int emu_rm_uninit(struct emu_sc_info *sc); 369d056fa04SAlexander Leidinger static int emu_rm_gpr_alloc(struct emu_rm *rm, int count); 370d056fa04SAlexander Leidinger 371d056fa04SAlexander Leidinger static int emu_getcard(device_t dev); 372d056fa04SAlexander Leidinger static uint32_t emu_rd_nolock(struct emu_sc_info *sc, unsigned int regno, unsigned int size); 373d056fa04SAlexander Leidinger static void emu_wr_nolock(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size); 374d056fa04SAlexander Leidinger static void emu_wr_cbptr(struct emu_sc_info *sc, uint32_t data); 375d056fa04SAlexander Leidinger 376d056fa04SAlexander Leidinger static void emu_vstop(struct emu_sc_info *sc, char channel, int enable); 377d056fa04SAlexander Leidinger 378d056fa04SAlexander Leidinger static void emu_intr(void *p); 379d056fa04SAlexander Leidinger static void emu_wrefx(struct emu_sc_info *sc, unsigned int pc, unsigned int data); 380d056fa04SAlexander Leidinger static 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); 381d056fa04SAlexander Leidinger static void emu_initefx(struct emu_sc_info *sc); 382d056fa04SAlexander Leidinger 383d056fa04SAlexander Leidinger static int emu_cardbus_init(struct emu_sc_info *sc); 384d056fa04SAlexander Leidinger static int emu_init(struct emu_sc_info *sc); 385d056fa04SAlexander Leidinger static int emu_uninit(struct emu_sc_info *sc); 386d056fa04SAlexander Leidinger 387d056fa04SAlexander Leidinger static int emu_read_ivar(device_t bus __unused, device_t dev, int ivar_index, uintptr_t * result); 388d056fa04SAlexander Leidinger static int emu_write_ivar(device_t bus __unused, device_t dev __unused, 389d056fa04SAlexander Leidinger int ivar_index, uintptr_t value __unused); 390d056fa04SAlexander Leidinger 391d056fa04SAlexander Leidinger static int emu_pci_probe(device_t dev); 392d056fa04SAlexander Leidinger static int emu_pci_attach(device_t dev); 393d056fa04SAlexander Leidinger static int emu_pci_detach(device_t dev); 394d056fa04SAlexander Leidinger static int emu_modevent(module_t mod __unused, int cmd, void *data __unused); 395d056fa04SAlexander Leidinger 396d056fa04SAlexander Leidinger /* Supported cards */ 397d056fa04SAlexander Leidinger struct emu_hwinfo { 398d056fa04SAlexander Leidinger uint16_t vendor; 399d056fa04SAlexander Leidinger uint16_t device; 400d056fa04SAlexander Leidinger uint16_t subvendor; 401d056fa04SAlexander Leidinger uint16_t subdevice; 402d056fa04SAlexander Leidinger char SBcode[8]; 403d056fa04SAlexander Leidinger char desc[32]; 404d056fa04SAlexander Leidinger int flags; 405d056fa04SAlexander Leidinger }; 406d056fa04SAlexander Leidinger 407d056fa04SAlexander Leidinger static struct emu_hwinfo emu_cards[] = { 408d056fa04SAlexander Leidinger /* 0x0020..0x002f 4.0 EMU10K1 cards */ 409d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x0020, "CT4850", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 410d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x0021, "CT4620", "SBLive!", HAS_AC97 | IS_EMU10K1}, 411d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x002f, "CT????", "SBLive! mainboard implementation", HAS_AC97 | IS_EMU10K1}, 412d056fa04SAlexander Leidinger 413d056fa04SAlexander Leidinger /* (range unknown) 5.1 EMU10K1 cards */ 414d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x100a, "CT????", "SBLive! 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1}, 415d056fa04SAlexander Leidinger 416d056fa04SAlexander Leidinger /* 0x80??..0x805? 4.0 EMU10K1 cards */ 417d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8022, "CT4780", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 418d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8023, "CT4790", "SB PCI512", HAS_AC97 | IS_EMU10K1}, 419d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8024, "CT4760", "SBLive!", HAS_AC97 | IS_EMU10K1}, 420d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8025, "CT????", "SBLive! Mainboard Implementation", HAS_AC97 | IS_EMU10K1}, 421d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8026, "CT4830", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 422d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8027, "CT4832", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 423d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8028, "CT4760", "SBLive! OEM version", HAS_AC97 | IS_EMU10K1}, 424d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8031, "CT4831", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 425d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8040, "CT4760", "SBLive!", HAS_AC97 | IS_EMU10K1}, 426d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8051, "CT4850", "SBLive! Value", HAS_AC97 | IS_EMU10K1}, 427d056fa04SAlexander Leidinger 428d056fa04SAlexander Leidinger /* 0x8061..0x???? 5.1 EMU10K1 cards */ 429d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8061, "SB????", "SBLive! Player 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1}, 430d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8064, "SB????", "SBLive! 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1}, 431d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8065, "SB0220", "SBLive! 5.1 Digital", HAS_AC97 | HAS_51 | IS_EMU10K1}, 432d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8066, "CT4780", "SBLive! 5.1 Digital", HAS_AC97 | HAS_51 | IS_EMU10K1}, 433d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x8067, "SB????", "SBLive!", HAS_AC97 | HAS_51 | IS_EMU10K1}, 434d056fa04SAlexander Leidinger 435d056fa04SAlexander Leidinger /* Generic SB Live! */ 436d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x0000, "SB????", "SBLive! (Unknown model)", HAS_AC97 | IS_EMU10K1}, 437d056fa04SAlexander Leidinger 438d056fa04SAlexander Leidinger /* 0x0041..0x0043 EMU10K2 (some kind of Audigy) cards */ 439d056fa04SAlexander Leidinger 440d056fa04SAlexander Leidinger /* 0x0051..0x0051 5.1 CA0100-IAF cards */ 441d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x0051, "SB0090", "Audigy", HAS_AC97 | HAS_51 | IS_EMU10K2}, 442d056fa04SAlexander Leidinger /* ES is CA0100-IDF chip that don't work in digital mode */ 443d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x0052, "SB0160", "Audigy ES", HAS_AC97 | HAS_71 | IS_EMU10K2 | BROKEN_DIGITAL}, 444d056fa04SAlexander Leidinger /* 0x0053..0x005C 5.1 CA0101-NAF cards */ 445d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x0053, "SB0090", "Audigy Player/OEM", HAS_AC97 | HAS_51 | IS_EMU10K2}, 446d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x0058, "SB0090", "Audigy Player/OEM", HAS_AC97 | HAS_51 | IS_EMU10K2}, 447d056fa04SAlexander Leidinger 448d056fa04SAlexander Leidinger /* 0x1002..0x1009 5.1 CA0102-IAT cards */ 449d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x1002, "SB????", "Audigy 2 Platinum", HAS_51 | IS_CA0102}, 450d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x1005, "SB????", "Audigy 2 Platinum EX", HAS_51 | IS_CA0102}, 451d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x1007, "SB0240", "Audigy 2", HAS_AC97 | HAS_51 | IS_CA0102}, 452d056fa04SAlexander Leidinger 453d056fa04SAlexander Leidinger /* 0x2001..0x2003 7.1 CA0102-ICT cards */ 454d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x2001, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102}, 455d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x2002, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102}, 456d056fa04SAlexander Leidinger 457d056fa04SAlexander Leidinger /* (range unknown) 7.1 CA0102-xxx Audigy 4 cards */ 458d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x2007, "SB0380", "Audigy 4 Pro", HAS_AC97 | HAS_71 | IS_CA0102}, 459d056fa04SAlexander Leidinger 460d056fa04SAlexander Leidinger /* Generic Audigy or Audigy 2 */ 461d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x0000, "SB????", "Audigy (Unknown model)", HAS_AC97 | HAS_51 | IS_EMU10K2}, 462d056fa04SAlexander Leidinger 463d056fa04SAlexander Leidinger /* We don't support CA0103-DAT (Audigy LS) cards */ 464d056fa04SAlexander Leidinger /* There is NO CA0104-xxx cards */ 465d056fa04SAlexander Leidinger /* There is NO CA0105-xxx cards */ 466d056fa04SAlexander Leidinger /* We don't support CA0106-DAT (SB Live! 24 bit) cards */ 467d056fa04SAlexander Leidinger /* There is NO CA0107-xxx cards */ 468d056fa04SAlexander Leidinger 469d056fa04SAlexander Leidinger /* 0x1000..0x1001 7.1 CA0108-IAT cards */ 470d056fa04SAlexander Leidinger {0x1102, 0x0008, 0x1102, 0x1000, "SB????", "Audigy 2 LS", HAS_AC97 | HAS_51 | IS_CA0108 | DIGITAL_ONLY}, 471d056fa04SAlexander Leidinger {0x1102, 0x0008, 0x1102, 0x1001, "SB0400", "Audigy 2 Value", HAS_AC97 | HAS_71 | IS_CA0108 | DIGITAL_ONLY}, 472d056fa04SAlexander Leidinger {0x1102, 0x0008, 0x1102, 0x1021, "SB0610", "Audigy 4", HAS_AC97 | HAS_71 | IS_CA0108 | DIGITAL_ONLY}, 473d056fa04SAlexander Leidinger 474d056fa04SAlexander Leidinger {0x1102, 0x0008, 0x1102, 0x2001, "SB0530", "Audigy 2 ZS CardBus", HAS_AC97 | HAS_71 | IS_CA0108 | IS_CARDBUS}, 475d056fa04SAlexander Leidinger 476d056fa04SAlexander Leidinger {0x1102, 0x0008, 0x0000, 0x0000, "SB????", "Audigy 2 Value (Unknown model)", HAS_AC97 | HAS_51 | IS_CA0108}, 477d056fa04SAlexander Leidinger }; 478d056fa04SAlexander Leidinger /* Unsupported cards */ 479d056fa04SAlexander Leidinger 480d056fa04SAlexander Leidinger static struct emu_hwinfo emu_bad_cards[] = { 481d056fa04SAlexander Leidinger /* APS cards should be possible to support */ 482d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x4001, "EMUAPS", "E-mu APS", 0}, 483d056fa04SAlexander Leidinger {0x1102, 0x0002, 0x1102, 0x4002, "EMUAPS", "E-mu APS", 0}, 484d056fa04SAlexander Leidinger {0x1102, 0x0004, 0x1102, 0x4001, "EMU???", "E-mu 1212m [4001]", 0}, 485d056fa04SAlexander Leidinger /* Similar-named ("Live!" or "Audigy") cards on different chipsets */ 486d056fa04SAlexander Leidinger {0x1102, 0x8064, 0x0000, 0x0000, "SB0100", "SBLive! 5.1 OEM", 0}, 487d056fa04SAlexander Leidinger {0x1102, 0x0006, 0x0000, 0x0000, "SB0200", "DELL OEM SBLive! Value", 0}, 488d056fa04SAlexander Leidinger {0x1102, 0x0007, 0x0000, 0x0000, "SB0310", "Audigy LS", 0}, 489d056fa04SAlexander Leidinger }; 490d056fa04SAlexander Leidinger 491d056fa04SAlexander Leidinger /* 492d056fa04SAlexander Leidinger * Get best known information about device. 493d056fa04SAlexander Leidinger */ 494d056fa04SAlexander Leidinger static int 495d056fa04SAlexander Leidinger emu_getcard(device_t dev) 496d056fa04SAlexander Leidinger { 497d056fa04SAlexander Leidinger uint16_t device; 498d056fa04SAlexander Leidinger uint16_t subdevice; 499d056fa04SAlexander Leidinger int n_cards; 500d056fa04SAlexander Leidinger int thiscard; 501d056fa04SAlexander Leidinger int i; 502d056fa04SAlexander Leidinger 503d056fa04SAlexander Leidinger device = pci_read_config(dev, PCIR_DEVICE, /* bytes */ 2); 504d056fa04SAlexander Leidinger subdevice = pci_read_config(dev, PCIR_SUBDEV_0, /* bytes */ 2); 505d056fa04SAlexander Leidinger 506d056fa04SAlexander Leidinger n_cards = sizeof(emu_cards) / sizeof(struct emu_hwinfo); 507d056fa04SAlexander Leidinger thiscard = (-1); 508d056fa04SAlexander Leidinger for (i = 0; i < n_cards; i++) { 509d056fa04SAlexander Leidinger if (device == emu_cards[i].device) { 510d056fa04SAlexander Leidinger if (subdevice == emu_cards[i].subdevice) { 511d056fa04SAlexander Leidinger thiscard = i; 512d056fa04SAlexander Leidinger break; 513d056fa04SAlexander Leidinger } 514d056fa04SAlexander Leidinger if (0x0000 == emu_cards[i].subdevice) { 515d056fa04SAlexander Leidinger thiscard = i; 516d056fa04SAlexander Leidinger /* don't break, we can get more specific card 517d056fa04SAlexander Leidinger * later in the list */ 518d056fa04SAlexander Leidinger } 519d056fa04SAlexander Leidinger } 520d056fa04SAlexander Leidinger } 521d056fa04SAlexander Leidinger 522d056fa04SAlexander Leidinger n_cards = sizeof(emu_bad_cards) / sizeof(struct emu_hwinfo); 523d056fa04SAlexander Leidinger for (i = 0; i < n_cards; i++) { 524d056fa04SAlexander Leidinger if (device == emu_bad_cards[i].device) { 525d056fa04SAlexander Leidinger if (subdevice == emu_bad_cards[i].subdevice) { 526d056fa04SAlexander Leidinger thiscard = (-1); 527d056fa04SAlexander Leidinger break; 528d056fa04SAlexander Leidinger } 529d056fa04SAlexander Leidinger if (0x0000 == emu_bad_cards[i].subdevice) { 530d056fa04SAlexander Leidinger thiscard = (-1); 531d056fa04SAlexander Leidinger break; /* we avoid all this cards */ 532d056fa04SAlexander Leidinger } 533d056fa04SAlexander Leidinger } 534d056fa04SAlexander Leidinger } 535d056fa04SAlexander Leidinger return (thiscard); 536d056fa04SAlexander Leidinger } 537d056fa04SAlexander Leidinger 538d056fa04SAlexander Leidinger 539d056fa04SAlexander Leidinger /* 540d056fa04SAlexander Leidinger * Base hardware interface are 32 (Audigy) or 64 (Audigy2) registers. 541d056fa04SAlexander Leidinger * Some of them are used directly, some of them provide pointer / data pairs. 542d056fa04SAlexander Leidinger */ 543d056fa04SAlexander Leidinger static uint32_t 544d056fa04SAlexander Leidinger emu_rd_nolock(struct emu_sc_info *sc, unsigned int regno, unsigned int size) 545d056fa04SAlexander Leidinger { 546d056fa04SAlexander Leidinger 547d056fa04SAlexander Leidinger KASSERT(sc != NULL, ("emu_rd: NULL sc")); 548d056fa04SAlexander Leidinger switch (size) { 549d056fa04SAlexander Leidinger case 1: 550d056fa04SAlexander Leidinger return (bus_space_read_1(sc->st, sc->sh, regno)); 551d056fa04SAlexander Leidinger case 2: 552d056fa04SAlexander Leidinger return (bus_space_read_2(sc->st, sc->sh, regno)); 553d056fa04SAlexander Leidinger case 4: 554d056fa04SAlexander Leidinger return (bus_space_read_4(sc->st, sc->sh, regno)); 555d056fa04SAlexander Leidinger } 556d056fa04SAlexander Leidinger return (0xffffffff); 557d056fa04SAlexander Leidinger } 558d056fa04SAlexander Leidinger 559d056fa04SAlexander Leidinger static void 560d056fa04SAlexander Leidinger emu_wr_nolock(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size) 561d056fa04SAlexander Leidinger { 562d056fa04SAlexander Leidinger 563d056fa04SAlexander Leidinger KASSERT(sc != NULL, ("emu_rd: NULL sc")); 564d056fa04SAlexander Leidinger switch (size) { 565d056fa04SAlexander Leidinger case 1: 566d056fa04SAlexander Leidinger bus_space_write_1(sc->st, sc->sh, regno, data); 567d056fa04SAlexander Leidinger break; 568d056fa04SAlexander Leidinger case 2: 569d056fa04SAlexander Leidinger bus_space_write_2(sc->st, sc->sh, regno, data); 570d056fa04SAlexander Leidinger break; 571d056fa04SAlexander Leidinger case 4: 572d056fa04SAlexander Leidinger bus_space_write_4(sc->st, sc->sh, regno, data); 573d056fa04SAlexander Leidinger break; 574d056fa04SAlexander Leidinger } 575d056fa04SAlexander Leidinger } 576d056fa04SAlexander Leidinger /* 577d056fa04SAlexander Leidinger * PTR / DATA interface. Access to EMU10Kx is made 578d056fa04SAlexander Leidinger * via (channel, register) pair. Some registers are channel-specific, 579d056fa04SAlexander Leidinger * some not. 580d056fa04SAlexander Leidinger */ 581d056fa04SAlexander Leidinger uint32_t 582d056fa04SAlexander Leidinger emu_rdptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg) 583d056fa04SAlexander Leidinger { 584d056fa04SAlexander Leidinger uint32_t ptr, val, mask, size, offset; 585d056fa04SAlexander Leidinger 586d056fa04SAlexander Leidinger ptr = ((reg << 16) & sc->address_mask) | (chn & PTR_CHANNELNUM_MASK); 587d056fa04SAlexander Leidinger mtx_lock(&sc->rw); 588d056fa04SAlexander Leidinger emu_wr_nolock(sc, PTR, ptr, 4); 589d056fa04SAlexander Leidinger val = emu_rd_nolock(sc, DATA, 4); 590d056fa04SAlexander Leidinger mtx_unlock(&sc->rw); 591d056fa04SAlexander Leidinger /* 592d056fa04SAlexander Leidinger * XXX Some register numbers has data size and offset encoded in 593d056fa04SAlexander Leidinger * it to get only part of 32bit register. This use is not described 594d056fa04SAlexander Leidinger * in register name, be careful! 595d056fa04SAlexander Leidinger */ 596d056fa04SAlexander Leidinger if (reg & 0xff000000) { 597d056fa04SAlexander Leidinger size = (reg >> 24) & 0x3f; 598d056fa04SAlexander Leidinger offset = (reg >> 16) & 0x1f; 599d056fa04SAlexander Leidinger mask = ((1 << size) - 1) << offset; 600d056fa04SAlexander Leidinger val &= mask; 601d056fa04SAlexander Leidinger val >>= offset; 602d056fa04SAlexander Leidinger } 603d056fa04SAlexander Leidinger return (val); 604d056fa04SAlexander Leidinger } 605d056fa04SAlexander Leidinger 606d056fa04SAlexander Leidinger void 607d056fa04SAlexander Leidinger emu_wrptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg, uint32_t data) 608d056fa04SAlexander Leidinger { 609d056fa04SAlexander Leidinger uint32_t ptr, mask, size, offset; 610d056fa04SAlexander Leidinger ptr = ((reg << 16) & sc->address_mask) | (chn & PTR_CHANNELNUM_MASK); 611d056fa04SAlexander Leidinger mtx_lock(&sc->rw); 612d056fa04SAlexander Leidinger emu_wr_nolock(sc, PTR, ptr, 4); 613d056fa04SAlexander Leidinger /* 614d056fa04SAlexander Leidinger * XXX Another kind of magic encoding in register number. This can 615d056fa04SAlexander Leidinger * give you side effect - it will read previous data from register 616d056fa04SAlexander Leidinger * and change only required bits. 617d056fa04SAlexander Leidinger */ 618d056fa04SAlexander Leidinger if (reg & 0xff000000) { 619d056fa04SAlexander Leidinger size = (reg >> 24) & 0x3f; 620d056fa04SAlexander Leidinger offset = (reg >> 16) & 0x1f; 621d056fa04SAlexander Leidinger mask = ((1 << size) - 1) << offset; 622d056fa04SAlexander Leidinger data <<= offset; 623d056fa04SAlexander Leidinger data &= mask; 624d056fa04SAlexander Leidinger data |= emu_rd_nolock(sc, DATA, 4) & ~mask; 625d056fa04SAlexander Leidinger } 626d056fa04SAlexander Leidinger emu_wr_nolock(sc, DATA, data, 4); 627d056fa04SAlexander Leidinger mtx_unlock(&sc->rw); 628d056fa04SAlexander Leidinger } 629d056fa04SAlexander Leidinger /* 630d056fa04SAlexander Leidinger * PTR2 / DATA2 interface. Access to P16v is made 631d056fa04SAlexander Leidinger * via (channel, register) pair. Some registers are channel-specific, 632d056fa04SAlexander Leidinger * some not. This interface is supported by CA0102 and CA0108 chips only. 633d056fa04SAlexander Leidinger */ 634d056fa04SAlexander Leidinger uint32_t 635d056fa04SAlexander Leidinger emu_rd_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg) 636d056fa04SAlexander Leidinger { 637d056fa04SAlexander Leidinger uint32_t val; 638d056fa04SAlexander Leidinger 639d056fa04SAlexander Leidinger mtx_lock(&sc->rw); 640d056fa04SAlexander Leidinger emu_wr_nolock(sc, PTR2, (reg << 16) | chn, 4); 641d056fa04SAlexander Leidinger val = emu_rd_nolock(sc, DATA2, 4); 642d056fa04SAlexander Leidinger mtx_unlock(&sc->rw); 643d056fa04SAlexander Leidinger return (val); 644d056fa04SAlexander Leidinger } 645d056fa04SAlexander Leidinger 646d056fa04SAlexander Leidinger void 647d056fa04SAlexander Leidinger emu_wr_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg, uint32_t data) 648d056fa04SAlexander Leidinger { 649d056fa04SAlexander Leidinger 650d056fa04SAlexander Leidinger mtx_lock(&sc->rw); 651d056fa04SAlexander Leidinger emu_wr_nolock(sc, PTR2, (reg << 16) | chn, 4); 652d056fa04SAlexander Leidinger emu_wr_nolock(sc, DATA2, data, 4); 653d056fa04SAlexander Leidinger mtx_unlock(&sc->rw); 654d056fa04SAlexander Leidinger } 655d056fa04SAlexander Leidinger /* 656d056fa04SAlexander Leidinger * XXX CardBus interface. Not tested on any real hardware. 657d056fa04SAlexander Leidinger */ 658d056fa04SAlexander Leidinger static void 659d056fa04SAlexander Leidinger emu_wr_cbptr(struct emu_sc_info *sc, uint32_t data) 660d056fa04SAlexander Leidinger { 661d056fa04SAlexander Leidinger uint32_t val; 662d056fa04SAlexander Leidinger 663d056fa04SAlexander Leidinger /* 0x38 is IPE3 (CD S/PDIF interrupt pending register) on CA0102 Seems 664d056fa04SAlexander Leidinger * to be some reg/value accessible kind of config register on CardBus 665d056fa04SAlexander Leidinger * CA0108, with value(?) in top 16 bit, address(?) in low 16 */ 666d056fa04SAlexander Leidinger mtx_lock(&sc->rw); 667d056fa04SAlexander Leidinger val = emu_rd_nolock(sc, 0x38, 4); 668d056fa04SAlexander Leidinger emu_wr_nolock(sc, 0x38, data, 4); 669d056fa04SAlexander Leidinger val = emu_rd_nolock(sc, 0x38, 4); 670d056fa04SAlexander Leidinger mtx_unlock(&sc->rw); 671d056fa04SAlexander Leidinger } 672d056fa04SAlexander Leidinger 673d056fa04SAlexander Leidinger /* 674d056fa04SAlexander Leidinger * Direct hardware register access 675d056fa04SAlexander Leidinger */ 676d056fa04SAlexander Leidinger void 677d056fa04SAlexander Leidinger emu_wr(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size) 678d056fa04SAlexander Leidinger { 679d056fa04SAlexander Leidinger 680d056fa04SAlexander Leidinger mtx_lock(&sc->rw); 681d056fa04SAlexander Leidinger emu_wr_nolock(sc, regno, data, size); 682d056fa04SAlexander Leidinger mtx_unlock(&sc->rw); 683d056fa04SAlexander Leidinger } 684d056fa04SAlexander Leidinger 685d056fa04SAlexander Leidinger uint32_t 686d056fa04SAlexander Leidinger emu_rd(struct emu_sc_info *sc, unsigned int regno, unsigned int size) 687d056fa04SAlexander Leidinger { 688d056fa04SAlexander Leidinger uint32_t rd; 689d056fa04SAlexander Leidinger 690d056fa04SAlexander Leidinger mtx_lock(&sc->rw); 691d056fa04SAlexander Leidinger rd = emu_rd_nolock(sc, regno, size); 692d056fa04SAlexander Leidinger mtx_unlock(&sc->rw); 693d056fa04SAlexander Leidinger return (rd); 694d056fa04SAlexander Leidinger } 695d056fa04SAlexander Leidinger 696d056fa04SAlexander Leidinger /* 697d056fa04SAlexander Leidinger * Enabling IR MIDI messages is another kind of black magic. It just 698d056fa04SAlexander Leidinger * has to be made this way. It really do it. 699d056fa04SAlexander Leidinger */ 700d056fa04SAlexander Leidinger void 701d056fa04SAlexander Leidinger emu_enable_ir(struct emu_sc_info *sc) 702d056fa04SAlexander Leidinger { 703d056fa04SAlexander Leidinger uint32_t iocfg; 704d056fa04SAlexander Leidinger 705d056fa04SAlexander Leidinger mtx_lock(&sc->rw); 706d056fa04SAlexander Leidinger if (sc->is_emu10k2 || sc->is_ca0102) { 707d056fa04SAlexander Leidinger iocfg = emu_rd_nolock(sc, A_IOCFG, 2); 708d056fa04SAlexander Leidinger emu_wr_nolock(sc, A_IOCFG, iocfg | A_IOCFG_GPOUT2, 2); 709d056fa04SAlexander Leidinger DELAY(500); 710d056fa04SAlexander Leidinger emu_wr_nolock(sc, A_IOCFG, iocfg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, 2); 711d056fa04SAlexander Leidinger DELAY(500); 712d056fa04SAlexander Leidinger emu_wr_nolock(sc, A_IOCFG, iocfg | A_IOCFG_GPOUT1, 2); 713d056fa04SAlexander Leidinger DELAY(100); 714d056fa04SAlexander Leidinger emu_wr_nolock(sc, A_IOCFG, iocfg, 2); 715d056fa04SAlexander Leidinger device_printf(sc->dev, "Audigy IR MIDI events enabled.\n"); 716d056fa04SAlexander Leidinger sc->enable_ir = 1; 717d056fa04SAlexander Leidinger } 718d056fa04SAlexander Leidinger if (sc->is_emu10k1) { 719d056fa04SAlexander Leidinger iocfg = emu_rd_nolock(sc, HCFG, 4); 720d056fa04SAlexander Leidinger emu_wr_nolock(sc, HCFG, iocfg | HCFG_GPOUT2, 4); 721d056fa04SAlexander Leidinger DELAY(500); 722d056fa04SAlexander Leidinger emu_wr_nolock(sc, HCFG, iocfg | HCFG_GPOUT1 | HCFG_GPOUT2, 4); 723d056fa04SAlexander Leidinger DELAY(100); 724d056fa04SAlexander Leidinger emu_wr_nolock(sc, HCFG, iocfg, 4); 725d056fa04SAlexander Leidinger device_printf(sc->dev, "SB Live! IR MIDI events enabled.\n"); 726d056fa04SAlexander Leidinger sc->enable_ir = 1; 727d056fa04SAlexander Leidinger } 728d056fa04SAlexander Leidinger mtx_unlock(&sc->rw); 729d056fa04SAlexander Leidinger } 730d056fa04SAlexander Leidinger 731d056fa04SAlexander Leidinger 732d056fa04SAlexander Leidinger /* 733d056fa04SAlexander Leidinger * emu_timer_ - HW timer managment 734d056fa04SAlexander Leidinger */ 735d056fa04SAlexander Leidinger int 736d056fa04SAlexander Leidinger emu_timer_create(struct emu_sc_info *sc) 737d056fa04SAlexander Leidinger { 738d056fa04SAlexander Leidinger int i, timer; 739d056fa04SAlexander Leidinger 740d056fa04SAlexander Leidinger timer = -1; 741d056fa04SAlexander Leidinger for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) 742d056fa04SAlexander Leidinger if (sc->timer[i] == 0) { 743d056fa04SAlexander Leidinger sc->timer[i] = -1; /* disable it */ 744d056fa04SAlexander Leidinger timer = i; 745d056fa04SAlexander Leidinger return (timer); 746d056fa04SAlexander Leidinger } 747d056fa04SAlexander Leidinger 748d056fa04SAlexander Leidinger return (-1); 749d056fa04SAlexander Leidinger } 750d056fa04SAlexander Leidinger 751d056fa04SAlexander Leidinger int 752d056fa04SAlexander Leidinger emu_timer_set(struct emu_sc_info *sc, int timer, int delay) 753d056fa04SAlexander Leidinger { 754d056fa04SAlexander Leidinger int i; 755d056fa04SAlexander Leidinger 756d056fa04SAlexander Leidinger RANGE(delay, 16, 1024); 757d056fa04SAlexander Leidinger RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS); 758d056fa04SAlexander Leidinger 759d056fa04SAlexander Leidinger sc->timer[timer] = delay; 760d056fa04SAlexander Leidinger for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) 761d056fa04SAlexander Leidinger if (sc->timerinterval > sc->timer[i]) 762d056fa04SAlexander Leidinger sc->timerinterval = sc->timer[i]; 763d056fa04SAlexander Leidinger 764d056fa04SAlexander Leidinger emu_wr(sc, TIMER, sc->timerinterval & 0x03ff, 2); 765d056fa04SAlexander Leidinger return (timer); 766d056fa04SAlexander Leidinger } 767d056fa04SAlexander Leidinger 768d056fa04SAlexander Leidinger int 769d056fa04SAlexander Leidinger emu_timer_enable(struct emu_sc_info *sc, int timer, int go) 770d056fa04SAlexander Leidinger { 771d056fa04SAlexander Leidinger uint32_t x; 772d056fa04SAlexander Leidinger int ena_int; 773d056fa04SAlexander Leidinger int i; 774d056fa04SAlexander Leidinger 775d056fa04SAlexander Leidinger mtx_lock(&sc->lock); 776d056fa04SAlexander Leidinger 777d056fa04SAlexander Leidinger if ((go == 1) && (sc->timer[timer] < 0)) 778d056fa04SAlexander Leidinger sc->timer[timer] = -sc->timer[timer]; 779d056fa04SAlexander Leidinger if ((go == 0) && (sc->timer[timer] > 0)) 780d056fa04SAlexander Leidinger sc->timer[timer] = -sc->timer[timer]; 781d056fa04SAlexander Leidinger 782d056fa04SAlexander Leidinger ena_int = 0; 783d056fa04SAlexander Leidinger for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) { 784d056fa04SAlexander Leidinger if (sc->timerinterval > sc->timer[i]) 785d056fa04SAlexander Leidinger sc->timerinterval = sc->timer[i]; 786d056fa04SAlexander Leidinger if (sc->timer[i] > 0) 787d056fa04SAlexander Leidinger ena_int = 1; 788d056fa04SAlexander Leidinger } 789d056fa04SAlexander Leidinger 790d056fa04SAlexander Leidinger emu_wr(sc, TIMER, sc->timerinterval & 0x03ff, 2); 791d056fa04SAlexander Leidinger 792d056fa04SAlexander Leidinger if (ena_int == 1) { 793d056fa04SAlexander Leidinger x = emu_rd(sc, INTE, 4); 794d056fa04SAlexander Leidinger x |= INTE_INTERVALTIMERENB; 795d056fa04SAlexander Leidinger emu_wr(sc, INTE, x, 4); 796d056fa04SAlexander Leidinger } else { 797d056fa04SAlexander Leidinger x = emu_rd(sc, INTE, 4); 798d056fa04SAlexander Leidinger x &= ~INTE_INTERVALTIMERENB; 799d056fa04SAlexander Leidinger emu_wr(sc, INTE, x, 4); 800d056fa04SAlexander Leidinger } 801d056fa04SAlexander Leidinger mtx_unlock(&sc->lock); 802d056fa04SAlexander Leidinger return (0); 803d056fa04SAlexander Leidinger } 804d056fa04SAlexander Leidinger 805d056fa04SAlexander Leidinger int 806d056fa04SAlexander Leidinger emu_timer_clear(struct emu_sc_info *sc, int timer) 807d056fa04SAlexander Leidinger { 808d056fa04SAlexander Leidinger emu_timer_enable(sc, timer, 0); 809d056fa04SAlexander Leidinger 810d056fa04SAlexander Leidinger mtx_lock(&sc->lock); 811d056fa04SAlexander Leidinger if (sc->timer[timer] != 0) 812d056fa04SAlexander Leidinger sc->timer[timer] = 0; 813d056fa04SAlexander Leidinger mtx_unlock(&sc->lock); 814d056fa04SAlexander Leidinger 815d056fa04SAlexander Leidinger return (timer); 816d056fa04SAlexander Leidinger } 817d056fa04SAlexander Leidinger 818d056fa04SAlexander Leidinger /* 819d056fa04SAlexander Leidinger * emu_intr_ - HW interrupt handler managment 820d056fa04SAlexander Leidinger */ 821d056fa04SAlexander Leidinger int 822d056fa04SAlexander Leidinger emu_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) 823d056fa04SAlexander Leidinger { 824d056fa04SAlexander Leidinger int i; 825d056fa04SAlexander Leidinger uint32_t x; 826d056fa04SAlexander Leidinger 827d056fa04SAlexander Leidinger mtx_lock(&sc->lock); 828d056fa04SAlexander Leidinger for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) 829d056fa04SAlexander Leidinger if (sc->ihandler[i].inte_mask == 0) { 830d056fa04SAlexander Leidinger sc->ihandler[i].inte_mask = inte_mask; 831d056fa04SAlexander Leidinger sc->ihandler[i].intr_mask = intr_mask; 832d056fa04SAlexander Leidinger sc->ihandler[i].softc = isc; 833d056fa04SAlexander Leidinger sc->ihandler[i].irq_func = func; 834d056fa04SAlexander Leidinger x = emu_rd(sc, INTE, 4); 835d056fa04SAlexander Leidinger x |= inte_mask; 836d056fa04SAlexander Leidinger emu_wr(sc, INTE, x, 4); 837d056fa04SAlexander Leidinger mtx_unlock(&sc->lock); 838d056fa04SAlexander Leidinger return (i); 839d056fa04SAlexander Leidinger } 840d056fa04SAlexander Leidinger mtx_unlock(&sc->lock); 841d056fa04SAlexander Leidinger return (-1); 842d056fa04SAlexander Leidinger } 843d056fa04SAlexander Leidinger 844d056fa04SAlexander Leidinger int 845d056fa04SAlexander Leidinger emu_intr_unregister(struct emu_sc_info *sc, int hnumber) 846d056fa04SAlexander Leidinger { 847d056fa04SAlexander Leidinger uint32_t x; 848d056fa04SAlexander Leidinger int i; 849d056fa04SAlexander Leidinger 850d056fa04SAlexander Leidinger mtx_lock(&sc->lock); 851d056fa04SAlexander Leidinger 852d056fa04SAlexander Leidinger if (sc->ihandler[hnumber].inte_mask == 0) { 853d056fa04SAlexander Leidinger mtx_unlock(&sc->lock); 854d056fa04SAlexander Leidinger return (-1); 855d056fa04SAlexander Leidinger } 856d056fa04SAlexander Leidinger 857d056fa04SAlexander Leidinger x = emu_rd(sc, INTE, 4); 858d056fa04SAlexander Leidinger x &= ~sc->ihandler[hnumber].inte_mask; 859d056fa04SAlexander Leidinger 860d056fa04SAlexander Leidinger sc->ihandler[hnumber].inte_mask = 0; 861d056fa04SAlexander Leidinger sc->ihandler[hnumber].intr_mask = 0; 862d056fa04SAlexander Leidinger sc->ihandler[hnumber].softc = NULL; 863d056fa04SAlexander Leidinger sc->ihandler[hnumber].irq_func = NULL; 864d056fa04SAlexander Leidinger 865d056fa04SAlexander Leidinger /* other interupt handlers may use this INTE value */ 866d056fa04SAlexander Leidinger for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) 867d056fa04SAlexander Leidinger if (sc->ihandler[i].inte_mask != 0) 868d056fa04SAlexander Leidinger x |= sc->ihandler[i].inte_mask; 869d056fa04SAlexander Leidinger 870d056fa04SAlexander Leidinger emu_wr(sc, INTE, x, 4); 871d056fa04SAlexander Leidinger 872d056fa04SAlexander Leidinger mtx_unlock(&sc->lock); 873d056fa04SAlexander Leidinger return (hnumber); 874d056fa04SAlexander Leidinger } 875d056fa04SAlexander Leidinger 876d056fa04SAlexander Leidinger static void 877d056fa04SAlexander Leidinger emu_intr(void *p) 878d056fa04SAlexander Leidinger { 879d056fa04SAlexander Leidinger struct emu_sc_info *sc = (struct emu_sc_info *)p; 880d056fa04SAlexander Leidinger uint32_t stat, ack; 881d056fa04SAlexander Leidinger int i; 882d056fa04SAlexander Leidinger 883d056fa04SAlexander Leidinger for (;;) { 884d056fa04SAlexander Leidinger stat = emu_rd(sc, IPR, 4); 885d056fa04SAlexander Leidinger ack = 0; 886d056fa04SAlexander Leidinger if (stat == 0) 887d056fa04SAlexander Leidinger break; 888d056fa04SAlexander Leidinger emu_wr(sc, IPR, stat, 4); 889d056fa04SAlexander Leidinger for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) { 890d056fa04SAlexander Leidinger if ((((sc->ihandler[i].intr_mask) & stat) != 0) && 891d056fa04SAlexander Leidinger (((void *)sc->ihandler[i].irq_func) != NULL)) { 892d056fa04SAlexander Leidinger ack |= sc->ihandler[i].irq_func(sc->ihandler[i].softc, 893d056fa04SAlexander Leidinger (sc->ihandler[i].intr_mask) & stat); 894d056fa04SAlexander Leidinger } 895d056fa04SAlexander Leidinger } 896d056fa04SAlexander Leidinger } 897d056fa04SAlexander Leidinger 898d056fa04SAlexander Leidinger if ((sc->is_ca0102) || (sc->is_ca0108)) 899d056fa04SAlexander Leidinger for (;;) { 900d056fa04SAlexander Leidinger stat = emu_rd(sc, IPR2, 4); 901d056fa04SAlexander Leidinger ack = 0; 902d056fa04SAlexander Leidinger if (stat == 0) 903d056fa04SAlexander Leidinger break; 904d056fa04SAlexander Leidinger emu_wr(sc, IPR2, stat, 4); 905d056fa04SAlexander Leidinger device_printf(sc->dev, "IPR2: %08x\n", stat); 906d056fa04SAlexander Leidinger break; /* to avoid infinite loop. shoud be removed 907d056fa04SAlexander Leidinger * after completion of P16V interface. */ 908d056fa04SAlexander Leidinger } 909d056fa04SAlexander Leidinger 910d056fa04SAlexander Leidinger if (sc->is_ca0102) 911d056fa04SAlexander Leidinger for (;;) { 912d056fa04SAlexander Leidinger stat = emu_rd(sc, IPR3, 4); 913d056fa04SAlexander Leidinger ack = 0; 914d056fa04SAlexander Leidinger if (stat == 0) 915d056fa04SAlexander Leidinger break; 916d056fa04SAlexander Leidinger emu_wr(sc, IPR3, stat, 4); 917d056fa04SAlexander Leidinger device_printf(sc->dev, "IPR3: %08x\n", stat); 918d056fa04SAlexander Leidinger break; /* to avoid infinite loop. should be removed 919d056fa04SAlexander Leidinger * after completion of S/PDIF interface */ 920d056fa04SAlexander Leidinger } 921d056fa04SAlexander Leidinger } 922d056fa04SAlexander Leidinger 923d056fa04SAlexander Leidinger 924d056fa04SAlexander Leidinger /* 925d056fa04SAlexander Leidinger * Get data from private emu10kx structure for PCM buffer allocation. 926d056fa04SAlexander Leidinger * Used by PCM code only. 927d056fa04SAlexander Leidinger */ 928d056fa04SAlexander Leidinger bus_dma_tag_t 929d056fa04SAlexander Leidinger emu_gettag(struct emu_sc_info *sc) 930d056fa04SAlexander Leidinger { 931d056fa04SAlexander Leidinger return (sc->mem.dmat); 932d056fa04SAlexander Leidinger } 933d056fa04SAlexander Leidinger 934d056fa04SAlexander Leidinger static void 935d056fa04SAlexander Leidinger emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error) 936d056fa04SAlexander Leidinger { 937d056fa04SAlexander Leidinger bus_addr_t *phys = (bus_addr_t *) arg; 938d056fa04SAlexander Leidinger 939d056fa04SAlexander Leidinger *phys = error ? 0 : (bus_addr_t) segs->ds_addr; 940d056fa04SAlexander Leidinger 941d056fa04SAlexander Leidinger if (bootverbose) { 942d056fa04SAlexander Leidinger printf("emu10kx: setmap (%lx, %lx), nseg=%d, error=%d\n", 943d056fa04SAlexander Leidinger (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len, 944d056fa04SAlexander Leidinger nseg, error); 945d056fa04SAlexander Leidinger } 946d056fa04SAlexander Leidinger } 947d056fa04SAlexander Leidinger 948d056fa04SAlexander Leidinger static void * 949d056fa04SAlexander Leidinger emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr) 950d056fa04SAlexander Leidinger { 951d056fa04SAlexander Leidinger void *dmabuf; 952d056fa04SAlexander Leidinger bus_dmamap_t map; 953d056fa04SAlexander Leidinger 954d056fa04SAlexander Leidinger *addr = 0; 955d056fa04SAlexander Leidinger if (bus_dmamem_alloc(mem->dmat, &dmabuf, BUS_DMA_NOWAIT, &map)) 956d056fa04SAlexander Leidinger return (NULL); 957d056fa04SAlexander Leidinger if (bus_dmamap_load(mem->dmat, map, dmabuf, sz, emu_setmap, addr, 0) || !*addr) 958d056fa04SAlexander Leidinger return (NULL); 959d056fa04SAlexander Leidinger return (dmabuf); 960d056fa04SAlexander Leidinger } 961d056fa04SAlexander Leidinger 962d056fa04SAlexander Leidinger static void 963d056fa04SAlexander Leidinger emu_free(struct emu_mem *mem, void *dmabuf) 964d056fa04SAlexander Leidinger { 965d056fa04SAlexander Leidinger bus_dmamem_free(mem->dmat, dmabuf, NULL); 966d056fa04SAlexander Leidinger } 967d056fa04SAlexander Leidinger 968d056fa04SAlexander Leidinger static void * 969d056fa04SAlexander Leidinger emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char *owner) 970d056fa04SAlexander Leidinger { 971d056fa04SAlexander Leidinger uint32_t blksz, start, idx, ofs, tmp, found; 972d056fa04SAlexander Leidinger struct emu_memblk *blk; 973d056fa04SAlexander Leidinger void *membuf; 974d056fa04SAlexander Leidinger 975d056fa04SAlexander Leidinger blksz = sz / EMUPAGESIZE; 976d056fa04SAlexander Leidinger if (sz > (blksz * EMUPAGESIZE)) 977d056fa04SAlexander Leidinger blksz++; 978d056fa04SAlexander Leidinger /* find a free block in the bitmap */ 979d056fa04SAlexander Leidinger found = 0; 980d056fa04SAlexander Leidinger start = 1; 981d056fa04SAlexander Leidinger while (!found && start + blksz < MAXPAGES) { 982d056fa04SAlexander Leidinger found = 1; 983d056fa04SAlexander Leidinger for (idx = start; idx < start + blksz; idx++) 984d056fa04SAlexander Leidinger if (mem->bmap[idx >> 3] & (1 << (idx & 7))) 985d056fa04SAlexander Leidinger found = 0; 986d056fa04SAlexander Leidinger if (!found) 987d056fa04SAlexander Leidinger start++; 988d056fa04SAlexander Leidinger } 989d056fa04SAlexander Leidinger if (!found) 990d056fa04SAlexander Leidinger return (NULL); 991d056fa04SAlexander Leidinger blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT); 992d056fa04SAlexander Leidinger if (blk == NULL) 993d056fa04SAlexander Leidinger return (NULL); 994d056fa04SAlexander Leidinger bzero(blk, sizeof(*blk)); 995d056fa04SAlexander Leidinger membuf = emu_malloc(mem, sz, &blk->buf_addr); 996d056fa04SAlexander Leidinger *addr = blk->buf_addr; 997d056fa04SAlexander Leidinger if (membuf == NULL) { 998d056fa04SAlexander Leidinger free(blk, M_DEVBUF); 999d056fa04SAlexander Leidinger return (NULL); 1000d056fa04SAlexander Leidinger } 1001d056fa04SAlexander Leidinger blk->buf = membuf; 1002d056fa04SAlexander Leidinger blk->pte_start = start; 1003d056fa04SAlexander Leidinger blk->pte_size = blksz; 1004d056fa04SAlexander Leidinger strncpy(blk->owner, owner, 15); 1005d056fa04SAlexander Leidinger blk->owner[15] = '\0'; 1006d056fa04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG 1007d056fa04SAlexander Leidinger printf("emu10kx emu_memalloc: allocating %d for %s\n", blk->pte_size, blk->owner); 1008d056fa04SAlexander Leidinger #endif 1009d056fa04SAlexander Leidinger ofs = 0; 1010d056fa04SAlexander Leidinger for (idx = start; idx < start + blksz; idx++) { 1011d056fa04SAlexander Leidinger mem->bmap[idx >> 3] |= 1 << (idx & 7); 1012d056fa04SAlexander Leidinger tmp = (uint32_t) (u_long) ((uint8_t *) blk->buf_addr + ofs); 1013d056fa04SAlexander Leidinger mem->ptb_pages[idx] = (tmp << 1) | idx; 1014d056fa04SAlexander Leidinger ofs += EMUPAGESIZE; 1015d056fa04SAlexander Leidinger } 1016d056fa04SAlexander Leidinger SLIST_INSERT_HEAD(&mem->blocks, blk, link); 1017d056fa04SAlexander Leidinger return (membuf); 1018d056fa04SAlexander Leidinger } 1019d056fa04SAlexander Leidinger 1020d056fa04SAlexander Leidinger static int 1021d056fa04SAlexander Leidinger emu_memfree(struct emu_mem *mem, void *membuf) 1022d056fa04SAlexander Leidinger { 1023d056fa04SAlexander Leidinger uint32_t idx, tmp; 1024d056fa04SAlexander Leidinger struct emu_memblk *blk, *i; 1025d056fa04SAlexander Leidinger 1026d056fa04SAlexander Leidinger blk = NULL; 1027d056fa04SAlexander Leidinger SLIST_FOREACH(i, &mem->blocks, link) { 1028d056fa04SAlexander Leidinger if (i->buf == membuf) 1029d056fa04SAlexander Leidinger blk = i; 1030d056fa04SAlexander Leidinger } 1031d056fa04SAlexander Leidinger if (blk == NULL) 1032d056fa04SAlexander Leidinger return (EINVAL); 1033d056fa04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG 1034d056fa04SAlexander Leidinger printf("emu10kx emu_memfree: freeing %d for %s\n", blk->pte_size, blk->owner); 1035d056fa04SAlexander Leidinger #endif 1036d056fa04SAlexander Leidinger SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link); 1037d056fa04SAlexander Leidinger emu_free(mem, membuf); 1038d056fa04SAlexander Leidinger tmp = (uint32_t) (mem->silent_page_addr) << 1; 1039d056fa04SAlexander Leidinger for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) { 1040d056fa04SAlexander Leidinger mem->bmap[idx >> 3] &= ~(1 << (idx & 7)); 1041d056fa04SAlexander Leidinger mem->ptb_pages[idx] = tmp | idx; 1042d056fa04SAlexander Leidinger } 1043d056fa04SAlexander Leidinger free(blk, M_DEVBUF); 1044d056fa04SAlexander Leidinger return (0); 1045d056fa04SAlexander Leidinger } 1046d056fa04SAlexander Leidinger 1047d056fa04SAlexander Leidinger static int 1048d056fa04SAlexander Leidinger emu_memstart(struct emu_mem *mem, void *membuf) 1049d056fa04SAlexander Leidinger { 1050d056fa04SAlexander Leidinger struct emu_memblk *blk, *i; 1051d056fa04SAlexander Leidinger 1052d056fa04SAlexander Leidinger blk = NULL; 1053d056fa04SAlexander Leidinger SLIST_FOREACH(i, &mem->blocks, link) { 1054d056fa04SAlexander Leidinger if (i->buf == membuf) 1055d056fa04SAlexander Leidinger blk = i; 1056d056fa04SAlexander Leidinger } 1057d056fa04SAlexander Leidinger if (blk == NULL) 1058d056fa04SAlexander Leidinger return (-1); 1059d056fa04SAlexander Leidinger return (blk->pte_start); 1060d056fa04SAlexander Leidinger } 1061d056fa04SAlexander Leidinger 1062d056fa04SAlexander Leidinger 1063d056fa04SAlexander Leidinger static uint32_t 1064d056fa04SAlexander Leidinger emu_rate_to_pitch(uint32_t rate) 1065d056fa04SAlexander Leidinger { 1066d056fa04SAlexander Leidinger static uint32_t logMagTable[128] = { 1067d056fa04SAlexander Leidinger 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2, 1068d056fa04SAlexander Leidinger 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5, 1069d056fa04SAlexander Leidinger 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081, 1070d056fa04SAlexander Leidinger 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191, 1071d056fa04SAlexander Leidinger 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, 1072d056fa04SAlexander Leidinger 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, 1073d056fa04SAlexander Leidinger 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e, 1074d056fa04SAlexander Leidinger 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26, 1075d056fa04SAlexander Leidinger 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d, 1076d056fa04SAlexander Leidinger 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885, 1077d056fa04SAlexander Leidinger 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, 1078d056fa04SAlexander Leidinger 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, 1079d056fa04SAlexander Leidinger 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, 1080d056fa04SAlexander Leidinger 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3, 1081d056fa04SAlexander Leidinger 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83, 1082d056fa04SAlexander Leidinger 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df 1083d056fa04SAlexander Leidinger }; 1084d056fa04SAlexander Leidinger static char logSlopeTable[128] = { 1085d056fa04SAlexander Leidinger 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58, 1086d056fa04SAlexander Leidinger 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53, 1087d056fa04SAlexander Leidinger 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f, 1088d056fa04SAlexander Leidinger 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b, 1089d056fa04SAlexander Leidinger 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47, 1090d056fa04SAlexander Leidinger 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44, 1091d056fa04SAlexander Leidinger 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41, 1092d056fa04SAlexander Leidinger 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e, 1093d056fa04SAlexander Leidinger 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, 1094d056fa04SAlexander Leidinger 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 1095d056fa04SAlexander Leidinger 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37, 1096d056fa04SAlexander Leidinger 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35, 1097d056fa04SAlexander Leidinger 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34, 1098d056fa04SAlexander Leidinger 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32, 1099d056fa04SAlexander Leidinger 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30, 1100d056fa04SAlexander Leidinger 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f 1101d056fa04SAlexander Leidinger }; 1102d056fa04SAlexander Leidinger int i; 1103d056fa04SAlexander Leidinger 1104d056fa04SAlexander Leidinger if (rate == 0) 1105d056fa04SAlexander Leidinger return (0); 1106d056fa04SAlexander Leidinger rate *= 11185; /* Scale 48000 to 0x20002380 */ 1107d056fa04SAlexander Leidinger for (i = 31; i > 0; i--) { 1108d056fa04SAlexander Leidinger if (rate & 0x80000000) { /* Detect leading "1" */ 1109d056fa04SAlexander Leidinger return (((uint32_t) (i - 15) << 20) + 1110d056fa04SAlexander Leidinger logMagTable[0x7f & (rate >> 24)] + 1111d056fa04SAlexander Leidinger (0x7f & (rate >> 17)) * 1112d056fa04SAlexander Leidinger logSlopeTable[0x7f & (rate >> 24)]); 1113d056fa04SAlexander Leidinger } 1114d056fa04SAlexander Leidinger rate <<= 1; 1115d056fa04SAlexander Leidinger } 1116d056fa04SAlexander Leidinger /* NOTREACHED */ 1117d056fa04SAlexander Leidinger return (0); 1118d056fa04SAlexander Leidinger } 1119d056fa04SAlexander Leidinger 1120d056fa04SAlexander Leidinger static uint32_t 1121d056fa04SAlexander Leidinger emu_rate_to_linearpitch(uint32_t rate) 1122d056fa04SAlexander Leidinger { 1123d056fa04SAlexander Leidinger rate = (rate << 8) / 375; 1124d056fa04SAlexander Leidinger return ((rate >> 1) + (rate & 1)); 1125d056fa04SAlexander Leidinger } 1126d056fa04SAlexander Leidinger 1127d056fa04SAlexander Leidinger struct emu_voice * 1128d056fa04SAlexander Leidinger emu_valloc(struct emu_sc_info *sc) 1129d056fa04SAlexander Leidinger { 1130d056fa04SAlexander Leidinger struct emu_voice *v; 1131d056fa04SAlexander Leidinger int i; 1132d056fa04SAlexander Leidinger 1133d056fa04SAlexander Leidinger v = NULL; 1134d056fa04SAlexander Leidinger mtx_lock(&sc->lock); 1135d056fa04SAlexander Leidinger for (i = 0; i < NUM_G && sc->voice[i].busy; i++); 1136d056fa04SAlexander Leidinger if (i < NUM_G) { 1137d056fa04SAlexander Leidinger v = &sc->voice[i]; 1138d056fa04SAlexander Leidinger v->busy = 1; 1139d056fa04SAlexander Leidinger } 1140d056fa04SAlexander Leidinger mtx_unlock(&sc->lock); 1141d056fa04SAlexander Leidinger return (v); 1142d056fa04SAlexander Leidinger } 1143d056fa04SAlexander Leidinger 1144d056fa04SAlexander Leidinger void 1145d056fa04SAlexander Leidinger emu_vfree(struct emu_sc_info *sc, struct emu_voice *v) 1146d056fa04SAlexander Leidinger { 1147d056fa04SAlexander Leidinger int i, r; 1148d056fa04SAlexander Leidinger 1149d056fa04SAlexander Leidinger mtx_lock(&sc->lock); 1150d056fa04SAlexander Leidinger for (i = 0; i < NUM_G; i++) { 1151d056fa04SAlexander Leidinger if (v == &sc->voice[i] && sc->voice[i].busy) { 1152d056fa04SAlexander Leidinger v->busy = 0; 1153d056fa04SAlexander Leidinger /* XXX What we should do with mono channels? 1154d056fa04SAlexander Leidinger See -pcm.c emupchan_init for other side of 1155d056fa04SAlexander Leidinger this problem */ 1156d056fa04SAlexander Leidinger if (v->slave != NULL) 1157d056fa04SAlexander Leidinger r = emu_memfree(&sc->mem, v->vbuf); 1158d056fa04SAlexander Leidinger } 1159d056fa04SAlexander Leidinger } 1160d056fa04SAlexander Leidinger mtx_unlock(&sc->lock); 1161d056fa04SAlexander Leidinger } 1162d056fa04SAlexander Leidinger 1163d056fa04SAlexander Leidinger int 1164d056fa04SAlexander Leidinger emu_vinit(struct emu_sc_info *sc, struct emu_voice *m, struct emu_voice *s, 1165d056fa04SAlexander Leidinger uint32_t sz, struct snd_dbuf *b) 1166d056fa04SAlexander Leidinger { 1167d056fa04SAlexander Leidinger void *vbuf; 1168d056fa04SAlexander Leidinger bus_addr_t tmp_addr; 1169d056fa04SAlexander Leidinger 1170d056fa04SAlexander Leidinger vbuf = emu_memalloc(&sc->mem, sz, &tmp_addr, "vinit"); 1171d056fa04SAlexander Leidinger if (vbuf == NULL) 1172d056fa04SAlexander Leidinger return (ENOMEM); 1173d056fa04SAlexander Leidinger if (b != NULL) 1174d056fa04SAlexander Leidinger sndbuf_setup(b, vbuf, sz); 1175d056fa04SAlexander Leidinger m->start = emu_memstart(&sc->mem, vbuf) * EMUPAGESIZE; 1176d056fa04SAlexander Leidinger if (m->start == -1) { 1177d056fa04SAlexander Leidinger emu_memfree(&sc->mem, vbuf); 1178d056fa04SAlexander Leidinger return (ENOMEM); 1179d056fa04SAlexander Leidinger } 1180d056fa04SAlexander Leidinger m->end = m->start + sz; 1181d056fa04SAlexander Leidinger m->speed = 0; 1182d056fa04SAlexander Leidinger m->b16 = 0; 1183d056fa04SAlexander Leidinger m->stereo = 0; 1184d056fa04SAlexander Leidinger m->running = 0; 1185d056fa04SAlexander Leidinger m->ismaster = 1; 1186d056fa04SAlexander Leidinger m->vol = 0xff; 1187d056fa04SAlexander Leidinger m->buf = tmp_addr; 1188d056fa04SAlexander Leidinger m->vbuf = vbuf; 1189d056fa04SAlexander Leidinger m->slave = s; 1190d056fa04SAlexander Leidinger if (s != NULL) { 1191d056fa04SAlexander Leidinger s->start = m->start; 1192d056fa04SAlexander Leidinger s->end = m->end; 1193d056fa04SAlexander Leidinger s->speed = 0; 1194d056fa04SAlexander Leidinger s->b16 = 0; 1195d056fa04SAlexander Leidinger s->stereo = 0; 1196d056fa04SAlexander Leidinger s->running = 0; 1197d056fa04SAlexander Leidinger s->ismaster = 0; 1198d056fa04SAlexander Leidinger s->vol = m->vol; 1199d056fa04SAlexander Leidinger s->buf = m->buf; 1200d056fa04SAlexander Leidinger s->vbuf = NULL; 1201d056fa04SAlexander Leidinger s->slave = NULL; 1202d056fa04SAlexander Leidinger } 1203d056fa04SAlexander Leidinger return (0); 1204d056fa04SAlexander Leidinger } 1205d056fa04SAlexander Leidinger 1206d056fa04SAlexander Leidinger void 1207d056fa04SAlexander Leidinger emu_vsetup(struct emu_voice *v, int fmt, int spd) 1208d056fa04SAlexander Leidinger { 1209d056fa04SAlexander Leidinger if (fmt) { 1210d056fa04SAlexander Leidinger v->b16 = (fmt & AFMT_16BIT) ? 1 : 0; 1211d056fa04SAlexander Leidinger v->stereo = (fmt & AFMT_STEREO) ? 1 : 0; 1212d056fa04SAlexander Leidinger if (v->slave != NULL) { 1213d056fa04SAlexander Leidinger v->slave->b16 = v->b16; 1214d056fa04SAlexander Leidinger v->slave->stereo = v->stereo; 1215d056fa04SAlexander Leidinger } 1216d056fa04SAlexander Leidinger } 1217d056fa04SAlexander Leidinger if (spd) { 1218d056fa04SAlexander Leidinger v->speed = spd; 1219d056fa04SAlexander Leidinger if (v->slave != NULL) 1220d056fa04SAlexander Leidinger v->slave->speed = v->speed; 1221d056fa04SAlexander Leidinger } 1222d056fa04SAlexander Leidinger } 1223d056fa04SAlexander Leidinger 1224d056fa04SAlexander Leidinger void 1225d056fa04SAlexander Leidinger emu_vroute(struct emu_sc_info *sc, struct emu_route *rt, struct emu_voice *v) 1226d056fa04SAlexander Leidinger { 1227d056fa04SAlexander Leidinger unsigned int routing[8], amounts[8]; 1228d056fa04SAlexander Leidinger int i; 1229d056fa04SAlexander Leidinger 1230d056fa04SAlexander Leidinger for (i = 0; i < 8; i++) { 1231d056fa04SAlexander Leidinger routing[i] = rt->routing_left[i]; 1232d056fa04SAlexander Leidinger amounts[i] = rt->amounts_left[i]; 1233d056fa04SAlexander Leidinger } 1234d056fa04SAlexander Leidinger if ((v->stereo) && (v->ismaster == 0)) 1235d056fa04SAlexander Leidinger for (i = 0; i < 8; i++) { 1236d056fa04SAlexander Leidinger routing[i] = rt->routing_right[i]; 1237d056fa04SAlexander Leidinger amounts[i] = rt->amounts_right[i]; 1238d056fa04SAlexander Leidinger } 1239d056fa04SAlexander Leidinger 1240d056fa04SAlexander Leidinger if (sc->is_emu10k1) { 1241d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, FXRT, ((routing[3] << 12) | 1242d056fa04SAlexander Leidinger (routing[2] << 8) | 1243d056fa04SAlexander Leidinger (routing[1] << 4) | 1244d056fa04SAlexander Leidinger (routing[0] << 0)) << 16); 1245d056fa04SAlexander Leidinger } else { 1246d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, A_FXRT1, (routing[3] << 24) | 1247d056fa04SAlexander Leidinger (routing[2] << 16) | 1248d056fa04SAlexander Leidinger (routing[1] << 8) | 1249d056fa04SAlexander Leidinger (routing[0] << 0)); 1250d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, A_FXRT2, (routing[7] << 24) | 1251d056fa04SAlexander Leidinger (routing[6] << 16) | 1252d056fa04SAlexander Leidinger (routing[5] << 8) | 1253d056fa04SAlexander Leidinger (routing[4] << 0)); 1254d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, A_SENDAMOUNTS, (amounts[7] << 24) | 1255d056fa04SAlexander Leidinger (amounts[6] << 26) | 1256d056fa04SAlexander Leidinger (amounts[5] << 8) | 1257d056fa04SAlexander Leidinger (amounts[4] << 0)); 1258d056fa04SAlexander Leidinger } 1259d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, PTRX, (amounts[0] << 8) | (amounts[1] << 0)); 1260d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, DSL, v->ea | (amounts[3] << 24)); 1261d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, PSST, v->sa | (amounts[2] << 24)); 1262d056fa04SAlexander Leidinger if ((v->stereo) && (v->slave != NULL)) 1263d056fa04SAlexander Leidinger emu_vroute(sc, rt, v->slave); 1264d056fa04SAlexander Leidinger } 1265d056fa04SAlexander Leidinger 1266d056fa04SAlexander Leidinger void 1267d056fa04SAlexander Leidinger emu_vwrite(struct emu_sc_info *sc, struct emu_voice *v) 1268d056fa04SAlexander Leidinger { 1269d056fa04SAlexander Leidinger int s; 1270d056fa04SAlexander Leidinger uint32_t am_2, am_3, start, val, silent_page; 1271d056fa04SAlexander Leidinger 1272d056fa04SAlexander Leidinger s = (v->stereo ? 1 : 0) + (v->b16 ? 1 : 0); 1273d056fa04SAlexander Leidinger 1274d056fa04SAlexander Leidinger v->sa = v->start >> s; 1275d056fa04SAlexander Leidinger v->ea = v->end >> s; 1276d056fa04SAlexander Leidinger 1277d056fa04SAlexander Leidinger 1278d056fa04SAlexander Leidinger if (v->stereo) { 1279d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CPF, CPF_STEREO_MASK); 1280d056fa04SAlexander Leidinger } else { 1281d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CPF, 0); 1282d056fa04SAlexander Leidinger } 1283d056fa04SAlexander Leidinger val = v->stereo ? 28 : 30; 1284d056fa04SAlexander Leidinger val *= v->b16 ? 1 : 2; 1285d056fa04SAlexander Leidinger start = v->sa + val; 1286d056fa04SAlexander Leidinger 1287d056fa04SAlexander Leidinger am_3 = emu_rdptr(sc, v->vnum, DSL) & 0xff000000; 1288d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, DSL, v->ea | am_3); 1289d056fa04SAlexander Leidinger am_2 = emu_rdptr(sc, v->vnum, PSST) & 0xff000000; 1290d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, PSST, v->sa | am_2); 1291d056fa04SAlexander Leidinger 1292d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CCCA, start | (v->b16 ? 0 : CCCA_8BITSELECT)); 1293d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, Z1, 0); 1294d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, Z2, 0); 1295d056fa04SAlexander Leidinger 1296d056fa04SAlexander Leidinger silent_page = ((uint32_t) (sc->mem.silent_page_addr) << 1) | MAP_PTI_MASK; 1297d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, MAPA, silent_page); 1298d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, MAPB, silent_page); 1299d056fa04SAlexander Leidinger 1300d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CVCF, CVCF_CURRENTFILTER_MASK); 1301d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, VTFT, VTFT_FILTERTARGET_MASK); 1302d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, ATKHLDM, 0); 1303d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, DCYSUSM, DCYSUSM_DECAYTIME_MASK); 1304d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, LFOVAL1, 0x8000); 1305d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, LFOVAL2, 0x8000); 1306d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, FMMOD, 0); 1307d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, TREMFRQ, 0); 1308d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, FM2FRQ2, 0); 1309d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, ENVVAL, 0x8000); 1310d056fa04SAlexander Leidinger 1311d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, ATKHLDV, ATKHLDV_HOLDTIME_MASK | ATKHLDV_ATTACKTIME_MASK); 1312d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, ENVVOL, 0x8000); 1313d056fa04SAlexander Leidinger 1314d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, PEFE_FILTERAMOUNT, 0x7f); 1315d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, PEFE_PITCHAMOUNT, 0); 1316d056fa04SAlexander Leidinger if ((v->stereo) && (v->slave != NULL)) 1317d056fa04SAlexander Leidinger emu_vwrite(sc, v->slave); 1318d056fa04SAlexander Leidinger } 1319d056fa04SAlexander Leidinger 1320d056fa04SAlexander Leidinger static void 1321d056fa04SAlexander Leidinger emu_vstop(struct emu_sc_info *sc, char channel, int enable) 1322d056fa04SAlexander Leidinger { 1323d056fa04SAlexander Leidinger int reg; 1324d056fa04SAlexander Leidinger 1325d056fa04SAlexander Leidinger reg = (channel & 0x20) ? SOLEH : SOLEL; 1326d056fa04SAlexander Leidinger channel &= 0x1f; 1327d056fa04SAlexander Leidinger reg |= 1 << 24; 1328d056fa04SAlexander Leidinger reg |= channel << 16; 1329d056fa04SAlexander Leidinger emu_wrptr(sc, 0, reg, enable); 1330d056fa04SAlexander Leidinger } 1331d056fa04SAlexander Leidinger 1332d056fa04SAlexander Leidinger void 1333d056fa04SAlexander Leidinger emu_vtrigger(struct emu_sc_info *sc, struct emu_voice *v, int go) 1334d056fa04SAlexander Leidinger { 1335d056fa04SAlexander Leidinger uint32_t pitch_target, initial_pitch; 1336d056fa04SAlexander Leidinger uint32_t cra, cs, ccis; 1337d056fa04SAlexander Leidinger uint32_t sample, i; 1338d056fa04SAlexander Leidinger 1339d056fa04SAlexander Leidinger if (go) { 1340d056fa04SAlexander Leidinger cra = 64; 1341d056fa04SAlexander Leidinger cs = v->stereo ? 4 : 2; 1342d056fa04SAlexander Leidinger ccis = v->stereo ? 28 : 30; 1343d056fa04SAlexander Leidinger ccis *= v->b16 ? 1 : 2; 1344d056fa04SAlexander Leidinger sample = v->b16 ? 0x00000000 : 0x80808080; 1345d056fa04SAlexander Leidinger for (i = 0; i < cs; i++) 1346d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CD0 + i, sample); 1347d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CCR_CACHEINVALIDSIZE, 0); 1348d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CCR_READADDRESS, cra); 1349d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CCR_CACHEINVALIDSIZE, ccis); 1350d056fa04SAlexander Leidinger 1351d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, IFATN, 0xff00); 1352d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, VTFT, 0xffffffff); 1353d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CVCF, 0xffffffff); 1354d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, DCYSUSV, 0x00007f7f); 1355d056fa04SAlexander Leidinger emu_vstop(sc, v->vnum, 0); 1356d056fa04SAlexander Leidinger 1357d056fa04SAlexander Leidinger pitch_target = emu_rate_to_linearpitch(v->speed); 1358d056fa04SAlexander Leidinger initial_pitch = emu_rate_to_pitch(v->speed) >> 8; 1359d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, pitch_target); 1360d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, pitch_target); 1361d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, IP, initial_pitch); 1362d056fa04SAlexander Leidinger } else { 1363d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, 0); 1364d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, 0); 1365d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, IFATN, 0xffff); 1366d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, VTFT, 0x0000ffff); 1367d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, CVCF, 0x0000ffff); 1368d056fa04SAlexander Leidinger emu_wrptr(sc, v->vnum, IP, 0); 1369d056fa04SAlexander Leidinger emu_vstop(sc, v->vnum, 1); 1370d056fa04SAlexander Leidinger } 1371d056fa04SAlexander Leidinger if ((v->stereo) && (v->slave != NULL)) 1372d056fa04SAlexander Leidinger emu_vtrigger(sc, v->slave, go); 1373d056fa04SAlexander Leidinger } 1374d056fa04SAlexander Leidinger 1375d056fa04SAlexander Leidinger int 1376d056fa04SAlexander Leidinger emu_vpos(struct emu_sc_info *sc, struct emu_voice *v) 1377d056fa04SAlexander Leidinger { 1378d056fa04SAlexander Leidinger int s, ptr; 1379d056fa04SAlexander Leidinger 1380d056fa04SAlexander Leidinger s = (v->b16 ? 1 : 0) + (v->stereo ? 1 : 0); 1381d056fa04SAlexander Leidinger ptr = (emu_rdptr(sc, v->vnum, CCCA_CURRADDR) - (v->start >> s)) << s; 1382d056fa04SAlexander Leidinger return (ptr & ~0x0000001f); 1383d056fa04SAlexander Leidinger } 1384d056fa04SAlexander Leidinger 1385d056fa04SAlexander Leidinger 1386d056fa04SAlexander Leidinger /* fx */ 1387d056fa04SAlexander Leidinger static void 1388d056fa04SAlexander Leidinger emu_wrefx(struct emu_sc_info *sc, unsigned int pc, unsigned int data) 1389d056fa04SAlexander Leidinger { 1390d056fa04SAlexander Leidinger emu_wrptr(sc, 0, sc->code_base + pc, data); 1391d056fa04SAlexander Leidinger } 1392d056fa04SAlexander Leidinger 1393d056fa04SAlexander Leidinger 1394d056fa04SAlexander Leidinger static void 1395d056fa04SAlexander Leidinger 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) 1396d056fa04SAlexander Leidinger { 1397d056fa04SAlexander Leidinger if ((*pc) + 1 > sc->code_size) { 1398d056fa04SAlexander Leidinger device_printf(sc->dev, "DSP CODE OVERRUN: attept to write past code_size (pc=%d)\n", (*pc)); 1399d056fa04SAlexander Leidinger return; 1400d056fa04SAlexander Leidinger } 1401d056fa04SAlexander Leidinger emu_wrefx(sc, (*pc) * 2, (x << sc->high_operand_shift) | y); 1402d056fa04SAlexander Leidinger emu_wrefx(sc, (*pc) * 2 + 1, (op << sc->opcode_shift) | (z << sc->high_operand_shift) | w); 1403d056fa04SAlexander Leidinger (*pc)++; 1404d056fa04SAlexander Leidinger } 1405d056fa04SAlexander Leidinger 1406d056fa04SAlexander Leidinger static int 1407d056fa04SAlexander Leidinger sysctl_emu_mixer_control(SYSCTL_HANDLER_ARGS) 1408d056fa04SAlexander Leidinger { 1409d056fa04SAlexander Leidinger struct emu_sc_info *sc; 1410d056fa04SAlexander Leidinger int mixer_id; 1411d056fa04SAlexander Leidinger int new_vol; 1412d056fa04SAlexander Leidinger int err; 1413d056fa04SAlexander Leidinger 1414d056fa04SAlexander Leidinger sc = arg1; 1415d056fa04SAlexander Leidinger mixer_id = arg2; 1416d056fa04SAlexander Leidinger 1417d056fa04SAlexander Leidinger new_vol = emumix_get_volume(sc, mixer_id); 1418d056fa04SAlexander Leidinger err = sysctl_handle_int(oidp, &new_vol, sizeof(new_vol), req); 1419d056fa04SAlexander Leidinger 1420d056fa04SAlexander Leidinger if (err || req->newptr == NULL) 1421d056fa04SAlexander Leidinger return (err); 1422d056fa04SAlexander Leidinger if (new_vol < 0 || new_vol > 100) 1423d056fa04SAlexander Leidinger return (EINVAL); 1424d056fa04SAlexander Leidinger emumix_set_volume(sc, mixer_id, new_vol); 1425d056fa04SAlexander Leidinger 1426d056fa04SAlexander Leidinger return (0); 1427d056fa04SAlexander Leidinger } 1428d056fa04SAlexander Leidinger 1429d056fa04SAlexander Leidinger static int 1430d056fa04SAlexander Leidinger emu_addefxmixer(struct emu_sc_info *sc, const char *mix_name, const int mix_id, uint32_t defvolume) 1431d056fa04SAlexander Leidinger { 1432d056fa04SAlexander Leidinger int volgpr; 14334002c392SAlexander Leidinger char sysctl_name[32]; 1434d056fa04SAlexander Leidinger 1435d056fa04SAlexander Leidinger volgpr = emu_rm_gpr_alloc(sc->rm, 1); 1436d056fa04SAlexander Leidinger emumix_set_fxvol(sc, volgpr, defvolume); 1437d056fa04SAlexander Leidinger /* Mixer controls with NULL mix_name are handled by AC97 emulation 1438d056fa04SAlexander Leidinger code or PCM mixer. */ 1439d056fa04SAlexander Leidinger if (mix_name != NULL) { 14404002c392SAlexander Leidinger /* Temporary sysctls should start with underscore, 14414002c392SAlexander Leidinger * see freebsd-current mailing list, emu10kx driver 14424002c392SAlexander Leidinger * discussion around May, 24th. */ 14434002c392SAlexander Leidinger snprintf(sysctl_name, 32, "_%s", mix_name); 1444d056fa04SAlexander Leidinger SYSCTL_ADD_PROC(sc->ctx, 1445d056fa04SAlexander Leidinger SYSCTL_CHILDREN(sc->root), 14464002c392SAlexander Leidinger OID_AUTO, sysctl_name, 1447d056fa04SAlexander Leidinger CTLTYPE_INT | CTLFLAG_RW, sc, mix_id, 1448d056fa04SAlexander Leidinger sysctl_emu_mixer_control, "I",""); 1449d056fa04SAlexander Leidinger } 1450d056fa04SAlexander Leidinger 1451d056fa04SAlexander Leidinger return (volgpr); 1452d056fa04SAlexander Leidinger } 1453d056fa04SAlexander Leidinger 1454d056fa04SAlexander Leidinger /* allocate cache GPRs that will hold mixed output channels 1455d056fa04SAlexander Leidinger * and clear it on every DSP run. 1456d056fa04SAlexander Leidinger */ 1457d056fa04SAlexander Leidinger #define EFX_CACHE(CACHE_IDX) do { \ 1458d056fa04SAlexander Leidinger sc->cache_gpr[CACHE_IDX] = emu_rm_gpr_alloc(sc->rm, 1); \ 1459d056fa04SAlexander Leidinger emu_addefxop(sc, ACC3, \ 1460d056fa04SAlexander Leidinger GPR(sc->cache_gpr[CACHE_IDX]), \ 1461d056fa04SAlexander Leidinger DSP_CONST(0), \ 1462d056fa04SAlexander Leidinger DSP_CONST(0), \ 1463d056fa04SAlexander Leidinger DSP_CONST(0), \ 1464d056fa04SAlexander Leidinger &pc); \ 1465d056fa04SAlexander Leidinger } while (0) 1466d056fa04SAlexander Leidinger 1467d056fa04SAlexander Leidinger /* Allocate GPR for volume control and route sound: OUT = OUT + IN * VOL */ 1468d056fa04SAlexander Leidinger #define EFX_ROUTE(TITLE, INP_NR, IN_GPR_IDX, OUT_CACHE_IDX, DEF) do { \ 1469d056fa04SAlexander Leidinger sc->mixer_gpr[IN_GPR_IDX] = emu_addefxmixer(sc, TITLE, IN_GPR_IDX, DEF); \ 1470d056fa04SAlexander Leidinger sc->mixer_volcache[IN_GPR_IDX] = DEF; \ 1471d056fa04SAlexander Leidinger emu_addefxop(sc, MACS, \ 1472d056fa04SAlexander Leidinger GPR(sc->cache_gpr[OUT_CACHE_IDX]), \ 1473d056fa04SAlexander Leidinger GPR(sc->cache_gpr[OUT_CACHE_IDX]), \ 1474d056fa04SAlexander Leidinger INP_NR, \ 1475d056fa04SAlexander Leidinger GPR(sc->mixer_gpr[IN_GPR_IDX]), \ 1476d056fa04SAlexander Leidinger &pc); \ 1477d056fa04SAlexander Leidinger } while (0) 1478d056fa04SAlexander Leidinger 1479d056fa04SAlexander Leidinger /* allocate GPR, OUT = IN * VOL */ 1480d056fa04SAlexander Leidinger #define EFX_OUTPUT(TITLE,OUT_CACHE_IDX, OUT_GPR_IDX, OUTP_NR, DEF) do { \ 1481d056fa04SAlexander Leidinger sc->mixer_gpr[OUT_GPR_IDX] = emu_addefxmixer(sc, TITLE, OUT_GPR_IDX, DEF); \ 1482d056fa04SAlexander Leidinger sc->mixer_volcache[OUT_GPR_IDX] = DEF; \ 1483d056fa04SAlexander Leidinger emu_addefxop(sc, MACS, \ 1484d056fa04SAlexander Leidinger OUTP(OUTP_NR), \ 1485d056fa04SAlexander Leidinger DSP_CONST(0), \ 1486d056fa04SAlexander Leidinger GPR(sc->cache_gpr[OUT_CACHE_IDX]), \ 1487d056fa04SAlexander Leidinger GPR(sc->mixer_gpr[OUT_GPR_IDX]), \ 1488d056fa04SAlexander Leidinger &pc); \ 1489d056fa04SAlexander Leidinger } while (0) 1490d056fa04SAlexander Leidinger 1491d056fa04SAlexander Leidinger /* like EFX_OUTPUT, but don't allocate mixer gpr */ 1492d056fa04SAlexander Leidinger #define EFX_OUTPUTD(OUT_CACHE_IDX, OUT_GPR_IDX, OUTP_NR) do{ \ 1493d056fa04SAlexander Leidinger emu_addefxop(sc, MACS, \ 1494d056fa04SAlexander Leidinger OUTP(OUTP_NR), \ 1495d056fa04SAlexander Leidinger DSP_CONST(0), \ 1496d056fa04SAlexander Leidinger GPR(sc->cache_gpr[OUT_CACHE_IDX]), \ 1497d056fa04SAlexander Leidinger GPR(sc->mixer_gpr[OUT_GPR_IDX]), \ 1498d056fa04SAlexander Leidinger &pc); \ 1499d056fa04SAlexander Leidinger } while(0) 1500d056fa04SAlexander Leidinger 1501d056fa04SAlexander Leidinger static void 1502d056fa04SAlexander Leidinger emu_initefx(struct emu_sc_info *sc) 1503d056fa04SAlexander Leidinger { 1504d056fa04SAlexander Leidinger unsigned int c; 1505d056fa04SAlexander Leidinger uint32_t pc; 1506d056fa04SAlexander Leidinger 1507d056fa04SAlexander Leidinger /* stop DSP */ 1508d056fa04SAlexander Leidinger if (sc->is_emu10k1) { 1509d056fa04SAlexander Leidinger emu_wrptr(sc, 0, DBG, EMU10K1_DBG_SINGLE_STEP); 1510d056fa04SAlexander Leidinger } else { 1511d056fa04SAlexander Leidinger emu_wrptr(sc, 0, A_DBG, A_DBG_SINGLE_STEP); 1512d056fa04SAlexander Leidinger } 1513d056fa04SAlexander Leidinger 1514d056fa04SAlexander Leidinger /* code size is in instructions */ 1515d056fa04SAlexander Leidinger pc = 0; 1516d056fa04SAlexander Leidinger for (c = 0; c < sc->code_size; c++) { 1517d056fa04SAlexander Leidinger if (sc->is_emu10k1) { 1518d056fa04SAlexander Leidinger emu_addefxop(sc, ACC3, DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0x0), &pc); 1519d056fa04SAlexander Leidinger } else { 1520d056fa04SAlexander Leidinger emu_addefxop(sc, SKIP, DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0xf), DSP_CONST(0x0), &pc); 1521d056fa04SAlexander Leidinger } 1522d056fa04SAlexander Leidinger } 1523d056fa04SAlexander Leidinger 1524d056fa04SAlexander Leidinger pc = 0; 1525d056fa04SAlexander Leidinger 1526d056fa04SAlexander Leidinger /* 1527d056fa04SAlexander Leidinger * DSP code below is not good, because: 1528d056fa04SAlexander Leidinger * 1. It can be written smaller, if it can use DSP accumulator register 1529d056fa04SAlexander Leidinger * instead of cache_gpr[]. 1530d056fa04SAlexander Leidinger * 2. It can be more careful when volume is 100%, because in DSP 1531d056fa04SAlexander Leidinger * x*0x7fffffff may not be equal to x ! 1532d056fa04SAlexander Leidinger */ 1533d056fa04SAlexander Leidinger 1534d056fa04SAlexander Leidinger /* clean outputs */ 1535d056fa04SAlexander Leidinger for (c = 0; c < 16 ; c++) { 1536d056fa04SAlexander Leidinger emu_addefxop(sc, ACC3, OUTP(c), DSP_CONST(0), DSP_CONST(0), DSP_CONST(0), &pc); 1537d056fa04SAlexander Leidinger } 1538d056fa04SAlexander Leidinger 1539d056fa04SAlexander Leidinger 1540d056fa04SAlexander Leidinger if (sc->is_emu10k1) { 1541d056fa04SAlexander Leidinger EFX_CACHE(C_FRONT_L); 1542d056fa04SAlexander Leidinger EFX_CACHE(C_FRONT_R); 1543d056fa04SAlexander Leidinger EFX_CACHE(C_REC_L); 1544d056fa04SAlexander Leidinger EFX_CACHE(C_REC_R); 1545d056fa04SAlexander Leidinger 1546d056fa04SAlexander Leidinger /* fx0 to front/record, 100%/muted by default */ 1547d056fa04SAlexander Leidinger EFX_ROUTE("pcm_front_l", FX(0), M_FX0_FRONT_L, C_FRONT_L, 100); 1548d056fa04SAlexander Leidinger EFX_ROUTE("pcm_front_r", FX(1), M_FX1_FRONT_R, C_FRONT_R, 100); 1549d056fa04SAlexander Leidinger EFX_ROUTE("pcm_rec_l", FX(0), M_FX0_REC_L, C_REC_L, 0); 1550d056fa04SAlexander Leidinger EFX_ROUTE("pcm_rec_r", FX(1), M_FX1_REC_R, C_REC_R, 0); 1551d056fa04SAlexander Leidinger 1552d056fa04SAlexander Leidinger /* in0, from AC97 codec output */ 1553d056fa04SAlexander Leidinger EFX_ROUTE("ac97_front_l", INP(IN_AC97_L), M_IN0_FRONT_L, C_FRONT_L, 0); 1554d056fa04SAlexander Leidinger EFX_ROUTE("ac97_front_r", INP(IN_AC97_R), M_IN0_FRONT_R, C_FRONT_R, 0); 1555d056fa04SAlexander Leidinger EFX_ROUTE("ac97_rec_l", INP(IN_AC97_L), M_IN0_REC_L, C_REC_L, 0); 1556d056fa04SAlexander Leidinger EFX_ROUTE("ac97_rec_r", INP(IN_AC97_R), M_IN0_REC_R, C_REC_R, 0); 1557d056fa04SAlexander Leidinger 1558d056fa04SAlexander Leidinger /* in1, from CD S/PDIF */ 1559d056fa04SAlexander Leidinger EFX_ROUTE("cdspdif_front_l", INP(IN_SPDIF_CD_L), M_IN1_FRONT_L, C_FRONT_L, 0); 1560d056fa04SAlexander Leidinger EFX_ROUTE("cdspdif_front_r", INP(IN_SPDIF_CD_R), M_IN1_FRONT_R, C_FRONT_R, 0); 1561d056fa04SAlexander Leidinger EFX_ROUTE("cdspdif_rec_l", INP(IN_SPDIF_CD_L), M_IN1_REC_L, C_REC_L, 0); 1562d056fa04SAlexander Leidinger EFX_ROUTE("cdspdif_rec_r", INP(IN_SPDIF_CD_R), M_IN1_REC_R, C_REC_R, 0); 1563d056fa04SAlexander Leidinger #if 0 1564d056fa04SAlexander Leidinger /* in2, ZoomVide (???) */ 1565d056fa04SAlexander Leidinger EFX_ROUTE("zoom_front_l", INP(IN_ZOOM_L), M_IN2_FRONT_L, C_FRONT_L, 0); 1566d056fa04SAlexander Leidinger EFX_ROUTE("zoom_front_r", INP(IN_ZOOM_R), M_IN2_FRONT_R, C_FRONT_R, 0); 1567d056fa04SAlexander Leidinger EFX_ROUTE("zoom_rec_l", INP(IN_ZOOM_L), M_IN2_REC_L, C_REC_L, 0); 1568d056fa04SAlexander Leidinger EFX_ROUTE("zoom_rec_r", INP(IN_ZOOM_R), M_IN2_REC_R, C_REC_R, 0); 1569d056fa04SAlexander Leidinger #endif 1570d056fa04SAlexander Leidinger #if 0 1571d056fa04SAlexander Leidinger /* in3, TOSLink (???) */ 1572d056fa04SAlexander Leidinger EFX_ROUTE("toslink_front_l", INP(IN_TOSLINK_L), M_IN3_FRONT_L, C_FRONT_L, 0); 1573d056fa04SAlexander Leidinger EFX_ROUTE("toslink_front_r", INP(IN_TOSLINK_R), M_IN3_FRONT_R, C_FRONT_R, 0); 1574d056fa04SAlexander Leidinger EFX_ROUTE("toslink_rec_l", INP(IN_TOSLINK_L), M_IN3_REC_L, C_REC_L, 0); 1575d056fa04SAlexander Leidinger EFX_ROUTE("toslink_rec_r", INP(IN_TOSLINK_R), M_IN3_REC_R, C_REC_R, 0); 1576d056fa04SAlexander Leidinger #endif 1577d056fa04SAlexander Leidinger /* in4, LineIn */ 1578d056fa04SAlexander Leidinger EFX_ROUTE("linein_front_l", INP(IN_LINE1_L), M_IN4_FRONT_L, C_FRONT_L, 0); 1579d056fa04SAlexander Leidinger EFX_ROUTE("linein_front_r", INP(IN_LINE1_R), M_IN4_FRONT_R, C_FRONT_R, 0); 1580d056fa04SAlexander Leidinger EFX_ROUTE("linein_rec_l", INP(IN_LINE1_L), M_IN4_REC_L, C_REC_L, 0); 1581d056fa04SAlexander Leidinger EFX_ROUTE("linein_rec_r", INP(IN_LINE1_R), M_IN4_REC_R, C_REC_R, 0); 1582d056fa04SAlexander Leidinger 1583d056fa04SAlexander Leidinger /* in5, on-card S/PDIF */ 1584d056fa04SAlexander Leidinger EFX_ROUTE("spdif_front_l", INP(IN_COAX_SPDIF_L), M_IN5_FRONT_L, C_FRONT_L, 0); 1585d056fa04SAlexander Leidinger EFX_ROUTE("spdif_front_r", INP(IN_COAX_SPDIF_R), M_IN5_FRONT_R, C_FRONT_R, 0); 1586d056fa04SAlexander Leidinger EFX_ROUTE("spdif_rec_l", INP(IN_COAX_SPDIF_L), M_IN5_REC_L, C_REC_L, 0); 1587d056fa04SAlexander Leidinger EFX_ROUTE("spdif_rec_r", INP(IN_COAX_SPDIF_R), M_IN5_REC_R, C_REC_R, 0); 1588d056fa04SAlexander Leidinger 1589d056fa04SAlexander Leidinger /* in6, Line2 on Live!Drive */ 1590d056fa04SAlexander Leidinger EFX_ROUTE("line2_front_l", INP(IN_LINE2_L), M_IN6_FRONT_L, C_FRONT_L, 0); 1591d056fa04SAlexander Leidinger EFX_ROUTE("line2_front_r", INP(IN_LINE2_R), M_IN6_FRONT_R, C_FRONT_R, 0); 1592d056fa04SAlexander Leidinger EFX_ROUTE("line2_rec_l", INP(IN_LINE2_L), M_IN6_REC_L, C_REC_L, 0); 1593d056fa04SAlexander Leidinger EFX_ROUTE("line2_rec_r", INP(IN_LINE2_R), M_IN6_REC_R, C_REC_R, 0); 1594d056fa04SAlexander Leidinger #if 0 1595d056fa04SAlexander Leidinger /* in7, unknown */ 1596d056fa04SAlexander Leidinger EFX_ROUTE("in7_front_l", INP(0xE), M_IN7_FRONT_L, C_FRONT_L, 0); 1597d056fa04SAlexander Leidinger EFX_ROUTE("in7_front_r", INP(0xF), M_IN7_FRONT_R, C_FRONT_R, 0); 1598d056fa04SAlexander Leidinger EFX_ROUTE("in7_rec_l", INP(0xE), M_IN7_REC_L, C_REC_L, 0); 1599d056fa04SAlexander Leidinger EFX_ROUTE("in7_rec_r", INP(0xF), M_IN7_REC_R, C_REC_R, 0); 1600d056fa04SAlexander Leidinger #endif 1601d056fa04SAlexander Leidinger /* front output to both analog and digital */ 1602d056fa04SAlexander Leidinger EFX_OUTPUT("master_front_l", C_FRONT_L, M_MASTER_FRONT_L, OUT_AC97_L, 100); 1603d056fa04SAlexander Leidinger EFX_OUTPUT("master_front_r", C_FRONT_R, M_MASTER_FRONT_R, OUT_AC97_R, 100); 1604d056fa04SAlexander Leidinger 1605d056fa04SAlexander Leidinger /* rec output to "ADC" */ 1606d056fa04SAlexander Leidinger EFX_OUTPUT("master_rec_l", C_REC_L, M_MASTER_REC_L, OUT_ADC_REC_L, 100); 1607d056fa04SAlexander Leidinger EFX_OUTPUT("master_rec_r", C_REC_R, M_MASTER_REC_R, OUT_ADC_REC_R, 100); 1608d056fa04SAlexander Leidinger #ifdef SND_EMU10KX_MULTICHANNEL 1609d056fa04SAlexander Leidinger /* 1610d056fa04SAlexander Leidinger * Additional channel volume is controlled by mixer in 1611d056fa04SAlexander Leidinger * emu_dspmixer_set() in -pcm.c 1612d056fa04SAlexander Leidinger */ 1613d056fa04SAlexander Leidinger 1614d056fa04SAlexander Leidinger /* fx2/3 (pcm1) to rear */ 1615d056fa04SAlexander Leidinger EFX_CACHE(C_REAR_L); 1616d056fa04SAlexander Leidinger EFX_CACHE(C_REAR_R); 1617d056fa04SAlexander Leidinger EFX_ROUTE(NULL, FX(2), M_FX2_REAR_L, C_REAR_L, 100); 1618d056fa04SAlexander Leidinger EFX_ROUTE(NULL, FX(3), M_FX3_REAR_R, C_REAR_R, 100); 1619d056fa04SAlexander Leidinger 1620d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_REAR_L, M_MASTER_REAR_L, OUT_REAR_L, 100); 1621d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_REAR_R, M_MASTER_REAR_R, OUT_REAR_R, 100); 1622d056fa04SAlexander Leidinger #else /* !SND_EMU10KX_MULTICHANNEL */ 1623d056fa04SAlexander Leidinger EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, OUT_REAR_L); 1624d056fa04SAlexander Leidinger EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, OUT_REAR_R); 1625d056fa04SAlexander Leidinger #endif 1626d056fa04SAlexander Leidinger } else /* emu10k2 and later */ { 1627d056fa04SAlexander Leidinger EFX_CACHE(C_FRONT_L); 1628d056fa04SAlexander Leidinger EFX_CACHE(C_FRONT_R); 1629d056fa04SAlexander Leidinger EFX_CACHE(C_REC_L); 1630d056fa04SAlexander Leidinger EFX_CACHE(C_REC_R); 1631d056fa04SAlexander Leidinger 1632d056fa04SAlexander Leidinger /* fx0 to front/record, 100%/muted by default */ 1633d056fa04SAlexander Leidinger /* 1634d056fa04SAlexander Leidinger * FRONT_[L|R] is controlled by AC97 emulation in 1635d056fa04SAlexander Leidinger * emu_ac97_[read|write]_emulation in -pcm.c 1636d056fa04SAlexander Leidinger */ 1637d056fa04SAlexander Leidinger EFX_ROUTE(NULL, FX(0), M_FX0_FRONT_L, C_FRONT_L, 100); 1638d056fa04SAlexander Leidinger EFX_ROUTE(NULL, FX(1), M_FX1_FRONT_R, C_FRONT_R, 100); 1639d056fa04SAlexander Leidinger EFX_ROUTE("pcm_rec_l", FX(0), M_FX0_REC_L, C_REC_L, 0); 1640d056fa04SAlexander Leidinger EFX_ROUTE("pcm_rec_r", FX(1), M_FX1_REC_R, C_REC_R, 0); 1641d056fa04SAlexander Leidinger 1642d056fa04SAlexander Leidinger /* in0, from AC97 codec output */ 1643d056fa04SAlexander Leidinger EFX_ROUTE("ac97_front_l", INP(A_IN_AC97_L), M_IN0_FRONT_L, C_FRONT_L, 100); 1644d056fa04SAlexander Leidinger EFX_ROUTE("ac97_front_r", INP(A_IN_AC97_R), M_IN0_FRONT_R, C_FRONT_R, 100); 1645d056fa04SAlexander Leidinger EFX_ROUTE("ac97_rec_l", INP(A_IN_AC97_L), M_IN0_REC_L, C_REC_L, 0); 1646d056fa04SAlexander Leidinger EFX_ROUTE("ac97_rec_r", INP(A_IN_AC97_R), M_IN0_REC_R, C_REC_R, 0); 1647d056fa04SAlexander Leidinger 1648d056fa04SAlexander Leidinger /* in1, from CD S/PDIF */ 1649d056fa04SAlexander Leidinger EFX_ROUTE("cdspdif_front_l", INP(A_IN_SPDIF_CD_L), M_IN1_FRONT_L, C_FRONT_L, 0); 1650d056fa04SAlexander Leidinger EFX_ROUTE("cdspdif_front_r", INP(A_IN_SPDIF_CD_R), M_IN1_FRONT_R, C_FRONT_R, 0); 1651d056fa04SAlexander Leidinger EFX_ROUTE("cdspdif_rec_l", INP(A_IN_SPDIF_CD_L), M_IN1_REC_L, C_REC_L, 0); 1652d056fa04SAlexander Leidinger EFX_ROUTE("cdspdif_rec_r", INP(A_IN_SPDIF_CD_R), M_IN1_REC_R, C_REC_R, 0); 1653d056fa04SAlexander Leidinger 1654d056fa04SAlexander Leidinger /* in2, optical & coax S/PDIF on AudigyDrive*/ 1655d056fa04SAlexander Leidinger EFX_ROUTE("ospdif_front_l", INP(A_IN_O_SPDIF_L), M_IN2_FRONT_L, C_FRONT_L, 0); 1656d056fa04SAlexander Leidinger EFX_ROUTE("ospdif_front_r", INP(A_IN_O_SPDIF_R), M_IN2_FRONT_R, C_FRONT_R, 0); 1657d056fa04SAlexander Leidinger EFX_ROUTE("ospdif_rec_l", INP(A_IN_O_SPDIF_L), M_IN2_REC_L, C_REC_L, 0); 1658d056fa04SAlexander Leidinger EFX_ROUTE("ospdif_rec_r", INP(A_IN_O_SPDIF_R), M_IN2_REC_R, C_REC_R, 0); 1659d056fa04SAlexander Leidinger #if 0 1660d056fa04SAlexander Leidinger /* in3, unknown */ 1661d056fa04SAlexander Leidinger EFX_ROUTE("in3_front_l", INP(0x6), M_IN3_FRONT_L, C_FRONT_L, 0); 1662d056fa04SAlexander Leidinger EFX_ROUTE("in3_front_r", INP(0x7), M_IN3_FRONT_R, C_FRONT_R, 0); 1663d056fa04SAlexander Leidinger EFX_ROUTE("in3_rec_l", INP(0x6), M_IN3_REC_L, C_REC_L, 0); 1664d056fa04SAlexander Leidinger EFX_ROUTE("in3_rec_r", INP(0x7), M_IN3_REC_R, C_REC_R, 0); 1665d056fa04SAlexander Leidinger #endif 1666d056fa04SAlexander Leidinger /* in4, LineIn 2 on AudigyDrive */ 1667d056fa04SAlexander Leidinger EFX_ROUTE("linein2_front_l", INP(A_IN_LINE2_L), M_IN4_FRONT_L, C_FRONT_L, 0); 1668d056fa04SAlexander Leidinger EFX_ROUTE("linein2_front_r", INP(A_IN_LINE2_R), M_IN4_FRONT_R, C_FRONT_R, 0); 1669d056fa04SAlexander Leidinger EFX_ROUTE("linein2_rec_l", INP(A_IN_LINE2_L), M_IN4_REC_L, C_REC_L, 0); 1670d056fa04SAlexander Leidinger EFX_ROUTE("linein2_rec_r", INP(A_IN_LINE2_R), M_IN4_REC_R, C_REC_R, 0); 1671d056fa04SAlexander Leidinger 1672d056fa04SAlexander Leidinger /* in5, on-card S/PDIF */ 1673d056fa04SAlexander Leidinger EFX_ROUTE("spdif_front_l", INP(A_IN_R_SPDIF_L), M_IN5_FRONT_L, C_FRONT_L, 0); 1674d056fa04SAlexander Leidinger EFX_ROUTE("spdif_front_r", INP(A_IN_R_SPDIF_R), M_IN5_FRONT_R, C_FRONT_R, 0); 1675d056fa04SAlexander Leidinger EFX_ROUTE("spdif_rec_l", INP(A_IN_R_SPDIF_L), M_IN5_REC_L, C_REC_L, 0); 1676d056fa04SAlexander Leidinger EFX_ROUTE("spdif_rec_r", INP(A_IN_R_SPDIF_R), M_IN5_REC_R, C_REC_R, 0); 1677d056fa04SAlexander Leidinger 1678d056fa04SAlexander Leidinger /* in6, AUX2 on AudigyDrive */ 1679d056fa04SAlexander Leidinger EFX_ROUTE("aux2_front_l", INP(A_IN_AUX2_L), M_IN6_FRONT_L, C_FRONT_L, 0); 1680d056fa04SAlexander Leidinger EFX_ROUTE("aux2_front_r", INP(A_IN_AUX2_R), M_IN6_FRONT_R, C_FRONT_R, 0); 1681d056fa04SAlexander Leidinger EFX_ROUTE("aux2_rec_l", INP(A_IN_AUX2_L), M_IN6_REC_L, C_REC_L, 0); 1682d056fa04SAlexander Leidinger EFX_ROUTE("aux2_rec_r", INP(A_IN_AUX2_R), M_IN6_REC_R, C_REC_R, 0); 1683d056fa04SAlexander Leidinger #if 0 1684d056fa04SAlexander Leidinger /* in7, unknown */ 1685d056fa04SAlexander Leidinger EFX_ROUTE("in7_front_l", INP(0xE), M_IN7_FRONT_L, C_FRONT_L, 0); 1686d056fa04SAlexander Leidinger EFX_ROUTE("in7_front_r", INP(0xF), M_IN7_FRONT_R, C_FRONT_R, 0); 1687d056fa04SAlexander Leidinger EFX_ROUTE("in7_rec_l", INP(0xE), M_IN7_REC_L, C_REC_L, 0); 1688d056fa04SAlexander Leidinger EFX_ROUTE("in7_rec_r", INP(0xF), M_IN7_REC_R, C_REC_R, 0); 1689d056fa04SAlexander Leidinger #endif 1690d056fa04SAlexander Leidinger /* front output to headphones and alog and digital *front */ 1691d056fa04SAlexander Leidinger /* volume controlled by AC97 emulation */ 1692d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_FRONT_L, M_MASTER_FRONT_L, A_OUT_A_FRONT_L, 100); 1693d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_FRONT_R, M_MASTER_FRONT_R, A_OUT_A_FRONT_R, 100); 1694d056fa04SAlexander Leidinger EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_D_FRONT_L); 1695d056fa04SAlexander Leidinger EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_D_FRONT_R); 1696d056fa04SAlexander Leidinger EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_HPHONE_L); 1697d056fa04SAlexander Leidinger EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_HPHONE_R); 1698d056fa04SAlexander Leidinger 1699d056fa04SAlexander Leidinger /* rec output to "ADC" */ 1700d056fa04SAlexander Leidinger /* volume controlled by AC97 emulation */ 1701d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_REC_L, M_MASTER_REC_L, A_OUT_ADC_REC_L, 100); 1702d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_REC_R, M_MASTER_REC_L, A_OUT_ADC_REC_R, 100); 1703d056fa04SAlexander Leidinger #ifdef SND_EMU10KX_MULTICHANNEL 1704d056fa04SAlexander Leidinger /* 1705d056fa04SAlexander Leidinger * Additional channel volume is controlled by mixer in 1706d056fa04SAlexander Leidinger * emu_dspmixer_set() in -pcm.c 1707d056fa04SAlexander Leidinger */ 1708d056fa04SAlexander Leidinger 1709d056fa04SAlexander Leidinger /* fx2/3 (pcm1) to rear */ 1710d056fa04SAlexander Leidinger EFX_CACHE(C_REAR_L); 1711d056fa04SAlexander Leidinger EFX_CACHE(C_REAR_R); 1712d056fa04SAlexander Leidinger EFX_ROUTE(NULL, FX(2), M_FX2_REAR_L, C_REAR_L, 100); 1713d056fa04SAlexander Leidinger EFX_ROUTE(NULL, FX(3), M_FX3_REAR_R, C_REAR_R, 100); 1714d056fa04SAlexander Leidinger 1715d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_REAR_L, M_MASTER_REAR_L, A_OUT_A_REAR_L, 100); 1716d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_REAR_R, M_MASTER_REAR_R, A_OUT_A_REAR_R, 100); 1717d056fa04SAlexander Leidinger EFX_OUTPUTD(C_REAR_L, M_MASTER_REAR_L, A_OUT_D_REAR_L); 1718d056fa04SAlexander Leidinger EFX_OUTPUTD(C_REAR_R, M_MASTER_REAR_L, A_OUT_D_REAR_R); 1719d056fa04SAlexander Leidinger 1720d056fa04SAlexander Leidinger /* fx4 (pcm2) to center */ 1721d056fa04SAlexander Leidinger EFX_CACHE(C_CENTER); 1722d056fa04SAlexander Leidinger EFX_ROUTE(NULL, FX(4), M_FX4_CENTER, C_CENTER, 100); 1723d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, A_OUT_D_CENTER, 100); 1724d056fa04SAlexander Leidinger #if 0 1725d056fa04SAlexander Leidinger /* XXX in digital mode (default) this should be muted because 1726d056fa04SAlexander Leidinger this output is shared with digital out */ 1727d056fa04SAlexander Leidinger EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, A_OUT_A_CENTER); 1728d056fa04SAlexander Leidinger #endif 1729d056fa04SAlexander Leidinger /* fx5 (pcm3) to sub */ 1730d056fa04SAlexander Leidinger EFX_CACHE(C_SUB); 1731d056fa04SAlexander Leidinger EFX_ROUTE(NULL, FX(5), M_FX5_SUBWOOFER, C_SUB, 100); 1732d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, A_OUT_D_SUB, 100); 1733d056fa04SAlexander Leidinger #if 0 1734d056fa04SAlexander Leidinger /* XXX in digital mode (default) this should be muted because 1735d056fa04SAlexander Leidinger this output is shared with digital out */ 1736d056fa04SAlexander Leidinger EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, A_OUT_A_SUB); 1737d056fa04SAlexander Leidinger #endif 1738d056fa04SAlexander Leidinger if (sc->has_71) { 1739d056fa04SAlexander Leidinger /* XXX this will broke headphones on AudigyDrive */ 1740d056fa04SAlexander Leidinger /* fx6/7 (pcm4) to side */ 1741d056fa04SAlexander Leidinger EFX_CACHE(C_SIDE_L); 1742d056fa04SAlexander Leidinger EFX_CACHE(C_SIDE_R); 1743d056fa04SAlexander Leidinger EFX_ROUTE(NULL, FX(6), M_FX6_SIDE_L, C_SIDE_L, 100); 1744d056fa04SAlexander Leidinger EFX_ROUTE(NULL, FX(7), M_FX7_SIDE_R, C_SIDE_R, 100); 1745d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_SIDE_L, M_MASTER_SIDE_L, A_OUT_A_SIDE_L, 100); 1746d056fa04SAlexander Leidinger EFX_OUTPUT(NULL, C_SIDE_R, M_MASTER_SIDE_R, A_OUT_A_SIDE_R, 100); 1747d056fa04SAlexander Leidinger EFX_OUTPUTD(C_SIDE_L, M_MASTER_SIDE_L, A_OUT_D_SIDE_L); 1748d056fa04SAlexander Leidinger EFX_OUTPUTD(C_SIDE_R, M_MASTER_SIDE_R, A_OUT_D_SIDE_R); 1749d056fa04SAlexander Leidinger } 1750d056fa04SAlexander Leidinger #else /* !SND_EMU10KX_MULTICHANNEL */ 1751d056fa04SAlexander Leidinger EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_A_REAR_L); 1752d056fa04SAlexander Leidinger EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_A_REAR_R); 1753d056fa04SAlexander Leidinger 1754d056fa04SAlexander Leidinger EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_D_REAR_L); 1755d056fa04SAlexander Leidinger EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_D_REAR_R); 1756d056fa04SAlexander Leidinger #endif 1757d056fa04SAlexander Leidinger } 1758d056fa04SAlexander Leidinger 1759d056fa04SAlexander Leidinger sc->routing_code_end = pc; 1760d056fa04SAlexander Leidinger 1761d056fa04SAlexander Leidinger /* start DSP */ 1762d056fa04SAlexander Leidinger if (sc->is_emu10k1) { 1763d056fa04SAlexander Leidinger emu_wrptr(sc, 0, DBG, 0); 1764d056fa04SAlexander Leidinger } else { 1765d056fa04SAlexander Leidinger emu_wrptr(sc, 0, A_DBG, 0); 1766d056fa04SAlexander Leidinger } 1767d056fa04SAlexander Leidinger } 1768d056fa04SAlexander Leidinger 1769d056fa04SAlexander Leidinger /* /dev/em10kx */ 1770d056fa04SAlexander Leidinger static d_open_t emu10kx_open; 1771d056fa04SAlexander Leidinger static d_close_t emu10kx_close; 1772d056fa04SAlexander Leidinger static d_read_t emu10kx_read; 1773d056fa04SAlexander Leidinger 1774d056fa04SAlexander Leidinger static struct cdevsw emu10kx_cdevsw = { 1775d056fa04SAlexander Leidinger .d_open = emu10kx_open, 1776d056fa04SAlexander Leidinger .d_close = emu10kx_close, 1777d056fa04SAlexander Leidinger .d_read = emu10kx_read, 1778d056fa04SAlexander Leidinger .d_name = "emu10kx", 1779d056fa04SAlexander Leidinger .d_version = D_VERSION, 1780d056fa04SAlexander Leidinger }; 1781d056fa04SAlexander Leidinger 1782d056fa04SAlexander Leidinger 1783d056fa04SAlexander Leidinger static int 1784d056fa04SAlexander Leidinger emu10kx_open(struct cdev *i_dev, int flags __unused, int mode __unused, struct thread *td __unused) 1785d056fa04SAlexander Leidinger { 1786d056fa04SAlexander Leidinger int error; 1787d056fa04SAlexander Leidinger struct emu_sc_info *sc; 1788d056fa04SAlexander Leidinger 1789d056fa04SAlexander Leidinger sc = i_dev->si_drv1; 1790d056fa04SAlexander Leidinger mtx_lock(&sc->emu10kx_lock); 1791d056fa04SAlexander Leidinger if (sc->emu10kx_isopen) { 1792d056fa04SAlexander Leidinger mtx_unlock(&sc->emu10kx_lock); 1793d056fa04SAlexander Leidinger return (EBUSY); 1794d056fa04SAlexander Leidinger } 1795d056fa04SAlexander Leidinger sc->emu10kx_isopen = 1; 1796d056fa04SAlexander Leidinger mtx_unlock(&sc->emu10kx_lock); 1797d056fa04SAlexander Leidinger if (sbuf_new(&sc->emu10kx_sbuf, NULL, 4096, 0) == NULL) { 1798d056fa04SAlexander Leidinger error = ENXIO; 1799d056fa04SAlexander Leidinger goto out; 1800d056fa04SAlexander Leidinger } 1801d056fa04SAlexander Leidinger sc->emu10kx_bufptr = 0; 1802d056fa04SAlexander Leidinger error = (emu10kx_prepare(sc, &sc->emu10kx_sbuf) > 0) ? 0 : ENOMEM; 1803d056fa04SAlexander Leidinger out: 1804d056fa04SAlexander Leidinger if (error) { 1805d056fa04SAlexander Leidinger mtx_lock(&sc->emu10kx_lock); 1806d056fa04SAlexander Leidinger sc->emu10kx_isopen = 0; 1807d056fa04SAlexander Leidinger mtx_unlock(&sc->emu10kx_lock); 1808d056fa04SAlexander Leidinger } 1809d056fa04SAlexander Leidinger return (error); 1810d056fa04SAlexander Leidinger } 1811d056fa04SAlexander Leidinger 1812d056fa04SAlexander Leidinger static int 1813d056fa04SAlexander Leidinger emu10kx_close(struct cdev *i_dev, int flags __unused, int mode __unused, struct thread *td __unused) 1814d056fa04SAlexander Leidinger { 1815d056fa04SAlexander Leidinger struct emu_sc_info *sc; 1816d056fa04SAlexander Leidinger 1817d056fa04SAlexander Leidinger sc = i_dev->si_drv1; 1818d056fa04SAlexander Leidinger 1819d056fa04SAlexander Leidinger mtx_lock(&sc->emu10kx_lock); 1820d056fa04SAlexander Leidinger if (!(sc->emu10kx_isopen)) { 1821d056fa04SAlexander Leidinger mtx_unlock(&sc->emu10kx_lock); 1822d056fa04SAlexander Leidinger return (EBADF); 1823d056fa04SAlexander Leidinger } 1824d056fa04SAlexander Leidinger sbuf_delete(&sc->emu10kx_sbuf); 1825d056fa04SAlexander Leidinger sc->emu10kx_isopen = 0; 1826d056fa04SAlexander Leidinger mtx_unlock(&sc->emu10kx_lock); 1827d056fa04SAlexander Leidinger 1828d056fa04SAlexander Leidinger return (0); 1829d056fa04SAlexander Leidinger } 1830d056fa04SAlexander Leidinger 1831d056fa04SAlexander Leidinger static int 1832d056fa04SAlexander Leidinger emu10kx_read(struct cdev *i_dev, struct uio *buf, int flag __unused) 1833d056fa04SAlexander Leidinger { 1834d056fa04SAlexander Leidinger int l, err; 1835d056fa04SAlexander Leidinger struct emu_sc_info *sc; 1836d056fa04SAlexander Leidinger 1837d056fa04SAlexander Leidinger sc = i_dev->si_drv1; 1838d056fa04SAlexander Leidinger mtx_lock(&sc->emu10kx_lock); 1839d056fa04SAlexander Leidinger if (!(sc->emu10kx_isopen)) { 1840d056fa04SAlexander Leidinger mtx_unlock(&sc->emu10kx_lock); 1841d056fa04SAlexander Leidinger return (EBADF); 1842d056fa04SAlexander Leidinger } 1843d056fa04SAlexander Leidinger mtx_unlock(&sc->emu10kx_lock); 1844d056fa04SAlexander Leidinger 1845d056fa04SAlexander Leidinger l = min(buf->uio_resid, sbuf_len(&sc->emu10kx_sbuf) - sc->emu10kx_bufptr); 1846d056fa04SAlexander Leidinger err = (l > 0) ? uiomove(sbuf_data(&sc->emu10kx_sbuf) + sc->emu10kx_bufptr, l, buf) : 0; 1847d056fa04SAlexander Leidinger sc->emu10kx_bufptr += l; 1848d056fa04SAlexander Leidinger 1849d056fa04SAlexander Leidinger return (err); 1850d056fa04SAlexander Leidinger } 1851d056fa04SAlexander Leidinger 1852d056fa04SAlexander Leidinger static int 1853d056fa04SAlexander Leidinger emu10kx_prepare(struct emu_sc_info *sc, struct sbuf *s) 1854d056fa04SAlexander Leidinger { 1855d056fa04SAlexander Leidinger int i; 1856d056fa04SAlexander Leidinger 1857d056fa04SAlexander Leidinger sbuf_printf(s, "FreeBSD EMU10Kx Audio Driver\n"); 1858d056fa04SAlexander Leidinger sbuf_printf(s, "\nHardware resource usage:\n"); 1859d056fa04SAlexander Leidinger sbuf_printf(s, "DSP General Purpose Registers: %d used, %d total\n", sc->rm->num_used, sc->rm->num_gprs); 1860d056fa04SAlexander Leidinger sbuf_printf(s, "DSP Instruction Registers: %d used, %d total\n", sc->routing_code_end, sc->code_size); 1861d056fa04SAlexander Leidinger sbuf_printf(s, "Card supports"); 1862d056fa04SAlexander Leidinger if (sc->has_ac97) { 1863d056fa04SAlexander Leidinger sbuf_printf(s, " AC97 codec"); 1864d056fa04SAlexander Leidinger } else { 1865d056fa04SAlexander Leidinger sbuf_printf(s, " NO AC97 codec"); 1866d056fa04SAlexander Leidinger } 1867d056fa04SAlexander Leidinger if (sc->has_51) { 1868d056fa04SAlexander Leidinger if (sc->has_71) 1869d056fa04SAlexander Leidinger sbuf_printf(s, " and 7.1 output"); 1870d056fa04SAlexander Leidinger else 1871d056fa04SAlexander Leidinger sbuf_printf(s, " and 5.1 output"); 1872d056fa04SAlexander Leidinger } 1873d056fa04SAlexander Leidinger if (sc->is_emu10k1) 1874d056fa04SAlexander Leidinger sbuf_printf(s, ", SBLive! DSP code"); 1875d056fa04SAlexander Leidinger if (sc->is_emu10k2) 1876d056fa04SAlexander Leidinger sbuf_printf(s, ", Audigy DSP code"); 1877d056fa04SAlexander Leidinger if (sc->is_ca0102) 1878d056fa04SAlexander Leidinger sbuf_printf(s, ", Audigy DSP code with Audigy2 hacks"); 1879d056fa04SAlexander Leidinger if (sc->is_ca0108) 1880d056fa04SAlexander Leidinger sbuf_printf(s, ", Audigy DSP code with Audigy2Value hacks"); 1881d056fa04SAlexander Leidinger sbuf_printf(s, "\n"); 1882d056fa04SAlexander Leidinger if (sc->broken_digital) 1883d056fa04SAlexander Leidinger sbuf_printf(s, "Digital mode unsupported\n"); 1884d056fa04SAlexander Leidinger sbuf_printf(s, "\nInstalled devices:\n"); 1885d056fa04SAlexander Leidinger for (i = 0; i < 5; i++) 1886d056fa04SAlexander Leidinger if (sc->pcm[i] != NULL) 1887d056fa04SAlexander Leidinger if (device_is_attached(sc->pcm[i])) { 1888d056fa04SAlexander Leidinger sbuf_printf(s, "%s on %s\n", device_get_desc(sc->pcm[i]), device_get_nameunit(sc->pcm[i])); 1889d056fa04SAlexander Leidinger } 1890d056fa04SAlexander Leidinger if (sc->midi[0] != NULL) 1891d056fa04SAlexander Leidinger if (device_is_attached(sc->midi[0])) { 1892d056fa04SAlexander Leidinger sbuf_printf(s, "EMU10Kx MIDI Interface\n"); 1893d056fa04SAlexander Leidinger sbuf_printf(s, "\tOn-card connector on %s\n", device_get_nameunit(sc->midi[0])); 1894d056fa04SAlexander Leidinger } 1895d056fa04SAlexander Leidinger if (sc->midi[1] != NULL) 1896d056fa04SAlexander Leidinger if (device_is_attached(sc->midi[1])) { 1897d056fa04SAlexander Leidinger sbuf_printf(s, "\tOn-Drive connector on %s\n", device_get_nameunit(sc->midi[1])); 1898d056fa04SAlexander Leidinger } 1899d056fa04SAlexander Leidinger if (sc->midi[0] != NULL) 1900d056fa04SAlexander Leidinger if (device_is_attached(sc->midi[0])) { 1901d056fa04SAlexander Leidinger sbuf_printf(s, "\tIR reciever MIDI events %s\n", sc->enable_ir ? "enabled" : "disabled"); 1902d056fa04SAlexander Leidinger } 1903d056fa04SAlexander Leidinger sbuf_finish(s); 1904d056fa04SAlexander Leidinger return (sbuf_len(s)); 1905d056fa04SAlexander Leidinger } 1906d056fa04SAlexander Leidinger 1907d056fa04SAlexander Leidinger /* INIT & UNINIT */ 1908d056fa04SAlexander Leidinger static int 1909d056fa04SAlexander Leidinger emu10kx_dev_init(struct emu_sc_info *sc) 1910d056fa04SAlexander Leidinger { 1911d056fa04SAlexander Leidinger int unit; 1912d056fa04SAlexander Leidinger 1913d056fa04SAlexander Leidinger mtx_init(&sc->emu10kx_lock, "kxdevlock", NULL, 0); 1914d056fa04SAlexander Leidinger unit = device_get_unit(sc->dev); 1915d056fa04SAlexander Leidinger 1916d056fa04SAlexander Leidinger sc->cdev = make_dev(&emu10kx_cdevsw, unit2minor(unit), UID_ROOT, GID_WHEEL, 0640, "emu10kx%d", unit); 1917d056fa04SAlexander Leidinger if (sc->cdev != NULL) { 1918d056fa04SAlexander Leidinger sc->cdev->si_drv1 = sc; 1919d056fa04SAlexander Leidinger return (0); 1920d056fa04SAlexander Leidinger } 1921d056fa04SAlexander Leidinger return (ENXIO); 1922d056fa04SAlexander Leidinger } 1923d056fa04SAlexander Leidinger 1924d056fa04SAlexander Leidinger static int 1925d056fa04SAlexander Leidinger emu10kx_dev_uninit(struct emu_sc_info *sc) 1926d056fa04SAlexander Leidinger { 1927d056fa04SAlexander Leidinger intrmask_t s; 1928d056fa04SAlexander Leidinger 1929d056fa04SAlexander Leidinger s = spltty(); 1930d056fa04SAlexander Leidinger mtx_lock(&sc->emu10kx_lock); 1931d056fa04SAlexander Leidinger if (sc->emu10kx_isopen) { 1932d056fa04SAlexander Leidinger mtx_unlock(&sc->emu10kx_lock); 1933d056fa04SAlexander Leidinger splx(s); 1934d056fa04SAlexander Leidinger return (EBUSY); 1935d056fa04SAlexander Leidinger } 1936d056fa04SAlexander Leidinger if (sc->cdev) 1937d056fa04SAlexander Leidinger destroy_dev(sc->cdev); 1938d056fa04SAlexander Leidinger sc->cdev = 0; 1939d056fa04SAlexander Leidinger 1940d056fa04SAlexander Leidinger splx(s); 1941d056fa04SAlexander Leidinger mtx_destroy(&sc->emu10kx_lock); 1942d056fa04SAlexander Leidinger return (0); 1943d056fa04SAlexander Leidinger } 1944d056fa04SAlexander Leidinger 1945d056fa04SAlexander Leidinger /* resource manager */ 1946d056fa04SAlexander Leidinger int 1947d056fa04SAlexander Leidinger emu_rm_init(struct emu_sc_info *sc) 1948d056fa04SAlexander Leidinger { 1949d056fa04SAlexander Leidinger int i; 1950d056fa04SAlexander Leidinger int maxcount; 1951d056fa04SAlexander Leidinger struct emu_rm *rm; 1952d056fa04SAlexander Leidinger 1953d056fa04SAlexander Leidinger rm = malloc(sizeof(struct emu_rm), M_DEVBUF, M_NOWAIT | M_ZERO); 1954d056fa04SAlexander Leidinger if (rm == NULL) { 1955d056fa04SAlexander Leidinger return (ENOMEM); 1956d056fa04SAlexander Leidinger } 1957d056fa04SAlexander Leidinger sc->rm = rm; 1958d056fa04SAlexander Leidinger rm->card = sc; 1959d056fa04SAlexander Leidinger maxcount = sc->num_gprs; 1960d056fa04SAlexander Leidinger rm->num_used = 0; 1961d056fa04SAlexander Leidinger mtx_init(&(rm->gpr_lock), "emu10k", "gpr alloc", MTX_DEF); 1962d056fa04SAlexander Leidinger rm->num_gprs = (maxcount < EMU_MAX_GPR ? maxcount : EMU_MAX_GPR); 1963d056fa04SAlexander Leidinger for (i = 0; i < rm->num_gprs; i++) 1964d056fa04SAlexander Leidinger rm->allocmap[i] = 0; 1965d056fa04SAlexander Leidinger rm->last_free_gpr = 0; 1966d056fa04SAlexander Leidinger 1967d056fa04SAlexander Leidinger return (0); 1968d056fa04SAlexander Leidinger } 1969d056fa04SAlexander Leidinger 1970d056fa04SAlexander Leidinger int 1971d056fa04SAlexander Leidinger emu_rm_uninit(struct emu_sc_info *sc) 1972d056fa04SAlexander Leidinger { 1973d056fa04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG 1974d056fa04SAlexander Leidinger int i; 1975d056fa04SAlexander Leidinger 1976d056fa04SAlexander Leidinger mtx_lock(&(sc->rm->gpr_lock)); 1977d056fa04SAlexander Leidinger for (i = 0; i < sc->rm->last_free_gpr; i++) 1978d056fa04SAlexander Leidinger if (sc->rm->allocmap[i] > 0) 1979d056fa04SAlexander Leidinger device_printf(sc->dev, "rm: gpr %d not free before uninit\n", i); 1980d056fa04SAlexander Leidinger mtx_unlock(&(sc->rm->gpr_lock)); 1981d056fa04SAlexander Leidinger #endif 1982d056fa04SAlexander Leidinger mtx_destroy(&(sc->rm->gpr_lock)); 1983d056fa04SAlexander Leidinger free(sc->rm, M_DEVBUF); 1984d056fa04SAlexander Leidinger return (0); 1985d056fa04SAlexander Leidinger } 1986d056fa04SAlexander Leidinger 1987d056fa04SAlexander Leidinger static int 1988d056fa04SAlexander Leidinger emu_rm_gpr_alloc(struct emu_rm *rm, int count) 1989d056fa04SAlexander Leidinger { 1990d056fa04SAlexander Leidinger int i, j; 1991d056fa04SAlexander Leidinger int allocated_gpr; 1992d056fa04SAlexander Leidinger 1993d056fa04SAlexander Leidinger allocated_gpr = rm->num_gprs; 1994d056fa04SAlexander Leidinger /* try fast way first */ 1995d056fa04SAlexander Leidinger mtx_lock(&(rm->gpr_lock)); 1996d056fa04SAlexander Leidinger if (rm->last_free_gpr + count <= rm->num_gprs) { 1997d056fa04SAlexander Leidinger allocated_gpr = rm->last_free_gpr; 1998d056fa04SAlexander Leidinger rm->last_free_gpr += count; 1999d056fa04SAlexander Leidinger rm->allocmap[allocated_gpr] = count; 2000d056fa04SAlexander Leidinger for (i = 1; i < count; i++) 2001d056fa04SAlexander Leidinger rm->allocmap[allocated_gpr + i] = -(count - i); 2002d056fa04SAlexander Leidinger } else { 2003d056fa04SAlexander Leidinger /* longer */ 2004d056fa04SAlexander Leidinger i = 0; 2005d056fa04SAlexander Leidinger allocated_gpr = rm->num_gprs; 2006d056fa04SAlexander Leidinger while (i < rm->last_free_gpr - count) { 2007d056fa04SAlexander Leidinger if (rm->allocmap[i] > 0) { 2008d056fa04SAlexander Leidinger i += rm->allocmap[i]; 2009d056fa04SAlexander Leidinger } else { 2010d056fa04SAlexander Leidinger allocated_gpr = i; 2011d056fa04SAlexander Leidinger for (j = 1; j < count; j++) { 2012d056fa04SAlexander Leidinger if (rm->allocmap[i + j] != 0) 2013d056fa04SAlexander Leidinger allocated_gpr = rm->num_gprs; 2014d056fa04SAlexander Leidinger } 2015d056fa04SAlexander Leidinger if (allocated_gpr == i) 2016d056fa04SAlexander Leidinger break; 2017d056fa04SAlexander Leidinger } 2018d056fa04SAlexander Leidinger } 2019d056fa04SAlexander Leidinger if (allocated_gpr + count < rm->last_free_gpr) { 2020d056fa04SAlexander Leidinger rm->allocmap[allocated_gpr] = count; 2021d056fa04SAlexander Leidinger for (i = 1; i < count; i++) 2022d056fa04SAlexander Leidinger rm->allocmap[allocated_gpr + i] = -(count - i); 2023d056fa04SAlexander Leidinger 2024d056fa04SAlexander Leidinger } 2025d056fa04SAlexander Leidinger } 2026d056fa04SAlexander Leidinger if (allocated_gpr == rm->num_gprs) 2027d056fa04SAlexander Leidinger allocated_gpr = (-1); 2028d056fa04SAlexander Leidinger if (allocated_gpr >= 0) 2029d056fa04SAlexander Leidinger rm->num_used += count; 2030d056fa04SAlexander Leidinger mtx_unlock(&(rm->gpr_lock)); 2031d056fa04SAlexander Leidinger return (allocated_gpr); 2032d056fa04SAlexander Leidinger } 2033d056fa04SAlexander Leidinger 2034d056fa04SAlexander Leidinger /* mixer */ 2035d056fa04SAlexander Leidinger void 2036d056fa04SAlexander Leidinger emumix_set_mode(struct emu_sc_info *sc, int mode) 2037d056fa04SAlexander Leidinger { 2038d056fa04SAlexander Leidinger uint32_t a_iocfg; 2039d056fa04SAlexander Leidinger uint32_t hcfg; 2040d056fa04SAlexander Leidinger uint32_t tmp; 2041d056fa04SAlexander Leidinger 2042d056fa04SAlexander Leidinger switch (mode) { 2043d056fa04SAlexander Leidinger case MODE_DIGITAL: 2044d056fa04SAlexander Leidinger /* FALLTHROUGH */ 2045d056fa04SAlexander Leidinger case MODE_ANALOG: 2046d056fa04SAlexander Leidinger break; 2047d056fa04SAlexander Leidinger default: 2048d056fa04SAlexander Leidinger return; 2049d056fa04SAlexander Leidinger } 2050d056fa04SAlexander Leidinger 2051d056fa04SAlexander Leidinger hcfg = HCFG_AUDIOENABLE | HCFG_AUTOMUTE; 2052d056fa04SAlexander Leidinger a_iocfg = 0; 2053d056fa04SAlexander Leidinger 2054d056fa04SAlexander Leidinger if (sc->rev >= 6) 2055d056fa04SAlexander Leidinger hcfg |= HCFG_JOYENABLE; 2056d056fa04SAlexander Leidinger 2057d056fa04SAlexander Leidinger if (sc->is_emu10k1) 2058d056fa04SAlexander Leidinger hcfg |= HCFG_LOCKTANKCACHE_MASK; 2059d056fa04SAlexander Leidinger else 2060d056fa04SAlexander Leidinger hcfg |= HCFG_CODECFORMAT_I2S | HCFG_JOYENABLE; 2061d056fa04SAlexander Leidinger 2062d056fa04SAlexander Leidinger 2063d056fa04SAlexander Leidinger if (mode == MODE_DIGITAL) { 2064d056fa04SAlexander Leidinger if (sc->broken_digital) { 2065d056fa04SAlexander Leidinger device_printf(sc->dev, "Digital mode is reported as broken on this card,\n"); 2066d056fa04SAlexander Leidinger } 2067d056fa04SAlexander Leidinger a_iocfg |= A_IOCFG_ENABLE_DIGITAL; 2068d056fa04SAlexander Leidinger hcfg |= HCFG_GPOUT0; 2069d056fa04SAlexander Leidinger } 2070d056fa04SAlexander Leidinger 2071d056fa04SAlexander Leidinger if (mode == MODE_ANALOG) 2072d056fa04SAlexander Leidinger emumix_set_spdif_mode(sc, SPDIF_MODE_PCM); 2073d056fa04SAlexander Leidinger 2074d056fa04SAlexander Leidinger if (sc->is_emu10k2) 2075d056fa04SAlexander Leidinger a_iocfg |= 0x80; /* XXX */ 2076d056fa04SAlexander Leidinger 2077d056fa04SAlexander Leidinger if ((sc->is_ca0102) || (sc->is_ca0108)) 2078d056fa04SAlexander Leidinger a_iocfg |= A_IOCFG_DISABLE_ANALOG; /* means "don't disable" 2079d056fa04SAlexander Leidinger on this two cards. Means "disable" on emu10k2. */ 2080d056fa04SAlexander Leidinger 2081d056fa04SAlexander Leidinger if (sc->is_ca0108) 2082d056fa04SAlexander Leidinger a_iocfg |= 0x20; /* XXX */ 2083d056fa04SAlexander Leidinger 2084d056fa04SAlexander Leidinger emu_wr(sc, HCFG, hcfg, 4); 2085d056fa04SAlexander Leidinger 2086d056fa04SAlexander Leidinger if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) { 2087d056fa04SAlexander Leidinger tmp = emu_rd(sc, A_IOCFG, 2); 2088d056fa04SAlexander Leidinger tmp = a_iocfg; 2089d056fa04SAlexander Leidinger emu_wr(sc, A_IOCFG, tmp, 2); 2090d056fa04SAlexander Leidinger } 2091d056fa04SAlexander Leidinger 2092d056fa04SAlexander Leidinger /* 2093d056fa04SAlexander Leidinger * XXX Mute center/sub if we go digital on Audigy or later card. 2094d056fa04SAlexander Leidinger * Route to analog center / sub in emu_initef should be disabled 2095d056fa04SAlexander Leidinger * until this problem is fixed. 2096d056fa04SAlexander Leidinger */ 2097d056fa04SAlexander Leidinger } 2098d056fa04SAlexander Leidinger 2099d056fa04SAlexander Leidinger void 2100d056fa04SAlexander Leidinger emumix_set_spdif_mode(struct emu_sc_info *sc, int mode) 2101d056fa04SAlexander Leidinger { 2102d056fa04SAlexander Leidinger uint32_t spcs; 2103d056fa04SAlexander Leidinger 2104d056fa04SAlexander Leidinger switch (mode) { 2105d056fa04SAlexander Leidinger case SPDIF_MODE_PCM: 2106d056fa04SAlexander Leidinger break; 2107d056fa04SAlexander Leidinger case SPDIF_MODE_AC3: 2108d056fa04SAlexander Leidinger device_printf(sc->dev, "AC3 mode does not work and disabled\n"); 2109d056fa04SAlexander Leidinger return; 2110d056fa04SAlexander Leidinger default: 2111d056fa04SAlexander Leidinger return; 2112d056fa04SAlexander Leidinger } 2113d056fa04SAlexander Leidinger 2114d056fa04SAlexander Leidinger spcs = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | 2115d056fa04SAlexander Leidinger SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | 2116d056fa04SAlexander Leidinger SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | 2117d056fa04SAlexander Leidinger SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; 2118d056fa04SAlexander Leidinger 2119d056fa04SAlexander Leidinger mode = SPDIF_MODE_PCM; 2120d056fa04SAlexander Leidinger 2121d056fa04SAlexander Leidinger emu_wrptr(sc, 0, SPCS0, spcs); 2122d056fa04SAlexander Leidinger emu_wrptr(sc, 0, SPCS1, spcs); 2123d056fa04SAlexander Leidinger emu_wrptr(sc, 0, SPCS2, spcs); 2124d056fa04SAlexander Leidinger } 2125d056fa04SAlexander Leidinger 2126d056fa04SAlexander Leidinger #define L2L_POINTS 10 2127d056fa04SAlexander Leidinger 2128d056fa04SAlexander Leidinger static int l2l_df[L2L_POINTS] = { 2129d056fa04SAlexander Leidinger 0x572C5CA, /* 100..90 */ 2130d056fa04SAlexander Leidinger 0x3211625, /* 90..80 */ 2131d056fa04SAlexander Leidinger 0x1CC1A76, /* 80..70 */ 2132d056fa04SAlexander Leidinger 0x108428F, /* 70..60 */ 2133d056fa04SAlexander Leidinger 0x097C70A, /* 60..50 */ 2134d056fa04SAlexander Leidinger 0x0572C5C, /* 50..40 */ 2135d056fa04SAlexander Leidinger 0x0321162, /* 40..30 */ 2136d056fa04SAlexander Leidinger 0x01CC1A7, /* 30..20 */ 2137d056fa04SAlexander Leidinger 0x0108428, /* 20..10 */ 2138d056fa04SAlexander Leidinger 0x016493D /* 10..0 */ 2139d056fa04SAlexander Leidinger }; 2140d056fa04SAlexander Leidinger 2141d056fa04SAlexander Leidinger static int l2l_f[L2L_POINTS] = { 2142d056fa04SAlexander Leidinger 0x4984461A, /* 90 */ 2143d056fa04SAlexander Leidinger 0x2A3968A7, /* 80 */ 2144d056fa04SAlexander Leidinger 0x18406003, /* 70 */ 2145d056fa04SAlexander Leidinger 0x0DEDC66D, /* 60 */ 2146d056fa04SAlexander Leidinger 0x07FFFFFF, /* 50 */ 2147d056fa04SAlexander Leidinger 0x04984461, /* 40 */ 2148d056fa04SAlexander Leidinger 0x02A3968A, /* 30 */ 2149d056fa04SAlexander Leidinger 0x01840600, /* 20 */ 2150d056fa04SAlexander Leidinger 0x00DEDC66, /* 10 */ 2151d056fa04SAlexander Leidinger 0x00000000 /* 0 */ 2152d056fa04SAlexander Leidinger }; 2153d056fa04SAlexander Leidinger 2154d056fa04SAlexander Leidinger 2155d056fa04SAlexander Leidinger static int 2156d056fa04SAlexander Leidinger log2lin(int log_t) 2157d056fa04SAlexander Leidinger { 2158d056fa04SAlexander Leidinger int lin_t; 2159d056fa04SAlexander Leidinger int idx, lin; 2160d056fa04SAlexander Leidinger 2161d056fa04SAlexander Leidinger if (log_t <= 0) { 2162d056fa04SAlexander Leidinger lin_t = 0x00000000; 2163d056fa04SAlexander Leidinger return (lin_t); 2164d056fa04SAlexander Leidinger } 2165d056fa04SAlexander Leidinger 2166d056fa04SAlexander Leidinger if (log_t >= 100) { 2167d056fa04SAlexander Leidinger lin_t = 0x7fffffff; 2168d056fa04SAlexander Leidinger return (lin_t); 2169d056fa04SAlexander Leidinger } 2170d056fa04SAlexander Leidinger 2171d056fa04SAlexander Leidinger idx = (L2L_POINTS - 1) - log_t / (L2L_POINTS); 2172d056fa04SAlexander Leidinger lin = log_t % (L2L_POINTS); 2173d056fa04SAlexander Leidinger lin_t = l2l_df[idx] * lin + l2l_f[idx]; 2174d056fa04SAlexander Leidinger return (lin_t); 2175d056fa04SAlexander Leidinger } 2176d056fa04SAlexander Leidinger 2177d056fa04SAlexander Leidinger 2178d056fa04SAlexander Leidinger void 2179d056fa04SAlexander Leidinger emumix_set_fxvol(struct emu_sc_info *sc, unsigned gpr, int32_t vol) 2180d056fa04SAlexander Leidinger { 2181d056fa04SAlexander Leidinger 2182d056fa04SAlexander Leidinger vol = log2lin(vol); 2183d056fa04SAlexander Leidinger emumix_set_gpr(sc, gpr, vol); 2184d056fa04SAlexander Leidinger } 2185d056fa04SAlexander Leidinger 2186d056fa04SAlexander Leidinger void 2187d056fa04SAlexander Leidinger emumix_set_gpr(struct emu_sc_info *sc, unsigned gpr, int32_t val) 2188d056fa04SAlexander Leidinger { 2189d056fa04SAlexander Leidinger 2190d056fa04SAlexander Leidinger emu_wrptr(sc, 0, GPR(gpr), val); 2191d056fa04SAlexander Leidinger } 2192d056fa04SAlexander Leidinger 2193d056fa04SAlexander Leidinger void 2194d056fa04SAlexander Leidinger emumix_set_volume(struct emu_sc_info *sc, int mixer_idx, int volume) 2195d056fa04SAlexander Leidinger { 2196d056fa04SAlexander Leidinger 2197d056fa04SAlexander Leidinger RANGE(volume, 0, 100); 2198d056fa04SAlexander Leidinger if (mixer_idx < NUM_MIXERS) { 2199d056fa04SAlexander Leidinger sc->mixer_volcache[mixer_idx] = volume; 2200d056fa04SAlexander Leidinger emumix_set_fxvol(sc, sc->mixer_gpr[mixer_idx], volume); 2201d056fa04SAlexander Leidinger } 2202d056fa04SAlexander Leidinger } 2203d056fa04SAlexander Leidinger 2204d056fa04SAlexander Leidinger int 2205d056fa04SAlexander Leidinger emumix_get_volume(struct emu_sc_info *sc, int mixer_idx) 2206d056fa04SAlexander Leidinger { 2207d056fa04SAlexander Leidinger if ((mixer_idx < NUM_MIXERS) && (mixer_idx >= 0)) 2208d056fa04SAlexander Leidinger return (sc->mixer_volcache[mixer_idx]); 2209d056fa04SAlexander Leidinger return (-1); 2210d056fa04SAlexander Leidinger } 2211d056fa04SAlexander Leidinger 2212d056fa04SAlexander Leidinger /* Init CardBus part */ 2213d056fa04SAlexander Leidinger static int 2214d056fa04SAlexander Leidinger emu_cardbus_init(struct emu_sc_info *sc) 2215d056fa04SAlexander Leidinger { 2216d056fa04SAlexander Leidinger 2217d056fa04SAlexander Leidinger /* 2218d056fa04SAlexander Leidinger * XXX May not need this if we have IPR3 handler. 2219d056fa04SAlexander Leidinger * Is it a real init calls, or IPR3 interrupt acknowledgments? 2220d056fa04SAlexander Leidinger * Looks much like "(data << 16) | register". 2221d056fa04SAlexander Leidinger */ 2222d056fa04SAlexander Leidinger emu_wr_cbptr(sc, (0x00d0 << 16) | 0x0000); 2223d056fa04SAlexander Leidinger emu_wr_cbptr(sc, (0x00d0 << 16) | 0x0001); 2224d056fa04SAlexander Leidinger emu_wr_cbptr(sc, (0x00d0 << 16) | 0x005f); 2225d056fa04SAlexander Leidinger emu_wr_cbptr(sc, (0x00d0 << 16) | 0x007f); 2226d056fa04SAlexander Leidinger 2227d056fa04SAlexander Leidinger emu_wr_cbptr(sc, (0x0090 << 16) | 0x007f); 2228d056fa04SAlexander Leidinger 2229d056fa04SAlexander Leidinger return (0); 2230d056fa04SAlexander Leidinger } 2231d056fa04SAlexander Leidinger 2232d056fa04SAlexander Leidinger /* Probe and attach the card */ 2233d056fa04SAlexander Leidinger static int 2234d056fa04SAlexander Leidinger emu_init(struct emu_sc_info *sc) 2235d056fa04SAlexander Leidinger { 2236d056fa04SAlexander Leidinger uint32_t ch, tmp; 2237d056fa04SAlexander Leidinger uint32_t spdif_sr; 2238d056fa04SAlexander Leidinger uint32_t ac97slot; 2239d056fa04SAlexander Leidinger int def_mode; 2240d056fa04SAlexander Leidinger int i; 2241d056fa04SAlexander Leidinger 2242d056fa04SAlexander Leidinger /* disable audio and lock cache */ 2243d056fa04SAlexander Leidinger emu_wr(sc, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, 4); 2244d056fa04SAlexander Leidinger 2245d056fa04SAlexander Leidinger /* reset recording buffers */ 2246d056fa04SAlexander Leidinger emu_wrptr(sc, 0, MICBS, ADCBS_BUFSIZE_NONE); 2247d056fa04SAlexander Leidinger emu_wrptr(sc, 0, MICBA, 0); 2248d056fa04SAlexander Leidinger emu_wrptr(sc, 0, FXBS, ADCBS_BUFSIZE_NONE); 2249d056fa04SAlexander Leidinger emu_wrptr(sc, 0, FXBA, 0); 2250d056fa04SAlexander Leidinger emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE); 2251d056fa04SAlexander Leidinger emu_wrptr(sc, 0, ADCBA, 0); 2252d056fa04SAlexander Leidinger 2253d056fa04SAlexander Leidinger /* disable channel interrupt */ 2254d056fa04SAlexander Leidinger emu_wr(sc, INTE, INTE_INTERVALTIMERENB | INTE_SAMPLERATETRACKER | INTE_PCIERRORENABLE, 4); 2255d056fa04SAlexander Leidinger emu_wrptr(sc, 0, CLIEL, 0); 2256d056fa04SAlexander Leidinger emu_wrptr(sc, 0, CLIEH, 0); 2257d056fa04SAlexander Leidinger emu_wrptr(sc, 0, SOLEL, 0); 2258d056fa04SAlexander Leidinger emu_wrptr(sc, 0, SOLEH, 0); 2259d056fa04SAlexander Leidinger 2260d056fa04SAlexander Leidinger /* disable P16V and S/PDIF interrupts */ 2261d056fa04SAlexander Leidinger if ((sc->is_ca0102) || (sc->is_ca0108)) 2262d056fa04SAlexander Leidinger emu_wr(sc, INTE2, 0, 4); 2263d056fa04SAlexander Leidinger 2264d056fa04SAlexander Leidinger if (sc->is_ca0102) 2265d056fa04SAlexander Leidinger emu_wr(sc, INTE3, 0, 4); 2266d056fa04SAlexander Leidinger 2267d056fa04SAlexander Leidinger /* init phys inputs and outputs */ 2268d056fa04SAlexander Leidinger ac97slot = 0; 2269d056fa04SAlexander Leidinger if (sc->has_51) 2270d056fa04SAlexander Leidinger ac97slot = AC97SLOT_CNTR | AC97SLOT_LFE; 2271d056fa04SAlexander Leidinger if (sc->has_71) 2272d056fa04SAlexander Leidinger ac97slot = AC97SLOT_CNTR | AC97SLOT_LFE | AC97SLOT_REAR_LEFT | AC97SLOT_REAR_RIGHT; 2273d056fa04SAlexander Leidinger if (sc->is_emu10k2) 2274d056fa04SAlexander Leidinger ac97slot |= 0x40; 2275d056fa04SAlexander Leidinger emu_wrptr(sc, 0, AC97SLOT, ac97slot); 2276d056fa04SAlexander Leidinger 2277d056fa04SAlexander Leidinger if (sc->is_emu10k2) /* XXX for later cards? */ 2278d056fa04SAlexander Leidinger emu_wrptr(sc, 0, SPBYPASS, 0xf00); /* What will happen if 2279d056fa04SAlexander Leidinger * we write 1 here? */ 2280d056fa04SAlexander Leidinger 2281d056fa04SAlexander Leidinger sc->bufsz = EMU_DEFAULT_BUFSZ; /* FIXME: pcm code can change this... */ 2282d056fa04SAlexander Leidinger 2283d056fa04SAlexander Leidinger 2284d056fa04SAlexander Leidinger if (bus_dma_tag_create( /* parent */ NULL, /* alignment */ 2, /* boundary */ 0, 2285d056fa04SAlexander Leidinger /* lowaddr */ 1 << 31, /* can only access 0-2gb */ 2286d056fa04SAlexander Leidinger /* highaddr */ BUS_SPACE_MAXADDR, 2287d056fa04SAlexander Leidinger /* filter */ NULL, /* filterarg */ NULL, 2288d056fa04SAlexander Leidinger /* maxsize */ sc->bufsz, /* nsegments */ 1, /* maxsegz */ 0x3ffff, 2289d056fa04SAlexander Leidinger /* flags */ 0, /* lockfunc */ busdma_lock_mutex, 2290d056fa04SAlexander Leidinger /* lockarg */ &Giant, &(sc->mem.dmat)) != 0) { 2291d056fa04SAlexander Leidinger device_printf(sc->dev, "unable to create dma tag\n"); 2292d056fa04SAlexander Leidinger bus_dma_tag_destroy(sc->mem.dmat); 2293d056fa04SAlexander Leidinger return (ENOMEM); 2294d056fa04SAlexander Leidinger } 2295d056fa04SAlexander Leidinger 2296d056fa04SAlexander Leidinger SLIST_INIT(&sc->mem.blocks); 2297d056fa04SAlexander Leidinger sc->mem.ptb_pages = emu_malloc(&sc->mem, MAXPAGES * sizeof(uint32_t), &sc->mem.ptb_pages_addr); 2298d056fa04SAlexander Leidinger if (sc->mem.ptb_pages == NULL) 2299d056fa04SAlexander Leidinger return (ENOMEM); 2300d056fa04SAlexander Leidinger 2301d056fa04SAlexander Leidinger sc->mem.silent_page = emu_malloc(&sc->mem, EMUPAGESIZE, &sc->mem.silent_page_addr); 2302d056fa04SAlexander Leidinger if (sc->mem.silent_page == NULL) { 2303d056fa04SAlexander Leidinger emu_free(&sc->mem, sc->mem.ptb_pages); 2304d056fa04SAlexander Leidinger return (ENOMEM); 2305d056fa04SAlexander Leidinger } 2306d056fa04SAlexander Leidinger /* Clear page with silence & setup all pointers to this page */ 2307d056fa04SAlexander Leidinger bzero(sc->mem.silent_page, EMUPAGESIZE); 2308d056fa04SAlexander Leidinger tmp = (uint32_t) (sc->mem.silent_page_addr) << 1; 2309d056fa04SAlexander Leidinger for (i = 0; i < MAXPAGES; i++) 2310d056fa04SAlexander Leidinger sc->mem.ptb_pages[i] = tmp | i; 2311d056fa04SAlexander Leidinger 2312d056fa04SAlexander Leidinger for (ch = 0; ch < NUM_G; ch++) { 2313d056fa04SAlexander Leidinger emu_wrptr(sc, ch, MAPA, tmp | MAP_PTI_MASK); 2314d056fa04SAlexander Leidinger emu_wrptr(sc, ch, MAPB, tmp | MAP_PTI_MASK); 2315d056fa04SAlexander Leidinger } 2316d056fa04SAlexander Leidinger emu_wrptr(sc, 0, PTB, (sc->mem.ptb_pages_addr)); 2317d056fa04SAlexander Leidinger emu_wrptr(sc, 0, TCB, 0); /* taken from original driver */ 2318d056fa04SAlexander Leidinger emu_wrptr(sc, 0, TCBS, 0); /* taken from original driver */ 2319d056fa04SAlexander Leidinger 2320d056fa04SAlexander Leidinger /* init envelope engine */ 2321d056fa04SAlexander Leidinger for (ch = 0; ch < NUM_G; ch++) { 2322d056fa04SAlexander Leidinger emu_wrptr(sc, ch, DCYSUSV, 0); 2323d056fa04SAlexander Leidinger emu_wrptr(sc, ch, IP, 0); 2324d056fa04SAlexander Leidinger emu_wrptr(sc, ch, VTFT, 0xffff); 2325d056fa04SAlexander Leidinger emu_wrptr(sc, ch, CVCF, 0xffff); 2326d056fa04SAlexander Leidinger emu_wrptr(sc, ch, PTRX, 0); 2327d056fa04SAlexander Leidinger emu_wrptr(sc, ch, CPF, 0); 2328d056fa04SAlexander Leidinger emu_wrptr(sc, ch, CCR, 0); 2329d056fa04SAlexander Leidinger 2330d056fa04SAlexander Leidinger emu_wrptr(sc, ch, PSST, 0); 2331d056fa04SAlexander Leidinger emu_wrptr(sc, ch, DSL, 0x10); 2332d056fa04SAlexander Leidinger emu_wrptr(sc, ch, CCCA, 0); 2333d056fa04SAlexander Leidinger emu_wrptr(sc, ch, Z1, 0); 2334d056fa04SAlexander Leidinger emu_wrptr(sc, ch, Z2, 0); 2335d056fa04SAlexander Leidinger emu_wrptr(sc, ch, FXRT, 0xd01c0000); 2336d056fa04SAlexander Leidinger 2337d056fa04SAlexander Leidinger emu_wrptr(sc, ch, ATKHLDM, 0); 2338d056fa04SAlexander Leidinger emu_wrptr(sc, ch, DCYSUSM, 0); 2339d056fa04SAlexander Leidinger emu_wrptr(sc, ch, IFATN, 0xffff); 2340d056fa04SAlexander Leidinger emu_wrptr(sc, ch, PEFE, 0); 2341d056fa04SAlexander Leidinger emu_wrptr(sc, ch, FMMOD, 0); 2342d056fa04SAlexander Leidinger emu_wrptr(sc, ch, TREMFRQ, 24); /* 1 Hz */ 2343d056fa04SAlexander Leidinger emu_wrptr(sc, ch, FM2FRQ2, 24); /* 1 Hz */ 2344d056fa04SAlexander Leidinger emu_wrptr(sc, ch, TEMPENV, 0); 2345d056fa04SAlexander Leidinger 2346d056fa04SAlexander Leidinger /*** these are last so OFF prevents writing ***/ 2347d056fa04SAlexander Leidinger emu_wrptr(sc, ch, LFOVAL2, 0); 2348d056fa04SAlexander Leidinger emu_wrptr(sc, ch, LFOVAL1, 0); 2349d056fa04SAlexander Leidinger emu_wrptr(sc, ch, ATKHLDV, 0); 2350d056fa04SAlexander Leidinger emu_wrptr(sc, ch, ENVVOL, 0); 2351d056fa04SAlexander Leidinger emu_wrptr(sc, ch, ENVVAL, 0); 2352d056fa04SAlexander Leidinger 2353d056fa04SAlexander Leidinger if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) { 2354d056fa04SAlexander Leidinger emu_wrptr(sc, ch, 0x4c, 0x0); 2355d056fa04SAlexander Leidinger emu_wrptr(sc, ch, 0x4d, 0x0); 2356d056fa04SAlexander Leidinger emu_wrptr(sc, ch, 0x4e, 0x0); 2357d056fa04SAlexander Leidinger emu_wrptr(sc, ch, 0x4f, 0x0); 2358d056fa04SAlexander Leidinger emu_wrptr(sc, ch, A_FXRT1, 0x3f3f3f3f); 2359d056fa04SAlexander Leidinger emu_wrptr(sc, ch, A_FXRT2, 0x3f3f3f3f); 2360d056fa04SAlexander Leidinger emu_wrptr(sc, ch, A_SENDAMOUNTS, 0x0); 2361d056fa04SAlexander Leidinger } 2362d056fa04SAlexander Leidinger } 2363d056fa04SAlexander Leidinger 2364d056fa04SAlexander Leidinger emumix_set_spdif_mode(sc, SPDIF_MODE_PCM); 2365d056fa04SAlexander Leidinger 2366d056fa04SAlexander Leidinger if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) 2367d056fa04SAlexander Leidinger emu_wrptr(sc, 0, A_SPDIF_SAMPLERATE, A_SPDIF_48000); 2368d056fa04SAlexander Leidinger 2369d056fa04SAlexander Leidinger /* 2370d056fa04SAlexander Leidinger * CAxxxx cards needs additional setup: 2371d056fa04SAlexander Leidinger * 1. Set I2S capture sample rate to 96000 2372d056fa04SAlexander Leidinger * 2. Disable P16v / P17v proceesing 2373d056fa04SAlexander Leidinger * 3. Allow EMU10K DSP inputs 2374d056fa04SAlexander Leidinger */ 2375d056fa04SAlexander Leidinger if ((sc->is_ca0102) || (sc->is_ca0108)) { 2376d056fa04SAlexander Leidinger 2377d056fa04SAlexander Leidinger spdif_sr = emu_rdptr(sc, 0, A_SPDIF_SAMPLERATE); 2378d056fa04SAlexander Leidinger spdif_sr &= 0xfffff1ff; 2379d056fa04SAlexander Leidinger spdif_sr |= A_I2S_CAPTURE_96000; 2380d056fa04SAlexander Leidinger emu_wrptr(sc, 0, A_SPDIF_SAMPLERATE, spdif_sr); 2381d056fa04SAlexander Leidinger 2382d056fa04SAlexander Leidinger /* Disable P16v processing */ 2383d056fa04SAlexander Leidinger emu_wr_p16vptr(sc, 0, SRCSel, 0x14); 2384d056fa04SAlexander Leidinger 2385d056fa04SAlexander Leidinger /* Setup P16v/P17v sound routing */ 2386d056fa04SAlexander Leidinger if (sc->is_ca0102) 2387d056fa04SAlexander Leidinger emu_wr_p16vptr(sc, 0, SRCMULTI_ENABLE, 0xFF00FF00); 2388d056fa04SAlexander Leidinger else { 2389d056fa04SAlexander Leidinger emu_wr_p16vptr(sc, 0, P17V_MIXER_I2S_ENABLE, 0xFF000000); 2390d056fa04SAlexander Leidinger emu_wr_p16vptr(sc, 0, P17V_MIXER_SPDIF_ENABLE, 0xFF000000); 2391d056fa04SAlexander Leidinger 2392d056fa04SAlexander Leidinger tmp = emu_rd(sc, A_IOCFG, 2); 2393d056fa04SAlexander Leidinger emu_wr(sc, A_IOCFG, tmp & ~0x8, 2); 2394d056fa04SAlexander Leidinger } 2395d056fa04SAlexander Leidinger } 2396d056fa04SAlexander Leidinger emu_initefx(sc); 2397d056fa04SAlexander Leidinger 2398d056fa04SAlexander Leidinger def_mode = MODE_ANALOG; 2399d056fa04SAlexander Leidinger if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) 2400d056fa04SAlexander Leidinger def_mode = MODE_DIGITAL; 2401d056fa04SAlexander Leidinger if (((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) && (sc->broken_digital)) { 2402d056fa04SAlexander Leidinger device_printf(sc->dev, "Audigy card initialized in analog mode.\n"); 2403d056fa04SAlexander Leidinger def_mode = MODE_ANALOG; 2404d056fa04SAlexander Leidinger } 2405d056fa04SAlexander Leidinger emumix_set_mode(sc, def_mode); 2406d056fa04SAlexander Leidinger 2407d056fa04SAlexander Leidinger if (bootverbose) { 2408d056fa04SAlexander Leidinger tmp = emu_rd(sc, HCFG, 4); 2409d056fa04SAlexander Leidinger device_printf(sc->dev, "Card Configuration ( 0x%08x )\n", tmp); 2410d056fa04SAlexander Leidinger device_printf(sc->dev, "Card Configuration ( & 0xff000000 ) : %s%s%s%s%s%s%s%s\n", 2411d056fa04SAlexander Leidinger (tmp & 0x80000000 ? "[Legacy MPIC] " : ""), 2412d056fa04SAlexander Leidinger (tmp & 0x40000000 ? "[0x40] " : ""), 2413d056fa04SAlexander Leidinger (tmp & 0x20000000 ? "[0x20] " : ""), 2414d056fa04SAlexander Leidinger (tmp & 0x10000000 ? "[0x10] " : ""), 2415d056fa04SAlexander Leidinger (tmp & 0x08000000 ? "[0x08] " : ""), 2416d056fa04SAlexander Leidinger (tmp & 0x04000000 ? "[0x04] " : ""), 2417d056fa04SAlexander Leidinger (tmp & 0x02000000 ? "[0x02] " : ""), 2418d056fa04SAlexander Leidinger (tmp & 0x01000000 ? "[0x01]" : " ")); 2419d056fa04SAlexander Leidinger device_printf(sc->dev, "Card Configuration ( & 0x00ff0000 ) : %s%s%s%s%s%s%s%s\n", 2420d056fa04SAlexander Leidinger (tmp & 0x00800000 ? "[0x80] " : ""), 2421d056fa04SAlexander Leidinger (tmp & 0x00400000 ? "[0x40] " : ""), 2422d056fa04SAlexander Leidinger (tmp & 0x00200000 ? "[Legacy INT] " : ""), 2423d056fa04SAlexander Leidinger (tmp & 0x00100000 ? "[0x10] " : ""), 2424d056fa04SAlexander Leidinger (tmp & 0x00080000 ? "[0x08] " : ""), 2425d056fa04SAlexander Leidinger (tmp & 0x00040000 ? "[Codec4] " : ""), 2426d056fa04SAlexander Leidinger (tmp & 0x00020000 ? "[Codec2] " : ""), 2427d056fa04SAlexander Leidinger (tmp & 0x00010000 ? "[I2S Codec]" : " ")); 2428d056fa04SAlexander Leidinger device_printf(sc->dev, "Card Configuration ( & 0x0000ff00 ) : %s%s%s%s%s%s%s%s\n", 2429d056fa04SAlexander Leidinger (tmp & 0x00008000 ? "[0x80] " : ""), 2430d056fa04SAlexander Leidinger (tmp & 0x00004000 ? "[GPINPUT0] " : ""), 2431d056fa04SAlexander Leidinger (tmp & 0x00002000 ? "[GPINPUT1] " : ""), 2432d056fa04SAlexander Leidinger (tmp & 0x00001000 ? "[GPOUT0] " : ""), 2433d056fa04SAlexander Leidinger (tmp & 0x00000800 ? "[GPOUT1] " : ""), 2434d056fa04SAlexander Leidinger (tmp & 0x00000400 ? "[GPOUT2] " : ""), 2435d056fa04SAlexander Leidinger (tmp & 0x00000200 ? "[Joystick] " : ""), 2436d056fa04SAlexander Leidinger (tmp & 0x00000100 ? "[0x01]" : " ")); 2437d056fa04SAlexander Leidinger device_printf(sc->dev, "Card Configuration ( & 0x000000ff ) : %s%s%s%s%s%s%s%s\n", 2438d056fa04SAlexander Leidinger (tmp & 0x00000080 ? "[0x80] " : ""), 2439d056fa04SAlexander Leidinger (tmp & 0x00000040 ? "[0x40] " : ""), 2440d056fa04SAlexander Leidinger (tmp & 0x00000020 ? "[0x20] " : ""), 2441d056fa04SAlexander Leidinger (tmp & 0x00000010 ? "[AUTOMUTE] " : ""), 2442d056fa04SAlexander Leidinger (tmp & 0x00000008 ? "[LOCKSOUNDCACHE] " : ""), 2443d056fa04SAlexander Leidinger (tmp & 0x00000004 ? "[LOCKTANKCACHE] " : ""), 2444d056fa04SAlexander Leidinger (tmp & 0x00000002 ? "[MUTEBUTTONENABLE] " : ""), 2445d056fa04SAlexander Leidinger (tmp & 0x00000001 ? "[AUDIOENABLE]" : " ")); 2446d056fa04SAlexander Leidinger 2447d056fa04SAlexander Leidinger if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) { 2448d056fa04SAlexander Leidinger tmp = emu_rd(sc, A_IOCFG, 2); 2449d056fa04SAlexander Leidinger device_printf(sc->dev, "Audigy Card Configuration ( 0x%04x )\n", tmp); 2450d056fa04SAlexander Leidinger device_printf(sc->dev, "Audigy Card Configuration ( & 0xff00 )"); 2451d056fa04SAlexander Leidinger printf(" : %s%s%s%s%s%s%s%s\n", 2452d056fa04SAlexander Leidinger (tmp & 0x8000 ? "[Rear Speakers] " : ""), 2453d056fa04SAlexander Leidinger (tmp & 0x4000 ? "[Front Speakers] " : ""), 2454d056fa04SAlexander Leidinger (tmp & 0x2000 ? "[0x20] " : ""), 2455d056fa04SAlexander Leidinger (tmp & 0x1000 ? "[0x10] " : ""), 2456d056fa04SAlexander Leidinger (tmp & 0x0800 ? "[0x08] " : ""), 2457d056fa04SAlexander Leidinger (tmp & 0x0400 ? "[0x04] " : ""), 2458d056fa04SAlexander Leidinger (tmp & 0x0200 ? "[0x02] " : ""), 2459d056fa04SAlexander Leidinger (tmp & 0x0100 ? "[AudigyDrive Phones]" : " ")); 2460d056fa04SAlexander Leidinger device_printf(sc->dev, "Audigy Card Configuration ( & 0x00ff )"); 2461d056fa04SAlexander Leidinger printf(" : %s%s%s%s%s%s%s%s\n", 2462d056fa04SAlexander Leidinger (tmp & 0x0080 ? "[0x80] " : ""), 2463d056fa04SAlexander Leidinger (tmp & 0x0040 ? "[Mute AnalogOut] " : ""), 2464d056fa04SAlexander Leidinger (tmp & 0x0020 ? "[0x20] " : ""), 2465d056fa04SAlexander Leidinger (tmp & 0x0010 ? "[0x10] " : ""), 2466d056fa04SAlexander Leidinger (tmp & 0x0008 ? "[0x08] " : ""), 2467d056fa04SAlexander Leidinger (tmp & 0x0004 ? "[GPOUT0] " : ""), 2468d056fa04SAlexander Leidinger (tmp & 0x0002 ? "[GPOUT1] " : ""), 2469d056fa04SAlexander Leidinger (tmp & 0x0001 ? "[GPOUT2]" : " ")); 2470d056fa04SAlexander Leidinger } /* is_emu10k2 or ca* */ 2471d056fa04SAlexander Leidinger } /* bootverbose */ 2472d056fa04SAlexander Leidinger return (0); 2473d056fa04SAlexander Leidinger } 2474d056fa04SAlexander Leidinger 2475d056fa04SAlexander Leidinger static int 2476d056fa04SAlexander Leidinger emu_uninit(struct emu_sc_info *sc) 2477d056fa04SAlexander Leidinger { 2478d056fa04SAlexander Leidinger uint32_t ch; 2479d056fa04SAlexander Leidinger struct emu_memblk *blk; 2480d056fa04SAlexander Leidinger 2481d056fa04SAlexander Leidinger emu_wr(sc, INTE, 0, 4); 2482d056fa04SAlexander Leidinger for (ch = 0; ch < NUM_G; ch++) 2483d056fa04SAlexander Leidinger emu_wrptr(sc, ch, DCYSUSV, 0); 2484d056fa04SAlexander Leidinger for (ch = 0; ch < NUM_G; ch++) { 2485d056fa04SAlexander Leidinger emu_wrptr(sc, ch, VTFT, 0); 2486d056fa04SAlexander Leidinger emu_wrptr(sc, ch, CVCF, 0); 2487d056fa04SAlexander Leidinger emu_wrptr(sc, ch, PTRX, 0); 2488d056fa04SAlexander Leidinger emu_wrptr(sc, ch, CPF, 0); 2489d056fa04SAlexander Leidinger } 2490d056fa04SAlexander Leidinger 2491d056fa04SAlexander Leidinger /* disable audio and lock cache */ 2492d056fa04SAlexander Leidinger emu_wr(sc, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, 4); 2493d056fa04SAlexander Leidinger 2494d056fa04SAlexander Leidinger emu_wrptr(sc, 0, PTB, 0); 2495d056fa04SAlexander Leidinger /* reset recording buffers */ 2496d056fa04SAlexander Leidinger emu_wrptr(sc, 0, MICBS, ADCBS_BUFSIZE_NONE); 2497d056fa04SAlexander Leidinger emu_wrptr(sc, 0, MICBA, 0); 2498d056fa04SAlexander Leidinger emu_wrptr(sc, 0, FXBS, ADCBS_BUFSIZE_NONE); 2499d056fa04SAlexander Leidinger emu_wrptr(sc, 0, FXBA, 0); 2500d056fa04SAlexander Leidinger emu_wrptr(sc, 0, FXWC, 0); 2501d056fa04SAlexander Leidinger emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE); 2502d056fa04SAlexander Leidinger emu_wrptr(sc, 0, ADCBA, 0); 2503d056fa04SAlexander Leidinger emu_wrptr(sc, 0, TCB, 0); 2504d056fa04SAlexander Leidinger emu_wrptr(sc, 0, TCBS, 0); 2505d056fa04SAlexander Leidinger 2506d056fa04SAlexander Leidinger /* disable channel interrupt */ 2507d056fa04SAlexander Leidinger emu_wrptr(sc, 0, CLIEL, 0); 2508d056fa04SAlexander Leidinger emu_wrptr(sc, 0, CLIEH, 0); 2509d056fa04SAlexander Leidinger emu_wrptr(sc, 0, SOLEL, 0); 2510d056fa04SAlexander Leidinger emu_wrptr(sc, 0, SOLEH, 0); 2511d056fa04SAlexander Leidinger 2512d056fa04SAlexander Leidinger if (sc->mem.dmat) 2513d056fa04SAlexander Leidinger bus_dma_tag_destroy(sc->mem.dmat); 2514d056fa04SAlexander Leidinger 2515d056fa04SAlexander Leidinger if (!SLIST_EMPTY(&sc->mem.blocks)) 2516d056fa04SAlexander Leidinger device_printf(sc->dev, "warning: memblock list not empty\n"); 2517d056fa04SAlexander Leidinger 2518d056fa04SAlexander Leidinger SLIST_FOREACH(blk, &sc->mem.blocks, link) 2519d056fa04SAlexander Leidinger if (blk != NULL) 2520d056fa04SAlexander Leidinger device_printf(sc->dev, "lost %d for %s\n", blk->pte_size, blk->owner); 2521d056fa04SAlexander Leidinger 2522d056fa04SAlexander Leidinger emu_free(&sc->mem, sc->mem.ptb_pages); 2523d056fa04SAlexander Leidinger emu_free(&sc->mem, sc->mem.silent_page); 2524d056fa04SAlexander Leidinger 2525d056fa04SAlexander Leidinger return (0); 2526d056fa04SAlexander Leidinger } 2527d056fa04SAlexander Leidinger 2528d056fa04SAlexander Leidinger static int 2529d056fa04SAlexander Leidinger emu_read_ivar(device_t bus, device_t dev, int ivar_index, uintptr_t * result) 2530d056fa04SAlexander Leidinger { 2531d056fa04SAlexander Leidinger struct sndcard_func *func = device_get_ivars(dev); 2532d056fa04SAlexander Leidinger struct emu_sc_info *sc = device_get_softc(bus); 2533d056fa04SAlexander Leidinger 2534d056fa04SAlexander Leidinger switch (ivar_index) { 2535d056fa04SAlexander Leidinger case EMU_VAR_FUNC: 2536d056fa04SAlexander Leidinger *result = func->func; 2537d056fa04SAlexander Leidinger break; 2538d056fa04SAlexander Leidinger case EMU_VAR_ROUTE: 2539d056fa04SAlexander Leidinger *result = ((struct emu_pcminfo *)func->varinfo)->route; 2540d056fa04SAlexander Leidinger break; 2541d056fa04SAlexander Leidinger case EMU_VAR_ISEMU10K1: 2542d056fa04SAlexander Leidinger *result = sc->is_emu10k1; 2543d056fa04SAlexander Leidinger break; 2544d056fa04SAlexander Leidinger default: 2545d056fa04SAlexander Leidinger return (ENOENT); 2546d056fa04SAlexander Leidinger } 2547d056fa04SAlexander Leidinger 2548d056fa04SAlexander Leidinger return (0); 2549d056fa04SAlexander Leidinger } 2550d056fa04SAlexander Leidinger 2551d056fa04SAlexander Leidinger static int 2552d056fa04SAlexander Leidinger emu_write_ivar(device_t bus __unused, device_t dev __unused, 2553d056fa04SAlexander Leidinger int ivar_index, uintptr_t value __unused) 2554d056fa04SAlexander Leidinger { 2555d056fa04SAlexander Leidinger 2556d056fa04SAlexander Leidinger switch (ivar_index) { 2557d056fa04SAlexander Leidinger case 0: 2558d056fa04SAlexander Leidinger return (EINVAL); 2559d056fa04SAlexander Leidinger 2560d056fa04SAlexander Leidinger default: 2561d056fa04SAlexander Leidinger return (ENOENT); 2562d056fa04SAlexander Leidinger } 2563d056fa04SAlexander Leidinger } 2564d056fa04SAlexander Leidinger 2565d056fa04SAlexander Leidinger static int 2566d056fa04SAlexander Leidinger emu_pci_probe(device_t dev) 2567d056fa04SAlexander Leidinger { 2568d056fa04SAlexander Leidinger struct sbuf *s; 2569d056fa04SAlexander Leidinger int thiscard = 0; 2570d056fa04SAlexander Leidinger uint16_t vendor; 2571d056fa04SAlexander Leidinger 2572d056fa04SAlexander Leidinger vendor = pci_read_config(dev, PCIR_DEVVENDOR, /* bytes */ 2); 2573d056fa04SAlexander Leidinger if (vendor != 0x1102) 2574d056fa04SAlexander Leidinger return (ENXIO); /* Not Creative */ 2575d056fa04SAlexander Leidinger 2576d056fa04SAlexander Leidinger thiscard = emu_getcard(dev); 2577d056fa04SAlexander Leidinger if (thiscard < 0) 2578d056fa04SAlexander Leidinger return (ENXIO); 2579d056fa04SAlexander Leidinger 2580d056fa04SAlexander Leidinger s = sbuf_new(NULL, NULL, 4096, 0); 2581d056fa04SAlexander Leidinger if (s == NULL) 2582d056fa04SAlexander Leidinger return (ENOMEM); 2583d056fa04SAlexander Leidinger sbuf_printf(s, "Creative %s [%s]", emu_cards[thiscard].desc, emu_cards[thiscard].SBcode); 2584d056fa04SAlexander Leidinger sbuf_finish(s); 2585d056fa04SAlexander Leidinger 2586d056fa04SAlexander Leidinger device_set_desc_copy(dev, sbuf_data(s)); 2587d056fa04SAlexander Leidinger return (BUS_PROBE_DEFAULT); 2588d056fa04SAlexander Leidinger } 2589d056fa04SAlexander Leidinger 2590d056fa04SAlexander Leidinger 2591d056fa04SAlexander Leidinger static int 2592d056fa04SAlexander Leidinger emu_pci_attach(device_t dev) 2593d056fa04SAlexander Leidinger { 2594d056fa04SAlexander Leidinger struct sndcard_func *func; 2595d056fa04SAlexander Leidinger struct emu_sc_info *sc; 2596d056fa04SAlexander Leidinger struct emu_pcminfo *pcminfo; 2597d056fa04SAlexander Leidinger struct emu_midiinfo *midiinfo[3]; 2598d056fa04SAlexander Leidinger uint32_t data; 2599d056fa04SAlexander Leidinger int i; 2600d056fa04SAlexander Leidinger int device_flags; 2601d056fa04SAlexander Leidinger char status[255]; 2602d056fa04SAlexander Leidinger int error = ENXIO; 2603d056fa04SAlexander Leidinger 2604d056fa04SAlexander Leidinger sc = device_get_softc(dev); 2605d056fa04SAlexander Leidinger 2606d056fa04SAlexander Leidinger /* Fill in the softc. */ 2607d056fa04SAlexander Leidinger mtx_init(&sc->lock, "emu10kx", "bridge conf", MTX_DEF); 2608d056fa04SAlexander Leidinger mtx_init(&sc->rw, "emu10kx", "atomic op", MTX_DEF); 2609d056fa04SAlexander Leidinger sc->dev = dev; 2610d056fa04SAlexander Leidinger sc->type = pci_get_devid(dev); 2611d056fa04SAlexander Leidinger sc->rev = pci_get_revid(dev); 2612d056fa04SAlexander Leidinger sc->enable_ir = 0; 2613d056fa04SAlexander Leidinger sc->enable_debug = 0; 2614d056fa04SAlexander Leidinger sc->has_ac97 = 0; 2615d056fa04SAlexander Leidinger sc->has_51 = 0; 2616d056fa04SAlexander Leidinger sc->has_71 = 0; 2617d056fa04SAlexander Leidinger sc->broken_digital = 0; 2618d056fa04SAlexander Leidinger sc->is_emu10k1 = 0; 2619d056fa04SAlexander Leidinger sc->is_emu10k2 = 0; 2620d056fa04SAlexander Leidinger sc->is_ca0102 = 0; 2621d056fa04SAlexander Leidinger sc->is_ca0108 = 0; 2622d056fa04SAlexander Leidinger sc->is_cardbus = 0; 2623d056fa04SAlexander Leidinger 2624d056fa04SAlexander Leidinger device_flags = emu_cards[emu_getcard(dev)].flags; 2625d056fa04SAlexander Leidinger if (device_flags & HAS_51) 2626d056fa04SAlexander Leidinger sc->has_51 = 1; 2627d056fa04SAlexander Leidinger if (device_flags & HAS_71) { 2628d056fa04SAlexander Leidinger sc->has_51 = 1; 2629d056fa04SAlexander Leidinger sc->has_71 = 1; 2630d056fa04SAlexander Leidinger } 2631d056fa04SAlexander Leidinger if (device_flags & IS_EMU10K1) 2632d056fa04SAlexander Leidinger sc->is_emu10k1 = 1; 2633d056fa04SAlexander Leidinger if (device_flags & IS_EMU10K2) 2634d056fa04SAlexander Leidinger sc->is_emu10k2 = 1; 2635d056fa04SAlexander Leidinger if (device_flags & IS_CA0102) 2636d056fa04SAlexander Leidinger sc->is_ca0102 = 1; 2637d056fa04SAlexander Leidinger if (device_flags & IS_CA0108) 2638d056fa04SAlexander Leidinger sc->is_ca0108 = 1; 2639d056fa04SAlexander Leidinger if ((sc->is_emu10k2) && (sc->rev == 4)) { 2640d056fa04SAlexander Leidinger sc->is_emu10k2 = 0; 2641d056fa04SAlexander Leidinger sc->is_ca0102 = 1; /* for unknown Audigy 2 cards */ 2642d056fa04SAlexander Leidinger } 2643d056fa04SAlexander Leidinger if ((sc->is_ca0102 == 1) || (sc->is_ca0108 == 1)) 2644d056fa04SAlexander Leidinger if (device_flags & IS_CARDBUS) 2645d056fa04SAlexander Leidinger sc->is_cardbus = 1; 2646d056fa04SAlexander Leidinger 2647d056fa04SAlexander Leidinger if ((sc->is_emu10k1 + sc->is_emu10k2 + sc->is_ca0102 + sc->is_ca0108) != 1) { 2648d056fa04SAlexander Leidinger device_printf(sc->dev, "Unable to detect HW chipset\n"); 2649d056fa04SAlexander Leidinger goto bad; 2650d056fa04SAlexander Leidinger } 2651d056fa04SAlexander Leidinger if (device_flags & BROKEN_DIGITAL) 2652d056fa04SAlexander Leidinger sc->broken_digital = 1; 2653d056fa04SAlexander Leidinger if (device_flags & HAS_AC97) 2654d056fa04SAlexander Leidinger sc->has_ac97 = 1; 2655d056fa04SAlexander Leidinger 2656d056fa04SAlexander Leidinger sc->opcode_shift = 0; 2657d056fa04SAlexander Leidinger if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) { 2658d056fa04SAlexander Leidinger sc->opcode_shift = 24; 2659d056fa04SAlexander Leidinger sc->high_operand_shift = 12; 2660d056fa04SAlexander Leidinger sc->code_base = A_MICROCODEBASE; 2661d056fa04SAlexander Leidinger sc->code_size = 0x800 / 2; /* 0x600-0xdff, 2048 words, 2662d056fa04SAlexander Leidinger * 1024 instructions */ 2663d056fa04SAlexander Leidinger sc->gpr_base = A_FXGPREGBASE; 2664d056fa04SAlexander Leidinger sc->num_gprs = 0x200; 2665d056fa04SAlexander Leidinger sc->input_base = 0x40; 2666d056fa04SAlexander Leidinger /* sc->p16vinput_base = 0x50; */ 2667d056fa04SAlexander Leidinger sc->output_base = 0x60; 2668d056fa04SAlexander Leidinger sc->efxc_base = 0x80; 2669d056fa04SAlexander Leidinger /* sc->output32h_base = 0xa0; */ 2670d056fa04SAlexander Leidinger /* sc->output32l_base = 0xb0; */ 2671d056fa04SAlexander Leidinger sc->dsp_zero = 0xc0; 2672d056fa04SAlexander Leidinger sc->mchannel_fx = 8; 2673d056fa04SAlexander Leidinger sc->num_fxbuses = 16; 2674d056fa04SAlexander Leidinger sc->num_inputs = 8; 2675d056fa04SAlexander Leidinger sc->num_outputs = 16; 2676d056fa04SAlexander Leidinger sc->address_mask = A_PTR_ADDRESS_MASK; 2677d056fa04SAlexander Leidinger } 2678d056fa04SAlexander Leidinger if (sc->is_emu10k1) { 2679d056fa04SAlexander Leidinger sc->has_51 = 0; /* We don't support 5.1 sound Live! 5.1 */ 2680d056fa04SAlexander Leidinger sc->opcode_shift = 20; 2681d056fa04SAlexander Leidinger sc->high_operand_shift = 10; 2682d056fa04SAlexander Leidinger sc->code_base = MICROCODEBASE; 2683d056fa04SAlexander Leidinger sc->code_size = 0x400 / 2; /* 0x400-0x7ff, 1024 words, 2684d056fa04SAlexander Leidinger * 512 instructions */ 2685d056fa04SAlexander Leidinger sc->gpr_base = FXGPREGBASE; 2686d056fa04SAlexander Leidinger sc->num_gprs = 0x100; 2687d056fa04SAlexander Leidinger sc->input_base = 0x10; 2688d056fa04SAlexander Leidinger sc->output_base = 0x20; 2689d056fa04SAlexander Leidinger sc->efxc_base = 0x30; 2690d056fa04SAlexander Leidinger sc->dsp_zero = 0x40; 2691d056fa04SAlexander Leidinger sc->mchannel_fx = 0; 2692d056fa04SAlexander Leidinger sc->num_fxbuses = 8; 2693d056fa04SAlexander Leidinger sc->num_inputs = 8; 2694d056fa04SAlexander Leidinger sc->num_outputs = 16; 2695d056fa04SAlexander Leidinger sc->address_mask = PTR_ADDRESS_MASK; 2696d056fa04SAlexander Leidinger } 2697d056fa04SAlexander Leidinger if (sc->opcode_shift == 0) 2698d056fa04SAlexander Leidinger goto bad; 2699d056fa04SAlexander Leidinger 2700d056fa04SAlexander Leidinger data = pci_read_config(dev, PCIR_COMMAND, 2); 2701d056fa04SAlexander Leidinger data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN); 2702d056fa04SAlexander Leidinger pci_write_config(dev, PCIR_COMMAND, data, 2); 2703d056fa04SAlexander Leidinger data = pci_read_config(dev, PCIR_COMMAND, 2); 2704d056fa04SAlexander Leidinger 2705d056fa04SAlexander Leidinger pci_enable_busmaster(dev); 2706d056fa04SAlexander Leidinger 2707d056fa04SAlexander Leidinger i = PCIR_BAR(0); 2708d056fa04SAlexander Leidinger sc->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &i, RF_ACTIVE); 2709d056fa04SAlexander Leidinger if (sc->reg == NULL) { 2710d056fa04SAlexander Leidinger device_printf(dev, "unable to map register space\n"); 2711d056fa04SAlexander Leidinger goto bad; 2712d056fa04SAlexander Leidinger } 2713d056fa04SAlexander Leidinger sc->st = rman_get_bustag(sc->reg); 2714d056fa04SAlexander Leidinger sc->sh = rman_get_bushandle(sc->reg); 2715d056fa04SAlexander Leidinger 2716d056fa04SAlexander Leidinger for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) 2717d056fa04SAlexander Leidinger sc->timer[i] = 0; /* disable it */ 2718d056fa04SAlexander Leidinger 2719d056fa04SAlexander Leidinger i = 0; 2720d056fa04SAlexander Leidinger sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE | RF_SHAREABLE); 2721d056fa04SAlexander Leidinger if ((sc->irq == NULL) || bus_setup_intr(dev, sc->irq, INTR_MPSAFE | INTR_TYPE_AV, emu_intr, sc, &sc->ih)) { 2722d056fa04SAlexander Leidinger device_printf(dev, "unable to map interrupt\n"); 2723d056fa04SAlexander Leidinger goto bad; 2724d056fa04SAlexander Leidinger } 2725d056fa04SAlexander Leidinger if (emu_rm_init(sc) != 0) { 2726d056fa04SAlexander Leidinger device_printf(dev, "unable to create resource manager\n"); 2727d056fa04SAlexander Leidinger goto bad; 2728d056fa04SAlexander Leidinger } 2729d056fa04SAlexander Leidinger if (sc->is_cardbus) 2730d056fa04SAlexander Leidinger if (emu_cardbus_init(sc) != 0) { 2731d056fa04SAlexander Leidinger device_printf(dev, "unable to initialize CardBus interface\n"); 2732d056fa04SAlexander Leidinger goto bad; 2733d056fa04SAlexander Leidinger } 2734d056fa04SAlexander Leidinger sc->ctx = device_get_sysctl_ctx(dev); 2735d056fa04SAlexander Leidinger if (sc->ctx == NULL) 2736d056fa04SAlexander Leidinger goto bad; 2737d056fa04SAlexander Leidinger sc->root = device_get_sysctl_tree(dev); 2738d056fa04SAlexander Leidinger if (sc->root == NULL) 2739d056fa04SAlexander Leidinger goto bad; 2740d056fa04SAlexander Leidinger if (emu_init(sc) == -1) { 2741d056fa04SAlexander Leidinger device_printf(dev, "unable to initialize the card\n"); 2742d056fa04SAlexander Leidinger goto bad; 2743d056fa04SAlexander Leidinger } 2744d056fa04SAlexander Leidinger if (emu10kx_dev_init(sc) == ENXIO) { 2745d056fa04SAlexander Leidinger device_printf(dev, "unable to create control device\n"); 2746d056fa04SAlexander Leidinger goto bad; 2747d056fa04SAlexander Leidinger } 2748d056fa04SAlexander Leidinger snprintf(status, 255, "rev %d at io 0x%lx irq %ld", sc->rev, rman_get_start(sc->reg), rman_get_start(sc->irq)); 2749d056fa04SAlexander Leidinger 2750d056fa04SAlexander Leidinger /* Voices */ 2751d056fa04SAlexander Leidinger for (i = 0; i < NUM_G; i++) { 2752d056fa04SAlexander Leidinger sc->voice[i].vnum = i; 2753d056fa04SAlexander Leidinger sc->voice[i].slave = NULL; 2754d056fa04SAlexander Leidinger sc->voice[i].busy = 0; 2755d056fa04SAlexander Leidinger sc->voice[i].ismaster = 0; 2756d056fa04SAlexander Leidinger sc->voice[i].running = 0; 2757d056fa04SAlexander Leidinger sc->voice[i].b16 = 0; 2758d056fa04SAlexander Leidinger sc->voice[i].stereo = 0; 2759d056fa04SAlexander Leidinger sc->voice[i].speed = 0; 2760d056fa04SAlexander Leidinger sc->voice[i].start = 0; 2761d056fa04SAlexander Leidinger sc->voice[i].end = 0; 2762d056fa04SAlexander Leidinger } 2763d056fa04SAlexander Leidinger 2764d056fa04SAlexander Leidinger /* PCM Audio */ 2765d056fa04SAlexander Leidinger /* FRONT */ 2766d056fa04SAlexander Leidinger func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 2767d056fa04SAlexander Leidinger if (func == NULL) { 2768d056fa04SAlexander Leidinger error = ENOMEM; 2769d056fa04SAlexander Leidinger goto bad; 2770d056fa04SAlexander Leidinger } 2771d056fa04SAlexander Leidinger pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 2772d056fa04SAlexander Leidinger if (pcminfo == NULL) { 2773d056fa04SAlexander Leidinger error = ENOMEM; 2774d056fa04SAlexander Leidinger goto bad; 2775d056fa04SAlexander Leidinger } 2776d056fa04SAlexander Leidinger pcminfo->card = sc; 2777d056fa04SAlexander Leidinger pcminfo->route = RT_FRONT; 2778d056fa04SAlexander Leidinger 2779d056fa04SAlexander Leidinger func->func = SCF_PCM; 2780d056fa04SAlexander Leidinger func->varinfo = pcminfo; 2781d056fa04SAlexander Leidinger sc->pcm[RT_FRONT] = device_add_child(dev, "pcm", -1); 2782d056fa04SAlexander Leidinger device_set_ivars(sc->pcm[RT_FRONT], func); 2783d056fa04SAlexander Leidinger /* REAR */ 2784d056fa04SAlexander Leidinger func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 2785d056fa04SAlexander Leidinger if (func == NULL) { 2786d056fa04SAlexander Leidinger error = ENOMEM; 2787d056fa04SAlexander Leidinger goto bad; 2788d056fa04SAlexander Leidinger } 2789d056fa04SAlexander Leidinger pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 2790d056fa04SAlexander Leidinger if (pcminfo == NULL) { 2791d056fa04SAlexander Leidinger error = ENOMEM; 2792d056fa04SAlexander Leidinger goto bad; 2793d056fa04SAlexander Leidinger } 2794d056fa04SAlexander Leidinger #ifdef SND_EMU10KX_MULTICHANNEL 2795d056fa04SAlexander Leidinger pcminfo->card = sc; 2796d056fa04SAlexander Leidinger pcminfo->route = RT_REAR; 2797d056fa04SAlexander Leidinger 2798d056fa04SAlexander Leidinger func->func = SCF_PCM; 2799d056fa04SAlexander Leidinger func->varinfo = pcminfo; 2800d056fa04SAlexander Leidinger sc->pcm[RT_REAR] = device_add_child(dev, "pcm", -1); 2801d056fa04SAlexander Leidinger device_set_ivars(sc->pcm[RT_REAR], func); 2802d056fa04SAlexander Leidinger if (sc->has_51) { 2803d056fa04SAlexander Leidinger /* CENTER */ 2804d056fa04SAlexander Leidinger func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 2805d056fa04SAlexander Leidinger if (func == NULL) { 2806d056fa04SAlexander Leidinger error = ENOMEM; 2807d056fa04SAlexander Leidinger goto bad; 2808d056fa04SAlexander Leidinger } 2809d056fa04SAlexander Leidinger pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 2810d056fa04SAlexander Leidinger if (pcminfo == NULL) { 2811d056fa04SAlexander Leidinger error = ENOMEM; 2812d056fa04SAlexander Leidinger goto bad; 2813d056fa04SAlexander Leidinger } 2814d056fa04SAlexander Leidinger pcminfo->card = sc; 2815d056fa04SAlexander Leidinger pcminfo->route = RT_CENTER; 2816d056fa04SAlexander Leidinger 2817d056fa04SAlexander Leidinger func->func = SCF_PCM; 2818d056fa04SAlexander Leidinger func->varinfo = pcminfo; 2819d056fa04SAlexander Leidinger sc->pcm[RT_CENTER] = device_add_child(dev, "pcm", -1); 2820d056fa04SAlexander Leidinger device_set_ivars(sc->pcm[RT_CENTER], func); 2821d056fa04SAlexander Leidinger /* SUB */ 2822d056fa04SAlexander Leidinger func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 2823d056fa04SAlexander Leidinger if (func == NULL) { 2824d056fa04SAlexander Leidinger error = ENOMEM; 2825d056fa04SAlexander Leidinger goto bad; 2826d056fa04SAlexander Leidinger } 2827d056fa04SAlexander Leidinger pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 2828d056fa04SAlexander Leidinger if (pcminfo == NULL) { 2829d056fa04SAlexander Leidinger error = ENOMEM; 2830d056fa04SAlexander Leidinger goto bad; 2831d056fa04SAlexander Leidinger } 2832d056fa04SAlexander Leidinger pcminfo->card = sc; 2833d056fa04SAlexander Leidinger pcminfo->route = RT_SUB; 2834d056fa04SAlexander Leidinger 2835d056fa04SAlexander Leidinger func->func = SCF_PCM; 2836d056fa04SAlexander Leidinger func->varinfo = pcminfo; 2837d056fa04SAlexander Leidinger sc->pcm[RT_SUB] = device_add_child(dev, "pcm", -1); 2838d056fa04SAlexander Leidinger device_set_ivars(sc->pcm[RT_SUB], func); 2839d056fa04SAlexander Leidinger } 2840d056fa04SAlexander Leidinger if (sc->has_71) { 2841d056fa04SAlexander Leidinger /* SIDE */ 2842d056fa04SAlexander Leidinger func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 2843d056fa04SAlexander Leidinger if (func == NULL) { 2844d056fa04SAlexander Leidinger error = ENOMEM; 2845d056fa04SAlexander Leidinger goto bad; 2846d056fa04SAlexander Leidinger } 2847d056fa04SAlexander Leidinger pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 2848d056fa04SAlexander Leidinger if (pcminfo == NULL) { 2849d056fa04SAlexander Leidinger error = ENOMEM; 2850d056fa04SAlexander Leidinger goto bad; 2851d056fa04SAlexander Leidinger } 2852d056fa04SAlexander Leidinger pcminfo->card = sc; 2853d056fa04SAlexander Leidinger pcminfo->route = RT_SIDE; 2854d056fa04SAlexander Leidinger 2855d056fa04SAlexander Leidinger func->func = SCF_PCM; 2856d056fa04SAlexander Leidinger func->varinfo = pcminfo; 2857d056fa04SAlexander Leidinger sc->pcm[RT_SIDE] = device_add_child(dev, "pcm", -1); 2858d056fa04SAlexander Leidinger device_set_ivars(sc->pcm[RT_SIDE], func); 2859d056fa04SAlexander Leidinger }; 2860d056fa04SAlexander Leidinger #endif /* SND_EMU10KX_MULTICHANNEL */ 2861d056fa04SAlexander Leidinger 2862d056fa04SAlexander Leidinger /* Midi Interface 1: Live!, Audigy, Audigy 2 */ 2863d056fa04SAlexander Leidinger if ((sc->is_emu10k1) || (sc->is_emu10k2) || (sc->is_ca0102)) { 2864d056fa04SAlexander Leidinger func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 2865d056fa04SAlexander Leidinger if (func == NULL) { 2866d056fa04SAlexander Leidinger error = ENOMEM; 2867d056fa04SAlexander Leidinger goto bad; 2868d056fa04SAlexander Leidinger } 2869d056fa04SAlexander Leidinger midiinfo[0] = malloc(sizeof(struct emu_midiinfo), M_DEVBUF, M_NOWAIT | M_ZERO); 2870d056fa04SAlexander Leidinger if (midiinfo[0] == NULL) { 2871d056fa04SAlexander Leidinger error = ENOMEM; 2872d056fa04SAlexander Leidinger goto bad; 2873d056fa04SAlexander Leidinger } 2874d056fa04SAlexander Leidinger midiinfo[0]->card = sc; 2875d056fa04SAlexander Leidinger if (sc->is_emu10k2 || (sc->is_ca0102)) { 2876d056fa04SAlexander Leidinger midiinfo[0]->port = A_MUDATA1; 2877d056fa04SAlexander Leidinger midiinfo[0]->portnr = 1; 2878d056fa04SAlexander Leidinger } 2879d056fa04SAlexander Leidinger if (sc->is_emu10k1) { 2880d056fa04SAlexander Leidinger midiinfo[0]->port = MUDATA; 2881d056fa04SAlexander Leidinger midiinfo[0]->portnr = 1; 2882d056fa04SAlexander Leidinger } 2883d056fa04SAlexander Leidinger func->func = SCF_MIDI; 2884d056fa04SAlexander Leidinger func->varinfo = midiinfo[0]; 2885d056fa04SAlexander Leidinger sc->midi[0] = device_add_child(dev, "midi", -1); 2886d056fa04SAlexander Leidinger device_set_ivars(sc->midi[0], func); 2887d056fa04SAlexander Leidinger } 2888d056fa04SAlexander Leidinger /* Midi Interface 2: Audigy, Audigy 2 (on AudigyDrive) */ 2889d056fa04SAlexander Leidinger if (sc->is_emu10k2 || (sc->is_ca0102)) { 2890d056fa04SAlexander Leidinger func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 2891d056fa04SAlexander Leidinger if (func == NULL) { 2892d056fa04SAlexander Leidinger error = ENOMEM; 2893d056fa04SAlexander Leidinger goto bad; 2894d056fa04SAlexander Leidinger } 2895d056fa04SAlexander Leidinger midiinfo[1] = malloc(sizeof(struct emu_midiinfo), M_DEVBUF, M_NOWAIT | M_ZERO); 2896d056fa04SAlexander Leidinger if (midiinfo[1] == NULL) { 2897d056fa04SAlexander Leidinger error = ENOMEM; 2898d056fa04SAlexander Leidinger goto bad; 2899d056fa04SAlexander Leidinger } 2900d056fa04SAlexander Leidinger midiinfo[1]->card = sc; 2901d056fa04SAlexander Leidinger 2902d056fa04SAlexander Leidinger midiinfo[1]->port = A_MUDATA2; 2903d056fa04SAlexander Leidinger midiinfo[1]->portnr = 2; 2904d056fa04SAlexander Leidinger 2905d056fa04SAlexander Leidinger func->func = SCF_MIDI; 2906d056fa04SAlexander Leidinger func->varinfo = midiinfo[1]; 2907d056fa04SAlexander Leidinger sc->midi[1] = device_add_child(dev, "midi", -1); 2908d056fa04SAlexander Leidinger device_set_ivars(sc->midi[1], func); 2909d056fa04SAlexander Leidinger } 2910d056fa04SAlexander Leidinger 2911d056fa04SAlexander Leidinger return (bus_generic_attach(dev)); 2912d056fa04SAlexander Leidinger 2913d056fa04SAlexander Leidinger bad: 2914d056fa04SAlexander Leidinger /* XXX can we just call emu_pci_detach here? */ 2915d056fa04SAlexander Leidinger if (sc->cdev) 2916d056fa04SAlexander Leidinger emu10kx_dev_uninit(sc); 2917d056fa04SAlexander Leidinger if (sc->rm != NULL) 2918d056fa04SAlexander Leidinger emu_rm_uninit(sc); 2919d056fa04SAlexander Leidinger if (sc->reg) 2920d056fa04SAlexander Leidinger bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg); 2921d056fa04SAlexander Leidinger if (sc->ih) 2922d056fa04SAlexander Leidinger bus_teardown_intr(dev, sc->irq, sc->ih); 2923d056fa04SAlexander Leidinger if (sc->irq) 2924d056fa04SAlexander Leidinger bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); 2925d056fa04SAlexander Leidinger mtx_destroy(&sc->lock); 2926d056fa04SAlexander Leidinger mtx_destroy(&sc->rw); 2927d056fa04SAlexander Leidinger return (error); 2928d056fa04SAlexander Leidinger } 2929d056fa04SAlexander Leidinger 2930d056fa04SAlexander Leidinger static int 2931d056fa04SAlexander Leidinger emu_pci_detach(device_t dev) 2932d056fa04SAlexander Leidinger { 2933d056fa04SAlexander Leidinger struct emu_sc_info *sc; 2934d056fa04SAlexander Leidinger int devcount, i; 2935d056fa04SAlexander Leidinger device_t *childlist; 2936d056fa04SAlexander Leidinger int r = 0; 2937d056fa04SAlexander Leidinger 2938d056fa04SAlexander Leidinger sc = device_get_softc(dev); 2939d056fa04SAlexander Leidinger 2940d056fa04SAlexander Leidinger for (i = 0; i < 5; i++) { 2941d056fa04SAlexander Leidinger if (sc->pcm[i] != NULL) 2942d056fa04SAlexander Leidinger r = device_delete_child(dev, sc->pcm[i]); 2943d056fa04SAlexander Leidinger if (r) 2944d056fa04SAlexander Leidinger return (r); 2945d056fa04SAlexander Leidinger } 2946d056fa04SAlexander Leidinger if (sc->midi[0] != NULL) 2947d056fa04SAlexander Leidinger r = device_delete_child(dev, sc->midi[0]); 2948d056fa04SAlexander Leidinger if (r) 2949d056fa04SAlexander Leidinger return (r); 2950d056fa04SAlexander Leidinger if (sc->midi[1] != NULL) 2951d056fa04SAlexander Leidinger r = device_delete_child(dev, sc->midi[1]); 2952d056fa04SAlexander Leidinger if (r) 2953d056fa04SAlexander Leidinger return (r); 2954d056fa04SAlexander Leidinger (void)device_get_children(dev, &childlist, &devcount); 2955d056fa04SAlexander Leidinger for (i = 0; i < devcount - 1; i++) { 2956d056fa04SAlexander Leidinger device_printf(dev, "removing stale child %d (unit %d)\n", i, device_get_unit(childlist[i])); 2957d056fa04SAlexander Leidinger device_delete_child(dev, childlist[i]); 2958d056fa04SAlexander Leidinger } 2959d056fa04SAlexander Leidinger free(childlist, M_TEMP); 2960d056fa04SAlexander Leidinger 2961d056fa04SAlexander Leidinger /* shutdown chip */ 2962d056fa04SAlexander Leidinger emu_uninit(sc); 2963d056fa04SAlexander Leidinger r = emu10kx_dev_uninit(sc); 2964d056fa04SAlexander Leidinger if (r) 2965d056fa04SAlexander Leidinger return (r); 2966d056fa04SAlexander Leidinger emu_rm_uninit(sc); 2967d056fa04SAlexander Leidinger if (sc->reg) 2968d056fa04SAlexander Leidinger bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg); 2969d056fa04SAlexander Leidinger bus_teardown_intr(dev, sc->irq, sc->ih); 2970d056fa04SAlexander Leidinger bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); 2971d056fa04SAlexander Leidinger mtx_destroy(&sc->lock); 2972d056fa04SAlexander Leidinger mtx_destroy(&sc->rw); 2973d056fa04SAlexander Leidinger return (bus_generic_detach(dev)); 2974d056fa04SAlexander Leidinger } 2975d056fa04SAlexander Leidinger /* add suspend, resume */ 2976d056fa04SAlexander Leidinger static device_method_t emu_methods[] = { 2977d056fa04SAlexander Leidinger /* Device interface */ 2978d056fa04SAlexander Leidinger DEVMETHOD(device_probe, emu_pci_probe), 2979d056fa04SAlexander Leidinger DEVMETHOD(device_attach, emu_pci_attach), 2980d056fa04SAlexander Leidinger DEVMETHOD(device_detach, emu_pci_detach), 2981d056fa04SAlexander Leidinger /* Bus methods */ 2982d056fa04SAlexander Leidinger DEVMETHOD(bus_read_ivar, emu_read_ivar), 2983d056fa04SAlexander Leidinger DEVMETHOD(bus_write_ivar, emu_write_ivar), 2984d056fa04SAlexander Leidinger 2985d056fa04SAlexander Leidinger {0, 0} 2986d056fa04SAlexander Leidinger }; 2987d056fa04SAlexander Leidinger 2988d056fa04SAlexander Leidinger 2989d056fa04SAlexander Leidinger static driver_t emu_driver = { 2990d056fa04SAlexander Leidinger "emu10kx", 2991d056fa04SAlexander Leidinger emu_methods, 2992d056fa04SAlexander Leidinger sizeof(struct emu_sc_info), 2993d056fa04SAlexander Leidinger NULL, 2994d056fa04SAlexander Leidinger 0, 2995d056fa04SAlexander Leidinger NULL 2996d056fa04SAlexander Leidinger }; 2997d056fa04SAlexander Leidinger 2998d056fa04SAlexander Leidinger static int 2999d056fa04SAlexander Leidinger emu_modevent(module_t mod __unused, int cmd, void *data __unused) 3000d056fa04SAlexander Leidinger { 3001d056fa04SAlexander Leidinger int err = 0; 3002d056fa04SAlexander Leidinger 3003d056fa04SAlexander Leidinger switch (cmd) { 3004d056fa04SAlexander Leidinger case MOD_LOAD: 3005d056fa04SAlexander Leidinger break; /* Success */ 3006d056fa04SAlexander Leidinger 3007d056fa04SAlexander Leidinger case MOD_UNLOAD: 3008d056fa04SAlexander Leidinger case MOD_SHUTDOWN: 3009d056fa04SAlexander Leidinger 3010d056fa04SAlexander Leidinger /* XXX Should we check state of pcm & midi subdevices here? */ 3011d056fa04SAlexander Leidinger 3012d056fa04SAlexander Leidinger break; /* Success */ 3013d056fa04SAlexander Leidinger 3014d056fa04SAlexander Leidinger default: 3015d056fa04SAlexander Leidinger err = EINVAL; 3016d056fa04SAlexander Leidinger break; 3017d056fa04SAlexander Leidinger } 3018d056fa04SAlexander Leidinger 3019d056fa04SAlexander Leidinger return (err); 3020d056fa04SAlexander Leidinger 3021d056fa04SAlexander Leidinger } 3022d056fa04SAlexander Leidinger 3023d056fa04SAlexander Leidinger static devclass_t emu_devclass; 3024d056fa04SAlexander Leidinger 3025d056fa04SAlexander Leidinger DRIVER_MODULE(snd_emu10kx, pci, emu_driver, emu_devclass, emu_modevent, NULL); 3026d056fa04SAlexander Leidinger DRIVER_MODULE(snd_emu10kx, cardbus, emu_driver, emu_devclass, emu_modevent, NULL); 3027d056fa04SAlexander Leidinger MODULE_VERSION(snd_emu10kx, SND_EMU10KX_PREFVER); 3028