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