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