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