1 /* $NetBSD: auvia.c,v 1.12 2001/08/04 22:15:56 jdolecek Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tyler C. Sarna 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * VIA Technologies VT82C686A Southbridge Audio Driver 41 * 42 * Documentation links: 43 * 44 * ftp://ftp.alsa-project.org/pub/manuals/via/686a.pdf 45 * ftp://ftp.alsa-project.org/pub/manuals/general/ac97r21.pdf 46 * ftp://ftp.alsa-project.org/pub/manuals/ad/AD1881_0.pdf (example AC'97 codec) 47 */ 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/malloc.h> 52 #include <sys/device.h> 53 #include <sys/audioio.h> 54 55 #include <uvm/uvm_extern.h> 56 57 #include <dev/pci/pcidevs.h> 58 #include <dev/pci/pcivar.h> 59 60 #include <dev/audio_if.h> 61 #include <dev/mulaw.h> 62 #include <dev/auconv.h> 63 64 #include <dev/ic/ac97reg.h> 65 #include <dev/ic/ac97var.h> 66 67 #include <dev/pci/auviavar.h> 68 69 struct auvia_dma { 70 struct auvia_dma *next; 71 caddr_t addr; 72 size_t size; 73 bus_dmamap_t map; 74 bus_dma_segment_t seg; 75 }; 76 77 struct auvia_dma_op { 78 u_int32_t ptr; 79 u_int32_t flags; 80 #define AUVIA_DMAOP_EOL 0x80000000 81 #define AUVIA_DMAOP_FLAG 0x40000000 82 #define AUVIA_DMAOP_STOP 0x20000000 83 #define AUVIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF) 84 }; 85 86 /* rev. H and later seem to support only fixed rate 48 kHz */ 87 #define AUVIA_FIXED_RATE 48000 88 89 int auvia_match(struct device *, struct cfdata *, void *); 90 void auvia_attach(struct device *, struct device *, void *); 91 int auvia_open(void *, int); 92 void auvia_close(void *); 93 int auvia_query_encoding(void *addr, struct audio_encoding *fp); 94 int auvia_set_params(void *, int, int, struct audio_params *, 95 struct audio_params *); 96 int auvia_round_blocksize(void *, int); 97 int auvia_halt_output(void *); 98 int auvia_halt_input(void *); 99 int auvia_getdev(void *, struct audio_device *); 100 int auvia_set_port(void *, mixer_ctrl_t *); 101 int auvia_get_port(void *, mixer_ctrl_t *); 102 int auvia_query_devinfo(void *, mixer_devinfo_t *); 103 void * auvia_malloc(void *, int, size_t, int, int); 104 void auvia_free(void *, void *, int); 105 size_t auvia_round_buffersize(void *, int, size_t); 106 paddr_t auvia_mappage(void *, void *, off_t, int); 107 int auvia_get_props(void *); 108 int auvia_build_dma_ops(struct auvia_softc *, struct auvia_softc_chan *, 109 struct auvia_dma *, void *, void *, int); 110 int auvia_trigger_output(void *, void *, void *, int, void (*)(void *), 111 void *, struct audio_params *); 112 int auvia_trigger_input(void *, void *, void *, int, void (*)(void *), 113 void *, struct audio_params *); 114 115 int auvia_intr __P((void *)); 116 117 struct cfattach auvia_ca = { 118 sizeof (struct auvia_softc), auvia_match, auvia_attach 119 }; 120 121 #define AUVIA_PCICONF_JUNK 0x40 122 #define AUVIA_PCICONF_ENABLES 0x00FF0000 /* reg 42 mask */ 123 #define AUVIA_PCICONF_ACLINKENAB 0x00008000 /* ac link enab */ 124 #define AUVIA_PCICONF_ACNOTRST 0x00004000 /* ~(ac reset) */ 125 #define AUVIA_PCICONF_ACSYNC 0x00002000 /* ac sync */ 126 #define AUVIA_PCICONF_ACVSR 0x00000800 /* var. samp. rate */ 127 #define AUVIA_PCICONF_ACSGD 0x00000400 /* SGD enab */ 128 #define AUVIA_PCICONF_ACFM 0x00000200 /* FM enab */ 129 #define AUVIA_PCICONF_ACSB 0x00000100 /* SB enab */ 130 131 #define AUVIA_PLAY_STAT 0x00 132 #define AUVIA_RECORD_STAT 0x10 133 #define AUVIA_RPSTAT_INTR 0x03 134 #define AUVIA_PLAY_CONTROL 0x01 135 #define AUVIA_RECORD_CONTROL 0x11 136 #define AUVIA_RPCTRL_START 0x80 137 #define AUVIA_RPCTRL_TERMINATE 0x40 138 #define AUVIA_PLAY_MODE 0x02 139 #define AUVIA_RECORD_MODE 0x12 140 #define AUVIA_RPMODE_INTR_FLAG 0x01 141 #define AUVIA_RPMODE_INTR_EOL 0x02 142 #define AUVIA_RPMODE_STEREO 0x10 143 #define AUVIA_RPMODE_16BIT 0x20 144 #define AUVIA_RPMODE_AUTOSTART 0x80 145 #define AUVIA_PLAY_DMAOPS_BASE 0x04 146 #define AUVIA_RECORD_DMAOPS_BASE 0x14 147 148 #define AUVIA_CODEC_CTL 0x80 149 #define AUVIA_CODEC_READ 0x00800000 150 #define AUVIA_CODEC_BUSY 0x01000000 151 #define AUVIA_CODEC_PRIVALID 0x02000000 152 #define AUVIA_CODEC_INDEX(x) ((x)<<16) 153 154 #define TIMEOUT 50 155 156 struct audio_hw_if auvia_hw_if = { 157 auvia_open, 158 auvia_close, 159 NULL, /* drain */ 160 auvia_query_encoding, 161 auvia_set_params, 162 auvia_round_blocksize, 163 NULL, /* commit_settings */ 164 NULL, /* init_output */ 165 NULL, /* init_input */ 166 NULL, /* start_output */ 167 NULL, /* start_input */ 168 auvia_halt_output, 169 auvia_halt_input, 170 NULL, /* speaker_ctl */ 171 auvia_getdev, 172 NULL, /* setfd */ 173 auvia_set_port, 174 auvia_get_port, 175 auvia_query_devinfo, 176 auvia_malloc, 177 auvia_free, 178 auvia_round_buffersize, 179 auvia_mappage, 180 auvia_get_props, 181 auvia_trigger_output, 182 auvia_trigger_input, 183 }; 184 185 int auvia_attach_codec(void *, struct ac97_codec_if *); 186 int auvia_write_codec(void *, u_int8_t, u_int16_t); 187 int auvia_read_codec(void *, u_int8_t, u_int16_t *); 188 void auvia_reset_codec(void *); 189 int auvia_waitready_codec(struct auvia_softc *sc); 190 int auvia_waitvalid_codec(struct auvia_softc *sc); 191 192 193 int 194 auvia_match(struct device *parent, struct cfdata *match, void *aux) 195 { 196 struct pci_attach_args *pa = (struct pci_attach_args *) aux; 197 198 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_VIATECH) 199 return 0; 200 if (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_VIATECH_VT82C686A_AC97) 201 return 0; 202 203 return 1; 204 } 205 206 207 void 208 auvia_attach(struct device *parent, struct device *self, void *aux) 209 { 210 struct pci_attach_args *pa = aux; 211 struct auvia_softc *sc = (struct auvia_softc *) self; 212 const char *intrstr = NULL; 213 struct mixer_ctrl ctl; 214 pci_chipset_tag_t pc = pa->pa_pc; 215 pcitag_t pt = pa->pa_tag; 216 pci_intr_handle_t ih; 217 pcireg_t pr; 218 u_int16_t v; 219 int r, i; 220 221 r = PCI_REVISION(pa->pa_class); 222 sc->sc_revision[1] = '\0'; 223 if (r == 0x20) { 224 sc->sc_revision[0] = 'H'; 225 } else if ((r >= 0x10) && (r <= 0x14)) { 226 sc->sc_revision[0] = 'A' + (r - 0x10); 227 } else { 228 sprintf(sc->sc_revision, "0x%02X", r); 229 } 230 231 printf(": VIA VT82C686A AC'97 Audio (rev %s)\n", 232 sc->sc_revision); 233 234 if (pci_intr_map(pa, &ih)) { 235 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); 236 return; 237 } 238 intrstr = pci_intr_string(pc, ih); 239 240 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, auvia_intr, sc); 241 if (sc->sc_ih == NULL) { 242 printf("%s: couldn't establish interrupt",sc->sc_dev.dv_xname); 243 if (intrstr != NULL) 244 printf(" at %s", intrstr); 245 printf("\n"); 246 return; 247 } 248 249 sc->sc_dmat = pa->pa_dmat; 250 sc->sc_pc = pc; 251 sc->sc_pt = pt; 252 253 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 254 255 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, 256 &sc->sc_ioh, &sc->sc_ioaddr, &sc->sc_iosize)) { 257 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname); 258 return; 259 } 260 261 /* disable SBPro compat & others */ 262 pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK); 263 264 pr &= ~AUVIA_PCICONF_ENABLES; /* clear compat function enables */ 265 /* XXX what to do about MIDI, FM, joystick? */ 266 267 pr |= (AUVIA_PCICONF_ACLINKENAB | AUVIA_PCICONF_ACNOTRST 268 | AUVIA_PCICONF_ACVSR | AUVIA_PCICONF_ACSGD); 269 270 pr &= ~(AUVIA_PCICONF_ACFM | AUVIA_PCICONF_ACSB); 271 272 pci_conf_write(pc, pt, AUVIA_PCICONF_JUNK, pr); 273 274 sc->host_if.arg = sc; 275 sc->host_if.attach = auvia_attach_codec; 276 sc->host_if.read = auvia_read_codec; 277 sc->host_if.write = auvia_write_codec; 278 sc->host_if.reset = auvia_reset_codec; 279 280 if ((r = ac97_attach(&sc->host_if)) != 0) { 281 printf("%s: can't attach codec (error 0x%X)\n", 282 sc->sc_dev.dv_xname, r); 283 return; 284 } 285 286 /* 287 * Print a warning if the codec doesn't support hardware variable 288 * rate audio. 289 */ 290 if (auvia_read_codec(sc, AC97_REG_EXTENDED_ID, &v) 291 || !(v & AC97_CODEC_DOES_VRA)) { 292 printf("%s: warning: codec doesn't support hardware AC'97 2.0 Variable Rate Audio\n", 293 sc->sc_dev.dv_xname); 294 sc->sc_fixed_rate = AUVIA_FIXED_RATE; /* XXX wrong value */ 295 } else { 296 /* enable VRA */ 297 auvia_write_codec(sc, AC97_REG_EXTENDED_STATUS, 298 AC97_ENAB_VRA | AC97_ENAB_MICVRA); 299 sc->sc_fixed_rate = 0; 300 } 301 302 /* disable mutes */ 303 for (i = 0; i < 4; i++) { 304 static struct { 305 char *class, *device; 306 } d[] = { 307 { AudioCoutputs, AudioNmaster}, 308 { AudioCinputs, AudioNdac}, 309 { AudioCinputs, AudioNcd}, 310 { AudioCinputs, AudioNline}, 311 { AudioCrecord, AudioNvolume}, 312 }; 313 314 ctl.type = AUDIO_MIXER_ENUM; 315 ctl.un.ord = 0; 316 317 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, 318 d[i].class, d[i].device, AudioNmute); 319 auvia_set_port(sc, &ctl); 320 } 321 322 /* set a reasonable default volume */ 323 324 ctl.type = AUDIO_MIXER_VALUE; 325 ctl.un.value.num_channels = 2; 326 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \ 327 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 199; 328 329 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, 330 AudioCoutputs, AudioNmaster, NULL); 331 auvia_set_port(sc, &ctl); 332 333 audio_attach_mi(&auvia_hw_if, sc, &sc->sc_dev); 334 } 335 336 337 int 338 auvia_attach_codec(void *addr, struct ac97_codec_if *cif) 339 { 340 struct auvia_softc *sc = addr; 341 342 sc->codec_if = cif; 343 344 return 0; 345 } 346 347 348 void 349 auvia_reset_codec(void *addr) 350 { 351 #ifdef notyet /* XXX seems to make codec become unready... ??? */ 352 struct auvia_softc *sc = addr; 353 pcireg_t r; 354 355 /* perform a codec cold reset */ 356 357 r = pci_conf_read(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK); 358 359 r &= ~AUVIA_PCICONF_ACNOTRST; /* enable RESET (active low) */ 360 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r); 361 delay(2); 362 363 r |= AUVIA_PCICONF_ACNOTRST; /* disable RESET (inactive high) */ 364 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r); 365 delay(200); 366 367 auvia_waitready_codec(sc); 368 #endif 369 } 370 371 372 int 373 auvia_waitready_codec(struct auvia_softc *sc) 374 { 375 int i; 376 377 /* poll until codec not busy */ 378 for (i = 0; (i < TIMEOUT) && (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 379 AUVIA_CODEC_CTL) & AUVIA_CODEC_BUSY); i++) 380 delay(1); 381 if (i >= TIMEOUT) { 382 printf("%s: codec busy\n", sc->sc_dev.dv_xname); 383 return 1; 384 } 385 386 return 0; 387 } 388 389 390 int 391 auvia_waitvalid_codec(struct auvia_softc *sc) 392 { 393 int i; 394 395 /* poll until codec valid */ 396 for (i = 0; (i < TIMEOUT) && !(bus_space_read_4(sc->sc_iot, sc->sc_ioh, 397 AUVIA_CODEC_CTL) & AUVIA_CODEC_PRIVALID); i++) 398 delay(1); 399 if (i >= TIMEOUT) { 400 printf("%s: codec invalid\n", sc->sc_dev.dv_xname); 401 return 1; 402 } 403 404 return 0; 405 } 406 407 408 int 409 auvia_write_codec(void *addr, u_int8_t reg, u_int16_t val) 410 { 411 struct auvia_softc *sc = addr; 412 413 if (auvia_waitready_codec(sc)) 414 return 1; 415 416 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL, 417 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_INDEX(reg) | val); 418 419 return 0; 420 } 421 422 423 int 424 auvia_read_codec(void *addr, u_int8_t reg, u_int16_t *val) 425 { 426 struct auvia_softc *sc = addr; 427 428 if (auvia_waitready_codec(sc)) 429 return 1; 430 431 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL, 432 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_READ | AUVIA_CODEC_INDEX(reg)); 433 434 if (auvia_waitready_codec(sc)) 435 return 1; 436 437 if (auvia_waitvalid_codec(sc)) 438 return 1; 439 440 *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL); 441 442 return 0; 443 } 444 445 446 int 447 auvia_open(void *addr, int flags) 448 { 449 return 0; 450 } 451 452 453 void 454 auvia_close(void *addr) 455 { 456 struct auvia_softc *sc = addr; 457 458 auvia_halt_output(sc); 459 auvia_halt_input(sc); 460 461 sc->sc_play.sc_intr = NULL; 462 sc->sc_record.sc_intr = NULL; 463 } 464 465 466 int 467 auvia_query_encoding(void *addr, struct audio_encoding *fp) 468 { 469 switch (fp->index) { 470 case 0: 471 strcpy(fp->name, AudioEulinear); 472 fp->encoding = AUDIO_ENCODING_ULINEAR; 473 fp->precision = 8; 474 fp->flags = 0; 475 return (0); 476 case 1: 477 strcpy(fp->name, AudioEmulaw); 478 fp->encoding = AUDIO_ENCODING_ULAW; 479 fp->precision = 8; 480 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 481 return (0); 482 case 2: 483 strcpy(fp->name, AudioEalaw); 484 fp->encoding = AUDIO_ENCODING_ALAW; 485 fp->precision = 8; 486 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 487 return (0); 488 case 3: 489 strcpy(fp->name, AudioEslinear); 490 fp->encoding = AUDIO_ENCODING_SLINEAR; 491 fp->precision = 8; 492 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 493 return (0); 494 case 4: 495 strcpy(fp->name, AudioEslinear_le); 496 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 497 fp->precision = 16; 498 fp->flags = 0; 499 return (0); 500 case 5: 501 strcpy(fp->name, AudioEulinear_le); 502 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 503 fp->precision = 16; 504 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 505 return (0); 506 case 6: 507 strcpy(fp->name, AudioEslinear_be); 508 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 509 fp->precision = 16; 510 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 511 return (0); 512 case 7: 513 strcpy(fp->name, AudioEulinear_be); 514 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 515 fp->precision = 16; 516 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 517 return (0); 518 default: 519 return (EINVAL); 520 } 521 } 522 523 524 int 525 auvia_set_params(void *addr, int setmode, int usemode, 526 struct audio_params *play, struct audio_params *rec) 527 { 528 struct auvia_softc *sc = addr; 529 struct audio_params *p; 530 u_int16_t regval; 531 int reg, mode; 532 533 /* for mode in (RECORD, PLAY) */ 534 for (mode = AUMODE_RECORD; mode != -1; 535 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 536 if ((setmode & mode) == 0) 537 continue; 538 539 p = mode == AUMODE_PLAY ? play : rec; 540 541 if (p->sample_rate < 4000 || p->sample_rate > 48000 || 542 (p->precision != 8 && p->precision != 16) || 543 (p->channels != 1 && p->channels != 2)) 544 return (EINVAL); 545 546 reg = mode == AUMODE_PLAY ? 547 AC97_REG_PCM_FRONT_DAC_RATE : AC97_REG_PCM_LR_ADC_RATE; 548 549 if (!sc->sc_fixed_rate) { 550 auvia_write_codec(sc, reg, (u_int16_t) p->sample_rate); 551 auvia_read_codec(sc, reg, ®val); 552 p->sample_rate = regval; 553 } else 554 p->sample_rate = sc->sc_fixed_rate; 555 556 p->factor = 1; 557 p->sw_code = 0; 558 switch (p->encoding) { 559 case AUDIO_ENCODING_SLINEAR_BE: 560 if (p->precision == 16) 561 p->sw_code = swap_bytes; 562 else 563 p->sw_code = change_sign8; 564 break; 565 case AUDIO_ENCODING_SLINEAR_LE: 566 if (p->precision != 16) 567 p->sw_code = change_sign8; 568 break; 569 case AUDIO_ENCODING_ULINEAR_BE: 570 if (p->precision == 16) { 571 if (mode == AUMODE_PLAY) 572 p->sw_code = swap_bytes_change_sign16_le; 573 else 574 p->sw_code = change_sign16_swap_bytes_le; 575 } 576 break; 577 case AUDIO_ENCODING_ULINEAR_LE: 578 if (p->precision == 16) 579 p->sw_code = change_sign16_le; 580 break; 581 case AUDIO_ENCODING_ULAW: 582 if (mode == AUMODE_PLAY) { 583 p->factor = 2; 584 p->sw_code = mulaw_to_slinear16_le; 585 } else 586 p->sw_code = ulinear8_to_mulaw; 587 break; 588 case AUDIO_ENCODING_ALAW: 589 if (mode == AUMODE_PLAY) { 590 p->factor = 2; 591 p->sw_code = alaw_to_slinear16_le; 592 } else 593 p->sw_code = ulinear8_to_alaw; 594 break; 595 default: 596 return (EINVAL); 597 } 598 599 regval = (p->channels == 2 ? AUVIA_RPMODE_STEREO : 0) 600 | (p->precision * p->factor == 16 ? 601 AUVIA_RPMODE_16BIT : 0) 602 | AUVIA_RPMODE_INTR_FLAG | AUVIA_RPMODE_INTR_EOL 603 | AUVIA_RPMODE_AUTOSTART; 604 605 if (mode == AUMODE_PLAY) { 606 sc->sc_play.sc_reg = regval; 607 } else { 608 sc->sc_record.sc_reg = regval; 609 } 610 } 611 612 return 0; 613 } 614 615 616 int 617 auvia_round_blocksize(void *addr, int blk) 618 { 619 return (blk & -32); 620 } 621 622 623 int 624 auvia_halt_output(void *addr) 625 { 626 struct auvia_softc *sc = addr; 627 628 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_CONTROL, 629 AUVIA_RPCTRL_TERMINATE); 630 631 return 0; 632 } 633 634 635 int 636 auvia_halt_input(void *addr) 637 { 638 struct auvia_softc *sc = addr; 639 640 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_CONTROL, 641 AUVIA_RPCTRL_TERMINATE); 642 643 return 0; 644 } 645 646 647 int 648 auvia_getdev(void *addr, struct audio_device *retp) 649 { 650 struct auvia_softc *sc = addr; 651 652 if (retp) { 653 strncpy(retp->name, "VIA VT82C686A", sizeof(retp->name)); 654 strncpy(retp->version, sc->sc_revision, sizeof(retp->version)); 655 strncpy(retp->config, "auvia", sizeof(retp->config)); 656 } 657 658 return 0; 659 } 660 661 662 int 663 auvia_set_port(void *addr, mixer_ctrl_t *cp) 664 { 665 struct auvia_softc *sc = addr; 666 667 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp)); 668 } 669 670 671 int 672 auvia_get_port(void *addr, mixer_ctrl_t *cp) 673 { 674 struct auvia_softc *sc = addr; 675 676 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp)); 677 } 678 679 680 int 681 auvia_query_devinfo(void *addr, mixer_devinfo_t *dip) 682 { 683 struct auvia_softc *sc = addr; 684 685 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip)); 686 } 687 688 689 void * 690 auvia_malloc(void *addr, int direction, size_t size, int pool, int flags) 691 { 692 struct auvia_softc *sc = addr; 693 struct auvia_dma *p; 694 int error; 695 int rseg; 696 697 p = malloc(sizeof(*p), pool, flags); 698 if (!p) 699 return 0; 700 701 p->size = size; 702 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &p->seg, 703 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 704 printf("%s: unable to allocate dma, error = %d\n", 705 sc->sc_dev.dv_xname, error); 706 goto fail_alloc; 707 } 708 709 if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr, 710 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 711 printf("%s: unable to map dma, error = %d\n", 712 sc->sc_dev.dv_xname, error); 713 goto fail_map; 714 } 715 716 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 717 BUS_DMA_NOWAIT, &p->map)) != 0) { 718 printf("%s: unable to create dma map, error = %d\n", 719 sc->sc_dev.dv_xname, error); 720 goto fail_create; 721 } 722 723 if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL, 724 BUS_DMA_NOWAIT)) != 0) { 725 printf("%s: unable to load dma map, error = %d\n", 726 sc->sc_dev.dv_xname, error); 727 goto fail_load; 728 } 729 730 p->next = sc->sc_dmas; 731 sc->sc_dmas = p; 732 733 return p->addr; 734 735 736 fail_load: 737 bus_dmamap_destroy(sc->sc_dmat, p->map); 738 fail_create: 739 bus_dmamem_unmap(sc->sc_dmat, p->addr, size); 740 fail_map: 741 bus_dmamem_free(sc->sc_dmat, &p->seg, 1); 742 fail_alloc: 743 free(p, pool); 744 return 0; 745 } 746 747 748 void 749 auvia_free(void *addr, void *ptr, int pool) 750 { 751 struct auvia_softc *sc = addr; 752 struct auvia_dma **pp, *p; 753 754 for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next) 755 if (p->addr == ptr) { 756 bus_dmamap_unload(sc->sc_dmat, p->map); 757 bus_dmamap_destroy(sc->sc_dmat, p->map); 758 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); 759 bus_dmamem_free(sc->sc_dmat, &p->seg, 1); 760 761 *pp = p->next; 762 free(p, pool); 763 return; 764 } 765 766 panic("auvia_free: trying to free unallocated memory"); 767 } 768 769 770 size_t 771 auvia_round_buffersize(void *addr, int direction, size_t size) 772 { 773 return size; 774 } 775 776 777 paddr_t 778 auvia_mappage(void *addr, void *mem, off_t off, int prot) 779 { 780 struct auvia_softc *sc = addr; 781 struct auvia_dma *p; 782 783 if (off < 0) 784 return -1; 785 786 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next) 787 ; 788 789 if (!p) 790 return -1; 791 792 return bus_dmamem_mmap(sc->sc_dmat, &p->seg, 1, off, prot, 793 BUS_DMA_WAITOK); 794 } 795 796 797 int 798 auvia_get_props(void *addr) 799 { 800 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT 801 | AUDIO_PROP_FULLDUPLEX; 802 } 803 804 805 int 806 auvia_build_dma_ops(struct auvia_softc *sc, struct auvia_softc_chan *ch, 807 struct auvia_dma *p, void *start, void *end, int blksize) 808 { 809 struct auvia_dma_op *op; 810 struct auvia_dma *dp; 811 bus_addr_t s, e; 812 size_t l; 813 int segs; 814 815 s = p->map->dm_segs[0].ds_addr; 816 l = ((char *)end - (char *)start); 817 e = s + l; 818 segs = (l + blksize - 1) / blksize; 819 820 if (segs > (ch->sc_dma_op_count)) { 821 /* if old list was too small, free it */ 822 if (ch->sc_dma_ops) { 823 auvia_free(sc, ch->sc_dma_ops, M_DEVBUF); 824 } 825 826 ch->sc_dma_ops = auvia_malloc(sc, 0, 827 sizeof(struct auvia_dma_op) * segs, M_DEVBUF, M_WAITOK); 828 829 if (ch->sc_dma_ops == NULL) { 830 printf("%s: couldn't build dmaops\n", sc->sc_dev.dv_xname); 831 return 1; 832 } 833 834 for (dp = sc->sc_dmas; 835 dp && dp->addr != (void *)(ch->sc_dma_ops); 836 dp = dp->next) 837 ; 838 839 if (!dp) 840 panic("%s: build_dma_ops: where'd my memory go??? " 841 "address (%p)\n", sc->sc_dev.dv_xname, 842 ch->sc_dma_ops); 843 844 ch->sc_dma_op_count = segs; 845 ch->sc_dma_ops_dma = dp; 846 } 847 848 dp = ch->sc_dma_ops_dma; 849 op = ch->sc_dma_ops; 850 851 while (l) { 852 op->ptr = s; 853 l = l - blksize; 854 if (!l) { 855 /* if last block */ 856 op->flags = AUVIA_DMAOP_EOL | blksize; 857 } else { 858 op->flags = AUVIA_DMAOP_FLAG | blksize; 859 } 860 s += blksize; 861 op++; 862 } 863 864 return 0; 865 } 866 867 868 int 869 auvia_trigger_output(void *addr, void *start, void *end, 870 int blksize, void (*intr)(void *), void *arg, 871 struct audio_params *param) 872 { 873 struct auvia_softc *sc = addr; 874 struct auvia_softc_chan *ch = &(sc->sc_play); 875 struct auvia_dma *p; 876 877 for (p = sc->sc_dmas; p && p->addr != start; p = p->next) 878 ; 879 880 if (!p) 881 panic("auvia_trigger_output: request with bad start " 882 "address (%p)\n", start); 883 884 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize)) { 885 return 1; 886 } 887 888 ch->sc_intr = intr; 889 ch->sc_arg = arg; 890 891 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_DMAOPS_BASE, 892 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr); 893 894 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_MODE, 895 ch->sc_reg); 896 897 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_CONTROL, 898 AUVIA_RPCTRL_START); 899 900 return 0; 901 } 902 903 904 int 905 auvia_trigger_input(void *addr, void *start, void *end, 906 int blksize, void (*intr)(void *), void *arg, 907 struct audio_params *param) 908 { 909 struct auvia_softc *sc = addr; 910 struct auvia_softc_chan *ch = &(sc->sc_record); 911 struct auvia_dma *p; 912 913 for (p = sc->sc_dmas; p && p->addr != start; p = p->next) 914 ; 915 916 if (!p) 917 panic("auvia_trigger_input: request with bad start " 918 "address (%p)\n", start); 919 920 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize)) { 921 return 1; 922 } 923 924 ch->sc_intr = intr; 925 ch->sc_arg = arg; 926 927 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_DMAOPS_BASE, 928 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr); 929 930 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_MODE, 931 ch->sc_reg); 932 933 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_CONTROL, 934 AUVIA_RPCTRL_START); 935 936 return 0; 937 } 938 939 940 int 941 auvia_intr(void *arg) 942 { 943 struct auvia_softc *sc = arg; 944 u_int8_t r; 945 946 r = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_STAT); 947 if (r & AUVIA_RPSTAT_INTR) { 948 if (sc->sc_record.sc_intr) 949 sc->sc_record.sc_intr(sc->sc_record.sc_arg); 950 951 /* clear interrupts */ 952 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_STAT, 953 AUVIA_RPSTAT_INTR); 954 } 955 r = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_STAT); 956 if (r & AUVIA_RPSTAT_INTR) { 957 if (sc->sc_play.sc_intr) 958 sc->sc_play.sc_intr(sc->sc_play.sc_arg); 959 960 /* clear interrupts */ 961 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_STAT, 962 AUVIA_RPSTAT_INTR); 963 } 964 965 return 1; 966 } 967