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