1 /* $OpenBSD: auvia.c,v 1.53 2014/07/12 18:48:51 tedu Exp $ */ 2 /* $NetBSD: auvia.c,v 1.28 2002/11/04 16:38:49 kent Exp $ */ 3 4 /*- 5 * Copyright (c) 2000 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Tyler C. Sarna 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 * VIA Technologies VT82C686A Southbridge Audio Driver 35 * 36 * Documentation links: 37 * 38 * ftp://ftp.alsa-project.org/pub/manuals/via/686a.pdf 39 */ 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/malloc.h> 44 #include <sys/device.h> 45 #include <sys/audioio.h> 46 47 #include <dev/pci/pcidevs.h> 48 #include <dev/pci/pcivar.h> 49 50 #include <dev/audio_if.h> 51 #include <dev/mulaw.h> 52 #include <dev/auconv.h> 53 54 #include <dev/ic/ac97.h> 55 56 #include <dev/pci/auviavar.h> 57 58 struct auvia_dma { 59 struct auvia_dma *next; 60 caddr_t addr; 61 size_t size; 62 bus_dmamap_t map; 63 bus_dma_segment_t seg; 64 }; 65 66 struct auvia_dma_op { 67 u_int32_t ptr; 68 u_int32_t flags; 69 #define AUVIA_DMAOP_EOL 0x80000000 70 #define AUVIA_DMAOP_FLAG 0x40000000 71 #define AUVIA_DMAOP_STOP 0x20000000 72 #define AUVIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF) 73 }; 74 75 int auvia_match(struct device *, void *, void *); 76 void auvia_attach(struct device *, struct device *, void *); 77 int auvia_open(void *, int); 78 void auvia_close(void *); 79 int auvia_query_encoding(void *, struct audio_encoding *); 80 void auvia_set_params_sub(struct auvia_softc *, struct auvia_softc_chan *, 81 struct audio_params *); 82 int auvia_set_params(void *, int, int, struct audio_params *, 83 struct audio_params *); 84 void auvia_get_default_params(void *, int, struct audio_params *); 85 int auvia_round_blocksize(void *, int); 86 int auvia_halt_output(void *); 87 int auvia_halt_input(void *); 88 int auvia_getdev(void *, struct audio_device *); 89 int auvia_set_port(void *, mixer_ctrl_t *); 90 int auvia_get_port(void *, mixer_ctrl_t *); 91 int auvia_query_devinfo(void *, mixer_devinfo_t *); 92 void * auvia_malloc(void *, int, size_t, int, int); 93 void auvia_free(void *, void *, int); 94 size_t auvia_round_buffersize(void *, int, size_t); 95 paddr_t auvia_mappage(void *, void *, off_t, int); 96 int auvia_get_props(void *); 97 int auvia_build_dma_ops(struct auvia_softc *, struct auvia_softc_chan *, 98 struct auvia_dma *, void *, void *, int); 99 int auvia_trigger_output(void *, void *, void *, int, void (*)(void *), 100 void *, struct audio_params *); 101 int auvia_trigger_input(void *, void *, void *, int, void (*)(void *), 102 void *, struct audio_params *); 103 104 int auvia_intr(void *); 105 106 int auvia_activate(struct device *, int); 107 108 struct cfdriver auvia_cd = { 109 NULL, "auvia", DV_DULL 110 }; 111 112 struct cfattach auvia_ca = { 113 sizeof (struct auvia_softc), auvia_match, auvia_attach, 114 NULL, auvia_activate 115 }; 116 117 #define AUVIA_PCICONF_JUNK 0x40 118 #define AUVIA_PCICONF_ENABLES 0x00FF0000 /* reg 42 mask */ 119 #define AUVIA_PCICONF_ACLINKENAB 0x00008000 /* ac link enab */ 120 #define AUVIA_PCICONF_ACNOTRST 0x00004000 /* ~(ac reset) */ 121 #define AUVIA_PCICONF_ACSYNC 0x00002000 /* ac sync */ 122 #define AUVIA_PCICONF_ACVSR 0x00000800 /* var. samp. rate */ 123 #define AUVIA_PCICONF_ACSGD 0x00000400 /* SGD enab */ 124 #define AUVIA_PCICONF_ACFM 0x00000200 /* FM enab */ 125 #define AUVIA_PCICONF_ACSB 0x00000100 /* SB enab */ 126 #define AUVIA_PCICONF_PRIVALID 0x00000001 /* primary codec rdy */ 127 128 #define AUVIA_PLAY_BASE 0x00 129 #define AUVIA_RECORD_BASE 0x10 130 131 /* *_RP_* are offsets from AUVIA_PLAY_BASE or AUVIA_RECORD_BASE */ 132 #define AUVIA_RP_STAT 0x00 133 #define AUVIA_RPSTAT_INTR 0x03 134 #define AUVIA_RP_CONTROL 0x01 135 #define AUVIA_RPCTRL_START 0x80 136 #define AUVIA_RPCTRL_TERMINATE 0x40 137 #define AUVIA_RPCTRL_AUTOSTART 0x20 138 /* The following are 8233 specific */ 139 #define AUVIA_RPCTRL_STOP 0x04 140 #define AUVIA_RPCTRL_EOL 0x02 141 #define AUVIA_RPCTRL_FLAG 0x01 142 #define AUVIA_RP_MODE 0x02 /* 82c686 specific */ 143 #define AUVIA_RPMODE_INTR_FLAG 0x01 144 #define AUVIA_RPMODE_INTR_EOL 0x02 145 #define AUVIA_RPMODE_STEREO 0x10 146 #define AUVIA_RPMODE_16BIT 0x20 147 #define AUVIA_RPMODE_AUTOSTART 0x80 148 #define AUVIA_RP_DMAOPS_BASE 0x04 149 150 #define VIA8233_RP_DXS_LVOL 0x02 151 #define VIA8233_RP_DXS_RVOL 0x03 152 #define VIA8233_RP_RATEFMT 0x08 153 #define VIA8233_RATEFMT_48K 0xfffff 154 #define VIA8233_RATEFMT_STEREO 0x00100000 155 #define VIA8233_RATEFMT_16BIT 0x00200000 156 157 #define VIA_RP_DMAOPS_COUNT 0x0c 158 159 #define VIA8233_MP_BASE 0x40 160 /* STAT, CONTROL, DMAOPS_BASE, DMAOPS_COUNT are valid */ 161 #define VIA8233_OFF_MP_FORMAT 0x02 162 #define VIA8233_MP_FORMAT_8BIT 0x00 163 #define VIA8233_MP_FORMAT_16BIT 0x80 164 #define VIA8233_MP_FORMAT_CHANNLE_MASK 0x70 /* 1, 2, 4, 6 */ 165 #define VIA8233_OFF_MP_SCRATCH 0x03 166 #define VIA8233_OFF_MP_STOP 0x08 167 168 #define VIA8233_WR_BASE 0x60 169 170 #define AUVIA_CODEC_CTL 0x80 171 #define AUVIA_CODEC_READ 0x00800000 172 #define AUVIA_CODEC_BUSY 0x01000000 173 #define AUVIA_CODEC_PRIVALID 0x02000000 174 #define AUVIA_CODEC_INDEX(x) ((x)<<16) 175 176 #define CH_WRITE1(sc, ch, off, v) \ 177 bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off), v) 178 #define CH_WRITE4(sc, ch, off, v) \ 179 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off), v) 180 #define CH_READ1(sc, ch, off) \ 181 bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off)) 182 #define CH_READ4(sc, ch, off) \ 183 bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off)) 184 185 #define TIMEOUT 50 186 187 struct audio_hw_if auvia_hw_if = { 188 auvia_open, 189 auvia_close, 190 NULL, /* drain */ 191 auvia_query_encoding, 192 auvia_set_params, 193 auvia_round_blocksize, 194 NULL, /* commit_settings */ 195 NULL, /* init_output */ 196 NULL, /* init_input */ 197 NULL, /* start_output */ 198 NULL, /* start_input */ 199 auvia_halt_output, 200 auvia_halt_input, 201 NULL, /* speaker_ctl */ 202 auvia_getdev, 203 NULL, /* setfd */ 204 auvia_set_port, 205 auvia_get_port, 206 auvia_query_devinfo, 207 auvia_malloc, 208 auvia_free, 209 auvia_round_buffersize, 210 auvia_mappage, 211 auvia_get_props, 212 auvia_trigger_output, 213 auvia_trigger_input, 214 auvia_get_default_params 215 }; 216 217 int auvia_attach_codec(void *, struct ac97_codec_if *); 218 int auvia_write_codec(void *, u_int8_t, u_int16_t); 219 int auvia_read_codec(void *, u_int8_t, u_int16_t *); 220 void auvia_reset_codec(void *); 221 int auvia_waitready_codec(struct auvia_softc *sc); 222 int auvia_waitvalid_codec(struct auvia_softc *sc); 223 void auvia_spdif_event(void *, int); 224 225 int auvia_resume(struct auvia_softc *); 226 227 const struct pci_matchid auvia_devices[] = { 228 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_AC97 }, 229 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8233_AC97 }, 230 }; 231 232 int 233 auvia_match(struct device *parent, void *match, void *aux) 234 { 235 return (pci_matchbyid((struct pci_attach_args *)aux, auvia_devices, 236 nitems(auvia_devices))); 237 } 238 239 int 240 auvia_activate(struct device *self, int act) 241 { 242 struct auvia_softc *sc = (struct auvia_softc *)self; 243 int rv = 0; 244 245 switch (act) { 246 case DVACT_RESUME: 247 auvia_resume(sc); 248 rv = config_activate_children(self, act); 249 break; 250 default: 251 rv = config_activate_children(self, act); 252 break; 253 } 254 return (rv); 255 } 256 257 258 void 259 auvia_attach(struct device *parent, struct device *self, void *aux) 260 { 261 struct pci_attach_args *pa = aux; 262 struct auvia_softc *sc = (struct auvia_softc *) self; 263 const char *intrstr = NULL; 264 struct mixer_ctrl ctl; 265 pci_chipset_tag_t pc = pa->pa_pc; 266 pcitag_t pt = pa->pa_tag; 267 pci_intr_handle_t ih; 268 bus_size_t iosize; 269 pcireg_t pr; 270 int r, i; 271 272 sc->sc_play.sc_base = AUVIA_PLAY_BASE; 273 sc->sc_record.sc_base = AUVIA_RECORD_BASE; 274 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT8233_AC97) { 275 sc->sc_flags |= AUVIA_FLAGS_VT8233; 276 sc->sc_play.sc_base = VIA8233_MP_BASE; 277 sc->sc_record.sc_base = VIA8233_WR_BASE; 278 } 279 280 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, 281 &sc->sc_ioh, NULL, &iosize, 0)) { 282 printf(": can't map i/o space\n"); 283 return; 284 } 285 286 sc->sc_dmat = pa->pa_dmat; 287 sc->sc_pc = pc; 288 sc->sc_pt = pt; 289 290 if (pci_intr_map(pa, &ih)) { 291 printf(": couldn't map interrupt\n"); 292 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 293 return; 294 } 295 intrstr = pci_intr_string(pc, ih); 296 297 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE, 298 auvia_intr, sc, sc->sc_dev.dv_xname); 299 if (sc->sc_ih == NULL) { 300 printf(": couldn't establish interrupt"); 301 if (intrstr != NULL) 302 printf(" at %s", intrstr); 303 printf("\n"); 304 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 305 return; 306 } 307 308 printf(": %s\n", intrstr); 309 310 /* disable SBPro compat & others */ 311 pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK); 312 313 pr &= ~AUVIA_PCICONF_ENABLES; /* clear compat function enables */ 314 /* XXX what to do about MIDI, FM, joystick? */ 315 316 pr |= (AUVIA_PCICONF_ACLINKENAB | AUVIA_PCICONF_ACNOTRST | 317 AUVIA_PCICONF_ACVSR | AUVIA_PCICONF_ACSGD); 318 319 pr &= ~(AUVIA_PCICONF_ACFM | AUVIA_PCICONF_ACSB); 320 321 pci_conf_write(pc, pt, AUVIA_PCICONF_JUNK, pr); 322 sc->sc_pci_junk = pr; 323 324 sc->host_if.arg = sc; 325 sc->host_if.attach = auvia_attach_codec; 326 sc->host_if.read = auvia_read_codec; 327 sc->host_if.write = auvia_write_codec; 328 sc->host_if.reset = auvia_reset_codec; 329 sc->host_if.spdif_event = auvia_spdif_event; 330 331 if ((r = ac97_attach(&sc->host_if)) != 0) { 332 printf("%s: can't attach codec (error 0x%X)\n", 333 sc->sc_dev.dv_xname, r); 334 pci_intr_disestablish(pc, sc->sc_ih); 335 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 336 return; 337 } 338 339 /* disable mutes */ 340 for (i = 0; i < 4; i++) { 341 static struct { 342 char *class, *device; 343 } d[] = { 344 { AudioCoutputs, AudioNmaster}, 345 { AudioCinputs, AudioNdac}, 346 { AudioCinputs, AudioNcd}, 347 { AudioCrecord, AudioNvolume}, 348 }; 349 350 ctl.type = AUDIO_MIXER_ENUM; 351 ctl.un.ord = 0; 352 353 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, 354 d[i].class, d[i].device, AudioNmute); 355 auvia_set_port(sc, &ctl); 356 } 357 358 /* set a reasonable default volume */ 359 360 ctl.type = AUDIO_MIXER_VALUE; 361 ctl.un.value.num_channels = 2; 362 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \ 363 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 199; 364 365 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, 366 AudioCoutputs, AudioNmaster, NULL); 367 auvia_set_port(sc, &ctl); 368 369 audio_attach_mi(&auvia_hw_if, sc, &sc->sc_dev); 370 sc->codec_if->vtbl->unlock(sc->codec_if); 371 } 372 373 374 int 375 auvia_attach_codec(void *addr, struct ac97_codec_if *cif) 376 { 377 struct auvia_softc *sc = addr; 378 379 sc->codec_if = cif; 380 381 return 0; 382 } 383 384 385 void 386 auvia_reset_codec(void *addr) 387 { 388 int i; 389 struct auvia_softc *sc = addr; 390 pcireg_t r; 391 392 /* perform a codec cold reset */ 393 394 r = pci_conf_read(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK); 395 396 r &= ~AUVIA_PCICONF_ACNOTRST; /* enable RESET (active low) */ 397 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r); 398 delay(2); 399 400 r |= AUVIA_PCICONF_ACNOTRST; /* disable RESET (inactive high) */ 401 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r); 402 delay(200); 403 404 for (i = 500000; i != 0 && !(pci_conf_read(sc->sc_pc, sc->sc_pt, 405 AUVIA_PCICONF_JUNK) & AUVIA_PCICONF_PRIVALID); i--) 406 DELAY(1); 407 if (i == 0) 408 printf("%s: codec reset timed out\n", sc->sc_dev.dv_xname); 409 } 410 411 412 int 413 auvia_waitready_codec(struct auvia_softc *sc) 414 { 415 int i; 416 417 /* poll until codec not busy */ 418 for (i = 0; (i < TIMEOUT) && (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 419 AUVIA_CODEC_CTL) & AUVIA_CODEC_BUSY); i++) 420 delay(1); 421 422 if (i >= TIMEOUT) { 423 printf("%s: codec busy\n", sc->sc_dev.dv_xname); 424 return 1; 425 } 426 427 return 0; 428 } 429 430 431 int 432 auvia_waitvalid_codec(struct auvia_softc *sc) 433 { 434 int i; 435 436 /* poll until codec valid */ 437 for (i = 0; (i < TIMEOUT) && !(bus_space_read_4(sc->sc_iot, sc->sc_ioh, 438 AUVIA_CODEC_CTL) & AUVIA_CODEC_PRIVALID); i++) 439 delay(1); 440 441 if (i >= TIMEOUT) { 442 printf("%s: codec invalid\n", sc->sc_dev.dv_xname); 443 return 1; 444 } 445 446 return 0; 447 } 448 449 450 int 451 auvia_write_codec(void *addr, u_int8_t reg, u_int16_t val) 452 { 453 struct auvia_softc *sc = addr; 454 455 if (auvia_waitready_codec(sc)) 456 return 1; 457 458 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL, 459 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_INDEX(reg) | val); 460 461 return 0; 462 } 463 464 465 int 466 auvia_read_codec(void *addr, u_int8_t reg, u_int16_t *val) 467 { 468 struct auvia_softc *sc = addr; 469 470 if (auvia_waitready_codec(sc)) 471 return 1; 472 473 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL, 474 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_READ | AUVIA_CODEC_INDEX(reg)); 475 476 if (auvia_waitready_codec(sc)) 477 return 1; 478 479 if (auvia_waitvalid_codec(sc)) 480 return 1; 481 482 *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL); 483 484 return 0; 485 } 486 487 488 void 489 auvia_spdif_event(void *addr, int flag) 490 { 491 struct auvia_softc *sc = addr; 492 sc->sc_spdif = flag; 493 } 494 495 int 496 auvia_open(void *addr, int flags) 497 { 498 struct auvia_softc *sc = addr; 499 sc->codec_if->vtbl->lock(sc->codec_if); 500 return 0; 501 } 502 503 504 void 505 auvia_close(void *addr) 506 { 507 struct auvia_softc *sc = addr; 508 sc->codec_if->vtbl->unlock(sc->codec_if); 509 510 /* XXX: already called by audio_close() */ 511 auvia_halt_output(sc); 512 auvia_halt_input(sc); 513 514 sc->sc_play.sc_intr = NULL; 515 sc->sc_record.sc_intr = NULL; 516 } 517 518 519 int 520 auvia_query_encoding(void *addr, struct audio_encoding *fp) 521 { 522 struct auvia_softc *sc = addr; 523 524 if (sc->sc_spdif) { 525 switch (fp->index) { 526 case 0: 527 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name); 528 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 529 fp->precision = 16; 530 fp->flags = 0; 531 fp->bps = 2; 532 fp->msb = 1; 533 return (0); 534 default: 535 return (EINVAL); 536 } 537 } else { 538 switch (fp->index) { 539 case 0: 540 strlcpy(fp->name, AudioEulinear, sizeof fp->name); 541 fp->encoding = AUDIO_ENCODING_ULINEAR; 542 fp->precision = 8; 543 fp->flags = 0; 544 break; 545 case 1: 546 strlcpy(fp->name, AudioEmulaw, sizeof fp->name); 547 fp->encoding = AUDIO_ENCODING_ULAW; 548 fp->precision = 8; 549 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 550 break; 551 case 2: 552 strlcpy(fp->name, AudioEalaw, sizeof fp->name); 553 fp->encoding = AUDIO_ENCODING_ALAW; 554 fp->precision = 8; 555 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 556 break; 557 case 3: 558 strlcpy(fp->name, AudioEslinear, sizeof fp->name); 559 fp->encoding = AUDIO_ENCODING_SLINEAR; 560 fp->precision = 8; 561 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 562 break; 563 case 4: 564 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name); 565 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 566 fp->precision = 16; 567 fp->flags = 0; 568 break; 569 case 5: 570 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name); 571 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 572 fp->precision = 16; 573 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 574 break; 575 case 6: 576 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name); 577 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 578 fp->precision = 16; 579 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 580 break; 581 case 7: 582 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name); 583 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 584 fp->precision = 16; 585 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 586 break; 587 default: 588 return (EINVAL); 589 } 590 fp->bps = AUDIO_BPS(fp->precision); 591 fp->msb = 1; 592 593 return (0); 594 } 595 } 596 597 void 598 auvia_set_params_sub(struct auvia_softc *sc, struct auvia_softc_chan *ch, 599 struct audio_params *p) 600 { 601 u_int32_t v; 602 u_int16_t regval; 603 604 if (!(sc->sc_flags & AUVIA_FLAGS_VT8233)) { 605 regval = (p->channels == 2 ? AUVIA_RPMODE_STEREO : 0) 606 | (p->precision * p->factor == 16 ? 607 AUVIA_RPMODE_16BIT : 0) 608 | AUVIA_RPMODE_INTR_FLAG | AUVIA_RPMODE_INTR_EOL 609 | AUVIA_RPMODE_AUTOSTART; 610 ch->sc_reg = regval; 611 } else if (ch->sc_base != VIA8233_MP_BASE) { 612 v = CH_READ4(sc, ch, VIA8233_RP_RATEFMT); 613 v &= ~(VIA8233_RATEFMT_48K | VIA8233_RATEFMT_STEREO 614 | VIA8233_RATEFMT_16BIT); 615 616 v |= VIA8233_RATEFMT_48K * (p->sample_rate / 20) 617 / (48000 / 20); 618 if (p->channels == 2) 619 v |= VIA8233_RATEFMT_STEREO; 620 if (p->precision == 16) 621 v |= VIA8233_RATEFMT_16BIT; 622 623 CH_WRITE4(sc, ch, VIA8233_RP_RATEFMT, v); 624 } else { 625 static const u_int32_t slottab[7] = 626 { 0, 0xff000011, 0xff000021, 0, 627 0xff004321, 0, 0xff436521}; 628 629 regval = (p->precision == 16 630 ? VIA8233_MP_FORMAT_16BIT : VIA8233_MP_FORMAT_8BIT) 631 | (p->channels << 4); 632 CH_WRITE1(sc, ch, VIA8233_OFF_MP_FORMAT, regval); 633 CH_WRITE4(sc, ch, VIA8233_OFF_MP_STOP, slottab[p->channels]); 634 } 635 } 636 637 void 638 auvia_get_default_params(void *addr, int mode, struct audio_params *params) 639 { 640 ac97_get_default_params(params); 641 } 642 643 int 644 auvia_set_params(void *addr, int setmode, int usemode, 645 struct audio_params *play, struct audio_params *rec) 646 { 647 struct auvia_softc *sc = addr; 648 struct auvia_softc_chan *ch; 649 struct audio_params *p; 650 struct ac97_codec_if* codec = sc->codec_if; 651 int reg, mode; 652 u_int16_t ext_id; 653 654 /* for mode in (RECORD, PLAY) */ 655 for (mode = AUMODE_RECORD; mode != -1; 656 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 657 if ((setmode & mode) == 0) 658 continue; 659 660 if (mode == AUMODE_PLAY) { 661 p = play; 662 ch = &sc->sc_play; 663 reg = AC97_REG_PCM_FRONT_DAC_RATE; 664 } else { 665 p = rec; 666 ch = &sc->sc_record; 667 reg = AC97_REG_PCM_LR_ADC_RATE; 668 } 669 670 if (ch->sc_base == VIA8233_MP_BASE && mode == AUMODE_PLAY) { 671 ext_id = codec->vtbl->get_caps(codec); 672 if (p->channels == 1) { 673 /* ok */ 674 } else if (p->channels == 2) { 675 /* ok */ 676 } else if (p->channels == 4 677 && ext_id & AC97_EXT_AUDIO_SDAC) { 678 /* ok */ 679 } else if (p->channels == 6 680 && (ext_id & AC97_BITS_6CH) == AC97_BITS_6CH) { 681 /* ok */ 682 } else { 683 p->channels = 2; 684 } 685 } else { 686 if (p->channels > 2) 687 p->channels = 2; 688 } 689 690 if (p->sample_rate < 4000) 691 p->sample_rate = 4000; 692 if (p->sample_rate > 48000) 693 p->sample_rate = 48000; 694 if (p->precision > 16) 695 p->precision = 16; 696 697 /* XXX only 16-bit 48kHz slinear_le if s/pdif enabled ? */ 698 if (sc->sc_spdif) { 699 p->sample_rate = 48000; 700 p->precision = 16; 701 p->encoding = AUDIO_ENCODING_SLINEAR_LE; 702 } 703 704 /* XXX only 16-bit 48kHz slinear_le if s/pdif enabled ? */ 705 if (sc->sc_spdif && 706 ((p->sample_rate != 48000) || (p->precision != 16) || 707 (p->encoding != AUDIO_ENCODING_SLINEAR_LE))) 708 return (EINVAL); 709 710 if (AC97_IS_FIXED_RATE(codec)) { 711 p->sample_rate = AC97_SINGLE_RATE; 712 } else { 713 if (codec->vtbl->set_rate(codec, reg, &p->sample_rate)) 714 return (EINVAL); 715 716 if (ch->sc_base == VIA8233_MP_BASE && 717 mode == AUMODE_PLAY) { 718 reg = AC97_REG_PCM_SURR_DAC_RATE; 719 if (p->channels >= 4 720 && codec->vtbl->set_rate(codec, reg, 721 &p->sample_rate)) 722 return (EINVAL); 723 reg = AC97_REG_PCM_LFE_DAC_RATE; 724 if (p->channels == 6 725 && codec->vtbl->set_rate(codec, reg, 726 &p->sample_rate)) 727 return (EINVAL); 728 } 729 } 730 731 p->factor = 1; 732 p->sw_code = 0; 733 switch (p->encoding) { 734 case AUDIO_ENCODING_SLINEAR_BE: 735 if (p->precision == 16) 736 p->sw_code = swap_bytes; 737 else 738 p->sw_code = change_sign8; 739 break; 740 case AUDIO_ENCODING_SLINEAR_LE: 741 if (p->precision != 16) 742 p->sw_code = change_sign8; 743 break; 744 case AUDIO_ENCODING_ULINEAR_BE: 745 if (p->precision == 16) 746 p->sw_code = mode == AUMODE_PLAY? 747 swap_bytes_change_sign16_le : 748 change_sign16_swap_bytes_le; 749 break; 750 case AUDIO_ENCODING_ULINEAR_LE: 751 if (p->precision == 16) 752 p->sw_code = change_sign16_le; 753 break; 754 case AUDIO_ENCODING_ULAW: 755 if (mode == AUMODE_PLAY) { 756 p->factor = 2; 757 p->sw_code = mulaw_to_slinear16_le; 758 } else 759 p->sw_code = ulinear8_to_mulaw; 760 break; 761 case AUDIO_ENCODING_ALAW: 762 if (mode == AUMODE_PLAY) { 763 p->factor = 2; 764 p->sw_code = alaw_to_slinear16_le; 765 } else 766 p->sw_code = ulinear8_to_alaw; 767 break; 768 case AUDIO_ENCODING_SLINEAR: 769 case AUDIO_ENCODING_ULINEAR: 770 break; 771 default: 772 return (EINVAL); 773 } 774 auvia_set_params_sub(sc, ch, p); 775 776 p->bps = AUDIO_BPS(p->precision); 777 p->msb = 1; 778 } 779 780 return 0; 781 } 782 783 784 int 785 auvia_round_blocksize(void *addr, int blk) 786 { 787 struct auvia_softc *sc = addr; 788 789 if (sc->bufsize / blk > AUVIA_DMALIST_MAX) 790 blk = sc->bufsize / AUVIA_DMALIST_MAX + 1; 791 return ((blk + 31) & -32); 792 } 793 794 795 int 796 auvia_halt_output(void *addr) 797 { 798 struct auvia_softc *sc = addr; 799 struct auvia_softc_chan *ch = &(sc->sc_play); 800 801 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE); 802 ch->sc_intr = NULL; 803 return 0; 804 } 805 806 807 int 808 auvia_halt_input(void *addr) 809 { 810 struct auvia_softc *sc = addr; 811 struct auvia_softc_chan *ch = &(sc->sc_record); 812 813 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE); 814 ch->sc_intr = NULL; 815 return 0; 816 } 817 818 819 int 820 auvia_getdev(void *addr, struct audio_device *retp) 821 { 822 struct auvia_softc *sc = addr; 823 824 if (retp) { 825 strncpy(retp->name, 826 sc->sc_flags & AUVIA_FLAGS_VT8233? "VIA VT8233" : 827 "VIA VT82C686A", sizeof(retp->name)); 828 strncpy(retp->version, sc->sc_revision, sizeof(retp->version)); 829 strncpy(retp->config, "auvia", sizeof(retp->config)); 830 } 831 832 return 0; 833 } 834 835 836 int 837 auvia_set_port(void *addr, mixer_ctrl_t *cp) 838 { 839 struct auvia_softc *sc = addr; 840 841 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp)); 842 } 843 844 845 int 846 auvia_get_port(void *addr, mixer_ctrl_t *cp) 847 { 848 struct auvia_softc *sc = addr; 849 850 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp)); 851 } 852 853 854 int 855 auvia_query_devinfo(void *addr, mixer_devinfo_t *dip) 856 { 857 struct auvia_softc *sc = addr; 858 859 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip)); 860 } 861 862 863 void * 864 auvia_malloc(void *addr, int direction, size_t size, int pool, int flags) 865 { 866 struct auvia_softc *sc = addr; 867 struct auvia_dma *p; 868 int error; 869 int rseg; 870 871 p = malloc(sizeof(*p), pool, flags); 872 if (!p) 873 return 0; 874 875 p->size = size; 876 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &p->seg, 877 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 878 printf("%s: unable to allocate dma, error = %d\n", 879 sc->sc_dev.dv_xname, error); 880 goto fail_alloc; 881 } 882 883 if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr, 884 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 885 printf("%s: unable to map dma, error = %d\n", 886 sc->sc_dev.dv_xname, error); 887 goto fail_map; 888 } 889 890 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 891 BUS_DMA_NOWAIT, &p->map)) != 0) { 892 printf("%s: unable to create dma map, error = %d\n", 893 sc->sc_dev.dv_xname, error); 894 goto fail_create; 895 } 896 897 if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL, 898 BUS_DMA_NOWAIT)) != 0) { 899 printf("%s: unable to load dma map, error = %d\n", 900 sc->sc_dev.dv_xname, error); 901 goto fail_load; 902 } 903 904 p->next = sc->sc_dmas; 905 sc->sc_dmas = p; 906 907 return p->addr; 908 909 910 fail_load: 911 bus_dmamap_destroy(sc->sc_dmat, p->map); 912 fail_create: 913 bus_dmamem_unmap(sc->sc_dmat, p->addr, size); 914 fail_map: 915 bus_dmamem_free(sc->sc_dmat, &p->seg, 1); 916 fail_alloc: 917 free(p, pool, 0); 918 return 0; 919 } 920 921 922 void 923 auvia_free(void *addr, void *ptr, int pool) 924 { 925 struct auvia_softc *sc = addr; 926 struct auvia_dma **pp, *p; 927 928 for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next) 929 if (p->addr == ptr) { 930 bus_dmamap_unload(sc->sc_dmat, p->map); 931 bus_dmamap_destroy(sc->sc_dmat, p->map); 932 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); 933 bus_dmamem_free(sc->sc_dmat, &p->seg, 1); 934 935 *pp = p->next; 936 free(p, pool, 0); 937 return; 938 } 939 940 panic("auvia_free: trying to free unallocated memory"); 941 } 942 943 size_t 944 auvia_round_buffersize(void *addr, int direction, size_t bufsize) 945 { 946 struct auvia_softc *sc = addr; 947 948 sc->bufsize = bufsize; 949 return bufsize; 950 } 951 952 paddr_t 953 auvia_mappage(void *addr, void *mem, off_t off, int prot) 954 { 955 struct auvia_softc *sc = addr; 956 struct auvia_dma *p; 957 958 if (off < 0) 959 return -1; 960 961 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next) 962 ; 963 964 if (!p) 965 return -1; 966 967 return bus_dmamem_mmap(sc->sc_dmat, &p->seg, 1, off, prot, 968 BUS_DMA_WAITOK); 969 } 970 971 972 int 973 auvia_get_props(void *addr) 974 { 975 int props; 976 977 props = AUDIO_PROP_MMAP|AUDIO_PROP_INDEPENDENT|AUDIO_PROP_FULLDUPLEX; 978 979 return props; 980 } 981 982 983 int 984 auvia_build_dma_ops(struct auvia_softc *sc, struct auvia_softc_chan *ch, 985 struct auvia_dma *p, void *start, void *end, int blksize) 986 { 987 struct auvia_dma_op *op; 988 struct auvia_dma *dp; 989 bus_addr_t s; 990 size_t l; 991 int segs; 992 993 s = p->map->dm_segs[0].ds_addr; 994 l = (vaddr_t)end - (vaddr_t)start; 995 segs = howmany(l, blksize); 996 if (segs > AUVIA_DMALIST_MAX) { 997 panic("%s: build_dma_ops: too many DMA segments", 998 sc->sc_dev.dv_xname); 999 } 1000 1001 if (segs > ch->sc_dma_op_count) { 1002 /* if old list was too small, free it */ 1003 if (ch->sc_dma_ops) 1004 auvia_free(sc, ch->sc_dma_ops, M_DEVBUF); 1005 1006 ch->sc_dma_ops = auvia_malloc(sc, 0, 1007 sizeof(struct auvia_dma_op) * segs, M_DEVBUF, M_WAITOK); 1008 1009 for (dp = sc->sc_dmas; dp && 1010 dp->addr != (void *)(ch->sc_dma_ops); dp = dp->next) 1011 ; 1012 1013 if (!dp) 1014 panic("%s: build_dma_ops: where'd my memory go??? " 1015 "address (%p)", sc->sc_dev.dv_xname, 1016 ch->sc_dma_ops); 1017 1018 ch->sc_dma_op_count = segs; 1019 ch->sc_dma_ops_dma = dp; 1020 } 1021 1022 op = ch->sc_dma_ops; 1023 1024 while (l) { 1025 op->ptr = htole32(s); 1026 l = l - min(l, blksize); 1027 /* if last block */ 1028 op->flags = htole32((l? AUVIA_DMAOP_FLAG : AUVIA_DMAOP_EOL) | blksize); 1029 s += blksize; 1030 op++; 1031 } 1032 1033 return 0; 1034 } 1035 1036 1037 int 1038 auvia_trigger_output(void *addr, void *start, void *end, int blksize, 1039 void (*intr)(void *), void *arg, struct audio_params *param) 1040 { 1041 struct auvia_softc *sc = addr; 1042 struct auvia_softc_chan *ch = &(sc->sc_play); 1043 struct auvia_dma *p; 1044 1045 for (p = sc->sc_dmas; p && p->addr != start; p = p->next) 1046 ; 1047 1048 if (!p) 1049 panic("auvia_trigger_output: request with bad start " 1050 "address (%p)", start); 1051 1052 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize)) { 1053 return 1; 1054 } 1055 1056 ch->sc_intr = intr; 1057 ch->sc_arg = arg; 1058 1059 CH_WRITE4(sc, ch, AUVIA_RP_DMAOPS_BASE, 1060 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr); 1061 mtx_enter(&audio_lock); 1062 if (sc->sc_flags & AUVIA_FLAGS_VT8233) { 1063 if (ch->sc_base != VIA8233_MP_BASE) { 1064 CH_WRITE1(sc, ch, VIA8233_RP_DXS_LVOL, 0); 1065 CH_WRITE1(sc, ch, VIA8233_RP_DXS_RVOL, 0); 1066 } 1067 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, 1068 AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART | 1069 AUVIA_RPCTRL_STOP | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG); 1070 } else { 1071 CH_WRITE1(sc, ch, AUVIA_RP_MODE, ch->sc_reg); 1072 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_START); 1073 } 1074 mtx_leave(&audio_lock); 1075 return 0; 1076 } 1077 1078 1079 int 1080 auvia_trigger_input(void *addr, void *start, void *end, int blksize, 1081 void (*intr)(void *), void *arg, struct audio_params *param) 1082 { 1083 struct auvia_softc *sc = addr; 1084 struct auvia_softc_chan *ch = &(sc->sc_record); 1085 struct auvia_dma *p; 1086 1087 for (p = sc->sc_dmas; p && p->addr != start; p = p->next) 1088 ; 1089 1090 if (!p) 1091 panic("auvia_trigger_input: request with bad start " 1092 "address (%p)", start); 1093 1094 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize)) 1095 return 1; 1096 1097 ch->sc_intr = intr; 1098 ch->sc_arg = arg; 1099 1100 CH_WRITE4(sc, ch, AUVIA_RP_DMAOPS_BASE, 1101 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr); 1102 1103 mtx_enter(&audio_lock); 1104 if (sc->sc_flags & AUVIA_FLAGS_VT8233) { 1105 if (ch->sc_base != VIA8233_MP_BASE) { 1106 CH_WRITE1(sc, ch, VIA8233_RP_DXS_LVOL, 0); 1107 CH_WRITE1(sc, ch, VIA8233_RP_DXS_RVOL, 0); 1108 } 1109 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, 1110 AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART | 1111 AUVIA_RPCTRL_STOP | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG); 1112 } else { 1113 CH_WRITE1(sc, ch, AUVIA_RP_MODE, ch->sc_reg); 1114 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_START); 1115 } 1116 mtx_leave(&audio_lock); 1117 return 0; 1118 } 1119 1120 1121 int 1122 auvia_intr(void *arg) 1123 { 1124 struct auvia_softc *sc = arg; 1125 struct auvia_softc_chan *ch; 1126 u_int8_t r; 1127 int i = 0; 1128 1129 mtx_enter(&audio_lock); 1130 ch = &sc->sc_record; 1131 r = CH_READ1(sc, ch, AUVIA_RP_STAT); 1132 if (r & AUVIA_RPSTAT_INTR) { 1133 if (sc->sc_record.sc_intr) 1134 sc->sc_record.sc_intr(sc->sc_record.sc_arg); 1135 1136 /* clear interrupts */ 1137 CH_WRITE1(sc, ch, AUVIA_RP_STAT, AUVIA_RPSTAT_INTR); 1138 1139 i++; 1140 } 1141 ch = &sc->sc_play; 1142 r = CH_READ1(sc, ch, AUVIA_RP_STAT); 1143 if (r & AUVIA_RPSTAT_INTR) { 1144 if (sc->sc_play.sc_intr) 1145 sc->sc_play.sc_intr(sc->sc_play.sc_arg); 1146 1147 /* clear interrupts */ 1148 CH_WRITE1(sc, ch, AUVIA_RP_STAT, AUVIA_RPSTAT_INTR); 1149 1150 i++; 1151 } 1152 mtx_leave(&audio_lock); 1153 return (i? 1 : 0); 1154 } 1155 1156 1157 int 1158 auvia_resume(struct auvia_softc *sc) 1159 { 1160 pci_conf_read(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK); 1161 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, 1162 sc->sc_pci_junk); 1163 1164 ac97_resume(&sc->host_if, sc->codec_if); 1165 1166 return (0); 1167 } 1168 1169