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