1/* $OpenBSD: neo.c,v 1.42 2024/05/24 06:02:58 jsg Exp $ */ 2 3/* 4 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 5 * All rights reserved. 6 * 7 * Derived from the public domain Linux driver 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $FreeBSD: src/sys/dev/sound/pci/neomagic.c,v 1.8 2000/03/20 15:30:50 cg Exp $ 31 */ 32 33 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/device.h> 38 39#include <dev/pci/pcidevs.h> 40#include <dev/pci/pcivar.h> 41 42#include <sys/audioio.h> 43#include <dev/audio_if.h> 44#include <dev/ic/ac97.h> 45 46#include <dev/pci/neoreg.h> 47 48/* -------------------------------------------------------------------- */ 49/* 50 * As of 04/13/00, public documentation on the Neomagic 256 is not available. 51 * These comments were gleaned by looking at the driver carefully. 52 * 53 * The Neomagic 256 AV/ZX chips provide both video and audio capabilities 54 * on one chip. About 2-6 megabytes of memory are associated with 55 * the chip. Most of this goes to video frame buffers, but some is used for 56 * audio buffering. 57 * 58 * Unlike most PCI audio chips, the Neomagic chip does not rely on DMA. 59 * Instead, the chip allows you to carve two ring buffers out of its 60 * memory. How you carve this and how much you can carve seems to be 61 * voodoo. The algorithm is in nm_init. 62 * 63 * Most Neomagic audio chips use the AC-97 codec interface. However, there 64 * seem to be a select few chips 256AV chips that do not support AC-97. 65 * This driver does not support them but there are rumors that it 66 * might work with wss isa drivers. This might require some playing around 67 * with your BIOS. 68 * 69 * The Neomagic 256 AV/ZX have 2 PCI I/O region descriptors. Both of 70 * them describe a memory region. The frame buffer is the first region 71 * and the register set is the second region. 72 * 73 * The register manipulation logic is taken from the Linux driver, 74 * which is in the public domain. 75 * 76 * The Neomagic is even nice enough to map the AC-97 codec registers into 77 * the register space to allow direct manipulation. Watch out, accessing 78 * AC-97 registers on the Neomagic requires great delicateness, otherwise 79 * the thing will hang the PCI bus, rendering your system frozen. 80 * 81 * For one, it seems the Neomagic status register that reports AC-97 82 * readiness should NOT be polled more often than once each 1ms. 83 * 84 * Also, writes to the AC-97 register space may take over 40us to 85 * complete. 86 * 87 * Unlike many sound engines, the Neomagic does not support (as fas as 88 * we know :) ) the notion of interrupting every n bytes transferred, 89 * unlike many DMA engines. Instead, it allows you to specify one 90 * location in each ring buffer (called the watermark). When the chip 91 * passes that location while playing, it signals an interrupt. 92 * 93 * The ring buffer size is currently 16k. That is about 100ms of audio 94 * at 44.1khz/stero/16 bit. However, to keep the buffer full, interrupts 95 * are generated more often than that, so 20-40 interrupts per second 96 * should not be unexpected. Increasing BUFFSIZE should help minimize 97 * the glitches due to drivers that spend too much time looping at high 98 * privilege levels as well as the impact of badly written audio 99 * interface clients. 100 * 101 * TO-DO list: 102 * neo_malloc/neo_free are still seriously broken. 103 * 104 * Figure out interaction with video stuff (look at Xfree86 driver?) 105 * 106 * Power management (neoactivate) 107 * 108 * Fix detection of Neo devices that don't work this driver (see neo_attach) 109 * 110 * Figure out how to shrink that huge table neo-coeff.h 111 */ 112 113#define NM_BUFFSIZE 16384 114 115#define NM256AV_PCI_ID 0x800510c8 116#define NM256ZX_PCI_ID 0x800610c8 117 118/* device private data */ 119struct neo_softc { 120 struct device dev; 121 122 bus_space_tag_t bufiot; 123 bus_space_handle_t bufioh; 124 125 bus_space_tag_t regiot; 126 bus_space_handle_t regioh; 127 128 u_int32_t type; 129 void *ih; 130 131 void (*pintr)(void *); /* dma completion intr handler */ 132 void *parg; /* arg for intr() */ 133 134 void (*rintr)(void *); /* dma completion intr handler */ 135 void *rarg; /* arg for intr() */ 136 137 u_int32_t ac97_base, ac97_status, ac97_busy; 138 u_int32_t buftop, pbuf, rbuf, cbuf, acbuf; 139 u_int32_t playint, recint, misc1int, misc2int; 140 u_int32_t irsz, badintr; 141 142 u_int32_t pbufsize; 143 u_int32_t rbufsize; 144 145 u_int32_t pblksize; 146 u_int32_t rblksize; 147 148 u_int32_t pwmark; 149 u_int32_t rwmark; 150 151 struct ac97_codec_if *codec_if; 152 struct ac97_host_if host_if; 153}; 154 155static struct neo_firmware *nf; 156 157/* -------------------------------------------------------------------- */ 158 159/* 160 * prototypes 161 */ 162 163static int nm_waitcd(struct neo_softc *sc); 164static int nm_loadcoeff(struct neo_softc *sc, int dir, int num); 165static int nm_init(struct neo_softc *); 166 167int nmchan_getptr(struct neo_softc *, int); 168/* talk to the card */ 169static u_int32_t nm_rd(struct neo_softc *, int, int); 170static void nm_wr(struct neo_softc *, int, u_int32_t, int); 171static u_int32_t nm_rdbuf(struct neo_softc *, int, int); 172static void nm_wrbuf(struct neo_softc *, int, u_int32_t, int); 173 174int neo_match(struct device *, void *, void *); 175void neo_attach(struct device *, struct device *, void *); 176int neo_activate(struct device *, int); 177int neo_intr(void *); 178 179int neo_open(void *, int); 180void neo_close(void *); 181int neo_set_params(void *, int, int, struct audio_params *, struct audio_params *); 182int neo_round_blocksize(void *, int); 183int neo_trigger_output(void *, void *, void *, int, void (*)(void *), 184 void *, struct audio_params *); 185int neo_trigger_input(void *, void *, void *, int, void (*)(void *), 186 void *, struct audio_params *); 187int neo_halt_output(void *); 188int neo_halt_input(void *); 189int neo_mixer_set_port(void *, mixer_ctrl_t *); 190int neo_mixer_get_port(void *, mixer_ctrl_t *); 191int neo_attach_codec(void *sc, struct ac97_codec_if *); 192int neo_read_codec(void *sc, u_int8_t a, u_int16_t *d); 193int neo_write_codec(void *sc, u_int8_t a, u_int16_t d); 194void neo_reset_codec(void *sc); 195enum ac97_host_flags neo_flags_codec(void *sc); 196int neo_query_devinfo(void *, mixer_devinfo_t *); 197void *neo_malloc(void *, int, size_t, int, int); 198void neo_free(void *, void *, int); 199size_t neo_round_buffersize(void *, int, size_t); 200 201struct cfdriver neo_cd = { 202 NULL, "neo", DV_DULL 203}; 204 205 206const struct cfattach neo_ca = { 207 sizeof(struct neo_softc), neo_match, neo_attach, NULL, 208 neo_activate 209}; 210 211 212#if 0 213static u_int32_t badcards[] = { 214 0x0007103c, 215 0x008f1028, 216}; 217#endif 218 219#define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t)) 220 221/* The actual rates supported by the card. */ 222static int samplerates[9] = { 223 8000, 224 11025, 225 16000, 226 22050, 227 24000, 228 32000, 229 44100, 230 48000, 231 99999999 232}; 233 234/* -------------------------------------------------------------------- */ 235 236const struct audio_hw_if neo_hw_if = { 237 .open = neo_open, 238 .close = neo_close, 239 .set_params = neo_set_params, 240 .round_blocksize = neo_round_blocksize, 241 .halt_output = neo_halt_output, 242 .halt_input = neo_halt_input, 243 .set_port = neo_mixer_set_port, 244 .get_port = neo_mixer_get_port, 245 .query_devinfo = neo_query_devinfo, 246 .allocm = neo_malloc, 247 .freem = neo_free, 248 .round_buffersize = neo_round_buffersize, 249 .trigger_output = neo_trigger_output, 250 .trigger_input = neo_trigger_input, 251 252}; 253 254/* -------------------------------------------------------------------- */ 255 256/* Hardware */ 257static u_int32_t 258nm_rd(struct neo_softc *sc, int regno, int size) 259{ 260 bus_space_tag_t st = sc->regiot; 261 bus_space_handle_t sh = sc->regioh; 262 263 switch (size) { 264 case 1: 265 return bus_space_read_1(st, sh, regno); 266 case 2: 267 return bus_space_read_2(st, sh, regno); 268 case 4: 269 return bus_space_read_4(st, sh, regno); 270 default: 271 return (0xffffffff); 272 } 273} 274 275static void 276nm_wr(struct neo_softc *sc, int regno, u_int32_t data, int size) 277{ 278 bus_space_tag_t st = sc->regiot; 279 bus_space_handle_t sh = sc->regioh; 280 281 switch (size) { 282 case 1: 283 bus_space_write_1(st, sh, regno, data); 284 break; 285 case 2: 286 bus_space_write_2(st, sh, regno, data); 287 break; 288 case 4: 289 bus_space_write_4(st, sh, regno, data); 290 break; 291 } 292} 293 294static u_int32_t 295nm_rdbuf(struct neo_softc *sc, int regno, int size) 296{ 297 bus_space_tag_t st = sc->bufiot; 298 bus_space_handle_t sh = sc->bufioh; 299 300 switch (size) { 301 case 1: 302 return bus_space_read_1(st, sh, regno); 303 case 2: 304 return bus_space_read_2(st, sh, regno); 305 case 4: 306 return bus_space_read_4(st, sh, regno); 307 default: 308 return (0xffffffff); 309 } 310} 311 312static void 313nm_wrbuf(struct neo_softc *sc, int regno, u_int32_t data, int size) 314{ 315 bus_space_tag_t st = sc->bufiot; 316 bus_space_handle_t sh = sc->bufioh; 317 318 switch (size) { 319 case 1: 320 bus_space_write_1(st, sh, regno, data); 321 break; 322 case 2: 323 bus_space_write_2(st, sh, regno, data); 324 break; 325 case 4: 326 bus_space_write_4(st, sh, regno, data); 327 break; 328 } 329} 330 331/* ac97 codec */ 332static int 333nm_waitcd(struct neo_softc *sc) 334{ 335 int cnt = 10; 336 int fail = 1; 337 338 while (cnt-- > 0) { 339 if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy) 340 DELAY(100); 341 else { 342 fail = 0; 343 break; 344 } 345 } 346 return (fail); 347} 348 349 350static void 351nm_ackint(struct neo_softc *sc, u_int32_t num) 352{ 353 if (sc->type == NM256AV_PCI_ID) 354 nm_wr(sc, NM_INT_REG, num << 1, 2); 355 else if (sc->type == NM256ZX_PCI_ID) 356 nm_wr(sc, NM_INT_REG, num, 4); 357} 358 359static int 360nm_loadcoeff(struct neo_softc *sc, int dir, int num) 361{ 362 int ofs, sz, i; 363 u_int32_t addr; 364 365 if (nf == NULL) { 366 size_t buflen; 367 u_char *buf; 368 int error; 369 370 error = loadfirmware("neo-coefficients", &buf, &buflen); 371 if (error) 372 return (error); 373 nf = (struct neo_firmware *)buf; 374 } 375 376 addr = (dir == AUMODE_PLAY)? 0x01c : 0x21c; 377 if (dir == AUMODE_RECORD) 378 num += 8; 379 sz = nf->coefficientSizes[num]; 380 ofs = 0; 381 while (num-- > 0) 382 ofs+= nf->coefficientSizes[num]; 383 for (i = 0; i < sz; i++) 384 nm_wrbuf(sc, sc->cbuf + i, nf->coefficients[ofs + i], 1); 385 nm_wr(sc, addr, sc->cbuf, 4); 386 if (dir == AUMODE_PLAY) 387 sz--; 388 nm_wr(sc, addr + 4, sc->cbuf + sz, 4); 389 return (0); 390} 391 392int 393nmchan_getptr(struct neo_softc *sc, int mode) 394{ 395 if (mode == AUMODE_PLAY) 396 return (nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf); 397 else 398 return (nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf); 399} 400 401 402/* The interrupt handler */ 403int 404neo_intr(void *p) 405{ 406 struct neo_softc *sc = (struct neo_softc *)p; 407 int status, x; 408 int rv = 0; 409 410 mtx_enter(&audio_lock); 411 status = nm_rd(sc, NM_INT_REG, sc->irsz); 412 413 if (status & sc->playint) { 414 status &= ~sc->playint; 415 416 sc->pwmark += sc->pblksize; 417 sc->pwmark %= sc->pbufsize; 418 419 nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pwmark, 4); 420 421 nm_ackint(sc, sc->playint); 422 423 if (sc->pintr) 424 (*sc->pintr)(sc->parg); 425 426 rv = 1; 427 } 428 if (status & sc->recint) { 429 status &= ~sc->recint; 430 431 sc->rwmark += sc->rblksize; 432 sc->rwmark %= sc->rbufsize; 433 434 nm_ackint(sc, sc->recint); 435 if (sc->rintr) 436 (*sc->rintr)(sc->rarg); 437 438 rv = 1; 439 } 440 if (status & sc->misc1int) { 441 status &= ~sc->misc1int; 442 nm_ackint(sc, sc->misc1int); 443 x = nm_rd(sc, 0x400, 1); 444 nm_wr(sc, 0x400, x | 2, 1); 445 printf("%s: misc int 1\n", sc->dev.dv_xname); 446 rv = 1; 447 } 448 if (status & sc->misc2int) { 449 status &= ~sc->misc2int; 450 nm_ackint(sc, sc->misc2int); 451 x = nm_rd(sc, 0x400, 1); 452 nm_wr(sc, 0x400, x & ~2, 1); 453 printf("%s: misc int 2\n", sc->dev.dv_xname); 454 rv = 1; 455 } 456 if (status) { 457 status &= ~sc->misc2int; 458 nm_ackint(sc, sc->misc2int); 459 printf("%s: unknown int\n", sc->dev.dv_xname); 460 rv = 1; 461 } 462 mtx_leave(&audio_lock); 463 return (rv); 464} 465 466/* -------------------------------------------------------------------- */ 467 468/* 469 * Probe and attach the card 470 */ 471 472static int 473nm_init(struct neo_softc *sc) 474{ 475 u_int32_t ofs, i; 476 477 if (sc->type == NM256AV_PCI_ID) { 478 sc->ac97_base = NM_MIXER_OFFSET; 479 sc->ac97_status = NM_MIXER_STATUS_OFFSET; 480 sc->ac97_busy = NM_MIXER_READY_MASK; 481 482 sc->buftop = 2560 * 1024; 483 484 sc->irsz = 2; 485 sc->playint = NM_PLAYBACK_INT; 486 sc->recint = NM_RECORD_INT; 487 sc->misc1int = NM_MISC_INT_1; 488 sc->misc2int = NM_MISC_INT_2; 489 } else if (sc->type == NM256ZX_PCI_ID) { 490 sc->ac97_base = NM_MIXER_OFFSET; 491 sc->ac97_status = NM2_MIXER_STATUS_OFFSET; 492 sc->ac97_busy = NM2_MIXER_READY_MASK; 493 494 sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024; 495 496 sc->irsz = 4; 497 sc->playint = NM2_PLAYBACK_INT; 498 sc->recint = NM2_RECORD_INT; 499 sc->misc1int = NM2_MISC_INT_1; 500 sc->misc2int = NM2_MISC_INT_2; 501 } else return -1; 502 sc->badintr = 0; 503 ofs = sc->buftop - 0x0400; 504 sc->buftop -= 0x1400; 505 506 if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) { 507 i = nm_rdbuf(sc, ofs + 4, 4); 508 if (i != 0 && i != 0xffffffff) 509 sc->buftop = i; 510 } 511 512 sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT; 513 sc->rbuf = sc->cbuf - NM_BUFFSIZE; 514 sc->pbuf = sc->rbuf - NM_BUFFSIZE; 515 sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4); 516 517 nm_wr(sc, 0, 0x11, 1); 518 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1); 519 nm_wr(sc, 0x214, 0, 2); 520 521 return 0; 522} 523 524 525void 526neo_attach(struct device *parent, struct device *self, void *aux) 527{ 528 struct neo_softc *sc = (struct neo_softc *)self; 529 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 530 pci_chipset_tag_t pc = pa->pa_pc; 531 char const *intrstr; 532 pci_intr_handle_t ih; 533 int error; 534 535 sc->type = pa->pa_id; 536 537 /* Map I/O register */ 538 if (pci_mapreg_map(pa, PCI_MAPS, PCI_MAPREG_TYPE_MEM, 0, 539 &sc->bufiot, &sc->bufioh, NULL, NULL, 0)) { 540 printf("\n%s: can't map i/o space\n", sc->dev.dv_xname); 541 return; 542 } 543 544 545 if (pci_mapreg_map(pa, PCI_MAPS + 4, PCI_MAPREG_TYPE_MEM, 0, 546 &sc->regiot, &sc->regioh, NULL, NULL, 0)) { 547 printf("\n%s: can't map i/o space\n", sc->dev.dv_xname); 548 return; 549 } 550 551 /* Map and establish the interrupt. */ 552 if (pci_intr_map(pa, &ih)) { 553 printf("\n%s: couldn't map interrupt\n", sc->dev.dv_xname); 554 return; 555 } 556 intrstr = pci_intr_string(pc, ih); 557 sc->ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE, 558 neo_intr, sc, sc->dev.dv_xname); 559 560 if (sc->ih == NULL) { 561 printf("\n%s: couldn't establish interrupt", 562 sc->dev.dv_xname); 563 if (intrstr != NULL) 564 printf(" at %s", intrstr); 565 printf("\n"); 566 return; 567 } 568 printf(": %s\n", intrstr); 569 570 if ((error = nm_init(sc)) != 0) 571 return; 572 573 sc->host_if.arg = sc; 574 575 sc->host_if.attach = neo_attach_codec; 576 sc->host_if.read = neo_read_codec; 577 sc->host_if.write = neo_write_codec; 578 sc->host_if.reset = neo_reset_codec; 579 sc->host_if.flags = neo_flags_codec; 580 581 if ((error = ac97_attach(&sc->host_if)) != 0) 582 return; 583 584 audio_attach_mi(&neo_hw_if, sc, NULL, &sc->dev); 585 586 return; 587} 588 589int 590neo_activate(struct device *self, int act) 591{ 592 struct neo_softc *sc = (struct neo_softc *)self; 593 594 switch (act) { 595 case DVACT_SUSPEND: 596 break; 597 case DVACT_RESUME: 598 nm_init(sc); 599 break; 600 } 601 return 0; 602} 603 604int 605neo_match(struct device *parent, void *match, void *aux) 606{ 607 struct pci_attach_args *pa = (struct pci_attach_args *) aux; 608#if 0 609 u_int32_t subdev, badcard; 610#endif 611 612 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_NEOMAGIC) 613 return (0); 614 615#if 0 616 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); 617#endif 618 switch (PCI_PRODUCT(pa->pa_id)) { 619 case PCI_PRODUCT_NEOMAGIC_NM256AV: 620#if 0 621 i = 0; 622 while ((i < NUM_BADCARDS) && (badcards[i] != subdev)) 623 i++; 624 if (i == NUM_BADCARDS) 625 s = "NeoMagic 256AV"; 626 DEB(else) 627 DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attaching\n")); 628 return (1); 629#endif 630 case PCI_PRODUCT_NEOMAGIC_NM256ZX: 631 return (1); 632 } 633 634 return (0); 635} 636 637int 638neo_read_codec(void *sc_, u_int8_t a, u_int16_t *d) 639{ 640 struct neo_softc *sc = sc_; 641 642 if (!nm_waitcd(sc)) { 643 *d = nm_rd(sc, sc->ac97_base + a, 2); 644 DELAY(1000); 645 return 0; 646 } 647 648 return (ENXIO); 649} 650 651 652int 653neo_write_codec(void *sc_, u_int8_t a, u_int16_t d) 654{ 655 struct neo_softc *sc = sc_; 656 int cnt = 3; 657 658 if (!nm_waitcd(sc)) { 659 while (cnt-- > 0) { 660 nm_wr(sc, sc->ac97_base + a, d, 2); 661 if (!nm_waitcd(sc)) { 662 DELAY(1000); 663 return (0); 664 } 665 } 666 } 667 668 return (ENXIO); 669} 670 671 672int 673neo_attach_codec(void *sc_, struct ac97_codec_if *codec_if) 674{ 675 struct neo_softc *sc = sc_; 676 677 sc->codec_if = codec_if; 678 return (0); 679} 680 681void 682neo_reset_codec(void *sc) 683{ 684 nm_wr(sc, 0x6c0, 0x01, 1); 685 nm_wr(sc, 0x6cc, 0x87, 1); 686 nm_wr(sc, 0x6cc, 0x80, 1); 687 nm_wr(sc, 0x6cc, 0x00, 1); 688 689 return; 690} 691 692 693enum ac97_host_flags 694neo_flags_codec(void *sc) 695{ 696 return (AC97_HOST_DONT_READANY); 697} 698 699int 700neo_open(void *addr, int flags) 701{ 702 return (0); 703} 704 705/* 706 * Close function is called at splaudio(). 707 */ 708void 709neo_close(void *addr) 710{ 711 struct neo_softc *sc = addr; 712 713 neo_halt_output(sc); 714 neo_halt_input(sc); 715 716 sc->pintr = 0; 717 sc->rintr = 0; 718} 719 720/* Todo: don't commit settings to card until we've verified all parameters */ 721int 722neo_set_params(void *addr, int setmode, int usemode, 723 struct audio_params *play, struct audio_params *rec) 724{ 725 struct neo_softc *sc = addr; 726 u_int32_t base; 727 u_int8_t x; 728 int mode; 729 struct audio_params *p; 730 731 for (mode = AUMODE_RECORD; mode != -1; 732 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 733 if ((setmode & mode) == 0) 734 continue; 735 736 p = mode == AUMODE_PLAY ? play : rec; 737 738 if (p == NULL) continue; 739 740 for (x = 0; x < 8; x++) 741 if (p->sample_rate < (samplerates[x] + samplerates[x + 1]) / 2) 742 break; 743 744 p->sample_rate = samplerates[x]; 745 nm_loadcoeff(sc, mode, x); 746 747 x <<= 4; 748 x &= NM_RATE_MASK; 749 if (p->precision == 16) x |= NM_RATE_BITS_16; 750 if (p->channels == 2) x |= NM_RATE_STEREO; 751 752 base = (mode == AUMODE_PLAY) ? 753 NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET; 754 nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1); 755 756 switch (p->encoding) { 757 case AUDIO_ENCODING_SLINEAR_LE: 758 if (p->precision != 16) 759 return EINVAL; 760 break; 761 case AUDIO_ENCODING_ULINEAR_LE: 762 case AUDIO_ENCODING_ULINEAR_BE: 763 if (p->precision != 8) 764 return EINVAL; 765 break; 766 default: 767 return (EINVAL); 768 } 769 p->bps = AUDIO_BPS(p->precision); 770 p->msb = 1; 771 } 772 773 return (0); 774} 775 776int 777neo_round_blocksize(void *addr, int blk) 778{ 779 return (NM_BUFFSIZE / 2); 780} 781 782int 783neo_trigger_output(void *addr, void *start, void *end, int blksize, 784 void (*intr)(void *), void *arg, struct audio_params *param) 785{ 786 struct neo_softc *sc = addr; 787 int ssz; 788 789 mtx_enter(&audio_lock); 790 sc->pintr = intr; 791 sc->parg = arg; 792 793 ssz = (param->precision == 16) ? 2 : 1; 794 if (param->channels == 2) 795 ssz <<= 1; 796 797 sc->pbufsize = ((char *)end - (char *)start); 798 sc->pblksize = blksize; 799 sc->pwmark = blksize; 800 nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4); 801 nm_wr(sc, NM_PBUFFER_END, sc->pbuf + sc->pbufsize - ssz, 4); 802 nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4); 803 nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pwmark, 4); 804 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN | 805 NM_PLAYBACK_ENABLE_FLAG, 1); 806 nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2); 807 mtx_leave(&audio_lock); 808 return (0); 809} 810 811 812 813int 814neo_trigger_input(void *addr, void *start, void *end, int blksize, 815 void (*intr)(void *), void *arg, struct audio_params *param) 816{ 817 struct neo_softc *sc = addr; 818 int ssz; 819 820 mtx_enter(&audio_lock); 821 sc->rintr = intr; 822 sc->rarg = arg; 823 824 ssz = (param->precision == 16) ? 2 : 1; 825 if (param->channels == 2) 826 ssz <<= 1; 827 828 sc->rbufsize = ((char *)end - (char *)start); 829 sc->rblksize = blksize; 830 sc->rwmark = blksize; 831 nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4); 832 nm_wr(sc, NM_RBUFFER_END, sc->rbuf + sc->rbufsize, 4); 833 nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4); 834 nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + sc->rwmark, 4); 835 nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN | 836 NM_RECORD_ENABLE_FLAG, 1); 837 mtx_leave(&audio_lock); 838 return (0); 839} 840 841int 842neo_halt_output(void *addr) 843{ 844 struct neo_softc *sc = (struct neo_softc *)addr; 845 846 mtx_enter(&audio_lock); 847 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1); 848 nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2); 849 850 sc->pintr = 0; 851 mtx_leave(&audio_lock); 852 return (0); 853} 854 855int 856neo_halt_input(void *addr) 857{ 858 struct neo_softc *sc = (struct neo_softc *)addr; 859 860 mtx_enter(&audio_lock); 861 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1); 862 863 sc->rintr = 0; 864 mtx_leave(&audio_lock); 865 return (0); 866} 867 868int 869neo_mixer_set_port(void *addr, mixer_ctrl_t *cp) 870{ 871 struct neo_softc *sc = addr; 872 873 return ((sc->codec_if->vtbl->mixer_set_port)(sc->codec_if, cp)); 874} 875 876int 877neo_mixer_get_port(void *addr, mixer_ctrl_t *cp) 878{ 879 struct neo_softc *sc = addr; 880 881 return ((sc->codec_if->vtbl->mixer_get_port)(sc->codec_if, cp)); 882} 883 884int 885neo_query_devinfo(void *addr, mixer_devinfo_t *dip) 886{ 887 struct neo_softc *sc = addr; 888 889 return ((sc->codec_if->vtbl->query_devinfo)(sc->codec_if, dip)); 890} 891 892void * 893neo_malloc(void *addr, int direction, size_t size, int pool, int flags) 894{ 895 struct neo_softc *sc = addr; 896 void *rv = 0; 897 898 switch (direction) { 899 case AUMODE_PLAY: 900 rv = (char *)sc->bufioh + sc->pbuf; 901 break; 902 case AUMODE_RECORD: 903 rv = (char *)sc->bufioh + sc->rbuf; 904 break; 905 default: 906 break; 907 } 908 909 return (rv); 910} 911 912void 913neo_free(void *addr, void *ptr, int pool) 914{ 915 return; 916} 917 918size_t 919neo_round_buffersize(void *addr, int direction, size_t size) 920{ 921 return (NM_BUFFSIZE); 922} 923