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