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