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