1 /* $OpenBSD: sv.c,v 1.44 2024/05/24 06:02:58 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 1998 Constantine Paul Sapuntzakis 5 * All rights reserved 6 * 7 * Author: Constantine Paul Sapuntzakis (csapuntz@cvs.openbsd.org) 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 * 3. The author's name or those of the contributors may be used to 18 * endorse or promote products derived from this software without 19 * specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * S3 SonicVibes driver 36 * Heavily based on the eap driver by Lennart Augustsson 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/malloc.h> 42 #include <sys/device.h> 43 44 #include <dev/pci/pcireg.h> 45 #include <dev/pci/pcivar.h> 46 #include <dev/pci/pcidevs.h> 47 48 #include <sys/audioio.h> 49 #include <dev/audio_if.h> 50 51 #include <dev/ic/i8237reg.h> 52 #include <dev/ic/s3_617.h> 53 54 55 #include <machine/bus.h> 56 57 struct cfdriver sv_cd = { 58 NULL, "sv", DV_DULL 59 }; 60 61 #ifdef AUDIO_DEBUG 62 #define DPRINTF(x) if (svdebug) printf x 63 #define DPRINTFN(n,x) if (svdebug>(n)) printf x 64 static int svdebug = 100; 65 #else 66 #define DPRINTF(x) 67 #define DPRINTFN(n,x) 68 #endif 69 70 int sv_match(struct device *, void *, void *); 71 static void sv_attach(struct device *, struct device *, void *); 72 int sv_intr(void *); 73 74 struct sv_dma { 75 bus_dmamap_t map; 76 caddr_t addr; 77 bus_dma_segment_t segs[1]; 78 int nsegs; 79 size_t size; 80 struct sv_dma *next; 81 }; 82 #define DMAADDR(map) ((map)->segs[0].ds_addr) 83 #define KERNADDR(map) ((void *)((map)->addr)) 84 85 enum { 86 SV_DMAA_CONFIGURED = 1, 87 SV_DMAC_CONFIGURED = 2, 88 SV_DMAA_TRIED_CONFIGURE = 4, 89 SV_DMAC_TRIED_CONFIGURE = 8 90 }; 91 92 struct sv_softc { 93 struct device sc_dev; /* base device */ 94 void *sc_ih; /* interrupt vectoring */ 95 96 pci_chipset_tag_t sc_pci_chipset_tag; 97 pcitag_t sc_pci_tag; 98 99 bus_space_tag_t sc_iot; 100 bus_space_handle_t sc_ioh; 101 bus_space_handle_t sc_dmaa_ioh; 102 bus_space_handle_t sc_dmac_ioh; 103 bus_dma_tag_t sc_dmatag; /* DMA tag */ 104 105 struct sv_dma *sc_dmas; 106 107 void (*sc_pintr)(void *); /* dma completion intr handler */ 108 void *sc_parg; /* arg for sc_intr() */ 109 110 void (*sc_rintr)(void *); /* dma completion intr handler */ 111 void *sc_rarg; /* arg for sc_intr() */ 112 char sc_enable; 113 char sc_trd; 114 115 char sc_dma_configured; 116 u_int sc_record_source; /* recording source mask */ 117 }; 118 119 120 const struct cfattach sv_ca = { 121 sizeof(struct sv_softc), sv_match, sv_attach 122 }; 123 124 #define ARRAY_SIZE(foo) ((sizeof(foo)) / sizeof(foo[0])) 125 126 int sv_allocmem(struct sv_softc *, size_t, size_t, struct sv_dma *); 127 int sv_freemem(struct sv_softc *, struct sv_dma *); 128 129 int sv_open(void *, int); 130 void sv_close(void *); 131 int sv_set_params(void *, int, int, struct audio_params *, struct audio_params *); 132 int sv_round_blocksize(void *, int); 133 int sv_dma_init_output(void *, void *, int); 134 int sv_dma_init_input(void *, void *, int); 135 int sv_dma_output(void *, void *, int, void (*)(void *), void *); 136 int sv_dma_input(void *, void *, int, void (*)(void *), void *); 137 int sv_halt_in_dma(void *); 138 int sv_halt_out_dma(void *); 139 int sv_mixer_set_port(void *, mixer_ctrl_t *); 140 int sv_mixer_get_port(void *, mixer_ctrl_t *); 141 int sv_query_devinfo(void *, mixer_devinfo_t *); 142 void *sv_malloc(void *, int, size_t, int, int); 143 void sv_free(void *, void *, int); 144 145 void sv_dumpregs(struct sv_softc *sc); 146 147 const struct audio_hw_if sv_hw_if = { 148 .open = sv_open, 149 .close = sv_close, 150 .set_params = sv_set_params, 151 .round_blocksize = sv_round_blocksize, 152 .init_output = sv_dma_init_output, 153 .init_input = sv_dma_init_input, 154 .start_output = sv_dma_output, 155 .start_input = sv_dma_input, 156 .halt_output = sv_halt_out_dma, 157 .halt_input = sv_halt_in_dma, 158 .set_port = sv_mixer_set_port, 159 .get_port = sv_mixer_get_port, 160 .query_devinfo = sv_query_devinfo, 161 .allocm = sv_malloc, 162 .freem = sv_free, 163 }; 164 165 166 static __inline__ u_int8_t sv_read(struct sv_softc *, u_int8_t); 167 static __inline__ u_int8_t sv_read_indirect(struct sv_softc *, u_int8_t); 168 static __inline__ void sv_write(struct sv_softc *, u_int8_t, u_int8_t ); 169 static __inline__ void sv_write_indirect(struct sv_softc *, u_int8_t, u_int8_t ); 170 static void sv_init_mixer(struct sv_softc *); 171 172 static __inline__ void 173 sv_write (struct sv_softc *sc, u_int8_t reg, u_int8_t val) 174 { 175 bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val); 176 } 177 178 static __inline__ u_int8_t 179 sv_read (struct sv_softc *sc, u_int8_t reg) 180 { 181 return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg)); 182 } 183 184 static __inline__ u_int8_t 185 sv_read_indirect (struct sv_softc *sc, u_int8_t reg) 186 { 187 u_int8_t iaddr = 0; 188 189 if (sc->sc_trd > 0) 190 iaddr |= SV_IADDR_TRD; 191 192 iaddr |= (reg & SV_IADDR_MASK); 193 sv_write (sc, SV_CODEC_IADDR, iaddr); 194 195 return (sv_read(sc, SV_CODEC_IDATA)); 196 } 197 198 static __inline__ void 199 sv_write_indirect (struct sv_softc *sc, u_int8_t reg, u_int8_t val) 200 { 201 u_int8_t iaddr = 0; 202 #ifdef DIAGNOSTIC 203 if (reg > 0x3f) { 204 printf ("Invalid register\n"); 205 return; 206 } 207 #endif 208 209 if (reg == SV_DMA_DATA_FORMAT) 210 iaddr |= SV_IADDR_MCE; 211 212 if (sc->sc_trd > 0) 213 iaddr |= SV_IADDR_TRD; 214 215 iaddr |= (reg & SV_IADDR_MASK); 216 sv_write (sc, SV_CODEC_IADDR, iaddr); 217 sv_write (sc, SV_CODEC_IDATA, val); 218 } 219 220 int 221 sv_match(struct device *parent, void *match, void *aux) 222 { 223 struct pci_attach_args *pa = aux; 224 225 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_S3 && 226 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_S3_SONICVIBES) 227 return (1); 228 229 return (0); 230 } 231 232 static void 233 sv_attach(struct device *parent, struct device *self, void *aux) 234 { 235 struct sv_softc *sc = (struct sv_softc *)self; 236 struct pci_attach_args *pa = aux; 237 pci_chipset_tag_t pc = pa->pa_pc; 238 pci_intr_handle_t ih; 239 bus_size_t iosize; 240 char const *intrstr; 241 u_int32_t dmareg, dmaio; 242 u_int8_t reg; 243 244 sc->sc_pci_chipset_tag = pc; 245 sc->sc_pci_tag = pa->pa_tag; 246 247 /* Map the enhanced port only */ 248 if (pci_mapreg_map(pa, SV_ENHANCED_PORTBASE_SLOT, PCI_MAPREG_TYPE_IO, 0, 249 &sc->sc_iot, &sc->sc_ioh, NULL, &iosize, 0)) { 250 printf (": Couldn't map enhanced synth I/O range\n"); 251 return; 252 } 253 254 sc->sc_dmatag = pa->pa_dmat; 255 256 dmareg = pci_conf_read(pa->pa_pc, pa->pa_tag, SV_DMAA_CONFIG_OFF); 257 iosize = 0x10; 258 dmaio = dmareg & ~(iosize - 1); 259 260 if (dmaio) { 261 dmareg &= 0xF; 262 263 if (bus_space_map(sc->sc_iot, dmaio, iosize, 0, &sc->sc_dmaa_ioh)) { 264 /* The BIOS assigned us some bad I/O address! Make sure to clear 265 and disable this DMA before we enable the device */ 266 pci_conf_write(pa->pa_pc, pa->pa_tag, SV_DMAA_CONFIG_OFF, 0); 267 268 printf (": can't map DMA i/o space\n"); 269 goto enable; 270 } 271 272 pci_conf_write(pa->pa_pc, pa->pa_tag, SV_DMAA_CONFIG_OFF, 273 dmaio | dmareg | 274 SV_DMA_CHANNEL_ENABLE | SV_DMAA_EXTENDED_ADDR); 275 sc->sc_dma_configured |= SV_DMAA_CONFIGURED; 276 } 277 278 dmareg = pci_conf_read(pa->pa_pc, pa->pa_tag, SV_DMAC_CONFIG_OFF); 279 dmaio = dmareg & ~(iosize - 1); 280 if (dmaio) { 281 dmareg &= 0xF; 282 283 if (bus_space_map(sc->sc_iot, dmaio, iosize, 0, &sc->sc_dmac_ioh)) { 284 /* The BIOS assigned us some bad I/O address! Make sure to clear 285 and disable this DMA before we enable the device */ 286 pci_conf_write (pa->pa_pc, pa->pa_tag, SV_DMAC_CONFIG_OFF, 287 dmareg & ~SV_DMA_CHANNEL_ENABLE); 288 printf (": can't map DMA i/o space\n"); 289 goto enable; 290 } 291 292 pci_conf_write(pa->pa_pc, pa->pa_tag, SV_DMAC_CONFIG_OFF, 293 dmaio | dmareg | SV_DMA_CHANNEL_ENABLE); 294 sc->sc_dma_configured |= SV_DMAC_CONFIGURED; 295 } 296 297 /* Enable the device. */ 298 enable: 299 sv_write_indirect(sc, SV_ANALOG_POWER_DOWN_CONTROL, 0); 300 sv_write_indirect(sc, SV_DIGITAL_POWER_DOWN_CONTROL, 0); 301 302 /* initialize codec registers */ 303 reg = sv_read(sc, SV_CODEC_CONTROL); 304 reg |= SV_CTL_RESET; 305 sv_write(sc, SV_CODEC_CONTROL, reg); 306 delay(50); 307 308 reg = sv_read(sc, SV_CODEC_CONTROL); 309 reg &= ~SV_CTL_RESET; 310 reg |= SV_CTL_INTA | SV_CTL_ENHANCED; 311 312 /* This write clears the reset */ 313 sv_write(sc, SV_CODEC_CONTROL, reg); 314 delay(50); 315 316 /* This write actually shoves the new values in */ 317 sv_write(sc, SV_CODEC_CONTROL, reg); 318 319 DPRINTF (("reg: %x\n", sv_read(sc, SV_CODEC_CONTROL))); 320 321 /* Enable DMA interrupts */ 322 reg = sv_read(sc, SV_CODEC_INTMASK); 323 reg &= ~(SV_INTMASK_DMAA | SV_INTMASK_DMAC); 324 reg |= SV_INTMASK_UD | SV_INTMASK_SINT | SV_INTMASK_MIDI; 325 sv_write(sc, SV_CODEC_INTMASK, reg); 326 327 sv_read(sc, SV_CODEC_STATUS); 328 329 sc->sc_trd = 0; 330 sc->sc_enable = 0; 331 332 /* Map and establish the interrupt. */ 333 if (pci_intr_map(pa, &ih)) { 334 printf(": couldn't map interrupt\n"); 335 return; 336 } 337 intrstr = pci_intr_string(pc, ih); 338 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE, 339 sv_intr, sc, sc->sc_dev.dv_xname); 340 if (sc->sc_ih == NULL) { 341 printf(": couldn't establish interrupt"); 342 if (intrstr != NULL) 343 printf(" at %s", intrstr); 344 printf("\n"); 345 return; 346 } 347 printf(": %s\n", intrstr); 348 349 sv_init_mixer(sc); 350 351 audio_attach_mi(&sv_hw_if, sc, NULL, &sc->sc_dev); 352 } 353 354 #ifdef AUDIO_DEBUG 355 void 356 sv_dumpregs(struct sv_softc *sc) 357 { 358 int idx; 359 360 { int idx; 361 for (idx = 0; idx < 0x50; idx += 4) { 362 printf ("%02x = %x\n", idx, pci_conf_read(sc->sc_pci_chipset_tag, 363 sc->sc_pci_tag, idx)); 364 } 365 } 366 367 for (idx = 0; idx < 6; idx++) { 368 printf ("REG %02x = %02x\n", idx, sv_read(sc, idx)); 369 } 370 371 for (idx = 0; idx < 0x32; idx++) { 372 printf ("IREG %02x = %02x\n", idx, sv_read_indirect(sc, idx)); 373 } 374 375 for (idx = 0; idx < 0x10; idx++) { 376 printf ("DMA %02x = %02x\n", idx, 377 bus_space_read_1(sc->sc_iot, sc->sc_dmaa_ioh, idx)); 378 } 379 380 return; 381 } 382 #endif 383 384 int 385 sv_intr(void *p) 386 { 387 struct sv_softc *sc = p; 388 u_int8_t intr; 389 390 mtx_enter(&audio_lock); 391 intr = sv_read(sc, SV_CODEC_STATUS); 392 393 if (!(intr & (SV_INTSTATUS_DMAA | SV_INTSTATUS_DMAC))) { 394 mtx_leave(&audio_lock); 395 return (0); 396 } 397 398 if (intr & SV_INTSTATUS_DMAA) { 399 if (sc->sc_pintr) 400 sc->sc_pintr(sc->sc_parg); 401 } 402 403 if (intr & SV_INTSTATUS_DMAC) { 404 if (sc->sc_rintr) 405 sc->sc_rintr(sc->sc_rarg); 406 } 407 mtx_leave(&audio_lock); 408 return (1); 409 } 410 411 int 412 sv_allocmem(struct sv_softc *sc, size_t size, size_t align, struct sv_dma *p) 413 { 414 int error; 415 416 p->size = size; 417 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0, 418 p->segs, ARRAY_SIZE(p->segs), 419 &p->nsegs, BUS_DMA_NOWAIT); 420 if (error) 421 return (error); 422 423 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 424 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 425 if (error) 426 goto free; 427 428 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size, 429 0, BUS_DMA_NOWAIT, &p->map); 430 if (error) 431 goto unmap; 432 433 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 434 BUS_DMA_NOWAIT); 435 if (error) 436 goto destroy; 437 return (0); 438 439 destroy: 440 bus_dmamap_destroy(sc->sc_dmatag, p->map); 441 unmap: 442 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 443 free: 444 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 445 return (error); 446 } 447 448 int 449 sv_freemem(struct sv_softc *sc, struct sv_dma *p) 450 { 451 bus_dmamap_unload(sc->sc_dmatag, p->map); 452 bus_dmamap_destroy(sc->sc_dmatag, p->map); 453 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 454 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 455 return (0); 456 } 457 458 int 459 sv_open(void *addr, int flags) 460 { 461 462 struct sv_softc *sc = addr; 463 int intr_mask = 0; 464 u_int8_t reg; 465 466 /* Map the DMA channels, if necessary */ 467 if (!(sc->sc_dma_configured & SV_DMAA_CONFIGURED)) { 468 /* XXX - there seems to be no general way to find an 469 I/O range */ 470 int dmaio; 471 int iosize = 0x10; 472 473 if (sc->sc_dma_configured & SV_DMAA_TRIED_CONFIGURE) 474 return (ENXIO); 475 476 for (dmaio = 0xa000; dmaio < 0xb000; dmaio += iosize) { 477 if (!bus_space_map(sc->sc_iot, dmaio, iosize, 0, 478 &sc->sc_dmaa_ioh)) { 479 goto found_dmaa; 480 } 481 } 482 483 sc->sc_dma_configured |= SV_DMAA_TRIED_CONFIGURE; 484 return (ENXIO); 485 found_dmaa: 486 487 pci_conf_write(sc->sc_pci_chipset_tag, sc->sc_pci_tag, 488 SV_DMAA_CONFIG_OFF, 489 dmaio | SV_DMA_CHANNEL_ENABLE 490 | SV_DMAA_EXTENDED_ADDR); 491 492 sc->sc_dma_configured |= SV_DMAA_CONFIGURED; 493 intr_mask = 1; 494 } 495 496 if (!(sc->sc_dma_configured & SV_DMAC_CONFIGURED)) { 497 /* XXX - there seems to be no general way to find an 498 I/O range */ 499 int dmaio; 500 int iosize = 0x10; 501 502 if (sc->sc_dma_configured & SV_DMAC_TRIED_CONFIGURE) 503 return (ENXIO); 504 505 for (dmaio = 0xa000; dmaio < 0xb000; dmaio += iosize) { 506 if (!bus_space_map(sc->sc_iot, dmaio, iosize, 0, 507 &sc->sc_dmac_ioh)) { 508 goto found_dmac; 509 } 510 } 511 512 sc->sc_dma_configured |= SV_DMAC_TRIED_CONFIGURE; 513 return (ENXIO); 514 found_dmac: 515 516 pci_conf_write(sc->sc_pci_chipset_tag, sc->sc_pci_tag, 517 SV_DMAC_CONFIG_OFF, 518 dmaio | SV_DMA_CHANNEL_ENABLE); 519 520 sc->sc_dma_configured |= SV_DMAC_CONFIGURED; 521 intr_mask = 1; 522 } 523 524 /* Make sure DMA interrupts are enabled */ 525 if (intr_mask) { 526 reg = sv_read(sc, SV_CODEC_INTMASK); 527 reg &= ~(SV_INTMASK_DMAA | SV_INTMASK_DMAC); 528 reg |= SV_INTMASK_UD | SV_INTMASK_SINT | SV_INTMASK_MIDI; 529 sv_write(sc, SV_CODEC_INTMASK, reg); 530 } 531 532 sc->sc_pintr = 0; 533 sc->sc_rintr = 0; 534 535 return (0); 536 } 537 538 /* 539 * Close function is called at splaudio(). 540 */ 541 void 542 sv_close(void *addr) 543 { 544 struct sv_softc *sc = addr; 545 546 sv_halt_in_dma(sc); 547 sv_halt_out_dma(sc); 548 549 sc->sc_pintr = 0; 550 sc->sc_rintr = 0; 551 } 552 553 int 554 sv_set_params(void *addr, int setmode, int usemode, 555 struct audio_params *p, struct audio_params *r) 556 { 557 struct sv_softc *sc = addr; 558 u_int32_t mode, val; 559 u_int8_t reg; 560 561 switch (p->encoding) { 562 case AUDIO_ENCODING_SLINEAR_LE: 563 if (p->precision != 16) 564 return EINVAL; 565 break; 566 case AUDIO_ENCODING_ULINEAR_BE: 567 case AUDIO_ENCODING_ULINEAR_LE: 568 if (p->precision != 8) 569 return EINVAL; 570 break; 571 default: 572 return (EINVAL); 573 } 574 575 if (p->precision == 16) 576 mode = SV_DMAA_FORMAT16 | SV_DMAC_FORMAT16; 577 else 578 mode = 0; 579 if (p->channels > 2) 580 p->channels = 2; 581 if (p->channels == 2) 582 mode |= SV_DMAA_STEREO | SV_DMAC_STEREO; 583 if (p->sample_rate < 2000) 584 p->sample_rate = 2000; 585 if (p->sample_rate > 48000) 586 p->sample_rate = 48000; 587 588 p->bps = AUDIO_BPS(p->precision); 589 r->bps = AUDIO_BPS(r->precision); 590 p->msb = r->msb = 1; 591 592 /* Set the encoding */ 593 reg = sv_read_indirect(sc, SV_DMA_DATA_FORMAT); 594 reg &= ~(SV_DMAA_FORMAT16 | SV_DMAC_FORMAT16 | SV_DMAA_STEREO | 595 SV_DMAC_STEREO); 596 reg |= (mode); 597 sv_write_indirect(sc, SV_DMA_DATA_FORMAT, reg); 598 599 val = p->sample_rate * 65536 / 48000; 600 601 sv_write_indirect(sc, SV_PCM_SAMPLE_RATE_0, (val & 0xff)); 602 sv_write_indirect(sc, SV_PCM_SAMPLE_RATE_1, (val >> 8)); 603 604 #define F_REF 24576000 605 606 if (setmode & AUMODE_RECORD) 607 { 608 /* The ADC reference frequency (f_out) is 512 * the sample rate */ 609 610 /* f_out is derived from the 24.576MHZ crystal by three values: 611 M & N & R. The equation is as follows: 612 613 f_out = (m + 2) * f_ref / ((n + 2) * (2 ^ a)) 614 615 with the constraint that: 616 617 80 MHz < (m + 2) / (n + 2) * f_ref <= 150MHz 618 and n, m >= 1 619 */ 620 621 int goal_f_out = 512 * r->sample_rate; 622 int a, n, m, best_n, best_m, best_error = 10000000; 623 int pll_sample; 624 625 for (a = 0; a < 8; a++) { 626 if ((goal_f_out * (1 << a)) >= 80000000) 627 break; 628 } 629 630 /* a != 8 because sample_rate >= 2000 */ 631 632 for (n = 33; n > 2; n--) { 633 int error; 634 635 m = (goal_f_out * n * (1 << a)) / F_REF; 636 637 if ((m > 257) || (m < 3)) continue; 638 639 pll_sample = (m * F_REF) / (n * (1 << a)); 640 pll_sample /= 512; 641 642 /* Threshold might be good here */ 643 error = pll_sample - r->sample_rate; 644 error = abs(error); 645 646 if (error < best_error) { 647 best_error = error; 648 best_n = n; 649 best_m = m; 650 if (error == 0) break; 651 } 652 } 653 654 655 best_n -= 2; 656 best_m -= 2; 657 658 sv_write_indirect(sc, SV_ADC_PLL_M, best_m); 659 sv_write_indirect(sc, SV_ADC_PLL_N, best_n | (a << SV_PLL_R_SHIFT)); 660 } 661 return (0); 662 } 663 664 int 665 sv_round_blocksize(void *addr, int blk) 666 { 667 return ((blk + 31) & -32); /* keep good alignment */ 668 } 669 670 int 671 sv_dma_init_input(void *addr, void *buf, int cc) 672 { 673 struct sv_softc *sc = addr; 674 struct sv_dma *p; 675 int dma_count; 676 677 DPRINTF(("sv_dma_init_input: dma start loop input addr=%p cc=%d\n", 678 buf, cc)); 679 for (p = sc->sc_dmas; p && KERNADDR(p) != buf; p = p->next) 680 ; 681 if (!p) { 682 printf("sv_dma_init_input: bad addr %p\n", buf); 683 return (EINVAL); 684 } 685 686 dma_count = (cc >> 1) - 1; 687 688 bus_space_write_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_ADDR0, 689 DMAADDR(p)); 690 bus_space_write_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_COUNT0, 691 dma_count); 692 bus_space_write_1(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_MODE, 693 DMA37MD_WRITE | DMA37MD_LOOP); 694 695 return (0); 696 } 697 698 int 699 sv_dma_init_output(void *addr, void *buf, int cc) 700 { 701 struct sv_softc *sc = addr; 702 struct sv_dma *p; 703 int dma_count; 704 705 DPRINTF(("sv: dma start loop output buf=%p cc=%d\n", buf, cc)); 706 for (p = sc->sc_dmas; p && KERNADDR(p) != buf; p = p->next) 707 ; 708 if (!p) { 709 printf("sv_dma_init_output: bad addr %p\n", buf); 710 return (EINVAL); 711 } 712 713 dma_count = cc - 1; 714 715 bus_space_write_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_ADDR0, 716 DMAADDR(p)); 717 bus_space_write_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_COUNT0, 718 dma_count); 719 bus_space_write_1(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_MODE, 720 DMA37MD_READ | DMA37MD_LOOP); 721 722 return (0); 723 } 724 725 int 726 sv_dma_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg) 727 { 728 struct sv_softc *sc = addr; 729 u_int8_t mode; 730 731 DPRINTFN(1, 732 ("sv_dma_output: sc=%p buf=%p cc=%d intr=%p(%p)\n", 733 addr, p, cc, intr, arg)); 734 sc->sc_pintr = intr; 735 sc->sc_parg = arg; 736 if (!(sc->sc_enable & SV_PLAY_ENABLE)) { 737 int dma_count = cc - 1; 738 739 sv_write_indirect(sc, SV_DMAA_COUNT1, dma_count >> 8); 740 sv_write_indirect(sc, SV_DMAA_COUNT0, (dma_count & 0xFF)); 741 742 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 743 mode |= SV_PLAY_ENABLE; 744 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode); 745 sc->sc_enable |= SV_PLAY_ENABLE; 746 } 747 return (0); 748 } 749 750 int 751 sv_dma_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg) 752 { 753 struct sv_softc *sc = addr; 754 u_int8_t mode; 755 756 DPRINTFN(1, ("sv_dma_input: sc=%p buf=%p cc=%d intr=%p(%p)\n", 757 addr, p, cc, intr, arg)); 758 sc->sc_rintr = intr; 759 sc->sc_rarg = arg; 760 if (!(sc->sc_enable & SV_RECORD_ENABLE)) { 761 int dma_count = (cc >> 1) - 1; 762 763 sv_write_indirect(sc, SV_DMAC_COUNT1, dma_count >> 8); 764 sv_write_indirect(sc, SV_DMAC_COUNT0, (dma_count & 0xFF)); 765 766 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 767 mode |= SV_RECORD_ENABLE; 768 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode); 769 sc->sc_enable |= SV_RECORD_ENABLE; 770 } 771 return (0); 772 } 773 774 int 775 sv_halt_out_dma(void *addr) 776 { 777 struct sv_softc *sc = addr; 778 u_int8_t mode; 779 780 DPRINTF(("sv: sv_halt_out_dma\n")); 781 mtx_enter(&audio_lock); 782 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 783 mode &= ~SV_PLAY_ENABLE; 784 sc->sc_enable &= ~SV_PLAY_ENABLE; 785 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode); 786 mtx_leave(&audio_lock); 787 return (0); 788 } 789 790 int 791 sv_halt_in_dma(void *addr) 792 { 793 struct sv_softc *sc = addr; 794 u_int8_t mode; 795 796 DPRINTF(("sv: sv_halt_in_dma\n")); 797 mtx_enter(&audio_lock); 798 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 799 mode &= ~SV_RECORD_ENABLE; 800 sc->sc_enable &= ~SV_RECORD_ENABLE; 801 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode); 802 mtx_leave(&audio_lock); 803 return (0); 804 } 805 806 /* 807 * Mixer related code is here 808 * 809 */ 810 811 #define SV_INPUT_CLASS 0 812 #define SV_OUTPUT_CLASS 1 813 #define SV_RECORD_CLASS 2 814 815 #define SV_LAST_CLASS 2 816 817 static const char *mixer_classes[] = { AudioCinputs, AudioCoutputs, AudioCrecord }; 818 819 static const struct { 820 u_int8_t l_port; 821 u_int8_t r_port; 822 u_int8_t mask; 823 u_int8_t class; 824 const char *audio; 825 } ports[] = { 826 { SV_LEFT_AUX1_INPUT_CONTROL, SV_RIGHT_AUX1_INPUT_CONTROL, SV_AUX1_MASK, 827 SV_INPUT_CLASS, "aux1" }, 828 { SV_LEFT_CD_INPUT_CONTROL, SV_RIGHT_CD_INPUT_CONTROL, SV_CD_MASK, 829 SV_INPUT_CLASS, AudioNcd }, 830 { SV_LEFT_LINE_IN_INPUT_CONTROL, SV_RIGHT_LINE_IN_INPUT_CONTROL, SV_LINE_IN_MASK, 831 SV_INPUT_CLASS, AudioNline }, 832 { SV_MIC_INPUT_CONTROL, 0, SV_MIC_MASK, SV_INPUT_CLASS, AudioNmicrophone }, 833 { SV_LEFT_SYNTH_INPUT_CONTROL, SV_RIGHT_SYNTH_INPUT_CONTROL, 834 SV_SYNTH_MASK, SV_INPUT_CLASS, AudioNfmsynth }, 835 { SV_LEFT_AUX2_INPUT_CONTROL, SV_RIGHT_AUX2_INPUT_CONTROL, SV_AUX2_MASK, 836 SV_INPUT_CLASS, "aux2" }, 837 { SV_LEFT_PCM_INPUT_CONTROL, SV_RIGHT_PCM_INPUT_CONTROL, SV_PCM_MASK, 838 SV_INPUT_CLASS, AudioNdac }, 839 { SV_LEFT_MIXER_OUTPUT_CONTROL, SV_RIGHT_MIXER_OUTPUT_CONTROL, 840 SV_MIXER_OUT_MASK, SV_OUTPUT_CLASS, AudioNmaster } 841 }; 842 843 844 static const struct { 845 int idx; 846 const char *name; 847 } record_sources[] = { 848 { SV_REC_CD, AudioNcd }, 849 { SV_REC_DAC, AudioNdac }, 850 { SV_REC_AUX2, "aux2" }, 851 { SV_REC_LINE, AudioNline }, 852 { SV_REC_AUX1, "aux1" }, 853 { SV_REC_MIC, AudioNmicrophone }, 854 { SV_REC_MIXER, AudioNmixerout } 855 }; 856 857 858 #define SV_DEVICES_PER_PORT 2 859 #define SV_FIRST_MIXER (SV_LAST_CLASS + 1) 860 #define SV_LAST_MIXER (SV_DEVICES_PER_PORT * (ARRAY_SIZE(ports)) + SV_LAST_CLASS) 861 #define SV_RECORD_SOURCE (SV_LAST_MIXER + 1) 862 #define SV_MIC_BOOST (SV_LAST_MIXER + 2) 863 #define SV_RECORD_GAIN (SV_LAST_MIXER + 3) 864 #define SV_SRS_MODE (SV_LAST_MIXER + 4) 865 866 int 867 sv_query_devinfo(void *addr, mixer_devinfo_t *dip) 868 { 869 870 if (dip->index < 0) 871 return (ENXIO); 872 873 /* It's a class */ 874 if (dip->index <= SV_LAST_CLASS) { 875 dip->type = AUDIO_MIXER_CLASS; 876 dip->mixer_class = dip->index; 877 dip->next = dip->prev = AUDIO_MIXER_LAST; 878 strlcpy(dip->label.name, mixer_classes[dip->index], 879 sizeof dip->label.name); 880 return (0); 881 } 882 883 if (dip->index >= SV_FIRST_MIXER && 884 dip->index <= SV_LAST_MIXER) { 885 int off = dip->index - SV_FIRST_MIXER; 886 int mute = (off % SV_DEVICES_PER_PORT); 887 int idx = off / SV_DEVICES_PER_PORT; 888 889 dip->mixer_class = ports[idx].class; 890 strlcpy(dip->label.name, ports[idx].audio, sizeof dip->label.name); 891 892 if (!mute) { 893 dip->type = AUDIO_MIXER_VALUE; 894 dip->prev = AUDIO_MIXER_LAST; 895 dip->next = dip->index + 1; 896 897 if (ports[idx].r_port != 0) 898 dip->un.v.num_channels = 2; 899 else 900 dip->un.v.num_channels = 1; 901 902 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name); 903 904 } else { 905 dip->type = AUDIO_MIXER_ENUM; 906 dip->prev = dip->index - 1; 907 dip->next = AUDIO_MIXER_LAST; 908 909 strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name); 910 dip->un.e.num_mem = 2; 911 strlcpy(dip->un.e.member[0].label.name, AudioNoff, 912 sizeof dip->un.e.member[0].label.name); 913 dip->un.e.member[0].ord = 0; 914 strlcpy(dip->un.e.member[1].label.name, AudioNon, 915 sizeof dip->un.e.member[1].label.name); 916 dip->un.e.member[1].ord = 1; 917 918 } 919 920 return (0); 921 } 922 923 switch (dip->index) { 924 case SV_RECORD_SOURCE: 925 dip->mixer_class = SV_RECORD_CLASS; 926 dip->prev = AUDIO_MIXER_LAST; 927 dip->next = SV_RECORD_GAIN; 928 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name); 929 dip->type = AUDIO_MIXER_ENUM; 930 931 dip->un.e.num_mem = ARRAY_SIZE(record_sources); 932 933 { 934 int idx; 935 for (idx = 0; idx < ARRAY_SIZE(record_sources); idx++) { 936 strlcpy(dip->un.e.member[idx].label.name, record_sources[idx].name, 937 sizeof dip->un.e.member[idx].label.name); 938 dip->un.e.member[idx].ord = record_sources[idx].idx; 939 } 940 } 941 return (0); 942 943 case SV_RECORD_GAIN: 944 dip->mixer_class = SV_RECORD_CLASS; 945 dip->prev = SV_RECORD_SOURCE; 946 dip->next = AUDIO_MIXER_LAST; 947 strlcpy(dip->label.name, "gain", sizeof dip->label.name); 948 dip->type = AUDIO_MIXER_VALUE; 949 dip->un.v.num_channels = 1; 950 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name); 951 return (0); 952 953 case SV_MIC_BOOST: 954 dip->mixer_class = SV_RECORD_CLASS; 955 dip->prev = AUDIO_MIXER_LAST; 956 dip->next = AUDIO_MIXER_LAST; 957 strlcpy(dip->label.name, "micboost", sizeof dip->label.name); 958 goto on_off; 959 960 case SV_SRS_MODE: 961 dip->mixer_class = SV_OUTPUT_CLASS; 962 dip->prev = dip->next = AUDIO_MIXER_LAST; 963 strlcpy(dip->label.name, AudioNspatial, sizeof dip->label.name); 964 965 on_off: 966 dip->type = AUDIO_MIXER_ENUM; 967 dip->un.e.num_mem = 2; 968 strlcpy(dip->un.e.member[0].label.name, AudioNoff, 969 sizeof dip->un.e.member[0].label.name); 970 dip->un.e.member[0].ord = 0; 971 strlcpy(dip->un.e.member[1].label.name, AudioNon, 972 sizeof dip->un.e.member[1].label.name); 973 dip->un.e.member[1].ord = 1; 974 return (0); 975 } 976 977 return (ENXIO); 978 } 979 980 int 981 sv_mixer_set_port(void *addr, mixer_ctrl_t *cp) 982 { 983 struct sv_softc *sc = addr; 984 u_int8_t reg; 985 int idx; 986 987 if (cp->dev >= SV_FIRST_MIXER && 988 cp->dev <= SV_LAST_MIXER) { 989 int off = cp->dev - SV_FIRST_MIXER; 990 int mute = (off % SV_DEVICES_PER_PORT); 991 idx = off / SV_DEVICES_PER_PORT; 992 993 if (mute) { 994 if (cp->type != AUDIO_MIXER_ENUM) 995 return (EINVAL); 996 997 reg = sv_read_indirect(sc, ports[idx].l_port); 998 if (cp->un.ord) 999 reg |= SV_MUTE_BIT; 1000 else 1001 reg &= ~SV_MUTE_BIT; 1002 sv_write_indirect(sc, ports[idx].l_port, reg); 1003 1004 if (ports[idx].r_port) { 1005 reg = sv_read_indirect(sc, ports[idx].r_port); 1006 if (cp->un.ord) 1007 reg |= SV_MUTE_BIT; 1008 else 1009 reg &= ~SV_MUTE_BIT; 1010 sv_write_indirect(sc, ports[idx].r_port, reg); 1011 } 1012 } else { 1013 int lval, rval; 1014 1015 if (cp->type != AUDIO_MIXER_VALUE) 1016 return (EINVAL); 1017 1018 if (cp->un.value.num_channels != 1 && 1019 cp->un.value.num_channels != 2) 1020 return (EINVAL); 1021 1022 if (ports[idx].r_port == 0) { 1023 if (cp->un.value.num_channels != 1) 1024 return (EINVAL); 1025 lval = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1026 } else { 1027 if (cp->un.value.num_channels != 2) 1028 return (EINVAL); 1029 1030 lval = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1031 rval = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1032 } 1033 1034 sc->sc_trd = 1; 1035 1036 reg = sv_read_indirect(sc, ports[idx].l_port); 1037 reg &= ~(ports[idx].mask); 1038 lval = ((AUDIO_MAX_GAIN - lval) * ports[idx].mask) / AUDIO_MAX_GAIN; 1039 reg |= lval; 1040 sv_write_indirect(sc, ports[idx].l_port, reg); 1041 1042 if (ports[idx].r_port != 0) { 1043 reg = sv_read_indirect(sc, ports[idx].r_port); 1044 reg &= ~(ports[idx].mask); 1045 1046 rval = ((AUDIO_MAX_GAIN - rval) * ports[idx].mask) / AUDIO_MAX_GAIN; 1047 reg |= rval; 1048 1049 sv_write_indirect(sc, ports[idx].r_port, reg); 1050 } 1051 1052 sc->sc_trd = 0; 1053 sv_read_indirect(sc, ports[idx].l_port); 1054 } 1055 1056 return (0); 1057 } 1058 1059 1060 switch (cp->dev) { 1061 case SV_RECORD_SOURCE: 1062 if (cp->type != AUDIO_MIXER_ENUM) 1063 return (EINVAL); 1064 1065 for (idx = 0; idx < ARRAY_SIZE(record_sources); idx++) { 1066 if (record_sources[idx].idx == cp->un.ord) 1067 goto found; 1068 } 1069 1070 return (EINVAL); 1071 1072 found: 1073 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1074 reg &= ~SV_REC_SOURCE_MASK; 1075 reg |= (((cp->un.ord) << SV_REC_SOURCE_SHIFT) & SV_REC_SOURCE_MASK); 1076 sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg); 1077 1078 reg = sv_read_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL); 1079 reg &= ~SV_REC_SOURCE_MASK; 1080 reg |= (((cp->un.ord) << SV_REC_SOURCE_SHIFT) & SV_REC_SOURCE_MASK); 1081 sv_write_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL, reg); 1082 return (0); 1083 1084 case SV_RECORD_GAIN: 1085 { 1086 int val; 1087 1088 if (cp->type != AUDIO_MIXER_VALUE) 1089 return (EINVAL); 1090 1091 if (cp->un.value.num_channels != 1) 1092 return (EINVAL); 1093 1094 val = (cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] * SV_REC_GAIN_MASK) 1095 / AUDIO_MAX_GAIN; 1096 1097 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1098 reg &= ~SV_REC_GAIN_MASK; 1099 reg |= val; 1100 sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg); 1101 1102 reg = sv_read_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL); 1103 reg &= ~SV_REC_GAIN_MASK; 1104 reg |= val; 1105 sv_write_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL, reg); 1106 1107 } 1108 1109 return (0); 1110 1111 case SV_MIC_BOOST: 1112 if (cp->type != AUDIO_MIXER_ENUM) 1113 return (EINVAL); 1114 1115 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1116 if (cp->un.ord) { 1117 reg |= SV_MIC_BOOST_BIT; 1118 } else { 1119 reg &= ~SV_MIC_BOOST_BIT; 1120 } 1121 1122 sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg); 1123 return (0); 1124 1125 case SV_SRS_MODE: 1126 if (cp->type != AUDIO_MIXER_ENUM) 1127 return (EINVAL); 1128 1129 reg = sv_read_indirect(sc, SV_SRS_SPACE_CONTROL); 1130 if (cp->un.ord) { 1131 reg &= ~SV_SRS_SPACE_ONOFF; 1132 } else { 1133 reg |= SV_SRS_SPACE_ONOFF; 1134 } 1135 1136 sv_write_indirect(sc, SV_SRS_SPACE_CONTROL, reg); 1137 return (0); 1138 } 1139 1140 return (EINVAL); 1141 } 1142 1143 int 1144 sv_mixer_get_port(void *addr, mixer_ctrl_t *cp) 1145 { 1146 struct sv_softc *sc = addr; 1147 int val; 1148 u_int8_t reg; 1149 1150 if (cp->dev >= SV_FIRST_MIXER && 1151 cp->dev <= SV_LAST_MIXER) { 1152 int off = cp->dev - SV_FIRST_MIXER; 1153 int mute = (off % 2); 1154 int idx = off / 2; 1155 1156 if (mute) { 1157 if (cp->type != AUDIO_MIXER_ENUM) 1158 return (EINVAL); 1159 1160 reg = sv_read_indirect(sc, ports[idx].l_port); 1161 cp->un.ord = ((reg & SV_MUTE_BIT) ? 1 : 0); 1162 } else { 1163 if (cp->type != AUDIO_MIXER_VALUE) 1164 return (EINVAL); 1165 1166 if (cp->un.value.num_channels != 1 && 1167 cp->un.value.num_channels != 2) 1168 return (EINVAL); 1169 1170 if ((ports[idx].r_port == 0 && 1171 cp->un.value.num_channels != 1) || 1172 (ports[idx].r_port != 0 && 1173 cp->un.value.num_channels != 2)) 1174 return (EINVAL); 1175 1176 reg = sv_read_indirect(sc, ports[idx].l_port); 1177 reg &= ports[idx].mask; 1178 1179 val = AUDIO_MAX_GAIN - ((reg * AUDIO_MAX_GAIN) / ports[idx].mask); 1180 1181 if (ports[idx].r_port != 0) { 1182 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = val; 1183 1184 reg = sv_read_indirect(sc, ports[idx].r_port); 1185 reg &= ports[idx].mask; 1186 1187 val = AUDIO_MAX_GAIN - ((reg * AUDIO_MAX_GAIN) / ports[idx].mask); 1188 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = val; 1189 } else 1190 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = val; 1191 } 1192 1193 return (0); 1194 } 1195 1196 switch (cp->dev) { 1197 case SV_RECORD_SOURCE: 1198 if (cp->type != AUDIO_MIXER_ENUM) 1199 return (EINVAL); 1200 1201 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1202 cp->un.ord = ((reg & SV_REC_SOURCE_MASK) >> SV_REC_SOURCE_SHIFT); 1203 1204 return (0); 1205 1206 case SV_RECORD_GAIN: 1207 if (cp->type != AUDIO_MIXER_VALUE) 1208 return (EINVAL); 1209 1210 if (cp->un.value.num_channels != 1) 1211 return (EINVAL); 1212 1213 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL) & SV_REC_GAIN_MASK; 1214 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 1215 (((unsigned int)reg) * AUDIO_MAX_GAIN) / SV_REC_GAIN_MASK; 1216 1217 return (0); 1218 1219 case SV_MIC_BOOST: 1220 if (cp->type != AUDIO_MIXER_ENUM) 1221 return (EINVAL); 1222 1223 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1224 cp->un.ord = ((reg & SV_MIC_BOOST_BIT) ? 1 : 0); 1225 1226 return (0); 1227 1228 1229 case SV_SRS_MODE: 1230 if (cp->type != AUDIO_MIXER_ENUM) 1231 return (EINVAL); 1232 1233 reg = sv_read_indirect(sc, SV_SRS_SPACE_CONTROL); 1234 1235 cp->un.ord = ((reg & SV_SRS_SPACE_ONOFF) ? 0 : 1); 1236 return (0); 1237 } 1238 1239 return (EINVAL); 1240 } 1241 1242 1243 static void 1244 sv_init_mixer(struct sv_softc *sc) 1245 { 1246 mixer_ctrl_t cp; 1247 int idx; 1248 1249 cp.type = AUDIO_MIXER_ENUM; 1250 cp.dev = SV_SRS_MODE; 1251 cp.un.ord = 0; 1252 1253 sv_mixer_set_port(sc, &cp); 1254 1255 for (idx = 0; idx < ARRAY_SIZE(ports); idx++) { 1256 if (strcmp(ports[idx].audio, AudioNdac) == 0) { 1257 cp.type = AUDIO_MIXER_ENUM; 1258 cp.dev = SV_FIRST_MIXER + idx * SV_DEVICES_PER_PORT + 1; 1259 cp.un.ord = 0; 1260 sv_mixer_set_port(sc, &cp); 1261 break; 1262 } 1263 } 1264 } 1265 1266 void * 1267 sv_malloc(void *addr, int direction, size_t size, int pool, int flags) 1268 { 1269 struct sv_softc *sc = addr; 1270 struct sv_dma *p; 1271 int error; 1272 1273 p = malloc(sizeof(*p), pool, flags); 1274 if (!p) 1275 return (0); 1276 error = sv_allocmem(sc, size, 16, p); 1277 if (error) { 1278 free(p, pool, sizeof(*p)); 1279 return (0); 1280 } 1281 p->next = sc->sc_dmas; 1282 sc->sc_dmas = p; 1283 return (KERNADDR(p)); 1284 } 1285 1286 void 1287 sv_free(void *addr, void *ptr, int pool) 1288 { 1289 struct sv_softc *sc = addr; 1290 struct sv_dma **p; 1291 1292 for (p = &sc->sc_dmas; *p; p = &(*p)->next) { 1293 if (KERNADDR(*p) == ptr) { 1294 sv_freemem(sc, *p); 1295 *p = (*p)->next; 1296 free(*p, pool, sizeof(**p)); 1297 return; 1298 } 1299 } 1300 } 1301