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