1/* $NetBSD: sv.c,v 1.45 2011/11/23 23:07:36 jmcneill Exp $ */ 2/* $OpenBSD: sv.c,v 1.2 1998/07/13 01:50:15 csapuntz Exp $ */ 3 4/* 5 * Copyright (c) 1999, 2008 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Charles M. Hannum. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33/* 34 * Copyright (c) 1998 Constantine Paul Sapuntzakis 35 * All rights reserved 36 * 37 * Author: Constantine Paul Sapuntzakis (csapuntz@cvs.openbsd.org) 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. The author's name or those of the contributors may be used to 48 * endorse or promote products derived from this software without 49 * specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS 52 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 61 * POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64/* 65 * S3 SonicVibes driver 66 * Heavily based on the eap driver by Lennart Augustsson 67 */ 68 69#include <sys/cdefs.h> 70__KERNEL_RCSID(0, "$NetBSD: sv.c,v 1.45 2011/11/23 23:07:36 jmcneill Exp $"); 71 72#include <sys/param.h> 73#include <sys/systm.h> 74#include <sys/kernel.h> 75#include <sys/kmem.h> 76#include <sys/device.h> 77 78#include <dev/pci/pcireg.h> 79#include <dev/pci/pcivar.h> 80#include <dev/pci/pcidevs.h> 81 82#include <sys/audioio.h> 83#include <dev/audio_if.h> 84#include <dev/mulaw.h> 85#include <dev/auconv.h> 86 87#include <dev/ic/i8237reg.h> 88#include <dev/pci/svreg.h> 89#include <dev/pci/svvar.h> 90 91#include <sys/bus.h> 92 93/* XXX 94 * The SonicVibes DMA is broken and only works on 24-bit addresses. 95 * As long as bus_dmamem_alloc_range() is missing we use the ISA 96 * DMA tag on i386. 97 */ 98#if defined(i386) 99#include "isa.h" 100#if NISA > 0 101#include <dev/isa/isavar.h> 102#endif 103#endif 104 105#ifdef AUDIO_DEBUG 106#define DPRINTF(x) if (svdebug) printf x 107#define DPRINTFN(n,x) if (svdebug>(n)) printf x 108int svdebug = 0; 109#else 110#define DPRINTF(x) 111#define DPRINTFN(n,x) 112#endif 113 114static int sv_match(device_t, cfdata_t, void *); 115static void sv_attach(device_t, device_t, void *); 116static int sv_intr(void *); 117 118struct sv_dma { 119 bus_dmamap_t map; 120 void *addr; 121 bus_dma_segment_t segs[1]; 122 int nsegs; 123 size_t size; 124 struct sv_dma *next; 125}; 126#define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) 127#define KERNADDR(p) ((void *)((p)->addr)) 128 129CFATTACH_DECL(sv, sizeof(struct sv_softc), 130 sv_match, sv_attach, NULL, NULL); 131 132static struct audio_device sv_device = { 133 "S3 SonicVibes", 134 "", 135 "sv" 136}; 137 138#define ARRAY_SIZE(foo) ((sizeof(foo)) / sizeof(foo[0])) 139 140static int sv_allocmem(struct sv_softc *, size_t, size_t, int, 141 struct sv_dma *); 142static int sv_freemem(struct sv_softc *, struct sv_dma *); 143 144static void sv_init_mixer(struct sv_softc *); 145 146static int sv_open(void *, int); 147static int sv_query_encoding(void *, struct audio_encoding *); 148static int sv_set_params(void *, int, int, audio_params_t *, 149 audio_params_t *, stream_filter_list_t *, 150 stream_filter_list_t *); 151static int sv_round_blocksize(void *, int, int, const audio_params_t *); 152static int sv_trigger_output(void *, void *, void *, int, void (*)(void *), 153 void *, const audio_params_t *); 154static int sv_trigger_input(void *, void *, void *, int, void (*)(void *), 155 void *, const audio_params_t *); 156static int sv_halt_output(void *); 157static int sv_halt_input(void *); 158static int sv_getdev(void *, struct audio_device *); 159static int sv_mixer_set_port(void *, mixer_ctrl_t *); 160static int sv_mixer_get_port(void *, mixer_ctrl_t *); 161static int sv_query_devinfo(void *, mixer_devinfo_t *); 162static void * sv_malloc(void *, int, size_t); 163static void sv_free(void *, void *, size_t); 164static size_t sv_round_buffersize(void *, int, size_t); 165static paddr_t sv_mappage(void *, void *, off_t, int); 166static int sv_get_props(void *); 167static void sv_get_locks(void *, kmutex_t **, kmutex_t **); 168 169#ifdef AUDIO_DEBUG 170void sv_dumpregs(struct sv_softc *sc); 171#endif 172 173static const struct audio_hw_if sv_hw_if = { 174 sv_open, 175 NULL, /* close */ 176 NULL, 177 sv_query_encoding, 178 sv_set_params, 179 sv_round_blocksize, 180 NULL, 181 NULL, 182 NULL, 183 NULL, 184 NULL, 185 sv_halt_output, 186 sv_halt_input, 187 NULL, 188 sv_getdev, 189 NULL, 190 sv_mixer_set_port, 191 sv_mixer_get_port, 192 sv_query_devinfo, 193 sv_malloc, 194 sv_free, 195 sv_round_buffersize, 196 sv_mappage, 197 sv_get_props, 198 sv_trigger_output, 199 sv_trigger_input, 200 NULL, 201 sv_get_locks, 202}; 203 204#define SV_NFORMATS 4 205static const struct audio_format sv_formats[SV_NFORMATS] = { 206 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 207 2, AUFMT_STEREO, 0, {2000, 48000}}, 208 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 209 1, AUFMT_MONAURAL, 0, {2000, 48000}}, 210 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8, 211 2, AUFMT_STEREO, 0, {2000, 48000}}, 212 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8, 213 1, AUFMT_MONAURAL, 0, {2000, 48000}}, 214}; 215 216 217static void 218sv_write(struct sv_softc *sc, uint8_t reg, uint8_t val) 219{ 220 221 DPRINTFN(8,("sv_write(0x%x, 0x%x)\n", reg, val)); 222 bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val); 223} 224 225static uint8_t 226sv_read(struct sv_softc *sc, uint8_t reg) 227{ 228 uint8_t val; 229 230 val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg); 231 DPRINTFN(8,("sv_read(0x%x) = 0x%x\n", reg, val)); 232 return val; 233} 234 235static uint8_t 236sv_read_indirect(struct sv_softc *sc, uint8_t reg) 237{ 238 uint8_t val; 239 240 sv_write(sc, SV_CODEC_IADDR, reg & SV_IADDR_MASK); 241 val = sv_read(sc, SV_CODEC_IDATA); 242 return val; 243} 244 245static void 246sv_write_indirect(struct sv_softc *sc, uint8_t reg, uint8_t val) 247{ 248 uint8_t iaddr; 249 250 iaddr = reg & SV_IADDR_MASK; 251 if (reg == SV_DMA_DATA_FORMAT) 252 iaddr |= SV_IADDR_MCE; 253 254 sv_write(sc, SV_CODEC_IADDR, iaddr); 255 sv_write(sc, SV_CODEC_IDATA, val); 256} 257 258static int 259sv_match(device_t parent, cfdata_t match, void *aux) 260{ 261 struct pci_attach_args *pa; 262 263 pa = aux; 264 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_S3 && 265 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_S3_SONICVIBES) 266 return 1; 267 268 return 0; 269} 270 271static pcireg_t pci_io_alloc_low, pci_io_alloc_high; 272 273static int 274pci_alloc_io(pci_chipset_tag_t pc, pcitag_t pt, int pcioffs, 275 bus_space_tag_t iot, bus_size_t size, bus_size_t align, 276 bus_size_t bound, int flags, bus_space_handle_t *ioh) 277{ 278 bus_addr_t addr; 279 int error; 280 281 error = bus_space_alloc(iot, pci_io_alloc_low, pci_io_alloc_high, 282 size, align, bound, flags, &addr, ioh); 283 if (error) 284 return error; 285 286 pci_conf_write(pc, pt, pcioffs, addr); 287 return 0; 288} 289 290/* 291 * Allocate IO addresses when all other configuration is done. 292 */ 293static void 294sv_defer(device_t self) 295{ 296 struct sv_softc *sc; 297 pci_chipset_tag_t pc; 298 pcitag_t pt; 299 pcireg_t dmaio; 300 301 sc = device_private(self); 302 pc = sc->sc_pa.pa_pc; 303 pt = sc->sc_pa.pa_tag; 304 DPRINTF(("sv_defer: %p\n", sc)); 305 306 /* XXX 307 * Get a reasonable default for the I/O range. 308 * Assume the range around SB_PORTBASE is valid on this PCI bus. 309 */ 310 pci_io_alloc_low = pci_conf_read(pc, pt, SV_SB_PORTBASE_SLOT); 311 pci_io_alloc_high = pci_io_alloc_low + 0x1000; 312 313 if (pci_alloc_io(pc, pt, SV_DMAA_CONFIG_OFF, 314 sc->sc_iot, SV_DMAA_SIZE, SV_DMAA_ALIGN, 0, 315 0, &sc->sc_dmaa_ioh)) { 316 printf("sv_attach: cannot allocate DMA A range\n"); 317 return; 318 } 319 dmaio = pci_conf_read(pc, pt, SV_DMAA_CONFIG_OFF); 320 DPRINTF(("sv_attach: addr a dmaio=0x%lx\n", (u_long)dmaio)); 321 pci_conf_write(pc, pt, SV_DMAA_CONFIG_OFF, 322 dmaio | SV_DMA_CHANNEL_ENABLE | SV_DMAA_EXTENDED_ADDR); 323 324 if (pci_alloc_io(pc, pt, SV_DMAC_CONFIG_OFF, 325 sc->sc_iot, SV_DMAC_SIZE, SV_DMAC_ALIGN, 0, 326 0, &sc->sc_dmac_ioh)) { 327 printf("sv_attach: cannot allocate DMA C range\n"); 328 return; 329 } 330 dmaio = pci_conf_read(pc, pt, SV_DMAC_CONFIG_OFF); 331 DPRINTF(("sv_attach: addr c dmaio=0x%lx\n", (u_long)dmaio)); 332 pci_conf_write(pc, pt, SV_DMAC_CONFIG_OFF, 333 dmaio | SV_DMA_CHANNEL_ENABLE); 334 335 sc->sc_dmaset = 1; 336} 337 338static void 339sv_attach(device_t parent, device_t self, void *aux) 340{ 341 struct sv_softc *sc; 342 struct pci_attach_args *pa; 343 pci_chipset_tag_t pc; 344 pcitag_t pt; 345 pci_intr_handle_t ih; 346 pcireg_t csr; 347 char const *intrstr; 348 uint8_t reg; 349 struct audio_attach_args arg; 350 351 sc = device_private(self); 352 pa = aux; 353 pc = pa->pa_pc; 354 pt = pa->pa_tag; 355 printf ("\n"); 356 357 /* Map I/O registers */ 358 if (pci_mapreg_map(pa, SV_ENHANCED_PORTBASE_SLOT, 359 PCI_MAPREG_TYPE_IO, 0, 360 &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) { 361 aprint_error_dev(&sc->sc_dev, "can't map enhanced i/o space\n"); 362 return; 363 } 364 if (pci_mapreg_map(pa, SV_FM_PORTBASE_SLOT, 365 PCI_MAPREG_TYPE_IO, 0, 366 &sc->sc_opliot, &sc->sc_oplioh, NULL, NULL)) { 367 aprint_error_dev(&sc->sc_dev, "can't map FM i/o space\n"); 368 return; 369 } 370 if (pci_mapreg_map(pa, SV_MIDI_PORTBASE_SLOT, 371 PCI_MAPREG_TYPE_IO, 0, 372 &sc->sc_midiiot, &sc->sc_midiioh, NULL, NULL)) { 373 aprint_error_dev(&sc->sc_dev, "can't map MIDI i/o space\n"); 374 return; 375 } 376 DPRINTF(("sv: IO ports: enhanced=0x%x, OPL=0x%x, MIDI=0x%x\n", 377 (int)sc->sc_ioh, (int)sc->sc_oplioh, (int)sc->sc_midiioh)); 378 379#if defined(alpha) 380 /* XXX Force allocation through the SGMAP. */ 381 sc->sc_dmatag = alphabus_dma_get_tag(pa->pa_dmat, ALPHA_BUS_ISA); 382#elif defined(i386) && NISA > 0 383/* XXX 384 * The SonicVibes DMA is broken and only works on 24-bit addresses. 385 * As long as bus_dmamem_alloc_range() is missing we use the ISA 386 * DMA tag on i386. 387 */ 388 sc->sc_dmatag = &isa_bus_dma_tag; 389#else 390 sc->sc_dmatag = pa->pa_dmat; 391#endif 392 393 pci_conf_write(pc, pt, SV_DMAA_CONFIG_OFF, SV_DMAA_EXTENDED_ADDR); 394 pci_conf_write(pc, pt, SV_DMAC_CONFIG_OFF, 0); 395 396 /* Enable the device. */ 397 csr = pci_conf_read(pc, pt, PCI_COMMAND_STATUS_REG); 398 pci_conf_write(pc, pt, PCI_COMMAND_STATUS_REG, 399 csr | PCI_COMMAND_MASTER_ENABLE); 400 401 sv_write_indirect(sc, SV_ANALOG_POWER_DOWN_CONTROL, 0); 402 sv_write_indirect(sc, SV_DIGITAL_POWER_DOWN_CONTROL, 0); 403 404 /* initialize codec registers */ 405 reg = sv_read(sc, SV_CODEC_CONTROL); 406 reg |= SV_CTL_RESET; 407 sv_write(sc, SV_CODEC_CONTROL, reg); 408 delay(50); 409 410 reg = sv_read(sc, SV_CODEC_CONTROL); 411 reg &= ~SV_CTL_RESET; 412 reg |= SV_CTL_INTA | SV_CTL_ENHANCED; 413 414 /* This write clears the reset */ 415 sv_write(sc, SV_CODEC_CONTROL, reg); 416 delay(50); 417 418 /* This write actually shoves the new values in */ 419 sv_write(sc, SV_CODEC_CONTROL, reg); 420 421 DPRINTF(("sv_attach: control=0x%x\n", sv_read(sc, SV_CODEC_CONTROL))); 422 423 /* Map and establish the interrupt. */ 424 if (pci_intr_map(pa, &ih)) { 425 aprint_error_dev(&sc->sc_dev, "couldn't map interrupt\n"); 426 return; 427 } 428 429 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 430 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); 431 432 intrstr = pci_intr_string(pc, ih); 433 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, sv_intr, sc); 434 if (sc->sc_ih == NULL) { 435 aprint_error_dev(&sc->sc_dev, "couldn't establish interrupt"); 436 if (intrstr != NULL) 437 aprint_error(" at %s", intrstr); 438 aprint_error("\n"); 439 mutex_destroy(&sc->sc_lock); 440 mutex_destroy(&sc->sc_intr_lock); 441 return; 442 } 443 printf("%s: interrupting at %s\n", device_xname(&sc->sc_dev), intrstr); 444 printf("%s: rev %d", device_xname(&sc->sc_dev), 445 sv_read_indirect(sc, SV_REVISION_LEVEL)); 446 if (sv_read(sc, SV_CODEC_CONTROL) & SV_CTL_MD1) 447 printf(", reverb SRAM present"); 448 if (!(sv_read_indirect(sc, SV_WAVETABLE_SOURCE_SELECT) & SV_WSS_WT0)) 449 printf(", wavetable ROM present"); 450 printf("\n"); 451 452 /* Enable DMA interrupts */ 453 reg = sv_read(sc, SV_CODEC_INTMASK); 454 reg &= ~(SV_INTMASK_DMAA | SV_INTMASK_DMAC); 455 reg |= SV_INTMASK_UD | SV_INTMASK_SINT | SV_INTMASK_MIDI; 456 sv_write(sc, SV_CODEC_INTMASK, reg); 457 sv_read(sc, SV_CODEC_STATUS); 458 459 sv_init_mixer(sc); 460 461 audio_attach_mi(&sv_hw_if, sc, &sc->sc_dev); 462 463 arg.type = AUDIODEV_TYPE_OPL; 464 arg.hwif = 0; 465 arg.hdl = 0; 466 (void)config_found(&sc->sc_dev, &arg, audioprint); 467 468 sc->sc_pa = *pa; /* for deferred setup */ 469 config_defer(self, sv_defer); 470} 471 472#ifdef AUDIO_DEBUG 473void 474sv_dumpregs(struct sv_softc *sc) 475{ 476 int idx; 477 478#if 0 479 for (idx = 0; idx < 0x50; idx += 4) 480 printf ("%02x = %x\n", idx, 481 pci_conf_read(pa->pa_pc, pa->pa_tag, idx)); 482#endif 483 484 for (idx = 0; idx < 6; idx++) 485 printf ("REG %02x = %02x\n", idx, sv_read(sc, idx)); 486 487 for (idx = 0; idx < 0x32; idx++) 488 printf ("IREG %02x = %02x\n", idx, sv_read_indirect(sc, idx)); 489 490 for (idx = 0; idx < 0x10; idx++) 491 printf ("DMA %02x = %02x\n", idx, 492 bus_space_read_1(sc->sc_iot, sc->sc_dmaa_ioh, idx)); 493} 494#endif 495 496static int 497sv_intr(void *p) 498{ 499 struct sv_softc *sc; 500 uint8_t intr; 501 502 sc = p; 503 504 mutex_spin_enter(&sc->sc_intr_lock); 505 506 intr = sv_read(sc, SV_CODEC_STATUS); 507 DPRINTFN(5,("sv_intr: intr=0x%x\n", intr)); 508 509 if (intr & SV_INTSTATUS_DMAA) { 510 if (sc->sc_pintr) 511 sc->sc_pintr(sc->sc_parg); 512 } 513 514 if (intr & SV_INTSTATUS_DMAC) { 515 if (sc->sc_rintr) 516 sc->sc_rintr(sc->sc_rarg); 517 } 518 519 mutex_spin_exit(&sc->sc_intr_lock); 520 521 return (intr & (SV_INTSTATUS_DMAA | SV_INTSTATUS_DMAC)) != 0; 522} 523 524static int 525sv_allocmem(struct sv_softc *sc, size_t size, size_t align, 526 int direction, struct sv_dma *p) 527{ 528 int error; 529 530 p->size = size; 531 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0, 532 p->segs, ARRAY_SIZE(p->segs), &p->nsegs, BUS_DMA_WAITOK); 533 if (error) 534 return error; 535 536 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 537 &p->addr, BUS_DMA_WAITOK|BUS_DMA_COHERENT); 538 if (error) 539 goto free; 540 541 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size, 542 0, BUS_DMA_WAITOK, &p->map); 543 if (error) 544 goto unmap; 545 546 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 547 BUS_DMA_WAITOK | (direction == AUMODE_RECORD) ? BUS_DMA_READ : BUS_DMA_WRITE); 548 if (error) 549 goto destroy; 550 DPRINTF(("sv_allocmem: pa=%lx va=%lx pba=%lx\n", 551 (long)p->segs[0].ds_addr, (long)KERNADDR(p), (long)DMAADDR(p))); 552 return 0; 553 554destroy: 555 bus_dmamap_destroy(sc->sc_dmatag, p->map); 556unmap: 557 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 558free: 559 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 560 return error; 561} 562 563static int 564sv_freemem(struct sv_softc *sc, struct sv_dma *p) 565{ 566 567 bus_dmamap_unload(sc->sc_dmatag, p->map); 568 bus_dmamap_destroy(sc->sc_dmatag, p->map); 569 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 570 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 571 return 0; 572} 573 574static int 575sv_open(void *addr, int flags) 576{ 577 struct sv_softc *sc; 578 579 sc = addr; 580 DPRINTF(("sv_open\n")); 581 if (!sc->sc_dmaset) 582 return ENXIO; 583 584 return 0; 585} 586 587static int 588sv_query_encoding(void *addr, struct audio_encoding *fp) 589{ 590 591 switch (fp->index) { 592 case 0: 593 strcpy(fp->name, AudioEulinear); 594 fp->encoding = AUDIO_ENCODING_ULINEAR; 595 fp->precision = 8; 596 fp->flags = 0; 597 return 0; 598 case 1: 599 strcpy(fp->name, AudioEmulaw); 600 fp->encoding = AUDIO_ENCODING_ULAW; 601 fp->precision = 8; 602 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 603 return 0; 604 case 2: 605 strcpy(fp->name, AudioEalaw); 606 fp->encoding = AUDIO_ENCODING_ALAW; 607 fp->precision = 8; 608 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 609 return 0; 610 case 3: 611 strcpy(fp->name, AudioEslinear); 612 fp->encoding = AUDIO_ENCODING_SLINEAR; 613 fp->precision = 8; 614 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 615 return 0; 616 case 4: 617 strcpy(fp->name, AudioEslinear_le); 618 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 619 fp->precision = 16; 620 fp->flags = 0; 621 return 0; 622 case 5: 623 strcpy(fp->name, AudioEulinear_le); 624 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 625 fp->precision = 16; 626 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 627 return 0; 628 case 6: 629 strcpy(fp->name, AudioEslinear_be); 630 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 631 fp->precision = 16; 632 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 633 return 0; 634 case 7: 635 strcpy(fp->name, AudioEulinear_be); 636 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 637 fp->precision = 16; 638 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 639 return 0; 640 default: 641 return EINVAL; 642 } 643} 644 645static int 646sv_set_params(void *addr, int setmode, int usemode, audio_params_t *play, 647 audio_params_t *rec, stream_filter_list_t *pfil, stream_filter_list_t *rfil) 648{ 649 struct sv_softc *sc; 650 audio_params_t *p; 651 uint32_t val; 652 653 sc = addr; 654 p = NULL; 655 /* 656 * This device only has one clock, so make the sample rates match. 657 */ 658 if (play->sample_rate != rec->sample_rate && 659 usemode == (AUMODE_PLAY | AUMODE_RECORD)) { 660 if (setmode == AUMODE_PLAY) { 661 rec->sample_rate = play->sample_rate; 662 setmode |= AUMODE_RECORD; 663 } else if (setmode == AUMODE_RECORD) { 664 play->sample_rate = rec->sample_rate; 665 setmode |= AUMODE_PLAY; 666 } else 667 return EINVAL; 668 } 669 670 if (setmode & AUMODE_RECORD) { 671 p = rec; 672 if (auconv_set_converter(sv_formats, SV_NFORMATS, 673 AUMODE_RECORD, rec, FALSE, rfil) < 0) 674 return EINVAL; 675 } 676 if (setmode & AUMODE_PLAY) { 677 p = play; 678 if (auconv_set_converter(sv_formats, SV_NFORMATS, 679 AUMODE_PLAY, play, FALSE, pfil) < 0) 680 return EINVAL; 681 } 682 683 if (p == NULL) 684 return 0; 685 686 val = p->sample_rate * 65536 / 48000; 687 /* 688 * If the sample rate is exactly 48 kHz, the fraction would overflow the 689 * register, so we have to bias it. This causes a little clock drift. 690 * The drift is below normal crystal tolerance (.0001%), so although 691 * this seems a little silly, we can pretty much ignore it. 692 * (I tested the output speed with values of 1-20, just to be sure this 693 * register isn't *supposed* to have a bias. It isn't.) 694 * - mycroft 695 */ 696 if (val > 65535) 697 val = 65535; 698 699 mutex_spin_enter(&sc->sc_intr_lock); 700 sv_write_indirect(sc, SV_PCM_SAMPLE_RATE_0, val & 0xff); 701 sv_write_indirect(sc, SV_PCM_SAMPLE_RATE_1, val >> 8); 702 mutex_spin_exit(&sc->sc_intr_lock); 703 704#define F_REF 24576000 705 706#define ABS(x) (((x) < 0) ? (-x) : (x)) 707 708 if (setmode & AUMODE_RECORD) { 709 /* The ADC reference frequency (f_out) is 512 * sample rate */ 710 711 /* f_out is dervied from the 24.576MHz crystal by three values: 712 M & N & R. The equation is as follows: 713 714 f_out = (m + 2) * f_ref / ((n + 2) * (2 ^ a)) 715 716 with the constraint that: 717 718 80 MHz < (m + 2) / (n + 2) * f_ref <= 150MHz 719 and n, m >= 1 720 */ 721 722 int goal_f_out; 723 int a, n, m, best_n, best_m, best_error; 724 int pll_sample; 725 int error; 726 727 goal_f_out = 512 * rec->sample_rate; 728 best_n = 0; 729 best_m = 0; 730 best_error = 10000000; 731 for (a = 0; a < 8; a++) { 732 if ((goal_f_out * (1 << a)) >= 80000000) 733 break; 734 } 735 736 /* a != 8 because sample_rate >= 2000 */ 737 738 for (n = 33; n > 2; n--) { 739 m = (goal_f_out * n * (1 << a)) / F_REF; 740 if ((m > 257) || (m < 3)) 741 continue; 742 743 pll_sample = (m * F_REF) / (n * (1 << a)); 744 pll_sample /= 512; 745 746 /* Threshold might be good here */ 747 error = pll_sample - rec->sample_rate; 748 error = ABS(error); 749 750 if (error < best_error) { 751 best_error = error; 752 best_n = n; 753 best_m = m; 754 if (error == 0) break; 755 } 756 } 757 758 best_n -= 2; 759 best_m -= 2; 760 761 mutex_spin_enter(&sc->sc_intr_lock); 762 sv_write_indirect(sc, SV_ADC_PLL_M, best_m); 763 sv_write_indirect(sc, SV_ADC_PLL_N, 764 best_n | (a << SV_PLL_R_SHIFT)); 765 mutex_spin_exit(&sc->sc_intr_lock); 766 } 767 768 return 0; 769} 770 771static int 772sv_round_blocksize(void *addr, int blk, int mode, 773 const audio_params_t *param) 774{ 775 776 return blk & -32; /* keep good alignment */ 777} 778 779static int 780sv_trigger_output(void *addr, void *start, void *end, int blksize, 781 void (*intr)(void *), void *arg, const audio_params_t *param) 782{ 783 struct sv_softc *sc; 784 struct sv_dma *p; 785 uint8_t mode; 786 int dma_count; 787 788 DPRINTFN(1, ("sv_trigger_output: sc=%p start=%p end=%p blksize=%d " 789 "intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 790 sc = addr; 791 sc->sc_pintr = intr; 792 sc->sc_parg = arg; 793 794 mode = sv_read_indirect(sc, SV_DMA_DATA_FORMAT); 795 mode &= ~(SV_DMAA_FORMAT16 | SV_DMAA_STEREO); 796 if (param->precision == 16) 797 mode |= SV_DMAA_FORMAT16; 798 if (param->channels == 2) 799 mode |= SV_DMAA_STEREO; 800 sv_write_indirect(sc, SV_DMA_DATA_FORMAT, mode); 801 802 for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) 803 continue; 804 if (p == NULL) { 805 printf("sv_trigger_output: bad addr %p\n", start); 806 return EINVAL; 807 } 808 809 dma_count = ((char *)end - (char *)start) - 1; 810 DPRINTF(("sv_trigger_output: DMA start loop input addr=%x cc=%d\n", 811 (int)DMAADDR(p), dma_count)); 812 813 bus_space_write_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_ADDR0, 814 DMAADDR(p)); 815 bus_space_write_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_COUNT0, 816 dma_count); 817 bus_space_write_1(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_MODE, 818 DMA37MD_READ | DMA37MD_LOOP); 819 820 DPRINTF(("sv_trigger_output: current addr=%x\n", 821 bus_space_read_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_ADDR0))); 822 823 dma_count = blksize - 1; 824 825 sv_write_indirect(sc, SV_DMAA_COUNT1, dma_count >> 8); 826 sv_write_indirect(sc, SV_DMAA_COUNT0, dma_count & 0xFF); 827 828 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 829 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode | SV_PLAY_ENABLE); 830 831 return 0; 832} 833 834static int 835sv_trigger_input(void *addr, void *start, void *end, int blksize, 836 void (*intr)(void *), void *arg, const audio_params_t *param) 837{ 838 struct sv_softc *sc; 839 struct sv_dma *p; 840 uint8_t mode; 841 int dma_count; 842 843 DPRINTFN(1, ("sv_trigger_input: sc=%p start=%p end=%p blksize=%d " 844 "intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 845 sc = addr; 846 sc->sc_rintr = intr; 847 sc->sc_rarg = arg; 848 849 mode = sv_read_indirect(sc, SV_DMA_DATA_FORMAT); 850 mode &= ~(SV_DMAC_FORMAT16 | SV_DMAC_STEREO); 851 if (param->precision == 16) 852 mode |= SV_DMAC_FORMAT16; 853 if (param->channels == 2) 854 mode |= SV_DMAC_STEREO; 855 sv_write_indirect(sc, SV_DMA_DATA_FORMAT, mode); 856 857 for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) 858 continue; 859 if (!p) { 860 printf("sv_trigger_input: bad addr %p\n", start); 861 return EINVAL; 862 } 863 864 dma_count = (((char *)end - (char *)start) >> 1) - 1; 865 DPRINTF(("sv_trigger_input: DMA start loop input addr=%x cc=%d\n", 866 (int)DMAADDR(p), dma_count)); 867 868 bus_space_write_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_ADDR0, 869 DMAADDR(p)); 870 bus_space_write_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_COUNT0, 871 dma_count); 872 bus_space_write_1(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_MODE, 873 DMA37MD_WRITE | DMA37MD_LOOP); 874 875 DPRINTF(("sv_trigger_input: current addr=%x\n", 876 bus_space_read_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_ADDR0))); 877 878 dma_count = (blksize >> 1) - 1; 879 880 sv_write_indirect(sc, SV_DMAC_COUNT1, dma_count >> 8); 881 sv_write_indirect(sc, SV_DMAC_COUNT0, dma_count & 0xFF); 882 883 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 884 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode | SV_RECORD_ENABLE); 885 886 return 0; 887} 888 889static int 890sv_halt_output(void *addr) 891{ 892 struct sv_softc *sc; 893 uint8_t mode; 894 895 DPRINTF(("sv: sv_halt_output\n")); 896 sc = addr; 897 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 898 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode & ~SV_PLAY_ENABLE); 899 sc->sc_pintr = 0; 900 901 return 0; 902} 903 904static int 905sv_halt_input(void *addr) 906{ 907 struct sv_softc *sc; 908 uint8_t mode; 909 910 DPRINTF(("sv: sv_halt_input\n")); 911 sc = addr; 912 mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE); 913 sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode & ~SV_RECORD_ENABLE); 914 sc->sc_rintr = 0; 915 916 return 0; 917} 918 919static int 920sv_getdev(void *addr, struct audio_device *retp) 921{ 922 923 *retp = sv_device; 924 return 0; 925} 926 927 928/* 929 * Mixer related code is here 930 * 931 */ 932 933#define SV_INPUT_CLASS 0 934#define SV_OUTPUT_CLASS 1 935#define SV_RECORD_CLASS 2 936 937#define SV_LAST_CLASS 2 938 939static const char *mixer_classes[] = 940 { AudioCinputs, AudioCoutputs, AudioCrecord }; 941 942static const struct { 943 uint8_t l_port; 944 uint8_t r_port; 945 uint8_t mask; 946 uint8_t class; 947 const char *audio; 948} ports[] = { 949 { SV_LEFT_AUX1_INPUT_CONTROL, SV_RIGHT_AUX1_INPUT_CONTROL, SV_AUX1_MASK, 950 SV_INPUT_CLASS, "aux1" }, 951 { SV_LEFT_CD_INPUT_CONTROL, SV_RIGHT_CD_INPUT_CONTROL, SV_CD_MASK, 952 SV_INPUT_CLASS, AudioNcd }, 953 { SV_LEFT_LINE_IN_INPUT_CONTROL, SV_RIGHT_LINE_IN_INPUT_CONTROL, SV_LINE_IN_MASK, 954 SV_INPUT_CLASS, AudioNline }, 955 { SV_MIC_INPUT_CONTROL, 0, SV_MIC_MASK, SV_INPUT_CLASS, AudioNmicrophone }, 956 { SV_LEFT_SYNTH_INPUT_CONTROL, SV_RIGHT_SYNTH_INPUT_CONTROL, 957 SV_SYNTH_MASK, SV_INPUT_CLASS, AudioNfmsynth }, 958 { SV_LEFT_AUX2_INPUT_CONTROL, SV_RIGHT_AUX2_INPUT_CONTROL, SV_AUX2_MASK, 959 SV_INPUT_CLASS, "aux2" }, 960 { SV_LEFT_PCM_INPUT_CONTROL, SV_RIGHT_PCM_INPUT_CONTROL, SV_PCM_MASK, 961 SV_INPUT_CLASS, AudioNdac }, 962 { SV_LEFT_MIXER_OUTPUT_CONTROL, SV_RIGHT_MIXER_OUTPUT_CONTROL, 963 SV_MIXER_OUT_MASK, SV_OUTPUT_CLASS, AudioNmaster } 964}; 965 966 967static const struct { 968 int idx; 969 const char *name; 970} record_sources[] = { 971 { SV_REC_CD, AudioNcd }, 972 { SV_REC_DAC, AudioNdac }, 973 { SV_REC_AUX2, "aux2" }, 974 { SV_REC_LINE, AudioNline }, 975 { SV_REC_AUX1, "aux1" }, 976 { SV_REC_MIC, AudioNmicrophone }, 977 { SV_REC_MIXER, AudioNmixerout } 978}; 979 980 981#define SV_DEVICES_PER_PORT 2 982#define SV_FIRST_MIXER (SV_LAST_CLASS + 1) 983#define SV_LAST_MIXER (SV_DEVICES_PER_PORT * (ARRAY_SIZE(ports)) + SV_LAST_CLASS) 984#define SV_RECORD_SOURCE (SV_LAST_MIXER + 1) 985#define SV_MIC_BOOST (SV_LAST_MIXER + 2) 986#define SV_RECORD_GAIN (SV_LAST_MIXER + 3) 987#define SV_SRS_MODE (SV_LAST_MIXER + 4) 988 989static int 990sv_query_devinfo(void *addr, mixer_devinfo_t *dip) 991{ 992 int i; 993 994 /* It's a class */ 995 if (dip->index <= SV_LAST_CLASS) { 996 dip->type = AUDIO_MIXER_CLASS; 997 dip->mixer_class = dip->index; 998 dip->next = dip->prev = AUDIO_MIXER_LAST; 999 strcpy(dip->label.name, mixer_classes[dip->index]); 1000 return 0; 1001 } 1002 1003 if (dip->index >= SV_FIRST_MIXER && 1004 dip->index <= SV_LAST_MIXER) { 1005 int off, mute ,idx; 1006 1007 off = dip->index - SV_FIRST_MIXER; 1008 mute = (off % SV_DEVICES_PER_PORT); 1009 idx = off / SV_DEVICES_PER_PORT; 1010 dip->mixer_class = ports[idx].class; 1011 strcpy(dip->label.name, ports[idx].audio); 1012 1013 if (!mute) { 1014 dip->type = AUDIO_MIXER_VALUE; 1015 dip->prev = AUDIO_MIXER_LAST; 1016 dip->next = dip->index + 1; 1017 1018 if (ports[idx].r_port != 0) 1019 dip->un.v.num_channels = 2; 1020 else 1021 dip->un.v.num_channels = 1; 1022 1023 strcpy(dip->un.v.units.name, AudioNvolume); 1024 } else { 1025 dip->type = AUDIO_MIXER_ENUM; 1026 dip->prev = dip->index - 1; 1027 dip->next = AUDIO_MIXER_LAST; 1028 1029 strcpy(dip->label.name, AudioNmute); 1030 dip->un.e.num_mem = 2; 1031 strcpy(dip->un.e.member[0].label.name, AudioNoff); 1032 dip->un.e.member[0].ord = 0; 1033 strcpy(dip->un.e.member[1].label.name, AudioNon); 1034 dip->un.e.member[1].ord = 1; 1035 } 1036 1037 return 0; 1038 } 1039 1040 switch (dip->index) { 1041 case SV_RECORD_SOURCE: 1042 dip->mixer_class = SV_RECORD_CLASS; 1043 dip->prev = AUDIO_MIXER_LAST; 1044 dip->next = SV_RECORD_GAIN; 1045 strcpy(dip->label.name, AudioNsource); 1046 dip->type = AUDIO_MIXER_ENUM; 1047 1048 dip->un.e.num_mem = ARRAY_SIZE(record_sources); 1049 for (i = 0; i < ARRAY_SIZE(record_sources); i++) { 1050 strcpy(dip->un.e.member[i].label.name, 1051 record_sources[i].name); 1052 dip->un.e.member[i].ord = record_sources[i].idx; 1053 } 1054 return 0; 1055 1056 case SV_RECORD_GAIN: 1057 dip->mixer_class = SV_RECORD_CLASS; 1058 dip->prev = SV_RECORD_SOURCE; 1059 dip->next = AUDIO_MIXER_LAST; 1060 strcpy(dip->label.name, "gain"); 1061 dip->type = AUDIO_MIXER_VALUE; 1062 dip->un.v.num_channels = 1; 1063 strcpy(dip->un.v.units.name, AudioNvolume); 1064 return 0; 1065 1066 case SV_MIC_BOOST: 1067 dip->mixer_class = SV_RECORD_CLASS; 1068 dip->prev = AUDIO_MIXER_LAST; 1069 dip->next = AUDIO_MIXER_LAST; 1070 strcpy(dip->label.name, "micboost"); 1071 goto on_off; 1072 1073 case SV_SRS_MODE: 1074 dip->mixer_class = SV_OUTPUT_CLASS; 1075 dip->prev = dip->next = AUDIO_MIXER_LAST; 1076 strcpy(dip->label.name, AudioNspatial); 1077 1078 on_off: 1079 dip->type = AUDIO_MIXER_ENUM; 1080 dip->un.e.num_mem = 2; 1081 strcpy(dip->un.e.member[0].label.name, AudioNoff); 1082 dip->un.e.member[0].ord = 0; 1083 strcpy(dip->un.e.member[1].label.name, AudioNon); 1084 dip->un.e.member[1].ord = 1; 1085 return 0; 1086 } 1087 1088 return ENXIO; 1089} 1090 1091static int 1092sv_mixer_set_port(void *addr, mixer_ctrl_t *cp) 1093{ 1094 struct sv_softc *sc; 1095 uint8_t reg; 1096 int idx; 1097 1098 sc = addr; 1099 if (cp->dev >= SV_FIRST_MIXER && 1100 cp->dev <= SV_LAST_MIXER) { 1101 int off, mute; 1102 1103 off = cp->dev - SV_FIRST_MIXER; 1104 mute = (off % SV_DEVICES_PER_PORT); 1105 idx = off / SV_DEVICES_PER_PORT; 1106 1107 if (mute) { 1108 if (cp->type != AUDIO_MIXER_ENUM) 1109 return EINVAL; 1110 1111 mutex_spin_enter(&sc->sc_intr_lock); 1112 reg = sv_read_indirect(sc, ports[idx].l_port); 1113 if (cp->un.ord) 1114 reg |= SV_MUTE_BIT; 1115 else 1116 reg &= ~SV_MUTE_BIT; 1117 sv_write_indirect(sc, ports[idx].l_port, reg); 1118 1119 if (ports[idx].r_port) { 1120 reg = sv_read_indirect(sc, ports[idx].r_port); 1121 if (cp->un.ord) 1122 reg |= SV_MUTE_BIT; 1123 else 1124 reg &= ~SV_MUTE_BIT; 1125 sv_write_indirect(sc, ports[idx].r_port, reg); 1126 } 1127 mutex_spin_exit(&sc->sc_intr_lock); 1128 } else { 1129 int lval, rval; 1130 1131 if (cp->type != AUDIO_MIXER_VALUE) 1132 return EINVAL; 1133 1134 if (cp->un.value.num_channels != 1 && 1135 cp->un.value.num_channels != 2) 1136 return (EINVAL); 1137 1138 if (ports[idx].r_port == 0) { 1139 if (cp->un.value.num_channels != 1) 1140 return (EINVAL); 1141 lval = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1142 rval = 0; /* shut up GCC */ 1143 } else { 1144 if (cp->un.value.num_channels != 2) 1145 return (EINVAL); 1146 1147 lval = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1148 rval = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1149 } 1150 1151 mutex_spin_enter(&sc->sc_intr_lock); 1152 reg = sv_read_indirect(sc, ports[idx].l_port); 1153 reg &= ~(ports[idx].mask); 1154 lval = (AUDIO_MAX_GAIN - lval) * ports[idx].mask / 1155 AUDIO_MAX_GAIN; 1156 reg |= lval; 1157 sv_write_indirect(sc, ports[idx].l_port, reg); 1158 1159 if (ports[idx].r_port != 0) { 1160 reg = sv_read_indirect(sc, ports[idx].r_port); 1161 reg &= ~(ports[idx].mask); 1162 1163 rval = (AUDIO_MAX_GAIN - rval) * ports[idx].mask / 1164 AUDIO_MAX_GAIN; 1165 reg |= rval; 1166 1167 sv_write_indirect(sc, ports[idx].r_port, reg); 1168 } 1169 1170 sv_read_indirect(sc, ports[idx].l_port); 1171 mutex_spin_exit(&sc->sc_intr_lock); 1172 } 1173 1174 return 0; 1175 } 1176 1177 1178 switch (cp->dev) { 1179 case SV_RECORD_SOURCE: 1180 if (cp->type != AUDIO_MIXER_ENUM) 1181 return EINVAL; 1182 1183 for (idx = 0; idx < ARRAY_SIZE(record_sources); idx++) { 1184 if (record_sources[idx].idx == cp->un.ord) 1185 goto found; 1186 } 1187 1188 return EINVAL; 1189 1190 found: 1191 mutex_spin_enter(&sc->sc_intr_lock); 1192 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1193 reg &= ~SV_REC_SOURCE_MASK; 1194 reg |= (((cp->un.ord) << SV_REC_SOURCE_SHIFT) & SV_REC_SOURCE_MASK); 1195 sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg); 1196 1197 reg = sv_read_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL); 1198 reg &= ~SV_REC_SOURCE_MASK; 1199 reg |= (((cp->un.ord) << SV_REC_SOURCE_SHIFT) & SV_REC_SOURCE_MASK); 1200 sv_write_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL, reg); 1201 mutex_spin_exit(&sc->sc_intr_lock); 1202 return 0; 1203 1204 case SV_RECORD_GAIN: 1205 { 1206 int val; 1207 1208 if (cp->type != AUDIO_MIXER_VALUE) 1209 return EINVAL; 1210 1211 if (cp->un.value.num_channels != 1) 1212 return EINVAL; 1213 1214 val = (cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] 1215 * SV_REC_GAIN_MASK) / AUDIO_MAX_GAIN; 1216 1217 mutex_spin_enter(&sc->sc_intr_lock); 1218 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1219 reg &= ~SV_REC_GAIN_MASK; 1220 reg |= val; 1221 sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg); 1222 1223 reg = sv_read_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL); 1224 reg &= ~SV_REC_GAIN_MASK; 1225 reg |= val; 1226 sv_write_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL, reg); 1227 mutex_spin_exit(&sc->sc_intr_lock); 1228 } 1229 return (0); 1230 1231 case SV_MIC_BOOST: 1232 if (cp->type != AUDIO_MIXER_ENUM) 1233 return EINVAL; 1234 1235 mutex_spin_enter(&sc->sc_intr_lock); 1236 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1237 if (cp->un.ord) { 1238 reg |= SV_MIC_BOOST_BIT; 1239 } else { 1240 reg &= ~SV_MIC_BOOST_BIT; 1241 } 1242 1243 sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg); 1244 mutex_spin_exit(&sc->sc_intr_lock); 1245 return 0; 1246 1247 case SV_SRS_MODE: 1248 if (cp->type != AUDIO_MIXER_ENUM) 1249 return EINVAL; 1250 1251 mutex_spin_enter(&sc->sc_intr_lock); 1252 reg = sv_read_indirect(sc, SV_SRS_SPACE_CONTROL); 1253 if (cp->un.ord) { 1254 reg &= ~SV_SRS_SPACE_ONOFF; 1255 } else { 1256 reg |= SV_SRS_SPACE_ONOFF; 1257 } 1258 1259 sv_write_indirect(sc, SV_SRS_SPACE_CONTROL, reg); 1260 mutex_spin_exit(&sc->sc_intr_lock); 1261 return 0; 1262 } 1263 1264 return EINVAL; 1265} 1266 1267static int 1268sv_mixer_get_port(void *addr, mixer_ctrl_t *cp) 1269{ 1270 struct sv_softc *sc; 1271 int val, error; 1272 uint8_t reg; 1273 1274 sc = addr; 1275 error = 0; 1276 1277 mutex_spin_enter(&sc->sc_intr_lock); 1278 1279 if (cp->dev >= SV_FIRST_MIXER && 1280 cp->dev <= SV_LAST_MIXER) { 1281 int off = cp->dev - SV_FIRST_MIXER; 1282 int mute = (off % 2); 1283 int idx = off / 2; 1284 1285 off = cp->dev - SV_FIRST_MIXER; 1286 mute = (off % 2); 1287 idx = off / 2; 1288 if (mute) { 1289 if (cp->type != AUDIO_MIXER_ENUM) 1290 error = EINVAL; 1291 else { 1292 reg = sv_read_indirect(sc, ports[idx].l_port); 1293 cp->un.ord = ((reg & SV_MUTE_BIT) ? 1 : 0); 1294 } 1295 } else { 1296 if (cp->type != AUDIO_MIXER_VALUE || 1297 (cp->un.value.num_channels != 1 && 1298 cp->un.value.num_channels != 2) || 1299 ((ports[idx].r_port == 0 && 1300 cp->un.value.num_channels != 1) || 1301 (ports[idx].r_port != 0 && 1302 cp->un.value.num_channels != 2))) 1303 error = EINVAL; 1304 else { 1305 reg = sv_read_indirect(sc, ports[idx].l_port); 1306 reg &= ports[idx].mask; 1307 1308 val = AUDIO_MAX_GAIN - 1309 ((reg * AUDIO_MAX_GAIN) / ports[idx].mask); 1310 1311 if (ports[idx].r_port != 0) { 1312 cp->un.value.level 1313 [AUDIO_MIXER_LEVEL_LEFT] = val; 1314 1315 reg = sv_read_indirect(sc, 1316 ports[idx].r_port); 1317 reg &= ports[idx].mask; 1318 1319 val = AUDIO_MAX_GAIN - 1320 ((reg * AUDIO_MAX_GAIN) 1321 / ports[idx].mask); 1322 cp->un.value.level 1323 [AUDIO_MIXER_LEVEL_RIGHT] = val; 1324 } else 1325 cp->un.value.level 1326 [AUDIO_MIXER_LEVEL_MONO] = val; 1327 } 1328 } 1329 1330 return error; 1331 } 1332 1333 switch (cp->dev) { 1334 case SV_RECORD_SOURCE: 1335 if (cp->type != AUDIO_MIXER_ENUM) { 1336 error = EINVAL; 1337 break; 1338 } 1339 1340 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1341 cp->un.ord = ((reg & SV_REC_SOURCE_MASK) >> SV_REC_SOURCE_SHIFT); 1342 1343 break; 1344 1345 case SV_RECORD_GAIN: 1346 if (cp->type != AUDIO_MIXER_VALUE) { 1347 error = EINVAL; 1348 break; 1349 } 1350 if (cp->un.value.num_channels != 1) { 1351 error = EINVAL; 1352 break; 1353 } 1354 1355 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL) & SV_REC_GAIN_MASK; 1356 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 1357 (((unsigned int)reg) * AUDIO_MAX_GAIN) / SV_REC_GAIN_MASK; 1358 1359 break; 1360 1361 case SV_MIC_BOOST: 1362 if (cp->type != AUDIO_MIXER_ENUM) { 1363 error = EINVAL; 1364 break; 1365 } 1366 reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL); 1367 cp->un.ord = ((reg & SV_MIC_BOOST_BIT) ? 1 : 0); 1368 break; 1369 1370 case SV_SRS_MODE: 1371 if (cp->type != AUDIO_MIXER_ENUM) { 1372 error = EINVAL; 1373 break; 1374 } 1375 reg = sv_read_indirect(sc, SV_SRS_SPACE_CONTROL); 1376 cp->un.ord = ((reg & SV_SRS_SPACE_ONOFF) ? 0 : 1); 1377 break; 1378 default: 1379 error = EINVAL; 1380 break; 1381 } 1382 1383 mutex_spin_exit(&sc->sc_intr_lock); 1384 return error; 1385} 1386 1387static void 1388sv_init_mixer(struct sv_softc *sc) 1389{ 1390 mixer_ctrl_t cp; 1391 int i; 1392 1393 cp.type = AUDIO_MIXER_ENUM; 1394 cp.dev = SV_SRS_MODE; 1395 cp.un.ord = 0; 1396 1397 sv_mixer_set_port(sc, &cp); 1398 1399 for (i = 0; i < ARRAY_SIZE(ports); i++) { 1400 if (!strcmp(ports[i].audio, AudioNdac)) { 1401 cp.type = AUDIO_MIXER_ENUM; 1402 cp.dev = SV_FIRST_MIXER + i * SV_DEVICES_PER_PORT + 1; 1403 cp.un.ord = 0; 1404 sv_mixer_set_port(sc, &cp); 1405 break; 1406 } 1407 } 1408} 1409 1410static void * 1411sv_malloc(void *addr, int direction, size_t size) 1412{ 1413 struct sv_softc *sc; 1414 struct sv_dma *p; 1415 int error; 1416 1417 sc = addr; 1418 p = kmem_alloc(sizeof(*p), KM_SLEEP); 1419 if (p == NULL) 1420 return NULL; 1421 error = sv_allocmem(sc, size, 16, direction, p); 1422 if (error) { 1423 kmem_free(p, sizeof(*p)); 1424 return 0; 1425 } 1426 p->next = sc->sc_dmas; 1427 sc->sc_dmas = p; 1428 return KERNADDR(p); 1429} 1430 1431static void 1432sv_free(void *addr, void *ptr, size_t size) 1433{ 1434 struct sv_softc *sc; 1435 struct sv_dma **pp, *p; 1436 1437 sc = addr; 1438 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) { 1439 if (KERNADDR(p) == ptr) { 1440 sv_freemem(sc, p); 1441 *pp = p->next; 1442 kmem_free(p, sizeof(*p)); 1443 return; 1444 } 1445 } 1446} 1447 1448static size_t 1449sv_round_buffersize(void *addr, int direction, size_t size) 1450{ 1451 1452 return size; 1453} 1454 1455static paddr_t 1456sv_mappage(void *addr, void *mem, off_t off, int prot) 1457{ 1458 struct sv_softc *sc; 1459 struct sv_dma *p; 1460 1461 sc = addr; 1462 if (off < 0) 1463 return -1; 1464 for (p = sc->sc_dmas; p && KERNADDR(p) != mem; p = p->next) 1465 continue; 1466 if (p == NULL) 1467 return -1; 1468 return bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, 1469 off, prot, BUS_DMA_WAITOK); 1470} 1471 1472static int 1473sv_get_props(void *addr) 1474{ 1475 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1476} 1477 1478static void 1479sv_get_locks(void *addr, kmutex_t **intr, kmutex_t **thread) 1480{ 1481 struct sv_softc *sc; 1482 1483 sc = addr; 1484 *intr = &sc->sc_intr_lock; 1485 *thread = &sc->sc_lock; 1486} 1487