1 /* $NetBSD: autri.c,v 1.57 2019/05/08 13:40:18 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.57 2019/05/08 13:40:18 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 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | 1065 AUDIO_PROP_FULLDUPLEX; 1066 } 1067 1068 static void 1069 autri_setup_channel(struct autri_softc *sc, int mode, 1070 const audio_params_t *param) 1071 { 1072 int i, ch, channel; 1073 uint32_t reg, cr[5]; 1074 uint32_t cso, eso; 1075 uint32_t delta, dch[2], ctrl; 1076 uint32_t alpha_fms, fm_vol, attribute; 1077 1078 uint32_t dmaaddr, dmalen; 1079 int factor, rvol, cvol; 1080 struct autri_chstatus *chst; 1081 1082 ctrl = AUTRI_CTRL_LOOPMODE; 1083 switch (param->encoding) { 1084 case AUDIO_ENCODING_SLINEAR_BE: 1085 case AUDIO_ENCODING_SLINEAR_LE: 1086 ctrl |= AUTRI_CTRL_SIGNED; 1087 break; 1088 } 1089 1090 factor = 0; 1091 if (param->precision == 16) { 1092 ctrl |= AUTRI_CTRL_16BIT; 1093 factor++; 1094 } 1095 1096 if (param->channels == 2) { 1097 ctrl |= AUTRI_CTRL_STEREO; 1098 factor++; 1099 } 1100 1101 delta = param->sample_rate; 1102 if (delta < 4000) 1103 delta = 4000; 1104 if (delta > 48000) 1105 delta = 48000; 1106 1107 attribute = 0; 1108 1109 dch[1] = ((delta << 12) / 48000) & 0x0000ffff; 1110 if (mode == AUMODE_PLAY) { 1111 chst = &sc->sc_play; 1112 dch[0] = ((delta << 12) / 48000) & 0x0000ffff; 1113 ctrl |= AUTRI_CTRL_WAVEVOL; 1114 } else { 1115 chst = &sc->sc_rec; 1116 dch[0] = ((48000 << 12) / delta) & 0x0000ffff; 1117 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) { 1118 ctrl |= AUTRI_CTRL_MUTEVOL_SIS; 1119 attribute = AUTRI_ATTR_PCMREC_SIS; 1120 if (delta != 48000) 1121 attribute |= AUTRI_ATTR_ENASRC_SIS; 1122 } else 1123 ctrl |= AUTRI_CTRL_MUTEVOL; 1124 } 1125 1126 dmaaddr = DMAADDR(chst->dma); 1127 cso = alpha_fms = 0; 1128 rvol = cvol = 0x7f; 1129 fm_vol = 0x0 | ((rvol & 0x7f) << 7) | (cvol & 0x7f); 1130 1131 for (ch = 0; ch < 2; ch++) { 1132 1133 if (ch == 0) 1134 dmalen = (chst->length >> factor); 1135 else { 1136 /* channel for interrupt */ 1137 dmalen = (chst->blksize >> factor); 1138 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) 1139 ctrl |= AUTRI_CTRL_MUTEVOL_SIS; 1140 else 1141 ctrl |= AUTRI_CTRL_MUTEVOL; 1142 attribute = 0; 1143 cso = dmalen - 1; 1144 } 1145 1146 eso = dmalen - 1; 1147 1148 switch (sc->sc_devid) { 1149 case AUTRI_DEVICE_ID_4DWAVE_DX: 1150 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff); 1151 cr[1] = dmaaddr; 1152 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 1153 cr[3] = fm_vol; 1154 cr[4] = ctrl; 1155 break; 1156 case AUTRI_DEVICE_ID_4DWAVE_NX: 1157 cr[0] = (dch[ch] << 24) | (cso & 0x00ffffff); 1158 cr[1] = dmaaddr; 1159 cr[2] = ((dch[ch] << 16) & 0xff000000) | (eso & 0x00ffffff); 1160 cr[3] = (alpha_fms << 16) | (fm_vol & 0x0000ffff); 1161 cr[4] = ctrl; 1162 break; 1163 case AUTRI_DEVICE_ID_SIS_7018: 1164 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff); 1165 cr[1] = dmaaddr; 1166 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 1167 cr[3] = attribute; 1168 cr[4] = ctrl; 1169 break; 1170 case AUTRI_DEVICE_ID_ALI_M5451: 1171 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff); 1172 cr[1] = dmaaddr; 1173 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 1174 cr[3] = 0; 1175 cr[4] = ctrl; 1176 break; 1177 } 1178 1179 /* write channel data */ 1180 channel = (ch == 0) ? chst->ch : chst->ch_intr; 1181 1182 reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f; 1183 TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | channel); 1184 1185 for (i = 0; i < 5; i++) { 1186 TWRITE4(sc, AUTRI_ARAM_CR + i*sizeof(cr[0]), cr[i]); 1187 DPRINTFN(5,("cr[%d] : 0x%08X\n", i, cr[i])); 1188 } 1189 1190 /* Bank A only */ 1191 if (channel < 0x20) { 1192 TWRITE4(sc, AUTRI_EBUF1, AUTRI_EMOD_STILL); 1193 TWRITE4(sc, AUTRI_EBUF2, AUTRI_EMOD_STILL); 1194 } 1195 } 1196 1197 } 1198 1199 static int 1200 autri_trigger_output(void *addr, void *start, void *end, int blksize, 1201 void (*intr)(void *), void *arg, 1202 const audio_params_t *param) 1203 { 1204 struct autri_softc *sc; 1205 struct autri_dma *p; 1206 1207 DPRINTFN(5,("autri_trigger_output: sc=%p start=%p end=%p " 1208 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 1209 sc = addr; 1210 sc->sc_play.intr = intr; 1211 sc->sc_play.intr_arg = arg; 1212 sc->sc_play.offset = 0; 1213 sc->sc_play.blksize = blksize; 1214 sc->sc_play.length = (char *)end - (char *)start; 1215 1216 p = autri_find_dma(sc, start); 1217 if (!p) { 1218 printf("autri_trigger_output: bad addr %p\n", start); 1219 return (EINVAL); 1220 } 1221 1222 sc->sc_play.dma = p; 1223 1224 /* */ 1225 autri_setup_channel(sc, AUMODE_PLAY, param); 1226 1227 /* volume set to no attenuation */ 1228 TWRITE4(sc, AUTRI_MUSICVOL_WAVEVOL, 0); 1229 1230 /* enable interrupt */ 1231 autri_enable_interrupt(sc, sc->sc_play.ch_intr); 1232 1233 /* start channel */ 1234 autri_startch(sc, sc->sc_play.ch, sc->sc_play.ch_intr); 1235 1236 return 0; 1237 } 1238 1239 static int 1240 autri_trigger_input(void *addr, void *start, void *end, int blksize, 1241 void (*intr)(void *), void *arg, 1242 const audio_params_t *param) 1243 { 1244 struct autri_softc *sc; 1245 struct autri_dma *p; 1246 1247 DPRINTFN(5,("autri_trigger_input: sc=%p start=%p end=%p " 1248 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 1249 sc = addr; 1250 sc->sc_rec.intr = intr; 1251 sc->sc_rec.intr_arg = arg; 1252 sc->sc_rec.offset = 0; 1253 sc->sc_rec.blksize = blksize; 1254 sc->sc_rec.length = (char *)end - (char *)start; 1255 1256 /* */ 1257 p = autri_find_dma(sc, start); 1258 if (!p) { 1259 printf("autri_trigger_input: bad addr %p\n", start); 1260 return (EINVAL); 1261 } 1262 1263 sc->sc_rec.dma = p; 1264 1265 /* */ 1266 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) { 1267 autri_reg_set_4(sc, AUTRI_NX_ACR0, AUTRI_NX_ACR0_PSB_CAPTURE); 1268 TWRITE1(sc, AUTRI_NX_RCI3, AUTRI_NX_RCI3_ENABLE | sc->sc_rec.ch); 1269 } 1270 1271 #if 0 1272 /* 4DWAVE only allows capturing at a 48 kHz rate */ 1273 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_DX || 1274 sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) 1275 param->sample_rate = 48000; 1276 #endif 1277 1278 autri_setup_channel(sc, AUMODE_RECORD, param); 1279 1280 /* enable interrupt */ 1281 autri_enable_interrupt(sc, sc->sc_rec.ch_intr); 1282 1283 /* start channel */ 1284 autri_startch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr); 1285 1286 return 0; 1287 } 1288 1289 1290 static void 1291 autri_get_locks(void *addr, kmutex_t **intr, kmutex_t **proc) 1292 { 1293 struct autri_softc *sc; 1294 1295 sc = addr; 1296 *intr = &sc->sc_intr_lock; 1297 *proc = &sc->sc_lock; 1298 } 1299 1300 #if 0 1301 static int 1302 autri_halt(struct autri_softc *sc) 1303 { 1304 1305 DPRINTF(("autri_halt().\n")); 1306 /*autri_stopch(sc);*/ 1307 autri_disable_interrupt(sc, sc->sc_play.channel); 1308 autri_disable_interrupt(sc, sc->sc_rec.channel); 1309 return 0; 1310 } 1311 #endif 1312 1313 static void 1314 autri_enable_interrupt(struct autri_softc *sc, int ch) 1315 { 1316 int reg; 1317 1318 reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A; 1319 ch &= 0x1f; 1320 1321 autri_reg_set_4(sc, reg, 1 << ch); 1322 } 1323 1324 static void 1325 autri_disable_interrupt(struct autri_softc *sc, int ch) 1326 { 1327 int reg; 1328 1329 reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A; 1330 ch &= 0x1f; 1331 1332 autri_reg_clear_4(sc, reg, 1 << ch); 1333 } 1334 1335 static void 1336 autri_startch(struct autri_softc *sc, int ch, int ch_intr) 1337 { 1338 int reg; 1339 uint32_t chmask; 1340 1341 reg = (ch & 0x20) ? AUTRI_START_B : AUTRI_START_A; 1342 ch &= 0x1f; 1343 ch_intr &= 0x1f; 1344 chmask = (1 << ch) | (1 << ch_intr); 1345 1346 autri_reg_set_4(sc, reg, chmask); 1347 } 1348 1349 static void 1350 autri_stopch(struct autri_softc *sc, int ch, int ch_intr) 1351 { 1352 int reg; 1353 uint32_t chmask; 1354 1355 reg = (ch & 0x20) ? AUTRI_STOP_B : AUTRI_STOP_A; 1356 ch &= 0x1f; 1357 ch_intr &= 0x1f; 1358 chmask = (1 << ch) | (1 << ch_intr); 1359 1360 autri_reg_set_4(sc, reg, chmask); 1361 } 1362 1363 #if NMIDI > 0 1364 static int 1365 autri_midi_open(void *addr, int flags, void (*iintr)(void *, int), 1366 void (*ointr)(void *), void *arg) 1367 { 1368 struct autri_softc *sc; 1369 1370 DPRINTF(("autri_midi_open()\n")); 1371 sc = addr; 1372 DPRINTFN(5,("MPUR1 : 0x%02X\n", TREAD1(sc, AUTRI_MPUR1))); 1373 DPRINTFN(5,("MPUR2 : 0x%02X\n", TREAD1(sc, AUTRI_MPUR2))); 1374 1375 sc->sc_iintr = iintr; 1376 sc->sc_ointr = ointr; 1377 sc->sc_arg = arg; 1378 1379 if (flags & FREAD) 1380 autri_reg_clear_1(sc, AUTRI_MPUR2, AUTRI_MIDIIN_ENABLE_INTR); 1381 1382 if (flags & FWRITE) 1383 autri_reg_set_1(sc, AUTRI_MPUR2, AUTRI_MIDIOUT_CONNECT); 1384 1385 return 0; 1386 } 1387 1388 static void 1389 autri_midi_close(void *addr) 1390 { 1391 struct autri_softc *sc; 1392 1393 DPRINTF(("autri_midi_close()\n")); 1394 sc = addr; 1395 kpause("autri", FALSE, hz/10, &sc->sc_lock); /* give uart a chance to drain */ 1396 1397 sc->sc_iintr = NULL; 1398 sc->sc_ointr = NULL; 1399 } 1400 1401 static int 1402 autri_midi_output(void *addr, int d) 1403 { 1404 struct autri_softc *sc; 1405 int x; 1406 1407 sc = addr; 1408 for (x = 0; x != MIDI_BUSY_WAIT; x++) { 1409 if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) == 0) { 1410 TWRITE1(sc, AUTRI_MPUR0, d); 1411 return 0; 1412 } 1413 delay(MIDI_BUSY_DELAY); 1414 } 1415 return EIO; 1416 } 1417 1418 static void 1419 autri_midi_getinfo(void *addr, struct midi_info *mi) 1420 { 1421 1422 mi->name = "4DWAVE MIDI UART"; 1423 mi->props = MIDI_PROP_CAN_INPUT; 1424 } 1425 1426 #endif 1427