1 1.79 andvar /* $NetBSD: emuxki.c,v 1.79 2024/06/08 21:02:29 andvar Exp $ */ 2 1.1 jdolecek 3 1.1 jdolecek /*- 4 1.60 jmcneill * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc. 5 1.1 jdolecek * All rights reserved. 6 1.1 jdolecek * 7 1.1 jdolecek * This code is derived from software contributed to The NetBSD Foundation 8 1.60 jmcneill * by Yannick Montulet, and by Andrew Doran. 9 1.1 jdolecek * 10 1.1 jdolecek * Redistribution and use in source and binary forms, with or without 11 1.1 jdolecek * modification, are permitted provided that the following conditions 12 1.1 jdolecek * are met: 13 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright 14 1.1 jdolecek * notice, this list of conditions and the following disclaimer. 15 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the 17 1.1 jdolecek * documentation and/or other materials provided with the distribution. 18 1.1 jdolecek * 19 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 jdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 jdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 jdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 jdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 jdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 jdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 jdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 jdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 jdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 jdolecek * POSSIBILITY OF SUCH DAMAGE. 30 1.1 jdolecek */ 31 1.1 jdolecek 32 1.1 jdolecek /* 33 1.68 isaki * EMU10K1 single voice driver 34 1.68 isaki * o. only 1 voice playback, 1 recording 35 1.68 isaki * o. only s16le 2ch 48k 36 1.68 isaki * This makes it simple to control buffers and interrupts 37 1.68 isaki * while satisfying playback and recording quality. 38 1.1 jdolecek */ 39 1.4 lukem 40 1.4 lukem #include <sys/cdefs.h> 41 1.79 andvar __KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.79 2024/06/08 21:02:29 andvar Exp $"); 42 1.1 jdolecek 43 1.5 lukem #include <sys/param.h> 44 1.1 jdolecek #include <sys/device.h> 45 1.73 khorben #include <sys/module.h> 46 1.1 jdolecek #include <sys/errno.h> 47 1.1 jdolecek #include <sys/systm.h> 48 1.1 jdolecek #include <sys/audioio.h> 49 1.60 jmcneill #include <sys/mutex.h> 50 1.60 jmcneill #include <sys/kmem.h> 51 1.68 isaki #include <sys/fcntl.h> 52 1.60 jmcneill 53 1.68 isaki #include <sys/bus.h> 54 1.68 isaki #include <sys/intr.h> 55 1.68 isaki 56 1.1 jdolecek #include <dev/pci/emuxkireg.h> 57 1.75 khorben #include <dev/pci/emuxkivar.h> 58 1.76 khorben #include <dev/pci/emuxki_boards.h> 59 1.1 jdolecek 60 1.68 isaki /* #define EMUXKI_DEBUG 1 */ 61 1.68 isaki #ifdef EMUXKI_DEBUG 62 1.68 isaki #define emudebug EMUXKI_DEBUG 63 1.68 isaki # define DPRINTF(fmt...) do { if (emudebug) printf(fmt); } while (0) 64 1.68 isaki # define DPRINTFN(n,fmt...) do { if (emudebug>=(n)) printf(fmt); } while (0) 65 1.68 isaki #else 66 1.68 isaki # define DPRINTF(fmt...) __nothing 67 1.68 isaki # define DPRINTFN(n,fmt...) __nothing 68 1.68 isaki #endif 69 1.68 isaki 70 1.68 isaki /* 71 1.68 isaki * PCI 72 1.68 isaki * Note: emuxki's page table entry uses only 31bit addressing. 73 1.68 isaki * (Maybe, later chip has 32bit mode, but it isn't used now.) 74 1.68 isaki */ 75 1.1 jdolecek 76 1.68 isaki #define EMU_PCI_CBIO (0x10) 77 1.1 jdolecek 78 1.68 isaki /* blackmagic */ 79 1.68 isaki #define X1(x) ((sc->sc_type & EMUXKI_AUDIGY) ? EMU_A_##x : EMU_##x) 80 1.68 isaki #define X2(x, y) ((sc->sc_type & EMUXKI_AUDIGY) \ 81 1.68 isaki ? EMU_A_##x(EMU_A_##y) : EMU_##x(EMU_##y)) 82 1.68 isaki #define EMU_A_DSP_FX EMU_DSP_FX 83 1.68 isaki #define EMU_A_DSP_IN_AC97 EMU_DSP_IN_AC97 84 1.1 jdolecek 85 1.68 isaki /* prototypes */ 86 1.68 isaki static struct dmamem *dmamem_alloc(struct emuxki_softc *, size_t); 87 1.68 isaki static void dmamem_free(struct dmamem *); 88 1.68 isaki static void dmamem_sync(struct dmamem *, int); 89 1.68 isaki static uint8_t emuxki_readio_1(struct emuxki_softc *, int) __unused; 90 1.68 isaki static uint16_t emuxki_readio_2(struct emuxki_softc *, int); 91 1.68 isaki static uint32_t emuxki_readio_4(struct emuxki_softc *, int); 92 1.68 isaki static void emuxki_writeio_1(struct emuxki_softc *, int, uint8_t); 93 1.68 isaki static void emuxki_writeio_2(struct emuxki_softc *, int, uint16_t); 94 1.68 isaki static void emuxki_writeio_4(struct emuxki_softc *, int, uint32_t); 95 1.68 isaki static uint32_t emuxki_readptr(struct emuxki_softc *, int, int, int); 96 1.68 isaki static void emuxki_writeptr(struct emuxki_softc *, int, int, int, uint32_t); 97 1.68 isaki static uint32_t emuxki_read(struct emuxki_softc *, int, int); 98 1.68 isaki static void emuxki_write(struct emuxki_softc *, int, int, uint32_t); 99 1.68 isaki static int emuxki_match(device_t, cfdata_t, void *); 100 1.68 isaki static void emuxki_attach(device_t, device_t, void *); 101 1.68 isaki static int emuxki_detach(device_t, int); 102 1.68 isaki static int emuxki_init(struct emuxki_softc *); 103 1.68 isaki static void emuxki_dsp_addop(struct emuxki_softc *, uint16_t *, uint8_t, 104 1.68 isaki uint16_t, uint16_t, uint16_t, uint16_t); 105 1.68 isaki static void emuxki_initfx(struct emuxki_softc *); 106 1.68 isaki static void emuxki_play_start(struct emuxki_softc *, int, uint32_t, 107 1.68 isaki uint32_t); 108 1.68 isaki static void emuxki_play_stop(struct emuxki_softc *, int); 109 1.1 jdolecek 110 1.68 isaki static int emuxki_query_format(void *, audio_format_query_t *); 111 1.68 isaki static int emuxki_set_format(void *, int, 112 1.68 isaki const audio_params_t *, const audio_params_t *, 113 1.68 isaki audio_filter_reg_t *, audio_filter_reg_t *); 114 1.3 jdolecek static int emuxki_halt_output(void *); 115 1.3 jdolecek static int emuxki_halt_input(void *); 116 1.68 isaki static int emuxki_intr(void *); 117 1.3 jdolecek static int emuxki_getdev(void *, struct audio_device *); 118 1.3 jdolecek static int emuxki_set_port(void *, mixer_ctrl_t *); 119 1.3 jdolecek static int emuxki_get_port(void *, mixer_ctrl_t *); 120 1.3 jdolecek static int emuxki_query_devinfo(void *, mixer_devinfo_t *); 121 1.68 isaki static void *emuxki_allocm(void *, int, size_t); 122 1.60 jmcneill static void emuxki_freem(void *, void *, size_t); 123 1.68 isaki static int emuxki_round_blocksize(void *, int, int, 124 1.68 isaki const audio_params_t *); 125 1.68 isaki static size_t emuxki_round_buffersize(void *, int, size_t); 126 1.3 jdolecek static int emuxki_get_props(void *); 127 1.68 isaki static int emuxki_trigger_output(void *, void *, void *, int, 128 1.68 isaki void (*)(void *), void *, const audio_params_t *); 129 1.68 isaki static int emuxki_trigger_input(void *, void *, void *, int, 130 1.68 isaki void (*)(void *), void *, const audio_params_t *); 131 1.60 jmcneill static void emuxki_get_locks(void *, kmutex_t **, kmutex_t **); 132 1.1 jdolecek 133 1.68 isaki static int emuxki_ac97_init(struct emuxki_softc *); 134 1.40 kent static int emuxki_ac97_attach(void *, struct ac97_codec_if *); 135 1.40 kent static int emuxki_ac97_read(void *, uint8_t, uint16_t *); 136 1.40 kent static int emuxki_ac97_write(void *, uint8_t, uint16_t); 137 1.40 kent static int emuxki_ac97_reset(void *); 138 1.68 isaki static enum ac97_host_flags emuxki_ac97_flags(void *); 139 1.68 isaki 140 1.1 jdolecek 141 1.58 tsutsui CFATTACH_DECL_NEW(emuxki, sizeof(struct emuxki_softc), 142 1.12 thorpej emuxki_match, emuxki_attach, emuxki_detach, NULL); 143 1.1 jdolecek 144 1.38 yamt static const struct audio_hw_if emuxki_hw_if = { 145 1.68 isaki .query_format = emuxki_query_format, 146 1.68 isaki .set_format = emuxki_set_format, 147 1.67 isaki .round_blocksize = emuxki_round_blocksize, 148 1.67 isaki .halt_output = emuxki_halt_output, 149 1.67 isaki .halt_input = emuxki_halt_input, 150 1.67 isaki .getdev = emuxki_getdev, 151 1.67 isaki .set_port = emuxki_set_port, 152 1.67 isaki .get_port = emuxki_get_port, 153 1.67 isaki .query_devinfo = emuxki_query_devinfo, 154 1.67 isaki .allocm = emuxki_allocm, 155 1.67 isaki .freem = emuxki_freem, 156 1.67 isaki .round_buffersize = emuxki_round_buffersize, 157 1.67 isaki .get_props = emuxki_get_props, 158 1.67 isaki .trigger_output = emuxki_trigger_output, 159 1.67 isaki .trigger_input = emuxki_trigger_input, 160 1.67 isaki .get_locks = emuxki_get_locks, 161 1.1 jdolecek }; 162 1.1 jdolecek 163 1.68 isaki static const struct audio_format emuxki_formats[] = { 164 1.68 isaki { 165 1.68 isaki .mode = AUMODE_PLAY | AUMODE_RECORD, 166 1.68 isaki .encoding = AUDIO_ENCODING_SLINEAR_LE, 167 1.68 isaki .validbits = 16, 168 1.68 isaki .precision = 16, 169 1.68 isaki .channels = 2, 170 1.68 isaki .channel_mask = AUFMT_STEREO, 171 1.68 isaki .frequency_type = 1, 172 1.68 isaki .frequency = { 48000 }, 173 1.68 isaki } 174 1.39 kent }; 175 1.68 isaki #define EMUXKI_NFORMATS __arraycount(emuxki_formats) 176 1.39 kent 177 1.1 jdolecek /* 178 1.68 isaki * dma memory 179 1.1 jdolecek */ 180 1.1 jdolecek 181 1.68 isaki static struct dmamem * 182 1.68 isaki dmamem_alloc(struct emuxki_softc *sc, size_t size) 183 1.1 jdolecek { 184 1.68 isaki struct dmamem *mem; 185 1.40 kent 186 1.68 isaki KASSERT(!mutex_owned(&sc->sc_intr_lock)); 187 1.1 jdolecek 188 1.1 jdolecek /* Allocate memory for structure */ 189 1.65 chs mem = kmem_alloc(sizeof(*mem), KM_SLEEP); 190 1.68 isaki mem->dmat = sc->sc_dmat; 191 1.1 jdolecek mem->size = size; 192 1.68 isaki mem->align = EMU_DMA_ALIGN; 193 1.68 isaki mem->nsegs = EMU_DMA_NSEGS; 194 1.1 jdolecek mem->bound = 0; 195 1.1 jdolecek 196 1.60 jmcneill mem->segs = kmem_alloc(mem->nsegs * sizeof(*(mem->segs)), KM_SLEEP); 197 1.1 jdolecek 198 1.68 isaki if (bus_dmamem_alloc(mem->dmat, mem->size, mem->align, mem->bound, 199 1.68 isaki mem->segs, mem->nsegs, &mem->rsegs, BUS_DMA_WAITOK)) { 200 1.68 isaki device_printf(sc->sc_dev, 201 1.68 isaki "%s bus_dmamem_alloc failed\n", __func__); 202 1.68 isaki goto memfree; 203 1.68 isaki } 204 1.68 isaki 205 1.68 isaki if (bus_dmamem_map(mem->dmat, mem->segs, mem->nsegs, mem->size, 206 1.68 isaki &mem->kaddr, BUS_DMA_WAITOK | BUS_DMA_COHERENT)) { 207 1.68 isaki device_printf(sc->sc_dev, 208 1.68 isaki "%s bus_dmamem_map failed\n", __func__); 209 1.68 isaki goto free; 210 1.68 isaki } 211 1.68 isaki 212 1.68 isaki if (bus_dmamap_create(mem->dmat, mem->size, mem->nsegs, mem->size, 213 1.68 isaki mem->bound, BUS_DMA_WAITOK, &mem->map)) { 214 1.68 isaki device_printf(sc->sc_dev, 215 1.68 isaki "%s bus_dmamap_create failed\n", __func__); 216 1.68 isaki goto unmap; 217 1.68 isaki } 218 1.68 isaki 219 1.68 isaki if (bus_dmamap_load(mem->dmat, mem->map, mem->kaddr, 220 1.68 isaki mem->size, NULL, BUS_DMA_WAITOK)) { 221 1.68 isaki device_printf(sc->sc_dev, 222 1.68 isaki "%s bus_dmamap_load failed\n", __func__); 223 1.68 isaki goto destroy; 224 1.1 jdolecek } 225 1.1 jdolecek 226 1.40 kent return mem; 227 1.68 isaki 228 1.68 isaki destroy: 229 1.68 isaki bus_dmamap_destroy(mem->dmat, mem->map); 230 1.68 isaki unmap: 231 1.68 isaki bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size); 232 1.68 isaki free: 233 1.68 isaki bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs); 234 1.68 isaki memfree: 235 1.68 isaki kmem_free(mem->segs, mem->nsegs * sizeof(*(mem->segs))); 236 1.68 isaki kmem_free(mem, sizeof(*mem)); 237 1.68 isaki 238 1.68 isaki return NULL; 239 1.1 jdolecek } 240 1.1 jdolecek 241 1.1 jdolecek static void 242 1.60 jmcneill dmamem_free(struct dmamem *mem) 243 1.1 jdolecek { 244 1.40 kent 245 1.1 jdolecek bus_dmamap_unload(mem->dmat, mem->map); 246 1.1 jdolecek bus_dmamap_destroy(mem->dmat, mem->map); 247 1.1 jdolecek bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size); 248 1.1 jdolecek bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs); 249 1.68 isaki 250 1.68 isaki kmem_free(mem->segs, mem->nsegs * sizeof(*(mem->segs))); 251 1.68 isaki kmem_free(mem, sizeof(*mem)); 252 1.68 isaki } 253 1.68 isaki 254 1.68 isaki static void 255 1.68 isaki dmamem_sync(struct dmamem *mem, int ops) 256 1.68 isaki { 257 1.68 isaki 258 1.68 isaki bus_dmamap_sync(mem->dmat, mem->map, 0, mem->size, ops); 259 1.1 jdolecek } 260 1.1 jdolecek 261 1.1 jdolecek 262 1.1 jdolecek /* 263 1.68 isaki * I/O register access 264 1.1 jdolecek */ 265 1.1 jdolecek 266 1.68 isaki static uint8_t 267 1.68 isaki emuxki_readio_1(struct emuxki_softc *sc, int addr) 268 1.68 isaki { 269 1.68 isaki 270 1.68 isaki return bus_space_read_1(sc->sc_iot, sc->sc_ioh, addr); 271 1.68 isaki } 272 1.68 isaki 273 1.68 isaki static void 274 1.68 isaki emuxki_writeio_1(struct emuxki_softc *sc, int addr, uint8_t data) 275 1.68 isaki { 276 1.68 isaki 277 1.68 isaki bus_space_write_1(sc->sc_iot, sc->sc_ioh, addr, data); 278 1.68 isaki } 279 1.68 isaki 280 1.68 isaki static uint16_t 281 1.68 isaki emuxki_readio_2(struct emuxki_softc *sc, int addr) 282 1.68 isaki { 283 1.68 isaki 284 1.68 isaki return bus_space_read_2(sc->sc_iot, sc->sc_ioh, addr); 285 1.68 isaki } 286 1.68 isaki 287 1.68 isaki static void 288 1.68 isaki emuxki_writeio_2(struct emuxki_softc *sc, int addr, uint16_t data) 289 1.68 isaki { 290 1.68 isaki 291 1.68 isaki bus_space_write_2(sc->sc_iot, sc->sc_ioh, addr, data); 292 1.68 isaki } 293 1.68 isaki 294 1.68 isaki static uint32_t 295 1.68 isaki emuxki_readio_4(struct emuxki_softc *sc, int addr) 296 1.68 isaki { 297 1.68 isaki 298 1.68 isaki return bus_space_read_4(sc->sc_iot, sc->sc_ioh, addr); 299 1.68 isaki } 300 1.68 isaki 301 1.1 jdolecek static void 302 1.68 isaki emuxki_writeio_4(struct emuxki_softc *sc, int addr, uint32_t data) 303 1.1 jdolecek { 304 1.40 kent 305 1.68 isaki bus_space_write_4(sc->sc_iot, sc->sc_ioh, addr, data); 306 1.1 jdolecek } 307 1.1 jdolecek 308 1.68 isaki static uint32_t 309 1.68 isaki emuxki_readptr(struct emuxki_softc *sc, int aptr, int dptr, int addr) 310 1.1 jdolecek { 311 1.68 isaki uint32_t data; 312 1.68 isaki 313 1.68 isaki mutex_spin_enter(&sc->sc_index_lock); 314 1.68 isaki emuxki_writeio_4(sc, aptr, addr); 315 1.68 isaki data = emuxki_readio_4(sc, dptr); 316 1.68 isaki mutex_spin_exit(&sc->sc_index_lock); 317 1.68 isaki return data; 318 1.68 isaki } 319 1.1 jdolecek 320 1.68 isaki static void 321 1.68 isaki emuxki_writeptr(struct emuxki_softc *sc, int aptr, int dptr, int addr, 322 1.68 isaki uint32_t data) 323 1.68 isaki { 324 1.1 jdolecek 325 1.68 isaki mutex_spin_enter(&sc->sc_index_lock); 326 1.68 isaki emuxki_writeio_4(sc, aptr, addr); 327 1.68 isaki emuxki_writeio_4(sc, dptr, data); 328 1.68 isaki mutex_spin_exit(&sc->sc_index_lock); 329 1.68 isaki } 330 1.1 jdolecek 331 1.68 isaki static uint32_t 332 1.68 isaki emuxki_read(struct emuxki_softc *sc, int ch, int addr) 333 1.68 isaki { 334 1.1 jdolecek 335 1.68 isaki /* Original HENTAI addressing is never supported. */ 336 1.68 isaki KASSERT((addr & 0xff000000) == 0); 337 1.1 jdolecek 338 1.68 isaki return emuxki_readptr(sc, EMU_PTR, EMU_DATA, (addr << 16) + ch); 339 1.1 jdolecek } 340 1.1 jdolecek 341 1.68 isaki static void 342 1.68 isaki emuxki_write(struct emuxki_softc *sc, int ch, int addr, uint32_t data) 343 1.1 jdolecek { 344 1.68 isaki 345 1.68 isaki /* Original HENTAI addressing is never supported. */ 346 1.68 isaki KASSERT((addr & 0xff000000) == 0); 347 1.68 isaki 348 1.68 isaki emuxki_writeptr(sc, EMU_PTR, EMU_DATA, (addr << 16) + ch, data); 349 1.1 jdolecek } 350 1.1 jdolecek 351 1.68 isaki /* 352 1.68 isaki * MD driver 353 1.68 isaki */ 354 1.68 isaki 355 1.1 jdolecek static int 356 1.56 cegger emuxki_match(device_t parent, cfdata_t match, void *aux) 357 1.1 jdolecek { 358 1.40 kent struct pci_attach_args *pa; 359 1.76 khorben pcireg_t reg; 360 1.1 jdolecek 361 1.40 kent pa = aux; 362 1.35 christos 363 1.76 khorben reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 364 1.76 khorben if (emuxki_board_lookup(PCI_VENDOR(pa->pa_id), 365 1.76 khorben PCI_PRODUCT(pa->pa_id), reg, 366 1.76 khorben PCI_REVISION(pa->pa_class)) != NULL) 367 1.40 kent return 1; 368 1.76 khorben 369 1.76 khorben return 0; 370 1.1 jdolecek } 371 1.1 jdolecek 372 1.1 jdolecek static void 373 1.56 cegger emuxki_attach(device_t parent, device_t self, void *aux) 374 1.1 jdolecek { 375 1.40 kent struct emuxki_softc *sc; 376 1.40 kent struct pci_attach_args *pa; 377 1.76 khorben const struct emuxki_board *sb; 378 1.1 jdolecek pci_intr_handle_t ih; 379 1.40 kent const char *intrstr; 380 1.63 christos char intrbuf[PCI_INTRSTR_LEN]; 381 1.68 isaki pcireg_t reg; 382 1.1 jdolecek 383 1.57 cegger sc = device_private(self); 384 1.58 tsutsui sc->sc_dev = self; 385 1.40 kent pa = aux; 386 1.15 thorpej 387 1.76 khorben reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 388 1.76 khorben sb = emuxki_board_lookup(PCI_VENDOR(pa->pa_id), 389 1.76 khorben PCI_PRODUCT(pa->pa_id), reg, 390 1.76 khorben PCI_REVISION(pa->pa_class)); 391 1.76 khorben KASSERT(sb != NULL); 392 1.76 khorben 393 1.68 isaki pci_aprint_devinfo(pa, "Audio controller"); 394 1.76 khorben aprint_normal_dev(self, "%s [%s]\n", sb->sb_name, sb->sb_board); 395 1.68 isaki DPRINTF("dmat=%p\n", (char *)pa->pa_dmat); 396 1.68 isaki 397 1.60 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 398 1.61 mrg mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); 399 1.61 mrg mutex_init(&sc->sc_index_lock, MUTEX_DEFAULT, IPL_AUDIO); 400 1.68 isaki 401 1.68 isaki sc->sc_pc = pa->pa_pc; 402 1.74 khorben 403 1.74 khorben /* EMU10K1 can only address 31 bits (2GB) */ 404 1.74 khorben if (bus_dmatag_subregion(pa->pa_dmat, 0, ((uint32_t)1 << 31) - 1, 405 1.74 khorben &(sc->sc_dmat), BUS_DMA_NOWAIT) != 0) { 406 1.74 khorben aprint_error_dev(self, 407 1.74 khorben "WARNING: failed to restrict dma range," 408 1.74 khorben " falling back to parent bus dma range\n"); 409 1.74 khorben sc->sc_dmat = pa->pa_dmat; 410 1.74 khorben } 411 1.68 isaki 412 1.68 isaki reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 413 1.68 isaki reg |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE | 414 1.68 isaki PCI_COMMAND_MEM_ENABLE; 415 1.68 isaki pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg); 416 1.60 jmcneill 417 1.1 jdolecek if (pci_mapreg_map(pa, EMU_PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, 418 1.68 isaki &sc->sc_iot, &sc->sc_ioh, &sc->sc_iob, &sc->sc_ios)) { 419 1.15 thorpej aprint_error(": can't map iospace\n"); 420 1.1 jdolecek return; 421 1.1 jdolecek } 422 1.62 drochner 423 1.1 jdolecek if (pci_intr_map(pa, &ih)) { 424 1.58 tsutsui aprint_error_dev(self, "couldn't map interrupt\n"); 425 1.68 isaki goto unmap; 426 1.1 jdolecek } 427 1.1 jdolecek 428 1.63 christos intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf)); 429 1.66 jdolecek sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_AUDIO, 430 1.66 jdolecek emuxki_intr, sc, device_xname(self)); 431 1.1 jdolecek if (sc->sc_ih == NULL) { 432 1.58 tsutsui aprint_error_dev(self, "couldn't establish interrupt"); 433 1.1 jdolecek if (intrstr != NULL) 434 1.59 njoly aprint_error(" at %s", intrstr); 435 1.59 njoly aprint_error("\n"); 436 1.68 isaki goto unmap; 437 1.1 jdolecek } 438 1.58 tsutsui aprint_normal_dev(self, "interrupting at %s\n", intrstr); 439 1.35 christos 440 1.66 jdolecek /* XXX it's unknown whether APS is made from Audigy as well */ 441 1.76 khorben sc->sc_type = sb->sb_flags; 442 1.76 khorben if (sc->sc_type & EMUXKI_AUDIGY2_CA0108) { 443 1.76 khorben strlcpy(sc->sc_audv.name, "Audigy2+CA0108", 444 1.72 khorben sizeof(sc->sc_audv.name)); 445 1.76 khorben } else if (sc->sc_type & EMUXKI_AUDIGY2) { 446 1.76 khorben strlcpy(sc->sc_audv.name, "Audigy2", sizeof(sc->sc_audv.name)); 447 1.76 khorben } else if (sc->sc_type & EMUXKI_AUDIGY) { 448 1.76 khorben strlcpy(sc->sc_audv.name, "Audigy", sizeof(sc->sc_audv.name)); 449 1.76 khorben } else if (sc->sc_type & EMUXKI_APS) { 450 1.68 isaki strlcpy(sc->sc_audv.name, "E-mu APS", sizeof(sc->sc_audv.name)); 451 1.40 kent } else { 452 1.68 isaki strlcpy(sc->sc_audv.name, "SB Live!", sizeof(sc->sc_audv.name)); 453 1.40 kent } 454 1.68 isaki snprintf(sc->sc_audv.version, sizeof(sc->sc_audv.version), "0x%02x", 455 1.68 isaki PCI_REVISION(pa->pa_class)); 456 1.68 isaki strlcpy(sc->sc_audv.config, "emuxki", sizeof(sc->sc_audv.config)); 457 1.68 isaki 458 1.68 isaki if (emuxki_init(sc)) { 459 1.68 isaki aprint_error("emuxki_init error\n"); 460 1.68 isaki goto intrdis; 461 1.68 isaki } 462 1.68 isaki if (emuxki_ac97_init(sc)) { 463 1.68 isaki aprint_error("emuxki_ac97_init error\n"); 464 1.68 isaki goto intrdis; 465 1.68 isaki } 466 1.68 isaki 467 1.68 isaki sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self); 468 1.68 isaki if (sc->sc_audev == NULL) { 469 1.68 isaki aprint_error("audio_attach_mi error\n"); 470 1.68 isaki goto intrdis; 471 1.19 toshii } 472 1.68 isaki 473 1.68 isaki return; 474 1.68 isaki 475 1.68 isaki intrdis: 476 1.68 isaki pci_intr_disestablish(sc->sc_pc, sc->sc_ih); 477 1.68 isaki unmap: 478 1.68 isaki bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 479 1.68 isaki return; 480 1.1 jdolecek } 481 1.1 jdolecek 482 1.1 jdolecek static int 483 1.56 cegger emuxki_detach(device_t self, int flags) 484 1.1 jdolecek { 485 1.77 riastrad struct emuxki_softc *sc = device_private(self); 486 1.77 riastrad int error; 487 1.1 jdolecek 488 1.77 riastrad error = config_detach_children(self, flags); 489 1.77 riastrad if (error) 490 1.77 riastrad return error; 491 1.1 jdolecek 492 1.1 jdolecek /* All voices should be stopped now but add some code here if not */ 493 1.68 isaki emuxki_writeio_4(sc, EMU_HCFG, 494 1.68 isaki EMU_HCFG_LOCKSOUNDCACHE | 495 1.68 isaki EMU_HCFG_LOCKTANKCACHE_MASK | 496 1.68 isaki EMU_HCFG_MUTEBUTTONENABLE); 497 1.68 isaki emuxki_writeio_4(sc, EMU_INTE, 0); 498 1.68 isaki 499 1.68 isaki /* Disable any Channels interrupts */ 500 1.68 isaki emuxki_write(sc, 0, EMU_CLIEL, 0); 501 1.68 isaki emuxki_write(sc, 0, EMU_CLIEH, 0); 502 1.68 isaki emuxki_write(sc, 0, EMU_SOLEL, 0); 503 1.68 isaki emuxki_write(sc, 0, EMU_SOLEH, 0); 504 1.68 isaki 505 1.68 isaki /* stop DSP */ 506 1.68 isaki emuxki_write(sc, 0, X1(DBG), X1(DBG_SINGLE_STEP)); 507 1.1 jdolecek 508 1.68 isaki dmamem_free(sc->ptb); 509 1.1 jdolecek 510 1.68 isaki pci_intr_disestablish(sc->sc_pc, sc->sc_ih); 511 1.68 isaki bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 512 1.1 jdolecek 513 1.60 jmcneill mutex_destroy(&sc->sc_lock); 514 1.60 jmcneill mutex_destroy(&sc->sc_intr_lock); 515 1.60 jmcneill mutex_destroy(&sc->sc_index_lock); 516 1.60 jmcneill 517 1.40 kent return 0; 518 1.1 jdolecek } 519 1.1 jdolecek 520 1.1 jdolecek static int 521 1.1 jdolecek emuxki_init(struct emuxki_softc *sc) 522 1.1 jdolecek { 523 1.68 isaki int i; 524 1.68 isaki uint32_t spcs; 525 1.68 isaki uint32_t hcfg; 526 1.68 isaki 527 1.68 isaki /* clear AUDIO bit */ 528 1.68 isaki emuxki_writeio_4(sc, EMU_HCFG, 529 1.68 isaki EMU_HCFG_LOCKSOUNDCACHE | 530 1.68 isaki EMU_HCFG_LOCKTANKCACHE_MASK | 531 1.68 isaki EMU_HCFG_MUTEBUTTONENABLE); 532 1.68 isaki 533 1.68 isaki /* mask interrupt without PCIERR */ 534 1.68 isaki emuxki_writeio_4(sc, EMU_INTE, 535 1.68 isaki EMU_INTE_SAMPLERATER | /* always on this bit */ 536 1.68 isaki EMU_INTE_PCIERRENABLE); 537 1.1 jdolecek 538 1.68 isaki /* disable all channel interrupt */ 539 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEL, 0); 540 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEH, 0); 541 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEL, 0); 542 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEH, 0); 543 1.1 jdolecek 544 1.1 jdolecek /* Set recording buffers sizes to zero */ 545 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE); 546 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBA, 0); 547 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE); 548 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBA, 0); 549 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE); 550 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBA, 0); 551 1.1 jdolecek 552 1.40 kent if(sc->sc_type & EMUXKI_AUDIGY) { 553 1.40 kent emuxki_write(sc, 0, EMU_SPBYPASS, EMU_SPBYPASS_24_BITS); 554 1.68 isaki emuxki_write(sc, 0, EMU_AC97SLOT, 555 1.68 isaki EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE); 556 1.40 kent } 557 1.35 christos 558 1.1 jdolecek /* Initialize all channels to stopped and no effects */ 559 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i++) { 560 1.68 isaki emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0x7f7f); 561 1.68 isaki emuxki_write(sc, i, EMU_CHAN_IP, EMU_CHAN_IP_UNITY); 562 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_VTFT, 0xffff); 563 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CVCF, 0xffff); 564 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PTRX, 0); 565 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CPF, 0); 566 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CCR, 0); 567 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PSST, 0); 568 1.68 isaki emuxki_write(sc, i, EMU_CHAN_DSL, 0); 569 1.68 isaki emuxki_write(sc, i, EMU_CHAN_CCCA, EMU_CHAN_CCCA_INTERPROM_1); 570 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_Z1, 0); 571 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_Z2, 0); 572 1.68 isaki emuxki_write(sc, i, EMU_CHAN_MAPA, 0xffffffff); 573 1.68 isaki emuxki_write(sc, i, EMU_CHAN_MAPB, 0xffffffff); 574 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_FXRT, 0x32100000); 575 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ATKHLDM, 0); 576 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_DCYSUSM, 0); 577 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_IFATN, 0xffff); 578 1.68 isaki emuxki_write(sc, i, EMU_CHAN_PEFE, 0x007f); 579 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_FMMOD, 0); 580 1.68 isaki emuxki_write(sc, i, EMU_CHAN_TREMFRQ, 0); 581 1.68 isaki emuxki_write(sc, i, EMU_CHAN_FM2FRQ2, 0); 582 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_TEMPENV, 0); 583 1.1 jdolecek 584 1.1 jdolecek /* these are last so OFF prevents writing */ 585 1.68 isaki emuxki_write(sc, i, EMU_CHAN_LFOVAL2, 0x8000); 586 1.68 isaki emuxki_write(sc, i, EMU_CHAN_LFOVAL1, 0x8000); 587 1.68 isaki emuxki_write(sc, i, EMU_CHAN_ATKHLDV, 0x7f7f); 588 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ENVVOL, 0); 589 1.68 isaki emuxki_write(sc, i, EMU_CHAN_ENVVAL, 0x8000); 590 1.1 jdolecek } 591 1.1 jdolecek 592 1.1 jdolecek /* set digital outputs format */ 593 1.68 isaki spcs = EMU_SPCS_CLKACCY_1000PPM | 594 1.68 isaki EMU_SPCS_SAMPLERATE_48 | 595 1.68 isaki EMU_SPCS_CHANNELNUM_LEFT | 596 1.68 isaki EMU_SPCS_SOURCENUM_UNSPEC | 597 1.68 isaki EMU_SPCS_GENERATIONSTATUS | 598 1.68 isaki 0x00001200 /* Cat code. */ | 599 1.68 isaki 0x00000000 /* IEC-958 Mode */ | 600 1.68 isaki EMU_SPCS_EMPHASIS_NONE | 601 1.68 isaki EMU_SPCS_COPYRIGHT; 602 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS0, spcs); 603 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS1, spcs); 604 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS2, spcs); 605 1.1 jdolecek 606 1.76 khorben if (sc->sc_type & EMUXKI_AUDIGY2_CA0108) { 607 1.72 khorben /* Setup SRCMulti_I2S SamplingRate */ 608 1.72 khorben emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE, 609 1.72 khorben emuxki_read(sc, 0, EMU_A2_SPDIF_SAMPLERATE) & 0xfffff1ff); 610 1.72 khorben 611 1.72 khorben /* Setup SRCSel (Enable SPDIF, I2S SRCMulti) */ 612 1.72 khorben emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, EMU_A2_SRCSEL, 613 1.72 khorben EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI); 614 1.72 khorben 615 1.72 khorben /* Setup SRCMulti Input Audio Enable */ 616 1.72 khorben emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, 617 1.72 khorben 0x7b0000, 0xff000000); 618 1.72 khorben 619 1.72 khorben /* Setup SPDIF Out Audio Enable 620 1.72 khorben * The Audigy 2 Value has a separate SPDIF out, 621 1.72 khorben * so no need for a mixer switch */ 622 1.72 khorben emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, 623 1.72 khorben 0x7a0000, 0xff000000); 624 1.72 khorben emuxki_writeio_4(sc, EMU_A_IOCFG, 625 1.72 khorben emuxki_readio_4(sc, EMU_A_IOCFG) & ~0x8); /* clear bit 3 */ 626 1.72 khorben } else if (sc->sc_type & EMUXKI_AUDIGY2) { 627 1.68 isaki emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE, 628 1.68 isaki EMU_A2_SPDIF_UNKNOWN); 629 1.35 christos 630 1.68 isaki emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, EMU_A2_SRCSEL, 631 1.68 isaki EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI); 632 1.40 kent 633 1.68 isaki emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, EMU_A2_SRCMULTI, 634 1.68 isaki EMU_A2_SRCMULTI_ENABLE_INPUT); 635 1.40 kent } 636 1.35 christos 637 1.68 isaki /* page table */ 638 1.68 isaki sc->ptb = dmamem_alloc(sc, EMU_MAXPTE * sizeof(uint32_t)); 639 1.68 isaki if (sc->ptb == NULL) { 640 1.68 isaki device_printf(sc->sc_dev, "ptb allocation error\n"); 641 1.68 isaki return ENOMEM; 642 1.68 isaki } 643 1.68 isaki emuxki_write(sc, 0, EMU_PTB, DMAADDR(sc->ptb)); 644 1.68 isaki 645 1.68 isaki emuxki_write(sc, 0, EMU_TCBS, 0); /* This means 16K TCB */ 646 1.68 isaki emuxki_write(sc, 0, EMU_TCB, 0); /* No TCB use for now */ 647 1.35 christos 648 1.1 jdolecek /* Let's play with sound processor */ 649 1.1 jdolecek emuxki_initfx(sc); 650 1.1 jdolecek 651 1.68 isaki /* enable interrupt */ 652 1.68 isaki emuxki_writeio_4(sc, EMU_INTE, 653 1.68 isaki emuxki_readio_4(sc, EMU_INTE) | 654 1.68 isaki EMU_INTE_VOLINCRENABLE | 655 1.68 isaki EMU_INTE_VOLDECRENABLE | 656 1.68 isaki EMU_INTE_MUTEENABLE); 657 1.1 jdolecek 658 1.76 khorben if (sc->sc_type & EMUXKI_AUDIGY2_CA0108) { 659 1.72 khorben emuxki_writeio_4(sc, EMU_A_IOCFG, 660 1.72 khorben 0x0060 | emuxki_readio_4(sc, EMU_A_IOCFG)); 661 1.72 khorben } else if (sc->sc_type & EMUXKI_AUDIGY2) { 662 1.68 isaki emuxki_writeio_4(sc, EMU_A_IOCFG, 663 1.72 khorben EMU_A_IOCFG_GPOUT0 | emuxki_readio_4(sc, EMU_A_IOCFG)); 664 1.1 jdolecek } 665 1.1 jdolecek 666 1.68 isaki /* enable AUDIO bit */ 667 1.68 isaki hcfg = EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE; 668 1.1 jdolecek 669 1.68 isaki if (sc->sc_type & EMUXKI_AUDIGY2) { 670 1.68 isaki hcfg |= EMU_HCFG_AC3ENABLE_CDSPDIF | 671 1.68 isaki EMU_HCFG_AC3ENABLE_GPSPDIF; 672 1.68 isaki } else if (sc->sc_type & EMUXKI_AUDIGY) { 673 1.68 isaki } else { 674 1.68 isaki hcfg |= EMU_HCFG_LOCKTANKCACHE_MASK; 675 1.1 jdolecek } 676 1.68 isaki /* joystick not supported now */ 677 1.68 isaki emuxki_writeio_4(sc, EMU_HCFG, hcfg); 678 1.1 jdolecek 679 1.40 kent return 0; 680 1.1 jdolecek } 681 1.1 jdolecek 682 1.68 isaki /* 683 1.68 isaki * dsp programming 684 1.68 isaki */ 685 1.68 isaki 686 1.1 jdolecek static void 687 1.68 isaki emuxki_dsp_addop(struct emuxki_softc *sc, uint16_t *pc, uint8_t op, 688 1.68 isaki uint16_t r, uint16_t a, uint16_t x, uint16_t y) 689 1.1 jdolecek { 690 1.68 isaki uint32_t loword; 691 1.68 isaki uint32_t hiword; 692 1.68 isaki int reg; 693 1.1 jdolecek 694 1.68 isaki if (sc->sc_type & EMUXKI_AUDIGY) { 695 1.68 isaki reg = EMU_A_MICROCODEBASE; 696 1.68 isaki loword = (x << 12) & EMU_A_DSP_LOWORD_OPX_MASK; 697 1.68 isaki loword |= y & EMU_A_DSP_LOWORD_OPY_MASK; 698 1.68 isaki hiword = (op << 24) & EMU_A_DSP_HIWORD_OPCODE_MASK; 699 1.68 isaki hiword |= (r << 12) & EMU_A_DSP_HIWORD_RESULT_MASK; 700 1.68 isaki hiword |= a & EMU_A_DSP_HIWORD_OPA_MASK; 701 1.40 kent } else { 702 1.68 isaki reg = EMU_MICROCODEBASE; 703 1.68 isaki loword = (x << 10) & EMU_DSP_LOWORD_OPX_MASK; 704 1.68 isaki loword |= y & EMU_DSP_LOWORD_OPY_MASK; 705 1.68 isaki hiword = (op << 20) & EMU_DSP_HIWORD_OPCODE_MASK; 706 1.68 isaki hiword |= (r << 10) & EMU_DSP_HIWORD_RESULT_MASK; 707 1.68 isaki hiword |= a & EMU_DSP_HIWORD_OPA_MASK; 708 1.40 kent } 709 1.1 jdolecek 710 1.68 isaki reg += (*pc) * 2; 711 1.68 isaki /* must ordering; lo, hi */ 712 1.68 isaki emuxki_write(sc, 0, reg, loword); 713 1.68 isaki emuxki_write(sc, 0, reg + 1, hiword); 714 1.1 jdolecek 715 1.68 isaki (*pc)++; 716 1.1 jdolecek } 717 1.1 jdolecek 718 1.68 isaki static void 719 1.68 isaki emuxki_initfx(struct emuxki_softc *sc) 720 1.1 jdolecek { 721 1.68 isaki uint16_t pc; 722 1.1 jdolecek 723 1.68 isaki /* Set all GPRs to 0 */ 724 1.68 isaki for (pc = 0; pc < 256; pc++) 725 1.68 isaki emuxki_write(sc, 0, EMU_DSP_GPR(pc), 0); 726 1.68 isaki for (pc = 0; pc < 160; pc++) { 727 1.68 isaki emuxki_write(sc, 0, EMU_TANKMEMDATAREGBASE + pc, 0); 728 1.68 isaki emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0); 729 1.1 jdolecek } 730 1.1 jdolecek 731 1.68 isaki /* stop DSP, single step mode */ 732 1.68 isaki emuxki_write(sc, 0, X1(DBG), X1(DBG_SINGLE_STEP)); 733 1.40 kent 734 1.68 isaki /* XXX: delay (48kHz equiv. 21us) if needed */ 735 1.1 jdolecek 736 1.68 isaki /* start DSP programming */ 737 1.68 isaki pc = 0; 738 1.1 jdolecek 739 1.68 isaki /* OUT[L/R] = 0 + FX[L/R] * 1 */ 740 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, 741 1.68 isaki X2(DSP_OUTL, DSP_OUT_A_FRONT), 742 1.68 isaki X1(DSP_CST(0)), 743 1.68 isaki X1(DSP_FX(0)), 744 1.68 isaki X1(DSP_CST(1))); 745 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, 746 1.68 isaki X2(DSP_OUTR, DSP_OUT_A_FRONT), 747 1.68 isaki X1(DSP_CST(0)), 748 1.68 isaki X1(DSP_FX(1)), 749 1.68 isaki X1(DSP_CST(1))); 750 1.68 isaki #if 0 751 1.68 isaki /* XXX: rear feature??? */ 752 1.68 isaki /* Rear OUT[L/R] = 0 + FX[L/R] * 1 */ 753 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, 754 1.68 isaki X2(DSP_OUTL, DSP_OUT_A_REAR), 755 1.68 isaki X1(DSP_CST(0)), 756 1.68 isaki X1(DSP_FX(0)), 757 1.68 isaki X1(DSP_CST(1))); 758 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS, 759 1.68 isaki X2(DSP_OUTR, DSP_OUT_A_REAR), 760 1.68 isaki X1(DSP_CST(0)), 761 1.68 isaki X1(DSP_FX(1)), 762 1.68 isaki X1(DSP_CST(1))); 763 1.68 isaki #endif 764 1.68 isaki /* ADC recording[L/R] = AC97 In[L/R] */ 765 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, 766 1.68 isaki X2(DSP_OUTL, DSP_OUT_ADC), 767 1.68 isaki X2(DSP_INL, DSP_IN_AC97), 768 1.68 isaki X1(DSP_CST(0)), 769 1.68 isaki X1(DSP_CST(0))); 770 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, 771 1.68 isaki X2(DSP_OUTR, DSP_OUT_ADC), 772 1.68 isaki X2(DSP_INR, DSP_IN_AC97), 773 1.68 isaki X1(DSP_CST(0)), 774 1.68 isaki X1(DSP_CST(0))); 775 1.1 jdolecek 776 1.68 isaki /* fill NOP the rest of the microcode */ 777 1.68 isaki while (pc < 512) { 778 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3, 779 1.68 isaki X1(DSP_CST(0)), 780 1.68 isaki X1(DSP_CST(0)), 781 1.68 isaki X1(DSP_CST(0)), 782 1.68 isaki X1(DSP_CST(0))); 783 1.68 isaki } 784 1.1 jdolecek 785 1.68 isaki /* clear single step flag, run DSP */ 786 1.68 isaki emuxki_write(sc, 0, X1(DBG), 0); 787 1.1 jdolecek } 788 1.1 jdolecek 789 1.1 jdolecek /* 790 1.68 isaki * operations 791 1.1 jdolecek */ 792 1.1 jdolecek 793 1.1 jdolecek static void 794 1.68 isaki emuxki_play_start(struct emuxki_softc *sc, int ch, uint32_t start, uint32_t end) 795 1.1 jdolecek { 796 1.68 isaki uint32_t pitch; 797 1.68 isaki uint32_t volume; 798 1.40 kent 799 1.68 isaki /* 48kHz:16384 = 128/375 */ 800 1.68 isaki pitch = sc->play.sample_rate * 128 / 375; 801 1.68 isaki volume = 32767; 802 1.1 jdolecek 803 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_DSL, 804 1.79 andvar (0 << 24) | /* send amount D = 0 */ 805 1.68 isaki end); 806 1.1 jdolecek 807 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_PSST, 808 1.68 isaki (0 << 24) | /* send amount C = 0 */ 809 1.68 isaki start); 810 1.1 jdolecek 811 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_VTFT, 812 1.68 isaki (volume << 16) | 813 1.68 isaki (0xffff)); /* cutoff filter = none */ 814 1.40 kent 815 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_CVCF, 816 1.68 isaki (volume << 16) | 817 1.68 isaki (0xffff)); /* cutoff filter = none */ 818 1.1 jdolecek 819 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_PTRX, 820 1.68 isaki (pitch << 16) | 821 1.68 isaki ((ch == 0 ? 0x7f : 0) << 8) | /* send amount A = 255,0(L) */ 822 1.68 isaki ((ch == 0 ? 0 : 0x7f))); /* send amount B = 0,255(R) */ 823 1.40 kent 824 1.68 isaki /* set the pitch to start */ 825 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_CPF, 826 1.68 isaki (pitch << 16) | 827 1.68 isaki EMU_CHAN_CPF_STEREO_MASK); /* stereo only */ 828 1.1 jdolecek } 829 1.1 jdolecek 830 1.1 jdolecek static void 831 1.68 isaki emuxki_play_stop(struct emuxki_softc *sc, int ch) 832 1.35 christos { 833 1.40 kent 834 1.68 isaki /* pitch = 0 to stop playing */ 835 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_CPF, EMU_CHAN_CPF_STOP_MASK); 836 1.68 isaki /* volume = 0 */ 837 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_CVCF, 0); 838 1.35 christos } 839 1.35 christos 840 1.35 christos static void 841 1.68 isaki emuxki_timer_start(struct emuxki_softc *sc) 842 1.1 jdolecek { 843 1.68 isaki uint32_t timer; 844 1.1 jdolecek 845 1.68 isaki /* frame count of half PTE at 16bit, 2ch, 48kHz */ 846 1.68 isaki timer = EMU_PTESIZE / 4 / 2; 847 1.1 jdolecek 848 1.68 isaki /* EMU_TIMER is 16bit register */ 849 1.68 isaki emuxki_writeio_2(sc, EMU_TIMER, timer); 850 1.68 isaki emuxki_writeio_4(sc, EMU_INTE, 851 1.68 isaki emuxki_readio_4(sc, EMU_INTE) | 852 1.68 isaki EMU_INTE_INTERTIMERENB); 853 1.68 isaki DPRINTF("timer start\n"); 854 1.1 jdolecek } 855 1.1 jdolecek 856 1.1 jdolecek static void 857 1.68 isaki emuxki_timer_stop(struct emuxki_softc *sc) 858 1.1 jdolecek { 859 1.1 jdolecek 860 1.68 isaki emuxki_writeio_4(sc, EMU_INTE, 861 1.68 isaki emuxki_readio_4(sc, EMU_INTE) & 862 1.68 isaki ~EMU_INTE_INTERTIMERENB); 863 1.68 isaki /* EMU_TIMER is 16bit register */ 864 1.68 isaki emuxki_writeio_2(sc, EMU_TIMER, 0); 865 1.68 isaki DPRINTF("timer stop\n"); 866 1.1 jdolecek } 867 1.1 jdolecek 868 1.1 jdolecek /* 869 1.68 isaki * audio interface 870 1.1 jdolecek */ 871 1.1 jdolecek 872 1.1 jdolecek static int 873 1.68 isaki emuxki_query_format(void *hdl, audio_format_query_t *afp) 874 1.1 jdolecek { 875 1.40 kent 876 1.68 isaki return audio_query_format(emuxki_formats, EMUXKI_NFORMATS, afp); 877 1.1 jdolecek } 878 1.1 jdolecek 879 1.1 jdolecek static int 880 1.68 isaki emuxki_set_format(void *hdl, int setmode, 881 1.68 isaki const audio_params_t *play, const audio_params_t *rec, 882 1.68 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 883 1.1 jdolecek { 884 1.68 isaki struct emuxki_softc *sc = hdl; 885 1.1 jdolecek 886 1.68 isaki if ((setmode & AUMODE_PLAY)) 887 1.68 isaki sc->play = *play; 888 1.68 isaki if ((setmode & AUMODE_RECORD)) 889 1.68 isaki sc->rec = *rec; 890 1.40 kent return 0; 891 1.1 jdolecek } 892 1.1 jdolecek 893 1.68 isaki static int 894 1.68 isaki emuxki_halt_output(void *hdl) 895 1.1 jdolecek { 896 1.68 isaki struct emuxki_softc *sc = hdl; 897 1.40 kent 898 1.68 isaki emuxki_timer_stop(sc); 899 1.68 isaki emuxki_play_stop(sc, 0); 900 1.68 isaki emuxki_play_stop(sc, 1); 901 1.68 isaki return 0; 902 1.1 jdolecek } 903 1.1 jdolecek 904 1.68 isaki static int 905 1.68 isaki emuxki_halt_input(void *hdl) 906 1.1 jdolecek { 907 1.68 isaki struct emuxki_softc *sc = hdl; 908 1.1 jdolecek 909 1.68 isaki /* stop ADC */ 910 1.68 isaki emuxki_write(sc, 0, EMU_ADCCR, 0); 911 1.1 jdolecek 912 1.68 isaki /* disable interrupt */ 913 1.68 isaki emuxki_writeio_4(sc, EMU_INTE, 914 1.68 isaki emuxki_readio_4(sc, EMU_INTE) & 915 1.68 isaki ~EMU_INTE_ADCBUFENABLE); 916 1.40 kent 917 1.40 kent return 0; 918 1.1 jdolecek } 919 1.1 jdolecek 920 1.1 jdolecek static int 921 1.68 isaki emuxki_intr(void *hdl) 922 1.1 jdolecek { 923 1.68 isaki struct emuxki_softc *sc = hdl; 924 1.68 isaki uint32_t ipr; 925 1.68 isaki uint32_t curaddr; 926 1.68 isaki int handled = 0; 927 1.1 jdolecek 928 1.68 isaki mutex_spin_enter(&sc->sc_intr_lock); 929 1.1 jdolecek 930 1.68 isaki ipr = emuxki_readio_4(sc, EMU_IPR); 931 1.68 isaki DPRINTFN(3, "emuxki: ipr=%08x\n", ipr); 932 1.68 isaki if (sc->pintr && (ipr & EMU_IPR_INTERVALTIMER)) { 933 1.68 isaki /* read ch 0 */ 934 1.68 isaki curaddr = emuxki_read(sc, 0, EMU_CHAN_CCCA) & 935 1.68 isaki EMU_CHAN_CCCA_CURRADDR_MASK; 936 1.68 isaki DPRINTFN(3, "curaddr=%08x\n", curaddr); 937 1.68 isaki curaddr *= sc->pframesize; 938 1.68 isaki 939 1.68 isaki if (curaddr < sc->poffset) 940 1.68 isaki curaddr += sc->plength; 941 1.68 isaki if (curaddr >= sc->poffset + sc->pblksize) { 942 1.68 isaki dmamem_sync(sc->pmem, BUS_DMASYNC_POSTWRITE); 943 1.68 isaki sc->pintr(sc->pintrarg); 944 1.68 isaki sc->poffset += sc->pblksize; 945 1.68 isaki if (sc->poffset >= sc->plength) { 946 1.68 isaki sc->poffset -= sc->plength; 947 1.19 toshii } 948 1.68 isaki dmamem_sync(sc->pmem, BUS_DMASYNC_PREWRITE); 949 1.1 jdolecek } 950 1.68 isaki handled = 1; 951 1.1 jdolecek } 952 1.1 jdolecek 953 1.68 isaki if (sc->rintr && 954 1.68 isaki (ipr & (EMU_IPR_ADCBUFHALFFULL | EMU_IPR_ADCBUFFULL))) { 955 1.68 isaki char *src; 956 1.68 isaki char *dst; 957 1.68 isaki 958 1.68 isaki /* Record DMA buffer has just 2 blocks */ 959 1.68 isaki src = KERNADDR(sc->rmem); 960 1.68 isaki if (ipr & EMU_IPR_ADCBUFFULL) { 961 1.68 isaki /* 2nd block */ 962 1.68 isaki src += EMU_REC_DMABLKSIZE; 963 1.35 christos } 964 1.68 isaki dst = (char *)sc->rptr + sc->rcurrent; 965 1.1 jdolecek 966 1.68 isaki dmamem_sync(sc->rmem, BUS_DMASYNC_POSTREAD); 967 1.68 isaki memcpy(dst, src, EMU_REC_DMABLKSIZE); 968 1.68 isaki /* for next trans */ 969 1.68 isaki dmamem_sync(sc->rmem, BUS_DMASYNC_PREREAD); 970 1.68 isaki sc->rcurrent += EMU_REC_DMABLKSIZE; 971 1.68 isaki 972 1.68 isaki if (sc->rcurrent >= sc->roffset + sc->rblksize) { 973 1.68 isaki sc->rintr(sc->rintrarg); 974 1.68 isaki sc->roffset += sc->rblksize; 975 1.68 isaki if (sc->roffset >= sc->rlength) { 976 1.68 isaki sc->roffset = 0; 977 1.68 isaki sc->rcurrent = 0; 978 1.35 christos } 979 1.68 isaki } 980 1.35 christos 981 1.68 isaki handled = 1; 982 1.1 jdolecek } 983 1.1 jdolecek 984 1.68 isaki #if defined(EMUXKI_DEBUG) 985 1.68 isaki if (!handled) { 986 1.68 isaki char buf[1024]; 987 1.68 isaki snprintb(buf, sizeof(buf), 988 1.68 isaki "\20" 989 1.68 isaki "\x19""RATETRCHANGE" 990 1.68 isaki "\x18""FXDSP" 991 1.68 isaki "\x17""FORCEINT" 992 1.68 isaki "\x16""PCIERROR" 993 1.68 isaki "\x15""VOLINCR" 994 1.68 isaki "\x14""VOLDECR" 995 1.68 isaki "\x13""MUTE" 996 1.68 isaki "\x12""MICBUFFULL" 997 1.68 isaki "\x11""MICBUFHALFFULL" 998 1.68 isaki "\x10""ADCBUFFULL" 999 1.68 isaki "\x0f""ADCBUFHALFFULL" 1000 1.68 isaki "\x0e""EFXBUFFULL" 1001 1.68 isaki "\x0d""EFXBUFHALFFULL" 1002 1.68 isaki "\x0c""GPSPDIFSTCHANGE" 1003 1.68 isaki "\x0b""CDROMSTCHANGE" 1004 1.68 isaki /* INTERVALTIMER */ 1005 1.68 isaki "\x09""MIDITRANSBUFE" 1006 1.68 isaki "\x08""MIDIRECVBUFE" 1007 1.68 isaki "\x07""CHANNELLOOP" 1008 1.68 isaki , ipr); 1009 1.68 isaki DPRINTF("unexpected intr: %s\n", buf); 1010 1.40 kent 1011 1.68 isaki /* for debugging (must not handle if !DEBUG) */ 1012 1.68 isaki handled = 1; 1013 1.1 jdolecek } 1014 1.19 toshii #endif 1015 1.13 jdolecek 1016 1.68 isaki /* Reset interrupt bit */ 1017 1.68 isaki emuxki_writeio_4(sc, EMU_IPR, ipr); 1018 1.1 jdolecek 1019 1.60 jmcneill mutex_spin_exit(&sc->sc_intr_lock); 1020 1.60 jmcneill 1021 1.68 isaki /* Interrupt handler must return !=0 if handled */ 1022 1.68 isaki return handled; 1023 1.1 jdolecek } 1024 1.1 jdolecek 1025 1.1 jdolecek static int 1026 1.68 isaki emuxki_getdev(void *hdl, struct audio_device *dev) 1027 1.1 jdolecek { 1028 1.68 isaki struct emuxki_softc *sc = hdl; 1029 1.1 jdolecek 1030 1.68 isaki *dev = sc->sc_audv; 1031 1.40 kent return 0; 1032 1.1 jdolecek } 1033 1.1 jdolecek 1034 1.68 isaki static int 1035 1.68 isaki emuxki_set_port(void *hdl, mixer_ctrl_t *mctl) 1036 1.1 jdolecek { 1037 1.68 isaki struct emuxki_softc *sc = hdl; 1038 1.1 jdolecek 1039 1.68 isaki return sc->codecif->vtbl->mixer_set_port(sc->codecif, mctl); 1040 1.1 jdolecek } 1041 1.1 jdolecek 1042 1.1 jdolecek static int 1043 1.68 isaki emuxki_get_port(void *hdl, mixer_ctrl_t *mctl) 1044 1.1 jdolecek { 1045 1.68 isaki struct emuxki_softc *sc = hdl; 1046 1.1 jdolecek 1047 1.68 isaki return sc->codecif->vtbl->mixer_get_port(sc->codecif, mctl); 1048 1.1 jdolecek } 1049 1.1 jdolecek 1050 1.1 jdolecek static int 1051 1.68 isaki emuxki_query_devinfo(void *hdl, mixer_devinfo_t *minfo) 1052 1.1 jdolecek { 1053 1.68 isaki struct emuxki_softc *sc = hdl; 1054 1.1 jdolecek 1055 1.68 isaki return sc->codecif->vtbl->query_devinfo(sc->codecif, minfo); 1056 1.1 jdolecek } 1057 1.1 jdolecek 1058 1.68 isaki static void * 1059 1.68 isaki emuxki_allocm(void *hdl, int direction, size_t size) 1060 1.1 jdolecek { 1061 1.68 isaki struct emuxki_softc *sc = hdl; 1062 1.68 isaki 1063 1.68 isaki if (direction == AUMODE_PLAY) { 1064 1.68 isaki if (sc->pmem) { 1065 1.68 isaki panic("pmem already allocated\n"); 1066 1.68 isaki return NULL; 1067 1.8 jdolecek } 1068 1.68 isaki sc->pmem = dmamem_alloc(sc, size); 1069 1.68 isaki return KERNADDR(sc->pmem); 1070 1.68 isaki } else { 1071 1.68 isaki /* rmem is fixed size internal DMA buffer */ 1072 1.68 isaki if (sc->rmem) { 1073 1.68 isaki panic("rmem already allocated\n"); 1074 1.68 isaki return NULL; 1075 1.8 jdolecek } 1076 1.68 isaki /* rmem fixed size */ 1077 1.68 isaki sc->rmem = dmamem_alloc(sc, EMU_REC_DMASIZE); 1078 1.1 jdolecek 1079 1.68 isaki /* recording MI buffer is normal kmem, software trans. */ 1080 1.68 isaki sc->rptr = kmem_alloc(size, KM_SLEEP); 1081 1.68 isaki return sc->rptr; 1082 1.1 jdolecek } 1083 1.1 jdolecek } 1084 1.1 jdolecek 1085 1.68 isaki static void 1086 1.68 isaki emuxki_freem(void *hdl, void *ptr, size_t size) 1087 1.1 jdolecek { 1088 1.68 isaki struct emuxki_softc *sc = hdl; 1089 1.1 jdolecek 1090 1.68 isaki if (sc->pmem && ptr == KERNADDR(sc->pmem)) { 1091 1.68 isaki dmamem_free(sc->pmem); 1092 1.68 isaki sc->pmem = NULL; 1093 1.68 isaki } 1094 1.68 isaki if (sc->rmem && ptr == sc->rptr) { 1095 1.68 isaki dmamem_free(sc->rmem); 1096 1.68 isaki sc->rmem = NULL; 1097 1.68 isaki kmem_free(sc->rptr, size); 1098 1.68 isaki sc->rptr = NULL; 1099 1.68 isaki } 1100 1.1 jdolecek } 1101 1.1 jdolecek 1102 1.68 isaki /* 1103 1.68 isaki * blocksize rounding to EMU_PTESIZE. It is for easy to drive. 1104 1.68 isaki */ 1105 1.1 jdolecek static int 1106 1.68 isaki emuxki_round_blocksize(void *hdl, int blksize, 1107 1.68 isaki int mode, const audio_params_t* param) 1108 1.1 jdolecek { 1109 1.1 jdolecek 1110 1.68 isaki /* 1111 1.68 isaki * This is not necessary for recording, but symmetric for easy. 1112 1.68 isaki * For recording buffer/block size requirements of hardware, 1113 1.68 isaki * see EMU_RECBS_BUFSIZE_* 1114 1.68 isaki */ 1115 1.68 isaki if (blksize < EMU_PTESIZE) 1116 1.68 isaki blksize = EMU_PTESIZE; 1117 1.68 isaki return rounddown(blksize, EMU_PTESIZE); 1118 1.1 jdolecek } 1119 1.1 jdolecek 1120 1.68 isaki static size_t 1121 1.68 isaki emuxki_round_buffersize(void *hdl, int direction, size_t bsize) 1122 1.1 jdolecek { 1123 1.40 kent 1124 1.68 isaki /* This is not necessary for recording, but symmetric for easy */ 1125 1.68 isaki if (bsize < EMU_MINPTE * EMU_PTESIZE) { 1126 1.68 isaki bsize = EMU_MINPTE * EMU_PTESIZE; 1127 1.68 isaki } else if (bsize > EMU_MAXPTE * EMU_PTESIZE) { 1128 1.68 isaki bsize = EMU_MAXPTE * EMU_PTESIZE; 1129 1.68 isaki } 1130 1.68 isaki return roundup(bsize, EMU_PTESIZE); 1131 1.1 jdolecek } 1132 1.1 jdolecek 1133 1.1 jdolecek static int 1134 1.68 isaki emuxki_get_props(void *hdl) 1135 1.1 jdolecek { 1136 1.1 jdolecek 1137 1.70 isaki return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE | 1138 1.70 isaki AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1139 1.1 jdolecek } 1140 1.1 jdolecek 1141 1.1 jdolecek static int 1142 1.68 isaki emuxki_trigger_output(void *hdl, void *start, void *end, int blksize, 1143 1.68 isaki void (*intr)(void *), void *arg, const audio_params_t *params) 1144 1.1 jdolecek { 1145 1.68 isaki struct emuxki_softc *sc = hdl; 1146 1.68 isaki int npage; 1147 1.68 isaki uint32_t *kptb; 1148 1.68 isaki bus_addr_t dpmem; 1149 1.68 isaki int i; 1150 1.68 isaki uint32_t hwstart; 1151 1.68 isaki uint32_t hwend; 1152 1.68 isaki 1153 1.68 isaki if (sc->pmem == NULL) 1154 1.68 isaki panic("pmem == NULL\n"); 1155 1.68 isaki if (start != KERNADDR(sc->pmem)) 1156 1.68 isaki panic("start != KERNADDR(sc->pmem)\n"); 1157 1.68 isaki 1158 1.68 isaki sc->pframesize = 4; /* channels * bit / 8 = 2*16/8=4 */ 1159 1.68 isaki sc->pblksize = blksize; 1160 1.68 isaki sc->plength = (char *)end - (char *)start; 1161 1.68 isaki sc->poffset = 0; 1162 1.68 isaki npage = roundup(sc->plength, EMU_PTESIZE); 1163 1.1 jdolecek 1164 1.68 isaki kptb = KERNADDR(sc->ptb); 1165 1.68 isaki dpmem = DMAADDR(sc->pmem); 1166 1.68 isaki for (i = 0; i < npage; i++) { 1167 1.68 isaki kptb[i] = htole32(dpmem << 1); 1168 1.68 isaki dpmem += EMU_PTESIZE; 1169 1.68 isaki } 1170 1.68 isaki dmamem_sync(sc->ptb, BUS_DMASYNC_PREWRITE); 1171 1.1 jdolecek 1172 1.68 isaki hwstart = 0; 1173 1.68 isaki hwend = hwstart + sc->plength / sc->pframesize; 1174 1.1 jdolecek 1175 1.68 isaki sc->pintr = intr; 1176 1.68 isaki sc->pintrarg = arg; 1177 1.1 jdolecek 1178 1.68 isaki dmamem_sync(sc->pmem, BUS_DMASYNC_PREWRITE); 1179 1.1 jdolecek 1180 1.68 isaki emuxki_play_start(sc, 0, hwstart, hwend); 1181 1.68 isaki emuxki_play_start(sc, 1, hwstart, hwend); 1182 1.1 jdolecek 1183 1.68 isaki emuxki_timer_start(sc); 1184 1.1 jdolecek 1185 1.68 isaki return 0; 1186 1.1 jdolecek } 1187 1.1 jdolecek 1188 1.68 isaki /* 1189 1.68 isaki * Recording uses temporary buffer. Because it can use ADC_HALF/FULL 1190 1.68 isaki * interrupts and this method doesn't conflict with playback. 1191 1.68 isaki */ 1192 1.68 isaki 1193 1.19 toshii static int 1194 1.68 isaki emuxki_trigger_input(void *hdl, void *start, void *end, int blksize, 1195 1.68 isaki void (*intr)(void *), void *arg, const audio_params_t *params) 1196 1.19 toshii { 1197 1.68 isaki struct emuxki_softc *sc = hdl; 1198 1.19 toshii 1199 1.68 isaki if (sc->rmem == NULL) 1200 1.68 isaki panic("rmem == NULL\n"); 1201 1.68 isaki if (start != sc->rptr) 1202 1.68 isaki panic("start != sc->rptr\n"); 1203 1.68 isaki 1204 1.68 isaki sc->rframesize = 4; /* channels * bit / 8 = 2*16/8=4 */ 1205 1.68 isaki sc->rblksize = blksize; 1206 1.68 isaki sc->rlength = (char *)end - (char *)start; 1207 1.68 isaki sc->roffset = 0; 1208 1.68 isaki sc->rcurrent = 0; 1209 1.19 toshii 1210 1.68 isaki sc->rintr = intr; 1211 1.68 isaki sc->rintrarg = arg; 1212 1.19 toshii 1213 1.68 isaki /* 1214 1.68 isaki * Memo: 1215 1.68 isaki * recording source is selected by AC97 1216 1.68 isaki * AC97 input source routes to ADC by FX(DSP) 1217 1.68 isaki * 1218 1.68 isaki * Must keep following sequence order 1219 1.68 isaki */ 1220 1.40 kent 1221 1.68 isaki /* first, stop ADC */ 1222 1.68 isaki emuxki_write(sc, 0, EMU_ADCCR, 0); 1223 1.68 isaki emuxki_write(sc, 0, EMU_ADCBA, 0); 1224 1.68 isaki emuxki_write(sc, 0, EMU_ADCBS, 0); 1225 1.1 jdolecek 1226 1.68 isaki dmamem_sync(sc->rmem, BUS_DMASYNC_PREREAD); 1227 1.1 jdolecek 1228 1.68 isaki /* ADC interrupt enable */ 1229 1.68 isaki emuxki_writeio_4(sc, EMU_INTE, 1230 1.68 isaki emuxki_readio_4(sc, EMU_INTE) | 1231 1.68 isaki EMU_INTE_ADCBUFENABLE); 1232 1.68 isaki 1233 1.68 isaki /* ADC Enable */ 1234 1.68 isaki /* stereo, 48kHz, enable */ 1235 1.68 isaki emuxki_write(sc, 0, EMU_ADCCR, 1236 1.68 isaki X1(ADCCR_LCHANENABLE) | X1(ADCCR_RCHANENABLE)); 1237 1.68 isaki 1238 1.68 isaki /* ADC buffer address */ 1239 1.68 isaki emuxki_write(sc, 0, X1(ADCIDX), 0); 1240 1.68 isaki emuxki_write(sc, 0, EMU_ADCBA, DMAADDR(sc->rmem)); 1241 1.1 jdolecek 1242 1.68 isaki /* ADC buffer size, to start */ 1243 1.68 isaki emuxki_write(sc, 0, EMU_ADCBS, EMU_REC_BUFSIZE_RECBS); 1244 1.1 jdolecek 1245 1.68 isaki return 0; 1246 1.1 jdolecek } 1247 1.1 jdolecek 1248 1.68 isaki static void 1249 1.68 isaki emuxki_get_locks(void *hdl, kmutex_t **intr, kmutex_t **proc) 1250 1.1 jdolecek { 1251 1.68 isaki struct emuxki_softc *sc = hdl; 1252 1.1 jdolecek 1253 1.68 isaki *intr = &sc->sc_intr_lock; 1254 1.68 isaki *proc = &sc->sc_lock; 1255 1.1 jdolecek } 1256 1.1 jdolecek 1257 1.68 isaki /* 1258 1.68 isaki * AC97 1259 1.68 isaki */ 1260 1.1 jdolecek 1261 1.1 jdolecek static int 1262 1.68 isaki emuxki_ac97_init(struct emuxki_softc *sc) 1263 1.1 jdolecek { 1264 1.1 jdolecek 1265 1.68 isaki sc->hostif.arg = sc; 1266 1.68 isaki sc->hostif.attach = emuxki_ac97_attach; 1267 1.68 isaki sc->hostif.read = emuxki_ac97_read; 1268 1.68 isaki sc->hostif.write = emuxki_ac97_write; 1269 1.68 isaki sc->hostif.reset = emuxki_ac97_reset; 1270 1.68 isaki sc->hostif.flags = emuxki_ac97_flags; 1271 1.68 isaki return ac97_attach(&sc->hostif, sc->sc_dev, &sc->sc_lock); 1272 1.1 jdolecek } 1273 1.1 jdolecek 1274 1.1 jdolecek /* 1275 1.1 jdolecek * AC97 callbacks 1276 1.1 jdolecek */ 1277 1.1 jdolecek 1278 1.1 jdolecek static int 1279 1.68 isaki emuxki_ac97_attach(void *hdl, struct ac97_codec_if *codecif) 1280 1.1 jdolecek { 1281 1.68 isaki struct emuxki_softc *sc = hdl; 1282 1.1 jdolecek 1283 1.1 jdolecek sc->codecif = codecif; 1284 1.40 kent return 0; 1285 1.1 jdolecek } 1286 1.1 jdolecek 1287 1.1 jdolecek static int 1288 1.68 isaki emuxki_ac97_read(void *hdl, uint8_t reg, uint16_t *val) 1289 1.1 jdolecek { 1290 1.68 isaki struct emuxki_softc *sc = hdl; 1291 1.1 jdolecek 1292 1.68 isaki mutex_spin_enter(&sc->sc_index_lock); 1293 1.68 isaki emuxki_writeio_1(sc, EMU_AC97ADDR, reg); 1294 1.68 isaki *val = emuxki_readio_2(sc, EMU_AC97DATA); 1295 1.68 isaki mutex_spin_exit(&sc->sc_index_lock); 1296 1.1 jdolecek 1297 1.40 kent return 0; 1298 1.1 jdolecek } 1299 1.1 jdolecek 1300 1.1 jdolecek static int 1301 1.68 isaki emuxki_ac97_write(void *hdl, uint8_t reg, uint16_t val) 1302 1.1 jdolecek { 1303 1.68 isaki struct emuxki_softc *sc = hdl; 1304 1.1 jdolecek 1305 1.68 isaki mutex_spin_enter(&sc->sc_index_lock); 1306 1.68 isaki emuxki_writeio_1(sc, EMU_AC97ADDR, reg); 1307 1.68 isaki emuxki_writeio_2(sc, EMU_AC97DATA, val); 1308 1.68 isaki mutex_spin_exit(&sc->sc_index_lock); 1309 1.1 jdolecek 1310 1.40 kent return 0; 1311 1.1 jdolecek } 1312 1.1 jdolecek 1313 1.36 kent static int 1314 1.68 isaki emuxki_ac97_reset(void *hdl) 1315 1.1 jdolecek { 1316 1.40 kent 1317 1.36 kent return 0; 1318 1.6 jdolecek } 1319 1.6 jdolecek 1320 1.68 isaki static enum ac97_host_flags 1321 1.68 isaki emuxki_ac97_flags(void *hdl) 1322 1.6 jdolecek { 1323 1.40 kent 1324 1.40 kent return AC97_HOST_SWAPPED_CHANNELS; 1325 1.1 jdolecek } 1326 1.73 khorben 1327 1.73 khorben MODULE(MODULE_CLASS_DRIVER, emuxki, "pci,audio"); 1328 1.73 khorben 1329 1.73 khorben #ifdef _MODULE 1330 1.73 khorben #include "ioconf.c" 1331 1.73 khorben #endif 1332 1.73 khorben 1333 1.73 khorben static int 1334 1.73 khorben emuxki_modcmd(modcmd_t cmd, void *opaque) 1335 1.73 khorben { 1336 1.73 khorben int error = 0; 1337 1.73 khorben 1338 1.73 khorben switch (cmd) { 1339 1.73 khorben case MODULE_CMD_INIT: 1340 1.73 khorben #ifdef _MODULE 1341 1.73 khorben error = config_init_component(cfdriver_ioconf_emuxki, 1342 1.73 khorben cfattach_ioconf_emuxki, cfdata_ioconf_emuxki); 1343 1.73 khorben #endif 1344 1.73 khorben return error; 1345 1.73 khorben case MODULE_CMD_FINI: 1346 1.73 khorben #ifdef _MODULE 1347 1.73 khorben error = config_fini_component(cfdriver_ioconf_emuxki, 1348 1.73 khorben cfattach_ioconf_emuxki, cfdata_ioconf_emuxki); 1349 1.73 khorben #endif 1350 1.73 khorben return error; 1351 1.73 khorben default: 1352 1.73 khorben return ENOTTY; 1353 1.73 khorben } 1354 1.73 khorben } 1355