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