1 /* $NetBSD: ym.c,v 1.35 2008/04/28 20:23:52 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 1999-2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by ITOH Yasufumi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1998 Constantine Sapuntzakis. All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. The name of the author may not be used to endorse or promote products 44 * derived from this software without specific prior written permission. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 */ 57 58 /* 59 * Original code from OpenBSD. 60 */ 61 62 #include <sys/cdefs.h> 63 __KERNEL_RCSID(0, "$NetBSD: ym.c,v 1.35 2008/04/28 20:23:52 martin Exp $"); 64 65 #include "mpu_ym.h" 66 #include "opt_ym.h" 67 68 #include <sys/param.h> 69 #include <sys/systm.h> 70 #include <sys/errno.h> 71 #include <sys/device.h> 72 #include <sys/fcntl.h> 73 #include <sys/kernel.h> 74 #include <sys/proc.h> 75 76 #include <sys/cpu.h> 77 #include <sys/intr.h> 78 #include <sys/bus.h> 79 80 #include <sys/audioio.h> 81 #include <dev/audio_if.h> 82 83 #include <dev/isa/isavar.h> 84 #include <dev/isa/isadmavar.h> 85 86 #include <dev/ic/ad1848reg.h> 87 #include <dev/isa/ad1848var.h> 88 #include <dev/ic/opl3sa3reg.h> 89 #include <dev/isa/wssreg.h> 90 #if NMPU_YM > 0 91 #include <dev/ic/mpuvar.h> 92 #endif 93 #include <dev/isa/ymvar.h> 94 #include <dev/isa/sbreg.h> 95 96 /* Power management mode. */ 97 #ifndef YM_POWER_MODE 98 #define YM_POWER_MODE YM_POWER_POWERSAVE 99 #endif 100 101 /* Time in second before power down the chip. */ 102 #ifndef YM_POWER_OFF_SEC 103 #define YM_POWER_OFF_SEC 5 104 #endif 105 106 /* Default mixer settings. */ 107 #ifndef YM_VOL_MASTER 108 #define YM_VOL_MASTER 208 109 #endif 110 111 #ifndef YM_VOL_DAC 112 #define YM_VOL_DAC 224 113 #endif 114 115 #ifndef YM_VOL_OPL3 116 #define YM_VOL_OPL3 184 117 #endif 118 119 /* 120 * Default position of the equalizer. 121 */ 122 #ifndef YM_DEFAULT_TREBLE 123 #define YM_DEFAULT_TREBLE YM_EQ_FLAT_OFFSET 124 #endif 125 #ifndef YM_DEFAULT_BASS 126 #define YM_DEFAULT_BASS YM_EQ_FLAT_OFFSET 127 #endif 128 129 #ifdef __i386__ /* XXX */ 130 # include "joy.h" 131 #else 132 # define NJOY 0 133 #endif 134 135 #ifdef AUDIO_DEBUG 136 #define DPRINTF(x) if (ymdebug) printf x 137 int ymdebug = 0; 138 #else 139 #define DPRINTF(x) 140 #endif 141 #define DVNAME(softc) (device_xname(&(softc)->sc_ad1848.sc_ad1848.sc_dev)) 142 143 int ym_getdev(void *, struct audio_device *); 144 int ym_mixer_set_port(void *, mixer_ctrl_t *); 145 int ym_mixer_get_port(void *, mixer_ctrl_t *); 146 int ym_query_devinfo(void *, mixer_devinfo_t *); 147 int ym_intr(void *); 148 #ifndef AUDIO_NO_POWER_CTL 149 static void ym_save_codec_regs(struct ym_softc *); 150 static void ym_restore_codec_regs(struct ym_softc *); 151 void ym_power_hook(int, void *); 152 int ym_codec_power_ctl(void *, int); 153 static void ym_chip_powerdown(struct ym_softc *); 154 static void ym_chip_powerup(struct ym_softc *, int); 155 void ym_powerdown_blocks(void *); 156 void ym_power_ctl(struct ym_softc *, int, int); 157 #endif 158 159 static void ym_init(struct ym_softc *); 160 static void ym_mute(struct ym_softc *, int, int); 161 static void ym_set_master_gain(struct ym_softc *, struct ad1848_volume*); 162 static void ym_hvol_to_master_gain(struct ym_softc *); 163 static void ym_set_mic_gain(struct ym_softc *, int); 164 static void ym_set_3d(struct ym_softc *, mixer_ctrl_t *, 165 struct ad1848_volume *, int); 166 167 168 const struct audio_hw_if ym_hw_if = { 169 ad1848_isa_open, 170 ad1848_isa_close, 171 NULL, 172 ad1848_query_encoding, 173 ad1848_set_params, 174 ad1848_round_blocksize, 175 ad1848_commit_settings, 176 NULL, 177 NULL, 178 NULL, 179 NULL, 180 ad1848_isa_halt_output, 181 ad1848_isa_halt_input, 182 NULL, 183 ym_getdev, 184 NULL, 185 ym_mixer_set_port, 186 ym_mixer_get_port, 187 ym_query_devinfo, 188 ad1848_isa_malloc, 189 ad1848_isa_free, 190 ad1848_isa_round_buffersize, 191 ad1848_isa_mappage, 192 ad1848_isa_get_props, 193 ad1848_isa_trigger_output, 194 ad1848_isa_trigger_input, 195 NULL, 196 NULL, /* powerstate */ 197 }; 198 199 static inline int ym_read(struct ym_softc *, int); 200 static inline void ym_write(struct ym_softc *, int, int); 201 202 void 203 ym_attach(struct ym_softc *sc) 204 { 205 static struct ad1848_volume vol_master = {YM_VOL_MASTER, YM_VOL_MASTER}; 206 static struct ad1848_volume vol_dac = {YM_VOL_DAC, YM_VOL_DAC}; 207 static struct ad1848_volume vol_opl3 = {YM_VOL_OPL3, YM_VOL_OPL3}; 208 struct ad1848_softc *ac; 209 mixer_ctrl_t mctl; 210 struct audio_attach_args arg; 211 212 ac = &sc->sc_ad1848.sc_ad1848; 213 callout_init(&sc->sc_powerdown_ch, 0); 214 215 /* Mute the output to reduce noise during initialization. */ 216 ym_mute(sc, SA3_VOL_L, 1); 217 ym_mute(sc, SA3_VOL_R, 1); 218 219 sc->sc_version = ym_read(sc, SA3_MISC) & SA3_MISC_VER; 220 ac->chip_name = YM_IS_SA3(sc) ? "OPL3-SA3" : "OPL3-SA2"; 221 222 sc->sc_ad1848.sc_ih = isa_intr_establish(sc->sc_ic, sc->ym_irq, 223 IST_EDGE, IPL_AUDIO, ym_intr, sc); 224 225 #ifndef AUDIO_NO_POWER_CTL 226 sc->sc_ad1848.powerctl = ym_codec_power_ctl; 227 sc->sc_ad1848.powerarg = sc; 228 #endif 229 ad1848_isa_attach(&sc->sc_ad1848); 230 printf("\n"); 231 ac->parent = sc; 232 233 /* Establish chip in well known mode */ 234 ym_set_master_gain(sc, &vol_master); 235 ym_set_mic_gain(sc, 0); 236 sc->master_mute = 0; 237 238 /* Override ad1848 settings. */ 239 ad1848_set_channel_gain(ac, AD1848_DAC_CHANNEL, &vol_dac); 240 ad1848_set_channel_gain(ac, AD1848_AUX2_CHANNEL, &vol_opl3); 241 242 /* 243 * Mute all external sources. If you change this, you must 244 * also change the initial value of sc->sc_external_sources 245 * (currently 0 --- no external source is active). 246 */ 247 sc->mic_mute = 1; 248 ym_mute(sc, SA3_MIC_VOL, sc->mic_mute); 249 ad1848_mute_channel(ac, AD1848_AUX1_CHANNEL, MUTE_ALL); /* CD */ 250 ad1848_mute_channel(ac, AD1848_LINE_CHANNEL, MUTE_ALL); /* line */ 251 ac->mute[AD1848_AUX1_CHANNEL] = MUTE_ALL; 252 ac->mute[AD1848_LINE_CHANNEL] = MUTE_ALL; 253 /* speaker is muted by default */ 254 255 /* We use only one IRQ (IRQ-A). */ 256 ym_write(sc, SA3_IRQ_CONF, SA3_IRQ_CONF_MPU_A | SA3_IRQ_CONF_WSS_A); 257 ym_write(sc, SA3_HVOL_INTR_CNF, SA3_HVOL_INTR_CNF_A); 258 259 /* audio at ym attachment */ 260 sc->sc_audiodev = audio_attach_mi(&ym_hw_if, ac, &ac->sc_dev); 261 262 /* opl at ym attachment */ 263 if (sc->sc_opl_ioh) { 264 arg.type = AUDIODEV_TYPE_OPL; 265 arg.hwif = 0; 266 arg.hdl = 0; 267 (void)config_found(&ac->sc_dev, &arg, audioprint); 268 } 269 270 #if NMPU_YM > 0 271 /* mpu at ym attachment */ 272 if (sc->sc_mpu_ioh) { 273 arg.type = AUDIODEV_TYPE_MPU; 274 arg.hwif = 0; 275 arg.hdl = 0; 276 sc->sc_mpudev = config_found(&ac->sc_dev, &arg, audioprint); 277 } 278 #endif 279 280 /* This must be AFTER the attachment of sub-devices. */ 281 ym_init(sc); 282 283 #ifndef AUDIO_NO_POWER_CTL 284 /* 285 * Initialize power control. 286 */ 287 sc->sc_pow_mode = YM_POWER_MODE; 288 sc->sc_pow_timeout = YM_POWER_OFF_SEC; 289 290 sc->sc_on_blocks = sc->sc_turning_off = 291 YM_POWER_CODEC_P | YM_POWER_CODEC_R | 292 YM_POWER_OPL3 | YM_POWER_MPU401 | YM_POWER_3D | 293 YM_POWER_CODEC_DA | YM_POWER_CODEC_AD | YM_POWER_OPL3_DA; 294 #if NJOY > 0 295 sc->sc_on_blocks |= YM_POWER_JOYSTICK; /* prevents chip powerdown */ 296 #endif 297 ym_powerdown_blocks(sc); 298 299 powerhook_establish(DVNAME(sc), ym_power_hook, sc); 300 #endif 301 302 /* Set tone control to the default position. */ 303 mctl.un.value.num_channels = 1; 304 mctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = YM_DEFAULT_TREBLE; 305 mctl.dev = YM_MASTER_TREBLE; 306 ym_mixer_set_port(sc, &mctl); 307 mctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = YM_DEFAULT_BASS; 308 mctl.dev = YM_MASTER_BASS; 309 ym_mixer_set_port(sc, &mctl); 310 311 /* Unmute the output now if the chip is on. */ 312 #ifndef AUDIO_NO_POWER_CTL 313 if (sc->sc_on_blocks & YM_POWER_ACTIVE) 314 #endif 315 { 316 ym_mute(sc, SA3_VOL_L, sc->master_mute); 317 ym_mute(sc, SA3_VOL_R, sc->master_mute); 318 } 319 } 320 321 static inline int 322 ym_read(struct ym_softc *sc, int reg) 323 { 324 325 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 326 SA3_CTL_INDEX, (reg & 0xff)); 327 return bus_space_read_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_DATA); 328 } 329 330 static inline void 331 ym_write(struct ym_softc *sc, int reg, int data) 332 { 333 334 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 335 SA3_CTL_INDEX, (reg & 0xff)); 336 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 337 SA3_CTL_DATA, (data & 0xff)); 338 } 339 340 static void 341 ym_init(struct ym_softc *sc) 342 { 343 uint8_t dpd, apd; 344 345 /* Mute SoundBlaster output if possible. */ 346 if (sc->sc_sb_ioh) { 347 bus_space_write_1(sc->sc_iot, sc->sc_sb_ioh, SBP_MIXER_ADDR, 348 SBP_MASTER_VOL); 349 bus_space_write_1(sc->sc_iot, sc->sc_sb_ioh, SBP_MIXER_DATA, 350 0x00); 351 } 352 353 if (!YM_IS_SA3(sc)) { 354 /* OPL3-SA2 */ 355 ym_write(sc, SA3_PWR_MNG, SA2_PWR_MNG_CLKO | 356 (sc->sc_opl_ioh == 0 ? SA2_PWR_MNG_FMPS : 0)); 357 return; 358 } 359 360 /* OPL3-SA3 */ 361 /* Figure out which part can be power down. */ 362 dpd = SA3_DPWRDWN_SB /* we never use SB */ 363 #if NMPU_YM > 0 364 | (sc->sc_mpu_ioh ? 0 : SA3_DPWRDWN_MPU) 365 #else 366 | SA3_DPWRDWN_MPU 367 #endif 368 #if NJOY == 0 369 | SA3_DPWRDWN_JOY 370 #endif 371 | SA3_DPWRDWN_PNP /* ISA Plug and Play is done */ 372 /* 373 * The master clock is for external wavetable synthesizer 374 * OPL4-ML (YMF704) or OPL4-ML2 (YMF721), 375 * and is currently unused. 376 */ 377 | SA3_DPWRDWN_MCLKO; 378 379 apd = SA3_APWRDWN_SBDAC; /* we never use SB */ 380 381 /* Power down OPL3 if not attached. */ 382 if (sc->sc_opl_ioh == 0) { 383 dpd |= SA3_DPWRDWN_FM; 384 apd |= SA3_APWRDWN_FMDAC; 385 } 386 /* CODEC is always attached. */ 387 388 /* Power down unused digital parts. */ 389 ym_write(sc, SA3_DPWRDWN, dpd); 390 391 /* Power down unused analog parts. */ 392 ym_write(sc, SA3_APWRDWN, apd); 393 } 394 395 396 int 397 ym_getdev(void *addr, struct audio_device *retp) 398 { 399 struct ym_softc *sc; 400 struct ad1848_softc *ac; 401 402 sc = addr; 403 ac = &sc->sc_ad1848.sc_ad1848; 404 strlcpy(retp->name, ac->chip_name, sizeof(retp->name)); 405 snprintf(retp->version, sizeof(retp->version), "%d", sc->sc_version); 406 strlcpy(retp->config, "ym", sizeof(retp->config)); 407 408 return 0; 409 } 410 411 412 static ad1848_devmap_t mappings[] = { 413 { YM_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL }, 414 { YM_MIDI_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL }, 415 { YM_CD_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL }, 416 { YM_LINE_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL }, 417 { YM_SPEAKER_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL }, 418 { YM_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL }, 419 { YM_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL }, 420 { YM_MIDI_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL }, 421 { YM_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL }, 422 { YM_LINE_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL }, 423 { YM_SPEAKER_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL }, 424 { YM_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL }, 425 { YM_REC_LVL, AD1848_KIND_RECORDGAIN, -1 }, 426 { YM_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1} 427 }; 428 429 #define NUMMAP (sizeof(mappings) / sizeof(mappings[0])) 430 431 432 static void 433 ym_mute(struct ym_softc *sc, int left_reg, int mute) 434 { 435 uint8_t reg; 436 437 reg = ym_read(sc, left_reg); 438 if (mute) 439 ym_write(sc, left_reg, reg | 0x80); 440 else 441 ym_write(sc, left_reg, reg & ~0x80); 442 } 443 444 445 static void 446 ym_set_master_gain(struct ym_softc *sc, struct ad1848_volume *vol) 447 { 448 u_int atten; 449 450 sc->master_gain = *vol; 451 452 atten = ((AUDIO_MAX_GAIN - vol->left) * (SA3_VOL_MV + 1)) / 453 (AUDIO_MAX_GAIN + 1); 454 455 ym_write(sc, SA3_VOL_L, (ym_read(sc, SA3_VOL_L) & ~SA3_VOL_MV) | atten); 456 457 atten = ((AUDIO_MAX_GAIN - vol->right) * (SA3_VOL_MV + 1)) / 458 (AUDIO_MAX_GAIN + 1); 459 460 ym_write(sc, SA3_VOL_R, (ym_read(sc, SA3_VOL_R) & ~SA3_VOL_MV) | atten); 461 } 462 463 /* 464 * Read current setting of master volume from hardware 465 * and update the software value if changed. 466 * [SA3] This function clears hardware volume interrupt. 467 */ 468 static void 469 ym_hvol_to_master_gain(struct ym_softc *sc) 470 { 471 u_int prevval, val; 472 int changed; 473 474 changed = 0; 475 val = SA3_VOL_MV & ~ym_read(sc, SA3_VOL_L); 476 prevval = (sc->master_gain.left * (SA3_VOL_MV + 1)) / 477 (AUDIO_MAX_GAIN + 1); 478 if (val != prevval) { 479 sc->master_gain.left = 480 val * ((AUDIO_MAX_GAIN + 1) / (SA3_VOL_MV + 1)); 481 changed = 1; 482 } 483 484 val = SA3_VOL_MV & ~ym_read(sc, SA3_VOL_R); 485 prevval = (sc->master_gain.right * (SA3_VOL_MV + 1)) / 486 (AUDIO_MAX_GAIN + 1); 487 if (val != prevval) { 488 sc->master_gain.right = 489 val * ((AUDIO_MAX_GAIN + 1) / (SA3_VOL_MV + 1)); 490 changed = 1; 491 } 492 493 #if 0 /* XXX NOT YET */ 494 /* Notify the change to async processes. */ 495 if (changed && sc->sc_audiodev) 496 mixer_signal(sc->sc_audiodev); 497 #endif 498 } 499 500 static void 501 ym_set_mic_gain(struct ym_softc *sc, int vol) 502 { 503 u_int atten; 504 505 sc->mic_gain = vol; 506 507 atten = ((AUDIO_MAX_GAIN - vol) * (SA3_MIC_MCV + 1)) / 508 (AUDIO_MAX_GAIN + 1); 509 510 ym_write(sc, SA3_MIC_VOL, 511 (ym_read(sc, SA3_MIC_VOL) & ~SA3_MIC_MCV) | atten); 512 } 513 514 static void 515 ym_set_3d(struct ym_softc *sc, mixer_ctrl_t *cp, 516 struct ad1848_volume *val, int reg) 517 { 518 uint8_t l, r, e; 519 520 ad1848_to_vol(cp, val); 521 522 l = val->left; 523 r = val->right; 524 if (reg != SA3_3D_WIDE) { 525 /* flat on center */ 526 l = YM_EQ_EXPAND_VALUE(l); 527 r = YM_EQ_EXPAND_VALUE(r); 528 } 529 530 e = (l * (SA3_3D_BITS + 1) + (SA3_3D_BITS + 1) / 2) / 531 (AUDIO_MAX_GAIN + 1) << SA3_3D_LSHIFT | 532 (r * (SA3_3D_BITS + 1) + (SA3_3D_BITS + 1) / 2) / 533 (AUDIO_MAX_GAIN + 1) << SA3_3D_RSHIFT; 534 535 #ifndef AUDIO_NO_POWER_CTL 536 /* turn wide stereo on if necessary */ 537 if (e) 538 ym_power_ctl(sc, YM_POWER_3D, 1); 539 #endif 540 541 ym_write(sc, reg, e); 542 543 #ifndef AUDIO_NO_POWER_CTL 544 /* turn wide stereo off if necessary */ 545 if (YM_EQ_OFF(&sc->sc_treble) && YM_EQ_OFF(&sc->sc_bass) && 546 YM_WIDE_OFF(&sc->sc_wide)) 547 ym_power_ctl(sc, YM_POWER_3D, 0); 548 #endif 549 } 550 551 int 552 ym_mixer_set_port(void *addr, mixer_ctrl_t *cp) 553 { 554 struct ad1848_softc *ac; 555 struct ym_softc *sc; 556 struct ad1848_volume vol; 557 int error; 558 uint8_t extsources; 559 560 ac = addr; 561 sc = ac->parent; 562 error = 0; 563 DPRINTF(("%s: ym_mixer_set_port: dev 0x%x, type 0x%x, 0x%x (%d; %d, %d)\n", 564 DVNAME(sc), cp->dev, cp->type, cp->un.ord, 565 cp->un.value.num_channels, cp->un.value.level[0], 566 cp->un.value.level[1])); 567 568 /* SA2 doesn't have equalizer */ 569 if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(cp->dev)) 570 return ENXIO; 571 572 #ifndef AUDIO_NO_POWER_CTL 573 /* Power-up chip */ 574 ym_power_ctl(sc, YM_POWER_CODEC_CTL, 1); 575 #endif 576 577 switch (cp->dev) { 578 case YM_OUTPUT_LVL: 579 ad1848_to_vol(cp, &vol); 580 ym_set_master_gain(sc, &vol); 581 goto out; 582 583 case YM_OUTPUT_MUTE: 584 sc->master_mute = (cp->un.ord != 0); 585 ym_mute(sc, SA3_VOL_L, sc->master_mute); 586 ym_mute(sc, SA3_VOL_R, sc->master_mute); 587 goto out; 588 589 case YM_MIC_LVL: 590 if (cp->un.value.num_channels != 1) 591 error = EINVAL; 592 else 593 ym_set_mic_gain(sc, 594 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]); 595 goto out; 596 597 case YM_MASTER_EQMODE: 598 sc->sc_eqmode = cp->un.ord & SA3_SYS_CTL_YMODE; 599 ym_write(sc, SA3_SYS_CTL, (ym_read(sc, SA3_SYS_CTL) & 600 ~SA3_SYS_CTL_YMODE) | sc->sc_eqmode); 601 goto out; 602 603 case YM_MASTER_TREBLE: 604 ym_set_3d(sc, cp, &sc->sc_treble, SA3_3D_TREBLE); 605 goto out; 606 607 case YM_MASTER_BASS: 608 ym_set_3d(sc, cp, &sc->sc_bass, SA3_3D_BASS); 609 goto out; 610 611 case YM_MASTER_WIDE: 612 ym_set_3d(sc, cp, &sc->sc_wide, SA3_3D_WIDE); 613 goto out; 614 615 #ifndef AUDIO_NO_POWER_CTL 616 case YM_PWR_MODE: 617 if ((unsigned) cp->un.ord > YM_POWER_NOSAVE) 618 error = EINVAL; 619 else 620 sc->sc_pow_mode = cp->un.ord; 621 goto out; 622 623 case YM_PWR_TIMEOUT: 624 if (cp->un.value.num_channels != 1) 625 error = EINVAL; 626 else 627 sc->sc_pow_timeout = 628 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 629 goto out; 630 631 /* 632 * Needs power-up to hear external sources. 633 */ 634 case YM_CD_MUTE: 635 case YM_LINE_MUTE: 636 case YM_SPEAKER_MUTE: 637 case YM_MIC_MUTE: 638 extsources = YM_MIXER_TO_XS(cp->dev); 639 if (cp->un.ord) { 640 if ((sc->sc_external_sources &= ~extsources) == 0) { 641 /* 642 * All the external sources are muted 643 * --- no need to keep the chip on. 644 */ 645 ym_power_ctl(sc, YM_POWER_EXT_SRC, 0); 646 DPRINTF(("%s: ym_mixer_set_port: off for ext\n", 647 DVNAME(sc))); 648 } 649 } else { 650 /* mute off - power-up the chip */ 651 sc->sc_external_sources |= extsources; 652 ym_power_ctl(sc, YM_POWER_EXT_SRC, 1); 653 DPRINTF(("%s: ym_mixer_set_port: on for ext\n", 654 DVNAME(sc))); 655 } 656 break; /* fall to ad1848_mixer_set_port() */ 657 658 /* 659 * Power on/off the playback part for monitoring. 660 */ 661 case YM_MONITOR_MUTE: 662 if ((ac->open_mode & (FREAD | FWRITE)) == FREAD) 663 ym_power_ctl(sc, YM_POWER_CODEC_P | YM_POWER_CODEC_DA, 664 cp->un.ord == 0); 665 break; /* fall to ad1848_mixer_set_port() */ 666 #endif 667 } 668 669 error = ad1848_mixer_set_port(ac, mappings, NUMMAP, cp); 670 671 if (error != ENXIO) 672 goto out; 673 674 error = 0; 675 676 switch (cp->dev) { 677 case YM_MIC_MUTE: 678 sc->mic_mute = (cp->un.ord != 0); 679 ym_mute(sc, SA3_MIC_VOL, sc->mic_mute); 680 break; 681 682 default: 683 error = ENXIO; 684 break; 685 } 686 687 out: 688 #ifndef AUDIO_NO_POWER_CTL 689 /* Power-down chip */ 690 ym_power_ctl(sc, YM_POWER_CODEC_CTL, 0); 691 #endif 692 693 return error; 694 } 695 696 int 697 ym_mixer_get_port(void *addr, mixer_ctrl_t *cp) 698 { 699 struct ad1848_softc *ac; 700 struct ym_softc *sc; 701 int error; 702 703 ac = addr; 704 sc = ac->parent; 705 /* SA2 doesn't have equalizer */ 706 if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(cp->dev)) 707 return ENXIO; 708 709 switch (cp->dev) { 710 case YM_OUTPUT_LVL: 711 if (!YM_IS_SA3(sc)) { 712 /* 713 * SA2 doesn't have hardware volume interrupt. 714 * Read current value and update every time. 715 */ 716 #ifndef AUDIO_NO_POWER_CTL 717 /* Power-up chip */ 718 ym_power_ctl(sc, YM_POWER_CODEC_CTL, 1); 719 #endif 720 ym_hvol_to_master_gain(sc); 721 #ifndef AUDIO_NO_POWER_CTL 722 /* Power-down chip */ 723 ym_power_ctl(sc, YM_POWER_CODEC_CTL, 0); 724 #endif 725 } 726 ad1848_from_vol(cp, &sc->master_gain); 727 return 0; 728 729 case YM_OUTPUT_MUTE: 730 cp->un.ord = sc->master_mute; 731 return 0; 732 733 case YM_MIC_LVL: 734 if (cp->un.value.num_channels != 1) 735 return EINVAL; 736 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->mic_gain; 737 return 0; 738 739 case YM_MASTER_EQMODE: 740 cp->un.ord = sc->sc_eqmode; 741 return 0; 742 743 case YM_MASTER_TREBLE: 744 ad1848_from_vol(cp, &sc->sc_treble); 745 return 0; 746 747 case YM_MASTER_BASS: 748 ad1848_from_vol(cp, &sc->sc_bass); 749 return 0; 750 751 case YM_MASTER_WIDE: 752 ad1848_from_vol(cp, &sc->sc_wide); 753 return 0; 754 755 #ifndef AUDIO_NO_POWER_CTL 756 case YM_PWR_MODE: 757 cp->un.ord = sc->sc_pow_mode; 758 return 0; 759 760 case YM_PWR_TIMEOUT: 761 if (cp->un.value.num_channels != 1) 762 return EINVAL; 763 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_pow_timeout; 764 return 0; 765 #endif 766 } 767 768 error = ad1848_mixer_get_port(ac, mappings, NUMMAP, cp); 769 770 if (error != ENXIO) 771 return error; 772 773 error = 0; 774 775 switch (cp->dev) { 776 case YM_MIC_MUTE: 777 cp->un.ord = sc->mic_mute; 778 break; 779 780 default: 781 error = ENXIO; 782 break; 783 } 784 785 return error; 786 } 787 788 static const char *mixer_classes[] = { 789 AudioCinputs, AudioCrecord, AudioCoutputs, AudioCmonitor, 790 #ifndef AUDIO_NO_POWER_CTL 791 AudioCpower, 792 #endif 793 AudioCequalization 794 }; 795 796 int 797 ym_query_devinfo(void *addr, mixer_devinfo_t *dip) 798 { 799 static const char *mixer_port_names[] = { 800 AudioNdac, AudioNmidi, AudioNcd, AudioNline, AudioNspeaker, 801 AudioNmicrophone, AudioNmonitor 802 }; 803 struct ad1848_softc *ac; 804 struct ym_softc *sc; 805 806 ac = addr; 807 sc = ac->parent; 808 /* SA2 doesn't have equalizer */ 809 if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(dip->index)) 810 return ENXIO; 811 812 dip->next = dip->prev = AUDIO_MIXER_LAST; 813 814 switch(dip->index) { 815 case YM_INPUT_CLASS: 816 case YM_OUTPUT_CLASS: 817 case YM_MONITOR_CLASS: 818 case YM_RECORD_CLASS: 819 #ifndef AUDIO_NO_POWER_CTL 820 case YM_PWR_CLASS: 821 #endif 822 case YM_EQ_CLASS: 823 dip->type = AUDIO_MIXER_CLASS; 824 dip->mixer_class = dip->index; 825 strcpy(dip->label.name, 826 mixer_classes[dip->index - YM_INPUT_CLASS]); 827 break; 828 829 case YM_DAC_LVL: 830 case YM_MIDI_LVL: 831 case YM_CD_LVL: 832 case YM_LINE_LVL: 833 case YM_SPEAKER_LVL: 834 case YM_MIC_LVL: 835 case YM_MONITOR_LVL: 836 dip->type = AUDIO_MIXER_VALUE; 837 if (dip->index == YM_MONITOR_LVL) 838 dip->mixer_class = YM_MONITOR_CLASS; 839 else 840 dip->mixer_class = YM_INPUT_CLASS; 841 842 dip->next = dip->index + 7; 843 844 strcpy(dip->label.name, 845 mixer_port_names[dip->index - YM_DAC_LVL]); 846 847 if (dip->index == YM_SPEAKER_LVL || 848 dip->index == YM_MIC_LVL) 849 dip->un.v.num_channels = 1; 850 else 851 dip->un.v.num_channels = 2; 852 853 if (dip->index == YM_SPEAKER_LVL) 854 dip->un.v.delta = 1 << (8 - 4 /* valid bits */); 855 else if (dip->index == YM_DAC_LVL || 856 dip->index == YM_MONITOR_LVL) 857 dip->un.v.delta = 1 << (8 - 6 /* valid bits */); 858 else 859 dip->un.v.delta = 1 << (8 - 5 /* valid bits */); 860 861 strcpy(dip->un.v.units.name, AudioNvolume); 862 break; 863 864 case YM_DAC_MUTE: 865 case YM_MIDI_MUTE: 866 case YM_CD_MUTE: 867 case YM_LINE_MUTE: 868 case YM_SPEAKER_MUTE: 869 case YM_MIC_MUTE: 870 case YM_MONITOR_MUTE: 871 if (dip->index == YM_MONITOR_MUTE) 872 dip->mixer_class = YM_MONITOR_CLASS; 873 else 874 dip->mixer_class = YM_INPUT_CLASS; 875 dip->type = AUDIO_MIXER_ENUM; 876 dip->prev = dip->index - 7; 877 mute: 878 strcpy(dip->label.name, AudioNmute); 879 dip->un.e.num_mem = 2; 880 strcpy(dip->un.e.member[0].label.name, AudioNoff); 881 dip->un.e.member[0].ord = 0; 882 strcpy(dip->un.e.member[1].label.name, AudioNon); 883 dip->un.e.member[1].ord = 1; 884 break; 885 886 887 case YM_OUTPUT_LVL: 888 dip->type = AUDIO_MIXER_VALUE; 889 dip->mixer_class = YM_OUTPUT_CLASS; 890 dip->next = YM_OUTPUT_MUTE; 891 strcpy(dip->label.name, AudioNmaster); 892 dip->un.v.num_channels = 2; 893 dip->un.v.delta = (AUDIO_MAX_GAIN + 1) / (SA3_VOL_MV + 1); 894 strcpy(dip->un.v.units.name, AudioNvolume); 895 break; 896 897 case YM_OUTPUT_MUTE: 898 dip->mixer_class = YM_OUTPUT_CLASS; 899 dip->type = AUDIO_MIXER_ENUM; 900 dip->prev = YM_OUTPUT_LVL; 901 goto mute; 902 903 904 case YM_REC_LVL: /* record level */ 905 dip->type = AUDIO_MIXER_VALUE; 906 dip->mixer_class = YM_RECORD_CLASS; 907 dip->next = YM_RECORD_SOURCE; 908 strcpy(dip->label.name, AudioNrecord); 909 dip->un.v.num_channels = 2; 910 dip->un.v.delta = 1 << (8 - 4 /* valid bits */); 911 strcpy(dip->un.v.units.name, AudioNvolume); 912 break; 913 914 case YM_RECORD_SOURCE: 915 dip->mixer_class = YM_RECORD_CLASS; 916 dip->type = AUDIO_MIXER_ENUM; 917 dip->prev = YM_REC_LVL; 918 strcpy(dip->label.name, AudioNsource); 919 dip->un.e.num_mem = 4; 920 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone); 921 dip->un.e.member[0].ord = MIC_IN_PORT; 922 strcpy(dip->un.e.member[1].label.name, AudioNline); 923 dip->un.e.member[1].ord = LINE_IN_PORT; 924 strcpy(dip->un.e.member[2].label.name, AudioNdac); 925 dip->un.e.member[2].ord = DAC_IN_PORT; 926 strcpy(dip->un.e.member[3].label.name, AudioNcd); 927 dip->un.e.member[3].ord = AUX1_IN_PORT; 928 break; 929 930 931 case YM_MASTER_EQMODE: 932 dip->type = AUDIO_MIXER_ENUM; 933 dip->mixer_class = YM_EQ_CLASS; 934 strcpy(dip->label.name, AudioNmode); 935 strcpy(dip->un.v.units.name, AudioNmode); 936 dip->un.e.num_mem = 4; 937 strcpy(dip->un.e.member[0].label.name, AudioNdesktop); 938 dip->un.e.member[0].ord = SA3_SYS_CTL_YMODE0; 939 strcpy(dip->un.e.member[1].label.name, AudioNlaptop); 940 dip->un.e.member[1].ord = SA3_SYS_CTL_YMODE1; 941 strcpy(dip->un.e.member[2].label.name, AudioNsubnote); 942 dip->un.e.member[2].ord = SA3_SYS_CTL_YMODE2; 943 strcpy(dip->un.e.member[3].label.name, AudioNhifi); 944 dip->un.e.member[3].ord = SA3_SYS_CTL_YMODE3; 945 break; 946 947 case YM_MASTER_TREBLE: 948 dip->type = AUDIO_MIXER_VALUE; 949 dip->mixer_class = YM_EQ_CLASS; 950 strcpy(dip->label.name, AudioNtreble); 951 dip->un.v.num_channels = 2; 952 dip->un.v.delta = (AUDIO_MAX_GAIN + 1) / (SA3_3D_BITS + 1) 953 >> YM_EQ_REDUCE_BIT; 954 strcpy(dip->un.v.units.name, AudioNtreble); 955 break; 956 957 case YM_MASTER_BASS: 958 dip->type = AUDIO_MIXER_VALUE; 959 dip->mixer_class = YM_EQ_CLASS; 960 strcpy(dip->label.name, AudioNbass); 961 dip->un.v.num_channels = 2; 962 dip->un.v.delta = (AUDIO_MAX_GAIN + 1) / (SA3_3D_BITS + 1) 963 >> YM_EQ_REDUCE_BIT; 964 strcpy(dip->un.v.units.name, AudioNbass); 965 break; 966 967 case YM_MASTER_WIDE: 968 dip->type = AUDIO_MIXER_VALUE; 969 dip->mixer_class = YM_EQ_CLASS; 970 strcpy(dip->label.name, AudioNsurround); 971 dip->un.v.num_channels = 2; 972 dip->un.v.delta = (AUDIO_MAX_GAIN + 1) / (SA3_3D_BITS + 1); 973 strcpy(dip->un.v.units.name, AudioNsurround); 974 break; 975 976 977 #ifndef AUDIO_NO_POWER_CTL 978 case YM_PWR_MODE: 979 dip->type = AUDIO_MIXER_ENUM; 980 dip->mixer_class = YM_PWR_CLASS; 981 dip->next = YM_PWR_TIMEOUT; 982 strcpy(dip->label.name, AudioNsave); 983 dip->un.e.num_mem = 3; 984 strcpy(dip->un.e.member[0].label.name, AudioNpowerdown); 985 dip->un.e.member[0].ord = YM_POWER_POWERDOWN; 986 strcpy(dip->un.e.member[1].label.name, AudioNpowersave); 987 dip->un.e.member[1].ord = YM_POWER_POWERSAVE; 988 strcpy(dip->un.e.member[2].label.name, AudioNnosave); 989 dip->un.e.member[2].ord = YM_POWER_NOSAVE; 990 break; 991 992 case YM_PWR_TIMEOUT: 993 dip->type = AUDIO_MIXER_VALUE; 994 dip->mixer_class = YM_PWR_CLASS; 995 dip->prev = YM_PWR_MODE; 996 strcpy(dip->label.name, AudioNtimeout); 997 dip->un.v.num_channels = 1; 998 strcpy(dip->un.v.units.name, AudioNtimeout); 999 break; 1000 #endif /* not AUDIO_NO_POWER_CTL */ 1001 1002 default: 1003 return ENXIO; 1004 /*NOTREACHED*/ 1005 } 1006 1007 return 0; 1008 } 1009 1010 int 1011 ym_intr(void *arg) 1012 { 1013 struct ym_softc *sc = arg; 1014 #if NMPU_YM > 0 1015 struct mpu_softc *sc_mpu = device_private(sc->sc_mpudev); 1016 #endif 1017 u_int8_t ist; 1018 int processed; 1019 1020 /* OPL3 timer is currently unused. */ 1021 if (((ist = ym_read(sc, SA3_IRQA_STAT)) & 1022 ~(SA3_IRQ_STAT_SB|SA3_IRQ_STAT_OPL3)) == 0) { 1023 DPRINTF(("%s: ym_intr: spurious interrupt\n", DVNAME(sc))); 1024 return 0; 1025 } 1026 1027 /* Process pending interrupts. */ 1028 do { 1029 processed = 0; 1030 /* 1031 * CODEC interrupts. 1032 */ 1033 if (ist & (SA3_IRQ_STAT_TI|SA3_IRQ_STAT_CI|SA3_IRQ_STAT_PI)) { 1034 ad1848_isa_intr(&sc->sc_ad1848); 1035 processed = 1; 1036 } 1037 #if NMPU_YM > 0 1038 /* 1039 * MPU401 interrupt. 1040 */ 1041 if (ist & SA3_IRQ_STAT_MPU) { 1042 mpu_intr(sc_mpu); 1043 processed = 1; 1044 } 1045 #endif 1046 /* 1047 * Hardware volume interrupt (SA3 only). 1048 * Recalculate master volume from the hardware setting. 1049 */ 1050 if ((ist & SA3_IRQ_STAT_MV) && YM_IS_SA3(sc)) { 1051 ym_hvol_to_master_gain(sc); 1052 processed = 1; 1053 } 1054 } while (processed && (ist = ym_read(sc, SA3_IRQA_STAT))); 1055 1056 return 1; 1057 } 1058 1059 1060 #ifndef AUDIO_NO_POWER_CTL 1061 static void 1062 ym_save_codec_regs(struct ym_softc *sc) 1063 { 1064 struct ad1848_softc *ac; 1065 int i; 1066 1067 DPRINTF(("%s: ym_save_codec_regs\n", DVNAME(sc))); 1068 ac = &sc->sc_ad1848.sc_ad1848; 1069 for (i = 0; i <= 0x1f; i++) 1070 sc->sc_codec_scan[i] = ad_read(ac, i); 1071 } 1072 1073 static void 1074 ym_restore_codec_regs(struct ym_softc *sc) 1075 { 1076 struct ad1848_softc *ac; 1077 int i, t; 1078 1079 DPRINTF(("%s: ym_restore_codec_regs\n", DVNAME(sc))); 1080 ac = &sc->sc_ad1848.sc_ad1848; 1081 for (i = 0; i <= 0x1f; i++) { 1082 /* 1083 * Wait til the chip becomes ready. 1084 * This is required after suspend/resume. 1085 */ 1086 for (t = 0; 1087 t < 100000 && ADREAD(ac, AD1848_IADDR) & SP_IN_INIT; t++) 1088 ; 1089 #ifdef AUDIO_DEBUG 1090 if (t) 1091 DPRINTF(("%s: ym_restore_codec_regs: reg %d, t %d\n", 1092 DVNAME(sc), i, t)); 1093 #endif 1094 ad_write(ac, i, sc->sc_codec_scan[i]); 1095 } 1096 } 1097 1098 /* 1099 * Save and restore the state on suspending / resumning. 1100 * 1101 * XXX This is not complete. 1102 * Currently only the parameters, such as output gain, are restored. 1103 * DMA state should also be restored. FIXME. 1104 */ 1105 void 1106 ym_power_hook(int why, void *v) 1107 { 1108 struct ym_softc *sc; 1109 int i, xmax; 1110 int s; 1111 1112 sc = v; 1113 DPRINTF(("%s: ym_power_hook: why = %d\n", DVNAME(sc), why)); 1114 1115 s = splaudio(); 1116 1117 switch (why) { 1118 case PWR_SUSPEND: 1119 case PWR_STANDBY: 1120 /* 1121 * suspending... 1122 */ 1123 callout_stop(&sc->sc_powerdown_ch); 1124 if (sc->sc_turning_off) 1125 ym_powerdown_blocks(sc); 1126 1127 /* 1128 * Save CODEC registers. 1129 * Note that the registers read incorrect 1130 * if the CODEC part is in power-down mode. 1131 */ 1132 if (sc->sc_on_blocks & YM_POWER_CODEC_DIGITAL) 1133 ym_save_codec_regs(sc); 1134 1135 /* 1136 * Save OPL3-SA3 control registers and power-down the chip. 1137 * Note that the registers read incorrect 1138 * if the chip is in global power-down mode. 1139 */ 1140 sc->sc_sa3_scan[SA3_PWR_MNG] = ym_read(sc, SA3_PWR_MNG); 1141 if (sc->sc_on_blocks) 1142 ym_chip_powerdown(sc); 1143 break; 1144 1145 case PWR_RESUME: 1146 /* 1147 * resuming... 1148 */ 1149 ym_chip_powerup(sc, 1); 1150 ym_init(sc); /* power-on CODEC */ 1151 1152 /* Restore control registers. */ 1153 xmax = YM_IS_SA3(sc)? YM_SAVE_REG_MAX_SA3 : YM_SAVE_REG_MAX_SA2; 1154 for (i = SA3_PWR_MNG + 1; i <= xmax; i++) { 1155 if (i == SA3_SB_SCAN || i == SA3_SB_SCAN_DATA || 1156 i == SA3_DPWRDWN) 1157 continue; 1158 ym_write(sc, i, sc->sc_sa3_scan[i]); 1159 } 1160 1161 /* Restore CODEC registers (including mixer). */ 1162 ym_restore_codec_regs(sc); 1163 1164 /* Restore global/digital power-down state. */ 1165 ym_write(sc, SA3_PWR_MNG, sc->sc_sa3_scan[SA3_PWR_MNG]); 1166 if (YM_IS_SA3(sc)) 1167 ym_write(sc, SA3_DPWRDWN, sc->sc_sa3_scan[SA3_DPWRDWN]); 1168 break; 1169 case PWR_SOFTSUSPEND: 1170 case PWR_SOFTSTANDBY: 1171 case PWR_SOFTRESUME: 1172 break; 1173 } 1174 splx(s); 1175 } 1176 1177 int 1178 ym_codec_power_ctl(void *arg, int flags) 1179 { 1180 struct ym_softc *sc; 1181 struct ad1848_softc *ac; 1182 int parts; 1183 1184 sc = arg; 1185 ac = &sc->sc_ad1848.sc_ad1848; 1186 DPRINTF(("%s: ym_codec_power_ctl: flags = 0x%x\n", DVNAME(sc), flags)); 1187 1188 if (flags != 0) { 1189 parts = 0; 1190 if (flags & FREAD) { 1191 parts |= YM_POWER_CODEC_R | YM_POWER_CODEC_AD; 1192 if (ac->mute[AD1848_MONITOR_CHANNEL] == 0) 1193 parts |= YM_POWER_CODEC_P | YM_POWER_CODEC_DA; 1194 } 1195 if (flags & FWRITE) 1196 parts |= YM_POWER_CODEC_P | YM_POWER_CODEC_DA; 1197 } else 1198 parts = YM_POWER_CODEC_P | YM_POWER_CODEC_R | 1199 YM_POWER_CODEC_DA | YM_POWER_CODEC_AD; 1200 1201 ym_power_ctl(sc, parts, flags); 1202 1203 return 0; 1204 } 1205 1206 /* 1207 * Enter Power Save mode or Global Power Down mode. 1208 * Total dissipation becomes 5mA and 10uA (typ.) respective. 1209 * 1210 * This must be called at splaudio(). 1211 */ 1212 static void 1213 ym_chip_powerdown(struct ym_softc *sc) 1214 { 1215 int i, xmax; 1216 1217 DPRINTF(("%s: ym_chip_powerdown\n", DVNAME(sc))); 1218 1219 xmax = YM_IS_SA3(sc) ? YM_SAVE_REG_MAX_SA3 : YM_SAVE_REG_MAX_SA2; 1220 1221 /* Save control registers. */ 1222 for (i = SA3_PWR_MNG + 1; i <= xmax; i++) { 1223 if (i == SA3_SB_SCAN || i == SA3_SB_SCAN_DATA) 1224 continue; 1225 sc->sc_sa3_scan[i] = ym_read(sc, i); 1226 } 1227 ym_write(sc, SA3_PWR_MNG, 1228 (sc->sc_pow_mode == YM_POWER_POWERDOWN ? 1229 SA3_PWR_MNG_PDN : SA3_PWR_MNG_PSV) | SA3_PWR_MNG_PDX); 1230 } 1231 1232 /* 1233 * Power up from Power Save / Global Power Down Mode. 1234 * 1235 * We assume no ym interrupt shall occur, since the chip is 1236 * in power-down mode (or should be blocked by splaudio()). 1237 */ 1238 static void 1239 ym_chip_powerup(struct ym_softc *sc, int nosleep) 1240 { 1241 int wchan; 1242 uint8_t pw; 1243 1244 DPRINTF(("%s: ym_chip_powerup\n", DVNAME(sc))); 1245 1246 pw = ym_read(sc, SA3_PWR_MNG); 1247 1248 if ((pw & (SA3_PWR_MNG_PSV | SA3_PWR_MNG_PDN | SA3_PWR_MNG_PDX)) == 0) 1249 return; /* already on */ 1250 1251 pw &= ~SA3_PWR_MNG_PDX; 1252 ym_write(sc, SA3_PWR_MNG, pw); 1253 1254 /* wait 100 ms */ 1255 if (nosleep) 1256 delay(100000); 1257 else 1258 tsleep(&wchan, PWAIT, "ym_pu1", hz / 10); 1259 1260 pw &= ~(SA3_PWR_MNG_PSV | SA3_PWR_MNG_PDN); 1261 ym_write(sc, SA3_PWR_MNG, pw); 1262 1263 /* wait 70 ms */ 1264 if (nosleep) 1265 delay(70000); 1266 else 1267 tsleep(&wchan, PWAIT, "ym_pu2", hz / 14); 1268 1269 /* The chip is muted automatically --- unmute it now. */ 1270 ym_mute(sc, SA3_VOL_L, sc->master_mute); 1271 ym_mute(sc, SA3_VOL_R, sc->master_mute); 1272 } 1273 1274 /* callout handler for power-down */ 1275 void 1276 ym_powerdown_blocks(void *arg) 1277 { 1278 struct ym_softc *sc; 1279 uint16_t parts; 1280 uint16_t on_blocks; 1281 uint8_t sv; 1282 int s; 1283 1284 sc = arg; 1285 on_blocks = sc->sc_on_blocks; 1286 DPRINTF(("%s: ym_powerdown_blocks: turning_off 0x%x\n", 1287 DVNAME(sc), sc->sc_turning_off)); 1288 1289 s = splaudio(); 1290 1291 on_blocks = sc->sc_on_blocks; 1292 1293 /* Be sure not to change the state of the chip. Save it first. */ 1294 sv = bus_space_read_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_INDEX); 1295 1296 parts = sc->sc_turning_off; 1297 1298 if (on_blocks & ~parts & YM_POWER_CODEC_CTL) 1299 parts &= ~(YM_POWER_CODEC_P | YM_POWER_CODEC_R); 1300 if (parts & YM_POWER_CODEC_CTL) { 1301 if ((on_blocks & YM_POWER_CODEC_P) == 0) 1302 parts |= YM_POWER_CODEC_P; 1303 if ((on_blocks & YM_POWER_CODEC_R) == 0) 1304 parts |= YM_POWER_CODEC_R; 1305 } 1306 parts &= ~YM_POWER_CODEC_PSEUDO; 1307 1308 /* If CODEC is being off, save the state. */ 1309 if ((sc->sc_on_blocks & YM_POWER_CODEC_DIGITAL) && 1310 (sc->sc_on_blocks & ~sc->sc_turning_off & 1311 YM_POWER_CODEC_DIGITAL) == 0) 1312 ym_save_codec_regs(sc); 1313 1314 if (YM_IS_SA3(sc)) { 1315 /* OPL3-SA3 */ 1316 ym_write(sc, SA3_DPWRDWN, 1317 ym_read(sc, SA3_DPWRDWN) | (u_int8_t) parts); 1318 ym_write(sc, SA3_APWRDWN, 1319 ym_read(sc, SA3_APWRDWN) | (parts >> 8)); 1320 } else { 1321 /* OPL3-SA2 (only OPL3 can be off partially) */ 1322 if (parts & YM_POWER_OPL3) 1323 ym_write(sc, SA3_PWR_MNG, 1324 ym_read(sc, SA3_PWR_MNG) | SA2_PWR_MNG_FMPS); 1325 } 1326 1327 if (((sc->sc_on_blocks &= ~sc->sc_turning_off) & YM_POWER_ACTIVE) == 0) 1328 ym_chip_powerdown(sc); 1329 1330 sc->sc_turning_off = 0; 1331 1332 /* Restore the state of the chip. */ 1333 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_INDEX, sv); 1334 1335 splx(s); 1336 } 1337 1338 /* 1339 * Power control entry point. 1340 */ 1341 void 1342 ym_power_ctl(struct ym_softc *sc, int parts, int onoff) 1343 { 1344 int s; 1345 int need_restore_codec; 1346 1347 DPRINTF(("%s: ym_power_ctl: parts = 0x%x, %s\n", 1348 DVNAME(sc), parts, onoff ? "on" : "off")); 1349 1350 #ifdef DIAGNOSTIC 1351 if (curproc == NULL) 1352 panic("ym_power_ctl: no curproc"); 1353 #endif 1354 /* This function may sleep --- needs locking. */ 1355 while (sc->sc_in_power_ctl & YM_POWER_CTL_INUSE) { 1356 sc->sc_in_power_ctl |= YM_POWER_CTL_WANTED; 1357 DPRINTF(("%s: ym_power_ctl: sleeping\n", DVNAME(sc))); 1358 tsleep(&sc->sc_in_power_ctl, PWAIT, "ym_pc", 0); 1359 DPRINTF(("%s: ym_power_ctl: awaken\n", DVNAME(sc))); 1360 } 1361 sc->sc_in_power_ctl |= YM_POWER_CTL_INUSE; 1362 1363 /* Defeat softclock interrupts. */ 1364 s = splsoftclock(); 1365 1366 /* If ON requested to parts which are scheduled to OFF, cancel it. */ 1367 if (onoff && sc->sc_turning_off && (sc->sc_turning_off &= ~parts) == 0) 1368 callout_stop(&sc->sc_powerdown_ch); 1369 1370 if (!onoff && sc->sc_turning_off) 1371 parts &= ~sc->sc_turning_off; 1372 1373 /* Discard bits which are currently {on,off}. */ 1374 parts &= onoff ? ~sc->sc_on_blocks : sc->sc_on_blocks; 1375 1376 /* Cancel previous timeout if needed. */ 1377 if (parts != 0 && sc->sc_turning_off) 1378 callout_stop(&sc->sc_powerdown_ch); 1379 1380 (void) splx(s); 1381 1382 if (parts == 0) 1383 goto unlock; /* no work to do */ 1384 1385 if (onoff) { 1386 /* Turning on is done immediately. */ 1387 1388 /* If the chip is off, turn it on. */ 1389 if ((sc->sc_on_blocks & YM_POWER_ACTIVE) == 0) 1390 ym_chip_powerup(sc, 0); 1391 1392 need_restore_codec = (parts & YM_POWER_CODEC_DIGITAL) && 1393 (sc->sc_on_blocks & YM_POWER_CODEC_DIGITAL) == 0; 1394 1395 sc->sc_on_blocks |= parts; 1396 if (parts & YM_POWER_CODEC_CTL) 1397 parts |= YM_POWER_CODEC_P | YM_POWER_CODEC_R; 1398 1399 s = splaudio(); 1400 1401 if (YM_IS_SA3(sc)) { 1402 /* OPL3-SA3 */ 1403 ym_write(sc, SA3_DPWRDWN, 1404 ym_read(sc, SA3_DPWRDWN) & (u_int8_t)~parts); 1405 ym_write(sc, SA3_APWRDWN, 1406 ym_read(sc, SA3_APWRDWN) & ~(parts >> 8)); 1407 } else { 1408 /* OPL3-SA2 (only OPL3 can be off partially) */ 1409 if (parts & YM_POWER_OPL3) 1410 ym_write(sc, SA3_PWR_MNG, 1411 ym_read(sc, SA3_PWR_MNG) 1412 & ~SA2_PWR_MNG_FMPS); 1413 } 1414 if (need_restore_codec) 1415 ym_restore_codec_regs(sc); 1416 1417 (void) splx(s); 1418 } else { 1419 /* Turning off is delayed. */ 1420 sc->sc_turning_off |= parts; 1421 } 1422 1423 /* Schedule turning off. */ 1424 if (sc->sc_pow_mode != YM_POWER_NOSAVE && sc->sc_turning_off) 1425 callout_reset(&sc->sc_powerdown_ch, hz * sc->sc_pow_timeout, 1426 ym_powerdown_blocks, sc); 1427 1428 unlock: 1429 if (sc->sc_in_power_ctl & YM_POWER_CTL_WANTED) 1430 wakeup(&sc->sc_in_power_ctl); 1431 sc->sc_in_power_ctl = 0; 1432 } 1433 #endif /* not AUDIO_NO_POWER_CTL */ 1434