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