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