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