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