1 /* $NetBSD: auvia.c,v 1.51 2005/01/15 15:19:52 kent 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 / VT8233 / VT8235 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/cdefs.h> 50 __KERNEL_RCSID(0, "$NetBSD: auvia.c,v 1.51 2005/01/15 15:19:52 kent Exp $"); 51 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <sys/malloc.h> 55 #include <sys/device.h> 56 #include <sys/audioio.h> 57 58 #include <uvm/uvm_extern.h> 59 60 #include <dev/pci/pcidevs.h> 61 #include <dev/pci/pcivar.h> 62 63 #include <dev/audio_if.h> 64 #include <dev/mulaw.h> 65 #include <dev/auconv.h> 66 67 #include <dev/ic/ac97reg.h> 68 #include <dev/ic/ac97var.h> 69 70 #include <dev/pci/auviavar.h> 71 72 struct auvia_dma { 73 struct auvia_dma *next; 74 caddr_t addr; 75 size_t size; 76 bus_dmamap_t map; 77 bus_dma_segment_t seg; 78 }; 79 80 struct auvia_dma_op { 81 uint32_t ptr; 82 uint32_t flags; 83 #define AUVIA_DMAOP_EOL 0x80000000 84 #define AUVIA_DMAOP_FLAG 0x40000000 85 #define AUVIA_DMAOP_STOP 0x20000000 86 #define AUVIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF) 87 }; 88 89 int auvia_match(struct device *, struct cfdata *, void *); 90 void auvia_attach(struct device *, struct device *, void *); 91 int auvia_query_encoding(void *, struct audio_encoding *); 92 void auvia_set_params_sub(struct auvia_softc *, struct auvia_softc_chan *, 93 const audio_params_t *); 94 int auvia_set_params(void *, int, int, audio_params_t *, audio_params_t *, 95 stream_filter_list_t *, stream_filter_list_t *); 96 int auvia_round_blocksize(void *, int, int, const audio_params_t *); 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, struct malloc_type *, int); 104 void auvia_free(void *, void *, struct malloc_type *); 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 *, const audio_params_t *); 112 int auvia_trigger_input(void *, void *, void *, int, void (*)(void *), 113 void *, const audio_params_t *); 114 void auvia_powerhook(int, void *); 115 int auvia_intr(void *); 116 117 CFATTACH_DECL(auvia, sizeof (struct auvia_softc), 118 auvia_match, auvia_attach, NULL, NULL); 119 120 /* VIA VT823xx revision number */ 121 #define VIA_REV_8233C 0x20 122 #define VIA_REV_8233 0x30 123 #define VIA_REV_8233A 0x40 124 #define VIA_REV_8235 0x50 125 #define VIA_REV_8237 0x60 126 127 #define AUVIA_PCICONF_JUNK 0x40 128 #define AUVIA_PCICONF_ENABLES 0x00FF0000 /* reg 42 mask */ 129 #define AUVIA_PCICONF_ACLINKENAB 0x00008000 /* ac link enab */ 130 #define AUVIA_PCICONF_ACNOTRST 0x00004000 /* ~(ac reset) */ 131 #define AUVIA_PCICONF_ACSYNC 0x00002000 /* ac sync */ 132 #define AUVIA_PCICONF_ACVSR 0x00000800 /* var. samp. rate */ 133 #define AUVIA_PCICONF_ACSGD 0x00000400 /* SGD enab */ 134 #define AUVIA_PCICONF_ACFM 0x00000200 /* FM enab */ 135 #define AUVIA_PCICONF_ACSB 0x00000100 /* SB enab */ 136 #define AUVIA_PCICONF_PRIVALID 0x00000001 /* primary codec rdy */ 137 138 #define AUVIA_PLAY_BASE 0x00 139 #define AUVIA_RECORD_BASE 0x10 140 141 /* *_RP_* are offsets from AUVIA_PLAY_BASE or AUVIA_RECORD_BASE */ 142 #define AUVIA_RP_STAT 0x00 143 #define AUVIA_RPSTAT_INTR 0x03 144 #define AUVIA_RP_CONTROL 0x01 145 #define AUVIA_RPCTRL_START 0x80 146 #define AUVIA_RPCTRL_TERMINATE 0x40 147 #define AUVIA_RPCTRL_AUTOSTART 0x20 148 /* The following are 8233 specific */ 149 #define AUVIA_RPCTRL_STOP 0x04 150 #define AUVIA_RPCTRL_EOL 0x02 151 #define AUVIA_RPCTRL_FLAG 0x01 152 #define AUVIA_RP_MODE 0x02 /* 82c686 specific */ 153 #define AUVIA_RPMODE_INTR_FLAG 0x01 154 #define AUVIA_RPMODE_INTR_EOL 0x02 155 #define AUVIA_RPMODE_STEREO 0x10 156 #define AUVIA_RPMODE_16BIT 0x20 157 #define AUVIA_RPMODE_AUTOSTART 0x80 158 #define AUVIA_RP_DMAOPS_BASE 0x04 159 160 #define VIA8233_RP_DXS_LVOL 0x02 161 #define VIA8233_RP_DXS_RVOL 0x03 162 #define VIA8233_RP_RATEFMT 0x08 163 #define VIA8233_RATEFMT_48K 0xfffff 164 #define VIA8233_RATEFMT_STEREO 0x00100000 165 #define VIA8233_RATEFMT_16BIT 0x00200000 166 167 #define VIA_RP_DMAOPS_COUNT 0x0c 168 169 #define VIA8233_MP_BASE 0x40 170 /* STAT, CONTROL, DMAOPS_BASE, DMAOPS_COUNT are valid */ 171 #define VIA8233_OFF_MP_FORMAT 0x02 172 #define VIA8233_MP_FORMAT_8BIT 0x00 173 #define VIA8233_MP_FORMAT_16BIT 0x80 174 #define VIA8233_MP_FORMAT_CHANNLE_MASK 0x70 /* 1, 2, 4, 6 */ 175 #define VIA8233_OFF_MP_SCRATCH 0x03 176 #define VIA8233_OFF_MP_STOP 0x08 177 178 #define AUVIA_CODEC_CTL 0x80 179 #define AUVIA_CODEC_READ 0x00800000 180 #define AUVIA_CODEC_BUSY 0x01000000 181 #define AUVIA_CODEC_PRIVALID 0x02000000 182 #define AUVIA_CODEC_INDEX(x) ((x)<<16) 183 184 #define CH_WRITE1(sc, ch, off, v) \ 185 bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off), v) 186 #define CH_WRITE4(sc, ch, off, v) \ 187 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off), v) 188 #define CH_READ1(sc, ch, off) \ 189 bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off)) 190 #define CH_READ4(sc, ch, off) \ 191 bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off)) 192 193 #define TIMEOUT 50 194 195 const struct audio_hw_if auvia_hw_if = { 196 NULL, /* open */ 197 NULL, /* close */ 198 NULL, /* drain */ 199 auvia_query_encoding, 200 auvia_set_params, 201 auvia_round_blocksize, 202 NULL, /* commit_settings */ 203 NULL, /* init_output */ 204 NULL, /* init_input */ 205 NULL, /* start_output */ 206 NULL, /* start_input */ 207 auvia_halt_output, 208 auvia_halt_input, 209 NULL, /* speaker_ctl */ 210 auvia_getdev, 211 NULL, /* setfd */ 212 auvia_set_port, 213 auvia_get_port, 214 auvia_query_devinfo, 215 auvia_malloc, 216 auvia_free, 217 auvia_round_buffersize, 218 auvia_mappage, 219 auvia_get_props, 220 auvia_trigger_output, 221 auvia_trigger_input, 222 NULL, /* dev_ioctl */ 223 }; 224 225 #define AUVIA_FORMATS_4CH_16 2 226 #define AUVIA_FORMATS_6CH_16 3 227 #define AUVIA_FORMATS_4CH_8 6 228 #define AUVIA_FORMATS_6CH_8 7 229 static const struct audio_format auvia_formats[AUVIA_NFORMATS] = { 230 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 231 1, AUFMT_MONAURAL, 0, {8000, 48000}}, 232 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 233 2, AUFMT_STEREO, 0, {8000, 48000}}, 234 {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 235 4, AUFMT_SURROUND4, 0, {8000, 48000}}, 236 {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 237 6, AUFMT_DOLBY_5_1, 0, {8000, 48000}}, 238 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8, 239 1, AUFMT_MONAURAL, 0, {8000, 48000}}, 240 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8, 241 2, AUFMT_STEREO, 0, {8000, 48000}}, 242 {NULL, AUMODE_PLAY, AUDIO_ENCODING_ULINEAR_LE, 8, 8, 243 4, AUFMT_SURROUND4, 0, {8000, 48000}}, 244 {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 8, 8, 245 6, AUFMT_DOLBY_5_1, 0, {8000, 48000}}, 246 }; 247 248 int auvia_attach_codec(void *, struct ac97_codec_if *); 249 int auvia_write_codec(void *, uint8_t, uint16_t); 250 int auvia_read_codec(void *, uint8_t, uint16_t *); 251 int auvia_reset_codec(void *); 252 int auvia_waitready_codec(struct auvia_softc *sc); 253 int auvia_waitvalid_codec(struct auvia_softc *sc); 254 255 256 int 257 auvia_match(struct device *parent, struct cfdata *match, void *aux) 258 { 259 struct pci_attach_args *pa; 260 261 pa = (struct pci_attach_args *) aux; 262 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_VIATECH) 263 return 0; 264 switch (PCI_PRODUCT(pa->pa_id)) { 265 case PCI_PRODUCT_VIATECH_VT82C686A_AC97: 266 case PCI_PRODUCT_VIATECH_VT8233_AC97: 267 break; 268 default: 269 return 0; 270 } 271 272 return 1; 273 } 274 275 void 276 auvia_attach(struct device *parent, struct device *self, void *aux) 277 { 278 struct pci_attach_args *pa; 279 struct auvia_softc *sc; 280 const char *intrstr; 281 pci_chipset_tag_t pc; 282 pcitag_t pt; 283 pci_intr_handle_t ih; 284 bus_size_t iosize; 285 pcireg_t pr; 286 int r; 287 const char *revnum; /* VT823xx revision number */ 288 289 pa = aux; 290 sc = (struct auvia_softc *)self; 291 intrstr = NULL; 292 pc = pa->pa_pc; 293 pt = pa->pa_tag; 294 revnum = NULL; 295 296 aprint_naive(": Audio controller\n"); 297 298 sc->sc_play.sc_base = AUVIA_PLAY_BASE; 299 sc->sc_record.sc_base = AUVIA_RECORD_BASE; 300 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT8233_AC97) { 301 sc->sc_flags |= AUVIA_FLAGS_VT8233; 302 sc->sc_play.sc_base = VIA8233_MP_BASE; 303 } 304 305 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, 306 &sc->sc_ioh, NULL, &iosize)) { 307 aprint_error(": can't map i/o space\n"); 308 return; 309 } 310 311 sc->sc_dmat = pa->pa_dmat; 312 sc->sc_pc = pc; 313 sc->sc_pt = pt; 314 315 r = PCI_REVISION(pa->pa_class); 316 if (sc->sc_flags & AUVIA_FLAGS_VT8233) { 317 snprintf(sc->sc_revision, sizeof(sc->sc_revision), "0x%02X", r); 318 switch(r) { 319 case VIA_REV_8233C: 320 /* 2 rec, 4 pb, 1 multi-pb */ 321 revnum = "3C"; 322 break; 323 case VIA_REV_8233: 324 /* 2 rec, 4 pb, 1 multi-pb, spdif */ 325 revnum = "3"; 326 break; 327 case VIA_REV_8233A: 328 /* 1 rec, 1 multi-pb, spdif */ 329 revnum = "3A"; 330 break; 331 default: 332 break; 333 } 334 if (r >= VIA_REV_8237) 335 revnum = "7"; 336 else if (r >= VIA_REV_8235) /* 2 rec, 4 pb, 1 multi-pb, spdif */ 337 revnum = "5"; 338 aprint_normal(": VIA Technologies VT823%s AC'97 Audio " 339 "(rev %s)\n", revnum, sc->sc_revision); 340 } else { 341 sc->sc_revision[1] = '\0'; 342 if (r == 0x20) { 343 sc->sc_revision[0] = 'H'; 344 } else if ((r >= 0x10) && (r <= 0x14)) { 345 sc->sc_revision[0] = 'A' + (r - 0x10); 346 } else { 347 snprintf(sc->sc_revision, sizeof(sc->sc_revision), 348 "0x%02X", r); 349 } 350 351 aprint_normal(": VIA Technologies VT82C686A AC'97 Audio " 352 "(rev %s)\n", sc->sc_revision); 353 } 354 355 if (pci_intr_map(pa, &ih)) { 356 aprint_error(": couldn't map interrupt\n"); 357 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 358 return; 359 } 360 intrstr = pci_intr_string(pc, ih); 361 362 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, auvia_intr, sc); 363 if (sc->sc_ih == NULL) { 364 aprint_error("%s: couldn't establish interrupt", 365 sc->sc_dev.dv_xname); 366 if (intrstr != NULL) 367 aprint_normal(" at %s", intrstr); 368 aprint_normal("\n"); 369 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 370 return; 371 } 372 373 aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 374 375 /* disable SBPro compat & others */ 376 pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK); 377 378 pr &= ~AUVIA_PCICONF_ENABLES; /* clear compat function enables */ 379 /* XXX what to do about MIDI, FM, joystick? */ 380 381 pr |= (AUVIA_PCICONF_ACLINKENAB | AUVIA_PCICONF_ACNOTRST 382 | AUVIA_PCICONF_ACVSR | AUVIA_PCICONF_ACSGD); 383 384 pr &= ~(AUVIA_PCICONF_ACFM | AUVIA_PCICONF_ACSB); 385 386 pci_conf_write(pc, pt, AUVIA_PCICONF_JUNK, pr); 387 388 sc->host_if.arg = sc; 389 sc->host_if.attach = auvia_attach_codec; 390 sc->host_if.read = auvia_read_codec; 391 sc->host_if.write = auvia_write_codec; 392 sc->host_if.reset = auvia_reset_codec; 393 394 if ((r = ac97_attach(&sc->host_if, self)) != 0) { 395 aprint_error("%s: can't attach codec (error 0x%X)\n", 396 sc->sc_dev.dv_xname, r); 397 pci_intr_disestablish(pc, sc->sc_ih); 398 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 399 return; 400 } 401 402 /* setup audio_format */ 403 memcpy(sc->sc_formats, auvia_formats, sizeof(auvia_formats)); 404 if (sc->sc_play.sc_base != VIA8233_MP_BASE || !AC97_IS_4CH(sc->codec_if)) { 405 AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_4CH_8]); 406 AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_4CH_16]); 407 } 408 if (sc->sc_play.sc_base != VIA8233_MP_BASE || !AC97_IS_6CH(sc->codec_if)) { 409 AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_6CH_8]); 410 AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_6CH_16]); 411 } 412 if (AC97_IS_FIXED_RATE(sc->codec_if)) { 413 for (r = 0; r < AUVIA_NFORMATS; r++) { 414 sc->sc_formats[r].frequency_type = 1; 415 sc->sc_formats[r].frequency[0] = 48000; 416 } 417 } 418 419 if (0 != auconv_create_encodings(sc->sc_formats, AUVIA_NFORMATS, 420 &sc->sc_encodings)) { 421 sc->codec_if->vtbl->detach(sc->codec_if); 422 pci_intr_disestablish(pc, sc->sc_ih); 423 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); 424 return; 425 } 426 427 /* Watch for power change */ 428 sc->sc_suspend = PWR_RESUME; 429 sc->sc_powerhook = powerhook_establish(auvia_powerhook, sc); 430 431 audio_attach_mi(&auvia_hw_if, sc, &sc->sc_dev); 432 return; 433 } 434 435 int 436 auvia_attach_codec(void *addr, struct ac97_codec_if *cif) 437 { 438 struct auvia_softc *sc; 439 440 sc = addr; 441 sc->codec_if = cif; 442 return 0; 443 } 444 445 int 446 auvia_reset_codec(void *addr) 447 { 448 struct auvia_softc *sc; 449 pcireg_t r; 450 int i; 451 452 /* perform a codec cold reset */ 453 sc = addr; 454 r = pci_conf_read(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK); 455 456 r &= ~AUVIA_PCICONF_ACNOTRST; /* enable RESET (active low) */ 457 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r); 458 delay(2); 459 460 r |= AUVIA_PCICONF_ACNOTRST; /* disable RESET (inactive high) */ 461 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r); 462 delay(200); 463 464 for (i = 500000; i != 0 && !(pci_conf_read(sc->sc_pc, sc->sc_pt, 465 AUVIA_PCICONF_JUNK) & AUVIA_PCICONF_PRIVALID); i--) 466 DELAY(1); 467 if (i == 0) { 468 printf("%s: codec reset timed out\n", sc->sc_dev.dv_xname); 469 return ETIMEDOUT; 470 } 471 return 0; 472 } 473 474 int 475 auvia_waitready_codec(struct auvia_softc *sc) 476 { 477 int i; 478 479 /* poll until codec not busy */ 480 for (i = 0; (i < TIMEOUT) && (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 481 AUVIA_CODEC_CTL) & AUVIA_CODEC_BUSY); i++) 482 delay(1); 483 if (i >= TIMEOUT) { 484 printf("%s: codec busy\n", sc->sc_dev.dv_xname); 485 return 1; 486 } 487 488 return 0; 489 } 490 491 int 492 auvia_waitvalid_codec(struct auvia_softc *sc) 493 { 494 int i; 495 496 /* poll until codec valid */ 497 for (i = 0; (i < TIMEOUT) && !(bus_space_read_4(sc->sc_iot, sc->sc_ioh, 498 AUVIA_CODEC_CTL) & AUVIA_CODEC_PRIVALID); i++) 499 delay(1); 500 if (i >= TIMEOUT) { 501 printf("%s: codec invalid\n", sc->sc_dev.dv_xname); 502 return 1; 503 } 504 505 return 0; 506 } 507 508 int 509 auvia_write_codec(void *addr, u_int8_t reg, u_int16_t val) 510 { 511 struct auvia_softc *sc; 512 513 sc = addr; 514 if (auvia_waitready_codec(sc)) 515 return 1; 516 517 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL, 518 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_INDEX(reg) | val); 519 520 return 0; 521 } 522 523 int 524 auvia_read_codec(void *addr, u_int8_t reg, u_int16_t *val) 525 { 526 struct auvia_softc *sc; 527 528 sc = addr; 529 if (auvia_waitready_codec(sc)) 530 return 1; 531 532 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL, 533 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_READ | AUVIA_CODEC_INDEX(reg)); 534 535 if (auvia_waitready_codec(sc)) 536 return 1; 537 538 if (auvia_waitvalid_codec(sc)) 539 return 1; 540 541 *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL); 542 543 return 0; 544 } 545 546 int 547 auvia_query_encoding(void *addr, struct audio_encoding *fp) 548 { 549 struct auvia_softc *sc; 550 551 sc = (struct auvia_softc *)addr; 552 return auconv_query_encoding(sc->sc_encodings, fp); 553 } 554 555 void 556 auvia_set_params_sub(struct auvia_softc *sc, struct auvia_softc_chan *ch, 557 const audio_params_t *p) 558 { 559 uint32_t v; 560 uint16_t regval; 561 562 if (!(sc->sc_flags & AUVIA_FLAGS_VT8233)) { 563 regval = (p->channels == 2 ? AUVIA_RPMODE_STEREO : 0) 564 | (p->precision == 16 ? 565 AUVIA_RPMODE_16BIT : 0) 566 | AUVIA_RPMODE_INTR_FLAG | AUVIA_RPMODE_INTR_EOL 567 | AUVIA_RPMODE_AUTOSTART; 568 ch->sc_reg = regval; 569 } else if (ch->sc_base != VIA8233_MP_BASE) { 570 v = CH_READ4(sc, ch, VIA8233_RP_RATEFMT); 571 v &= ~(VIA8233_RATEFMT_48K | VIA8233_RATEFMT_STEREO 572 | VIA8233_RATEFMT_16BIT); 573 574 v |= VIA8233_RATEFMT_48K * (p->sample_rate / 20) 575 / (48000 / 20); 576 if (p->channels == 2) 577 v |= VIA8233_RATEFMT_STEREO; 578 if (p->precision == 16) 579 v |= VIA8233_RATEFMT_16BIT; 580 581 CH_WRITE4(sc, ch, VIA8233_RP_RATEFMT, v); 582 } else { 583 static const u_int32_t slottab[7] = 584 { 0, 0xff000011, 0xff000021, 0, 585 0xff004321, 0, 0xff436521}; 586 587 regval = (p->precision == 16 588 ? VIA8233_MP_FORMAT_16BIT : VIA8233_MP_FORMAT_8BIT) 589 | (p->channels << 4); 590 CH_WRITE1(sc, ch, VIA8233_OFF_MP_FORMAT, regval); 591 CH_WRITE4(sc, ch, VIA8233_OFF_MP_STOP, slottab[p->channels]); 592 } 593 } 594 595 int 596 auvia_set_params(void *addr, int setmode, int usemode, 597 audio_params_t *play, audio_params_t *rec, 598 stream_filter_list_t *pfil, stream_filter_list_t *rfil) 599 { 600 struct auvia_softc *sc; 601 struct auvia_softc_chan *ch; 602 struct audio_params *p; 603 struct ac97_codec_if* codec; 604 stream_filter_list_t *fil; 605 int reg, mode; 606 int index; 607 608 sc = addr; 609 codec = sc->codec_if; 610 /* for mode in (RECORD, PLAY) */ 611 for (mode = AUMODE_RECORD; mode != -1; 612 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 613 if ((setmode & mode) == 0) 614 continue; 615 616 if (mode == AUMODE_PLAY ) { 617 p = play; 618 ch = &sc->sc_play; 619 reg = AC97_REG_PCM_FRONT_DAC_RATE; 620 fil = pfil; 621 } else { 622 p = rec; 623 ch = &sc->sc_record; 624 reg = AC97_REG_PCM_LR_ADC_RATE; 625 fil = rfil; 626 } 627 628 if (p->sample_rate < 4000 || p->sample_rate > 48000 || 629 (p->precision != 8 && p->precision != 16)) 630 return (EINVAL); 631 index = auconv_set_converter(sc->sc_formats, AUVIA_NFORMATS, 632 mode, p, TRUE, fil); 633 if (index < 0) 634 return EINVAL; 635 if (fil->req_size > 0) 636 p = &fil->filters[0].param; 637 if (!AC97_IS_FIXED_RATE(codec)) { 638 if (codec->vtbl->set_rate(codec, reg, &p->sample_rate)) 639 return EINVAL; 640 reg = AC97_REG_PCM_SURR_DAC_RATE; 641 if (p->channels >= 4 642 && codec->vtbl->set_rate(codec, reg, 643 &p->sample_rate)) 644 return EINVAL; 645 reg = AC97_REG_PCM_LFE_DAC_RATE; 646 if (p->channels == 6 647 && codec->vtbl->set_rate(codec, reg, 648 &p->sample_rate)) 649 return EINVAL; 650 } 651 auvia_set_params_sub(sc, ch, p); 652 } 653 654 return 0; 655 } 656 657 int 658 auvia_round_blocksize(void *addr, int blk, 659 int mode, const audio_params_t *param) 660 { 661 struct auvia_softc *sc; 662 663 sc = addr; 664 /* XXX VT823x might have the limitation of dma_ops size */ 665 if (sc->sc_flags & AUVIA_FLAGS_VT8233 && blk < 288) 666 blk = 288; 667 668 return (blk & -32); 669 } 670 671 int 672 auvia_halt_output(void *addr) 673 { 674 struct auvia_softc *sc; 675 struct auvia_softc_chan *ch; 676 677 sc = addr; 678 ch = &(sc->sc_play); 679 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE); 680 ch->sc_intr = NULL; 681 return 0; 682 } 683 684 int 685 auvia_halt_input(void *addr) 686 { 687 struct auvia_softc *sc; 688 struct auvia_softc_chan *ch; 689 690 sc = addr; 691 ch = &(sc->sc_record); 692 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE); 693 ch->sc_intr = NULL; 694 return 0; 695 } 696 697 int 698 auvia_getdev(void *addr, struct audio_device *retp) 699 { 700 struct auvia_softc *sc; 701 702 if (retp) { 703 sc = addr; 704 if (sc->sc_flags & AUVIA_FLAGS_VT8233) { 705 strncpy(retp->name, "VIA VT823x", 706 sizeof(retp->name)); 707 } else { 708 strncpy(retp->name, "VIA VT82C686A", 709 sizeof(retp->name)); 710 } 711 strncpy(retp->version, sc->sc_revision, sizeof(retp->version)); 712 strncpy(retp->config, "auvia", sizeof(retp->config)); 713 } 714 715 return 0; 716 } 717 718 int 719 auvia_set_port(void *addr, mixer_ctrl_t *cp) 720 { 721 struct auvia_softc *sc; 722 723 sc = addr; 724 return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp); 725 } 726 727 int 728 auvia_get_port(void *addr, mixer_ctrl_t *cp) 729 { 730 struct auvia_softc *sc; 731 732 sc = addr; 733 return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp); 734 } 735 736 int 737 auvia_query_devinfo(void *addr, mixer_devinfo_t *dip) 738 { 739 struct auvia_softc *sc; 740 741 sc = addr; 742 return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip); 743 } 744 745 void * 746 auvia_malloc(void *addr, int direction, size_t size, struct malloc_type * pool, 747 int flags) 748 { 749 struct auvia_softc *sc; 750 struct auvia_dma *p; 751 int error; 752 int rseg; 753 754 p = malloc(sizeof(*p), pool, flags); 755 if (!p) 756 return 0; 757 sc = addr; 758 p->size = size; 759 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &p->seg, 760 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 761 printf("%s: unable to allocate DMA, error = %d\n", 762 sc->sc_dev.dv_xname, error); 763 goto fail_alloc; 764 } 765 766 if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr, 767 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 768 printf("%s: unable to map DMA, error = %d\n", 769 sc->sc_dev.dv_xname, error); 770 goto fail_map; 771 } 772 773 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 774 BUS_DMA_NOWAIT, &p->map)) != 0) { 775 printf("%s: unable to create DMA map, error = %d\n", 776 sc->sc_dev.dv_xname, error); 777 goto fail_create; 778 } 779 780 if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL, 781 BUS_DMA_NOWAIT)) != 0) { 782 printf("%s: unable to load DMA map, error = %d\n", 783 sc->sc_dev.dv_xname, error); 784 goto fail_load; 785 } 786 787 p->next = sc->sc_dmas; 788 sc->sc_dmas = p; 789 790 return p->addr; 791 792 793 fail_load: 794 bus_dmamap_destroy(sc->sc_dmat, p->map); 795 fail_create: 796 bus_dmamem_unmap(sc->sc_dmat, p->addr, size); 797 fail_map: 798 bus_dmamem_free(sc->sc_dmat, &p->seg, 1); 799 fail_alloc: 800 free(p, pool); 801 return NULL; 802 } 803 804 void 805 auvia_free(void *addr, void *ptr, struct malloc_type *pool) 806 { 807 struct auvia_softc *sc; 808 struct auvia_dma **pp, *p; 809 810 sc = addr; 811 for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next) 812 if (p->addr == ptr) { 813 bus_dmamap_unload(sc->sc_dmat, p->map); 814 bus_dmamap_destroy(sc->sc_dmat, p->map); 815 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); 816 bus_dmamem_free(sc->sc_dmat, &p->seg, 1); 817 818 *pp = p->next; 819 free(p, pool); 820 return; 821 } 822 823 panic("auvia_free: trying to free unallocated memory"); 824 } 825 826 size_t 827 auvia_round_buffersize(void *addr, int direction, size_t size) 828 { 829 830 return size; 831 } 832 833 paddr_t 834 auvia_mappage(void *addr, void *mem, off_t off, int prot) 835 { 836 struct auvia_softc *sc; 837 struct auvia_dma *p; 838 839 if (off < 0) 840 return -1; 841 sc = addr; 842 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next) 843 continue; 844 845 if (!p) 846 return -1; 847 848 return bus_dmamem_mmap(sc->sc_dmat, &p->seg, 1, off, prot, 849 BUS_DMA_WAITOK); 850 } 851 852 int 853 auvia_get_props(void *addr) 854 { 855 struct auvia_softc *sc; 856 int props; 857 858 props = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 859 sc = addr; 860 /* 861 * Even if the codec is fixed-rate, set_param() succeeds for any sample 862 * rate because of aurateconv. Applications can't know what rate the 863 * device can process in the case of mmap(). 864 */ 865 if (!AC97_IS_FIXED_RATE(sc->codec_if)) 866 props |= AUDIO_PROP_MMAP; 867 return props; 868 } 869 870 int 871 auvia_build_dma_ops(struct auvia_softc *sc, struct auvia_softc_chan *ch, 872 struct auvia_dma *p, void *start, void *end, int blksize) 873 { 874 struct auvia_dma_op *op; 875 struct auvia_dma *dp; 876 bus_addr_t s; 877 size_t l; 878 int segs; 879 880 s = p->map->dm_segs[0].ds_addr; 881 l = ((char *)end - (char *)start); 882 segs = (l + blksize - 1) / blksize; 883 884 if (segs > (ch->sc_dma_op_count)) { 885 /* if old list was too small, free it */ 886 if (ch->sc_dma_ops) { 887 auvia_free(sc, ch->sc_dma_ops, M_DEVBUF); 888 } 889 890 ch->sc_dma_ops = auvia_malloc(sc, 0, 891 sizeof(struct auvia_dma_op) * segs, M_DEVBUF, M_WAITOK); 892 893 if (ch->sc_dma_ops == NULL) { 894 printf("%s: couldn't build dmaops\n", sc->sc_dev.dv_xname); 895 return 1; 896 } 897 898 for (dp = sc->sc_dmas; 899 dp && dp->addr != (void *)(ch->sc_dma_ops); 900 dp = dp->next) 901 continue; 902 903 if (!dp) 904 panic("%s: build_dma_ops: where'd my memory go??? " 905 "address (%p)\n", sc->sc_dev.dv_xname, 906 ch->sc_dma_ops); 907 908 ch->sc_dma_op_count = segs; 909 ch->sc_dma_ops_dma = dp; 910 } 911 912 dp = ch->sc_dma_ops_dma; 913 op = ch->sc_dma_ops; 914 915 while (l) { 916 op->ptr = s; 917 l = l - blksize; 918 if (!l) { 919 /* if last block */ 920 op->flags = AUVIA_DMAOP_EOL | blksize; 921 } else { 922 op->flags = AUVIA_DMAOP_FLAG | blksize; 923 } 924 s += blksize; 925 op++; 926 } 927 928 return 0; 929 } 930 931 932 int 933 auvia_trigger_output(void *addr, void *start, void *end, 934 int blksize, void (*intr)(void *), void *arg, 935 const audio_params_t *param) 936 { 937 struct auvia_softc *sc; 938 struct auvia_softc_chan *ch; 939 struct auvia_dma *p; 940 941 sc = addr; 942 ch = &(sc->sc_play); 943 for (p = sc->sc_dmas; p && p->addr != start; p = p->next) 944 continue; 945 946 if (!p) 947 panic("auvia_trigger_output: request with bad start " 948 "address (%p)", start); 949 950 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize)) { 951 return 1; 952 } 953 954 ch->sc_intr = intr; 955 ch->sc_arg = arg; 956 957 CH_WRITE4(sc, ch, AUVIA_RP_DMAOPS_BASE, 958 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr); 959 960 if (sc->sc_flags & AUVIA_FLAGS_VT8233) { 961 if (ch->sc_base != VIA8233_MP_BASE) { 962 CH_WRITE1(sc, ch, VIA8233_RP_DXS_LVOL, 0); 963 CH_WRITE1(sc, ch, VIA8233_RP_DXS_RVOL, 0); 964 } 965 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, 966 AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART | 967 AUVIA_RPCTRL_STOP | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG); 968 } else { 969 CH_WRITE1(sc, ch, AUVIA_RP_MODE, ch->sc_reg); 970 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_START); 971 } 972 973 return 0; 974 } 975 976 int 977 auvia_trigger_input(void *addr, void *start, void *end, 978 int blksize, void (*intr)(void *), void *arg, 979 const audio_params_t *param) 980 { 981 struct auvia_softc *sc; 982 struct auvia_softc_chan *ch; 983 struct auvia_dma *p; 984 985 sc = addr; 986 ch = &(sc->sc_record); 987 for (p = sc->sc_dmas; p && p->addr != start; p = p->next) 988 continue; 989 990 if (!p) 991 panic("auvia_trigger_input: request with bad start " 992 "address (%p)", start); 993 994 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize)) { 995 return 1; 996 } 997 998 ch->sc_intr = intr; 999 ch->sc_arg = arg; 1000 1001 CH_WRITE4(sc, ch, AUVIA_RP_DMAOPS_BASE, 1002 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr); 1003 1004 if (sc->sc_flags & AUVIA_FLAGS_VT8233) { 1005 CH_WRITE1(sc, ch, VIA8233_RP_DXS_LVOL, 0); 1006 CH_WRITE1(sc, ch, VIA8233_RP_DXS_RVOL, 0); 1007 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, 1008 AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART | 1009 AUVIA_RPCTRL_STOP | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG); 1010 } else { 1011 CH_WRITE1(sc, ch, AUVIA_RP_MODE, ch->sc_reg); 1012 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_START); 1013 } 1014 1015 return 0; 1016 } 1017 1018 int 1019 auvia_intr(void *arg) 1020 { 1021 struct auvia_softc *sc; 1022 struct auvia_softc_chan *ch; 1023 u_int8_t r; 1024 int rval; 1025 1026 sc = arg; 1027 rval = 0; 1028 1029 ch = &sc->sc_record; 1030 r = CH_READ1(sc, ch, AUVIA_RP_STAT); 1031 if (r & AUVIA_RPSTAT_INTR) { 1032 if (sc->sc_record.sc_intr) 1033 sc->sc_record.sc_intr(sc->sc_record.sc_arg); 1034 1035 /* clear interrupts */ 1036 CH_WRITE1(sc, ch, AUVIA_RP_STAT, AUVIA_RPSTAT_INTR); 1037 rval = 1; 1038 } 1039 1040 ch = &sc->sc_play; 1041 r = CH_READ1(sc, ch, AUVIA_RP_STAT); 1042 if (r & AUVIA_RPSTAT_INTR) { 1043 if (sc->sc_play.sc_intr) 1044 sc->sc_play.sc_intr(sc->sc_play.sc_arg); 1045 1046 /* clear interrupts */ 1047 CH_WRITE1(sc, ch, AUVIA_RP_STAT, AUVIA_RPSTAT_INTR); 1048 rval = 1; 1049 } 1050 1051 return rval; 1052 } 1053 1054 void 1055 auvia_powerhook(int why, void *addr) 1056 { 1057 struct auvia_softc *sc; 1058 1059 sc = addr; 1060 switch (why) { 1061 case PWR_SUSPEND: 1062 case PWR_STANDBY: 1063 /* Power down */ 1064 sc->sc_suspend = why; 1065 break; 1066 1067 case PWR_RESUME: 1068 /* Wake up */ 1069 if (sc->sc_suspend == PWR_RESUME) { 1070 printf("%s: resume without suspend.\n", 1071 sc->sc_dev.dv_xname); 1072 sc->sc_suspend = why; 1073 return; 1074 } 1075 sc->sc_suspend = why; 1076 auvia_reset_codec(sc); 1077 DELAY(1000); 1078 (sc->codec_if->vtbl->restore_ports)(sc->codec_if); 1079 break; 1080 1081 case PWR_SOFTSUSPEND: 1082 case PWR_SOFTSTANDBY: 1083 case PWR_SOFTRESUME: 1084 break; 1085 } 1086 } 1087