1 /* $NetBSD: ym.c,v 1.37 2010/01/02 02:37:08 christos Exp $ */
4 * Copyright (c) 1999-2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
33 * Copyright (c) 1998 Constantine Sapuntzakis. All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
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.
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.
59 * Original code from OpenBSD.
62 #include <sys/cdefs.h>
63 __KERNEL_RCSID(0, "$NetBSD: ym.c,v 1.37 2010/01/02 02:37:08 christos Exp $");
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>
80 #include <sys/audioio.h>
81 #include <dev/audio_if.h>
83 #include <dev/isa/isavar.h>
84 #include <dev/isa/isadmavar.h>
86 #include <dev/ic/ad1848reg.h>
87 #include <dev/isa/ad1848var.h>
88 #include <dev/ic/opl3sa3reg.h>
89 #include <dev/isa/wssreg.h>
91 #include <dev/ic/mpuvar.h>
93 #include <dev/isa/ymvar.h>
94 #include <dev/isa/sbreg.h>
96 /* Power management mode. */
98 #define YM_POWER_MODE YM_POWER_POWERSAVE
101 /* Time in second before power down the chip. */
102 #ifndef YM_POWER_OFF_SEC
103 #define YM_POWER_OFF_SEC 5
106 /* Default mixer settings. */
107 #ifndef YM_VOL_MASTER
108 #define YM_VOL_MASTER 208
112 #define YM_VOL_DAC 224
116 #define YM_VOL_OPL3 184
120 * Default position of the equalizer.
122 #ifndef YM_DEFAULT_TREBLE
123 #define YM_DEFAULT_TREBLE YM_EQ_FLAT_OFFSET
125 #ifndef YM_DEFAULT_BASS
126 #define YM_DEFAULT_BASS YM_EQ_FLAT_OFFSET
129 #ifdef __i386__ /* XXX */
136 #define DPRINTF(x) if (ymdebug) printf x
141 #define DVNAME(softc) (device_xname(&(softc)->sc_ad1848.sc_ad1848.sc_dev))
143 int ym_getdev(void *, struct audio_device
*);
144 int ym_mixer_set_port(void *, mixer_ctrl_t
*);
145 int ym_mixer_get_port(void *, mixer_ctrl_t
*);
146 int ym_query_devinfo(void *, mixer_devinfo_t
*);
148 #ifndef AUDIO_NO_POWER_CTL
149 static void ym_save_codec_regs(struct ym_softc
*);
150 static void ym_restore_codec_regs(struct ym_softc
*);
151 int ym_codec_power_ctl(void *, int);
152 static void ym_chip_powerdown(struct ym_softc
*);
153 static void ym_chip_powerup(struct ym_softc
*, int);
154 void ym_powerdown_blocks(void *);
155 void ym_power_ctl(struct ym_softc
*, int, int);
158 static void ym_init(struct ym_softc
*);
159 static void ym_mute(struct ym_softc
*, int, int);
160 static void ym_set_master_gain(struct ym_softc
*, struct ad1848_volume
*);
161 static void ym_hvol_to_master_gain(struct ym_softc
*);
162 static void ym_set_mic_gain(struct ym_softc
*, int);
163 static void ym_set_3d(struct ym_softc
*, mixer_ctrl_t
*,
164 struct ad1848_volume
*, int);
165 static bool ym_suspend(device_t
, pmf_qual_t
);
166 static bool ym_resume(device_t
, pmf_qual_t
);
169 const struct audio_hw_if ym_hw_if
= {
173 ad1848_query_encoding
,
175 ad1848_round_blocksize
,
176 ad1848_commit_settings
,
181 ad1848_isa_halt_output
,
182 ad1848_isa_halt_input
,
191 ad1848_isa_round_buffersize
,
193 ad1848_isa_get_props
,
194 ad1848_isa_trigger_output
,
195 ad1848_isa_trigger_input
,
197 NULL
, /* powerstate */
200 static inline int ym_read(struct ym_softc
*, int);
201 static inline void ym_write(struct ym_softc
*, int, int);
204 ym_attach(struct ym_softc
*sc
)
206 static struct ad1848_volume vol_master
= {YM_VOL_MASTER
, YM_VOL_MASTER
};
207 static struct ad1848_volume vol_dac
= {YM_VOL_DAC
, YM_VOL_DAC
};
208 static struct ad1848_volume vol_opl3
= {YM_VOL_OPL3
, YM_VOL_OPL3
};
209 struct ad1848_softc
*ac
;
211 struct audio_attach_args arg
;
213 ac
= &sc
->sc_ad1848
.sc_ad1848
;
214 callout_init(&sc
->sc_powerdown_ch
, 0);
216 /* Mute the output to reduce noise during initialization. */
217 ym_mute(sc
, SA3_VOL_L
, 1);
218 ym_mute(sc
, SA3_VOL_R
, 1);
220 sc
->sc_version
= ym_read(sc
, SA3_MISC
) & SA3_MISC_VER
;
221 ac
->chip_name
= YM_IS_SA3(sc
) ? "OPL3-SA3" : "OPL3-SA2";
223 sc
->sc_ad1848
.sc_ih
= isa_intr_establish(sc
->sc_ic
, sc
->ym_irq
,
224 IST_EDGE
, IPL_AUDIO
, ym_intr
, sc
);
226 #ifndef AUDIO_NO_POWER_CTL
227 sc
->sc_ad1848
.powerctl
= ym_codec_power_ctl
;
228 sc
->sc_ad1848
.powerarg
= sc
;
230 ad1848_isa_attach(&sc
->sc_ad1848
);
234 /* Establish chip in well known mode */
235 ym_set_master_gain(sc
, &vol_master
);
236 ym_set_mic_gain(sc
, 0);
239 /* Override ad1848 settings. */
240 ad1848_set_channel_gain(ac
, AD1848_DAC_CHANNEL
, &vol_dac
);
241 ad1848_set_channel_gain(ac
, AD1848_AUX2_CHANNEL
, &vol_opl3
);
244 * Mute all external sources. If you change this, you must
245 * also change the initial value of sc->sc_external_sources
246 * (currently 0 --- no external source is active).
249 ym_mute(sc
, SA3_MIC_VOL
, sc
->mic_mute
);
250 ad1848_mute_channel(ac
, AD1848_AUX1_CHANNEL
, MUTE_ALL
); /* CD */
251 ad1848_mute_channel(ac
, AD1848_LINE_CHANNEL
, MUTE_ALL
); /* line */
252 ac
->mute
[AD1848_AUX1_CHANNEL
] = MUTE_ALL
;
253 ac
->mute
[AD1848_LINE_CHANNEL
] = MUTE_ALL
;
254 /* speaker is muted by default */
256 /* We use only one IRQ (IRQ-A). */
257 ym_write(sc
, SA3_IRQ_CONF
, SA3_IRQ_CONF_MPU_A
| SA3_IRQ_CONF_WSS_A
);
258 ym_write(sc
, SA3_HVOL_INTR_CNF
, SA3_HVOL_INTR_CNF_A
);
260 /* audio at ym attachment */
261 sc
->sc_audiodev
= audio_attach_mi(&ym_hw_if
, ac
, &ac
->sc_dev
);
263 /* opl at ym attachment */
264 if (sc
->sc_opl_ioh
) {
265 arg
.type
= AUDIODEV_TYPE_OPL
;
268 (void)config_found(&ac
->sc_dev
, &arg
, audioprint
);
272 /* mpu at ym attachment */
273 if (sc
->sc_mpu_ioh
) {
274 arg
.type
= AUDIODEV_TYPE_MPU
;
277 sc
->sc_mpudev
= config_found(&ac
->sc_dev
, &arg
, audioprint
);
281 /* This must be AFTER the attachment of sub-devices. */
284 #ifndef AUDIO_NO_POWER_CTL
286 * Initialize power control.
288 sc
->sc_pow_mode
= YM_POWER_MODE
;
289 sc
->sc_pow_timeout
= YM_POWER_OFF_SEC
;
291 sc
->sc_on_blocks
= sc
->sc_turning_off
=
292 YM_POWER_CODEC_P
| YM_POWER_CODEC_R
|
293 YM_POWER_OPL3
| YM_POWER_MPU401
| YM_POWER_3D
|
294 YM_POWER_CODEC_DA
| YM_POWER_CODEC_AD
| YM_POWER_OPL3_DA
;
296 sc
->sc_on_blocks
|= YM_POWER_JOYSTICK
; /* prevents chip powerdown */
298 ym_powerdown_blocks(sc
);
300 if (!pmf_device_register(&ac
->sc_dev
, ym_suspend
, ym_resume
)) {
301 aprint_error_dev(&ac
->sc_dev
,
302 "cannot set power mgmt handler\n");
306 /* Set tone control to the default position. */
307 mctl
.un
.value
.num_channels
= 1;
308 mctl
.un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] = YM_DEFAULT_TREBLE
;
309 mctl
.dev
= YM_MASTER_TREBLE
;
310 ym_mixer_set_port(sc
, &mctl
);
311 mctl
.un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] = YM_DEFAULT_BASS
;
312 mctl
.dev
= YM_MASTER_BASS
;
313 ym_mixer_set_port(sc
, &mctl
);
315 /* Unmute the output now if the chip is on. */
316 #ifndef AUDIO_NO_POWER_CTL
317 if (sc
->sc_on_blocks
& YM_POWER_ACTIVE
)
320 ym_mute(sc
, SA3_VOL_L
, sc
->master_mute
);
321 ym_mute(sc
, SA3_VOL_R
, sc
->master_mute
);
326 ym_read(struct ym_softc
*sc
, int reg
)
329 bus_space_write_1(sc
->sc_iot
, sc
->sc_controlioh
,
330 SA3_CTL_INDEX
, (reg
& 0xff));
331 return bus_space_read_1(sc
->sc_iot
, sc
->sc_controlioh
, SA3_CTL_DATA
);
335 ym_write(struct ym_softc
*sc
, int reg
, int data
)
338 bus_space_write_1(sc
->sc_iot
, sc
->sc_controlioh
,
339 SA3_CTL_INDEX
, (reg
& 0xff));
340 bus_space_write_1(sc
->sc_iot
, sc
->sc_controlioh
,
341 SA3_CTL_DATA
, (data
& 0xff));
345 ym_init(struct ym_softc
*sc
)
349 /* Mute SoundBlaster output if possible. */
351 bus_space_write_1(sc
->sc_iot
, sc
->sc_sb_ioh
, SBP_MIXER_ADDR
,
353 bus_space_write_1(sc
->sc_iot
, sc
->sc_sb_ioh
, SBP_MIXER_DATA
,
357 if (!YM_IS_SA3(sc
)) {
359 ym_write(sc
, SA3_PWR_MNG
, SA2_PWR_MNG_CLKO
|
360 (sc
->sc_opl_ioh
== 0 ? SA2_PWR_MNG_FMPS
: 0));
365 /* Figure out which part can be power down. */
366 dpd
= SA3_DPWRDWN_SB
/* we never use SB */
368 | (sc
->sc_mpu_ioh
? 0 : SA3_DPWRDWN_MPU
)
375 | SA3_DPWRDWN_PNP
/* ISA Plug and Play is done */
377 * The master clock is for external wavetable synthesizer
378 * OPL4-ML (YMF704) or OPL4-ML2 (YMF721),
379 * and is currently unused.
383 apd
= SA3_APWRDWN_SBDAC
; /* we never use SB */
385 /* Power down OPL3 if not attached. */
386 if (sc
->sc_opl_ioh
== 0) {
387 dpd
|= SA3_DPWRDWN_FM
;
388 apd
|= SA3_APWRDWN_FMDAC
;
390 /* CODEC is always attached. */
392 /* Power down unused digital parts. */
393 ym_write(sc
, SA3_DPWRDWN
, dpd
);
395 /* Power down unused analog parts. */
396 ym_write(sc
, SA3_APWRDWN
, apd
);
401 ym_getdev(void *addr
, struct audio_device
*retp
)
404 struct ad1848_softc
*ac
;
407 ac
= &sc
->sc_ad1848
.sc_ad1848
;
408 strlcpy(retp
->name
, ac
->chip_name
, sizeof(retp
->name
));
409 snprintf(retp
->version
, sizeof(retp
->version
), "%d", sc
->sc_version
);
410 strlcpy(retp
->config
, "ym", sizeof(retp
->config
));
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}
433 #define NUMMAP (sizeof(mappings) / sizeof(mappings[0]))
437 ym_mute(struct ym_softc
*sc
, int left_reg
, int mute
)
441 reg
= ym_read(sc
, left_reg
);
443 ym_write(sc
, left_reg
, reg
| 0x80);
445 ym_write(sc
, left_reg
, reg
& ~0x80);
450 ym_set_master_gain(struct ym_softc
*sc
, struct ad1848_volume
*vol
)
454 sc
->master_gain
= *vol
;
456 atten
= ((AUDIO_MAX_GAIN
- vol
->left
) * (SA3_VOL_MV
+ 1)) /
457 (AUDIO_MAX_GAIN
+ 1);
459 ym_write(sc
, SA3_VOL_L
, (ym_read(sc
, SA3_VOL_L
) & ~SA3_VOL_MV
) | atten
);
461 atten
= ((AUDIO_MAX_GAIN
- vol
->right
) * (SA3_VOL_MV
+ 1)) /
462 (AUDIO_MAX_GAIN
+ 1);
464 ym_write(sc
, SA3_VOL_R
, (ym_read(sc
, SA3_VOL_R
) & ~SA3_VOL_MV
) | atten
);
468 * Read current setting of master volume from hardware
469 * and update the software value if changed.
470 * [SA3] This function clears hardware volume interrupt.
473 ym_hvol_to_master_gain(struct ym_softc
*sc
)
479 val
= SA3_VOL_MV
& ~ym_read(sc
, SA3_VOL_L
);
480 prevval
= (sc
->master_gain
.left
* (SA3_VOL_MV
+ 1)) /
481 (AUDIO_MAX_GAIN
+ 1);
482 if (val
!= prevval
) {
483 sc
->master_gain
.left
=
484 val
* ((AUDIO_MAX_GAIN
+ 1) / (SA3_VOL_MV
+ 1));
488 val
= SA3_VOL_MV
& ~ym_read(sc
, SA3_VOL_R
);
489 prevval
= (sc
->master_gain
.right
* (SA3_VOL_MV
+ 1)) /
490 (AUDIO_MAX_GAIN
+ 1);
491 if (val
!= prevval
) {
492 sc
->master_gain
.right
=
493 val
* ((AUDIO_MAX_GAIN
+ 1) / (SA3_VOL_MV
+ 1));
497 #if 0 /* XXX NOT YET */
498 /* Notify the change to async processes. */
499 if (changed
&& sc
->sc_audiodev
)
500 mixer_signal(sc
->sc_audiodev
);
505 ym_set_mic_gain(struct ym_softc
*sc
, int vol
)
511 atten
= ((AUDIO_MAX_GAIN
- vol
) * (SA3_MIC_MCV
+ 1)) /
512 (AUDIO_MAX_GAIN
+ 1);
514 ym_write(sc
, SA3_MIC_VOL
,
515 (ym_read(sc
, SA3_MIC_VOL
) & ~SA3_MIC_MCV
) | atten
);
519 ym_set_3d(struct ym_softc
*sc
, mixer_ctrl_t
*cp
,
520 struct ad1848_volume
*val
, int reg
)
524 ad1848_to_vol(cp
, val
);
528 if (reg
!= SA3_3D_WIDE
) {
530 l
= YM_EQ_EXPAND_VALUE(l
);
531 r
= YM_EQ_EXPAND_VALUE(r
);
534 e
= (l
* (SA3_3D_BITS
+ 1) + (SA3_3D_BITS
+ 1) / 2) /
535 (AUDIO_MAX_GAIN
+ 1) << SA3_3D_LSHIFT
|
536 (r
* (SA3_3D_BITS
+ 1) + (SA3_3D_BITS
+ 1) / 2) /
537 (AUDIO_MAX_GAIN
+ 1) << SA3_3D_RSHIFT
;
539 #ifndef AUDIO_NO_POWER_CTL
540 /* turn wide stereo on if necessary */
542 ym_power_ctl(sc
, YM_POWER_3D
, 1);
545 ym_write(sc
, reg
, e
);
547 #ifndef AUDIO_NO_POWER_CTL
548 /* turn wide stereo off if necessary */
549 if (YM_EQ_OFF(&sc
->sc_treble
) && YM_EQ_OFF(&sc
->sc_bass
) &&
550 YM_WIDE_OFF(&sc
->sc_wide
))
551 ym_power_ctl(sc
, YM_POWER_3D
, 0);
556 ym_mixer_set_port(void *addr
, mixer_ctrl_t
*cp
)
558 struct ad1848_softc
*ac
;
560 struct ad1848_volume vol
;
567 DPRINTF(("%s: ym_mixer_set_port: dev 0x%x, type 0x%x, 0x%x (%d; %d, %d)\n",
568 DVNAME(sc
), cp
->dev
, cp
->type
, cp
->un
.ord
,
569 cp
->un
.value
.num_channels
, cp
->un
.value
.level
[0],
570 cp
->un
.value
.level
[1]));
572 /* SA2 doesn't have equalizer */
573 if (!YM_IS_SA3(sc
) && YM_MIXER_SA3_ONLY(cp
->dev
))
576 #ifndef AUDIO_NO_POWER_CTL
578 ym_power_ctl(sc
, YM_POWER_CODEC_CTL
, 1);
583 ad1848_to_vol(cp
, &vol
);
584 ym_set_master_gain(sc
, &vol
);
588 sc
->master_mute
= (cp
->un
.ord
!= 0);
589 ym_mute(sc
, SA3_VOL_L
, sc
->master_mute
);
590 ym_mute(sc
, SA3_VOL_R
, sc
->master_mute
);
594 if (cp
->un
.value
.num_channels
!= 1)
598 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
]);
601 case YM_MASTER_EQMODE
:
602 sc
->sc_eqmode
= cp
->un
.ord
& SA3_SYS_CTL_YMODE
;
603 ym_write(sc
, SA3_SYS_CTL
, (ym_read(sc
, SA3_SYS_CTL
) &
604 ~SA3_SYS_CTL_YMODE
) | sc
->sc_eqmode
);
607 case YM_MASTER_TREBLE
:
608 ym_set_3d(sc
, cp
, &sc
->sc_treble
, SA3_3D_TREBLE
);
612 ym_set_3d(sc
, cp
, &sc
->sc_bass
, SA3_3D_BASS
);
616 ym_set_3d(sc
, cp
, &sc
->sc_wide
, SA3_3D_WIDE
);
619 #ifndef AUDIO_NO_POWER_CTL
621 if ((unsigned) cp
->un
.ord
> YM_POWER_NOSAVE
)
624 sc
->sc_pow_mode
= cp
->un
.ord
;
628 if (cp
->un
.value
.num_channels
!= 1)
632 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
];
636 * Needs power-up to hear external sources.
640 case YM_SPEAKER_MUTE
:
642 extsources
= YM_MIXER_TO_XS(cp
->dev
);
644 if ((sc
->sc_external_sources
&= ~extsources
) == 0) {
646 * All the external sources are muted
647 * --- no need to keep the chip on.
649 ym_power_ctl(sc
, YM_POWER_EXT_SRC
, 0);
650 DPRINTF(("%s: ym_mixer_set_port: off for ext\n",
654 /* mute off - power-up the chip */
655 sc
->sc_external_sources
|= extsources
;
656 ym_power_ctl(sc
, YM_POWER_EXT_SRC
, 1);
657 DPRINTF(("%s: ym_mixer_set_port: on for ext\n",
660 break; /* fall to ad1848_mixer_set_port() */
663 * Power on/off the playback part for monitoring.
665 case YM_MONITOR_MUTE
:
666 if ((ac
->open_mode
& (FREAD
| FWRITE
)) == FREAD
)
667 ym_power_ctl(sc
, YM_POWER_CODEC_P
| YM_POWER_CODEC_DA
,
669 break; /* fall to ad1848_mixer_set_port() */
673 error
= ad1848_mixer_set_port(ac
, mappings
, NUMMAP
, cp
);
682 sc
->mic_mute
= (cp
->un
.ord
!= 0);
683 ym_mute(sc
, SA3_MIC_VOL
, sc
->mic_mute
);
692 #ifndef AUDIO_NO_POWER_CTL
693 /* Power-down chip */
694 ym_power_ctl(sc
, YM_POWER_CODEC_CTL
, 0);
701 ym_mixer_get_port(void *addr
, mixer_ctrl_t
*cp
)
703 struct ad1848_softc
*ac
;
709 /* SA2 doesn't have equalizer */
710 if (!YM_IS_SA3(sc
) && YM_MIXER_SA3_ONLY(cp
->dev
))
715 if (!YM_IS_SA3(sc
)) {
717 * SA2 doesn't have hardware volume interrupt.
718 * Read current value and update every time.
720 #ifndef AUDIO_NO_POWER_CTL
722 ym_power_ctl(sc
, YM_POWER_CODEC_CTL
, 1);
724 ym_hvol_to_master_gain(sc
);
725 #ifndef AUDIO_NO_POWER_CTL
726 /* Power-down chip */
727 ym_power_ctl(sc
, YM_POWER_CODEC_CTL
, 0);
730 ad1848_from_vol(cp
, &sc
->master_gain
);
734 cp
->un
.ord
= sc
->master_mute
;
738 if (cp
->un
.value
.num_channels
!= 1)
740 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] = sc
->mic_gain
;
743 case YM_MASTER_EQMODE
:
744 cp
->un
.ord
= sc
->sc_eqmode
;
747 case YM_MASTER_TREBLE
:
748 ad1848_from_vol(cp
, &sc
->sc_treble
);
752 ad1848_from_vol(cp
, &sc
->sc_bass
);
756 ad1848_from_vol(cp
, &sc
->sc_wide
);
759 #ifndef AUDIO_NO_POWER_CTL
761 cp
->un
.ord
= sc
->sc_pow_mode
;
765 if (cp
->un
.value
.num_channels
!= 1)
767 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] = sc
->sc_pow_timeout
;
772 error
= ad1848_mixer_get_port(ac
, mappings
, NUMMAP
, cp
);
781 cp
->un
.ord
= sc
->mic_mute
;
792 static const char *mixer_classes
[] = {
793 AudioCinputs
, AudioCrecord
, AudioCoutputs
, AudioCmonitor
,
794 #ifndef AUDIO_NO_POWER_CTL
801 ym_query_devinfo(void *addr
, mixer_devinfo_t
*dip
)
803 static const char *mixer_port_names
[] = {
804 AudioNdac
, AudioNmidi
, AudioNcd
, AudioNline
, AudioNspeaker
,
805 AudioNmicrophone
, AudioNmonitor
807 struct ad1848_softc
*ac
;
812 /* SA2 doesn't have equalizer */
813 if (!YM_IS_SA3(sc
) && YM_MIXER_SA3_ONLY(dip
->index
))
816 dip
->next
= dip
->prev
= AUDIO_MIXER_LAST
;
820 case YM_OUTPUT_CLASS
:
821 case YM_MONITOR_CLASS
:
822 case YM_RECORD_CLASS
:
823 #ifndef AUDIO_NO_POWER_CTL
827 dip
->type
= AUDIO_MIXER_CLASS
;
828 dip
->mixer_class
= dip
->index
;
829 strcpy(dip
->label
.name
,
830 mixer_classes
[dip
->index
- YM_INPUT_CLASS
]);
840 dip
->type
= AUDIO_MIXER_VALUE
;
841 if (dip
->index
== YM_MONITOR_LVL
)
842 dip
->mixer_class
= YM_MONITOR_CLASS
;
844 dip
->mixer_class
= YM_INPUT_CLASS
;
846 dip
->next
= dip
->index
+ 7;
848 strcpy(dip
->label
.name
,
849 mixer_port_names
[dip
->index
- YM_DAC_LVL
]);
851 if (dip
->index
== YM_SPEAKER_LVL
||
852 dip
->index
== YM_MIC_LVL
)
853 dip
->un
.v
.num_channels
= 1;
855 dip
->un
.v
.num_channels
= 2;
857 if (dip
->index
== YM_SPEAKER_LVL
)
858 dip
->un
.v
.delta
= 1 << (8 - 4 /* valid bits */);
859 else if (dip
->index
== YM_DAC_LVL
||
860 dip
->index
== YM_MONITOR_LVL
)
861 dip
->un
.v
.delta
= 1 << (8 - 6 /* valid bits */);
863 dip
->un
.v
.delta
= 1 << (8 - 5 /* valid bits */);
865 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
872 case YM_SPEAKER_MUTE
:
874 case YM_MONITOR_MUTE
:
875 if (dip
->index
== YM_MONITOR_MUTE
)
876 dip
->mixer_class
= YM_MONITOR_CLASS
;
878 dip
->mixer_class
= YM_INPUT_CLASS
;
879 dip
->type
= AUDIO_MIXER_ENUM
;
880 dip
->prev
= dip
->index
- 7;
882 strcpy(dip
->label
.name
, AudioNmute
);
883 dip
->un
.e
.num_mem
= 2;
884 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNoff
);
885 dip
->un
.e
.member
[0].ord
= 0;
886 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNon
);
887 dip
->un
.e
.member
[1].ord
= 1;
892 dip
->type
= AUDIO_MIXER_VALUE
;
893 dip
->mixer_class
= YM_OUTPUT_CLASS
;
894 dip
->next
= YM_OUTPUT_MUTE
;
895 strcpy(dip
->label
.name
, AudioNmaster
);
896 dip
->un
.v
.num_channels
= 2;
897 dip
->un
.v
.delta
= (AUDIO_MAX_GAIN
+ 1) / (SA3_VOL_MV
+ 1);
898 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
902 dip
->mixer_class
= YM_OUTPUT_CLASS
;
903 dip
->type
= AUDIO_MIXER_ENUM
;
904 dip
->prev
= YM_OUTPUT_LVL
;
908 case YM_REC_LVL
: /* record level */
909 dip
->type
= AUDIO_MIXER_VALUE
;
910 dip
->mixer_class
= YM_RECORD_CLASS
;
911 dip
->next
= YM_RECORD_SOURCE
;
912 strcpy(dip
->label
.name
, AudioNrecord
);
913 dip
->un
.v
.num_channels
= 2;
914 dip
->un
.v
.delta
= 1 << (8 - 4 /* valid bits */);
915 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
918 case YM_RECORD_SOURCE
:
919 dip
->mixer_class
= YM_RECORD_CLASS
;
920 dip
->type
= AUDIO_MIXER_ENUM
;
921 dip
->prev
= YM_REC_LVL
;
922 strcpy(dip
->label
.name
, AudioNsource
);
923 dip
->un
.e
.num_mem
= 4;
924 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNmicrophone
);
925 dip
->un
.e
.member
[0].ord
= MIC_IN_PORT
;
926 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNline
);
927 dip
->un
.e
.member
[1].ord
= LINE_IN_PORT
;
928 strcpy(dip
->un
.e
.member
[2].label
.name
, AudioNdac
);
929 dip
->un
.e
.member
[2].ord
= DAC_IN_PORT
;
930 strcpy(dip
->un
.e
.member
[3].label
.name
, AudioNcd
);
931 dip
->un
.e
.member
[3].ord
= AUX1_IN_PORT
;
935 case YM_MASTER_EQMODE
:
936 dip
->type
= AUDIO_MIXER_ENUM
;
937 dip
->mixer_class
= YM_EQ_CLASS
;
938 strcpy(dip
->label
.name
, AudioNmode
);
939 strcpy(dip
->un
.v
.units
.name
, AudioNmode
);
940 dip
->un
.e
.num_mem
= 4;
941 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNdesktop
);
942 dip
->un
.e
.member
[0].ord
= SA3_SYS_CTL_YMODE0
;
943 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNlaptop
);
944 dip
->un
.e
.member
[1].ord
= SA3_SYS_CTL_YMODE1
;
945 strcpy(dip
->un
.e
.member
[2].label
.name
, AudioNsubnote
);
946 dip
->un
.e
.member
[2].ord
= SA3_SYS_CTL_YMODE2
;
947 strcpy(dip
->un
.e
.member
[3].label
.name
, AudioNhifi
);
948 dip
->un
.e
.member
[3].ord
= SA3_SYS_CTL_YMODE3
;
951 case YM_MASTER_TREBLE
:
952 dip
->type
= AUDIO_MIXER_VALUE
;
953 dip
->mixer_class
= YM_EQ_CLASS
;
954 strcpy(dip
->label
.name
, AudioNtreble
);
955 dip
->un
.v
.num_channels
= 2;
956 dip
->un
.v
.delta
= (AUDIO_MAX_GAIN
+ 1) / (SA3_3D_BITS
+ 1)
958 strcpy(dip
->un
.v
.units
.name
, AudioNtreble
);
962 dip
->type
= AUDIO_MIXER_VALUE
;
963 dip
->mixer_class
= YM_EQ_CLASS
;
964 strcpy(dip
->label
.name
, AudioNbass
);
965 dip
->un
.v
.num_channels
= 2;
966 dip
->un
.v
.delta
= (AUDIO_MAX_GAIN
+ 1) / (SA3_3D_BITS
+ 1)
968 strcpy(dip
->un
.v
.units
.name
, AudioNbass
);
972 dip
->type
= AUDIO_MIXER_VALUE
;
973 dip
->mixer_class
= YM_EQ_CLASS
;
974 strcpy(dip
->label
.name
, AudioNsurround
);
975 dip
->un
.v
.num_channels
= 2;
976 dip
->un
.v
.delta
= (AUDIO_MAX_GAIN
+ 1) / (SA3_3D_BITS
+ 1);
977 strcpy(dip
->un
.v
.units
.name
, AudioNsurround
);
981 #ifndef AUDIO_NO_POWER_CTL
983 dip
->type
= AUDIO_MIXER_ENUM
;
984 dip
->mixer_class
= YM_PWR_CLASS
;
985 dip
->next
= YM_PWR_TIMEOUT
;
986 strcpy(dip
->label
.name
, AudioNsave
);
987 dip
->un
.e
.num_mem
= 3;
988 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNpowerdown
);
989 dip
->un
.e
.member
[0].ord
= YM_POWER_POWERDOWN
;
990 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNpowersave
);
991 dip
->un
.e
.member
[1].ord
= YM_POWER_POWERSAVE
;
992 strcpy(dip
->un
.e
.member
[2].label
.name
, AudioNnosave
);
993 dip
->un
.e
.member
[2].ord
= YM_POWER_NOSAVE
;
997 dip
->type
= AUDIO_MIXER_VALUE
;
998 dip
->mixer_class
= YM_PWR_CLASS
;
999 dip
->prev
= YM_PWR_MODE
;
1000 strcpy(dip
->label
.name
, AudioNtimeout
);
1001 dip
->un
.v
.num_channels
= 1;
1002 strcpy(dip
->un
.v
.units
.name
, AudioNtimeout
);
1004 #endif /* not AUDIO_NO_POWER_CTL */
1017 struct ym_softc
*sc
= arg
;
1019 struct mpu_softc
*sc_mpu
= device_private(sc
->sc_mpudev
);
1024 /* OPL3 timer is currently unused. */
1025 if (((ist
= ym_read(sc
, SA3_IRQA_STAT
)) &
1026 ~(SA3_IRQ_STAT_SB
|SA3_IRQ_STAT_OPL3
)) == 0) {
1027 DPRINTF(("%s: ym_intr: spurious interrupt\n", DVNAME(sc
)));
1031 /* Process pending interrupts. */
1037 if (ist
& (SA3_IRQ_STAT_TI
|SA3_IRQ_STAT_CI
|SA3_IRQ_STAT_PI
)) {
1038 ad1848_isa_intr(&sc
->sc_ad1848
);
1045 if (ist
& SA3_IRQ_STAT_MPU
) {
1051 * Hardware volume interrupt (SA3 only).
1052 * Recalculate master volume from the hardware setting.
1054 if ((ist
& SA3_IRQ_STAT_MV
) && YM_IS_SA3(sc
)) {
1055 ym_hvol_to_master_gain(sc
);
1058 } while (processed
&& (ist
= ym_read(sc
, SA3_IRQA_STAT
)));
1064 #ifndef AUDIO_NO_POWER_CTL
1066 ym_save_codec_regs(struct ym_softc
*sc
)
1068 struct ad1848_softc
*ac
;
1071 DPRINTF(("%s: ym_save_codec_regs\n", DVNAME(sc
)));
1072 ac
= &sc
->sc_ad1848
.sc_ad1848
;
1073 for (i
= 0; i
<= 0x1f; i
++)
1074 sc
->sc_codec_scan
[i
] = ad_read(ac
, i
);
1078 ym_restore_codec_regs(struct ym_softc
*sc
)
1080 struct ad1848_softc
*ac
;
1083 DPRINTF(("%s: ym_restore_codec_regs\n", DVNAME(sc
)));
1084 ac
= &sc
->sc_ad1848
.sc_ad1848
;
1085 for (i
= 0; i
<= 0x1f; i
++) {
1087 * Wait til the chip becomes ready.
1088 * This is required after suspend/resume.
1091 t
< 100000 && ADREAD(ac
, AD1848_IADDR
) & SP_IN_INIT
; t
++)
1095 DPRINTF(("%s: ym_restore_codec_regs: reg %d, t %d\n",
1098 ad_write(ac
, i
, sc
->sc_codec_scan
[i
]);
1103 * Save and restore the state on suspending / resumning.
1105 * XXX This is not complete.
1106 * Currently only the parameters, such as output gain, are restored.
1107 * DMA state should also be restored. FIXME.
1110 ym_suspend(device_t self
, pmf_qual_t qual
)
1112 struct ym_softc
*sc
= device_private(self
);
1115 DPRINTF(("%s: ym_power_hook: suspend\n", DVNAME(sc
)));
1122 callout_stop(&sc
->sc_powerdown_ch
);
1123 if (sc
->sc_turning_off
)
1124 ym_powerdown_blocks(sc
);
1127 * Save CODEC registers.
1128 * Note that the registers read incorrect
1129 * if the CODEC part is in power-down mode.
1131 if (sc
->sc_on_blocks
& YM_POWER_CODEC_DIGITAL
)
1132 ym_save_codec_regs(sc
);
1135 * Save OPL3-SA3 control registers and power-down the chip.
1136 * Note that the registers read incorrect
1137 * if the chip is in global power-down mode.
1139 sc
->sc_sa3_scan
[SA3_PWR_MNG
] = ym_read(sc
, SA3_PWR_MNG
);
1140 if (sc
->sc_on_blocks
)
1141 ym_chip_powerdown(sc
);
1147 ym_resume(device_t self
, pmf_qual_t qual
)
1149 struct ym_softc
*sc
= device_private(self
);
1153 DPRINTF(("%s: ym_power_hook: resume\n", DVNAME(sc
)));
1159 ym_chip_powerup(sc
, 1);
1160 ym_init(sc
); /* power-on CODEC */
1162 /* Restore control registers. */
1163 xmax
= YM_IS_SA3(sc
)? YM_SAVE_REG_MAX_SA3
: YM_SAVE_REG_MAX_SA2
;
1164 for (i
= SA3_PWR_MNG
+ 1; i
<= xmax
; i
++) {
1165 if (i
== SA3_SB_SCAN
|| i
== SA3_SB_SCAN_DATA
||
1168 ym_write(sc
, i
, sc
->sc_sa3_scan
[i
]);
1171 /* Restore CODEC registers (including mixer). */
1172 ym_restore_codec_regs(sc
);
1174 /* Restore global/digital power-down state. */
1175 ym_write(sc
, SA3_PWR_MNG
, sc
->sc_sa3_scan
[SA3_PWR_MNG
]);
1177 ym_write(sc
, SA3_DPWRDWN
, sc
->sc_sa3_scan
[SA3_DPWRDWN
]);
1183 ym_codec_power_ctl(void *arg
, int flags
)
1185 struct ym_softc
*sc
;
1186 struct ad1848_softc
*ac
;
1190 ac
= &sc
->sc_ad1848
.sc_ad1848
;
1191 DPRINTF(("%s: ym_codec_power_ctl: flags = 0x%x\n", DVNAME(sc
), flags
));
1195 if (flags
& FREAD
) {
1196 parts
|= YM_POWER_CODEC_R
| YM_POWER_CODEC_AD
;
1197 if (ac
->mute
[AD1848_MONITOR_CHANNEL
] == 0)
1198 parts
|= YM_POWER_CODEC_P
| YM_POWER_CODEC_DA
;
1201 parts
|= YM_POWER_CODEC_P
| YM_POWER_CODEC_DA
;
1203 parts
= YM_POWER_CODEC_P
| YM_POWER_CODEC_R
|
1204 YM_POWER_CODEC_DA
| YM_POWER_CODEC_AD
;
1206 ym_power_ctl(sc
, parts
, flags
);
1212 * Enter Power Save mode or Global Power Down mode.
1213 * Total dissipation becomes 5mA and 10uA (typ.) respective.
1215 * This must be called at splaudio().
1218 ym_chip_powerdown(struct ym_softc
*sc
)
1222 DPRINTF(("%s: ym_chip_powerdown\n", DVNAME(sc
)));
1224 xmax
= YM_IS_SA3(sc
) ? YM_SAVE_REG_MAX_SA3
: YM_SAVE_REG_MAX_SA2
;
1226 /* Save control registers. */
1227 for (i
= SA3_PWR_MNG
+ 1; i
<= xmax
; i
++) {
1228 if (i
== SA3_SB_SCAN
|| i
== SA3_SB_SCAN_DATA
)
1230 sc
->sc_sa3_scan
[i
] = ym_read(sc
, i
);
1232 ym_write(sc
, SA3_PWR_MNG
,
1233 (sc
->sc_pow_mode
== YM_POWER_POWERDOWN
?
1234 SA3_PWR_MNG_PDN
: SA3_PWR_MNG_PSV
) | SA3_PWR_MNG_PDX
);
1238 * Power up from Power Save / Global Power Down Mode.
1240 * We assume no ym interrupt shall occur, since the chip is
1241 * in power-down mode (or should be blocked by splaudio()).
1244 ym_chip_powerup(struct ym_softc
*sc
, int nosleep
)
1249 DPRINTF(("%s: ym_chip_powerup\n", DVNAME(sc
)));
1251 pw
= ym_read(sc
, SA3_PWR_MNG
);
1253 if ((pw
& (SA3_PWR_MNG_PSV
| SA3_PWR_MNG_PDN
| SA3_PWR_MNG_PDX
)) == 0)
1254 return; /* already on */
1256 pw
&= ~SA3_PWR_MNG_PDX
;
1257 ym_write(sc
, SA3_PWR_MNG
, pw
);
1263 tsleep(&wchan
, PWAIT
, "ym_pu1", hz
/ 10);
1265 pw
&= ~(SA3_PWR_MNG_PSV
| SA3_PWR_MNG_PDN
);
1266 ym_write(sc
, SA3_PWR_MNG
, pw
);
1272 tsleep(&wchan
, PWAIT
, "ym_pu2", hz
/ 14);
1274 /* The chip is muted automatically --- unmute it now. */
1275 ym_mute(sc
, SA3_VOL_L
, sc
->master_mute
);
1276 ym_mute(sc
, SA3_VOL_R
, sc
->master_mute
);
1279 /* callout handler for power-down */
1281 ym_powerdown_blocks(void *arg
)
1283 struct ym_softc
*sc
;
1290 on_blocks
= sc
->sc_on_blocks
;
1291 DPRINTF(("%s: ym_powerdown_blocks: turning_off 0x%x\n",
1292 DVNAME(sc
), sc
->sc_turning_off
));
1296 on_blocks
= sc
->sc_on_blocks
;
1298 /* Be sure not to change the state of the chip. Save it first. */
1299 sv
= bus_space_read_1(sc
->sc_iot
, sc
->sc_controlioh
, SA3_CTL_INDEX
);
1301 parts
= sc
->sc_turning_off
;
1303 if (on_blocks
& ~parts
& YM_POWER_CODEC_CTL
)
1304 parts
&= ~(YM_POWER_CODEC_P
| YM_POWER_CODEC_R
);
1305 if (parts
& YM_POWER_CODEC_CTL
) {
1306 if ((on_blocks
& YM_POWER_CODEC_P
) == 0)
1307 parts
|= YM_POWER_CODEC_P
;
1308 if ((on_blocks
& YM_POWER_CODEC_R
) == 0)
1309 parts
|= YM_POWER_CODEC_R
;
1311 parts
&= ~YM_POWER_CODEC_PSEUDO
;
1313 /* If CODEC is being off, save the state. */
1314 if ((sc
->sc_on_blocks
& YM_POWER_CODEC_DIGITAL
) &&
1315 (sc
->sc_on_blocks
& ~sc
->sc_turning_off
&
1316 YM_POWER_CODEC_DIGITAL
) == 0)
1317 ym_save_codec_regs(sc
);
1319 if (YM_IS_SA3(sc
)) {
1321 ym_write(sc
, SA3_DPWRDWN
,
1322 ym_read(sc
, SA3_DPWRDWN
) | (u_int8_t
) parts
);
1323 ym_write(sc
, SA3_APWRDWN
,
1324 ym_read(sc
, SA3_APWRDWN
) | (parts
>> 8));
1326 /* OPL3-SA2 (only OPL3 can be off partially) */
1327 if (parts
& YM_POWER_OPL3
)
1328 ym_write(sc
, SA3_PWR_MNG
,
1329 ym_read(sc
, SA3_PWR_MNG
) | SA2_PWR_MNG_FMPS
);
1332 if (((sc
->sc_on_blocks
&= ~sc
->sc_turning_off
) & YM_POWER_ACTIVE
) == 0)
1333 ym_chip_powerdown(sc
);
1335 sc
->sc_turning_off
= 0;
1337 /* Restore the state of the chip. */
1338 bus_space_write_1(sc
->sc_iot
, sc
->sc_controlioh
, SA3_CTL_INDEX
, sv
);
1344 * Power control entry point.
1347 ym_power_ctl(struct ym_softc
*sc
, int parts
, int onoff
)
1350 int need_restore_codec
;
1352 DPRINTF(("%s: ym_power_ctl: parts = 0x%x, %s\n",
1353 DVNAME(sc
), parts
, onoff
? "on" : "off"));
1356 if (curproc
== NULL
)
1357 panic("ym_power_ctl: no curproc");
1359 /* This function may sleep --- needs locking. */
1360 while (sc
->sc_in_power_ctl
& YM_POWER_CTL_INUSE
) {
1361 sc
->sc_in_power_ctl
|= YM_POWER_CTL_WANTED
;
1362 DPRINTF(("%s: ym_power_ctl: sleeping\n", DVNAME(sc
)));
1363 tsleep(&sc
->sc_in_power_ctl
, PWAIT
, "ym_pc", 0);
1364 DPRINTF(("%s: ym_power_ctl: awaken\n", DVNAME(sc
)));
1366 sc
->sc_in_power_ctl
|= YM_POWER_CTL_INUSE
;
1368 /* Defeat softclock interrupts. */
1371 /* If ON requested to parts which are scheduled to OFF, cancel it. */
1372 if (onoff
&& sc
->sc_turning_off
&& (sc
->sc_turning_off
&= ~parts
) == 0)
1373 callout_stop(&sc
->sc_powerdown_ch
);
1375 if (!onoff
&& sc
->sc_turning_off
)
1376 parts
&= ~sc
->sc_turning_off
;
1378 /* Discard bits which are currently {on,off}. */
1379 parts
&= onoff
? ~sc
->sc_on_blocks
: sc
->sc_on_blocks
;
1381 /* Cancel previous timeout if needed. */
1382 if (parts
!= 0 && sc
->sc_turning_off
)
1383 callout_stop(&sc
->sc_powerdown_ch
);
1388 goto unlock
; /* no work to do */
1391 /* Turning on is done immediately. */
1393 /* If the chip is off, turn it on. */
1394 if ((sc
->sc_on_blocks
& YM_POWER_ACTIVE
) == 0)
1395 ym_chip_powerup(sc
, 0);
1397 need_restore_codec
= (parts
& YM_POWER_CODEC_DIGITAL
) &&
1398 (sc
->sc_on_blocks
& YM_POWER_CODEC_DIGITAL
) == 0;
1400 sc
->sc_on_blocks
|= parts
;
1401 if (parts
& YM_POWER_CODEC_CTL
)
1402 parts
|= YM_POWER_CODEC_P
| YM_POWER_CODEC_R
;
1406 if (YM_IS_SA3(sc
)) {
1408 ym_write(sc
, SA3_DPWRDWN
,
1409 ym_read(sc
, SA3_DPWRDWN
) & (u_int8_t
)~parts
);
1410 ym_write(sc
, SA3_APWRDWN
,
1411 ym_read(sc
, SA3_APWRDWN
) & ~(parts
>> 8));
1413 /* OPL3-SA2 (only OPL3 can be off partially) */
1414 if (parts
& YM_POWER_OPL3
)
1415 ym_write(sc
, SA3_PWR_MNG
,
1416 ym_read(sc
, SA3_PWR_MNG
)
1417 & ~SA2_PWR_MNG_FMPS
);
1419 if (need_restore_codec
)
1420 ym_restore_codec_regs(sc
);
1424 /* Turning off is delayed. */
1425 sc
->sc_turning_off
|= parts
;
1428 /* Schedule turning off. */
1429 if (sc
->sc_pow_mode
!= YM_POWER_NOSAVE
&& sc
->sc_turning_off
)
1430 callout_reset(&sc
->sc_powerdown_ch
, hz
* sc
->sc_pow_timeout
,
1431 ym_powerdown_blocks
, sc
);
1434 if (sc
->sc_in_power_ctl
& YM_POWER_CTL_WANTED
)
1435 wakeup(&sc
->sc_in_power_ctl
);
1436 sc
->sc_in_power_ctl
= 0;
1438 #endif /* not AUDIO_NO_POWER_CTL */