1 1.60 andvar /* $NetBSD: autri.c,v 1.60 2022/01/25 22:01:35 andvar Exp $ */ 2 1.1 someya 3 1.1 someya /* 4 1.1 someya * Copyright (c) 2001 SOMEYA Yoshihiko and KUROSAWA Takahiro. 5 1.1 someya * All rights reserved. 6 1.1 someya * 7 1.1 someya * Redistribution and use in source and binary forms, with or without 8 1.1 someya * modification, are permitted provided that the following conditions 9 1.1 someya * are met: 10 1.1 someya * 1. Redistributions of source code must retain the above copyright 11 1.1 someya * notice, this list of conditions and the following disclaimer. 12 1.1 someya * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 someya * notice, this list of conditions and the following disclaimer in the 14 1.1 someya * documentation and/or other materials provided with the distribution. 15 1.1 someya * 16 1.1 someya * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 someya * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 someya * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 someya * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 someya * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 someya * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 someya * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 someya * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 someya * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.1 someya * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.1 someya */ 27 1.1 someya 28 1.24 kent /* 29 1.1 someya * Trident 4DWAVE-DX/NX, SiS 7018, ALi M5451 Sound Driver 30 1.24 kent * 31 1.1 someya * The register information is taken from the ALSA driver. 32 1.1 someya * 33 1.1 someya * Documentation links: 34 1.1 someya * - ftp://ftp.alsa-project.org/pub/manuals/trident/ 35 1.1 someya */ 36 1.16 lukem 37 1.16 lukem #include <sys/cdefs.h> 38 1.60 andvar __KERNEL_RCSID(0, "$NetBSD: autri.c,v 1.60 2022/01/25 22:01:35 andvar Exp $"); 39 1.1 someya 40 1.1 someya #include "midi.h" 41 1.1 someya 42 1.1 someya #include <sys/param.h> 43 1.1 someya #include <sys/systm.h> 44 1.1 someya #include <sys/kernel.h> 45 1.1 someya #include <sys/fcntl.h> 46 1.47 jmcneill #include <sys/kmem.h> 47 1.1 someya #include <sys/device.h> 48 1.1 someya #include <sys/proc.h> 49 1.47 jmcneill #include <sys/audioio.h> 50 1.47 jmcneill #include <sys/bus.h> 51 1.47 jmcneill #include <sys/intr.h> 52 1.1 someya 53 1.57 isaki #include <dev/audio/audio_if.h> 54 1.1 someya #include <dev/midi_if.h> 55 1.47 jmcneill 56 1.1 someya #include <dev/ic/ac97reg.h> 57 1.1 someya #include <dev/ic/ac97var.h> 58 1.1 someya #include <dev/ic/mpuvar.h> 59 1.1 someya 60 1.47 jmcneill #include <dev/pci/pcidevs.h> 61 1.47 jmcneill #include <dev/pci/pcireg.h> 62 1.47 jmcneill #include <dev/pci/pcivar.h> 63 1.1 someya #include <dev/pci/autrireg.h> 64 1.1 someya #include <dev/pci/autrivar.h> 65 1.1 someya 66 1.1 someya #ifdef AUDIO_DEBUG 67 1.1 someya # define DPRINTF(x) if (autridebug) printf x 68 1.1 someya # define DPRINTFN(n,x) if (autridebug > (n)) printf x 69 1.1 someya int autridebug = 0; 70 1.1 someya #else 71 1.1 someya # define DPRINTF(x) 72 1.1 someya # define DPRINTFN(n,x) 73 1.1 someya #endif 74 1.1 someya 75 1.26 thorpej static int autri_intr(void *); 76 1.1 someya 77 1.1 someya #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) 78 1.1 someya #define KERNADDR(p) ((void *)((p)->addr)) 79 1.1 someya 80 1.26 thorpej static int autri_allocmem(struct autri_softc *, size_t, 81 1.26 thorpej size_t, struct autri_dma *); 82 1.26 thorpej static int autri_freemem(struct autri_softc *, struct autri_dma *); 83 1.1 someya 84 1.1 someya #define TWRITE1(sc, r, x) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x)) 85 1.1 someya #define TWRITE2(sc, r, x) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x)) 86 1.1 someya #define TWRITE4(sc, r, x) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x)) 87 1.1 someya #define TREAD1(sc, r) bus_space_read_1((sc)->memt, (sc)->memh, (r)) 88 1.1 someya #define TREAD2(sc, r) bus_space_read_2((sc)->memt, (sc)->memh, (r)) 89 1.1 someya #define TREAD4(sc, r) bus_space_read_4((sc)->memt, (sc)->memh, (r)) 90 1.1 someya 91 1.26 thorpej static int autri_attach_codec(void *, struct ac97_codec_if *); 92 1.26 thorpej static int autri_read_codec(void *, uint8_t, uint16_t *); 93 1.26 thorpej static int autri_write_codec(void *, uint8_t, uint16_t); 94 1.26 thorpej static int autri_reset_codec(void *); 95 1.26 thorpej static enum ac97_host_flags autri_flags_codec(void *); 96 1.1 someya 97 1.46 dyoung static bool autri_resume(device_t, const pmf_qual_t *); 98 1.24 kent static int autri_init(void *); 99 1.3 augustss static struct autri_dma *autri_find_dma(struct autri_softc *, void *); 100 1.24 kent static void autri_setup_channel(struct autri_softc *, int, 101 1.23 kent const audio_params_t *param); 102 1.24 kent static void autri_enable_interrupt(struct autri_softc *, int); 103 1.24 kent static void autri_disable_interrupt(struct autri_softc *, int); 104 1.24 kent static void autri_startch(struct autri_softc *, int, int); 105 1.24 kent static void autri_stopch(struct autri_softc *, int, int); 106 1.24 kent static void autri_enable_loop_interrupt(void *); 107 1.1 someya #if 0 108 1.24 kent static void autri_disable_loop_interrupt(void *); 109 1.1 someya #endif 110 1.1 someya 111 1.26 thorpej static int autri_open(void *, int); 112 1.57 isaki static int autri_query_format(void *, audio_format_query_t *); 113 1.57 isaki static int autri_set_format(void *, int, 114 1.57 isaki const audio_params_t *, const audio_params_t *, 115 1.57 isaki audio_filter_reg_t *, audio_filter_reg_t *); 116 1.26 thorpej static int autri_trigger_output(void *, void *, void *, int, 117 1.26 thorpej void (*)(void *), void *, 118 1.26 thorpej const audio_params_t *); 119 1.26 thorpej static int autri_trigger_input(void *, void *, void *, int, 120 1.26 thorpej void (*)(void *), void *, 121 1.26 thorpej const audio_params_t *); 122 1.26 thorpej static int autri_halt_output(void *); 123 1.26 thorpej static int autri_halt_input(void *); 124 1.26 thorpej static int autri_getdev(void *, struct audio_device *); 125 1.26 thorpej static int autri_mixer_set_port(void *, mixer_ctrl_t *); 126 1.26 thorpej static int autri_mixer_get_port(void *, mixer_ctrl_t *); 127 1.47 jmcneill static void* autri_malloc(void *, int, size_t); 128 1.47 jmcneill static void autri_free(void *, void *, size_t); 129 1.26 thorpej static int autri_get_props(void *); 130 1.26 thorpej static int autri_query_devinfo(void *, mixer_devinfo_t *); 131 1.47 jmcneill static void autri_get_locks(void *, kmutex_t **, kmutex_t **); 132 1.1 someya 133 1.21 yamt static const struct audio_hw_if autri_hw_if = { 134 1.56 isaki .open = autri_open, 135 1.57 isaki .query_format = autri_query_format, 136 1.57 isaki .set_format = autri_set_format, 137 1.56 isaki .halt_output = autri_halt_output, 138 1.56 isaki .halt_input = autri_halt_input, 139 1.56 isaki .getdev = autri_getdev, 140 1.56 isaki .set_port = autri_mixer_set_port, 141 1.56 isaki .get_port = autri_mixer_get_port, 142 1.56 isaki .query_devinfo = autri_query_devinfo, 143 1.56 isaki .allocm = autri_malloc, 144 1.56 isaki .freem = autri_free, 145 1.56 isaki .get_props = autri_get_props, 146 1.56 isaki .trigger_output = autri_trigger_output, 147 1.56 isaki .trigger_input = autri_trigger_input, 148 1.56 isaki .get_locks = autri_get_locks, 149 1.1 someya }; 150 1.1 someya 151 1.1 someya #if NMIDI > 0 152 1.26 thorpej static void autri_midi_close(void *); 153 1.26 thorpej static void autri_midi_getinfo(void *, struct midi_info *); 154 1.26 thorpej static int autri_midi_open(void *, int, void (*)(void *, int), 155 1.1 someya void (*)(void *), void *); 156 1.26 thorpej static int autri_midi_output(void *, int); 157 1.1 someya 158 1.26 thorpej static const struct midi_hw_if autri_midi_hw_if = { 159 1.1 someya autri_midi_open, 160 1.1 someya autri_midi_close, 161 1.1 someya autri_midi_output, 162 1.1 someya autri_midi_getinfo, 163 1.1 someya NULL, /* ioctl */ 164 1.47 jmcneill autri_get_locks, 165 1.1 someya }; 166 1.1 someya #endif 167 1.1 someya 168 1.57 isaki /* 169 1.57 isaki * The hardware actually supports frequencies other than 48kHz. But 170 1.57 isaki * 48kHz is the basis frequency of this hardware and it's enough. 171 1.57 isaki */ 172 1.57 isaki static const struct audio_format autri_formats[] = { 173 1.57 isaki { 174 1.57 isaki .mode = AUMODE_PLAY | AUMODE_RECORD, 175 1.57 isaki .encoding = AUDIO_ENCODING_SLINEAR_LE, 176 1.57 isaki .validbits = 16, 177 1.57 isaki .precision = 16, 178 1.57 isaki .channels = 2, 179 1.57 isaki .channel_mask = AUFMT_STEREO, 180 1.57 isaki .frequency_type = 1, 181 1.57 isaki .frequency = { 48000 }, 182 1.57 isaki }, 183 1.23 kent }; 184 1.57 isaki #define AUTRI_NFORMATS __arraycount(autri_formats) 185 1.23 kent 186 1.1 someya /* 187 1.1 someya * register set/clear bit 188 1.1 someya */ 189 1.52 joerg #if NMIDI > 0 190 1.28 perry static inline void 191 1.3 augustss autri_reg_set_1(struct autri_softc *sc, int no, uint8_t mask) 192 1.1 someya { 193 1.1 someya bus_space_write_1(sc->memt, sc->memh, no, 194 1.1 someya (bus_space_read_1(sc->memt, sc->memh, no) | mask)); 195 1.1 someya } 196 1.1 someya 197 1.28 perry static inline void 198 1.3 augustss autri_reg_clear_1(struct autri_softc *sc, int no, uint8_t mask) 199 1.1 someya { 200 1.1 someya bus_space_write_1(sc->memt, sc->memh, no, 201 1.1 someya (bus_space_read_1(sc->memt, sc->memh, no) & ~mask)); 202 1.1 someya } 203 1.52 joerg #endif 204 1.1 someya 205 1.28 perry static inline void 206 1.3 augustss autri_reg_set_4(struct autri_softc *sc, int no, uint32_t mask) 207 1.1 someya { 208 1.1 someya bus_space_write_4(sc->memt, sc->memh, no, 209 1.1 someya (bus_space_read_4(sc->memt, sc->memh, no) | mask)); 210 1.1 someya } 211 1.1 someya 212 1.28 perry static inline void 213 1.3 augustss autri_reg_clear_4(struct autri_softc *sc, int no, uint32_t mask) 214 1.1 someya { 215 1.1 someya bus_space_write_4(sc->memt, sc->memh, no, 216 1.1 someya (bus_space_read_4(sc->memt, sc->memh, no) & ~mask)); 217 1.1 someya } 218 1.1 someya 219 1.1 someya /* 220 1.1 someya * AC'97 codec 221 1.1 someya */ 222 1.26 thorpej static int 223 1.3 augustss autri_attach_codec(void *sc_, struct ac97_codec_if *codec_if) 224 1.1 someya { 225 1.24 kent struct autri_codec_softc *sc; 226 1.1 someya 227 1.1 someya DPRINTF(("autri_attach_codec()\n")); 228 1.24 kent sc = sc_; 229 1.1 someya sc->codec_if = codec_if; 230 1.1 someya return 0; 231 1.1 someya } 232 1.1 someya 233 1.26 thorpej static int 234 1.24 kent autri_read_codec(void *sc_, uint8_t index, uint16_t *data) 235 1.1 someya { 236 1.24 kent struct autri_codec_softc *codec; 237 1.24 kent struct autri_softc *sc; 238 1.24 kent uint32_t status, addr, cmd, busy; 239 1.24 kent uint16_t count; 240 1.1 someya 241 1.24 kent codec = sc_; 242 1.24 kent sc = codec->sc; 243 1.1 someya /*DPRINTF(("sc->sc->type : 0x%X",sc->sc->type));*/ 244 1.1 someya 245 1.1 someya switch (sc->sc_devid) { 246 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_DX: 247 1.1 someya addr = AUTRI_DX_ACR1; 248 1.1 someya cmd = AUTRI_DX_ACR1_CMD_READ; 249 1.1 someya busy = AUTRI_DX_ACR1_BUSY_READ; 250 1.1 someya break; 251 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_NX: 252 1.1 someya addr = AUTRI_NX_ACR2; 253 1.1 someya cmd = AUTRI_NX_ACR2_CMD_READ; 254 1.1 someya busy = AUTRI_NX_ACR2_BUSY_READ | AUTRI_NX_ACR2_RECV_WAIT; 255 1.1 someya break; 256 1.1 someya case AUTRI_DEVICE_ID_SIS_7018: 257 1.1 someya addr = AUTRI_SIS_ACRD; 258 1.1 someya cmd = AUTRI_SIS_ACRD_CMD_READ; 259 1.1 someya busy = AUTRI_SIS_ACRD_BUSY_READ | AUTRI_SIS_ACRD_AUDIO_BUSY; 260 1.1 someya break; 261 1.1 someya case AUTRI_DEVICE_ID_ALI_M5451: 262 1.1 someya if (sc->sc_revision > 0x01) 263 1.1 someya addr = AUTRI_ALI_ACWR; 264 1.1 someya else 265 1.1 someya addr = AUTRI_ALI_ACRD; 266 1.1 someya cmd = AUTRI_ALI_ACRD_CMD_READ; 267 1.1 someya busy = AUTRI_ALI_ACRD_BUSY_READ; 268 1.1 someya break; 269 1.1 someya default: 270 1.1 someya printf("%s: autri_read_codec : unknown device\n", 271 1.50 martin device_xname(sc->sc_dev)); 272 1.1 someya return -1; 273 1.1 someya } 274 1.1 someya 275 1.1 someya /* wait for 'Ready to Read' */ 276 1.1 someya for (count=0; count<0xffff; count++) { 277 1.1 someya if ((TREAD4(sc, addr) & busy) == 0) 278 1.1 someya break; 279 1.1 someya } 280 1.1 someya 281 1.1 someya if (count == 0xffff) { 282 1.1 someya printf("%s: Codec timeout. Busy reading AC'97 codec.\n", 283 1.50 martin device_xname(sc->sc_dev)); 284 1.1 someya return -1; 285 1.1 someya } 286 1.1 someya 287 1.1 someya /* send Read Command to AC'97 */ 288 1.1 someya TWRITE4(sc, addr, (index & 0x7f) | cmd); 289 1.1 someya 290 1.60 andvar /* wait for 'Returned data is available' */ 291 1.1 someya for (count=0; count<0xffff; count++) { 292 1.1 someya status = TREAD4(sc, addr); 293 1.1 someya if ((status & busy) == 0) 294 1.1 someya break; 295 1.1 someya } 296 1.1 someya 297 1.1 someya if (count == 0xffff) { 298 1.1 someya printf("%s: Codec timeout. Busy reading AC'97 codec.\n", 299 1.50 martin device_xname(sc->sc_dev)); 300 1.1 someya return -1; 301 1.1 someya } 302 1.1 someya 303 1.1 someya *data = (status >> 16) & 0x0000ffff; 304 1.1 someya /*DPRINTF(("autri_read_codec(0x%X) return 0x%X\n",reg,*data));*/ 305 1.1 someya return 0; 306 1.1 someya } 307 1.1 someya 308 1.26 thorpej static int 309 1.24 kent autri_write_codec(void *sc_, uint8_t index, uint16_t data) 310 1.1 someya { 311 1.24 kent struct autri_codec_softc *codec; 312 1.24 kent struct autri_softc *sc; 313 1.24 kent uint32_t addr, cmd, busy; 314 1.24 kent uint16_t count; 315 1.1 someya 316 1.24 kent codec = sc_; 317 1.24 kent sc = codec->sc; 318 1.1 someya /*DPRINTF(("autri_write_codec(0x%X,0x%X)\n",index,data));*/ 319 1.1 someya 320 1.1 someya switch (sc->sc_devid) { 321 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_DX: 322 1.1 someya addr = AUTRI_DX_ACR0; 323 1.1 someya cmd = AUTRI_DX_ACR0_CMD_WRITE; 324 1.1 someya busy = AUTRI_DX_ACR0_BUSY_WRITE; 325 1.1 someya break; 326 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_NX: 327 1.1 someya addr = AUTRI_NX_ACR1; 328 1.1 someya cmd = AUTRI_NX_ACR1_CMD_WRITE; 329 1.1 someya busy = AUTRI_NX_ACR1_BUSY_WRITE; 330 1.1 someya break; 331 1.1 someya case AUTRI_DEVICE_ID_SIS_7018: 332 1.1 someya addr = AUTRI_SIS_ACWR; 333 1.1 someya cmd = AUTRI_SIS_ACWR_CMD_WRITE; 334 1.1 someya busy = AUTRI_SIS_ACWR_BUSY_WRITE | AUTRI_SIS_ACWR_AUDIO_BUSY; 335 1.1 someya break; 336 1.1 someya case AUTRI_DEVICE_ID_ALI_M5451: 337 1.1 someya addr = AUTRI_ALI_ACWR; 338 1.1 someya cmd = AUTRI_ALI_ACWR_CMD_WRITE; 339 1.1 someya if (sc->sc_revision > 0x01) 340 1.1 someya cmd |= 0x0100; 341 1.1 someya busy = AUTRI_ALI_ACWR_BUSY_WRITE; 342 1.1 someya break; 343 1.1 someya default: 344 1.1 someya printf("%s: autri_write_codec : unknown device.\n", 345 1.50 martin device_xname(sc->sc_dev)); 346 1.1 someya return -1; 347 1.1 someya } 348 1.1 someya 349 1.1 someya /* wait for 'Ready to Write' */ 350 1.1 someya for (count=0; count<0xffff; count++) { 351 1.1 someya if ((TREAD4(sc, addr) & busy) == 0) 352 1.1 someya break; 353 1.1 someya } 354 1.1 someya 355 1.1 someya if (count == 0xffff) { 356 1.1 someya printf("%s: Codec timeout. Busy writing AC'97 codec\n", 357 1.50 martin device_xname(sc->sc_dev)); 358 1.1 someya return -1; 359 1.1 someya } 360 1.1 someya 361 1.1 someya /* send Write Command to AC'97 */ 362 1.1 someya TWRITE4(sc, addr, (data << 16) | (index & 0x7f) | cmd); 363 1.1 someya 364 1.1 someya return 0; 365 1.1 someya } 366 1.1 someya 367 1.26 thorpej static int 368 1.3 augustss autri_reset_codec(void *sc_) 369 1.1 someya { 370 1.24 kent struct autri_codec_softc *codec; 371 1.24 kent struct autri_softc *sc; 372 1.24 kent uint32_t reg, ready; 373 1.24 kent int addr, count; 374 1.24 kent 375 1.24 kent codec = sc_; 376 1.24 kent sc = codec->sc; 377 1.24 kent count = 200; 378 1.24 kent DPRINTF(("autri_reset_codec(codec=%p,sc=%p)\n", codec, sc)); 379 1.24 kent DPRINTF(("sc->sc_devid=%X\n", sc->sc_devid)); 380 1.1 someya 381 1.4 eeh switch (sc->sc_devid) { 382 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_DX: 383 1.1 someya /* warm reset AC'97 codec */ 384 1.1 someya autri_reg_set_4(sc, AUTRI_DX_ACR2, 1); 385 1.1 someya delay(100); 386 1.1 someya /* release reset */ 387 1.1 someya autri_reg_clear_4(sc, AUTRI_DX_ACR2, 1); 388 1.1 someya delay(100); 389 1.1 someya 390 1.1 someya addr = AUTRI_DX_ACR2; 391 1.1 someya ready = AUTRI_DX_ACR2_CODEC_READY; 392 1.1 someya break; 393 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_NX: 394 1.1 someya /* warm reset AC'97 codec */ 395 1.1 someya autri_reg_set_4(sc, AUTRI_NX_ACR0, 1); 396 1.1 someya delay(100); 397 1.1 someya /* release reset */ 398 1.1 someya autri_reg_clear_4(sc, AUTRI_NX_ACR0, 1); 399 1.1 someya delay(100); 400 1.1 someya 401 1.1 someya addr = AUTRI_NX_ACR0; 402 1.1 someya ready = AUTRI_NX_ACR0_CODEC_READY; 403 1.1 someya break; 404 1.1 someya case AUTRI_DEVICE_ID_SIS_7018: 405 1.5 someya /* cold reset AC'97 codec */ 406 1.5 someya autri_reg_set_4(sc, AUTRI_SIS_SCTRL, 2); 407 1.5 someya delay(1000); 408 1.1 someya /* release reset (warm & cold) */ 409 1.1 someya autri_reg_clear_4(sc, AUTRI_SIS_SCTRL, 3); 410 1.5 someya delay(2000); 411 1.1 someya 412 1.1 someya addr = AUTRI_SIS_SCTRL; 413 1.1 someya ready = AUTRI_SIS_SCTRL_CODEC_READY; 414 1.1 someya break; 415 1.1 someya case AUTRI_DEVICE_ID_ALI_M5451: 416 1.1 someya /* warm reset AC'97 codec */ 417 1.1 someya autri_reg_set_4(sc, AUTRI_ALI_SCTRL, 1); 418 1.1 someya delay(100); 419 1.1 someya /* release reset (warm & cold) */ 420 1.1 someya autri_reg_clear_4(sc, AUTRI_ALI_SCTRL, 3); 421 1.1 someya delay(100); 422 1.1 someya 423 1.1 someya addr = AUTRI_ALI_SCTRL; 424 1.1 someya ready = AUTRI_ALI_SCTRL_CODEC_READY; 425 1.17 christos break; 426 1.17 christos default: 427 1.18 mycroft printf("%s: autri_reset_codec : unknown device\n", 428 1.50 martin device_xname(sc->sc_dev)); 429 1.20 kent return EOPNOTSUPP; 430 1.1 someya } 431 1.1 someya 432 1.1 someya /* wait for 'Codec Ready' */ 433 1.1 someya while (count--) { 434 1.1 someya reg = TREAD4(sc, addr); 435 1.1 someya if (reg & ready) 436 1.1 someya break; 437 1.1 someya delay(1000); 438 1.1 someya } 439 1.1 someya 440 1.20 kent if (count == 0) { 441 1.1 someya printf("%s: Codec timeout. AC'97 is not ready for operation.\n", 442 1.50 martin device_xname(sc->sc_dev)); 443 1.20 kent return ETIMEDOUT; 444 1.20 kent } 445 1.20 kent return 0; 446 1.1 someya } 447 1.1 someya 448 1.26 thorpej static enum ac97_host_flags 449 1.34 christos autri_flags_codec(void *sc) 450 1.9 someya { 451 1.9 someya return AC97_HOST_DONT_READ; 452 1.9 someya } 453 1.9 someya 454 1.1 someya /* 455 1.1 someya * 456 1.1 someya */ 457 1.1 someya 458 1.26 thorpej static int 459 1.42 cegger autri_match(device_t parent, cfdata_t match, void *aux) 460 1.1 someya { 461 1.24 kent struct pci_attach_args *pa; 462 1.1 someya 463 1.24 kent pa = (struct pci_attach_args *)aux; 464 1.1 someya switch (PCI_VENDOR(pa->pa_id)) { 465 1.1 someya case PCI_VENDOR_TRIDENT: 466 1.1 someya switch (PCI_PRODUCT(pa->pa_id)) { 467 1.1 someya case PCI_PRODUCT_TRIDENT_4DWAVE_DX: 468 1.29 garbled /* 469 1.29 garbled * IBM makes a pcn network card and improperly 470 1.29 garbled * sets the vendor and product ID's. Avoid matching. 471 1.29 garbled */ 472 1.29 garbled if (PCI_CLASS(pa->pa_class) == PCI_CLASS_NETWORK) 473 1.29 garbled return 0; 474 1.29 garbled /* FALLTHROUGH */ 475 1.1 someya case PCI_PRODUCT_TRIDENT_4DWAVE_NX: 476 1.1 someya return 1; 477 1.1 someya } 478 1.1 someya break; 479 1.1 someya case PCI_VENDOR_SIS: 480 1.1 someya switch (PCI_PRODUCT(pa->pa_id)) { 481 1.1 someya case PCI_PRODUCT_SIS_7018: 482 1.1 someya return 1; 483 1.1 someya } 484 1.1 someya break; 485 1.1 someya case PCI_VENDOR_ALI: 486 1.1 someya switch (PCI_PRODUCT(pa->pa_id)) { 487 1.1 someya case PCI_PRODUCT_ALI_M5451: 488 1.1 someya return 1; 489 1.1 someya } 490 1.1 someya break; 491 1.1 someya } 492 1.1 someya 493 1.1 someya return 0; 494 1.1 someya } 495 1.1 someya 496 1.26 thorpej static void 497 1.42 cegger autri_attach(device_t parent, device_t self, void *aux) 498 1.1 someya { 499 1.24 kent struct autri_softc *sc; 500 1.24 kent struct pci_attach_args *pa; 501 1.24 kent pci_chipset_tag_t pc; 502 1.1 someya struct autri_codec_softc *codec; 503 1.1 someya pci_intr_handle_t ih; 504 1.1 someya char const *intrstr; 505 1.22 kent int r; 506 1.24 kent uint32_t reg; 507 1.51 christos char intrbuf[PCI_INTRSTR_LEN]; 508 1.1 someya 509 1.43 cegger sc = device_private(self); 510 1.50 martin sc->sc_dev = self; 511 1.24 kent pa = (struct pci_attach_args *)aux; 512 1.24 kent pc = pa->pa_pc; 513 1.13 thorpej 514 1.1 someya sc->sc_devid = pa->pa_id; 515 1.1 someya sc->sc_class = pa->pa_class; 516 1.1 someya 517 1.49 drochner pci_aprint_devinfo(pa, "Audio controller"); 518 1.1 someya sc->sc_revision = PCI_REVISION(pa->pa_class); 519 1.1 someya 520 1.1 someya /* map register to memory */ 521 1.1 someya if (pci_mapreg_map(pa, AUTRI_PCI_MEMORY_BASE, 522 1.1 someya PCI_MAPREG_TYPE_MEM, 0, &sc->memt, &sc->memh, NULL, NULL)) { 523 1.50 martin aprint_error_dev(sc->sc_dev, "can't map memory space\n"); 524 1.1 someya return; 525 1.1 someya } 526 1.1 someya 527 1.47 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 528 1.48 mrg mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); 529 1.47 jmcneill 530 1.1 someya /* map and establish the interrupt */ 531 1.1 someya if (pci_intr_map(pa, &ih)) { 532 1.50 martin aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n"); 533 1.1 someya return; 534 1.1 someya } 535 1.51 christos intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); 536 1.54 msaitoh sc->sc_ih = pci_intr_establish_xname(pc, ih, IPL_AUDIO, autri_intr, 537 1.54 msaitoh sc, device_xname(self)); 538 1.1 someya if (sc->sc_ih == NULL) { 539 1.50 martin aprint_error_dev(sc->sc_dev, "couldn't establish interrupt"); 540 1.1 someya if (intrstr != NULL) 541 1.44 njoly aprint_error(" at %s", intrstr); 542 1.44 njoly aprint_error("\n"); 543 1.1 someya return; 544 1.1 someya } 545 1.50 martin aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); 546 1.1 someya 547 1.1 someya sc->sc_dmatag = pa->pa_dmat; 548 1.1 someya sc->sc_pc = pc; 549 1.1 someya sc->sc_pt = pa->pa_tag; 550 1.1 someya 551 1.1 someya /* enable the device */ 552 1.1 someya reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 553 1.1 someya reg |= (PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE); 554 1.1 someya pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg); 555 1.1 someya 556 1.1 someya /* initialize the device */ 557 1.1 someya autri_init(sc); 558 1.1 someya 559 1.1 someya /* attach AC'97 codec */ 560 1.1 someya codec = &sc->sc_codec; 561 1.1 someya codec->sc = sc; 562 1.1 someya 563 1.1 someya codec->host_if.arg = codec; 564 1.1 someya codec->host_if.attach = autri_attach_codec; 565 1.1 someya codec->host_if.reset = autri_reset_codec; 566 1.1 someya codec->host_if.read = autri_read_codec; 567 1.1 someya codec->host_if.write = autri_write_codec; 568 1.9 someya codec->host_if.flags = autri_flags_codec; 569 1.1 someya 570 1.47 jmcneill r = ac97_attach(&codec->host_if, self, &sc->sc_lock); 571 1.47 jmcneill if (r != 0) { 572 1.54 msaitoh aprint_error_dev(self, "can't attach codec (error 0x%X)\n", r); 573 1.1 someya return; 574 1.1 someya } 575 1.1 someya 576 1.36 jmcneill if (!pmf_device_register(self, NULL, autri_resume)) 577 1.36 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 578 1.36 jmcneill 579 1.50 martin audio_attach_mi(&autri_hw_if, sc, sc->sc_dev); 580 1.1 someya 581 1.1 someya #if NMIDI > 0 582 1.50 martin midi_attach_mi(&autri_midi_hw_if, sc, sc->sc_dev); 583 1.1 someya #endif 584 1.1 someya } 585 1.1 someya 586 1.50 martin CFATTACH_DECL_NEW(autri, sizeof(struct autri_softc), 587 1.26 thorpej autri_match, autri_attach, NULL, NULL); 588 1.26 thorpej 589 1.36 jmcneill static bool 590 1.46 dyoung autri_resume(device_t dv, const pmf_qual_t *qual) 591 1.1 someya { 592 1.36 jmcneill struct autri_softc *sc = device_private(dv); 593 1.36 jmcneill 594 1.47 jmcneill mutex_enter(&sc->sc_lock); 595 1.47 jmcneill mutex_spin_enter(&sc->sc_intr_lock); 596 1.36 jmcneill autri_init(sc); 597 1.47 jmcneill mutex_spin_exit(&sc->sc_intr_lock); 598 1.36 jmcneill (sc->sc_codec.codec_if->vtbl->restore_ports)(sc->sc_codec.codec_if); 599 1.47 jmcneill mutex_exit(&sc->sc_lock); 600 1.1 someya 601 1.36 jmcneill return true; 602 1.1 someya } 603 1.1 someya 604 1.26 thorpej static int 605 1.3 augustss autri_init(void *sc_) 606 1.1 someya { 607 1.24 kent struct autri_softc *sc; 608 1.24 kent uint32_t reg; 609 1.24 kent pci_chipset_tag_t pc; 610 1.24 kent pcitag_t pt; 611 1.24 kent 612 1.24 kent sc = sc_; 613 1.24 kent pc = sc->sc_pc; 614 1.24 kent pt = sc->sc_pt; 615 1.1 someya DPRINTF(("in autri_init()\n")); 616 1.1 someya DPRINTFN(5,("pci_conf_read(0x40) : 0x%X\n",pci_conf_read(pc,pt,0x40))); 617 1.1 someya DPRINTFN(5,("pci_conf_read(0x44) : 0x%X\n",pci_conf_read(pc,pt,0x44))); 618 1.1 someya 619 1.1 someya switch (sc->sc_devid) { 620 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_DX: 621 1.1 someya /* disable Legacy Control */ 622 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0); 623 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 624 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000); 625 1.1 someya delay(100); 626 1.1 someya /* audio engine reset */ 627 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 628 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00040000); 629 1.1 someya delay(100); 630 1.1 someya /* release reset */ 631 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 632 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000); 633 1.1 someya delay(100); 634 1.1 someya /* DAC on */ 635 1.1 someya autri_reg_set_4(sc,AUTRI_DX_ACR2,0x02); 636 1.1 someya break; 637 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_NX: 638 1.1 someya /* disable Legacy Control */ 639 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0); 640 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 641 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000); 642 1.1 someya delay(100); 643 1.1 someya /* audio engine reset */ 644 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 645 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00010000); 646 1.1 someya delay(100); 647 1.1 someya /* release reset */ 648 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 649 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00010000); 650 1.1 someya delay(100); 651 1.1 someya /* DAC on */ 652 1.1 someya autri_reg_set_4(sc,AUTRI_NX_ACR0,0x02); 653 1.1 someya break; 654 1.1 someya case AUTRI_DEVICE_ID_SIS_7018: 655 1.1 someya /* disable Legacy Control */ 656 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0); 657 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 658 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000); 659 1.1 someya delay(100); 660 1.1 someya /* reset Digital Controller */ 661 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 662 1.15 perry pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000); 663 1.1 someya delay(100); 664 1.1 someya /* release reset */ 665 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 666 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000); 667 1.1 someya delay(100); 668 1.1 someya /* disable AC97 GPIO interrupt */ 669 1.1 someya TWRITE1(sc, AUTRI_SIS_ACGPIO, 0); 670 1.1 someya /* enable 64 channel mode */ 671 1.1 someya autri_reg_set_4(sc, AUTRI_LFO_GC_CIR, BANK_B_EN); 672 1.1 someya break; 673 1.1 someya case AUTRI_DEVICE_ID_ALI_M5451: 674 1.1 someya /* disable Legacy Control */ 675 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0); 676 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 677 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000); 678 1.1 someya delay(100); 679 1.1 someya /* reset Digital Controller */ 680 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 681 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000); 682 1.1 someya delay(100); 683 1.1 someya /* release reset */ 684 1.1 someya reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 685 1.1 someya pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000); 686 1.1 someya delay(100); 687 1.1 someya /* enable PCM input */ 688 1.1 someya autri_reg_set_4(sc, AUTRI_ALI_GCONTROL, AUTRI_ALI_GCONTROL_PCM_IN); 689 1.1 someya break; 690 1.1 someya } 691 1.1 someya 692 1.1 someya if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) { 693 1.1 someya sc->sc_play.ch = 0; 694 1.1 someya sc->sc_play.ch_intr = 1; 695 1.1 someya sc->sc_rec.ch = 31; 696 1.1 someya sc->sc_rec.ch_intr = 2; 697 1.1 someya } else { 698 1.1 someya sc->sc_play.ch = 0x20; 699 1.1 someya sc->sc_play.ch_intr = 0x21; 700 1.1 someya sc->sc_rec.ch = 0x22; 701 1.1 someya sc->sc_rec.ch_intr = 0x23; 702 1.1 someya } 703 1.1 someya 704 1.1 someya /* clear channel status */ 705 1.1 someya TWRITE4(sc, AUTRI_STOP_A, 0xffffffff); 706 1.1 someya TWRITE4(sc, AUTRI_STOP_B, 0xffffffff); 707 1.1 someya 708 1.1 someya /* disable channel interrupt */ 709 1.1 someya TWRITE4(sc, AUTRI_AINTEN_A, 0); 710 1.1 someya TWRITE4(sc, AUTRI_AINTEN_B, 0); 711 1.1 someya 712 1.1 someya #if 0 713 1.1 someya /* TLB */ 714 1.1 someya if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) { 715 1.1 someya TWRITE4(sc,AUTRI_NX_TLBC,0); 716 1.1 someya } 717 1.1 someya #endif 718 1.1 someya 719 1.1 someya autri_enable_loop_interrupt(sc); 720 1.1 someya 721 1.1 someya DPRINTF(("out autri_init()\n")); 722 1.1 someya return 0; 723 1.1 someya } 724 1.1 someya 725 1.1 someya static void 726 1.3 augustss autri_enable_loop_interrupt(void *sc_) 727 1.1 someya { 728 1.24 kent struct autri_softc *sc; 729 1.24 kent uint32_t reg; 730 1.1 someya 731 1.1 someya /*reg = (ENDLP_IE | MIDLP_IE);*/ 732 1.1 someya reg = ENDLP_IE; 733 1.24 kent sc = sc_; 734 1.1 someya if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) 735 1.1 someya reg |= BANK_B_EN; 736 1.5 someya 737 1.24 kent autri_reg_set_4(sc, AUTRI_LFO_GC_CIR, reg); 738 1.1 someya } 739 1.1 someya 740 1.1 someya #if 0 741 1.1 someya static void 742 1.3 augustss autri_disable_loop_interrupt(void *sc_) 743 1.1 someya { 744 1.24 kent struct autri_softc *sc; 745 1.24 kent uint32_t reg; 746 1.1 someya 747 1.1 someya reg = (ENDLP_IE | MIDLP_IE); 748 1.24 kent sc = sc_; 749 1.24 kent autri_reg_clear_4(sc, AUTRI_LFO_GC_CIR, reg); 750 1.1 someya } 751 1.1 someya #endif 752 1.1 someya 753 1.26 thorpej static int 754 1.3 augustss autri_intr(void *p) 755 1.1 someya { 756 1.24 kent struct autri_softc *sc; 757 1.24 kent uint32_t intsrc; 758 1.24 kent uint32_t mask, active[2]; 759 1.1 someya int ch, endch; 760 1.1 someya /* 761 1.1 someya u_int32_t reg; 762 1.1 someya u_int32_t cso,eso; 763 1.1 someya */ 764 1.24 kent sc = p; 765 1.47 jmcneill mutex_spin_enter(&sc->sc_intr_lock); 766 1.47 jmcneill 767 1.24 kent intsrc = TREAD4(sc, AUTRI_MISCINT); 768 1.47 jmcneill if ((intsrc & (ADDRESS_IRQ | MPU401_IRQ)) == 0) { 769 1.47 jmcneill mutex_spin_exit(&sc->sc_intr_lock); 770 1.1 someya return 0; 771 1.47 jmcneill } 772 1.1 someya 773 1.1 someya if (intsrc & ADDRESS_IRQ) { 774 1.1 someya 775 1.1 someya active[0] = TREAD4(sc,AUTRI_AIN_A); 776 1.1 someya active[1] = TREAD4(sc,AUTRI_AIN_B); 777 1.1 someya 778 1.1 someya if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) { 779 1.1 someya endch = 32; 780 1.1 someya } else { 781 1.1 someya endch = 64; 782 1.1 someya } 783 1.1 someya 784 1.24 kent for (ch = 0; ch < endch; ch++) { 785 1.1 someya mask = 1 << (ch & 0x1f); 786 1.1 someya if (active[(ch & 0x20) ? 1 : 0] & mask) { 787 1.1 someya 788 1.12 wiz /* clear interrupt */ 789 1.1 someya TWRITE4(sc, (ch & 0x20) ? AUTRI_AIN_B : AUTRI_AIN_A, mask); 790 1.12 wiz /* disable interrupt */ 791 1.1 someya autri_reg_clear_4(sc,(ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask); 792 1.1 someya #if 0 793 1.1 someya reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f; 794 1.1 someya TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | ch); 795 1.1 someya 796 1.1 someya if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) { 797 1.24 kent cso = TREAD4(sc, 0xe0) & 0x00ffffff; 798 1.24 kent eso = TREAD4(sc, 0xe8) & 0x00ffffff; 799 1.1 someya } else { 800 1.24 kent cso = (TREAD4(sc, 0xe0) >> 16) & 0x0000ffff; 801 1.24 kent eso = (TREAD4(sc, 0xe8) >> 16) & 0x0000ffff; 802 1.1 someya } 803 1.1 someya /*printf("cso=%d, eso=%d\n",cso,eso);*/ 804 1.1 someya #endif 805 1.1 someya if (ch == sc->sc_play.ch_intr) { 806 1.1 someya if (sc->sc_play.intr) 807 1.1 someya sc->sc_play.intr(sc->sc_play.intr_arg); 808 1.1 someya } 809 1.1 someya 810 1.1 someya if (ch == sc->sc_rec.ch_intr) { 811 1.1 someya if (sc->sc_rec.intr) 812 1.1 someya sc->sc_rec.intr(sc->sc_rec.intr_arg); 813 1.1 someya } 814 1.1 someya 815 1.1 someya /* enable interrupt */ 816 1.1 someya autri_reg_set_4(sc, (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask); 817 1.1 someya } 818 1.1 someya } 819 1.1 someya } 820 1.1 someya 821 1.1 someya if (intsrc & MPU401_IRQ) { 822 1.1 someya /* XXX */ 823 1.1 someya } 824 1.1 someya 825 1.1 someya autri_reg_set_4(sc,AUTRI_MISCINT, 826 1.1 someya ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW); 827 1.1 someya 828 1.47 jmcneill mutex_spin_exit(&sc->sc_intr_lock); 829 1.1 someya return 1; 830 1.1 someya } 831 1.1 someya 832 1.1 someya /* 833 1.1 someya * 834 1.1 someya */ 835 1.1 someya 836 1.26 thorpej static int 837 1.24 kent autri_allocmem(struct autri_softc *sc, size_t size, size_t align, 838 1.3 augustss struct autri_dma *p) 839 1.1 someya { 840 1.1 someya int error; 841 1.1 someya 842 1.1 someya p->size = size; 843 1.1 someya error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0, 844 1.1 someya p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 845 1.47 jmcneill &p->nsegs, BUS_DMA_WAITOK); 846 1.1 someya if (error) 847 1.24 kent return error; 848 1.1 someya 849 1.1 someya error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 850 1.47 jmcneill &p->addr, BUS_DMA_WAITOK|BUS_DMA_COHERENT); 851 1.1 someya if (error) 852 1.1 someya goto free; 853 1.1 someya 854 1.1 someya error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size, 855 1.47 jmcneill 0, BUS_DMA_WAITOK, &p->map); 856 1.1 someya if (error) 857 1.1 someya goto unmap; 858 1.1 someya 859 1.1 someya error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 860 1.47 jmcneill BUS_DMA_WAITOK); 861 1.1 someya if (error) 862 1.1 someya goto destroy; 863 1.1 someya return (0); 864 1.1 someya 865 1.1 someya destroy: 866 1.1 someya bus_dmamap_destroy(sc->sc_dmatag, p->map); 867 1.1 someya unmap: 868 1.1 someya bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 869 1.1 someya free: 870 1.1 someya bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 871 1.24 kent return error; 872 1.1 someya } 873 1.1 someya 874 1.26 thorpej static int 875 1.3 augustss autri_freemem(struct autri_softc *sc, struct autri_dma *p) 876 1.1 someya { 877 1.24 kent 878 1.1 someya bus_dmamap_unload(sc->sc_dmatag, p->map); 879 1.1 someya bus_dmamap_destroy(sc->sc_dmatag, p->map); 880 1.1 someya bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 881 1.1 someya bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 882 1.1 someya return 0; 883 1.1 someya } 884 1.1 someya 885 1.26 thorpej static int 886 1.34 christos autri_open(void *addr, int flags) 887 1.1 someya { 888 1.1 someya DPRINTF(("autri_open()\n")); 889 1.1 someya DPRINTFN(5,("MISCINT : 0x%08X\n", 890 1.1 someya TREAD4((struct autri_softc *)addr, AUTRI_MISCINT))); 891 1.1 someya DPRINTFN(5,("LFO_GC_CIR : 0x%08X\n", 892 1.1 someya TREAD4((struct autri_softc *)addr, AUTRI_LFO_GC_CIR))); 893 1.24 kent return 0; 894 1.1 someya } 895 1.1 someya 896 1.26 thorpej static int 897 1.57 isaki autri_query_format(void *addr, audio_format_query_t *afp) 898 1.1 someya { 899 1.24 kent 900 1.57 isaki return audio_query_format(autri_formats, AUTRI_NFORMATS, afp); 901 1.1 someya } 902 1.1 someya 903 1.26 thorpej static int 904 1.57 isaki autri_set_format(void *addr, int setmode, 905 1.57 isaki const audio_params_t *play, const audio_params_t *rec, 906 1.57 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 907 1.57 isaki { 908 1.57 isaki 909 1.1 someya return 0; 910 1.1 someya } 911 1.1 someya 912 1.26 thorpej static int 913 1.3 augustss autri_halt_output(void *addr) 914 1.1 someya { 915 1.24 kent struct autri_softc *sc; 916 1.1 someya 917 1.1 someya DPRINTF(("autri_halt_output()\n")); 918 1.24 kent sc = addr; 919 1.1 someya sc->sc_play.intr = NULL; 920 1.1 someya autri_stopch(sc, sc->sc_play.ch, sc->sc_play.ch_intr); 921 1.1 someya autri_disable_interrupt(sc, sc->sc_play.ch_intr); 922 1.1 someya 923 1.1 someya return 0; 924 1.1 someya } 925 1.1 someya 926 1.26 thorpej static int 927 1.3 augustss autri_halt_input(void *addr) 928 1.1 someya { 929 1.24 kent struct autri_softc *sc; 930 1.1 someya 931 1.1 someya DPRINTF(("autri_halt_input()\n")); 932 1.24 kent sc = addr; 933 1.1 someya sc->sc_rec.intr = NULL; 934 1.1 someya autri_stopch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr); 935 1.1 someya autri_disable_interrupt(sc, sc->sc_rec.ch_intr); 936 1.1 someya 937 1.1 someya return 0; 938 1.1 someya } 939 1.1 someya 940 1.26 thorpej static int 941 1.3 augustss autri_getdev(void *addr, struct audio_device *retp) 942 1.1 someya { 943 1.24 kent struct autri_softc *sc; 944 1.1 someya 945 1.1 someya DPRINTF(("autri_getdev().\n")); 946 1.24 kent sc = addr; 947 1.1 someya strncpy(retp->name, "Trident 4DWAVE", sizeof(retp->name)); 948 1.1 someya snprintf(retp->version, sizeof(retp->version), "0x%02x", 949 1.1 someya PCI_REVISION(sc->sc_class)); 950 1.1 someya 951 1.1 someya switch (sc->sc_devid) { 952 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_DX: 953 1.1 someya strncpy(retp->config, "4DWAVE-DX", sizeof(retp->config)); 954 1.1 someya break; 955 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_NX: 956 1.1 someya strncpy(retp->config, "4DWAVE-NX", sizeof(retp->config)); 957 1.1 someya break; 958 1.1 someya case AUTRI_DEVICE_ID_SIS_7018: 959 1.1 someya strncpy(retp->config, "SiS 7018", sizeof(retp->config)); 960 1.1 someya break; 961 1.1 someya case AUTRI_DEVICE_ID_ALI_M5451: 962 1.1 someya strncpy(retp->config, "ALi M5451", sizeof(retp->config)); 963 1.1 someya break; 964 1.1 someya default: 965 1.1 someya strncpy(retp->config, "unknown", sizeof(retp->config)); 966 1.1 someya } 967 1.1 someya 968 1.1 someya return 0; 969 1.1 someya } 970 1.1 someya 971 1.26 thorpej static int 972 1.3 augustss autri_mixer_set_port(void *addr, mixer_ctrl_t *cp) 973 1.1 someya { 974 1.24 kent struct autri_softc *sc; 975 1.1 someya 976 1.24 kent sc = addr; 977 1.24 kent return sc->sc_codec.codec_if->vtbl->mixer_set_port( 978 1.24 kent sc->sc_codec.codec_if, cp); 979 1.1 someya } 980 1.1 someya 981 1.26 thorpej static int 982 1.3 augustss autri_mixer_get_port(void *addr, mixer_ctrl_t *cp) 983 1.1 someya { 984 1.24 kent struct autri_softc *sc; 985 1.1 someya 986 1.24 kent sc = addr; 987 1.24 kent return sc->sc_codec.codec_if->vtbl->mixer_get_port( 988 1.24 kent sc->sc_codec.codec_if, cp); 989 1.1 someya } 990 1.1 someya 991 1.26 thorpej static int 992 1.3 augustss autri_query_devinfo(void *addr, mixer_devinfo_t *dip) 993 1.1 someya { 994 1.24 kent struct autri_softc *sc; 995 1.1 someya 996 1.24 kent sc = addr; 997 1.24 kent return sc->sc_codec.codec_if->vtbl->query_devinfo( 998 1.24 kent sc->sc_codec.codec_if, dip); 999 1.1 someya } 1000 1.1 someya 1001 1.26 thorpej static void * 1002 1.47 jmcneill autri_malloc(void *addr, int direction, size_t size) 1003 1.1 someya { 1004 1.24 kent struct autri_softc *sc; 1005 1.1 someya struct autri_dma *p; 1006 1.1 someya int error; 1007 1.1 someya 1008 1.47 jmcneill p = kmem_alloc(sizeof(*p), KM_SLEEP); 1009 1.24 kent sc = addr; 1010 1.1 someya #if 0 1011 1.1 someya error = autri_allocmem(sc, size, 16, p); 1012 1.1 someya #endif 1013 1.1 someya error = autri_allocmem(sc, size, 0x10000, p); 1014 1.1 someya if (error) { 1015 1.47 jmcneill kmem_free(p, sizeof(*p)); 1016 1.1 someya return NULL; 1017 1.1 someya } 1018 1.1 someya 1019 1.1 someya p->next = sc->sc_dmas; 1020 1.1 someya sc->sc_dmas = p; 1021 1.1 someya return KERNADDR(p); 1022 1.1 someya } 1023 1.1 someya 1024 1.26 thorpej static void 1025 1.47 jmcneill autri_free(void *addr, void *ptr, size_t size) 1026 1.1 someya { 1027 1.24 kent struct autri_softc *sc; 1028 1.1 someya struct autri_dma **pp, *p; 1029 1.1 someya 1030 1.24 kent sc = addr; 1031 1.1 someya for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) { 1032 1.1 someya if (KERNADDR(p) == ptr) { 1033 1.1 someya autri_freemem(sc, p); 1034 1.1 someya *pp = p->next; 1035 1.47 jmcneill kmem_free(p, sizeof(*p)); 1036 1.1 someya return; 1037 1.1 someya } 1038 1.1 someya } 1039 1.1 someya } 1040 1.1 someya 1041 1.1 someya static struct autri_dma * 1042 1.3 augustss autri_find_dma(struct autri_softc *sc, void *addr) 1043 1.1 someya { 1044 1.1 someya struct autri_dma *p; 1045 1.1 someya 1046 1.1 someya for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next) 1047 1.24 kent continue; 1048 1.1 someya 1049 1.1 someya return p; 1050 1.1 someya } 1051 1.1 someya 1052 1.26 thorpej static int 1053 1.34 christos autri_get_props(void *addr) 1054 1.1 someya { 1055 1.58 isaki 1056 1.58 isaki return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE | 1057 1.58 isaki AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1058 1.1 someya } 1059 1.1 someya 1060 1.1 someya static void 1061 1.3 augustss autri_setup_channel(struct autri_softc *sc, int mode, 1062 1.23 kent const audio_params_t *param) 1063 1.1 someya { 1064 1.1 someya int i, ch, channel; 1065 1.24 kent uint32_t reg, cr[5]; 1066 1.24 kent uint32_t cso, eso; 1067 1.24 kent uint32_t delta, dch[2], ctrl; 1068 1.24 kent uint32_t alpha_fms, fm_vol, attribute; 1069 1.1 someya 1070 1.24 kent uint32_t dmaaddr, dmalen; 1071 1.1 someya int factor, rvol, cvol; 1072 1.1 someya struct autri_chstatus *chst; 1073 1.1 someya 1074 1.1 someya ctrl = AUTRI_CTRL_LOOPMODE; 1075 1.1 someya switch (param->encoding) { 1076 1.1 someya case AUDIO_ENCODING_SLINEAR_BE: 1077 1.1 someya case AUDIO_ENCODING_SLINEAR_LE: 1078 1.1 someya ctrl |= AUTRI_CTRL_SIGNED; 1079 1.1 someya break; 1080 1.1 someya } 1081 1.1 someya 1082 1.1 someya factor = 0; 1083 1.1 someya if (param->precision == 16) { 1084 1.1 someya ctrl |= AUTRI_CTRL_16BIT; 1085 1.1 someya factor++; 1086 1.1 someya } 1087 1.1 someya 1088 1.1 someya if (param->channels == 2) { 1089 1.1 someya ctrl |= AUTRI_CTRL_STEREO; 1090 1.1 someya factor++; 1091 1.1 someya } 1092 1.1 someya 1093 1.23 kent delta = param->sample_rate; 1094 1.1 someya if (delta < 4000) 1095 1.1 someya delta = 4000; 1096 1.1 someya if (delta > 48000) 1097 1.1 someya delta = 48000; 1098 1.1 someya 1099 1.11 someya attribute = 0; 1100 1.11 someya 1101 1.1 someya dch[1] = ((delta << 12) / 48000) & 0x0000ffff; 1102 1.1 someya if (mode == AUMODE_PLAY) { 1103 1.1 someya chst = &sc->sc_play; 1104 1.1 someya dch[0] = ((delta << 12) / 48000) & 0x0000ffff; 1105 1.5 someya ctrl |= AUTRI_CTRL_WAVEVOL; 1106 1.1 someya } else { 1107 1.1 someya chst = &sc->sc_rec; 1108 1.1 someya dch[0] = ((48000 << 12) / delta) & 0x0000ffff; 1109 1.11 someya if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) { 1110 1.5 someya ctrl |= AUTRI_CTRL_MUTEVOL_SIS; 1111 1.11 someya attribute = AUTRI_ATTR_PCMREC_SIS; 1112 1.11 someya if (delta != 48000) 1113 1.11 someya attribute |= AUTRI_ATTR_ENASRC_SIS; 1114 1.11 someya } else 1115 1.5 someya ctrl |= AUTRI_CTRL_MUTEVOL; 1116 1.1 someya } 1117 1.1 someya 1118 1.1 someya dmaaddr = DMAADDR(chst->dma); 1119 1.1 someya cso = alpha_fms = 0; 1120 1.1 someya rvol = cvol = 0x7f; 1121 1.1 someya fm_vol = 0x0 | ((rvol & 0x7f) << 7) | (cvol & 0x7f); 1122 1.1 someya 1123 1.24 kent for (ch = 0; ch < 2; ch++) { 1124 1.1 someya 1125 1.1 someya if (ch == 0) 1126 1.1 someya dmalen = (chst->length >> factor); 1127 1.1 someya else { 1128 1.1 someya /* channel for interrupt */ 1129 1.1 someya dmalen = (chst->blksize >> factor); 1130 1.5 someya if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) 1131 1.5 someya ctrl |= AUTRI_CTRL_MUTEVOL_SIS; 1132 1.5 someya else 1133 1.5 someya ctrl |= AUTRI_CTRL_MUTEVOL; 1134 1.11 someya attribute = 0; 1135 1.25 gson cso = dmalen - 1; 1136 1.1 someya } 1137 1.1 someya 1138 1.1 someya eso = dmalen - 1; 1139 1.1 someya 1140 1.1 someya switch (sc->sc_devid) { 1141 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_DX: 1142 1.1 someya cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff); 1143 1.1 someya cr[1] = dmaaddr; 1144 1.24 kent cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 1145 1.1 someya cr[3] = fm_vol; 1146 1.1 someya cr[4] = ctrl; 1147 1.1 someya break; 1148 1.1 someya case AUTRI_DEVICE_ID_4DWAVE_NX: 1149 1.1 someya cr[0] = (dch[ch] << 24) | (cso & 0x00ffffff); 1150 1.1 someya cr[1] = dmaaddr; 1151 1.1 someya cr[2] = ((dch[ch] << 16) & 0xff000000) | (eso & 0x00ffffff); 1152 1.1 someya cr[3] = (alpha_fms << 16) | (fm_vol & 0x0000ffff); 1153 1.1 someya cr[4] = ctrl; 1154 1.1 someya break; 1155 1.1 someya case AUTRI_DEVICE_ID_SIS_7018: 1156 1.1 someya cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff); 1157 1.1 someya cr[1] = dmaaddr; 1158 1.24 kent cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 1159 1.11 someya cr[3] = attribute; 1160 1.1 someya cr[4] = ctrl; 1161 1.1 someya break; 1162 1.1 someya case AUTRI_DEVICE_ID_ALI_M5451: 1163 1.1 someya cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff); 1164 1.1 someya cr[1] = dmaaddr; 1165 1.1 someya cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 1166 1.1 someya cr[3] = 0; 1167 1.1 someya cr[4] = ctrl; 1168 1.1 someya break; 1169 1.1 someya } 1170 1.1 someya 1171 1.1 someya /* write channel data */ 1172 1.1 someya channel = (ch == 0) ? chst->ch : chst->ch_intr; 1173 1.1 someya 1174 1.1 someya reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f; 1175 1.1 someya TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | channel); 1176 1.1 someya 1177 1.24 kent for (i = 0; i < 5; i++) { 1178 1.1 someya TWRITE4(sc, AUTRI_ARAM_CR + i*sizeof(cr[0]), cr[i]); 1179 1.1 someya DPRINTFN(5,("cr[%d] : 0x%08X\n", i, cr[i])); 1180 1.1 someya } 1181 1.1 someya 1182 1.24 kent /* Bank A only */ 1183 1.1 someya if (channel < 0x20) { 1184 1.1 someya TWRITE4(sc, AUTRI_EBUF1, AUTRI_EMOD_STILL); 1185 1.1 someya TWRITE4(sc, AUTRI_EBUF2, AUTRI_EMOD_STILL); 1186 1.1 someya } 1187 1.1 someya } 1188 1.1 someya 1189 1.1 someya } 1190 1.1 someya 1191 1.26 thorpej static int 1192 1.3 augustss autri_trigger_output(void *addr, void *start, void *end, int blksize, 1193 1.3 augustss void (*intr)(void *), void *arg, 1194 1.23 kent const audio_params_t *param) 1195 1.1 someya { 1196 1.24 kent struct autri_softc *sc; 1197 1.23 kent struct autri_dma *p; 1198 1.1 someya 1199 1.1 someya DPRINTFN(5,("autri_trigger_output: sc=%p start=%p end=%p " 1200 1.1 someya "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 1201 1.24 kent sc = addr; 1202 1.1 someya sc->sc_play.intr = intr; 1203 1.1 someya sc->sc_play.intr_arg = arg; 1204 1.1 someya sc->sc_play.offset = 0; 1205 1.1 someya sc->sc_play.blksize = blksize; 1206 1.1 someya sc->sc_play.length = (char *)end - (char *)start; 1207 1.1 someya 1208 1.1 someya p = autri_find_dma(sc, start); 1209 1.1 someya if (!p) { 1210 1.1 someya printf("autri_trigger_output: bad addr %p\n", start); 1211 1.1 someya return (EINVAL); 1212 1.1 someya } 1213 1.1 someya 1214 1.1 someya sc->sc_play.dma = p; 1215 1.1 someya 1216 1.1 someya /* */ 1217 1.1 someya autri_setup_channel(sc, AUMODE_PLAY, param); 1218 1.1 someya 1219 1.1 someya /* volume set to no attenuation */ 1220 1.1 someya TWRITE4(sc, AUTRI_MUSICVOL_WAVEVOL, 0); 1221 1.1 someya 1222 1.1 someya /* enable interrupt */ 1223 1.1 someya autri_enable_interrupt(sc, sc->sc_play.ch_intr); 1224 1.1 someya 1225 1.1 someya /* start channel */ 1226 1.1 someya autri_startch(sc, sc->sc_play.ch, sc->sc_play.ch_intr); 1227 1.1 someya 1228 1.1 someya return 0; 1229 1.1 someya } 1230 1.1 someya 1231 1.26 thorpej static int 1232 1.3 augustss autri_trigger_input(void *addr, void *start, void *end, int blksize, 1233 1.3 augustss void (*intr)(void *), void *arg, 1234 1.23 kent const audio_params_t *param) 1235 1.1 someya { 1236 1.24 kent struct autri_softc *sc; 1237 1.23 kent struct autri_dma *p; 1238 1.1 someya 1239 1.1 someya DPRINTFN(5,("autri_trigger_input: sc=%p start=%p end=%p " 1240 1.1 someya "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 1241 1.24 kent sc = addr; 1242 1.1 someya sc->sc_rec.intr = intr; 1243 1.1 someya sc->sc_rec.intr_arg = arg; 1244 1.1 someya sc->sc_rec.offset = 0; 1245 1.1 someya sc->sc_rec.blksize = blksize; 1246 1.1 someya sc->sc_rec.length = (char *)end - (char *)start; 1247 1.1 someya 1248 1.1 someya /* */ 1249 1.1 someya p = autri_find_dma(sc, start); 1250 1.1 someya if (!p) { 1251 1.1 someya printf("autri_trigger_input: bad addr %p\n", start); 1252 1.1 someya return (EINVAL); 1253 1.1 someya } 1254 1.1 someya 1255 1.1 someya sc->sc_rec.dma = p; 1256 1.1 someya 1257 1.1 someya /* */ 1258 1.1 someya if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) { 1259 1.1 someya autri_reg_set_4(sc, AUTRI_NX_ACR0, AUTRI_NX_ACR0_PSB_CAPTURE); 1260 1.1 someya TWRITE1(sc, AUTRI_NX_RCI3, AUTRI_NX_RCI3_ENABLE | sc->sc_rec.ch); 1261 1.1 someya } 1262 1.1 someya 1263 1.1 someya #if 0 1264 1.30 lukem /* 4DWAVE only allows capturing at a 48 kHz rate */ 1265 1.1 someya if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_DX || 1266 1.1 someya sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) 1267 1.1 someya param->sample_rate = 48000; 1268 1.1 someya #endif 1269 1.1 someya 1270 1.1 someya autri_setup_channel(sc, AUMODE_RECORD, param); 1271 1.1 someya 1272 1.1 someya /* enable interrupt */ 1273 1.1 someya autri_enable_interrupt(sc, sc->sc_rec.ch_intr); 1274 1.1 someya 1275 1.1 someya /* start channel */ 1276 1.1 someya autri_startch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr); 1277 1.1 someya 1278 1.1 someya return 0; 1279 1.1 someya } 1280 1.1 someya 1281 1.47 jmcneill 1282 1.47 jmcneill static void 1283 1.47 jmcneill autri_get_locks(void *addr, kmutex_t **intr, kmutex_t **proc) 1284 1.47 jmcneill { 1285 1.47 jmcneill struct autri_softc *sc; 1286 1.47 jmcneill 1287 1.47 jmcneill sc = addr; 1288 1.47 jmcneill *intr = &sc->sc_intr_lock; 1289 1.47 jmcneill *proc = &sc->sc_lock; 1290 1.47 jmcneill } 1291 1.47 jmcneill 1292 1.1 someya #if 0 1293 1.1 someya static int 1294 1.3 augustss autri_halt(struct autri_softc *sc) 1295 1.1 someya { 1296 1.24 kent 1297 1.1 someya DPRINTF(("autri_halt().\n")); 1298 1.1 someya /*autri_stopch(sc);*/ 1299 1.1 someya autri_disable_interrupt(sc, sc->sc_play.channel); 1300 1.1 someya autri_disable_interrupt(sc, sc->sc_rec.channel); 1301 1.1 someya return 0; 1302 1.1 someya } 1303 1.1 someya #endif 1304 1.1 someya 1305 1.1 someya static void 1306 1.3 augustss autri_enable_interrupt(struct autri_softc *sc, int ch) 1307 1.1 someya { 1308 1.1 someya int reg; 1309 1.1 someya 1310 1.1 someya reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A; 1311 1.1 someya ch &= 0x1f; 1312 1.1 someya 1313 1.1 someya autri_reg_set_4(sc, reg, 1 << ch); 1314 1.1 someya } 1315 1.1 someya 1316 1.1 someya static void 1317 1.3 augustss autri_disable_interrupt(struct autri_softc *sc, int ch) 1318 1.1 someya { 1319 1.1 someya int reg; 1320 1.1 someya 1321 1.1 someya reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A; 1322 1.1 someya ch &= 0x1f; 1323 1.1 someya 1324 1.1 someya autri_reg_clear_4(sc, reg, 1 << ch); 1325 1.1 someya } 1326 1.1 someya 1327 1.1 someya static void 1328 1.3 augustss autri_startch(struct autri_softc *sc, int ch, int ch_intr) 1329 1.1 someya { 1330 1.1 someya int reg; 1331 1.24 kent uint32_t chmask; 1332 1.1 someya 1333 1.1 someya reg = (ch & 0x20) ? AUTRI_START_B : AUTRI_START_A; 1334 1.1 someya ch &= 0x1f; 1335 1.10 someya ch_intr &= 0x1f; 1336 1.1 someya chmask = (1 << ch) | (1 << ch_intr); 1337 1.1 someya 1338 1.1 someya autri_reg_set_4(sc, reg, chmask); 1339 1.1 someya } 1340 1.1 someya 1341 1.1 someya static void 1342 1.3 augustss autri_stopch(struct autri_softc *sc, int ch, int ch_intr) 1343 1.1 someya { 1344 1.1 someya int reg; 1345 1.24 kent uint32_t chmask; 1346 1.1 someya 1347 1.1 someya reg = (ch & 0x20) ? AUTRI_STOP_B : AUTRI_STOP_A; 1348 1.1 someya ch &= 0x1f; 1349 1.10 someya ch_intr &= 0x1f; 1350 1.1 someya chmask = (1 << ch) | (1 << ch_intr); 1351 1.1 someya 1352 1.1 someya autri_reg_set_4(sc, reg, chmask); 1353 1.1 someya } 1354 1.1 someya 1355 1.1 someya #if NMIDI > 0 1356 1.26 thorpej static int 1357 1.3 augustss autri_midi_open(void *addr, int flags, void (*iintr)(void *, int), 1358 1.3 augustss void (*ointr)(void *), void *arg) 1359 1.1 someya { 1360 1.24 kent struct autri_softc *sc; 1361 1.1 someya 1362 1.1 someya DPRINTF(("autri_midi_open()\n")); 1363 1.24 kent sc = addr; 1364 1.24 kent DPRINTFN(5,("MPUR1 : 0x%02X\n", TREAD1(sc, AUTRI_MPUR1))); 1365 1.24 kent DPRINTFN(5,("MPUR2 : 0x%02X\n", TREAD1(sc, AUTRI_MPUR2))); 1366 1.1 someya 1367 1.1 someya sc->sc_iintr = iintr; 1368 1.1 someya sc->sc_ointr = ointr; 1369 1.1 someya sc->sc_arg = arg; 1370 1.1 someya 1371 1.1 someya if (flags & FREAD) 1372 1.1 someya autri_reg_clear_1(sc, AUTRI_MPUR2, AUTRI_MIDIIN_ENABLE_INTR); 1373 1.1 someya 1374 1.1 someya if (flags & FWRITE) 1375 1.1 someya autri_reg_set_1(sc, AUTRI_MPUR2, AUTRI_MIDIOUT_CONNECT); 1376 1.24 kent 1377 1.24 kent return 0; 1378 1.1 someya } 1379 1.1 someya 1380 1.26 thorpej static void 1381 1.1 someya autri_midi_close(void *addr) 1382 1.1 someya { 1383 1.24 kent struct autri_softc *sc; 1384 1.1 someya 1385 1.1 someya DPRINTF(("autri_midi_close()\n")); 1386 1.24 kent sc = addr; 1387 1.47 jmcneill kpause("autri", FALSE, hz/10, &sc->sc_lock); /* give uart a chance to drain */ 1388 1.1 someya 1389 1.1 someya sc->sc_iintr = NULL; 1390 1.1 someya sc->sc_ointr = NULL; 1391 1.1 someya } 1392 1.1 someya 1393 1.26 thorpej static int 1394 1.34 christos autri_midi_output(void *addr, int d) 1395 1.1 someya { 1396 1.24 kent struct autri_softc *sc; 1397 1.1 someya int x; 1398 1.1 someya 1399 1.24 kent sc = addr; 1400 1.1 someya for (x = 0; x != MIDI_BUSY_WAIT; x++) { 1401 1.1 someya if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) == 0) { 1402 1.1 someya TWRITE1(sc, AUTRI_MPUR0, d); 1403 1.24 kent return 0; 1404 1.1 someya } 1405 1.1 someya delay(MIDI_BUSY_DELAY); 1406 1.1 someya } 1407 1.24 kent return EIO; 1408 1.1 someya } 1409 1.1 someya 1410 1.26 thorpej static void 1411 1.34 christos autri_midi_getinfo(void *addr, struct midi_info *mi) 1412 1.1 someya { 1413 1.24 kent 1414 1.1 someya mi->name = "4DWAVE MIDI UART"; 1415 1.1 someya mi->props = MIDI_PROP_CAN_INPUT; 1416 1.1 someya } 1417 1.1 someya 1418 1.1 someya #endif 1419