1 /* $NetBSD: fms.c,v 1.18 2003/05/03 18:11:34 wiz 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.18 2003/05/03 18:11:34 wiz 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 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 void 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 int i; 251 252 u_int16_t k1; 253 254 aprint_naive(": Audio controller\n"); 255 aprint_normal(": Forte Media FM-801\n"); 256 257 if (pci_intr_map(pa, &ih)) { 258 aprint_error("%s: couldn't map interrupt\n", 259 sc->sc_dev.dv_xname); 260 return; 261 } 262 intrstr = pci_intr_string(pc, ih); 263 264 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, fms_intr, sc); 265 if (sc->sc_ih == NULL) { 266 aprint_error("%s: couldn't establish interrupt", 267 sc->sc_dev.dv_xname); 268 if (intrstr != NULL) 269 aprint_normal(" at %s", intrstr); 270 aprint_normal("\n"); 271 return; 272 } 273 274 sc->sc_dmat = pa->pa_dmat; 275 276 aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 277 278 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, 279 &sc->sc_ioh, &sc->sc_ioaddr, &sc->sc_iosize)) { 280 aprint_error("%s: can't map i/o space\n", sc->sc_dev.dv_xname); 281 return; 282 } 283 284 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x30, 2, 285 &sc->sc_mpu_ioh)) 286 panic("fms_attach: can't get mpu subregion handle"); 287 288 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x68, 4, 289 &sc->sc_opl_ioh)) 290 panic("fms_attach: can't get opl subregion handle"); 291 292 /* Disable legacy audio (SBPro compatibility) */ 293 pci_conf_write(pc, pt, 0x40, 0); 294 295 /* Reset codec and AC'97 */ 296 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020); 297 delay(2); /* > 1us according to AC'97 documentation */ 298 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000); 299 delay(1); /* > 168.2ns according to AC'97 documentation */ 300 301 /* Set up volume */ 302 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PCM_VOLUME, 0x0808); 303 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_FM_VOLUME, 0x0808); 304 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_I2S_VOLUME, 0x0808); 305 306 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_RECORD_SOURCE, 0x0000); 307 308 /* Unmask playback, record and mpu interrupts, mask the rest */ 309 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK); 310 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK, 311 (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) | 312 FM_INTMASK_VOL); 313 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS, 314 FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU | 315 FM_INTSTATUS_VOL); 316 317 sc->host_if.arg = sc; 318 sc->host_if.attach = fms_attach_codec; 319 sc->host_if.read = fms_read_codec; 320 sc->host_if.write = fms_write_codec; 321 sc->host_if.reset = fms_reset_codec; 322 323 if (ac97_attach(&sc->host_if) != 0) 324 return; 325 326 /* Turn mute off */ 327 for (i = 0; i < 3; i++) { 328 static struct { 329 char *class, *device; 330 } d[] = { 331 { AudioCoutputs, AudioNmaster }, 332 { AudioCinputs, AudioNdac }, 333 { AudioCrecord, AudioNvolume } 334 }; 335 struct mixer_ctrl ctl; 336 337 ctl.type = AUDIO_MIXER_ENUM; 338 ctl.un.ord = 0; 339 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, 340 d[i].class, d[i].device, AudioNmute); 341 fms_set_port(sc, &ctl); 342 } 343 344 audio_attach_mi(&fms_hw_if, sc, &sc->sc_dev); 345 346 aa.type = AUDIODEV_TYPE_OPL; 347 aa.hwif = NULL; 348 aa.hdl = NULL; 349 config_found(&sc->sc_dev, &aa, audioprint); 350 351 aa.type = AUDIODEV_TYPE_MPU; 352 aa.hwif = NULL; 353 aa.hdl = NULL; 354 sc->sc_mpu_dev = config_found(&sc->sc_dev, &aa, audioprint); 355 } 356 357 /* 358 * Each AC-link frame takes 20.8us, data should be ready in next frame, 359 * we allow more than two. 360 */ 361 #define TIMO 50 362 int 363 fms_read_codec(addr, reg, val) 364 void *addr; 365 u_int8_t reg; 366 u_int16_t *val; 367 { 368 struct fms_softc *sc = addr; 369 int i; 370 371 /* Poll until codec is ready */ 372 for (i = 0; i < TIMO && bus_space_read_2(sc->sc_iot, sc->sc_ioh, 373 FM_CODEC_CMD) & FM_CODEC_CMD_BUSY; i++) 374 delay(1); 375 if (i >= TIMO) { 376 printf("fms: codec busy\n"); 377 return 1; 378 } 379 380 /* Write register index, read access */ 381 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CMD, 382 reg | FM_CODEC_CMD_READ); 383 384 /* Poll until we have valid data */ 385 for (i = 0; i < TIMO && !(bus_space_read_2(sc->sc_iot, sc->sc_ioh, 386 FM_CODEC_CMD) & FM_CODEC_CMD_VALID); i++) 387 delay(1); 388 if (i >= TIMO) { 389 printf("fms: no data from codec\n"); 390 return 1; 391 } 392 393 /* Read data */ 394 *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_DATA); 395 return 0; 396 } 397 398 int 399 fms_write_codec(addr, reg, val) 400 void *addr; 401 u_int8_t reg; 402 u_int16_t val; 403 { 404 struct fms_softc *sc = addr; 405 int i; 406 407 /* Poll until codec is ready */ 408 for (i = 0; i < TIMO && bus_space_read_2(sc->sc_iot, sc->sc_ioh, 409 FM_CODEC_CMD) & FM_CODEC_CMD_BUSY; i++) 410 delay(1); 411 if (i >= TIMO) { 412 printf("fms: codec busy\n"); 413 return 1; 414 } 415 416 /* Write data */ 417 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_DATA, val); 418 /* Write index register, write access */ 419 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CMD, reg); 420 return 0; 421 } 422 #undef TIMO 423 424 int 425 fms_attach_codec(addr, cif) 426 void *addr; 427 struct ac97_codec_if *cif; 428 { 429 struct fms_softc *sc = addr; 430 431 sc->codec_if = cif; 432 return 0; 433 } 434 435 /* Cold Reset */ 436 void 437 fms_reset_codec(addr) 438 void *addr; 439 { 440 struct fms_softc *sc = addr; 441 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020); 442 delay(2); 443 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000); 444 delay(1); 445 } 446 447 int 448 fms_intr(arg) 449 void *arg; 450 { 451 struct fms_softc *sc = arg; 452 u_int16_t istat; 453 454 istat = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS); 455 456 if (istat & FM_INTSTATUS_PLAY) { 457 if ((sc->sc_play_nextblk += sc->sc_play_blksize) >= 458 sc->sc_play_end) 459 sc->sc_play_nextblk = sc->sc_play_start; 460 461 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 462 sc->sc_play_flip++ & 1 ? 463 FM_PLAY_DMABUF2 : FM_PLAY_DMABUF1, sc->sc_play_nextblk); 464 465 if (sc->sc_pintr) 466 sc->sc_pintr(sc->sc_parg); 467 else 468 printf("unexpected play intr\n"); 469 } 470 471 if (istat & FM_INTSTATUS_REC) { 472 if ((sc->sc_rec_nextblk += sc->sc_rec_blksize) >= 473 sc->sc_rec_end) 474 sc->sc_rec_nextblk = sc->sc_rec_start; 475 476 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 477 sc->sc_rec_flip++ & 1 ? 478 FM_REC_DMABUF2 : FM_REC_DMABUF1, sc->sc_rec_nextblk); 479 480 if (sc->sc_rintr) 481 sc->sc_rintr(sc->sc_rarg); 482 else 483 printf("unexpected rec intr\n"); 484 } 485 486 #if NMPU > 0 487 if (istat & FM_INTSTATUS_MPU) 488 mpu_intr(sc->sc_mpu_dev); 489 #endif 490 491 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS, 492 istat & (FM_INTSTATUS_PLAY | FM_INTSTATUS_REC)); 493 494 return 1; 495 } 496 497 int 498 fms_open(addr, flags) 499 void *addr; 500 int flags; 501 { 502 /* UNUSED struct fms_softc *sc = addr;*/ 503 504 return 0; 505 } 506 507 void 508 fms_close(addr) 509 void *addr; 510 { 511 /* UNUSED struct fms_softc *sc = addr;*/ 512 } 513 514 int 515 fms_query_encoding(addr, fp) 516 void *addr; 517 struct audio_encoding *fp; 518 { 519 520 switch (fp->index) { 521 case 0: 522 strcpy(fp->name, AudioEmulaw); 523 fp->encoding = AUDIO_ENCODING_ULAW; 524 fp->precision = 8; 525 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 526 return 0; 527 case 1: 528 strcpy(fp->name, AudioEslinear_le); 529 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 530 fp->precision = 16; 531 fp->flags = 0; 532 return 0; 533 case 2: 534 strcpy(fp->name, AudioEulinear); 535 fp->encoding = AUDIO_ENCODING_ULINEAR; 536 fp->precision = 8; 537 fp->flags = 0; 538 return 0; 539 case 3: 540 strcpy(fp->name, AudioEalaw); 541 fp->encoding = AUDIO_ENCODING_ALAW; 542 fp->precision = 8; 543 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 544 return 0; 545 case 4: 546 strcpy(fp->name, AudioEulinear_le); 547 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 548 fp->precision = 16; 549 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 550 return 0; 551 case 5: 552 strcpy(fp->name, AudioEslinear); 553 fp->encoding = AUDIO_ENCODING_SLINEAR; 554 fp->precision = 8; 555 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 556 return 0; 557 case 6: 558 strcpy(fp->name, AudioEulinear_be); 559 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 560 fp->precision = 16; 561 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 562 return 0; 563 case 7: 564 strcpy(fp->name, AudioEslinear_be); 565 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 566 fp->precision = 16; 567 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 568 return 0; 569 default: 570 return EINVAL; 571 } 572 } 573 574 /* 575 * Range below -limit- is set to -rate- 576 * What a pity FM801 does not have 24000 577 * 24000 -> 22050 sounds rather poor 578 */ 579 struct { 580 int limit; 581 int rate; 582 } fms_rates[11] = { 583 { 6600, 5500 }, 584 { 8750, 8000 }, 585 { 10250, 9600 }, 586 { 13200, 11025 }, 587 { 17500, 16000 }, 588 { 20500, 19200 }, 589 { 26500, 22050 }, 590 { 35000, 32000 }, 591 { 41000, 38400 }, 592 { 46000, 44100 }, 593 { 48000, 48000 }, 594 /* anything above -> 48000 */ 595 }; 596 597 int 598 fms_set_params(addr, setmode, usemode, play, rec) 599 void *addr; 600 int setmode, usemode; 601 struct audio_params *play, *rec; 602 { 603 struct fms_softc *sc = addr; 604 int i; 605 606 if (setmode & AUMODE_PLAY) { 607 play->factor = 1; 608 play->sw_code = 0; 609 switch(play->encoding) { 610 case AUDIO_ENCODING_ULAW: 611 play->factor = 2; 612 play->sw_code = mulaw_to_slinear16_le; 613 break; 614 case AUDIO_ENCODING_SLINEAR_LE: 615 if (play->precision == 8) 616 play->sw_code = change_sign8; 617 break; 618 case AUDIO_ENCODING_ULINEAR_LE: 619 if (play->precision == 16) 620 play->sw_code = change_sign16_le; 621 break; 622 case AUDIO_ENCODING_ALAW: 623 play->factor = 2; 624 play->sw_code = alaw_to_slinear16_le; 625 break; 626 case AUDIO_ENCODING_SLINEAR_BE: 627 if (play->precision == 16) 628 play->sw_code = swap_bytes; 629 else 630 play->sw_code = change_sign8; 631 break; 632 case AUDIO_ENCODING_ULINEAR_BE: 633 if (play->precision == 16) 634 play->sw_code = change_sign16_swap_bytes_le; 635 break; 636 default: 637 return EINVAL; 638 } 639 for (i = 0; i < 10 && play->sample_rate > fms_rates[i].limit; 640 i++) 641 ; 642 play->sample_rate = fms_rates[i].rate; 643 sc->sc_play_reg = (play->channels == 2 ? FM_PLAY_STEREO : 0) | 644 (play->precision * play->factor == 16 ? FM_PLAY_16BIT : 0) | 645 (i << 8); 646 } 647 648 if (setmode & AUMODE_RECORD) { 649 650 rec->factor = 1; 651 rec->sw_code = 0; 652 switch(rec->encoding) { 653 case AUDIO_ENCODING_ULAW: 654 rec->sw_code = ulinear8_to_mulaw; 655 break; 656 case AUDIO_ENCODING_SLINEAR_LE: 657 if (rec->precision == 8) 658 rec->sw_code = change_sign8; 659 break; 660 case AUDIO_ENCODING_ULINEAR_LE: 661 if (rec->precision == 16) 662 rec->sw_code = change_sign16_le; 663 break; 664 case AUDIO_ENCODING_ALAW: 665 rec->sw_code = ulinear8_to_alaw; 666 break; 667 case AUDIO_ENCODING_SLINEAR_BE: 668 if (play->precision == 16) 669 play->sw_code = swap_bytes; 670 else 671 play->sw_code = change_sign8; 672 break; 673 case AUDIO_ENCODING_ULINEAR_BE: 674 if (play->precision == 16) 675 play->sw_code = swap_bytes_change_sign16_le; 676 break; 677 default: 678 return EINVAL; 679 } 680 for (i = 0; i < 10 && rec->sample_rate > fms_rates[i].limit; 681 i++) 682 ; 683 rec->sample_rate = fms_rates[i].rate; 684 sc->sc_rec_reg = 685 (rec->channels == 2 ? FM_REC_STEREO : 0) | 686 (rec->precision * rec->factor == 16 ? FM_REC_16BIT : 0) | 687 (i << 8); 688 } 689 690 return 0; 691 } 692 693 int 694 fms_round_blocksize(addr, blk) 695 void *addr; 696 int blk; 697 { 698 return blk & ~0xf; 699 } 700 701 int 702 fms_halt_output(addr) 703 void *addr; 704 { 705 struct fms_softc *sc = addr; 706 u_int16_t k1; 707 708 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL); 709 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL, 710 (k1 & ~(FM_PLAY_STOPNOW | FM_PLAY_START)) | 711 FM_PLAY_BUF1_LAST | FM_PLAY_BUF2_LAST); 712 713 return 0; 714 } 715 716 int 717 fms_halt_input(addr) 718 void *addr; 719 { 720 struct fms_softc *sc = addr; 721 u_int16_t k1; 722 723 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL); 724 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL, 725 (k1 & ~(FM_REC_STOPNOW | FM_REC_START)) | 726 FM_REC_BUF1_LAST | FM_REC_BUF2_LAST); 727 728 return 0; 729 } 730 731 int 732 fms_getdev(addr, retp) 733 void *addr; 734 struct audio_device *retp; 735 { 736 *retp = fms_device; 737 return 0; 738 } 739 740 int 741 fms_set_port(addr, cp) 742 void *addr; 743 mixer_ctrl_t *cp; 744 { 745 struct fms_softc *sc = addr; 746 747 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp)); 748 } 749 750 int 751 fms_get_port(addr, cp) 752 void *addr; 753 mixer_ctrl_t *cp; 754 { 755 struct fms_softc *sc = addr; 756 757 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp)); 758 } 759 760 void * 761 fms_malloc(addr, direction, size, pool, flags) 762 void *addr; 763 int direction; 764 size_t size; 765 struct malloc_type *pool; 766 int flags; 767 { 768 struct fms_softc *sc = addr; 769 struct fms_dma *p; 770 int error; 771 int rseg; 772 773 p = malloc(sizeof(*p), pool, flags); 774 if (!p) 775 return 0; 776 777 p->size = size; 778 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &p->seg, 779 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 780 printf("%s: unable to allocate DMA, error = %d\n", 781 sc->sc_dev.dv_xname, error); 782 goto fail_alloc; 783 } 784 785 if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr, 786 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 787 printf("%s: unable to map DMA, error = %d\n", 788 sc->sc_dev.dv_xname, error); 789 goto fail_map; 790 } 791 792 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 793 BUS_DMA_NOWAIT, &p->map)) != 0) { 794 printf("%s: unable to create DMA map, error = %d\n", 795 sc->sc_dev.dv_xname, error); 796 goto fail_create; 797 } 798 799 if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL, 800 BUS_DMA_NOWAIT)) != 0) { 801 printf("%s: unable to load DMA map, error = %d\n", 802 sc->sc_dev.dv_xname, error); 803 goto fail_load; 804 } 805 806 p->next = sc->sc_dmas; 807 sc->sc_dmas = p; 808 809 return p->addr; 810 811 812 fail_load: 813 bus_dmamap_destroy(sc->sc_dmat, p->map); 814 fail_create: 815 bus_dmamem_unmap(sc->sc_dmat, p->addr, size); 816 fail_map: 817 bus_dmamem_free(sc->sc_dmat, &p->seg, 1); 818 fail_alloc: 819 free(p, pool); 820 return 0; 821 } 822 823 void 824 fms_free(addr, ptr, pool) 825 void *addr; 826 void *ptr; 827 struct malloc_type *pool; 828 { 829 struct fms_softc *sc = addr; 830 struct fms_dma **pp, *p; 831 832 for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next) 833 if (p->addr == ptr) { 834 bus_dmamap_unload(sc->sc_dmat, p->map); 835 bus_dmamap_destroy(sc->sc_dmat, p->map); 836 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); 837 bus_dmamem_free(sc->sc_dmat, &p->seg, 1); 838 839 *pp = p->next; 840 free(p, pool); 841 return; 842 } 843 844 panic("fms_free: trying to free unallocated memory"); 845 } 846 847 size_t 848 fms_round_buffersize(addr, direction, size) 849 void *addr; 850 int direction; 851 size_t size; 852 { 853 return size; 854 } 855 856 paddr_t 857 fms_mappage(addr, mem, off, prot) 858 void *addr; 859 void *mem; 860 off_t off; 861 int prot; 862 { 863 struct fms_softc *sc = addr; 864 struct fms_dma *p; 865 866 if (off < 0) 867 return -1; 868 869 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next) 870 ; 871 if (!p) 872 return -1; 873 874 return bus_dmamem_mmap(sc->sc_dmat, &p->seg, 1, off, prot, 875 BUS_DMA_WAITOK); 876 } 877 878 int 879 fms_get_props(addr) 880 void *addr; 881 { 882 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | 883 AUDIO_PROP_FULLDUPLEX; 884 } 885 886 int 887 fms_query_devinfo(addr, dip) 888 void *addr; 889 mixer_devinfo_t *dip; 890 { 891 struct fms_softc *sc = addr; 892 893 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip)); 894 } 895 896 int 897 fms_trigger_output(addr, start, end, blksize, intr, arg, param) 898 void *addr; 899 void *start, *end; 900 int blksize; 901 void (*intr) __P((void *)); 902 void *arg; 903 struct audio_params *param; 904 { 905 struct fms_softc *sc = addr; 906 struct fms_dma *p; 907 908 sc->sc_pintr = intr; 909 sc->sc_parg = arg; 910 911 for (p = sc->sc_dmas; p && p->addr != start; p = p->next) 912 ; 913 914 if (!p) 915 panic("fms_trigger_output: request with bad start " 916 "address (%p)", start); 917 918 sc->sc_play_start = p->map->dm_segs[0].ds_addr; 919 sc->sc_play_end = sc->sc_play_start + ((char *)end - (char *)start); 920 sc->sc_play_blksize = blksize; 921 sc->sc_play_nextblk = sc->sc_play_start + sc->sc_play_blksize; 922 sc->sc_play_flip = 0; 923 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMALEN, blksize - 1); 924 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMABUF1, 925 sc->sc_play_start); 926 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMABUF2, 927 sc->sc_play_nextblk); 928 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL, 929 FM_PLAY_START | FM_PLAY_STOPNOW | sc->sc_play_reg); 930 return 0; 931 } 932 933 934 int 935 fms_trigger_input(addr, start, end, blksize, intr, arg, param) 936 void *addr; 937 void *start, *end; 938 int blksize; 939 void (*intr) __P((void *)); 940 void *arg; 941 struct audio_params *param; 942 { 943 struct fms_softc *sc = addr; 944 struct fms_dma *p; 945 946 sc->sc_rintr = intr; 947 sc->sc_rarg = arg; 948 949 for (p = sc->sc_dmas; p && p->addr != start; p = p->next) 950 ; 951 952 if (!p) 953 panic("fms_trigger_input: request with bad start " 954 "address (%p)", start); 955 956 sc->sc_rec_start = p->map->dm_segs[0].ds_addr; 957 sc->sc_rec_end = sc->sc_rec_start + ((char *)end - (char *)start); 958 sc->sc_rec_blksize = blksize; 959 sc->sc_rec_nextblk = sc->sc_rec_start + sc->sc_rec_blksize; 960 sc->sc_rec_flip = 0; 961 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_DMALEN, blksize - 1); 962 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_REC_DMABUF1, 963 sc->sc_rec_start); 964 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_REC_DMABUF2, 965 sc->sc_rec_nextblk); 966 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL, 967 FM_REC_START | FM_REC_STOPNOW | sc->sc_rec_reg); 968 return 0; 969 } 970 971 972