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