ym.c revision 1.15 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