1 /* $OpenBSD: autri.c,v 1.13 2003/04/27 11:22:53 ho 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 #include <sys/proc.h> 46 47 #include <dev/pci/pcidevs.h> 48 #include <dev/pci/pcireg.h> 49 #include <dev/pci/pcivar.h> 50 51 #include <sys/audioio.h> 52 #include <dev/audio_if.h> 53 #include <dev/midi_if.h> 54 #include <dev/mulaw.h> 55 #include <dev/auconv.h> 56 #include <dev/ic/ac97.h> 57 #include <dev/ic/mpuvar.h> 58 59 #include <machine/bus.h> 60 #include <machine/intr.h> 61 62 #include <dev/pci/autrireg.h> 63 #include <dev/pci/autrivar.h> 64 65 #ifdef AUDIO_DEBUG 66 # define DPRINTF(x) if (autridebug) printf x 67 # define DPRINTFN(n,x) if (autridebug > (n)) printf x 68 int autridebug = 0; 69 #else 70 # define DPRINTF(x) 71 # define DPRINTFN(n,x) 72 #endif 73 74 int autri_match(struct device *, void *, void *); 75 void autri_attach(struct device *, struct device *, void *); 76 int autri_intr(void *); 77 78 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) 79 #define KERNADDR(p) ((void *)((p)->addr)) 80 81 int autri_allocmem(struct autri_softc *, size_t, size_t, struct autri_dma *); 82 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 __inline void autri_reg_set_1(struct autri_softc *, int, uint8_t); 92 static __inline void autri_reg_clear_1(struct autri_softc *, int, uint8_t); 93 static __inline void autri_reg_set_4(struct autri_softc *, int, uint32_t); 94 static __inline void autri_reg_clear_4(struct autri_softc *, int, uint32_t); 95 96 int autri_attach_codec(void *sc, struct ac97_codec_if *); 97 int autri_read_codec(void *sc, u_int8_t a, u_int16_t *d); 98 int autri_write_codec(void *sc, u_int8_t a, u_int16_t d); 99 void autri_reset_codec(void *sc); 100 enum ac97_host_flags autri_flags_codec(void *); 101 102 void autri_powerhook(int why,void *addr); 103 int autri_init(void *sc); 104 struct autri_dma *autri_find_dma(struct autri_softc *, void *); 105 void autri_setup_channel(struct autri_softc *sc,int mode, 106 struct audio_params *param); 107 void autri_enable_interrupt(struct autri_softc *sc, int ch); 108 void autri_disable_interrupt(struct autri_softc *sc, int ch); 109 void autri_startch(struct autri_softc *sc, int ch, int ch_intr); 110 void autri_stopch(struct autri_softc *sc, int ch, int ch_intr); 111 void autri_enable_loop_interrupt(void *sc); 112 #if 0 113 void autri_disable_loop_interrupt(void *sc); 114 #endif 115 116 struct cfdriver autri_cd = { 117 NULL, "autri", DV_DULL 118 }; 119 120 struct cfattach autri_ca = { 121 sizeof(struct autri_softc), autri_match, autri_attach 122 }; 123 124 int autri_open(void *, int); 125 void autri_close(void *); 126 int autri_query_encoding(void *, struct audio_encoding *); 127 int autri_set_params(void *, int, int, struct audio_params *, 128 struct audio_params *); 129 int autri_round_blocksize(void *, int); 130 int autri_trigger_output(void *, void *, void *, int, void (*)(void *), 131 void *, struct audio_params *); 132 int autri_trigger_input(void *, void *, void *, int, void (*)(void *), 133 void *, struct audio_params *); 134 int autri_halt_output(void *); 135 int autri_halt_input(void *); 136 int autri_getdev(void *, struct audio_device *); 137 int autri_mixer_set_port(void *, mixer_ctrl_t *); 138 int autri_mixer_get_port(void *, mixer_ctrl_t *); 139 void *autri_malloc(void *, int, size_t, int, int); 140 void autri_free(void *, void *, int); 141 size_t autri_round_buffersize(void *, int, size_t); 142 paddr_t autri_mappage(void *, void *, off_t, int); 143 int autri_get_props(void *); 144 int autri_query_devinfo(void *addr, mixer_devinfo_t *dip); 145 146 int autri_get_portnum_by_name(struct autri_softc *, char *, char *, char *); 147 148 struct audio_hw_if autri_hw_if = { 149 autri_open, 150 autri_close, 151 NULL, /* drain */ 152 autri_query_encoding, 153 autri_set_params, 154 autri_round_blocksize, 155 NULL, /* commit_settings */ 156 NULL, /* init_output */ 157 NULL, /* init_input */ 158 NULL, /* start_output */ 159 NULL, /* start_input */ 160 autri_halt_output, 161 autri_halt_input, 162 NULL, /* speaker_ctl */ 163 autri_getdev, 164 NULL, /* setfd */ 165 autri_mixer_set_port, 166 autri_mixer_get_port, 167 autri_query_devinfo, 168 autri_malloc, 169 autri_free, 170 autri_round_buffersize, 171 autri_mappage, 172 autri_get_props, 173 autri_trigger_output, 174 autri_trigger_input, 175 }; 176 177 #if NMIDI > 0 178 void autri_midi_close(void *); 179 void autri_midi_getinfo(void *, struct midi_info *); 180 int autri_midi_open(void *, int, void (*)(void *, int), 181 void (*)(void *), void *); 182 int autri_midi_output(void *, int); 183 184 struct midi_hw_if autri_midi_hw_if = { 185 autri_midi_open, 186 autri_midi_close, 187 autri_midi_output, 188 autri_midi_getinfo, 189 NULL, /* ioctl */ 190 }; 191 #endif 192 193 /* 194 * register set/clear bit 195 */ 196 static __inline void 197 autri_reg_set_1(sc, no, mask) 198 struct autri_softc *sc; 199 int no; 200 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 206 static __inline void 207 autri_reg_clear_1(sc, no, mask) 208 struct autri_softc *sc; 209 int no; 210 uint8_t mask; 211 { 212 bus_space_write_1(sc->memt, sc->memh, no, 213 (bus_space_read_1(sc->memt, sc->memh, no) & ~mask)); 214 } 215 216 static __inline void 217 autri_reg_set_4(sc, no, mask) 218 struct autri_softc *sc; 219 int no; 220 uint32_t mask; 221 { 222 bus_space_write_4(sc->memt, sc->memh, no, 223 (bus_space_read_4(sc->memt, sc->memh, no) | mask)); 224 } 225 226 static __inline void 227 autri_reg_clear_4(sc, no, mask) 228 struct autri_softc *sc; 229 int no; 230 uint32_t mask; 231 { 232 bus_space_write_4(sc->memt, sc->memh, no, 233 (bus_space_read_4(sc->memt, sc->memh, no) & ~mask)); 234 } 235 236 /* 237 * AC97 codec 238 */ 239 int 240 autri_attach_codec(sc_, codec_if) 241 void *sc_; 242 struct ac97_codec_if *codec_if; 243 { 244 struct autri_codec_softc *sc = sc_; 245 246 DPRINTF(("autri_attach_codec()\n")); 247 248 sc->codec_if = codec_if; 249 return 0; 250 } 251 252 int 253 autri_read_codec(sc_, index, data) 254 void *sc_; 255 u_int8_t index; 256 u_int16_t *data; 257 { 258 struct autri_codec_softc *codec = sc_; 259 struct autri_softc *sc = codec->sc; 260 u_int32_t status, addr, cmd, busy; 261 u_int16_t count; 262 263 /*DPRINTF(("sc->sc->type : 0x%X",sc->sc->type));*/ 264 265 switch (sc->sc_devid) { 266 case AUTRI_DEVICE_ID_4DWAVE_DX: 267 addr = AUTRI_DX_ACR1; 268 cmd = AUTRI_DX_ACR1_CMD_READ; 269 busy = AUTRI_DX_ACR1_BUSY_READ; 270 break; 271 case AUTRI_DEVICE_ID_4DWAVE_NX: 272 addr = AUTRI_NX_ACR2; 273 cmd = AUTRI_NX_ACR2_CMD_READ; 274 busy = AUTRI_NX_ACR2_BUSY_READ | AUTRI_NX_ACR2_RECV_WAIT; 275 break; 276 case AUTRI_DEVICE_ID_SIS_7018: 277 addr = AUTRI_SIS_ACRD; 278 cmd = AUTRI_SIS_ACRD_CMD_READ; 279 busy = AUTRI_SIS_ACRD_BUSY_READ | AUTRI_SIS_ACRD_AUDIO_BUSY; 280 break; 281 case AUTRI_DEVICE_ID_ALI_M5451: 282 if (sc->sc_revision > 0x01) 283 addr = AUTRI_ALI_ACWR; 284 else 285 addr = AUTRI_ALI_ACRD; 286 cmd = AUTRI_ALI_ACRD_CMD_READ; 287 busy = AUTRI_ALI_ACRD_BUSY_READ; 288 break; 289 default: 290 printf("%s: autri_read_codec : unknown device\n", 291 sc->sc_dev.dv_xname); 292 return -1; 293 } 294 295 /* wait for 'Ready to Read' */ 296 for (count=0; count < 0xffff; count++) { 297 if ((TREAD4(sc, addr) & busy) == 0) 298 break; 299 DELAY(1); 300 } 301 302 if (count == 0xffff) { 303 printf("%s: Codec timeout. Busy reading AC97 codec.\n", 304 sc->sc_dev.dv_xname); 305 return -1; 306 } 307 308 /* send Read Command to AC97 */ 309 TWRITE4(sc, addr, (index & 0x7f) | cmd); 310 311 /* wait for 'Returned data is avalable' */ 312 for (count=0; count < 0xffff; count++) { 313 status = TREAD4(sc, addr); 314 if ((status & busy) == 0) 315 break; 316 DELAY(1); 317 } 318 319 if (count == 0xffff) { 320 printf("%s: Codec timeout. Busy reading AC97 codec.\n", 321 sc->sc_dev.dv_xname); 322 return -1; 323 } 324 325 *data = (status >> 16) & 0x0000ffff; 326 /*DPRINTF(("autri_read_codec(0x%X) return 0x%X\n",reg,*data));*/ 327 return 0; 328 } 329 330 int 331 autri_write_codec(sc_, index, data) 332 void *sc_; 333 u_int8_t index; 334 u_int16_t data; 335 { 336 struct autri_codec_softc *codec = sc_; 337 struct autri_softc *sc = codec->sc; 338 u_int32_t addr, cmd, busy; 339 u_int16_t count; 340 341 /*DPRINTF(("autri_write_codec(0x%X,0x%X)\n",index,data));*/ 342 343 switch (sc->sc_devid) { 344 case AUTRI_DEVICE_ID_4DWAVE_DX: 345 addr = AUTRI_DX_ACR0; 346 cmd = AUTRI_DX_ACR0_CMD_WRITE; 347 busy = AUTRI_DX_ACR0_BUSY_WRITE; 348 break; 349 case AUTRI_DEVICE_ID_4DWAVE_NX: 350 addr = AUTRI_NX_ACR1; 351 cmd = AUTRI_NX_ACR1_CMD_WRITE; 352 busy = AUTRI_NX_ACR1_BUSY_WRITE; 353 break; 354 case AUTRI_DEVICE_ID_SIS_7018: 355 addr = AUTRI_SIS_ACWR; 356 cmd = AUTRI_SIS_ACWR_CMD_WRITE; 357 busy = AUTRI_SIS_ACWR_BUSY_WRITE | AUTRI_SIS_ACWR_AUDIO_BUSY; 358 break; 359 case AUTRI_DEVICE_ID_ALI_M5451: 360 addr = AUTRI_ALI_ACWR; 361 cmd = AUTRI_ALI_ACWR_CMD_WRITE; 362 if (sc->sc_revision > 0x01) 363 cmd |= 0x0100; 364 busy = AUTRI_ALI_ACWR_BUSY_WRITE; 365 break; 366 default: 367 printf("%s: autri_write_codec : unknown device.\n", 368 sc->sc_dev.dv_xname); 369 return -1; 370 } 371 372 /* wait for 'Ready to Write' */ 373 for (count=0; count < 0xffff; count++) { 374 if ((TREAD4(sc, addr) & busy) == 0) 375 break; 376 DELAY(1); 377 } 378 379 if (count == 0xffff) { 380 printf("%s: Codec timeout. Busy writing AC97 codec\n", 381 sc->sc_dev.dv_xname); 382 return -1; 383 } 384 385 /* send Write Command to AC97 */ 386 TWRITE4(sc, addr, (data << 16) | (index & 0x7f) | cmd); 387 388 return 0; 389 } 390 391 void 392 autri_reset_codec(sc_) 393 void *sc_; 394 { 395 struct autri_codec_softc *codec = sc_; 396 struct autri_softc *sc = codec->sc; 397 u_int32_t reg, ready; 398 int addr, count = 200; 399 400 DPRINTF(("autri_reset_codec(codec=%p,sc=%p)\n",codec,sc)); 401 DPRINTF(("sc->sc_devid=%X\n",sc->sc_devid)); 402 403 switch (sc->sc_devid) { 404 case AUTRI_DEVICE_ID_4DWAVE_DX: 405 /* warm reset AC97 codec */ 406 autri_reg_set_4(sc, AUTRI_DX_ACR2, 1); 407 delay(100); 408 /* release reset */ 409 autri_reg_clear_4(sc, AUTRI_DX_ACR2, 1); 410 delay(100); 411 412 addr = AUTRI_DX_ACR2; 413 ready = AUTRI_DX_ACR2_CODEC_READY; 414 break; 415 case AUTRI_DEVICE_ID_4DWAVE_NX: 416 /* warm reset AC97 codec */ 417 autri_reg_set_4(sc, AUTRI_NX_ACR0, 1); 418 delay(100); 419 /* release reset */ 420 autri_reg_clear_4(sc, AUTRI_NX_ACR0, 1); 421 delay(100); 422 423 addr = AUTRI_NX_ACR0; 424 ready = AUTRI_NX_ACR0_CODEC_READY; 425 break; 426 case AUTRI_DEVICE_ID_SIS_7018: 427 /* warm reset AC97 codec */ 428 autri_reg_set_4(sc, AUTRI_SIS_SCTRL, 2); 429 delay(1000); 430 /* release reset (warm & cold) */ 431 autri_reg_clear_4(sc, AUTRI_SIS_SCTRL, 3); 432 delay(2000); 433 434 addr = AUTRI_SIS_SCTRL; 435 ready = AUTRI_SIS_SCTRL_CODEC_READY; 436 break; 437 case AUTRI_DEVICE_ID_ALI_M5451: 438 /* warm reset AC97 codec */ 439 autri_reg_set_4(sc, AUTRI_ALI_SCTRL, 1); 440 delay(100); 441 /* release reset (warm & cold) */ 442 autri_reg_clear_4(sc, AUTRI_ALI_SCTRL, 3); 443 delay(100); 444 445 addr = AUTRI_ALI_SCTRL; 446 ready = AUTRI_ALI_SCTRL_CODEC_READY; 447 break; 448 } 449 450 /* wait for 'Codec Ready' */ 451 while (count--) { 452 reg = TREAD4(sc, addr); 453 if (reg & ready) 454 break; 455 delay(1000); 456 } 457 458 if (count == 0) 459 printf("%s: Codec timeout. AC97 is not ready for operation.\n", 460 sc->sc_dev.dv_xname); 461 } 462 463 enum ac97_host_flags 464 autri_flags_codec(void *v) 465 { 466 struct autri_codec_softc *sc = v; 467 468 return (sc->flags); 469 } 470 471 /* 472 * 473 */ 474 const struct pci_matchid autri_devices[] = { 475 { PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_4DWAVE_DX }, 476 { PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_4DWAVE_NX }, 477 { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7018 }, 478 { PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5451 }, 479 }; 480 481 int 482 autri_match(parent, match, aux) 483 struct device *parent; 484 void *match; 485 void *aux; 486 { 487 return (pci_matchbyid((struct pci_attach_args *)aux, autri_devices, 488 sizeof(autri_devices)/sizeof(autri_devices[0]))); 489 } 490 491 void 492 autri_attach(parent, self, aux) 493 struct device *parent; 494 struct device *self; 495 void *aux; 496 { 497 struct autri_softc *sc = (struct autri_softc *)self; 498 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 499 pci_chipset_tag_t pc = pa->pa_pc; 500 struct autri_codec_softc *codec; 501 bus_size_t iosize; 502 pci_intr_handle_t ih; 503 char const *intrstr; 504 mixer_ctrl_t ctl; 505 int i, r; 506 u_int32_t reg; 507 508 sc->sc_devid = pa->pa_id; 509 sc->sc_class = pa->pa_class; 510 sc->sc_revision = PCI_REVISION(pa->pa_class); 511 512 /* map register to memory */ 513 if (pci_mapreg_map(pa, AUTRI_PCI_MEMORY_BASE, 514 PCI_MAPREG_TYPE_MEM, 0, &sc->memt, &sc->memh, NULL, &iosize, 0)) { 515 printf("%s: can't map memory space\n", sc->sc_dev.dv_xname); 516 return; 517 } 518 519 /* map and establish the interrupt */ 520 if (pci_intr_map(pa, &ih)) { 521 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); 522 bus_space_unmap(sc->memt, sc->memh, iosize); 523 return; 524 } 525 intrstr = pci_intr_string(pc, ih); 526 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, autri_intr, sc, 527 sc->sc_dev.dv_xname); 528 if (sc->sc_ih == NULL) { 529 printf("%s: couldn't establish interrupt", 530 sc->sc_dev.dv_xname); 531 if (intrstr != NULL) 532 printf(" at %s", intrstr); 533 printf("\n"); 534 bus_space_unmap(sc->memt, sc->memh, iosize); 535 return; 536 } 537 printf(": %s\n", intrstr); 538 539 sc->sc_dmatag = pa->pa_dmat; 540 sc->sc_pc = pc; 541 sc->sc_pt = pa->pa_tag; 542 543 /* enable the device */ 544 reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 545 reg |= (PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE); 546 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg); 547 548 /* initialize the device */ 549 autri_init(sc); 550 551 /* attach AC97 codec */ 552 codec = &sc->sc_codec; 553 memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev)); 554 codec->sc = sc; 555 556 codec->host_if.arg = codec; 557 codec->host_if.attach = autri_attach_codec; 558 codec->host_if.reset = autri_reset_codec; 559 codec->host_if.read = autri_read_codec; 560 codec->host_if.write = autri_write_codec; 561 codec->host_if.flags = autri_flags_codec; 562 codec->flags = AC97_HOST_DONT_READ | AC97_HOST_SWAPPED_CHANNELS; 563 if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001) 564 codec->flags &= ~AC97_HOST_SWAPPED_CHANNELS; 565 566 if ((r = ac97_attach(&codec->host_if)) != 0) { 567 printf("%s: can't attach codec (error 0x%X)\n", 568 sc->sc_dev.dv_xname, r); 569 pci_intr_disestablish(pc, sc->sc_ih); 570 bus_space_unmap(sc->memt, sc->memh, iosize); 571 return; 572 } 573 574 /* disable mutes */ 575 for (i = 0; i < 4; i++) { 576 static struct { 577 char *class, *device; 578 } d[] = { 579 { AudioCoutputs, AudioNmaster}, 580 { AudioCinputs, AudioNdac}, 581 { AudioCinputs, AudioNcd}, 582 { AudioCrecord, AudioNvolume}, 583 }; 584 585 ctl.type = AUDIO_MIXER_ENUM; 586 ctl.un.ord = 0; 587 588 #if 0 589 ctl.dev = sc->sc_codec.codec_if->vtbl->get_portnum_by_name(sc->sc_codec.codec_if, 590 d[i].class, d[i].device, AudioNmute); 591 #endif 592 ctl.dev = autri_get_portnum_by_name(sc,d[i].class, 593 d[i].device, AudioNmute); 594 autri_mixer_set_port(sc, &ctl); 595 } 596 597 /* set a reasonable default volume */ 598 ctl.type = AUDIO_MIXER_VALUE; 599 ctl.un.value.num_channels = 2; 600 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 601 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127; 602 603 ctl.dev = autri_get_portnum_by_name(sc,AudioCoutputs,AudioNmaster,NULL); 604 autri_mixer_set_port(sc, &ctl); 605 606 audio_attach_mi(&autri_hw_if, sc, &sc->sc_dev); 607 608 #if NMIDI > 0 609 midi_attach_mi(&autri_midi_hw_if, sc, &sc->sc_dev); 610 #endif 611 612 sc->sc_old_power = PWR_RESUME; 613 powerhook_establish(autri_powerhook, sc); 614 } 615 616 void 617 autri_powerhook(int why,void *addr) 618 { 619 struct autri_softc *sc = addr; 620 621 if (why == PWR_RESUME && sc->sc_old_power == PWR_SUSPEND) { 622 DPRINTF(("PWR_RESUME\n")); 623 autri_init(sc); 624 /*autri_reset_codec(&sc->sc_codec);*/ 625 (sc->sc_codec.codec_if->vtbl->restore_ports)(sc->sc_codec.codec_if); 626 } 627 sc->sc_old_power = why; 628 } 629 630 int 631 autri_init(sc_) 632 void *sc_; 633 { 634 struct autri_softc *sc = sc_; 635 u_int32_t reg; 636 637 pci_chipset_tag_t pc = sc->sc_pc; 638 pcitag_t pt = sc->sc_pt; 639 640 DPRINTF(("in autri_init()\n")); 641 DPRINTFN(5,("pci_conf_read(0x40) : 0x%X\n",pci_conf_read(pc,pt,0x40))); 642 DPRINTFN(5,("pci_conf_read(0x44) : 0x%X\n",pci_conf_read(pc,pt,0x44))); 643 644 switch (sc->sc_devid) { 645 case AUTRI_DEVICE_ID_4DWAVE_DX: 646 /* disable Legacy Control */ 647 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0); 648 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 649 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000); 650 delay(100); 651 /* audio engine reset */ 652 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 653 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00040000); 654 delay(100); 655 /* release reset */ 656 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 657 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000); 658 delay(100); 659 /* DAC on */ 660 autri_reg_set_4(sc,AUTRI_DX_ACR2,0x02); 661 break; 662 case AUTRI_DEVICE_ID_4DWAVE_NX: 663 /* disable Legacy Control */ 664 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0); 665 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 666 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000); 667 delay(100); 668 /* audio engine reset */ 669 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 670 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00010000); 671 delay(100); 672 /* release reset */ 673 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 674 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00010000); 675 delay(100); 676 /* DAC on */ 677 autri_reg_set_4(sc,AUTRI_NX_ACR0,0x02); 678 break; 679 case AUTRI_DEVICE_ID_SIS_7018: 680 /* disable Legacy Control */ 681 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0); 682 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 683 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000); 684 delay(100); 685 /* reset Digital Controller */ 686 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 687 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000); 688 delay(100); 689 /* release reset */ 690 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 691 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000); 692 delay(100); 693 /* disable AC97 GPIO interrupt */ 694 TWRITE1(sc, AUTRI_SIS_ACGPIO, 0); 695 /* enable 64 channel mode */ 696 autri_reg_set_4(sc, AUTRI_LFO_GC_CIR, BANK_B_EN); 697 break; 698 case AUTRI_DEVICE_ID_ALI_M5451: 699 /* disable Legacy Control */ 700 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0); 701 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 702 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000); 703 delay(100); 704 /* reset Digital Controller */ 705 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 706 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000); 707 delay(100); 708 /* release reset */ 709 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE); 710 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000); 711 delay(100); 712 /* enable PCM input */ 713 autri_reg_set_4(sc, AUTRI_ALI_GCONTROL, AUTRI_ALI_GCONTROL_PCM_IN); 714 break; 715 } 716 717 if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) { 718 sc->sc_play.ch = 0; 719 sc->sc_play.ch_intr = 1; 720 sc->sc_rec.ch = 31; 721 sc->sc_rec.ch_intr = 2; 722 } else { 723 sc->sc_play.ch = 0x20; 724 sc->sc_play.ch_intr = 0x21; 725 sc->sc_rec.ch = 0x22; 726 sc->sc_rec.ch_intr = 0x23; 727 } 728 729 /* clear channel status */ 730 TWRITE4(sc, AUTRI_STOP_A, 0xffffffff); 731 TWRITE4(sc, AUTRI_STOP_B, 0xffffffff); 732 733 /* disable channel interrupt */ 734 TWRITE4(sc, AUTRI_AINTEN_A, 0); 735 TWRITE4(sc, AUTRI_AINTEN_B, 0); 736 737 #if 0 738 /* TLB */ 739 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) { 740 TWRITE4(sc,AUTRI_NX_TLBC,0); 741 } 742 #endif 743 744 autri_enable_loop_interrupt(sc); 745 746 DPRINTF(("out autri_init()\n")); 747 return 0; 748 } 749 750 void 751 autri_enable_loop_interrupt(sc_) 752 void *sc_; 753 { 754 struct autri_softc *sc = sc_; 755 u_int32_t reg; 756 757 /*reg = (ENDLP_IE | MIDLP_IE);*/ 758 reg = ENDLP_IE; 759 #if 0 760 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) 761 reg |= BANK_B_EN; 762 #endif 763 autri_reg_set_4(sc,AUTRI_LFO_GC_CIR,reg); 764 } 765 766 #if 0 767 void 768 autri_disable_loop_interrupt(sc_) 769 void *sc_; 770 { 771 struct autri_softc *sc = sc_; 772 u_int32_t reg; 773 774 reg = (ENDLP_IE | MIDLP_IE); 775 autri_reg_clear_4(sc,AUTRI_LFO_GC_CIR,reg); 776 } 777 #endif 778 779 int 780 autri_intr(p) 781 void *p; 782 { 783 struct autri_softc *sc = p; 784 u_int32_t intsrc; 785 u_int32_t mask, active[2]; 786 int ch, endch; 787 /* 788 u_int32_t reg; 789 u_int32_t cso,eso; 790 */ 791 792 intsrc = TREAD4(sc,AUTRI_MISCINT); 793 if ((intsrc & (ADDRESS_IRQ|MPU401_IRQ)) == 0) 794 return 0; 795 796 if (intsrc & ADDRESS_IRQ) { 797 798 active[0] = TREAD4(sc,AUTRI_AIN_A); 799 active[1] = TREAD4(sc,AUTRI_AIN_B); 800 801 if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) { 802 endch = 32; 803 } else { 804 endch = 64; 805 } 806 807 for (ch=0; ch<endch; ch++) { 808 mask = 1 << (ch & 0x1f); 809 if (active[(ch & 0x20) ? 1 : 0] & mask) { 810 811 /* clear interupt */ 812 TWRITE4(sc, (ch & 0x20) ? AUTRI_AIN_B : AUTRI_AIN_A, mask); 813 /* disable interupt */ 814 autri_reg_clear_4(sc,(ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask); 815 #if 0 816 reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f; 817 TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | ch); 818 819 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) { 820 cso = TREAD4(sc, 0xe0) & 0x00ffffff; 821 eso = TREAD4(sc, 0xe8) & 0x00ffffff; 822 } else { 823 cso = (TREAD4(sc, 0xe0) >> 16) & 0x0000ffff; 824 eso = (TREAD4(sc, 0xe8) >> 16) & 0x0000ffff; 825 } 826 /*printf("cso=%d, eso=%d\n",cso,eso);*/ 827 #endif 828 if (ch == sc->sc_play.ch_intr) { 829 if (sc->sc_play.intr) 830 sc->sc_play.intr(sc->sc_play.intr_arg); 831 } 832 833 if (ch == sc->sc_rec.ch_intr) { 834 if (sc->sc_rec.intr) 835 sc->sc_rec.intr(sc->sc_rec.intr_arg); 836 } 837 838 /* enable interrupt */ 839 autri_reg_set_4(sc, (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask); 840 } 841 } 842 } 843 844 if (intsrc & MPU401_IRQ) { 845 /* XXX */ 846 } 847 848 autri_reg_set_4(sc,AUTRI_MISCINT, 849 ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW); 850 851 return 1; 852 } 853 854 /* 855 * 856 */ 857 858 int 859 autri_allocmem(sc, size, align, p) 860 struct autri_softc *sc; 861 size_t size; 862 size_t align; 863 struct autri_dma *p; 864 { 865 int error; 866 867 p->size = size; 868 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0, 869 p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 870 &p->nsegs, BUS_DMA_NOWAIT); 871 if (error) 872 return (error); 873 874 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 875 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 876 if (error) 877 goto free; 878 879 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size, 880 0, BUS_DMA_NOWAIT, &p->map); 881 if (error) 882 goto unmap; 883 884 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 885 BUS_DMA_NOWAIT); 886 if (error) 887 goto destroy; 888 return (0); 889 890 destroy: 891 bus_dmamap_destroy(sc->sc_dmatag, p->map); 892 unmap: 893 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 894 free: 895 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 896 return (error); 897 } 898 899 int 900 autri_freemem(sc, p) 901 struct autri_softc *sc; 902 struct autri_dma *p; 903 { 904 bus_dmamap_unload(sc->sc_dmatag, p->map); 905 bus_dmamap_destroy(sc->sc_dmatag, p->map); 906 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 907 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 908 return 0; 909 } 910 911 int 912 autri_open(addr, flags) 913 void *addr; 914 int flags; 915 { 916 DPRINTF(("autri_open()\n")); 917 DPRINTFN(5,("MISCINT : 0x%08X\n", 918 TREAD4((struct autri_softc *)addr, AUTRI_MISCINT))); 919 DPRINTFN(5,("LFO_GC_CIR : 0x%08X\n", 920 TREAD4((struct autri_softc *)addr, AUTRI_LFO_GC_CIR))); 921 return 0; 922 } 923 924 void 925 autri_close(addr) 926 void *addr; 927 { 928 DPRINTF(("autri_close()\n")); 929 } 930 931 int 932 autri_query_encoding(addr, fp) 933 void *addr; 934 struct audio_encoding *fp; 935 { 936 switch (fp->index) { 937 case 0: 938 strlcpy(fp->name, AudioEulinear, sizeof fp->name); 939 fp->encoding = AUDIO_ENCODING_ULINEAR; 940 fp->precision = 8; 941 fp->flags = 0; 942 break; 943 case 1: 944 strlcpy(fp->name, AudioEmulaw, sizeof fp->name); 945 fp->encoding = AUDIO_ENCODING_ULAW; 946 fp->precision = 8; 947 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 948 break; 949 case 2: 950 strlcpy(fp->name, AudioEalaw, sizeof fp->name); 951 fp->encoding = AUDIO_ENCODING_ALAW; 952 fp->precision = 8; 953 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 954 break; 955 case 3: 956 strlcpy(fp->name, AudioEslinear, sizeof fp->name); 957 fp->encoding = AUDIO_ENCODING_SLINEAR; 958 fp->precision = 8; 959 fp->flags = 0; 960 break; 961 case 4: 962 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name); 963 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 964 fp->precision = 16; 965 fp->flags = 0; 966 break; 967 case 5: 968 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name); 969 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 970 fp->precision = 16; 971 fp->flags = 0; 972 break; 973 case 6: 974 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name); 975 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 976 fp->precision = 16; 977 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 978 break; 979 case 7: 980 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name); 981 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 982 fp->precision = 16; 983 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 984 break; 985 default: 986 return (EINVAL); 987 } 988 989 return 0; 990 } 991 992 int 993 autri_set_params(addr, setmode, usemode, play, rec) 994 void *addr; 995 int setmode, usemode; 996 struct audio_params *play, *rec; 997 { 998 struct audio_params *p; 999 int mode; 1000 1001 for (mode = AUMODE_RECORD; mode != -1; 1002 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 1003 if ((setmode & mode) == 0) 1004 continue; 1005 1006 p = mode == AUMODE_PLAY ? play : rec; 1007 1008 if (p->sample_rate < 4000 || p->sample_rate > 48000 || 1009 (p->precision != 8 && p->precision != 16) || 1010 (p->channels != 1 && p->channels != 2)) 1011 return (EINVAL); 1012 1013 p->factor = 1; 1014 p->sw_code = 0; 1015 switch (p->encoding) { 1016 case AUDIO_ENCODING_SLINEAR_BE: 1017 case AUDIO_ENCODING_ULINEAR_BE: 1018 if (p->precision == 16) 1019 p->sw_code = swap_bytes; 1020 break; 1021 case AUDIO_ENCODING_SLINEAR_LE: 1022 case AUDIO_ENCODING_ULINEAR_LE: 1023 break; 1024 case AUDIO_ENCODING_ULAW: 1025 if (mode == AUMODE_PLAY) 1026 p->sw_code = mulaw_to_ulinear8; 1027 else 1028 p->sw_code = ulinear8_to_mulaw; 1029 1030 break; 1031 case AUDIO_ENCODING_ALAW: 1032 if (mode == AUMODE_PLAY) 1033 p->sw_code = alaw_to_ulinear8; 1034 else 1035 p->sw_code = ulinear8_to_alaw; 1036 1037 break; 1038 default: 1039 return (EINVAL); 1040 } 1041 } 1042 1043 return 0; 1044 } 1045 1046 int 1047 autri_round_blocksize(addr, block) 1048 void *addr; 1049 int block; 1050 { 1051 return (block & -4); 1052 } 1053 1054 int 1055 autri_halt_output(addr) 1056 void *addr; 1057 { 1058 struct autri_softc *sc = addr; 1059 1060 DPRINTF(("autri_halt_output()\n")); 1061 1062 sc->sc_play.intr = NULL; 1063 autri_stopch(sc, sc->sc_play.ch, sc->sc_play.ch_intr); 1064 autri_disable_interrupt(sc, sc->sc_play.ch_intr); 1065 1066 return 0; 1067 } 1068 1069 int 1070 autri_halt_input(addr) 1071 void *addr; 1072 { 1073 struct autri_softc *sc = addr; 1074 1075 DPRINTF(("autri_halt_input()\n")); 1076 1077 sc->sc_rec.intr = NULL; 1078 autri_stopch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr); 1079 autri_disable_interrupt(sc, sc->sc_rec.ch_intr); 1080 1081 return 0; 1082 } 1083 1084 int 1085 autri_getdev(addr, retp) 1086 void *addr; 1087 struct audio_device *retp; 1088 { 1089 struct autri_softc *sc = addr; 1090 1091 DPRINTF(("autri_getdev().\n")); 1092 1093 strncpy(retp->name, "Trident 4DWAVE", sizeof(retp->name)); 1094 snprintf(retp->version, sizeof(retp->version), "0x%02x", 1095 PCI_REVISION(sc->sc_class)); 1096 1097 switch (sc->sc_devid) { 1098 case AUTRI_DEVICE_ID_4DWAVE_DX: 1099 strncpy(retp->config, "4DWAVE-DX", sizeof(retp->config)); 1100 break; 1101 case AUTRI_DEVICE_ID_4DWAVE_NX: 1102 strncpy(retp->config, "4DWAVE-NX", sizeof(retp->config)); 1103 break; 1104 case AUTRI_DEVICE_ID_SIS_7018: 1105 strncpy(retp->config, "SiS 7018", sizeof(retp->config)); 1106 break; 1107 case AUTRI_DEVICE_ID_ALI_M5451: 1108 strncpy(retp->config, "ALi M5451", sizeof(retp->config)); 1109 break; 1110 default: 1111 strncpy(retp->config, "unknown", sizeof(retp->config)); 1112 } 1113 1114 return 0; 1115 } 1116 1117 int 1118 autri_mixer_set_port(addr, cp) 1119 void *addr; 1120 mixer_ctrl_t *cp; 1121 { 1122 struct autri_softc *sc = addr; 1123 1124 return (sc->sc_codec.codec_if->vtbl->mixer_set_port( 1125 sc->sc_codec.codec_if, cp)); 1126 } 1127 1128 int 1129 autri_mixer_get_port(addr, cp) 1130 void *addr; 1131 mixer_ctrl_t *cp; 1132 { 1133 struct autri_softc *sc = addr; 1134 1135 return (sc->sc_codec.codec_if->vtbl->mixer_get_port( 1136 sc->sc_codec.codec_if, cp)); 1137 } 1138 1139 int 1140 autri_query_devinfo(addr, dip) 1141 void *addr; 1142 mixer_devinfo_t *dip; 1143 { 1144 struct autri_softc *sc = addr; 1145 1146 return (sc->sc_codec.codec_if->vtbl->query_devinfo( 1147 sc->sc_codec.codec_if, dip)); 1148 } 1149 1150 int 1151 autri_get_portnum_by_name(sc, class, device, qualifier) 1152 struct autri_softc *sc; 1153 char *class, *device, *qualifier; 1154 { 1155 return (sc->sc_codec.codec_if->vtbl->get_portnum_by_name( 1156 sc->sc_codec.codec_if, class, device, qualifier)); 1157 } 1158 1159 void * 1160 autri_malloc(addr, direction, size, pool, flags) 1161 void *addr; 1162 int direction; 1163 size_t size; 1164 int pool, flags; 1165 { 1166 struct autri_softc *sc = addr; 1167 struct autri_dma *p; 1168 int error; 1169 1170 p = malloc(sizeof(*p), pool, flags); 1171 if (!p) 1172 return NULL; 1173 1174 #if 0 1175 error = autri_allocmem(sc, size, 16, p); 1176 #endif 1177 error = autri_allocmem(sc, size, 0x10000, p); 1178 if (error) { 1179 free(p, pool); 1180 return NULL; 1181 } 1182 1183 p->next = sc->sc_dmas; 1184 sc->sc_dmas = p; 1185 return KERNADDR(p); 1186 } 1187 1188 void 1189 autri_free(addr, ptr, pool) 1190 void *addr; 1191 void *ptr; 1192 int pool; 1193 { 1194 struct autri_softc *sc = addr; 1195 struct autri_dma **pp, *p; 1196 1197 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) { 1198 if (KERNADDR(p) == ptr) { 1199 autri_freemem(sc, p); 1200 *pp = p->next; 1201 free(p, pool); 1202 return; 1203 } 1204 } 1205 } 1206 1207 struct autri_dma * 1208 autri_find_dma(sc, addr) 1209 struct autri_softc *sc; 1210 void *addr; 1211 { 1212 struct autri_dma *p; 1213 1214 for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next) 1215 ; 1216 1217 return p; 1218 } 1219 1220 size_t 1221 autri_round_buffersize(addr, direction, size) 1222 void *addr; 1223 int direction; 1224 size_t size; 1225 { 1226 return size; 1227 } 1228 1229 paddr_t 1230 autri_mappage(addr, mem, off, prot) 1231 void *addr; 1232 void *mem; 1233 off_t off; 1234 int prot; 1235 { 1236 struct autri_softc *sc = addr; 1237 struct autri_dma *p; 1238 1239 if (off < 0) 1240 return (-1); 1241 1242 p = autri_find_dma(sc, mem); 1243 if (!p) 1244 return (-1); 1245 1246 return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, 1247 off, prot, BUS_DMA_WAITOK)); 1248 } 1249 1250 int 1251 autri_get_props(addr) 1252 void *addr; 1253 { 1254 return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | 1255 AUDIO_PROP_FULLDUPLEX); 1256 } 1257 1258 void 1259 autri_setup_channel(sc, mode, param) 1260 struct autri_softc *sc; 1261 int mode; 1262 struct audio_params *param; 1263 { 1264 int i, ch, channel; 1265 u_int32_t reg, cr[5]; 1266 u_int32_t cso, eso; 1267 u_int32_t delta, dch[2], ctrl; 1268 u_int32_t alpha_fms, fm_vol, attribute; 1269 1270 u_int32_t dmaaddr, dmalen; 1271 int factor, rvol, cvol; 1272 struct autri_chstatus *chst; 1273 1274 ctrl = AUTRI_CTRL_LOOPMODE; 1275 switch (param->encoding) { 1276 case AUDIO_ENCODING_SLINEAR_BE: 1277 case AUDIO_ENCODING_SLINEAR_LE: 1278 ctrl |= AUTRI_CTRL_SIGNED; 1279 break; 1280 } 1281 1282 factor = 0; 1283 if (param->precision == 16) { 1284 ctrl |= AUTRI_CTRL_16BIT; 1285 factor++; 1286 } 1287 1288 if (param->channels == 2) { 1289 ctrl |= AUTRI_CTRL_STEREO; 1290 factor++; 1291 } 1292 1293 delta = (u_int32_t)param->sample_rate; 1294 if (delta < 4000) 1295 delta = 4000; 1296 if (delta > 48000) 1297 delta = 48000; 1298 1299 attribute = 0; 1300 1301 dch[1] = ((delta << 12) / 48000) & 0x0000ffff; 1302 if (mode == AUMODE_PLAY) { 1303 chst = &sc->sc_play; 1304 dch[0] = ((delta << 12) / 48000) & 0x0000ffff; 1305 ctrl |= AUTRI_CTRL_WAVEVOL; 1306 /* 1307 if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) 1308 ctrl |= 0x80000000; 1309 */ 1310 } else { 1311 chst = &sc->sc_rec; 1312 dch[0] = ((48000 << 12) / delta) & 0x0000ffff; 1313 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) { 1314 ctrl |= AUTRI_CTRL_MUTE_SIS; 1315 attribute = AUTRI_ATTR_PCMREC_SIS; 1316 if (delta != 48000) 1317 attribute |= AUTRI_ATTR_ENASRC_SIS; 1318 } 1319 ctrl |= AUTRI_CTRL_MUTE; 1320 } 1321 1322 dmaaddr = DMAADDR(chst->dma); 1323 cso = alpha_fms = 0; 1324 rvol = cvol = 0x7f; 1325 fm_vol = 0x0 | ((rvol & 0x7f) << 7) | (cvol & 0x7f); 1326 1327 for (ch=0; ch<2; ch++) { 1328 1329 if (ch == 0) 1330 dmalen = (chst->length >> factor); 1331 else { 1332 /* channel for interrupt */ 1333 dmalen = (chst->blksize >> factor); 1334 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) 1335 ctrl |= AUTRI_CTRL_MUTE_SIS; 1336 else 1337 ctrl |= AUTRI_CTRL_MUTE; 1338 attribute = 0; 1339 } 1340 1341 eso = dmalen - 1; 1342 1343 switch (sc->sc_devid) { 1344 case AUTRI_DEVICE_ID_4DWAVE_DX: 1345 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff); 1346 cr[1] = dmaaddr; 1347 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 1348 cr[3] = fm_vol; 1349 cr[4] = ctrl; 1350 break; 1351 case AUTRI_DEVICE_ID_4DWAVE_NX: 1352 cr[0] = (dch[ch] << 24) | (cso & 0x00ffffff); 1353 cr[1] = dmaaddr; 1354 cr[2] = ((dch[ch] << 16) & 0xff000000) | (eso & 0x00ffffff); 1355 cr[3] = (alpha_fms << 16) | (fm_vol & 0x0000ffff); 1356 cr[4] = ctrl; 1357 break; 1358 case AUTRI_DEVICE_ID_SIS_7018: 1359 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff); 1360 cr[1] = dmaaddr; 1361 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 1362 cr[3] = attribute; 1363 cr[4] = ctrl; 1364 break; 1365 case AUTRI_DEVICE_ID_ALI_M5451: 1366 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff); 1367 cr[1] = dmaaddr; 1368 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 1369 cr[3] = 0; 1370 cr[4] = ctrl; 1371 break; 1372 } 1373 1374 /* write channel data */ 1375 channel = (ch == 0) ? chst->ch : chst->ch_intr; 1376 1377 reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f; 1378 TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | channel); 1379 1380 for (i=0; i<5; i++) { 1381 TWRITE4(sc, AUTRI_ARAM_CR + i*sizeof(cr[0]), cr[i]); 1382 DPRINTFN(5,("cr[%d] : 0x%08X\n", i, cr[i])); 1383 } 1384 1385 /* Bank A only */ 1386 if (channel < 0x20) { 1387 TWRITE4(sc, AUTRI_EBUF1, AUTRI_EMOD_STILL); 1388 TWRITE4(sc, AUTRI_EBUF2, AUTRI_EMOD_STILL); 1389 } 1390 } 1391 1392 } 1393 1394 int 1395 autri_trigger_output(addr, start, end, blksize, intr, arg, param) 1396 void *addr; 1397 void *start, *end; 1398 int blksize; 1399 void (*intr)(void *); 1400 void *arg; 1401 struct audio_params *param; 1402 { 1403 struct autri_softc *sc = addr; 1404 struct autri_dma *p; 1405 1406 DPRINTFN(5,("autri_trigger_output: sc=%p start=%p end=%p " 1407 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 1408 1409 sc->sc_play.intr = intr; 1410 sc->sc_play.intr_arg = arg; 1411 sc->sc_play.offset = 0; 1412 sc->sc_play.blksize = blksize; 1413 sc->sc_play.length = (char *)end - (char *)start; 1414 1415 p = autri_find_dma(sc, start); 1416 if (!p) { 1417 printf("autri_trigger_output: bad addr %p\n", start); 1418 return (EINVAL); 1419 } 1420 1421 sc->sc_play.dma = p; 1422 1423 /* */ 1424 autri_setup_channel(sc, AUMODE_PLAY, param); 1425 1426 /* volume set to no attenuation */ 1427 TWRITE4(sc, AUTRI_MUSICVOL_WAVEVOL, 0); 1428 1429 /* enable interrupt */ 1430 autri_enable_interrupt(sc, sc->sc_play.ch_intr); 1431 1432 /* start channel */ 1433 autri_startch(sc, sc->sc_play.ch, sc->sc_play.ch_intr); 1434 1435 return 0; 1436 } 1437 1438 int 1439 autri_trigger_input(addr, start, end, blksize, intr, arg, param) 1440 void *addr; 1441 void *start, *end; 1442 int blksize; 1443 void (*intr)(void *); 1444 void *arg; 1445 struct audio_params *param; 1446 { 1447 struct autri_softc *sc = addr; 1448 struct autri_dma *p; 1449 1450 DPRINTFN(5,("autri_trigger_input: sc=%p start=%p end=%p " 1451 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 1452 1453 sc->sc_rec.intr = intr; 1454 sc->sc_rec.intr_arg = arg; 1455 sc->sc_rec.offset = 0; 1456 sc->sc_rec.blksize = blksize; 1457 sc->sc_rec.length = (char *)end - (char *)start; 1458 1459 /* */ 1460 p = autri_find_dma(sc, start); 1461 if (!p) { 1462 printf("autri_trigger_input: bad addr %p\n", start); 1463 return (EINVAL); 1464 } 1465 1466 sc->sc_rec.dma = p; 1467 1468 /* */ 1469 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) { 1470 autri_reg_set_4(sc, AUTRI_NX_ACR0, AUTRI_NX_ACR0_PSB_CAPTURE); 1471 TWRITE1(sc, AUTRI_NX_RCI3, AUTRI_NX_RCI3_ENABLE | sc->sc_rec.ch); 1472 } 1473 1474 #if 0 1475 /* 4DWAVE only allows capturing at a 48KHz rate */ 1476 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_DX || 1477 sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) 1478 param->sample_rate = 48000; 1479 #endif 1480 1481 autri_setup_channel(sc, AUMODE_RECORD, param); 1482 1483 /* enable interrupt */ 1484 autri_enable_interrupt(sc, sc->sc_rec.ch_intr); 1485 1486 /* start channel */ 1487 autri_startch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr); 1488 1489 return 0; 1490 } 1491 1492 #if 0 1493 int 1494 autri_halt(sc) 1495 struct autri_softc *sc; 1496 { 1497 DPRINTF(("autri_halt().\n")); 1498 /*autri_stopch(sc);*/ 1499 autri_disable_interrupt(sc, sc->sc_play.channel); 1500 autri_disable_interrupt(sc, sc->sc_rec.channel); 1501 return 0; 1502 } 1503 #endif 1504 1505 void 1506 autri_enable_interrupt(sc, ch) 1507 struct autri_softc *sc; 1508 int ch; 1509 { 1510 int reg; 1511 1512 reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A; 1513 ch &= 0x1f; 1514 1515 autri_reg_set_4(sc, reg, 1 << ch); 1516 } 1517 1518 void 1519 autri_disable_interrupt(sc, ch) 1520 struct autri_softc *sc; 1521 int ch; 1522 { 1523 int reg; 1524 1525 reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A; 1526 ch &= 0x1f; 1527 1528 autri_reg_clear_4(sc, reg, 1 << ch); 1529 } 1530 1531 void 1532 autri_startch(sc, ch, ch_intr) 1533 struct autri_softc *sc; 1534 int ch, ch_intr; 1535 { 1536 int reg; 1537 u_int32_t chmask; 1538 1539 reg = (ch & 0x20) ? AUTRI_START_B : AUTRI_START_A; 1540 ch &= 0x1f; 1541 chmask = (1 << ch) | (1 << ch_intr); 1542 1543 autri_reg_set_4(sc, reg, chmask); 1544 } 1545 1546 void 1547 autri_stopch(sc, ch, ch_intr) 1548 struct autri_softc *sc; 1549 int ch, ch_intr; 1550 { 1551 int reg; 1552 u_int32_t chmask; 1553 1554 reg = (ch & 0x20) ? AUTRI_STOP_B : AUTRI_STOP_A; 1555 ch &= 0x1f; 1556 chmask = (1 << ch) | (1 << ch_intr); 1557 1558 autri_reg_set_4(sc, reg, chmask); 1559 } 1560 1561 #if NMIDI > 0 1562 int 1563 autri_midi_open(void *addr, int flags, 1564 void (*iintr)(void *, int), 1565 void (*ointr)(void *), 1566 void *arg) 1567 { 1568 struct autri_softc *sc = addr; 1569 1570 DPRINTF(("autri_midi_open()\n")); 1571 1572 DPRINTFN(5,("MPUR1 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR1))); 1573 DPRINTFN(5,("MPUR2 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR2))); 1574 1575 sc->sc_iintr = iintr; 1576 sc->sc_ointr = ointr; 1577 sc->sc_arg = arg; 1578 1579 if (flags & FREAD) 1580 autri_reg_clear_1(sc, AUTRI_MPUR2, AUTRI_MIDIIN_ENABLE_INTR); 1581 1582 if (flags & FWRITE) 1583 autri_reg_set_1(sc, AUTRI_MPUR2, AUTRI_MIDIOUT_CONNECT); 1584 1585 return (0); 1586 } 1587 1588 void 1589 autri_midi_close(void *addr) 1590 { 1591 struct autri_softc *sc = addr; 1592 1593 DPRINTF(("autri_midi_close()\n")); 1594 1595 tsleep(sc, PWAIT, "autri", hz/10); /* give uart a chance to drain */ 1596 1597 sc->sc_iintr = NULL; 1598 sc->sc_ointr = NULL; 1599 } 1600 1601 int 1602 autri_midi_output(void *addr, int d) 1603 { 1604 struct autri_softc *sc = addr; 1605 int x; 1606 1607 for (x = 0; x != MIDI_BUSY_WAIT; x++) { 1608 if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) == 0) { 1609 TWRITE1(sc, AUTRI_MPUR0, d); 1610 return (0); 1611 } 1612 delay(MIDI_BUSY_DELAY); 1613 } 1614 return (EIO); 1615 } 1616 1617 void 1618 autri_midi_getinfo(void *addr, struct midi_info *mi) 1619 { 1620 mi->name = "4DWAVE MIDI UART"; 1621 mi->props = MIDI_PROP_CAN_INPUT; 1622 } 1623 1624 #endif 1625