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