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