1 /* $OpenBSD: sv.c,v 1.8 2000/04/03 21:13:48 deraadt 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/kernel.h> 42 #include <sys/malloc.h> 43 #include <sys/device.h> 44 45 #include <dev/pci/pcireg.h> 46 #include <dev/pci/pcivar.h> 47 #include <dev/pci/pcidevs.h> 48 49 #include <sys/audioio.h> 50 #include <dev/audio_if.h> 51 #include <dev/mulaw.h> 52 #include <dev/auconv.h> 53 54 #include <dev/ic/i8237reg.h> 55 #include <dev/ic/s3_617.h> 56 57 58 #include <machine/bus.h> 59 60 #ifdef __OpenBSD__ 61 struct cfdriver sv_cd = { 62 NULL, "sv", DV_DULL 63 }; 64 #endif 65 66 #ifdef AUDIO_DEBUG 67 #define DPRINTF(x) if (svdebug) printf x 68 #define DPRINTFN(n,x) if (svdebug>(n)) printf x 69 static int svdebug = 100; 70 #else 71 #define DPRINTF(x) 72 #define DPRINTFN(n,x) 73 #endif 74 75 #define __BROKEN_INDIRECT_CONFIG 76 #ifdef __BROKEN_INDIRECT_CONFIG 77 int sv_match __P((struct device *, void *, void *)); 78 #else 79 int sv_match __P((struct device *, struct cfdata *, void *)); 80 #endif 81 static void sv_attach __P((struct device *, struct device *, void *)); 82 int sv_intr __P((void *)); 83 84 struct sv_dma { 85 bus_dmamap_t map; 86 caddr_t addr; 87 bus_dma_segment_t segs[1]; 88 int nsegs; 89 size_t size; 90 struct sv_dma *next; 91 }; 92 #define DMAADDR(map) ((map)->segs[0].ds_addr) 93 #define KERNADDR(map) ((void *)((map)->addr)) 94 95 enum { 96 SV_DMAA_CONFIGURED = 1, 97 SV_DMAC_CONFIGURED = 2, 98 SV_DMAA_TRIED_CONFIGURE = 4, 99 SV_DMAC_TRIED_CONFIGURE = 8 100 }; 101 102 struct sv_softc { 103 struct device sc_dev; /* base device */ 104 void *sc_ih; /* interrupt vectoring */ 105 106 pci_chipset_tag_t sc_pci_chipset_tag; 107 pcitag_t sc_pci_tag; 108 109 bus_space_tag_t sc_iot; 110 bus_space_handle_t sc_ioh; 111 bus_space_handle_t sc_dmaa_ioh; 112 bus_space_handle_t sc_dmac_ioh; 113 bus_dma_tag_t sc_dmatag; /* DMA tag */ 114 115 struct sv_dma *sc_dmas; 116 117 void (*sc_pintr)(void *); /* dma completion intr handler */ 118 void *sc_parg; /* arg for sc_intr() */ 119 120 void (*sc_rintr)(void *); /* dma completion intr handler */ 121 void *sc_rarg; /* arg for sc_intr() */ 122 char sc_enable; 123 char sc_trd; 124 125 char sc_dma_configured; 126 u_int sc_record_source; /* recording source mask */ 127 }; 128 129 130 struct cfattach sv_ca = { 131 sizeof(struct sv_softc), sv_match, sv_attach 132 }; 133 134 struct audio_device sv_device = { 135 "S3 SonicVibes", 136 "", 137 "sv" 138 }; 139 140 #define ARRAY_SIZE(foo) ((sizeof(foo)) / sizeof(foo[0])) 141 142 int sv_allocmem __P((struct sv_softc *, size_t, size_t, struct sv_dma *)); 143 int sv_freemem __P((struct sv_softc *, struct sv_dma *)); 144 145 int sv_open __P((void *, int)); 146 void sv_close __P((void *)); 147 int sv_query_encoding __P((void *, struct audio_encoding *)); 148 int sv_set_params __P((void *, int, int, struct audio_params *, struct audio_params *)); 149 int sv_round_blocksize __P((void *, int)); 150 int sv_dma_init_output __P((void *, void *, int)); 151 int sv_dma_init_input __P((void *, void *, int)); 152 int sv_dma_output __P((void *, void *, int, void (*)(void *), void*)); 153 int sv_dma_input __P((void *, void *, int, void (*)(void *), void*)); 154 int sv_halt_in_dma __P((void *)); 155 int sv_halt_out_dma __P((void *)); 156 int sv_getdev __P((void *, struct audio_device *)); 157 int sv_mixer_set_port __P((void *, mixer_ctrl_t *)); 158 int sv_mixer_get_port __P((void *, mixer_ctrl_t *)); 159 int sv_query_devinfo __P((void *, mixer_devinfo_t *)); 160 void *sv_malloc __P((void *, u_long, int, int)); 161 void sv_free __P((void *, void *, int)); 162 u_long sv_round __P((void *, u_long)); 163 int sv_mappage __P((void *, void *, int, int)); 164 int sv_get_props __P((void *)); 165 166 void sv_dumpregs __P((struct sv_softc *sc)); 167 168 struct audio_hw_if sv_hw_if = { 169 sv_open, 170 sv_close, 171 NULL, 172 sv_query_encoding, 173 sv_set_params, 174 sv_round_blocksize, 175 NULL, 176 sv_dma_init_output, 177 sv_dma_init_input, 178 sv_dma_output, 179 sv_dma_input, 180 sv_halt_out_dma, 181 sv_halt_in_dma, 182 NULL, 183 sv_getdev, 184 NULL, 185 sv_mixer_set_port, 186 sv_mixer_get_port, 187 sv_query_devinfo, 188 sv_malloc, 189 sv_free, 190 sv_round, 191 sv_mappage, 192 sv_get_props, 193 NULL, 194 NULL 195 }; 196 197 198 static __inline__ u_int8_t sv_read __P((struct sv_softc *, u_int8_t)); 199 static __inline__ u_int8_t sv_read_indirect __P((struct sv_softc *, u_int8_t)); 200 static __inline__ void sv_write __P((struct sv_softc *, u_int8_t, u_int8_t )); 201 static __inline__ void sv_write_indirect __P((struct sv_softc *, u_int8_t, u_int8_t )); 202 static void sv_init_mixer __P((struct sv_softc *)); 203 204 static __inline__ void 205 sv_write (sc, reg, val) 206 struct sv_softc *sc; 207 u_int8_t reg, val; 208 209 { 210 bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val); 211 } 212 213 static __inline__ u_int8_t 214 sv_read (sc, reg) 215 struct sv_softc *sc; 216 u_int8_t reg; 217 218 { 219 return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg)); 220 } 221 222 static __inline__ u_int8_t 223 sv_read_indirect (sc, reg) 224 struct sv_softc *sc; 225 u_int8_t reg; 226 { 227 u_int8_t iaddr = 0; 228 229 if (sc->sc_trd > 0) 230 iaddr |= SV_IADDR_TRD; 231 232 iaddr |= (reg & SV_IADDR_MASK); 233 sv_write (sc, SV_CODEC_IADDR, iaddr); 234 235 return (sv_read(sc, SV_CODEC_IDATA)); 236 } 237 238 static __inline__ void 239 sv_write_indirect (sc, reg, val) 240 struct sv_softc *sc; 241 u_int8_t reg, val; 242 { 243 u_int8_t iaddr = 0; 244 #ifdef DIAGNOSTIC 245 if (reg > 0x3f) { 246 printf ("Invalid register\n"); 247 return; 248 } 249 #endif 250 251 if (reg == SV_DMA_DATA_FORMAT) 252 iaddr |= SV_IADDR_MCE; 253 254 if (sc->sc_trd > 0) 255 iaddr |= SV_IADDR_TRD; 256 257 iaddr |= (reg & SV_IADDR_MASK); 258 sv_write (sc, SV_CODEC_IADDR, iaddr); 259 sv_write (sc, SV_CODEC_IDATA, val); 260 } 261 262 int 263 sv_match(parent, match, aux) 264 struct device *parent; 265 void *match, *aux; 266 { 267 struct pci_attach_args *pa = aux; 268 269 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_S3 && 270 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_S3_SONICVIBES) 271 return (1); 272 273 return (0); 274 } 275 276 static void 277 sv_attach(parent, self, aux) 278 struct device *parent, *self; 279 void *aux; 280 281 { 282 struct sv_softc *sc = (struct sv_softc *)self; 283 struct pci_attach_args *pa = aux; 284 pci_chipset_tag_t pc = pa->pa_pc; 285 pci_intr_handle_t ih; 286 bus_addr_t iobase; 287 bus_size_t iosize; 288 pcireg_t csr; 289 char const *intrstr; 290 u_int32_t dmareg, dmaio; 291 u_int8_t reg; 292 293 sc->sc_pci_chipset_tag = pc; 294 sc->sc_pci_tag = pa->pa_tag; 295 296 /* Map the enhanced port only */ 297 if (pci_io_find(pc, pa->pa_tag, SV_ENHANCED_PORTBASE_SLOT, 298 &iobase, &iosize)) { 299 printf (": Couldn't find enhanced synth I/O range\n"); 300 return; 301 } 302 303 if (bus_space_map(sc->sc_iot, iobase, iosize, 0, &sc->sc_ioh)) { 304 printf(": can't map i/o space\n"); 305 return; 306 } 307 308 sc->sc_dmatag = pa->pa_dmat; 309 310 dmareg = pci_conf_read(pa->pa_pc, pa->pa_tag, SV_DMAA_CONFIG_OFF); 311 iosize = 0x10; 312 dmaio = dmareg & ~(iosize - 1); 313 314 if (dmaio) { 315 dmareg &= 0xF; 316 317 if (bus_space_map(sc->sc_iot, dmaio, iosize, 0, &sc->sc_dmaa_ioh)) { 318 /* The BIOS assigned us some bad I/O address! Make sure to clear 319 and disable this DMA before we enable the device */ 320 pci_conf_write(pa->pa_pc, pa->pa_tag, SV_DMAA_CONFIG_OFF, 0); 321 322 printf (": can't map DMA i/o space\n"); 323 goto enable; 324 } 325 326 pci_conf_write(pa->pa_pc, pa->pa_tag, SV_DMAA_CONFIG_OFF, 327 dmaio | dmareg | 328 SV_DMA_CHANNEL_ENABLE | SV_DMAA_EXTENDED_ADDR); 329 sc->sc_dma_configured |= SV_DMAA_CONFIGURED; 330 } 331 332 dmareg = pci_conf_read(pa->pa_pc, pa->pa_tag, SV_DMAC_CONFIG_OFF); 333 dmaio = dmareg & ~(iosize - 1); 334 if (dmaio) { 335 dmareg &= 0xF; 336 337 if (bus_space_map(sc->sc_iot, dmaio, iosize, 0, &sc->sc_dmac_ioh)) { 338 /* The BIOS assigned us some bad I/O address! Make sure to clear 339 and disable this DMA before we enable the device */ 340 pci_conf_write (pa->pa_pc, pa->pa_tag, SV_DMAC_CONFIG_OFF, 341 dmareg & ~SV_DMA_CHANNEL_ENABLE); 342 printf (": can't map DMA i/o space\n"); 343 goto enable; 344 } 345 346 pci_conf_write(pa->pa_pc, pa->pa_tag, SV_DMAC_CONFIG_OFF, 347 dmaio | dmareg | SV_DMA_CHANNEL_ENABLE); 348 sc->sc_dma_configured |= SV_DMAC_CONFIGURED; 349 } 350 351 /* Enable the device. */ 352 enable: 353 csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 354 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 355 csr | PCI_COMMAND_MASTER_ENABLE 356 /* | PCI_COMMAND_IO_ENABLE | PCI_COMMAND_PARITY_ENABLE */); 357 358 sv_write_indirect(sc, SV_ANALOG_POWER_DOWN_CONTROL, 0); 359 sv_write_indirect(sc, SV_DIGITAL_POWER_DOWN_CONTROL, 0); 360 361 /* initialize codec registers */ 362 reg = sv_read(sc, SV_CODEC_CONTROL); 363 reg |= SV_CTL_RESET; 364 sv_write(sc, SV_CODEC_CONTROL, reg); 365 delay(50); 366 367 reg = sv_read(sc, SV_CODEC_CONTROL); 368 reg &= ~SV_CTL_RESET; 369 reg |= SV_CTL_INTA | SV_CTL_ENHANCED; 370 371 /* This write clears the reset */ 372 sv_write(sc, SV_CODEC_CONTROL, reg); 373 delay(50); 374 375 /* This write actually shoves the new values in */ 376 sv_write(sc, SV_CODEC_CONTROL, reg); 377 378 DPRINTF (("reg: %x\n", sv_read(sc, SV_CODEC_CONTROL))); 379 380 /* Enable DMA interrupts */ 381 reg = sv_read(sc, SV_CODEC_INTMASK); 382 reg &= ~(SV_INTMASK_DMAA | SV_INTMASK_DMAC); 383 reg |= SV_INTMASK_UD | SV_INTMASK_SINT | SV_INTMASK_MIDI; 384 sv_write(sc, SV_CODEC_INTMASK, reg); 385 386 sv_read(sc, SV_CODEC_STATUS); 387 388 sc->sc_trd = 0; 389 sc->sc_enable = 0; 390 391 /* Map and establish the interrupt. */ 392 if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, 393 pa->pa_intrline, &ih)) { 394 printf(": couldn't map interrupt\n"); 395 return; 396 } 397 intrstr = pci_intr_string(pc, ih); 398 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, sv_intr, sc, 399 sc->sc_dev.dv_xname); 400 if (sc->sc_ih == NULL) { 401 printf(": couldn't establish interrupt"); 402 if (intrstr != NULL) 403 printf(" at %s", intrstr); 404 printf("\n"); 405 return; 406 } 407 printf(": %s\n", intrstr); 408 409 sv_init_mixer(sc); 410 411 audio_attach_mi(&sv_hw_if, sc, &sc->sc_dev); 412 } 413 414 #ifdef AUDIO_DEBUG 415 void 416 sv_dumpregs(sc) 417 struct sv_softc *sc; 418 { 419 int idx; 420 421 { int idx; 422 for (idx = 0; idx < 0x50; idx += 4) { 423 printf ("%02x = %x\n", idx, pci_conf_read(sc->sc_pci_chipset_tag, 424 sc->sc_pci_tag, idx)); 425 } 426 } 427 428 for (idx = 0; idx < 6; idx++) { 429 printf ("REG %02x = %02x\n", idx, sv_read(sc, idx)); 430 } 431 432 for (idx = 0; idx < 0x32; idx++) { 433 printf ("IREG %02x = %02x\n", idx, sv_read_indirect(sc, idx)); 434 } 435 436 for (idx = 0; idx < 0x10; idx++) { 437 printf ("DMA %02x = %02x\n", idx, 438 bus_space_read_1(sc->sc_iot, sc->sc_dmaa_ioh, idx)); 439 } 440 441 return; 442 } 443 #endif 444 445 int 446 sv_intr(p) 447 void *p; 448 { 449 struct sv_softc *sc = p; 450 u_int8_t intr; 451 452 intr = sv_read(sc, SV_CODEC_STATUS); 453 454 if (!(intr & (SV_INTSTATUS_DMAA | SV_INTSTATUS_DMAC))) 455 return (0); 456 457 if (intr & SV_INTSTATUS_DMAA) { 458 if (sc->sc_pintr) 459 sc->sc_pintr(sc->sc_parg); 460 } 461 462 if (intr & SV_INTSTATUS_DMAC) { 463 if (sc->sc_rintr) 464 sc->sc_rintr(sc->sc_rarg); 465 } 466 467 return (1); 468 } 469 470 int 471 sv_allocmem(sc, size, align, p) 472 struct sv_softc *sc; 473 size_t size; 474 size_t align; 475 struct sv_dma *p; 476 { 477 int error; 478 479 p->size = size; 480 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0, 481 p->segs, ARRAY_SIZE(p->segs), 482 &p->nsegs, BUS_DMA_NOWAIT); 483 if (error) 484 return (error); 485 486 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 487 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 488 if (error) 489 goto free; 490 491 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size, 492 0, BUS_DMA_NOWAIT, &p->map); 493 if (error) 494 goto unmap; 495 496 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 497 BUS_DMA_NOWAIT); 498 if (error) 499 goto destroy; 500 return (0); 501 502 destroy: 503 bus_dmamap_destroy(sc->sc_dmatag, p->map); 504 unmap: 505 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 506 free: 507 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 508 return (error); 509 } 510 511 int 512 sv_freemem(sc, p) 513 struct sv_softc *sc; 514 struct sv_dma *p; 515 { 516 bus_dmamap_unload(sc->sc_dmatag, p->map); 517 bus_dmamap_destroy(sc->sc_dmatag, p->map); 518 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 519 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 520 return (0); 521 } 522 523 int 524 sv_open(addr, flags) 525 void *addr; 526 int flags; 527 { 528 529 struct sv_softc *sc = addr; 530 int intr_mask = 0; 531 u_int8_t reg; 532 533 /* Map the DMA channels, if necessary */ 534 if (!(sc->sc_dma_configured & SV_DMAA_CONFIGURED)) { 535 /* XXX - there seems to be no general way to find an 536 I/O range */ 537 int dmaio; 538 int iosize = 0x10; 539 540 if (sc->sc_dma_configured & SV_DMAA_TRIED_CONFIGURE) 541 return (ENXIO); 542 543 for (dmaio = 0xa000; dmaio < 0xb000; dmaio += iosize) { 544 if (!bus_space_map(sc->sc_iot, dmaio, iosize, 0, 545 &sc->sc_dmaa_ioh)) { 546 goto found_dmaa; 547 } 548 } 549 550 sc->sc_dma_configured |= SV_DMAA_TRIED_CONFIGURE; 551 return (ENXIO); 552 found_dmaa: 553 554 pci_conf_write(sc->sc_pci_chipset_tag, sc->sc_pci_tag, 555 SV_DMAA_CONFIG_OFF, 556 dmaio | SV_DMA_CHANNEL_ENABLE 557 | SV_DMAA_EXTENDED_ADDR); 558 559 sc->sc_dma_configured |= SV_DMAA_CONFIGURED; 560 intr_mask = 1; 561 } 562 563 if (!(sc->sc_dma_configured & SV_DMAC_CONFIGURED)) { 564 /* XXX - there seems to be no general way to find an 565 I/O range */ 566 int dmaio; 567 int iosize = 0x10; 568 569 if (sc->sc_dma_configured & SV_DMAC_TRIED_CONFIGURE) 570 return (ENXIO); 571 572 for (dmaio = 0xa000; dmaio < 0xb000; dmaio += iosize) { 573 if (!bus_space_map(sc->sc_iot, dmaio, iosize, 0, 574 &sc->sc_dmac_ioh)) { 575 goto found_dmac; 576 } 577 } 578 579 sc->sc_dma_configured |= SV_DMAC_TRIED_CONFIGURE; 580 return (ENXIO); 581 found_dmac: 582 583 pci_conf_write(sc->sc_pci_chipset_tag, sc->sc_pci_tag, 584 SV_DMAC_CONFIG_OFF, 585 dmaio | SV_DMA_CHANNEL_ENABLE); 586 587 sc->sc_dma_configured |= SV_DMAC_CONFIGURED; 588 intr_mask = 1; 589 } 590 591 /* Make sure DMA interrupts are enabled */ 592 if (intr_mask) { 593 reg = sv_read(sc, SV_CODEC_INTMASK); 594 reg &= ~(SV_INTMASK_DMAA | SV_INTMASK_DMAC); 595 reg |= SV_INTMASK_UD | SV_INTMASK_SINT | SV_INTMASK_MIDI; 596 sv_write(sc, SV_CODEC_INTMASK, reg); 597 } 598 599 sc->sc_pintr = 0; 600 sc->sc_rintr = 0; 601 602 return (0); 603 } 604 605 /* 606 * Close function is called at splaudio(). 607 */ 608 void 609 sv_close(addr) 610 void *addr; 611 { 612 struct sv_softc *sc = addr; 613 614 sv_halt_in_dma(sc); 615 sv_halt_out_dma(sc); 616 617 sc->sc_pintr = 0; 618 sc->sc_rintr = 0; 619 } 620 621 int 622 sv_query_encoding(addr, fp) 623 void *addr; 624 struct audio_encoding *fp; 625 { 626 switch (fp->index) { 627 case 0: 628 strcpy(fp->name, AudioEulinear); 629 fp->encoding = AUDIO_ENCODING_ULINEAR; 630 fp->precision = 8; 631 fp->flags = 0; 632 return (0); 633 case 1: 634 strcpy(fp->name, AudioEmulaw); 635 fp->encoding = AUDIO_ENCODING_ULAW; 636 fp->precision = 8; 637 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 638 return (0); 639 case 2: 640 strcpy(fp->name, AudioEalaw); 641 fp->encoding = AUDIO_ENCODING_ALAW; 642 fp->precision = 8; 643 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 644 return (0); 645 case 3: 646 strcpy(fp->name, AudioEslinear); 647 fp->encoding = AUDIO_ENCODING_SLINEAR; 648 fp->precision = 8; 649 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 650 return (0); 651 case 4: 652 strcpy(fp->name, AudioEslinear_le); 653 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 654 fp->precision = 16; 655 fp->flags = 0; 656 return (0); 657 case 5: 658 strcpy(fp->name, AudioEulinear_le); 659 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 660 fp->precision = 16; 661 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 662 return (0); 663 case 6: 664 strcpy(fp->name, AudioEslinear_be); 665 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 666 fp->precision = 16; 667 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 668 return (0); 669 case 7: 670 strcpy(fp->name, AudioEulinear_be); 671 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 672 fp->precision = 16; 673 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 674 return (0); 675 default: 676 return (EINVAL); 677 } 678 } 679 680 int 681 sv_set_params(addr, setmode, usemode, p, r) 682 void *addr; 683 int setmode, usemode; 684 struct audio_params *p, *r; 685 { 686 struct sv_softc *sc = addr; 687 void (*pswcode) __P((void *, u_char *buf, int cnt)); 688 void (*rswcode) __P((void *, u_char *buf, int cnt)); 689 u_int32_t mode, val; 690 u_int8_t reg; 691 692 pswcode = rswcode = 0; 693 switch (p->encoding) { 694 case AUDIO_ENCODING_SLINEAR_BE: 695 if (p->precision == 16) 696 rswcode = pswcode = swap_bytes; 697 else 698 pswcode = rswcode = change_sign8; 699 break; 700 case AUDIO_ENCODING_SLINEAR_LE: 701 if (p->precision != 16) 702 pswcode = rswcode = change_sign8; 703 break; 704 case AUDIO_ENCODING_ULINEAR_BE: 705 if (p->precision == 16) { 706 pswcode = swap_bytes_change_sign16; 707 rswcode = change_sign16_swap_bytes; 708 } 709 break; 710 case AUDIO_ENCODING_ULINEAR_LE: 711 if (p->precision == 16) 712 pswcode = rswcode = change_sign16; 713 break; 714 case AUDIO_ENCODING_ULAW: 715 pswcode = mulaw_to_ulinear8; 716 rswcode = ulinear8_to_mulaw; 717 break; 718 case AUDIO_ENCODING_ALAW: 719 pswcode = alaw_to_ulinear8; 720 rswcode = ulinear8_to_alaw; 721 break; 722 default: 723 return (EINVAL); 724 } 725 726 if (p->precision == 16) 727 mode = SV_DMAA_FORMAT16 | SV_DMAC_FORMAT16; 728 else 729 mode = 0; 730 if (p->channels == 2) 731 mode |= SV_DMAA_STEREO | SV_DMAC_STEREO; 732 else if (p->channels != 1) 733 return (EINVAL); 734 if (p->sample_rate < 2000 || p->sample_rate > 48000) 735 return (EINVAL); 736 737 p->sw_code = pswcode; 738 r->sw_code = rswcode; 739 740 /* Set the encoding */ 741 reg = sv_read_indirect(sc, SV_DMA_DATA_FORMAT); 742 reg &= ~(SV_DMAA_FORMAT16 | SV_DMAC_FORMAT16 | SV_DMAA_STEREO | 743 SV_DMAC_STEREO); 744 reg |= (mode); 745 sv_write_indirect(sc, SV_DMA_DATA_FORMAT, reg); 746 747 val = p->sample_rate * 65536 / 48000; 748 749 sv_write_indirect(sc, SV_PCM_SAMPLE_RATE_0, (val & 0xff)); 750 sv_write_indirect(sc, SV_PCM_SAMPLE_RATE_1, (val >> 8)); 751 752 #define F_REF 24576000 753 754 #define ABS(x) (((x) < 0) ? (-x) : (x)) 755 756 if (setmode & AUMODE_RECORD) 757 { 758 /* The ADC reference frequency (f_out) is 512 * the sample rate */ 759 760 /* f_out is dervied from the 24.576MHZ crystal by three values: 761 M & N & R. The equation is as follows: 762 763 f_out = (m + 2) * f_ref / ((n + 2) * (2 ^ a)) 764 765 with the constraint that: 766 767 80 MhZ < (m + 2) / (n + 2) * f_ref <= 150Mhz 768 and n, m >= 1 769 */ 770 771 int goal_f_out = 512 * r->sample_rate; 772 int a, n, m, best_n, best_m, best_error = 10000000; 773 int pll_sample; 774 775 for (a = 0; a < 8; a++) { 776 if ((goal_f_out * (1 << a)) >= 80000000) 777 break; 778 } 779 780 /* a != 8 because sample_rate >= 2000 */ 781 782 for (n = 33; n > 2; n--) { 783 int error; 784 785 m = (goal_f_out * n * (1 << a)) / F_REF; 786 787 if ((m > 257) || (m < 3)) continue; 788 789 pll_sample = (m * F_REF) / (n * (1 << a)); 790 pll_sample /= 512; 791 792 /* Threshold might be good here */ 793 error = pll_sample - r->sample_rate; 794 error = ABS(error); 795 796 if (error < best_error) { 797 best_error = error; 798 best_n = n; 799 best_m = m; 800 if (error == 0) break; 801 } 802 } 803 804 805 best_n -= 2; 806 best_m -= 2; 807 808 sv_write_indirect(sc, SV_ADC_PLL_M, best_m); 809 sv_write_indirect(sc, SV_ADC_PLL_N, best_n | (a << SV_PLL_R_SHIFT)); 810 } 811 return (0); 812 } 813 814 int 815 sv_round_blocksize(addr, blk) 816 void *addr; 817 int blk; 818 { 819 return (blk & -32); /* keep good alignment */ 820 } 821 822 int 823 sv_dma_init_input(addr, buf, cc) 824 void *addr; 825 void *buf; 826 int cc; 827 { 828 struct sv_softc *sc = addr; 829 struct sv_dma *p; 830 int dma_count; 831 832 DPRINTF(("sv_dma_init_input: dma start loop input addr=%p cc=%d\n", 833 buf, cc)); 834 for (p = sc->sc_dmas; p && KERNADDR(p) != buf; p = p->next) 835 ; 836 if (!p) { 837 printf("sv_dma_init_input: bad addr %p\n", buf); 838 return (EINVAL); 839 } 840 841 dma_count = (cc >> 1) - 1; 842 843 bus_space_write_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_ADDR0, 844 DMAADDR(p)); 845 bus_space_write_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_COUNT0, 846 dma_count); 847 bus_space_write_1(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_MODE, 848 DMA37MD_WRITE | DMA37MD_LOOP); 849 850 return (0); 851 } 852 853 int 854 sv_dma_init_output(addr, buf, cc) 855 void *addr; 856 void *buf; 857 int cc; 858 { 859 struct sv_softc *sc = addr; 860 struct sv_dma *p; 861 int dma_count; 862 863 DPRINTF(("eap: dma start loop output buf=%p cc=%d\n", buf, cc)); 864 for (p = sc->sc_dmas; p && KERNADDR(p) != buf; p = p->next) 865 ; 866 if (!p) { 867 printf("sv_dma_init_output: bad addr %p\n", buf); 868 return (EINVAL); 869 } 870 871 dma_count = cc - 1; 872 873 bus_space_write_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_ADDR0, 874 DMAADDR(p)); 875 bus_space_write_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_COUNT0, 876 dma_count); 877 bus_space_write_1(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_MODE, 878 DMA37MD_READ | DMA37MD_LOOP); 879 880 return (0); 881 } 882 883 int 884 sv_dma_output(addr, p, cc, intr, arg) 885 void *addr; 886 void *p; 887 int cc; 888 void (*intr) __P((void *)); 889 void *arg; 890 { 891 struct sv_softc *sc = addr; 892 u_int8_t mode; 893 894 DPRINTFN(1, 895 ("sv_dma_output: sc=%p buf=%p cc=%d intr=%p(%p)\n", 896 addr, p, cc, intr, arg)); 897 898 sc->sc_pintr = intr; 899 sc->sc_parg = arg; 900 if (!(sc->sc_enable & SV_PLAY_ENABLE)) { 901 int dma_count = cc - 1; 902 903 sv_write_indirect(sc, SV_DMAA_COUNT1, dma_count >> 8); 904 sv_write_indirect(sc, SV_DMAA_COUNT0, (dma_count & 0xFF)); 905 906 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 907 mode |= SV_PLAY_ENABLE; 908 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode); 909 sc->sc_enable |= SV_PLAY_ENABLE; 910 } 911 return (0); 912 } 913 914 int 915 sv_dma_input(addr, p, cc, intr, arg) 916 void *addr; 917 void *p; 918 int cc; 919 void (*intr) __P((void *)); 920 void *arg; 921 { 922 struct sv_softc *sc = addr; 923 u_int8_t mode; 924 925 DPRINTFN(1, ("sv_dma_input: sc=%p buf=%p cc=%d intr=%p(%p)\n", 926 addr, p, cc, intr, arg)); 927 sc->sc_rintr = intr; 928 sc->sc_rarg = arg; 929 if (!(sc->sc_enable & SV_RECORD_ENABLE)) { 930 int dma_count = (cc >> 1) - 1; 931 932 sv_write_indirect(sc, SV_DMAC_COUNT1, dma_count >> 8); 933 sv_write_indirect(sc, SV_DMAC_COUNT0, (dma_count & 0xFF)); 934 935 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 936 mode |= SV_RECORD_ENABLE; 937 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode); 938 sc->sc_enable |= SV_RECORD_ENABLE; 939 } 940 return (0); 941 } 942 943 int 944 sv_halt_out_dma(addr) 945 void *addr; 946 { 947 struct sv_softc *sc = addr; 948 u_int8_t mode; 949 950 DPRINTF(("eap: sv_halt_out_dma\n")); 951 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 952 mode &= ~SV_PLAY_ENABLE; 953 sc->sc_enable &= ~SV_PLAY_ENABLE; 954 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode); 955 956 return (0); 957 } 958 959 int 960 sv_halt_in_dma(addr) 961 void *addr; 962 { 963 struct sv_softc *sc = addr; 964 u_int8_t mode; 965 966 DPRINTF(("eap: sv_halt_in_dma\n")); 967 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 968 mode &= ~SV_RECORD_ENABLE; 969 sc->sc_enable &= ~SV_RECORD_ENABLE; 970 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode); 971 972 return (0); 973 } 974 975 int 976 sv_getdev(addr, retp) 977 void *addr; 978 struct audio_device *retp; 979 { 980 *retp = sv_device; 981 return (0); 982 } 983 984 985 /* 986 * Mixer related code is here 987 * 988 */ 989 990 #define SV_INPUT_CLASS 0 991 #define SV_OUTPUT_CLASS 1 992 #define SV_RECORD_CLASS 2 993 994 #define SV_LAST_CLASS 2 995 996 static const char *mixer_classes[] = { AudioCinputs, AudioCoutputs, AudioCrecord }; 997 998 static const struct { 999 u_int8_t l_port; 1000 u_int8_t r_port; 1001 u_int8_t mask; 1002 u_int8_t class; 1003 const char *audio; 1004 } ports[] = { 1005 { SV_LEFT_AUX1_INPUT_CONTROL, SV_RIGHT_AUX1_INPUT_CONTROL, SV_AUX1_MASK, 1006 SV_INPUT_CLASS, "aux1" }, 1007 { SV_LEFT_CD_INPUT_CONTROL, SV_RIGHT_CD_INPUT_CONTROL, SV_CD_MASK, 1008 SV_INPUT_CLASS, AudioNcd }, 1009 { SV_LEFT_LINE_IN_INPUT_CONTROL, SV_RIGHT_LINE_IN_INPUT_CONTROL, SV_LINE_IN_MASK, 1010 SV_INPUT_CLASS, AudioNline }, 1011 { SV_MIC_INPUT_CONTROL, 0, SV_MIC_MASK, SV_INPUT_CLASS, AudioNmicrophone }, 1012 { SV_LEFT_SYNTH_INPUT_CONTROL, SV_RIGHT_SYNTH_INPUT_CONTROL, 1013 SV_SYNTH_MASK, SV_INPUT_CLASS, AudioNfmsynth }, 1014 { SV_LEFT_AUX2_INPUT_CONTROL, SV_RIGHT_AUX2_INPUT_CONTROL, SV_AUX2_MASK, 1015 SV_INPUT_CLASS, "aux2" }, 1016 { SV_LEFT_PCM_INPUT_CONTROL, SV_RIGHT_PCM_INPUT_CONTROL, SV_PCM_MASK, 1017 SV_INPUT_CLASS, AudioNdac }, 1018 { SV_LEFT_MIXER_OUTPUT_CONTROL, SV_RIGHT_MIXER_OUTPUT_CONTROL, 1019 SV_MIXER_OUT_MASK, SV_OUTPUT_CLASS, AudioNmaster } 1020 }; 1021 1022 1023 static const struct { 1024 int idx; 1025 const char *name; 1026 } record_sources[] = { 1027 { SV_REC_CD, AudioNcd }, 1028 { SV_REC_DAC, AudioNdac }, 1029 { SV_REC_AUX2, "aux2" }, 1030 { SV_REC_LINE, AudioNline }, 1031 { SV_REC_AUX1, "aux1" }, 1032 { SV_REC_MIC, AudioNmicrophone }, 1033 { SV_REC_MIXER, AudioNmixerout } 1034 }; 1035 1036 1037 #define SV_DEVICES_PER_PORT 2 1038 #define SV_FIRST_MIXER (SV_LAST_CLASS + 1) 1039 #define SV_LAST_MIXER (SV_DEVICES_PER_PORT * (ARRAY_SIZE(ports)) + SV_LAST_CLASS) 1040 #define SV_RECORD_SOURCE (SV_LAST_MIXER + 1) 1041 #define SV_MIC_BOOST (SV_LAST_MIXER + 2) 1042 #define SV_RECORD_GAIN (SV_LAST_MIXER + 3) 1043 #define SV_SRS_MODE (SV_LAST_MIXER + 4) 1044 1045 int 1046 sv_query_devinfo(addr, dip) 1047 void *addr; 1048 mixer_devinfo_t *dip; 1049 { 1050 1051 /* It's a class */ 1052 if (dip->index <= SV_LAST_CLASS) { 1053 dip->type = AUDIO_MIXER_CLASS; 1054 dip->mixer_class = dip->index; 1055 dip->next = dip->prev = AUDIO_MIXER_LAST; 1056 strcpy(dip->label.name, 1057 mixer_classes[dip->index]); 1058 return (0); 1059 } 1060 1061 if (dip->index >= SV_FIRST_MIXER && 1062 dip->index <= SV_LAST_MIXER) { 1063 int off = dip->index - SV_FIRST_MIXER; 1064 int mute = (off % SV_DEVICES_PER_PORT); 1065 int idx = off / SV_DEVICES_PER_PORT; 1066 1067 dip->mixer_class = ports[idx].class; 1068 strcpy(dip->label.name, ports[idx].audio); 1069 1070 if (!mute) { 1071 dip->type = AUDIO_MIXER_VALUE; 1072 dip->prev = AUDIO_MIXER_LAST; 1073 dip->next = dip->index + 1; 1074 1075 if (ports[idx].r_port != 0) 1076 dip->un.v.num_channels = 2; 1077 else 1078 dip->un.v.num_channels = 1; 1079 1080 strcpy(dip->un.v.units.name, AudioNvolume); 1081 1082 } else { 1083 dip->type = AUDIO_MIXER_ENUM; 1084 dip->prev = dip->index - 1; 1085 dip->next = AUDIO_MIXER_LAST; 1086 1087 strcpy(dip->label.name, AudioNmute); 1088 dip->un.e.num_mem = 2; 1089 strcpy(dip->un.e.member[0].label.name, AudioNoff); 1090 dip->un.e.member[0].ord = 0; 1091 strcpy(dip->un.e.member[1].label.name, AudioNon); 1092 dip->un.e.member[1].ord = 1; 1093 1094 } 1095 1096 return (0); 1097 } 1098 1099 switch (dip->index) { 1100 case SV_RECORD_SOURCE: 1101 dip->mixer_class = SV_RECORD_CLASS; 1102 dip->prev = AUDIO_MIXER_LAST; 1103 dip->next = SV_RECORD_GAIN; 1104 strcpy(dip->label.name, AudioNsource); 1105 dip->type = AUDIO_MIXER_ENUM; 1106 1107 dip->un.e.num_mem = ARRAY_SIZE(record_sources); 1108 1109 { 1110 int idx; 1111 for (idx = 0; idx < ARRAY_SIZE(record_sources); idx++) { 1112 strcpy(dip->un.e.member[idx].label.name, record_sources[idx].name); 1113 dip->un.e.member[idx].ord = record_sources[idx].idx; 1114 } 1115 } 1116 return (0); 1117 1118 case SV_RECORD_GAIN: 1119 dip->mixer_class = SV_RECORD_CLASS; 1120 dip->prev = SV_RECORD_SOURCE; 1121 dip->next = AUDIO_MIXER_LAST; 1122 strcpy(dip->label.name, "gain"); 1123 dip->type = AUDIO_MIXER_VALUE; 1124 dip->un.v.num_channels = 1; 1125 strcpy(dip->un.v.units.name, AudioNvolume); 1126 return (0); 1127 1128 case SV_MIC_BOOST: 1129 dip->mixer_class = SV_RECORD_CLASS; 1130 dip->prev = AUDIO_MIXER_LAST; 1131 dip->next = AUDIO_MIXER_LAST; 1132 strcpy(dip->label.name, "micboost"); 1133 goto on_off; 1134 1135 case SV_SRS_MODE: 1136 dip->mixer_class = SV_OUTPUT_CLASS; 1137 dip->prev = dip->next = AUDIO_MIXER_LAST; 1138 strcpy(dip->label.name, AudioNspatial); 1139 1140 on_off: 1141 dip->type = AUDIO_MIXER_ENUM; 1142 dip->un.e.num_mem = 2; 1143 strcpy(dip->un.e.member[0].label.name, AudioNoff); 1144 dip->un.e.member[0].ord = 0; 1145 strcpy(dip->un.e.member[1].label.name, AudioNon); 1146 dip->un.e.member[1].ord = 1; 1147 return (0); 1148 } 1149 1150 return (ENXIO); 1151 } 1152 1153 int 1154 sv_mixer_set_port(addr, cp) 1155 void *addr; 1156 mixer_ctrl_t *cp; 1157 { 1158 struct sv_softc *sc = addr; 1159 u_int8_t reg; 1160 int idx; 1161 1162 if (cp->dev >= SV_FIRST_MIXER && 1163 cp->dev <= SV_LAST_MIXER) { 1164 int off = cp->dev - SV_FIRST_MIXER; 1165 int mute = (off % SV_DEVICES_PER_PORT); 1166 idx = off / SV_DEVICES_PER_PORT; 1167 1168 if (mute) { 1169 if (cp->type != AUDIO_MIXER_ENUM) 1170 return (EINVAL); 1171 1172 reg = sv_read_indirect(sc, ports[idx].l_port); 1173 if (cp->un.ord) 1174 reg |= SV_MUTE_BIT; 1175 else 1176 reg &= ~SV_MUTE_BIT; 1177 sv_write_indirect(sc, ports[idx].l_port, reg); 1178 1179 if (ports[idx].r_port) { 1180 reg = sv_read_indirect(sc, ports[idx].r_port); 1181 if (cp->un.ord) 1182 reg |= SV_MUTE_BIT; 1183 else 1184 reg &= ~SV_MUTE_BIT; 1185 sv_write_indirect(sc, ports[idx].r_port, reg); 1186 } 1187 } else { 1188 int lval, rval; 1189 1190 if (cp->type != AUDIO_MIXER_VALUE) 1191 return (EINVAL); 1192 1193 if (cp->un.value.num_channels != 1 && 1194 cp->un.value.num_channels != 2) 1195 return (EINVAL); 1196 1197 if (ports[idx].r_port == 0) { 1198 if (cp->un.value.num_channels != 1) 1199 return (EINVAL); 1200 lval = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1201 } else { 1202 if (cp->un.value.num_channels != 2) 1203 return (EINVAL); 1204 1205 lval = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1206 rval = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1207 } 1208 1209 sc->sc_trd = 1; 1210 1211 reg = sv_read_indirect(sc, ports[idx].l_port); 1212 reg &= ~(ports[idx].mask); 1213 lval = ((AUDIO_MAX_GAIN - lval) * ports[idx].mask) / AUDIO_MAX_GAIN; 1214 reg |= lval; 1215 sv_write_indirect(sc, ports[idx].l_port, reg); 1216 1217 if (ports[idx].r_port != 0) { 1218 reg = sv_read_indirect(sc, ports[idx].r_port); 1219 reg &= ~(ports[idx].mask); 1220 1221 rval = ((AUDIO_MAX_GAIN - rval) * ports[idx].mask) / AUDIO_MAX_GAIN; 1222 reg |= rval; 1223 1224 sv_write_indirect(sc, ports[idx].r_port, reg); 1225 } 1226 1227 sc->sc_trd = 0; 1228 sv_read_indirect(sc, ports[idx].l_port); 1229 } 1230 1231 return (0); 1232 } 1233 1234 1235 switch (cp->dev) { 1236 case SV_RECORD_SOURCE: 1237 if (cp->type != AUDIO_MIXER_ENUM) 1238 return (EINVAL); 1239 1240 for (idx = 0; idx < ARRAY_SIZE(record_sources); idx++) { 1241 if (record_sources[idx].idx == cp->un.ord) 1242 goto found; 1243 } 1244 1245 return (EINVAL); 1246 1247 found: 1248 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1249 reg &= ~SV_REC_SOURCE_MASK; 1250 reg |= (((cp->un.ord) << SV_REC_SOURCE_SHIFT) & SV_REC_SOURCE_MASK); 1251 sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg); 1252 1253 reg = sv_read_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL); 1254 reg &= ~SV_REC_SOURCE_MASK; 1255 reg |= (((cp->un.ord) << SV_REC_SOURCE_SHIFT) & SV_REC_SOURCE_MASK); 1256 sv_write_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL, reg); 1257 return (0); 1258 1259 case SV_RECORD_GAIN: 1260 { 1261 int val; 1262 1263 if (cp->type != AUDIO_MIXER_VALUE) 1264 return (EINVAL); 1265 1266 if (cp->un.value.num_channels != 1) 1267 return (EINVAL); 1268 1269 val = (cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] * SV_REC_GAIN_MASK) 1270 / AUDIO_MAX_GAIN; 1271 1272 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1273 reg &= ~SV_REC_GAIN_MASK; 1274 reg |= val; 1275 sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg); 1276 1277 reg = sv_read_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL); 1278 reg &= ~SV_REC_GAIN_MASK; 1279 reg |= val; 1280 sv_write_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL, reg); 1281 1282 } 1283 1284 return (0); 1285 1286 case SV_MIC_BOOST: 1287 if (cp->type != AUDIO_MIXER_ENUM) 1288 return (EINVAL); 1289 1290 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1291 if (cp->un.ord) { 1292 reg |= SV_MIC_BOOST_BIT; 1293 } else { 1294 reg &= ~SV_MIC_BOOST_BIT; 1295 } 1296 1297 sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg); 1298 return (0); 1299 1300 case SV_SRS_MODE: 1301 if (cp->type != AUDIO_MIXER_ENUM) 1302 return (EINVAL); 1303 1304 reg = sv_read_indirect(sc, SV_SRS_SPACE_CONTROL); 1305 if (cp->un.ord) { 1306 reg &= ~SV_SRS_SPACE_ONOFF; 1307 } else { 1308 reg |= SV_SRS_SPACE_ONOFF; 1309 } 1310 1311 sv_write_indirect(sc, SV_SRS_SPACE_CONTROL, reg); 1312 return (0); 1313 } 1314 1315 return (EINVAL); 1316 } 1317 1318 int 1319 sv_mixer_get_port(addr, cp) 1320 void *addr; 1321 mixer_ctrl_t *cp; 1322 { 1323 struct sv_softc *sc = addr; 1324 int val; 1325 u_int8_t reg; 1326 1327 if (cp->dev >= SV_FIRST_MIXER && 1328 cp->dev <= SV_LAST_MIXER) { 1329 int off = cp->dev - SV_FIRST_MIXER; 1330 int mute = (off % 2); 1331 int idx = off / 2; 1332 1333 if (mute) { 1334 if (cp->type != AUDIO_MIXER_ENUM) 1335 return (EINVAL); 1336 1337 reg = sv_read_indirect(sc, ports[idx].l_port); 1338 cp->un.ord = ((reg & SV_MUTE_BIT) ? 1 : 0); 1339 } else { 1340 if (cp->type != AUDIO_MIXER_VALUE) 1341 return (EINVAL); 1342 1343 if (cp->un.value.num_channels != 1 && 1344 cp->un.value.num_channels != 2) 1345 return (EINVAL); 1346 1347 if ((ports[idx].r_port == 0 && 1348 cp->un.value.num_channels != 1) || 1349 (ports[idx].r_port != 0 && 1350 cp->un.value.num_channels != 2)) 1351 return (EINVAL); 1352 1353 reg = sv_read_indirect(sc, ports[idx].l_port); 1354 reg &= ports[idx].mask; 1355 1356 val = AUDIO_MAX_GAIN - ((reg * AUDIO_MAX_GAIN) / ports[idx].mask); 1357 1358 if (ports[idx].r_port != 0) { 1359 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = val; 1360 1361 reg = sv_read_indirect(sc, ports[idx].r_port); 1362 reg &= ports[idx].mask; 1363 1364 val = AUDIO_MAX_GAIN - ((reg * AUDIO_MAX_GAIN) / ports[idx].mask); 1365 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = val; 1366 } else 1367 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = val; 1368 } 1369 1370 return (0); 1371 } 1372 1373 switch (cp->dev) { 1374 case SV_RECORD_SOURCE: 1375 if (cp->type != AUDIO_MIXER_ENUM) 1376 return (EINVAL); 1377 1378 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1379 cp->un.ord = ((reg & SV_REC_SOURCE_MASK) >> SV_REC_SOURCE_SHIFT); 1380 1381 return (0); 1382 1383 case SV_RECORD_GAIN: 1384 if (cp->type != AUDIO_MIXER_VALUE) 1385 return (EINVAL); 1386 1387 if (cp->un.value.num_channels != 1) 1388 return (EINVAL); 1389 1390 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL) & SV_REC_GAIN_MASK; 1391 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 1392 (((unsigned int)reg) * AUDIO_MAX_GAIN) / SV_REC_GAIN_MASK; 1393 1394 return (0); 1395 1396 case SV_MIC_BOOST: 1397 if (cp->type != AUDIO_MIXER_ENUM) 1398 return (EINVAL); 1399 1400 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1401 cp->un.ord = ((reg & SV_MIC_BOOST_BIT) ? 1 : 0); 1402 1403 return (0); 1404 1405 1406 case SV_SRS_MODE: 1407 if (cp->type != AUDIO_MIXER_ENUM) 1408 return (EINVAL); 1409 1410 reg = sv_read_indirect(sc, SV_SRS_SPACE_CONTROL); 1411 1412 cp->un.ord = ((reg & SV_SRS_SPACE_ONOFF) ? 0 : 1); 1413 return (0); 1414 } 1415 1416 return (EINVAL); 1417 } 1418 1419 1420 static void 1421 sv_init_mixer(sc) 1422 struct sv_softc *sc; 1423 { 1424 mixer_ctrl_t cp; 1425 int idx; 1426 1427 cp.type = AUDIO_MIXER_ENUM; 1428 cp.dev = SV_SRS_MODE; 1429 cp.un.ord = 0; 1430 1431 sv_mixer_set_port(sc, &cp); 1432 1433 for (idx = 0; idx < ARRAY_SIZE(ports); idx++) { 1434 if (ports[idx].audio == AudioNdac) { 1435 cp.type = AUDIO_MIXER_ENUM; 1436 cp.dev = SV_FIRST_MIXER + idx * SV_DEVICES_PER_PORT + 1; 1437 cp.un.ord = 0; 1438 sv_mixer_set_port(sc, &cp); 1439 break; 1440 } 1441 } 1442 } 1443 1444 void * 1445 sv_malloc(addr, size, pool, flags) 1446 void *addr; 1447 u_long size; 1448 int pool; 1449 int flags; 1450 { 1451 struct sv_softc *sc = addr; 1452 struct sv_dma *p; 1453 int error; 1454 1455 p = malloc(sizeof(*p), pool, flags); 1456 if (!p) 1457 return (0); 1458 error = sv_allocmem(sc, size, 16, p); 1459 if (error) { 1460 free(p, pool); 1461 return (0); 1462 } 1463 p->next = sc->sc_dmas; 1464 sc->sc_dmas = p; 1465 return (KERNADDR(p)); 1466 } 1467 1468 void 1469 sv_free(addr, ptr, pool) 1470 void *addr; 1471 void *ptr; 1472 int pool; 1473 { 1474 struct sv_softc *sc = addr; 1475 struct sv_dma **p; 1476 1477 for (p = &sc->sc_dmas; *p; p = &(*p)->next) { 1478 if (KERNADDR(*p) == ptr) { 1479 sv_freemem(sc, *p); 1480 *p = (*p)->next; 1481 free(*p, pool); 1482 return; 1483 } 1484 } 1485 } 1486 1487 u_long 1488 sv_round(addr, size) 1489 void *addr; 1490 u_long size; 1491 { 1492 return (size); 1493 } 1494 1495 int 1496 sv_mappage(addr, mem, off, prot) 1497 void *addr; 1498 void *mem; 1499 int off; 1500 int prot; 1501 { 1502 struct sv_softc *sc = addr; 1503 struct sv_dma *p; 1504 1505 for (p = sc->sc_dmas; p && KERNADDR(p) != mem; p = p->next) 1506 ; 1507 if (!p) 1508 return (-1); 1509 return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, 1510 off, prot, BUS_DMA_WAITOK)); 1511 } 1512 1513 int 1514 sv_get_props(addr) 1515 void *addr; 1516 { 1517 return (AUDIO_PROP_MMAP | AUDIO_PROP_FULLDUPLEX); 1518 } 1519