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