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