1 /* $OpenBSD: fms.c,v 1.26 2014/07/12 18:48:51 tedu Exp $ */ 2 /* $NetBSD: fms.c,v 1.5.4.1 2000/06/30 16:27:50 simonb Exp $ */ 3 4 /*- 5 * Copyright (c) 1999 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Witold J. Wnuk. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Forte Media FM801 Audio Device Driver 35 */ 36 37 #include "radio.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/malloc.h> 43 #include <sys/device.h> 44 #include <sys/audioio.h> 45 46 #include <machine/bus.h> 47 #include <machine/cpu.h> 48 49 #include <dev/pci/pcidevs.h> 50 #include <dev/pci/pcivar.h> 51 52 #include <dev/audio_if.h> 53 #include <dev/mulaw.h> 54 #include <dev/auconv.h> 55 56 #include <dev/ic/ac97.h> 57 #if 0 58 #include <dev/ic/mpuvar.h> 59 #endif 60 61 #include <dev/pci/fmsreg.h> 62 #include <dev/pci/fmsvar.h> 63 64 65 struct fms_dma { 66 struct fms_dma *next; 67 caddr_t addr; 68 size_t size; 69 bus_dmamap_t map; 70 bus_dma_segment_t seg; 71 }; 72 73 74 75 int fms_match(struct device *, void *, void *); 76 void fms_attach(struct device *, struct device *, void *); 77 int fms_intr(void *); 78 79 int fms_open(void *, int); 80 void fms_close(void *); 81 int fms_query_encoding(void *, struct audio_encoding *); 82 int fms_set_params(void *, int, int, struct audio_params *, 83 struct audio_params *); 84 void fms_get_default_params(void *, int, struct audio_params *); 85 int fms_round_blocksize(void *, int); 86 int fms_halt_output(void *); 87 int fms_halt_input(void *); 88 int fms_getdev(void *, struct audio_device *); 89 int fms_set_port(void *, mixer_ctrl_t *); 90 int fms_get_port(void *, mixer_ctrl_t *); 91 int fms_query_devinfo(void *, mixer_devinfo_t *); 92 void *fms_malloc(void *, int, size_t, int, int); 93 void fms_free(void *, void *, int); 94 paddr_t fms_mappage(void *, void *, off_t, int); 95 int fms_get_props(void *); 96 int fms_trigger_output(void *, void *, void *, int, void (*)(void *), 97 void *, struct audio_params *); 98 int fms_trigger_input(void *, void *, void *, int, void (*)(void *), 99 void *, struct audio_params *); 100 101 struct cfdriver fms_cd = { 102 NULL, "fms", DV_DULL 103 }; 104 105 struct cfattach fms_ca = { 106 sizeof (struct fms_softc), fms_match, fms_attach 107 }; 108 109 struct audio_device fms_device = { 110 "Forte Media 801", 111 "1.0", 112 "fms" 113 }; 114 115 116 struct audio_hw_if fms_hw_if = { 117 fms_open, 118 fms_close, 119 NULL, 120 fms_query_encoding, 121 fms_set_params, 122 fms_round_blocksize, 123 NULL, 124 NULL, 125 NULL, 126 NULL, 127 NULL, 128 fms_halt_output, 129 fms_halt_input, 130 NULL, 131 fms_getdev, 132 NULL, 133 fms_set_port, 134 fms_get_port, 135 fms_query_devinfo, 136 fms_malloc, 137 fms_free, 138 NULL, 139 fms_mappage, 140 fms_get_props, 141 fms_trigger_output, 142 fms_trigger_input, 143 fms_get_default_params 144 }; 145 146 int fms_attach_codec(void *, struct ac97_codec_if *); 147 int fms_read_codec(void *, u_int8_t, u_int16_t *); 148 int fms_write_codec(void *, u_int8_t, u_int16_t); 149 void fms_reset_codec(void *); 150 151 int fms_allocmem(struct fms_softc *, size_t, size_t, 152 struct fms_dma *); 153 int fms_freemem(struct fms_softc *, struct fms_dma *); 154 155 int 156 fms_match(struct device *parent, void *match, void *aux) 157 { 158 struct pci_attach_args *pa = (struct pci_attach_args *) aux; 159 160 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_FORTEMEDIA && 161 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_FORTEMEDIA_FM801) 162 return (1); 163 return (0); 164 } 165 166 void 167 fms_attach(struct device *parent, struct device *self, void *aux) 168 { 169 struct pci_attach_args *pa = aux; 170 struct fms_softc *sc = (struct fms_softc *) self; 171 struct audio_attach_args aa; 172 pci_chipset_tag_t pc = pa->pa_pc; 173 pcitag_t pt = pa->pa_tag; 174 pci_intr_handle_t ih; 175 bus_size_t iosize; 176 const char *intrstr; 177 u_int16_t k1; 178 int i; 179 180 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, 181 &sc->sc_ioh, NULL, &iosize, 0)) { 182 printf(": can't map i/o space\n"); 183 return; 184 } 185 186 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x30, 2, 187 &sc->sc_mpu_ioh)) { 188 printf(": can't get mpu subregion handle\n"); 189 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 190 return; 191 } 192 193 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x68, 4, 194 &sc->sc_opl_ioh)) { 195 printf(": can't get opl subregion handle\n"); 196 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 197 return; 198 } 199 200 if (pci_intr_map(pa, &ih)) { 201 printf(": couldn't map interrupt\n"); 202 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 203 return; 204 } 205 intrstr = pci_intr_string(pc, ih); 206 207 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE, 208 fms_intr, sc, sc->sc_dev.dv_xname); 209 if (sc->sc_ih == NULL) { 210 printf(": couldn't establish interrupt"); 211 if (intrstr != NULL) 212 printf(" at %s", intrstr); 213 printf("\n"); 214 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 215 return; 216 } 217 218 printf(": %s\n", intrstr); 219 220 sc->sc_dmat = pa->pa_dmat; 221 222 /* Disable legacy audio (SBPro compatibility) */ 223 pci_conf_write(pc, pt, 0x40, 0); 224 225 /* Reset codec and AC'97 */ 226 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020); 227 delay(2); /* > 1us according to AC'97 documentation */ 228 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000); 229 delay(1); /* > 168.2ns according to AC'97 documentation */ 230 231 /* Set up volume */ 232 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PCM_VOLUME, 0x0808); 233 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_FM_VOLUME, 0x0808); 234 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_I2S_VOLUME, 0x0808); 235 236 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_RECORD_SOURCE, 0x0000); 237 238 /* Unmask playback, record and mpu interrupts, mask the rest */ 239 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK); 240 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK, 241 (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) | 242 FM_INTMASK_VOL); 243 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS, 244 FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU | 245 FM_INTSTATUS_VOL); 246 247 #if NRADIO > 0 248 fmsradio_attach(sc); 249 #endif /* NRADIO > 0 */ 250 251 sc->host_if.arg = sc; 252 sc->host_if.attach = fms_attach_codec; 253 sc->host_if.read = fms_read_codec; 254 sc->host_if.write = fms_write_codec; 255 sc->host_if.reset = fms_reset_codec; 256 257 if (ac97_attach(&sc->host_if) != 0) 258 return; 259 260 /* Turn mute off */ 261 for (i = 0; i < 3; i++) { 262 static struct { 263 char *class, *device; 264 } d[] = { 265 { AudioCoutputs, AudioNmaster }, 266 { AudioCinputs, AudioNdac }, 267 { AudioCrecord, AudioNvolume } 268 }; 269 struct mixer_ctrl ctl; 270 271 ctl.type = AUDIO_MIXER_ENUM; 272 ctl.un.ord = 0; 273 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, 274 d[i].class, d[i].device, AudioNmute); 275 fms_set_port(sc, &ctl); 276 } 277 278 audio_attach_mi(&fms_hw_if, sc, &sc->sc_dev); 279 280 aa.type = AUDIODEV_TYPE_OPL; 281 aa.hwif = NULL; 282 aa.hdl = NULL; 283 config_found(&sc->sc_dev, &aa, audioprint); 284 285 aa.type = AUDIODEV_TYPE_MPU; 286 aa.hwif = NULL; 287 aa.hdl = NULL; 288 sc->sc_mpu_dev = config_found(&sc->sc_dev, &aa, audioprint); 289 } 290 291 /* 292 * Each AC-link frame takes 20.8us, data should be ready in next frame, 293 * we allow more than two. 294 */ 295 #define TIMO 50 296 int 297 fms_read_codec(void *addr, u_int8_t reg, u_int16_t *val) 298 { 299 struct fms_softc *sc = addr; 300 int i; 301 302 /* Poll until codec is ready */ 303 for (i = 0; i < TIMO && bus_space_read_2(sc->sc_iot, sc->sc_ioh, 304 FM_CODEC_CMD) & FM_CODEC_CMD_BUSY; i++) 305 delay(1); 306 if (i >= TIMO) { 307 printf("fms: codec busy\n"); 308 return 1; 309 } 310 311 /* Write register index, read access */ 312 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CMD, 313 reg | FM_CODEC_CMD_READ); 314 315 /* Poll until we have valid data */ 316 for (i = 0; i < TIMO && !(bus_space_read_2(sc->sc_iot, sc->sc_ioh, 317 FM_CODEC_CMD) & FM_CODEC_CMD_VALID); i++) 318 delay(1); 319 if (i >= TIMO) { 320 printf("fms: no data from codec\n"); 321 return 1; 322 } 323 324 /* Read data */ 325 *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_DATA); 326 return 0; 327 } 328 329 int 330 fms_write_codec(void *addr, u_int8_t reg, u_int16_t val) 331 { 332 struct fms_softc *sc = addr; 333 int i; 334 335 /* Poll until codec is ready */ 336 for (i = 0; i < TIMO && bus_space_read_2(sc->sc_iot, sc->sc_ioh, 337 FM_CODEC_CMD) & FM_CODEC_CMD_BUSY; i++) 338 delay(1); 339 if (i >= TIMO) { 340 printf("fms: codec busy\n"); 341 return 1; 342 } 343 344 /* Write data */ 345 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_DATA, val); 346 /* Write index register, write access */ 347 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CMD, reg); 348 return 0; 349 } 350 #undef TIMO 351 352 int 353 fms_attach_codec(void *addr, struct ac97_codec_if *cif) 354 { 355 struct fms_softc *sc = addr; 356 357 sc->codec_if = cif; 358 return 0; 359 } 360 361 /* Cold Reset */ 362 void 363 fms_reset_codec(void *addr) 364 { 365 struct fms_softc *sc = addr; 366 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020); 367 delay(2); 368 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000); 369 delay(1); 370 } 371 372 int 373 fms_intr(void *arg) 374 { 375 struct fms_softc *sc = arg; 376 u_int16_t istat; 377 378 mtx_enter(&audio_lock); 379 istat = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS); 380 381 if (istat & FM_INTSTATUS_PLAY) { 382 if ((sc->sc_play_nextblk += sc->sc_play_blksize) >= 383 sc->sc_play_end) 384 sc->sc_play_nextblk = sc->sc_play_start; 385 386 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 387 sc->sc_play_flip++ & 1 ? 388 FM_PLAY_DMABUF2 : FM_PLAY_DMABUF1, sc->sc_play_nextblk); 389 390 if (sc->sc_pintr) 391 sc->sc_pintr(sc->sc_parg); 392 else 393 printf("unexpected play intr\n"); 394 } 395 396 if (istat & FM_INTSTATUS_REC) { 397 if ((sc->sc_rec_nextblk += sc->sc_rec_blksize) >= 398 sc->sc_rec_end) 399 sc->sc_rec_nextblk = sc->sc_rec_start; 400 401 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 402 sc->sc_rec_flip++ & 1 ? 403 FM_REC_DMABUF2 : FM_REC_DMABUF1, sc->sc_rec_nextblk); 404 405 if (sc->sc_rintr) 406 sc->sc_rintr(sc->sc_rarg); 407 else 408 printf("unexpected rec intr\n"); 409 } 410 411 #if 0 412 if (istat & FM_INTSTATUS_MPU) 413 mpu_intr(sc->sc_mpu_dev); 414 #endif 415 416 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS, 417 istat & (FM_INTSTATUS_PLAY | FM_INTSTATUS_REC)); 418 mtx_leave(&audio_lock); 419 return 1; 420 } 421 422 int 423 fms_open(void *addr, int flags) 424 { 425 /* UNUSED struct fms_softc *sc = addr;*/ 426 427 return 0; 428 } 429 430 void 431 fms_close(void *addr) 432 { 433 /* UNUSED struct fms_softc *sc = addr;*/ 434 } 435 436 int 437 fms_query_encoding(void *addr, struct audio_encoding *fp) 438 { 439 440 switch (fp->index) { 441 case 0: 442 strlcpy(fp->name, AudioEmulaw, sizeof fp->name); 443 fp->encoding = AUDIO_ENCODING_ULAW; 444 fp->precision = 8; 445 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 446 break; 447 case 1: 448 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name); 449 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 450 fp->precision = 16; 451 fp->flags = 0; 452 break; 453 case 2: 454 strlcpy(fp->name, AudioEulinear, sizeof fp->name); 455 fp->encoding = AUDIO_ENCODING_ULINEAR; 456 fp->precision = 8; 457 fp->flags = 0; 458 break; 459 case 3: 460 strlcpy(fp->name, AudioEalaw, sizeof fp->name); 461 fp->encoding = AUDIO_ENCODING_ALAW; 462 fp->precision = 8; 463 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 464 break; 465 case 4: 466 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name); 467 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 468 fp->precision = 16; 469 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 470 break; 471 case 5: 472 strlcpy(fp->name, AudioEslinear, sizeof fp->name); 473 fp->encoding = AUDIO_ENCODING_SLINEAR; 474 fp->precision = 8; 475 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 476 break; 477 case 6: 478 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name); 479 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 480 fp->precision = 16; 481 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 482 break; 483 case 7: 484 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name); 485 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 486 fp->precision = 16; 487 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 488 break; 489 default: 490 return EINVAL; 491 } 492 fp->bps = AUDIO_BPS(fp->precision); 493 fp->msb = 1; 494 495 return 0; 496 } 497 498 void 499 fms_get_default_params(void *addr, int mode, struct audio_params *params) 500 { 501 ac97_get_default_params(params); 502 } 503 504 /* 505 * Range below -limit- is set to -rate- 506 * What a pity FM801 does not have 24000 507 * 24000 -> 22050 sounds rather poor 508 */ 509 struct { 510 int limit; 511 int rate; 512 } fms_rates[11] = { 513 { 6600, 5500 }, 514 { 8750, 8000 }, 515 { 10250, 9600 }, 516 { 13200, 11025 }, 517 { 17500, 16000 }, 518 { 20500, 19200 }, 519 { 26500, 22050 }, 520 { 35000, 32000 }, 521 { 41000, 38400 }, 522 { 46000, 44100 }, 523 { 48000, 48000 }, 524 /* anything above -> 48000 */ 525 }; 526 527 int 528 fms_set_params(void *addr, int setmode, int usemode, struct audio_params *play, 529 struct audio_params *rec) 530 { 531 struct fms_softc *sc = addr; 532 int i; 533 534 if (setmode & AUMODE_PLAY) { 535 play->factor = 1; 536 play->sw_code = 0; 537 switch(play->encoding) { 538 case AUDIO_ENCODING_ULAW: 539 play->factor = 2; 540 play->sw_code = mulaw_to_slinear16_le; 541 break; 542 case AUDIO_ENCODING_SLINEAR_LE: 543 if (play->precision == 8) 544 play->sw_code = change_sign8; 545 break; 546 case AUDIO_ENCODING_ULINEAR_LE: 547 if (play->precision == 16) 548 play->sw_code = change_sign16_le; 549 break; 550 case AUDIO_ENCODING_ALAW: 551 play->factor = 2; 552 play->sw_code = alaw_to_slinear16_le; 553 break; 554 case AUDIO_ENCODING_SLINEAR_BE: 555 if (play->precision == 16) 556 play->sw_code = swap_bytes; 557 else 558 play->sw_code = change_sign8; 559 break; 560 case AUDIO_ENCODING_ULINEAR_BE: 561 if (play->precision == 16) 562 play->sw_code = change_sign16_swap_bytes_le; 563 break; 564 default: 565 return EINVAL; 566 } 567 play->bps = AUDIO_BPS(play->precision); 568 play->msb = 1; 569 570 for (i = 0; i < 10 && play->sample_rate > fms_rates[i].limit; 571 i++) 572 ; 573 play->sample_rate = fms_rates[i].rate; 574 sc->sc_play_reg = (play->channels == 2 ? FM_PLAY_STEREO : 0) | 575 (play->precision * play->factor == 16 ? FM_PLAY_16BIT : 0) | 576 (i << 8); 577 } 578 579 if (setmode & AUMODE_RECORD) { 580 581 rec->factor = 1; 582 rec->sw_code = 0; 583 switch(rec->encoding) { 584 case AUDIO_ENCODING_ULAW: 585 rec->sw_code = ulinear8_to_mulaw; 586 break; 587 case AUDIO_ENCODING_SLINEAR_LE: 588 if (rec->precision == 8) 589 rec->sw_code = change_sign8; 590 break; 591 case AUDIO_ENCODING_ULINEAR_LE: 592 if (rec->precision == 16) 593 rec->sw_code = change_sign16_le; 594 break; 595 case AUDIO_ENCODING_ALAW: 596 rec->sw_code = ulinear8_to_alaw; 597 break; 598 case AUDIO_ENCODING_SLINEAR_BE: 599 if (rec->precision == 16) 600 rec->sw_code = swap_bytes; 601 else 602 rec->sw_code = change_sign8; 603 break; 604 case AUDIO_ENCODING_ULINEAR_BE: 605 if (rec->precision == 16) 606 rec->sw_code = swap_bytes_change_sign16_le; 607 break; 608 default: 609 return EINVAL; 610 } 611 rec->bps = AUDIO_BPS(rec->precision); 612 rec->msb = 1; 613 614 for (i = 0; i < 10 && rec->sample_rate > fms_rates[i].limit; 615 i++) 616 ; 617 rec->sample_rate = fms_rates[i].rate; 618 sc->sc_rec_reg = 619 (rec->channels == 2 ? FM_REC_STEREO : 0) | 620 (rec->precision * rec->factor == 16 ? FM_REC_16BIT : 0) | 621 (i << 8); 622 } 623 624 return 0; 625 } 626 627 int 628 fms_round_blocksize(void *addr, int blk) 629 { 630 return (blk + 0xf) & ~0xf; 631 } 632 633 int 634 fms_halt_output(void *addr) 635 { 636 struct fms_softc *sc = addr; 637 u_int16_t k1; 638 639 mtx_enter(&audio_lock); 640 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL); 641 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL, 642 (k1 & ~(FM_PLAY_STOPNOW | FM_PLAY_START)) | 643 FM_PLAY_BUF1_LAST | FM_PLAY_BUF2_LAST); 644 mtx_leave(&audio_lock); 645 return 0; 646 } 647 648 int 649 fms_halt_input(void *addr) 650 { 651 struct fms_softc *sc = addr; 652 u_int16_t k1; 653 654 mtx_enter(&audio_lock); 655 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL); 656 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL, 657 (k1 & ~(FM_REC_STOPNOW | FM_REC_START)) | 658 FM_REC_BUF1_LAST | FM_REC_BUF2_LAST); 659 mtx_leave(&audio_lock); 660 return 0; 661 } 662 663 int 664 fms_getdev(void *addr, struct audio_device *retp) 665 { 666 *retp = fms_device; 667 return 0; 668 } 669 670 int 671 fms_set_port(void *addr, mixer_ctrl_t *cp) 672 { 673 struct fms_softc *sc = addr; 674 675 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp)); 676 } 677 678 int 679 fms_get_port(void *addr, mixer_ctrl_t *cp) 680 { 681 struct fms_softc *sc = addr; 682 683 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp)); 684 } 685 686 void * 687 fms_malloc(void *addr, int direction, size_t size, int pool, int flags) 688 { 689 struct fms_softc *sc = addr; 690 struct fms_dma *p; 691 int error; 692 int rseg; 693 694 p = malloc(sizeof(*p), pool, flags); 695 if (!p) 696 return 0; 697 698 p->size = size; 699 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &p->seg, 1, 700 &rseg, BUS_DMA_NOWAIT)) != 0) { 701 printf("%s: unable to allocate dma, error = %d\n", 702 sc->sc_dev.dv_xname, error); 703 goto fail_alloc; 704 } 705 706 if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr, 707 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 708 printf("%s: unable to map dma, error = %d\n", 709 sc->sc_dev.dv_xname, error); 710 goto fail_map; 711 } 712 713 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 714 BUS_DMA_NOWAIT, &p->map)) != 0) { 715 printf("%s: unable to create dma map, error = %d\n", 716 sc->sc_dev.dv_xname, error); 717 goto fail_create; 718 } 719 720 if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL, 721 BUS_DMA_NOWAIT)) != 0) { 722 printf("%s: unable to load dma map, error = %d\n", 723 sc->sc_dev.dv_xname, error); 724 goto fail_load; 725 } 726 727 p->next = sc->sc_dmas; 728 sc->sc_dmas = p; 729 730 return p->addr; 731 732 733 fail_load: 734 bus_dmamap_destroy(sc->sc_dmat, p->map); 735 fail_create: 736 bus_dmamem_unmap(sc->sc_dmat, p->addr, size); 737 fail_map: 738 bus_dmamem_free(sc->sc_dmat, &p->seg, 1); 739 fail_alloc: 740 free(p, pool, 0); 741 return 0; 742 } 743 744 void 745 fms_free(void *addr, void *ptr, int pool) 746 { 747 struct fms_softc *sc = addr; 748 struct fms_dma **pp, *p; 749 750 for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next) 751 if (p->addr == ptr) { 752 bus_dmamap_unload(sc->sc_dmat, p->map); 753 bus_dmamap_destroy(sc->sc_dmat, p->map); 754 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); 755 bus_dmamem_free(sc->sc_dmat, &p->seg, 1); 756 757 *pp = p->next; 758 free(p, pool, 0); 759 return; 760 } 761 762 panic("fms_free: trying to free unallocated memory"); 763 } 764 765 paddr_t 766 fms_mappage(void *addr, void *mem, off_t off, int prot) 767 { 768 struct fms_softc *sc = addr; 769 struct fms_dma *p; 770 771 if (off < 0) 772 return -1; 773 774 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next) 775 ; 776 if (!p) 777 return -1; 778 779 return bus_dmamem_mmap(sc->sc_dmat, &p->seg, 1, off, prot, 780 BUS_DMA_WAITOK); 781 } 782 783 int 784 fms_get_props(void *addr) 785 { 786 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | 787 AUDIO_PROP_FULLDUPLEX; 788 } 789 790 int 791 fms_query_devinfo(void *addr, mixer_devinfo_t *dip) 792 { 793 struct fms_softc *sc = addr; 794 795 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip)); 796 } 797 798 int 799 fms_trigger_output(void *addr, void *start, void *end, int blksize, 800 void (*intr)(void *), void *arg, struct audio_params *param) 801 { 802 struct fms_softc *sc = addr; 803 struct fms_dma *p; 804 805 sc->sc_pintr = intr; 806 sc->sc_parg = arg; 807 808 for (p = sc->sc_dmas; p && p->addr != start; p = p->next) 809 ; 810 811 if (!p) 812 panic("fms_trigger_output: request with bad start " 813 "address (%p)", start); 814 815 sc->sc_play_start = p->map->dm_segs[0].ds_addr; 816 sc->sc_play_end = sc->sc_play_start + ((char *)end - (char *)start); 817 sc->sc_play_blksize = blksize; 818 sc->sc_play_nextblk = sc->sc_play_start + sc->sc_play_blksize; 819 sc->sc_play_flip = 0; 820 mtx_enter(&audio_lock); 821 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMALEN, blksize - 1); 822 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMABUF1, 823 sc->sc_play_start); 824 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMABUF2, 825 sc->sc_play_nextblk); 826 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL, 827 FM_PLAY_START | FM_PLAY_STOPNOW | sc->sc_play_reg); 828 mtx_leave(&audio_lock); 829 return 0; 830 } 831 832 833 int 834 fms_trigger_input(void *addr, void *start, void *end, int blksize, 835 void (*intr)(void *), void *arg, struct audio_params *param) 836 { 837 struct fms_softc *sc = addr; 838 struct fms_dma *p; 839 840 sc->sc_rintr = intr; 841 sc->sc_rarg = arg; 842 843 for (p = sc->sc_dmas; p && p->addr != start; p = p->next) 844 ; 845 846 if (!p) 847 panic("fms_trigger_input: request with bad start " 848 "address (%p)", start); 849 850 sc->sc_rec_start = p->map->dm_segs[0].ds_addr; 851 sc->sc_rec_end = sc->sc_rec_start + ((char *)end - (char *)start); 852 sc->sc_rec_blksize = blksize; 853 sc->sc_rec_nextblk = sc->sc_rec_start + sc->sc_rec_blksize; 854 sc->sc_rec_flip = 0; 855 mtx_enter(&audio_lock); 856 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_DMALEN, blksize - 1); 857 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_REC_DMABUF1, 858 sc->sc_rec_start); 859 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_REC_DMABUF2, 860 sc->sc_rec_nextblk); 861 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL, 862 FM_REC_START | FM_REC_STOPNOW | sc->sc_rec_reg); 863 mtx_leave(&audio_lock); 864 return 0; 865 } 866