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