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