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