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