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