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