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