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