1 /* $NetBSD: esm.c,v 1.53 2010/02/24 22:38:00 dyoung Exp $ */ 2 3 /*- 4 * Copyright (c) 2002, 2003 Matt Fredette 5 * All rights reserved. 6 * 7 * Copyright (c) 2000, 2001 Rene Hexel <rh@NetBSD.org> 8 * All rights reserved. 9 * 10 * Copyright (c) 2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp> 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * Taku Id: maestro.c,v 1.12 2000/09/06 03:32:34 taku Exp 35 * FreeBSD: /c/ncvs/src/sys/dev/sound/pci/maestro.c,v 1.4 2000/12/18 01:36:35 cg Exp 36 */ 37 38 /* 39 * TODO: 40 * - hardware volume support 41 * - fix 16-bit stereo recording, add 8-bit recording 42 * - MIDI support 43 * - joystick support 44 * 45 * 46 * Credits: 47 * 48 * This code is based on the FreeBSD driver written by Taku YAMAMOTO 49 * 50 * 51 * Original credits from the FreeBSD driver: 52 * 53 * Part of this code (especially in many magic numbers) was heavily inspired 54 * by the Linux driver originally written by 55 * Alan Cox <alan.cox@linux.org>, modified heavily by 56 * Zach Brown <zab@zabbo.net>. 57 * 58 * busdma()-ize and buffer size reduction were suggested by 59 * Cameron Grant <gandalf@vilnya.demon.co.uk>. 60 * Also he showed me the way to use busdma() suite. 61 * 62 * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500 63 * were looked at by 64 * Munehiro Matsuda <haro@tk.kubota.co.jp>, 65 * who brought patches based on the Linux driver with some simplification. 66 */ 67 68 #include <sys/cdefs.h> 69 __KERNEL_RCSID(0, "$NetBSD: esm.c,v 1.53 2010/02/24 22:38:00 dyoung Exp $"); 70 71 #include <sys/param.h> 72 #include <sys/systm.h> 73 #include <sys/kernel.h> 74 #include <sys/malloc.h> 75 #include <sys/device.h> 76 77 #include <sys/bus.h> 78 79 #include <sys/audioio.h> 80 #include <dev/audio_if.h> 81 #include <dev/mulaw.h> 82 #include <dev/auconv.h> 83 #include <dev/ic/ac97var.h> 84 #include <dev/ic/ac97reg.h> 85 86 #include <dev/pci/pcidevs.h> 87 #include <dev/pci/pcivar.h> 88 89 #include <dev/pci/esmreg.h> 90 #include <dev/pci/esmvar.h> 91 92 #define PCI_CBIO 0x10 /* Configuration Base I/O Address */ 93 94 /* Debug */ 95 #ifdef AUDIO_DEBUG 96 #define DPRINTF(l,x) do { if (esm_debug & (l)) printf x; } while(0) 97 #define DUMPREG(x) do { if (esm_debug & ESM_DEBUG_REG) \ 98 esm_dump_regs(x); } while(0) 99 int esm_debug = 0xfffc; 100 #define ESM_DEBUG_CODECIO 0x0001 101 #define ESM_DEBUG_IRQ 0x0002 102 #define ESM_DEBUG_DMA 0x0004 103 #define ESM_DEBUG_TIMER 0x0008 104 #define ESM_DEBUG_REG 0x0010 105 #define ESM_DEBUG_PARAM 0x0020 106 #define ESM_DEBUG_APU 0x0040 107 #define ESM_DEBUG_CODEC 0x0080 108 #define ESM_DEBUG_PCI 0x0100 109 #define ESM_DEBUG_RESUME 0x0200 110 #else 111 #define DPRINTF(x,y) /* nothing */ 112 #define DUMPREG(x) /* nothing */ 113 #endif 114 115 #ifdef DIAGNOSTIC 116 #define RANGE(n, l, h) if ((n) < (l) || (n) >= (h)) \ 117 printf (#n "=%d out of range (%d, %d) in " \ 118 __FILE__ ", line %d\n", (n), (l), (h), __LINE__) 119 #else 120 #define RANGE(x,y,z) /* nothing */ 121 #endif 122 123 #define inline inline 124 125 static inline void ringbus_setdest(struct esm_softc *, int, int); 126 127 static inline uint16_t wp_rdreg(struct esm_softc *, uint16_t); 128 static inline void wp_wrreg(struct esm_softc *, uint16_t, uint16_t); 129 static inline uint16_t wp_rdapu(struct esm_softc *, int, uint16_t); 130 static inline void wp_wrapu(struct esm_softc *, int, uint16_t, 131 uint16_t); 132 static inline void wp_settimer(struct esm_softc *, u_int); 133 static inline void wp_starttimer(struct esm_softc *); 134 static inline void wp_stoptimer(struct esm_softc *); 135 136 static inline uint16_t wc_rdreg(struct esm_softc *, uint16_t); 137 static inline void wc_wrreg(struct esm_softc *, uint16_t, uint16_t); 138 static inline uint16_t wc_rdchctl(struct esm_softc *, int); 139 static inline void wc_wrchctl(struct esm_softc *, int, uint16_t); 140 141 static inline u_int calc_timer_freq(struct esm_chinfo*); 142 static void set_timer(struct esm_softc *); 143 144 static void esmch_set_format(struct esm_chinfo *, 145 const audio_params_t *); 146 static void esmch_combine_input(struct esm_softc *, 147 struct esm_chinfo *); 148 149 static bool esm_suspend(device_t, const pmf_qual_t *); 150 static bool esm_resume(device_t, const pmf_qual_t *); 151 static void esm_childdet(device_t, device_t); 152 static int esm_match(device_t, cfdata_t, void *); 153 static void esm_attach(device_t, device_t, void *); 154 static int esm_detach(device_t, int); 155 static int esm_intr(void *); 156 157 static void esm_freemem(struct esm_softc *, struct esm_dma *); 158 static int esm_allocmem(struct esm_softc *, size_t, size_t, 159 struct esm_dma *); 160 161 162 CFATTACH_DECL2_NEW(esm, sizeof(struct esm_softc), 163 esm_match, esm_attach, esm_detach, NULL, NULL, esm_childdet); 164 165 const struct audio_hw_if esm_hw_if = { 166 NULL, /* open */ 167 NULL, /* close */ 168 NULL, /* drain */ 169 esm_query_encoding, 170 esm_set_params, 171 esm_round_blocksize, 172 NULL, /* commit_settings */ 173 esm_init_output, 174 esm_init_input, 175 NULL, /* start_output */ 176 NULL, /* start_input */ 177 esm_halt_output, 178 esm_halt_input, 179 NULL, /* speaker_ctl */ 180 esm_getdev, 181 NULL, /* getfd */ 182 esm_set_port, 183 esm_get_port, 184 esm_query_devinfo, 185 esm_malloc, 186 esm_free, 187 esm_round_buffersize, 188 esm_mappage, 189 esm_get_props, 190 esm_trigger_output, 191 esm_trigger_input, 192 NULL, 193 NULL, 194 }; 195 196 struct audio_device esm_device = { 197 "ESS Maestro", 198 "", 199 "esm" 200 }; 201 202 #define MAESTRO_NENCODINGS 8 203 static audio_encoding_t esm_encoding[MAESTRO_NENCODINGS] = { 204 { 0, AudioEulinear, AUDIO_ENCODING_ULINEAR, 8, 0 }, 205 { 1, AudioEmulaw, AUDIO_ENCODING_ULAW, 8, 206 AUDIO_ENCODINGFLAG_EMULATED }, 207 { 2, AudioEalaw, AUDIO_ENCODING_ALAW, 8, AUDIO_ENCODINGFLAG_EMULATED }, 208 { 3, AudioEslinear, AUDIO_ENCODING_SLINEAR, 8, 0 }, 209 { 4, AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE, 16, 0 }, 210 { 5, AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE, 16, 211 AUDIO_ENCODINGFLAG_EMULATED }, 212 { 6, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16, 213 AUDIO_ENCODINGFLAG_EMULATED }, 214 { 7, AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE, 16, 215 AUDIO_ENCODINGFLAG_EMULATED }, 216 }; 217 218 #define ESM_NFORMATS 4 219 static const struct audio_format esm_formats[ESM_NFORMATS] = { 220 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 221 2, AUFMT_STEREO, 0, {4000, 48000}}, 222 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 223 1, AUFMT_MONAURAL, 0, {4000, 48000}}, 224 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8, 225 2, AUFMT_STEREO, 0, {4000, 48000}}, 226 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8, 227 1, AUFMT_MONAURAL, 0, {4000, 48000}}, 228 }; 229 230 static const struct esm_quirks esm_quirks[] = { 231 /* COMPAL 38W2 OEM Notebook, e.g. Dell INSPIRON 5000e */ 232 { PCI_VENDOR_COMPAL, PCI_PRODUCT_COMPAL_38W2, ESM_QUIRKF_SWAPPEDCH }, 233 234 /* COMPAQ Armada M700 Notebook */ 235 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_M700, ESM_QUIRKF_SWAPPEDCH }, 236 237 /* NEC Versa Pro LX VA26D */ 238 { PCI_VENDOR_NEC, PCI_PRODUCT_NEC_VA26D, ESM_QUIRKF_GPIO }, 239 240 /* NEC Versa LX */ 241 { PCI_VENDOR_NEC, PCI_PRODUCT_NEC_VERSALX, ESM_QUIRKF_GPIO }, 242 243 /* Toshiba Portege */ 244 { PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_PORTEGE, ESM_QUIRKF_SWAPPEDCH } 245 }; 246 247 enum esm_quirk_flags 248 esm_get_quirks(pcireg_t subid) 249 { 250 int i; 251 252 for (i = 0; i < __arraycount(esm_quirks); i++) { 253 if (PCI_VENDOR(subid) == esm_quirks[i].eq_vendor && 254 PCI_PRODUCT(subid) == esm_quirks[i].eq_product) { 255 return esm_quirks[i].eq_quirks; 256 } 257 } 258 259 return 0; 260 } 261 262 263 #ifdef AUDIO_DEBUG 264 struct esm_reg_info { 265 int offset; /* register offset */ 266 int width; /* 1/2/4 bytes */ 267 } dump_regs[] = { 268 { PORT_WAVCACHE_CTRL, 2 }, 269 { PORT_HOSTINT_CTRL, 2 }, 270 { PORT_HOSTINT_STAT, 2 }, 271 { PORT_HWVOL_VOICE_SHADOW, 1 }, 272 { PORT_HWVOL_VOICE, 1 }, 273 { PORT_HWVOL_MASTER_SHADOW, 1 }, 274 { PORT_HWVOL_MASTER, 1 }, 275 { PORT_RINGBUS_CTRL, 4 }, 276 { PORT_GPIO_DATA, 2 }, 277 { PORT_GPIO_MASK, 2 }, 278 { PORT_GPIO_DIR, 2 }, 279 { PORT_ASSP_CTRL_A, 1 }, 280 { PORT_ASSP_CTRL_B, 1 }, 281 { PORT_ASSP_CTRL_C, 1 }, 282 { PORT_ASSP_INT_STAT, 1 } 283 }; 284 285 static void 286 esm_dump_regs(struct esm_softc *ess) 287 { 288 int i; 289 290 printf("%s registers:", device_xname(ess->sc_dev)); 291 for (i = 0; i < __arraycount(dump_regs); i++) { 292 if (i % 5 == 0) 293 printf("\n"); 294 printf("0x%2.2x: ", dump_regs[i].offset); 295 switch(dump_regs[i].width) { 296 case 4: 297 printf("%8.8x, ", bus_space_read_4(ess->st, ess->sh, 298 dump_regs[i].offset)); 299 break; 300 case 2: 301 printf("%4.4x, ", bus_space_read_2(ess->st, ess->sh, 302 dump_regs[i].offset)); 303 break; 304 default: 305 printf("%2.2x, ", 306 bus_space_read_1(ess->st, ess->sh, 307 dump_regs[i].offset)); 308 } 309 } 310 printf("\n"); 311 } 312 #endif 313 314 315 /* ----------------------------- 316 * Subsystems. 317 */ 318 319 /* Codec/Ringbus */ 320 321 /* -------------------------------------------------------------------- */ 322 323 int 324 esm_read_codec(void *sc, uint8_t regno, uint16_t *result) 325 { 326 struct esm_softc *ess; 327 unsigned t; 328 329 ess = sc; 330 /* We have to wait for a SAFE time to write addr/data */ 331 for (t = 0; t < 20; t++) { 332 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 333 & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) 334 break; 335 delay(2); /* 20.8us / 13 */ 336 } 337 if (t == 20) 338 printf("%s: esm_read_codec() PROGLESS timed out.\n", 339 device_xname(ess->sc_dev)); 340 341 bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, 342 CODEC_CMD_READ | regno); 343 delay(21); /* AC97 cycle = 20.8usec */ 344 345 /* Wait for data retrieve */ 346 for (t = 0; t < 20; t++) { 347 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 348 & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE) 349 break; 350 delay(2); /* 20.8us / 13 */ 351 } 352 if (t == 20) 353 /* Timed out, but perform dummy read. */ 354 printf("%s: esm_read_codec() RW_DONE timed out.\n", 355 device_xname(ess->sc_dev)); 356 357 *result = bus_space_read_2(ess->st, ess->sh, PORT_CODEC_REG); 358 359 return 0; 360 } 361 362 int 363 esm_write_codec(void *sc, uint8_t regno, uint16_t data) 364 { 365 struct esm_softc *ess; 366 unsigned t; 367 368 ess = sc; 369 /* We have to wait for a SAFE time to write addr/data */ 370 for (t = 0; t < 20; t++) { 371 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 372 & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) 373 break; 374 delay(2); /* 20.8us / 13 */ 375 } 376 if (t == 20) { 377 /* Timed out. Abort writing. */ 378 printf("%s: esm_write_codec() PROGLESS timed out.\n", 379 device_xname(ess->sc_dev)); 380 return -1; 381 } 382 383 bus_space_write_2(ess->st, ess->sh, PORT_CODEC_REG, data); 384 bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, 385 CODEC_CMD_WRITE | regno); 386 387 return 0; 388 } 389 390 /* -------------------------------------------------------------------- */ 391 392 static inline void 393 ringbus_setdest(struct esm_softc *ess, int src, int dest) 394 { 395 uint32_t data; 396 397 data = bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL); 398 data &= ~(0xfU << src); 399 data |= (0xfU & dest) << src; 400 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, data); 401 } 402 403 /* Wave Processor */ 404 405 static inline uint16_t 406 wp_rdreg(struct esm_softc *ess, uint16_t reg) 407 { 408 409 bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); 410 return bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA); 411 } 412 413 static inline void 414 wp_wrreg(struct esm_softc *ess, uint16_t reg, uint16_t data) 415 { 416 417 bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); 418 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); 419 } 420 421 static inline void 422 apu_setindex(struct esm_softc *ess, uint16_t reg) 423 { 424 int t; 425 426 wp_wrreg(ess, WPREG_CRAM_PTR, reg); 427 /* Sometimes WP fails to set apu register index. */ 428 for (t = 0; t < 1000; t++) { 429 if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == reg) 430 break; 431 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, reg); 432 } 433 if (t == 1000) 434 printf("%s: apu_setindex() timed out.\n", device_xname(ess->sc_dev)); 435 } 436 437 static inline uint16_t 438 wp_rdapu(struct esm_softc *ess, int ch, uint16_t reg) 439 { 440 uint16_t ret; 441 442 apu_setindex(ess, ((unsigned)ch << 4) + reg); 443 ret = wp_rdreg(ess, WPREG_DATA_PORT); 444 return ret; 445 } 446 447 static inline void 448 wp_wrapu(struct esm_softc *ess, int ch, uint16_t reg, uint16_t data) 449 { 450 int t; 451 452 DPRINTF(ESM_DEBUG_APU, 453 ("wp_wrapu(%p, ch=%d, reg=0x%x, data=0x%04x)\n", 454 ess, ch, reg, data)); 455 456 apu_setindex(ess, ((unsigned)ch << 4) + reg); 457 wp_wrreg(ess, WPREG_DATA_PORT, data); 458 for (t = 0; t < 1000; t++) { 459 if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == data) 460 break; 461 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); 462 } 463 if (t == 1000) 464 printf("%s: wp_wrapu() timed out.\n", device_xname(ess->sc_dev)); 465 } 466 467 static inline void 468 wp_settimer(struct esm_softc *ess, u_int freq) 469 { 470 u_int clock; 471 u_int prescale, divide; 472 473 clock = 48000 << 2; 474 prescale = 0; 475 divide = (freq != 0) ? (clock / freq) : ~0; 476 RANGE(divide, WPTIMER_MINDIV, WPTIMER_MAXDIV); 477 478 for (; divide > 32 << 1; divide >>= 1) 479 prescale++; 480 divide = (divide + 1) >> 1; 481 482 for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1) 483 prescale++; 484 485 DPRINTF(ESM_DEBUG_TIMER, 486 ("wp_settimer(%p, %u): clock = %u, prescale = %u, divide = %u\n", 487 ess, freq, clock, prescale, divide)); 488 489 wp_wrreg(ess, WPREG_TIMER_ENABLE, 0); 490 wp_wrreg(ess, WPREG_TIMER_FREQ, 491 (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1)); 492 wp_wrreg(ess, WPREG_TIMER_ENABLE, 1); 493 } 494 495 static inline void 496 wp_starttimer(struct esm_softc *ess) 497 { 498 499 wp_wrreg(ess, WPREG_TIMER_START, 1); 500 } 501 502 static inline void 503 wp_stoptimer(struct esm_softc *ess) 504 { 505 506 wp_wrreg(ess, WPREG_TIMER_START, 0); 507 bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); 508 } 509 510 /* WaveCache */ 511 512 static inline uint16_t 513 wc_rdreg(struct esm_softc *ess, uint16_t reg) 514 { 515 516 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); 517 return bus_space_read_2(ess->st, ess->sh, PORT_WAVCACHE_DATA); 518 } 519 520 static inline void 521 wc_wrreg(struct esm_softc *ess, uint16_t reg, uint16_t data) 522 { 523 524 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); 525 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_DATA, data); 526 } 527 528 static inline uint16_t 529 wc_rdchctl(struct esm_softc *ess, int ch) 530 { 531 532 return wc_rdreg(ess, ch << 3); 533 } 534 535 static inline void 536 wc_wrchctl(struct esm_softc *ess, int ch, uint16_t data) 537 { 538 539 wc_wrreg(ess, ch << 3, data); 540 } 541 542 /* ----------------------------- 543 * Controller. 544 */ 545 546 int 547 esm_attach_codec(void *sc, struct ac97_codec_if *codec_if) 548 { 549 struct esm_softc *ess; 550 551 ess = sc; 552 ess->codec_if = codec_if; 553 554 return 0; 555 } 556 557 int 558 esm_reset_codec(void *sc) 559 { 560 561 return 0; 562 } 563 564 565 enum ac97_host_flags 566 esm_flags_codec(void *sc) 567 { 568 struct esm_softc *ess; 569 570 ess = sc; 571 return ess->codec_flags; 572 } 573 574 575 void 576 esm_initcodec(struct esm_softc *ess) 577 { 578 uint16_t data; 579 580 DPRINTF(ESM_DEBUG_CODEC, ("esm_initcodec(%p)\n", ess)); 581 582 if (bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL) 583 & RINGBUS_CTRL_ACLINK_ENABLED) { 584 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 585 delay(104); /* 20.8us * (4 + 1) */ 586 } 587 /* XXX - 2nd codec should be looked at. */ 588 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 589 RINGBUS_CTRL_AC97_SWRESET); 590 delay(2); 591 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 592 RINGBUS_CTRL_ACLINK_ENABLED); 593 delay(21); 594 595 esm_read_codec(ess, 0, &data); 596 if (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 597 & CODEC_STAT_MASK) { 598 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 599 delay(21); 600 601 /* Try cold reset. */ 602 printf("%s: will perform cold reset.\n", device_xname(ess->sc_dev)); 603 data = bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR); 604 if (pci_conf_read(ess->pc, ess->tag, 0x58) & 1) 605 data |= 0x10; 606 data |= 0x009 & 607 ~bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DATA); 608 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0xff6); 609 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 610 data | 0x009); 611 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x000); 612 delay(2); 613 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x001); 614 delay(1); 615 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x009); 616 delay(500000); 617 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, data); 618 delay(84); /* 20.8us * 4 */ 619 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 620 RINGBUS_CTRL_ACLINK_ENABLED); 621 delay(21); 622 } 623 } 624 625 void 626 esm_init(struct esm_softc *ess) 627 { 628 629 /* Reset direct sound. */ 630 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 631 HOSTINT_CTRL_DSOUND_RESET); 632 delay(10000); 633 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 634 delay(10000); 635 636 /* Enable direct sound interruption. */ 637 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 638 HOSTINT_CTRL_DSOUND_INT_ENABLED); 639 640 /* Setup Wave Processor. */ 641 642 /* Enable WaveCache */ 643 wp_wrreg(ess, WPREG_WAVE_ROMRAM, 644 WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED); 645 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_CTRL, 646 WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB); 647 648 /* Setup Codec/Ringbus. */ 649 esm_initcodec(ess); 650 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 651 RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED); 652 653 /* Undocumented registers from the Linux driver. */ 654 wp_wrreg(ess, 0x8, 0xB004); 655 wp_wrreg(ess, 0x9, 0x001B); 656 wp_wrreg(ess, 0xA, 0x8000); 657 wp_wrreg(ess, 0xB, 0x3F37); 658 wp_wrreg(ess, 0xD, 0x7632); 659 660 wp_wrreg(ess, WPREG_BASE, 0x8598); /* Parallel I/O */ 661 ringbus_setdest(ess, RINGBUS_SRC_ADC, 662 RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN); 663 ringbus_setdest(ess, RINGBUS_SRC_DSOUND, 664 RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC); 665 666 /* Setup ASSP. Needed for Dell Inspiron 7500? */ 667 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_B, 0x00); 668 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_A, 0x03); 669 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_C, 0x00); 670 671 /* 672 * Setup GPIO. 673 * There seems to be speciality with NEC systems. 674 */ 675 if (esm_get_quirks(ess->subid) & ESM_QUIRKF_GPIO) { 676 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 677 0x9ff); 678 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 679 bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR) | 680 0x600); 681 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 682 0x200); 683 } 684 685 DUMPREG(ess); 686 } 687 688 /* Channel controller. */ 689 690 int 691 esm_init_output (void *sc, void *start, int size) 692 { 693 struct esm_softc *ess; 694 struct esm_dma *p; 695 696 ess = sc; 697 p = &ess->sc_dma; 698 if ((char *)start != (char *)p->addr + MAESTRO_PLAYBUF_OFF) { 699 printf("%s: esm_init_output: bad addr %p\n", 700 device_xname(ess->sc_dev), start); 701 return EINVAL; 702 } 703 704 ess->pch.base = DMAADDR(p) + MAESTRO_PLAYBUF_OFF; 705 706 DPRINTF(ESM_DEBUG_DMA, ("%s: pch.base = 0x%x\n", 707 device_xname(ess->sc_dev), ess->pch.base)); 708 709 return 0; 710 } 711 712 int 713 esm_init_input (void *sc, void *start, int size) 714 { 715 struct esm_softc *ess; 716 struct esm_dma *p; 717 718 ess = sc; 719 p = &ess->sc_dma; 720 if ((char *)start != (char *)p->addr + MAESTRO_RECBUF_OFF) { 721 printf("%s: esm_init_input: bad addr %p\n", 722 device_xname(ess->sc_dev), start); 723 return EINVAL; 724 } 725 726 switch (ess->rch.aputype) { 727 case APUTYPE_16BITSTEREO: 728 ess->rch.base = DMAADDR(p) + MAESTRO_RECBUF_L_OFF; 729 break; 730 default: 731 ess->rch.base = DMAADDR(p) + MAESTRO_RECBUF_OFF; 732 break; 733 } 734 735 DPRINTF(ESM_DEBUG_DMA, ("%s: rch.base = 0x%x\n", 736 device_xname(ess->sc_dev), ess->rch.base)); 737 738 return 0; 739 } 740 741 int 742 esm_trigger_output(void *sc, void *start, void *end, int blksize, 743 void (*intr)(void *), void *arg, const audio_params_t *param) 744 { 745 size_t size; 746 struct esm_softc *ess; 747 struct esm_chinfo *ch; 748 struct esm_dma *p; 749 int pan, choffset; 750 int i, nch; 751 unsigned speed, offset, wpwa, dv; 752 uint16_t apuch; 753 754 DPRINTF(ESM_DEBUG_DMA, 755 ("esm_trigger_output(%p, %p, %p, 0x%x, %p, %p, %p)\n", 756 sc, start, end, blksize, intr, arg, param)); 757 ess = sc; 758 ch = &ess->pch; 759 pan = 0; 760 nch = 1; 761 speed = ch->sample_rate; 762 apuch = ch->num << 1; 763 764 #ifdef DIAGNOSTIC 765 if (ess->pactive) { 766 printf("%s: esm_trigger_output: already running", 767 device_xname(ess->sc_dev)); 768 return EINVAL; 769 } 770 #endif 771 772 ess->sc_pintr = intr; 773 ess->sc_parg = arg; 774 p = &ess->sc_dma; 775 if ((char *)start != (char *)p->addr + MAESTRO_PLAYBUF_OFF) { 776 printf("%s: esm_trigger_output: bad addr %p\n", 777 device_xname(ess->sc_dev), start); 778 return EINVAL; 779 } 780 781 ess->pch.blocksize = blksize; 782 ess->pch.apublk = blksize >> 1; 783 ess->pactive = 1; 784 785 size = (size_t)(((char *)end - (char *)start) >> 1); 786 choffset = MAESTRO_PLAYBUF_OFF; 787 offset = choffset >> 1; 788 wpwa = APU_USE_SYSMEM | ((offset >> 8) & APU_64KPAGE_MASK); 789 790 DPRINTF(ESM_DEBUG_DMA, 791 ("choffs=0x%x, wpwa=0x%x, size=0x%lx words\n", 792 choffset, wpwa, (unsigned long int)size)); 793 794 switch (ch->aputype) { 795 case APUTYPE_16BITSTEREO: 796 ess->pch.apublk >>= 1; 797 wpwa >>= 1; 798 size >>= 1; 799 offset >>= 1; 800 /* FALLTHROUGH */ 801 case APUTYPE_8BITSTEREO: 802 if (ess->codec_flags & AC97_HOST_SWAPPED_CHANNELS) 803 pan = 8; 804 else 805 pan = -8; 806 nch++; 807 break; 808 case APUTYPE_8BITLINEAR: 809 ess->pch.apublk <<= 1; 810 speed >>= 1; 811 break; 812 } 813 814 ess->pch.apubase = offset; 815 ess->pch.apubuf = size; 816 ess->pch.nextirq = ess->pch.apublk; 817 818 set_timer(ess); 819 wp_starttimer(ess); 820 821 dv = (((speed % 48000) << 16) + 24000) / 48000 822 + ((speed / 48000) << 16); 823 824 for (i = nch-1; i >= 0; i--) { 825 wp_wrapu(ess, apuch + i, APUREG_WAVESPACE, wpwa & 0xff00); 826 wp_wrapu(ess, apuch + i, APUREG_CURPTR, offset); 827 wp_wrapu(ess, apuch + i, APUREG_ENDPTR, offset + size); 828 wp_wrapu(ess, apuch + i, APUREG_LOOPLEN, size - 1); 829 wp_wrapu(ess, apuch + i, APUREG_AMPLITUDE, 0xe800); 830 wp_wrapu(ess, apuch + i, APUREG_POSITION, 0x8f00 831 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 832 | ((PAN_FRONT + pan) << APU_PAN_SHIFT)); 833 wp_wrapu(ess, apuch + i, APUREG_FREQ_LOBYTE, APU_plus6dB 834 | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT)); 835 wp_wrapu(ess, apuch + i, APUREG_FREQ_HIWORD, dv >> 8); 836 837 if (ch->aputype == APUTYPE_16BITSTEREO) 838 wpwa |= APU_STEREO >> 1; 839 pan = -pan; 840 } 841 842 wc_wrchctl(ess, apuch, ch->wcreg_tpl); 843 if (nch > 1) 844 wc_wrchctl(ess, apuch + 1, ch->wcreg_tpl); 845 846 wp_wrapu(ess, apuch, APUREG_APUTYPE, 847 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 848 if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) 849 wp_wrapu(ess, apuch + 1, APUREG_APUTYPE, 850 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 851 852 return 0; 853 } 854 855 int 856 esm_trigger_input(void *sc, void *start, void *end, int blksize, 857 void (*intr)(void *), void *arg, const audio_params_t *param) 858 { 859 size_t size; 860 size_t mixsize; 861 struct esm_softc *ess; 862 struct esm_chinfo *ch; 863 struct esm_dma *p; 864 uint32_t chctl, choffset; 865 uint32_t speed, offset, wpwa, dv; 866 uint32_t mixoffset, mixdv; 867 int i, nch; 868 uint16_t apuch; 869 uint16_t reg; 870 871 DPRINTF(ESM_DEBUG_DMA, 872 ("esm_trigger_input(%p, %p, %p, 0x%x, %p, %p, %p)\n", 873 sc, start, end, blksize, intr, arg, param)); 874 ess = sc; 875 ch = &ess->rch; 876 nch = 1; 877 speed = ch->sample_rate; 878 apuch = ch->num << 1; 879 880 #ifdef DIAGNOSTIC 881 if (ess->ractive) { 882 printf("%s: esm_trigger_input: already running", 883 device_xname(ess->sc_dev)); 884 return EINVAL; 885 } 886 #endif 887 888 ess->sc_rintr = intr; 889 ess->sc_rarg = arg; 890 p = &ess->sc_dma; 891 if ((char *)start != (char *)p->addr + MAESTRO_RECBUF_OFF) { 892 printf("%s: esm_trigger_input: bad addr %p\n", 893 device_xname(ess->sc_dev), start); 894 return EINVAL; 895 } 896 897 ess->rch.buffer = (void *)start; 898 ess->rch.offset = 0; 899 ess->rch.blocksize = blksize; 900 ess->rch.bufsize = ((char *)end - (char *)start); 901 ess->rch.apublk = blksize >> 1; 902 ess->ractive = 1; 903 904 size = (size_t)(((char *)end - (char *)start) >> 1); 905 choffset = MAESTRO_RECBUF_OFF; 906 switch (ch->aputype) { 907 case APUTYPE_16BITSTEREO: 908 size >>= 1; 909 choffset = MAESTRO_RECBUF_L_OFF; 910 ess->rch.apublk >>= 1; 911 nch++; 912 break; 913 case APUTYPE_16BITLINEAR: 914 break; 915 default: 916 ess->ractive = 0; 917 return EINVAL; 918 } 919 920 mixsize = (MAESTRO_MIXBUF_SZ >> 1) >> 1; 921 mixoffset = MAESTRO_MIXBUF_OFF; 922 923 ess->rch.apubase = (choffset >> 1); 924 ess->rch.apubuf = size; 925 ess->rch.nextirq = ess->rch.apublk; 926 927 set_timer(ess); 928 wp_starttimer(ess); 929 930 if (speed > 47999) speed = 47999; 931 if (speed < 4000) speed = 4000; 932 dv = (((speed % 48000) << 16) + 24000) / 48000 933 + ((speed / 48000) << 16); 934 mixdv = 65536; /* 48 kHz */ 935 936 for (i = 0; i < nch; i++) { 937 938 /* Clear all rate conversion WP channel registers first. */ 939 for (reg = 0; reg < 15; reg++) 940 wp_wrapu(ess, apuch + i, reg, 0); 941 942 /* Program the WaveCache for the rate conversion WP channel. */ 943 chctl = (DMAADDR(p) + choffset - 0x10) & 944 WAVCACHE_CHCTL_ADDRTAG_MASK; 945 wc_wrchctl(ess, apuch + i, chctl); 946 947 /* Program the rate conversion WP channel. */ 948 wp_wrapu(ess, apuch + i, APUREG_FREQ_LOBYTE, APU_plus6dB 949 | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT) | 0x08); 950 wp_wrapu(ess, apuch + i, APUREG_FREQ_HIWORD, dv >> 8); 951 offset = choffset >> 1; 952 wpwa = APU_USE_SYSMEM | ((offset >> 8) & APU_64KPAGE_MASK); 953 wp_wrapu(ess, apuch + i, APUREG_WAVESPACE, wpwa); 954 wp_wrapu(ess, apuch + i, APUREG_CURPTR, offset); 955 wp_wrapu(ess, apuch + i, APUREG_ENDPTR, offset + size); 956 wp_wrapu(ess, apuch + i, APUREG_LOOPLEN, size - 1); 957 wp_wrapu(ess, apuch + i, APUREG_EFFECTS_ENV, 0x00f0); 958 wp_wrapu(ess, apuch + i, APUREG_AMPLITUDE, 0xe800); 959 wp_wrapu(ess, apuch + i, APUREG_POSITION, 0x8f00 960 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 961 | (PAN_FRONT << APU_PAN_SHIFT)); 962 wp_wrapu(ess, apuch + i, APUREG_ROUTE, apuch + 2 + i); 963 964 DPRINTF(ESM_DEBUG_DMA, 965 ("choffs=0x%x, wpwa=0x%x, offset=0x%x words, size=0x%lx words\n", 966 choffset, wpwa, offset, (unsigned long int)size)); 967 968 /* Clear all mixer WP channel registers first. */ 969 for (reg = 0; reg < 15; reg++) 970 wp_wrapu(ess, apuch + 2 + i, reg, 0); 971 972 /* Program the WaveCache for the mixer WP channel. */ 973 chctl = (ess->rch.base + mixoffset - 0x10) & 974 WAVCACHE_CHCTL_ADDRTAG_MASK; 975 wc_wrchctl(ess, apuch + 2 + i, chctl); 976 977 /* Program the mixer WP channel. */ 978 wp_wrapu(ess, apuch + 2 + i, APUREG_FREQ_LOBYTE, APU_plus6dB 979 | ((mixdv & 0xff) << APU_FREQ_LOBYTE_SHIFT) | 0x08); 980 wp_wrapu(ess, apuch + 2 + i, APUREG_FREQ_HIWORD, mixdv >> 8); 981 offset = mixoffset >> 1; 982 wpwa = APU_USE_SYSMEM | ((offset >> 8) & APU_64KPAGE_MASK); 983 wp_wrapu(ess, apuch + 2 + i, APUREG_WAVESPACE, wpwa); 984 wp_wrapu(ess, apuch + 2 + i, APUREG_CURPTR, offset); 985 wp_wrapu(ess, apuch + 2 + i, APUREG_ENDPTR, 986 offset + mixsize); 987 wp_wrapu(ess, apuch + 2 + i, APUREG_LOOPLEN, mixsize); 988 wp_wrapu(ess, apuch + 2 + i, APUREG_EFFECTS_ENV, 0x00f0); 989 wp_wrapu(ess, apuch + 2 + i, APUREG_AMPLITUDE, 0xe800); 990 wp_wrapu(ess, apuch + 2 + i, APUREG_POSITION, 0x8f00 991 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 992 | (PAN_FRONT << APU_PAN_SHIFT)); 993 wp_wrapu(ess, apuch + 2 + i, APUREG_ROUTE, 994 ROUTE_PARALLEL + i); 995 996 DPRINTF(ESM_DEBUG_DMA, 997 ("mixoffs=0x%x, wpwa=0x%x, offset=0x%x words, size=0x%lx words\n", 998 mixoffset, wpwa, offset, (unsigned long int)mixsize)); 999 1000 /* Assume we're going to loop to do the right channel. */ 1001 choffset += MAESTRO_RECBUF_L_SZ; 1002 mixoffset += MAESTRO_MIXBUF_SZ >> 1; 1003 } 1004 1005 wp_wrapu(ess, apuch, APUREG_APUTYPE, 1006 (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | 1007 APU_DMA_ENABLED | 0xf); 1008 if (nch > 1) 1009 wp_wrapu(ess, apuch + 1, APUREG_APUTYPE, 1010 (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | 1011 APU_DMA_ENABLED | 0xf); 1012 wp_wrapu(ess, apuch + 2, APUREG_APUTYPE, 1013 (APUTYPE_INPUTMIXER << APU_APUTYPE_SHIFT) | 1014 APU_DMA_ENABLED | 0xf); 1015 if (nch > 1) 1016 wp_wrapu(ess, apuch + 3, APUREG_APUTYPE, 1017 (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | 1018 APU_DMA_ENABLED | 0xf); 1019 1020 return 0; 1021 } 1022 1023 int 1024 esm_halt_output(void *sc) 1025 { 1026 struct esm_softc *ess; 1027 struct esm_chinfo *ch; 1028 1029 DPRINTF(ESM_DEBUG_PARAM, ("esm_halt_output(%p)\n", sc)); 1030 ess = sc; 1031 ch = &ess->pch; 1032 1033 wp_wrapu(ess, (ch->num << 1), APUREG_APUTYPE, 1034 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1035 wp_wrapu(ess, (ch->num << 1) + 1, APUREG_APUTYPE, 1036 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1037 1038 ess->pactive = 0; 1039 if (!ess->ractive) 1040 wp_stoptimer(ess); 1041 1042 return 0; 1043 } 1044 1045 int 1046 esm_halt_input(void *sc) 1047 { 1048 struct esm_softc *ess; 1049 struct esm_chinfo *ch; 1050 1051 DPRINTF(ESM_DEBUG_PARAM, ("esm_halt_input(%p)\n", sc)); 1052 ess = sc; 1053 ch = &ess->rch; 1054 1055 wp_wrapu(ess, (ch->num << 1), APUREG_APUTYPE, 1056 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1057 wp_wrapu(ess, (ch->num << 1) + 1, APUREG_APUTYPE, 1058 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1059 wp_wrapu(ess, (ch->num << 1) + 2, APUREG_APUTYPE, 1060 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1061 wp_wrapu(ess, (ch->num << 1) + 3, APUREG_APUTYPE, 1062 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1063 1064 ess->ractive = 0; 1065 if (!ess->pactive) 1066 wp_stoptimer(ess); 1067 1068 return 0; 1069 } 1070 1071 static inline u_int 1072 calc_timer_freq(struct esm_chinfo *ch) 1073 { 1074 u_int freq; 1075 1076 freq = (ch->sample_rate + ch->apublk - 1) / ch->apublk; 1077 1078 DPRINTF(ESM_DEBUG_TIMER, 1079 ("calc_timer_freq(%p): rate = %u, blk = 0x%x (0x%x): freq = %u\n", 1080 ch, ch->sample_rate, ch->apublk, ch->blocksize, freq)); 1081 1082 return freq; 1083 } 1084 1085 static void 1086 set_timer(struct esm_softc *ess) 1087 { 1088 unsigned freq, freq2; 1089 1090 freq = 0; 1091 if (ess->pactive) 1092 freq = calc_timer_freq(&ess->pch); 1093 1094 if (ess->ractive) { 1095 freq2 = calc_timer_freq(&ess->rch); 1096 if (freq2 > freq) 1097 freq = freq2; 1098 } 1099 1100 KASSERT(freq != 0); 1101 1102 for (; freq < MAESTRO_MINFREQ; freq <<= 1) 1103 continue; 1104 1105 if (freq > 0) 1106 wp_settimer(ess, freq); 1107 } 1108 1109 static void 1110 esmch_set_format(struct esm_chinfo *ch, const audio_params_t *p) 1111 { 1112 uint16_t wcreg_tpl; 1113 uint16_t aputype; 1114 1115 wcreg_tpl = (ch->base - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK; 1116 aputype = APUTYPE_16BITLINEAR; 1117 if (p->channels == 2) { 1118 wcreg_tpl |= WAVCACHE_CHCTL_STEREO; 1119 aputype++; 1120 } 1121 if (p->precision == 8) { 1122 aputype += 2; 1123 switch (p->encoding) { 1124 case AUDIO_ENCODING_ULINEAR: 1125 case AUDIO_ENCODING_ULINEAR_BE: 1126 case AUDIO_ENCODING_ULINEAR_LE: 1127 wcreg_tpl |= WAVCACHE_CHCTL_U8; 1128 break; 1129 } 1130 } 1131 ch->wcreg_tpl = wcreg_tpl; 1132 ch->aputype = aputype; 1133 ch->sample_rate = p->sample_rate; 1134 1135 DPRINTF(ESM_DEBUG_PARAM, ("esmch_set_format: " 1136 "numch=%u, prec=%u, tpl=0x%x, aputype=%d, rate=%u\n", 1137 p->channels, p->precision, wcreg_tpl, aputype, p->sample_rate)); 1138 } 1139 1140 /* 1141 * Since we can't record in true stereo, this function combines 1142 * the separately recorded left and right channels into the final 1143 * buffer for the upper layer. 1144 */ 1145 static void 1146 esmch_combine_input(struct esm_softc *ess, struct esm_chinfo *ch) 1147 { 1148 size_t offset, resid, count; 1149 uint32_t *dst32s; 1150 const uint32_t *left32s, *right32s; 1151 uint32_t left32, right32; 1152 1153 /* The current offset into the upper layer buffer. */ 1154 offset = ch->offset; 1155 1156 /* The number of bytes left to combine. */ 1157 resid = ch->blocksize; 1158 1159 while (resid > 0) { 1160 1161 /* The 32-bit words for the left channel. */ 1162 left32s = (const uint32_t *)((char *)ess->sc_dma.addr + 1163 MAESTRO_RECBUF_L_OFF + offset / 2); 1164 1165 /* The 32-bit words for the right channel. */ 1166 right32s = (const uint32_t *)((char *)ess->sc_dma.addr + 1167 MAESTRO_RECBUF_R_OFF + offset / 2); 1168 1169 /* The pointer to the 32-bit words we will write. */ 1170 dst32s = (uint32_t *)((char *)ch->buffer + offset); 1171 1172 /* Get the number of bytes we will combine now. */ 1173 count = ch->bufsize - offset; 1174 if (count > resid) 1175 count = resid; 1176 resid -= count; 1177 offset += count; 1178 if (offset == ch->bufsize) 1179 offset = 0; 1180 1181 /* Combine, writing two 32-bit words at a time. */ 1182 KASSERT((count & (sizeof(uint32_t) * 2 - 1)) == 0); 1183 count /= (sizeof(uint32_t) * 2); 1184 while (count > 0) { 1185 left32 = *(left32s++); 1186 right32 = *(right32s++); 1187 /* XXX this endian handling is half-baked at best */ 1188 #if BYTE_ORDER == LITTLE_ENDIAN 1189 *(dst32s++) = (left32 & 0xFFFF) | (right32 << 16); 1190 *(dst32s++) = (left32 >> 16) | (right32 & 0xFFFF0000); 1191 #else /* BYTE_ORDER == BIG_ENDIAN */ 1192 *(dst32s++) = (left32 & 0xFFFF0000) | (right32 >> 16); 1193 *(dst32s++) = (left32 << 16) | (right32 & 0xFFFF); 1194 #endif /* BYTE_ORDER == BIG_ENDIAN */ 1195 count--; 1196 } 1197 } 1198 1199 /* Update the offset. */ 1200 ch->offset = offset; 1201 } 1202 1203 /* 1204 * Audio interface glue functions 1205 */ 1206 1207 int 1208 esm_getdev (void *sc, struct audio_device *adp) 1209 { 1210 1211 *adp = esm_device; 1212 return 0; 1213 } 1214 1215 int 1216 esm_round_blocksize(void *sc, int blk, int mode, 1217 const audio_params_t *param) 1218 { 1219 1220 DPRINTF(ESM_DEBUG_PARAM, 1221 ("esm_round_blocksize(%p, 0x%x)", sc, blk)); 1222 1223 blk &= ~0x3f; /* keep good alignment */ 1224 1225 DPRINTF(ESM_DEBUG_PARAM, (" = 0x%x\n", blk)); 1226 1227 return blk; 1228 } 1229 1230 int 1231 esm_query_encoding(void *sc, struct audio_encoding *fp) 1232 { 1233 1234 DPRINTF(ESM_DEBUG_PARAM, 1235 ("esm_query_encoding(%p, %d)\n", sc, fp->index)); 1236 1237 if (fp->index < 0 || fp->index >= MAESTRO_NENCODINGS) 1238 return EINVAL; 1239 1240 *fp = esm_encoding[fp->index]; 1241 return 0; 1242 } 1243 1244 int 1245 esm_set_params(void *sc, int setmode, int usemode, 1246 audio_params_t *play, audio_params_t *rec, 1247 stream_filter_list_t *pfil, stream_filter_list_t *rfil) 1248 { 1249 struct esm_softc *ess; 1250 audio_params_t *p; 1251 const audio_params_t *hw_play, *hw_rec; 1252 stream_filter_list_t *fil; 1253 int mode, i; 1254 1255 DPRINTF(ESM_DEBUG_PARAM, 1256 ("esm_set_params(%p, 0x%x, 0x%x, %p, %p)\n", 1257 sc, setmode, usemode, play, rec)); 1258 ess = sc; 1259 hw_play = NULL; 1260 hw_rec = NULL; 1261 for (mode = AUMODE_RECORD; mode != -1; 1262 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 1263 if ((setmode & mode) == 0) 1264 continue; 1265 1266 p = mode == AUMODE_PLAY ? play : rec; 1267 1268 if (p->sample_rate < 4000 || p->sample_rate > 48000 || 1269 (p->precision != 8 && p->precision != 16) || 1270 (p->channels != 1 && p->channels != 2)) 1271 return EINVAL; 1272 1273 fil = mode == AUMODE_PLAY ? pfil : rfil; 1274 i = auconv_set_converter(esm_formats, ESM_NFORMATS, 1275 mode, p, FALSE, fil); 1276 if (i < 0) 1277 return EINVAL; 1278 if (fil->req_size > 0) 1279 p = &fil->filters[0].param; 1280 if (mode == AUMODE_PLAY) 1281 hw_play = p; 1282 else 1283 hw_rec = p; 1284 } 1285 1286 if (hw_play) 1287 esmch_set_format(&ess->pch, hw_play); 1288 1289 if (hw_rec) 1290 esmch_set_format(&ess->rch, hw_rec); 1291 1292 return 0; 1293 } 1294 1295 int 1296 esm_set_port(void *sc, mixer_ctrl_t *cp) 1297 { 1298 struct esm_softc *ess; 1299 1300 ess = sc; 1301 return ess->codec_if->vtbl->mixer_set_port(ess->codec_if, cp); 1302 } 1303 1304 int 1305 esm_get_port(void *sc, mixer_ctrl_t *cp) 1306 { 1307 struct esm_softc *ess; 1308 1309 ess = sc; 1310 return ess->codec_if->vtbl->mixer_get_port(ess->codec_if, cp); 1311 } 1312 1313 int 1314 esm_query_devinfo(void *sc, mixer_devinfo_t *dip) 1315 { 1316 struct esm_softc *ess; 1317 1318 ess = sc; 1319 return ess->codec_if->vtbl->query_devinfo(ess->codec_if, dip); 1320 } 1321 1322 void * 1323 esm_malloc(void *sc, int direction, size_t size, 1324 struct malloc_type *pool, int flags) 1325 { 1326 struct esm_softc *ess; 1327 int off; 1328 1329 DPRINTF(ESM_DEBUG_DMA, 1330 ("esm_malloc(%p, %d, 0x%lx, %p, 0x%x)", 1331 sc, direction, (unsigned long int)size, pool, flags)); 1332 ess = sc; 1333 /* 1334 * Each buffer can only be allocated once. 1335 */ 1336 if (ess->rings_alloced & direction) { 1337 DPRINTF(ESM_DEBUG_DMA, (" = 0 (ENOMEM)\n")); 1338 return 0; 1339 } 1340 1341 /* 1342 * Mark this buffer as allocated and return its 1343 * kernel virtual address. 1344 */ 1345 ess->rings_alloced |= direction; 1346 off = (direction == AUMODE_PLAY ? 1347 MAESTRO_PLAYBUF_OFF : MAESTRO_RECBUF_OFF); 1348 DPRINTF(ESM_DEBUG_DMA, (" = %p (DMAADDR 0x%x)\n", 1349 (char *)ess->sc_dma.addr + off, 1350 (int)DMAADDR(&ess->sc_dma) + off)); 1351 return (char *)ess->sc_dma.addr + off; 1352 } 1353 1354 void 1355 esm_free(void *sc, void *ptr, struct malloc_type *pool) 1356 { 1357 struct esm_softc *ess; 1358 1359 DPRINTF(ESM_DEBUG_DMA, 1360 ("esm_free(%p, %p, %p)\n", 1361 sc, ptr, pool)); 1362 ess = sc; 1363 if ((char *)ptr == (char *)ess->sc_dma.addr + MAESTRO_PLAYBUF_OFF) 1364 ess->rings_alloced &= ~AUMODE_PLAY; 1365 else if ((char *)ptr == (char *)ess->sc_dma.addr + MAESTRO_RECBUF_OFF) 1366 ess->rings_alloced &= ~AUMODE_RECORD; 1367 } 1368 1369 size_t 1370 esm_round_buffersize(void *sc, int direction, size_t size) 1371 { 1372 1373 if (size > MAESTRO_PLAYBUF_SZ) 1374 size = MAESTRO_PLAYBUF_SZ; 1375 if (size > MAESTRO_RECBUF_SZ) 1376 size = MAESTRO_RECBUF_SZ; 1377 return size; 1378 } 1379 1380 paddr_t 1381 esm_mappage(void *sc, void *mem, off_t off, int prot) 1382 { 1383 struct esm_softc *ess; 1384 1385 DPRINTF(ESM_DEBUG_DMA, 1386 ("esm_mappage(%p, %p, 0x%lx, 0x%x)\n", 1387 sc, mem, (unsigned long)off, prot)); 1388 ess = sc; 1389 if (off < 0) 1390 return -1; 1391 1392 if ((char *)mem == (char *)ess->sc_dma.addr + MAESTRO_PLAYBUF_OFF) 1393 off += MAESTRO_PLAYBUF_OFF; 1394 else if ((char *)mem == (char *)ess->sc_dma.addr + MAESTRO_RECBUF_OFF) 1395 off += MAESTRO_RECBUF_OFF; 1396 else 1397 return -1; 1398 return bus_dmamem_mmap(ess->dmat, ess->sc_dma.segs, ess->sc_dma.nsegs, 1399 off, prot, BUS_DMA_WAITOK); 1400 } 1401 1402 int 1403 esm_get_props(void *sc) 1404 { 1405 1406 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1407 } 1408 1409 1410 /* ----------------------------- 1411 * Bus space. 1412 */ 1413 1414 static int 1415 esm_intr(void *sc) 1416 { 1417 struct esm_softc *ess; 1418 uint16_t status; 1419 uint16_t pos; 1420 int ret; 1421 1422 ess = sc; 1423 ret = 0; 1424 status = bus_space_read_1(ess->st, ess->sh, PORT_HOSTINT_STAT); 1425 if (!status) 1426 return 0; 1427 1428 /* Acknowledge all. */ 1429 bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); 1430 bus_space_write_1(ess->st, ess->sh, PORT_HOSTINT_STAT, 0); 1431 #if 0 /* XXX - HWVOL */ 1432 if (status & HOSTINT_STAT_HWVOL) { 1433 u_int delta; 1434 delta = bus_space_read_1(ess->st, ess->sh, PORT_HWVOL_MASTER) 1435 - 0x88; 1436 if (delta & 0x11) 1437 mixer_set(device_get_softc(ess->dev), 1438 SOUND_MIXER_VOLUME, 0); 1439 else { 1440 mixer_set(device_get_softc(ess->dev), 1441 SOUND_MIXER_VOLUME, 1442 mixer_get(device_get_softc(ess->dev), 1443 SOUND_MIXER_VOLUME) 1444 + ((delta >> 5) & 0x7) - 4 1445 + ((delta << 7) & 0x700) - 0x400); 1446 } 1447 bus_space_write_1(ess->st, ess->sh, PORT_HWVOL_MASTER, 0x88); 1448 ret++; 1449 } 1450 #endif /* XXX - HWVOL */ 1451 1452 if (ess->pactive) { 1453 pos = wp_rdapu(ess, ess->pch.num << 1, APUREG_CURPTR); 1454 1455 DPRINTF(ESM_DEBUG_IRQ, (" %4.4x/%4.4x ", pos, 1456 wp_rdapu(ess, (ess->pch.num<<1)+1, APUREG_CURPTR))); 1457 1458 pos -= ess->pch.apubase; 1459 if (pos >= ess->pch.nextirq && 1460 pos - ess->pch.nextirq < ess->pch.apubuf / 2) { 1461 ess->pch.nextirq += ess->pch.apublk; 1462 1463 if (ess->pch.nextirq >= ess->pch.apubuf) 1464 ess->pch.nextirq = 0; 1465 1466 if (ess->sc_pintr) { 1467 DPRINTF(ESM_DEBUG_IRQ, ("P\n")); 1468 ess->sc_pintr(ess->sc_parg); 1469 } 1470 1471 } 1472 ret++; 1473 } 1474 1475 if (ess->ractive) { 1476 pos = wp_rdapu(ess, ess->rch.num << 1, APUREG_CURPTR); 1477 1478 DPRINTF(ESM_DEBUG_IRQ, (" %4.4x/%4.4x ", pos, 1479 wp_rdapu(ess, (ess->rch.num<<1)+1, APUREG_CURPTR))); 1480 1481 pos -= ess->rch.apubase; 1482 if (pos >= ess->rch.nextirq && 1483 pos - ess->rch.nextirq < ess->rch.apubuf / 2) { 1484 ess->rch.nextirq += ess->rch.apublk; 1485 1486 if (ess->rch.nextirq >= ess->rch.apubuf) 1487 ess->rch.nextirq = 0; 1488 1489 if (ess->sc_rintr) { 1490 DPRINTF(ESM_DEBUG_IRQ, ("R\n")); 1491 switch(ess->rch.aputype) { 1492 case APUTYPE_16BITSTEREO: 1493 esmch_combine_input(ess, &ess->rch); 1494 break; 1495 } 1496 ess->sc_rintr(ess->sc_rarg); 1497 } 1498 1499 } 1500 ret++; 1501 } 1502 1503 return ret; 1504 } 1505 1506 static void 1507 esm_freemem(struct esm_softc *sc, struct esm_dma *p) 1508 { 1509 if (p->size == 0) 1510 return; 1511 1512 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 1513 1514 bus_dmamem_unmap(sc->dmat, p->addr, p->size); 1515 1516 bus_dmamap_destroy(sc->dmat, p->map); 1517 1518 bus_dmamap_unload(sc->dmat, p->map); 1519 1520 p->size = 0; 1521 } 1522 1523 static int 1524 esm_allocmem(struct esm_softc *sc, size_t size, size_t align, 1525 struct esm_dma *p) 1526 { 1527 int error; 1528 1529 p->size = size; 1530 error = bus_dmamem_alloc(sc->dmat, p->size, align, 0, 1531 p->segs, __arraycount(p->segs), 1532 &p->nsegs, BUS_DMA_NOWAIT); 1533 if (error) 1534 return error; 1535 1536 error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size, 1537 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 1538 if (error) 1539 goto free; 1540 1541 error = bus_dmamap_create(sc->dmat, p->size, 1, p->size, 1542 0, BUS_DMA_NOWAIT, &p->map); 1543 if (error) 1544 goto unmap; 1545 1546 error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, NULL, 1547 BUS_DMA_NOWAIT); 1548 if (error) 1549 goto destroy; 1550 1551 return 0; 1552 1553 destroy: 1554 bus_dmamap_destroy(sc->dmat, p->map); 1555 unmap: 1556 bus_dmamem_unmap(sc->dmat, p->addr, p->size); 1557 free: 1558 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 1559 1560 p->size = 0; 1561 return error; 1562 } 1563 1564 static int 1565 esm_match(device_t dev, cfdata_t match, void *aux) 1566 { 1567 struct pci_attach_args *pa; 1568 1569 pa = (struct pci_attach_args *)aux; 1570 switch (PCI_VENDOR(pa->pa_id)) { 1571 case PCI_VENDOR_ESSTECH: 1572 switch (PCI_PRODUCT(pa->pa_id)) { 1573 case PCI_PRODUCT_ESSTECH_MAESTRO1: 1574 case PCI_PRODUCT_ESSTECH_MAESTRO2: 1575 case PCI_PRODUCT_ESSTECH_MAESTRO2E: 1576 return 1; 1577 } 1578 1579 case PCI_VENDOR_ESSTECH2: 1580 switch (PCI_PRODUCT(pa->pa_id)) { 1581 case PCI_PRODUCT_ESSTECH2_MAESTRO1: 1582 return 1; 1583 } 1584 } 1585 return 0; 1586 } 1587 1588 static void 1589 esm_attach(device_t parent, device_t self, void *aux) 1590 { 1591 char devinfo[256]; 1592 struct esm_softc *ess; 1593 struct pci_attach_args *pa; 1594 const char *intrstr; 1595 pci_chipset_tag_t pc; 1596 pcitag_t tag; 1597 pci_intr_handle_t ih; 1598 pcireg_t csr, data; 1599 int revision; 1600 uint16_t codec_data; 1601 uint16_t pcmbar; 1602 int error; 1603 1604 ess = device_private(self); 1605 ess->sc_dev = self; 1606 pa = (struct pci_attach_args *)aux; 1607 pc = pa->pa_pc; 1608 tag = pa->pa_tag; 1609 aprint_naive(": Audio controller\n"); 1610 1611 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 1612 revision = PCI_REVISION(pa->pa_class); 1613 aprint_normal(": %s (rev. 0x%02x)\n", devinfo, revision); 1614 1615 /* Enable the device. */ 1616 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 1617 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, 1618 csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE); 1619 1620 /* Map I/O register */ 1621 if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, 1622 &ess->st, &ess->sh, NULL, &ess->sz)) { 1623 aprint_error_dev(ess->sc_dev, "can't map i/o space\n"); 1624 return; 1625 } 1626 1627 /* Initialize softc */ 1628 ess->pch.num = 0; 1629 ess->rch.num = 1; 1630 ess->dmat = pa->pa_dmat; 1631 ess->tag = tag; 1632 ess->pc = pc; 1633 ess->subid = pci_conf_read(pc, tag, PCI_SUBSYS_ID_REG); 1634 1635 DPRINTF(ESM_DEBUG_PCI, 1636 ("%s: sub-system vendor 0x%4.4x, product 0x%4.4x\n", 1637 device_xname(ess->sc_dev), 1638 PCI_VENDOR(ess->subid), PCI_PRODUCT(ess->subid))); 1639 1640 /* Map and establish the interrupt. */ 1641 if (pci_intr_map(pa, &ih)) { 1642 aprint_error_dev(ess->sc_dev, "can't map interrupt\n"); 1643 return; 1644 } 1645 intrstr = pci_intr_string(pc, ih); 1646 ess->ih = pci_intr_establish(pc, ih, IPL_AUDIO, esm_intr, self); 1647 if (ess->ih == NULL) { 1648 aprint_error_dev(ess->sc_dev, "can't establish interrupt"); 1649 if (intrstr != NULL) 1650 aprint_error(" at %s", intrstr); 1651 aprint_error("\n"); 1652 return; 1653 } 1654 aprint_normal_dev(ess->sc_dev, "interrupting at %s\n", 1655 intrstr); 1656 1657 /* 1658 * Setup PCI config registers 1659 */ 1660 1661 /* power up chip */ 1662 if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, 1663 pci_activate_null)) && error != EOPNOTSUPP) { 1664 aprint_error_dev(ess->sc_dev, "cannot activate %d\n", 1665 error); 1666 return; 1667 } 1668 delay(100000); 1669 1670 /* Disable all legacy emulations. */ 1671 data = pci_conf_read(pc, tag, CONF_LEGACY); 1672 pci_conf_write(pc, tag, CONF_LEGACY, data | LEGACY_DISABLED); 1673 1674 /* Disconnect from CHI. (Makes Dell inspiron 7500 work?) 1675 * Enable posted write. 1676 * Prefer PCI timing rather than that of ISA. 1677 * Don't swap L/R. */ 1678 data = pci_conf_read(pc, tag, CONF_MAESTRO); 1679 data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING; 1680 data &= ~MAESTRO_SWAP_LR; 1681 pci_conf_write(pc, tag, CONF_MAESTRO, data); 1682 1683 /* initialize sound chip */ 1684 esm_init(ess); 1685 1686 esm_read_codec(ess, 0, &codec_data); 1687 if (codec_data == 0x80) { 1688 aprint_error_dev(ess->sc_dev, "PT101 codec detected!\n"); 1689 return; 1690 } 1691 1692 /* 1693 * Some cards and Notebooks appear to have left and right channels 1694 * reversed. Check if there is a corresponding quirk entry for 1695 * the subsystem vendor and product and if so, set the appropriate 1696 * codec flag. 1697 */ 1698 if (esm_get_quirks(ess->subid) & ESM_QUIRKF_SWAPPEDCH) { 1699 ess->codec_flags |= AC97_HOST_SWAPPED_CHANNELS; 1700 } 1701 ess->codec_flags |= AC97_HOST_DONT_READ; 1702 1703 /* initialize AC97 host interface */ 1704 ess->host_if.arg = self; 1705 ess->host_if.attach = esm_attach_codec; 1706 ess->host_if.read = esm_read_codec; 1707 ess->host_if.write = esm_write_codec; 1708 ess->host_if.reset = esm_reset_codec; 1709 ess->host_if.flags = esm_flags_codec; 1710 1711 if (ac97_attach(&ess->host_if, self) != 0) 1712 return; 1713 1714 /* allocate our DMA region */ 1715 if (esm_allocmem(ess, MAESTRO_DMA_SZ, MAESTRO_DMA_ALIGN, 1716 &ess->sc_dma)) { 1717 aprint_error_dev(ess->sc_dev, "couldn't allocate memory!\n"); 1718 return; 1719 } 1720 ess->rings_alloced = 0; 1721 1722 /* set DMA base address */ 1723 for (pcmbar = WAVCACHE_PCMBAR; pcmbar < WAVCACHE_PCMBAR + 4; pcmbar++) 1724 wc_wrreg(ess, pcmbar, 1725 DMAADDR(&ess->sc_dma) >> WAVCACHE_BASEADDR_SHIFT); 1726 1727 audio_attach_mi(&esm_hw_if, self, ess->sc_dev); 1728 1729 if (!pmf_device_register(self, esm_suspend, esm_resume)) 1730 aprint_error_dev(self, "couldn't establish power handler\n"); 1731 } 1732 1733 static void 1734 esm_childdet(device_t self, device_t child) 1735 { 1736 /* we hold no child references, so do nothing */ 1737 } 1738 1739 static int 1740 esm_detach(device_t self, int flags) 1741 { 1742 int rc; 1743 struct esm_softc *ess = device_private(self); 1744 1745 pmf_device_deregister(self); 1746 1747 if ((rc = config_detach_children(self, flags)) != 0) 1748 return rc; 1749 1750 /* free our DMA region */ 1751 esm_freemem(ess, &ess->sc_dma); 1752 1753 if (ess->codec_if != NULL) 1754 ess->codec_if->vtbl->detach(ess->codec_if); 1755 1756 /* XXX Restore CONF_MAESTRO? */ 1757 /* XXX Restore legacy emulations? */ 1758 /* XXX Restore PCI config registers? */ 1759 1760 if (ess->ih != NULL) 1761 pci_intr_disestablish(ess->pc, ess->ih); 1762 1763 bus_space_unmap(ess->st, ess->sh, ess->sz); 1764 1765 return 0; 1766 } 1767 1768 static bool 1769 esm_suspend(device_t dv, const pmf_qual_t *qual) 1770 { 1771 struct esm_softc *ess = device_private(dv); 1772 int x; 1773 1774 x = splaudio(); 1775 wp_stoptimer(ess); 1776 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 1777 1778 esm_halt_output(ess); 1779 esm_halt_input(ess); 1780 splx(x); 1781 1782 /* Power down everything except clock. */ 1783 esm_write_codec(ess, AC97_REG_POWER, 0xdf00); 1784 delay(20); 1785 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 1786 delay(1); 1787 1788 return true; 1789 } 1790 1791 static bool 1792 esm_resume(device_t dv, const pmf_qual_t *qual) 1793 { 1794 struct esm_softc *ess = device_private(dv); 1795 int x; 1796 uint16_t pcmbar; 1797 1798 delay(100000); 1799 esm_init(ess); 1800 1801 /* set DMA base address */ 1802 for (pcmbar = WAVCACHE_PCMBAR; pcmbar < WAVCACHE_PCMBAR + 4; pcmbar++) 1803 wc_wrreg(ess, pcmbar, 1804 DMAADDR(&ess->sc_dma) >> WAVCACHE_BASEADDR_SHIFT); 1805 1806 ess->codec_if->vtbl->restore_ports(ess->codec_if); 1807 #if 0 1808 if (mixer_reinit(dev)) { 1809 printf("%s: unable to reinitialize the mixer\n", 1810 device_xname(ess->sc_dev)); 1811 return ENXIO; 1812 } 1813 #endif 1814 1815 x = splaudio(); 1816 #if TODO 1817 if (ess->pactive) 1818 esm_start_output(ess); 1819 if (ess->ractive) 1820 esm_start_input(ess); 1821 #endif 1822 if (ess->pactive || ess->ractive) { 1823 set_timer(ess); 1824 wp_starttimer(ess); 1825 } 1826 splx(x); 1827 1828 return true; 1829 } 1830