Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/isa New ym driver.



details:   https://anonhg.NetBSD.org/src/rev/264f7e4206a7
branches:  trunk
changeset: 476971:264f7e4206a7
user:      itohy <itohy%NetBSD.org@localhost>
date:      Tue Oct 05 03:46:08 1999 +0000

description:
New ym driver.
 1. Add power control to reduce power consumption.
    The behavior can be controlled by mixerctl(1).
 2. Add suspend/resume hook to keep the parameters.
    Currently this includes CODEC and control registers but
    does not include the DMA state.  FIXME.
 3. Support "opl at ym" and "mpu at ym" attachment.
    Actually, this is required for power control.
 4. Add support for the on-chip 3D enhancement hardware.
    This includes bass/treble enhancement, wide stereo, and
    the equalization mode.  This can be controlled by mixerctl(1).
 5. Make "audioctl -w play.gain=xxx" work like as
    "mixerctl -w inputs.dac=xxx" and now it changes
    the wave output volume correctly.
 6. Support hardware master volume switches.
 7. Change formula of calculating gain so that all the levels
    should be used equally.
 8. Change "audioctl name" to "OPL3-SA3" and "audioctl version"
    to the version of the chip.

diffstat:

 sys/dev/isa/ym.c    |  1040 ++++++++++++++++++++++++++++++++++++++++++++------
 sys/dev/isa/ymvar.h |   195 ++++++++-
 2 files changed, 1075 insertions(+), 160 deletions(-)

diffs (truncated from 1523 to 300 lines):

diff -r 8639d3ed994e -r 264f7e4206a7 sys/dev/isa/ym.c
--- a/sys/dev/isa/ym.c  Tue Oct 05 03:44:31 1999 +0000
+++ b/sys/dev/isa/ym.c  Tue Oct 05 03:46:08 1999 +0000
@@ -1,9 +1,44 @@
-/* $NetBSD: ym.c,v 1.9 1999/02/18 17:27:39 mycroft Exp $ */
+/*     $NetBSD: ym.c,v 1.10 1999/10/05 03:46:08 itohy Exp $    */
 
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by ITOH Yasufumi.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
 
 /*
  * Copyright (c) 1998 Constantine Sapuntzakis. All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -31,11 +66,16 @@
  *  Original code from OpenBSD.
  */
 
+#include "mpu_ym.h"
+#include "opt_ym.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/errno.h>
 #include <sys/device.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
 
 #include <machine/cpu.h>
 #include <machine/intr.h>
@@ -49,19 +89,64 @@
 
 #include <dev/ic/ad1848reg.h>
 #include <dev/isa/ad1848var.h>
-#include <dev/ic/opl3sa3.h>
+#include <dev/ic/opl3sa3reg.h>
+#include <dev/isa/wssreg.h>
+#if NMPU_YM > 0
+#include <dev/ic/mpuvar.h>
+#endif
 #include <dev/isa/ymvar.h>
+#include <dev/isa/sbreg.h>
 
+#ifndef spllowersoftclock
+ #error "We depend on the new semantics of splsoftclock(9)."
+#endif
+
+/* Power management mode. */
+#ifndef YM_POWER_MODE
+#define YM_POWER_MODE          YM_POWER_POWERSAVE
+#endif
+
+/* Time in second before power down the chip. */
+#ifndef YM_POWER_OFF_SEC
+#define YM_POWER_OFF_SEC       5
+#endif
+
+#ifdef __i386__                /* XXX */
+# include "joy.h"
+#else
+# define NJOY  0
+#endif
+
+#ifdef AUDIO_DEBUG
+#define DPRINTF(x)     if (ymdebug) printf x
+int    ymdebug = 0;
+#else
+#define DPRINTF(x)
+#endif
+#define DVNAME(softc)  ((softc)->sc_ad1848.sc_ad1848.sc_dev.dv_xname)
 
 int    ym_getdev __P((void *, struct audio_device *));
 int    ym_mixer_set_port __P((void *, mixer_ctrl_t *));
 int    ym_mixer_get_port __P((void *, mixer_ctrl_t *));
 int    ym_query_devinfo __P((void *, mixer_devinfo_t *));
+int    ym_intr __P((void *));
+#ifndef AUDIO_NO_POWER_CTL
+static void ym_save_codec_regs __P((struct ym_softc *));
+static void ym_restore_codec_regs __P((struct ym_softc *));
+void   ym_power_hook __P((int, void *));
+int    ym_codec_power_ctl __P((void *, int));
+static void ym_chip_powerdown __P((struct ym_softc *));
+static void ym_chip_powerup __P((struct ym_softc *, int));
+void ym_powerdown_blocks __P((void *));
+void ym_power_ctl __P((struct ym_softc *, int, int));
+#endif
 
+static void ym_init __P((struct ym_softc *));
 static void ym_mute __P((struct ym_softc *, int, int));
 static void ym_set_master_gain __P((struct ym_softc *, struct ad1848_volume*));
-static void ym_set_mic_gain __P((struct ym_softc *, struct ad1848_volume *));
-
+static void ym_set_mic_gain __P((struct ym_softc *, int));
+static void ym_set_3d __P((struct ym_softc *, mixer_ctrl_t *,
+       struct ad1848_volume *, int));
 
 
 struct audio_hw_if ym_hw_if = {
@@ -93,13 +178,6 @@
        ad1848_isa_trigger_input,
 };
 
-
-struct audio_device ym_device = {
-       "ym,ad1848",
-       "",
-       "ym"
-};
-
 static __inline int ym_read __P((struct ym_softc *, int));
 static __inline void ym_write __P((struct ym_softc *, int, int));
 
@@ -109,28 +187,81 @@
 {
        struct ad1848_softc *ac = &sc->sc_ad1848.sc_ad1848;
        struct ad1848_volume vol_mid = {220, 220};
-       struct ad1848_volume vol_0   = {0, 0};
-  
+       struct audio_attach_args arg;
+
        sc->sc_ad1848.sc_ih = isa_intr_establish(sc->sc_ic, sc->ym_irq,
-                                                IST_EDGE, 
-                                                IPL_AUDIO, ad1848_isa_intr,
-                                                &sc->sc_ad1848);
+                                                IST_EDGE, IPL_AUDIO,
+                                                ym_intr, sc);
 
+#ifndef AUDIO_NO_POWER_CTL
+       sc->sc_ad1848.powerctl = ym_codec_power_ctl;
+       sc->sc_ad1848.powerarg = sc;
+#endif
        ad1848_isa_attach(&sc->sc_ad1848);
        printf("\n");
        ac->parent = sc;
 
        /* Establish chip in well known mode */
        ym_set_master_gain(sc, &vol_mid);
-       ym_set_mic_gain(sc, &vol_0);
+       ym_set_mic_gain(sc, 0);
        sc->master_mute = 0;
-       ym_mute(sc, SA3_LCH, sc->master_mute);
-       ym_mute(sc, SA3_RCH, sc->master_mute);
-       
+       ym_mute(sc, SA3_VOL_L, sc->master_mute);
+       ym_mute(sc, SA3_VOL_R, sc->master_mute);
+
        sc->mic_mute = 1;
-       ym_mute(sc, SA3_MIC, sc->mic_mute);
+       ym_mute(sc, SA3_MIC_VOL, sc->mic_mute);
+
+       sc->sc_version = ym_read(sc, SA3_MISC) & SA3_MISC_VER;
+
+       /* We use only one IRQ (IRQ-A). */
+       ym_write(sc, SA3_IRQ_CONF, SA3_IRQ_CONF_MPU_A | SA3_IRQ_CONF_WSS_A);
+       ym_write(sc, SA3_HVOL_INTR_CNF, SA3_HVOL_INTR_CNF_A);
+
+       /* audio at ym attachment */
+       sc->sc_audiodev = audio_attach_mi(&ym_hw_if, ac, &ac->sc_dev);
+
+       /* opl at ym attachment */
+       if (sc->sc_opl_ioh) {
+               arg.type = AUDIODEV_TYPE_OPL;
+               arg.hwif = 0;
+               arg.hdl = 0;
+               (void)config_found(&ac->sc_dev, &arg, audioprint);
+       }
 
-       audio_attach_mi(&ym_hw_if, ac, &ac->sc_dev);
+#if NMPU_YM > 0
+       /* mpu at ym attachment */
+       if (sc->sc_mpu_ioh) {
+               arg.type = AUDIODEV_TYPE_MPU;
+               arg.hwif = 0;
+               arg.hdl = 0;
+               sc->sc_mpudev = config_found(&ac->sc_dev, &arg, audioprint);
+       }
+#endif
+
+       /* This must be AFTER the attachment of sub-devices. */
+       ym_init(sc);
+
+#ifndef AUDIO_NO_POWER_CTL
+       /* 3D enhancement is unused at startup time. */
+       ym_write(sc, SA3_APWRDWN, ym_read(sc, SA3_APWRDWN) | SA3_APWRDWN_WIDE);
+
+       /*
+        * Initialize power control.
+        */
+       sc->sc_pow_mode = YM_POWER_MODE;
+       sc->sc_pow_timeout = YM_POWER_OFF_SEC;
+
+       sc->sc_on_blocks = sc->sc_turning_off =
+               YM_POWER_CODEC_P | YM_POWER_CODEC_R |
+               YM_POWER_OPL3 | YM_POWER_MPU401 | YM_POWER_JOYSTICK |
+               YM_POWER_CODEC_DA | YM_POWER_CODEC_AD | YM_POWER_OPL3_DA;
+#if NJOY > 0
+       sc->sc_on_blocks |= YM_POWER_JOYSTICK;  /* prevents global powerdown */
+#endif
+       ym_powerdown_blocks(sc);
+
+       powerhook_establish(ym_power_hook, sc);
+#endif
 }
 
 static __inline int
@@ -138,9 +269,9 @@
        struct ym_softc *sc;
        int reg;
 {
-       bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, 0x1d);
-       bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, (reg & 0xff));
-       return (bus_space_read_1(sc->sc_iot, sc->sc_controlioh, 1));
+       bus_space_write_1(sc->sc_iot, sc->sc_controlioh,
+                               SA3_CTL_INDEX, (reg & 0xff));
+       return (bus_space_read_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_DATA));
 }
 
 static __inline void
@@ -149,11 +280,59 @@
        int reg;
        int data;
 {
-       bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, 0x1d);
-       bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, (reg & 0xff));
-       bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 1, (data & 0xff));
+       bus_space_write_1(sc->sc_iot, sc->sc_controlioh,
+                               SA3_CTL_INDEX, (reg & 0xff));
+       bus_space_write_1(sc->sc_iot, sc->sc_controlioh,
+                               SA3_CTL_DATA, (data & 0xff));
 }
 
+static void
+ym_init(sc)
+       struct ym_softc *sc;
+{
+       u_int8_t dpd, apd;
+
+       /* Mute SoundBlaster output if possible. */
+       if (sc->sc_sb_ioh) {
+               bus_space_write_1(sc->sc_iot, sc->sc_sb_ioh, SBP_MIXER_ADDR,
+                                 SBP_MASTER_VOL);
+               bus_space_write_1(sc->sc_iot, sc->sc_sb_ioh, SBP_MIXER_DATA,
+                                 0x00);
+       }
+
+       /* Figure out which part can be power down. */
+       dpd = SA3_DPWRDWN_SB            /* we never use SB */
+#if NMPU_YM > 0
+               | (sc->sc_mpu_ioh ? 0 : SA3_DPWRDWN_MPU)
+#else
+               | SA3_DPWRDWN_MPU
+#endif
+#if NJOY == 0
+               | SA3_DPWRDWN_JOY
+#endif
+               | SA3_DPWRDWN_PNP       /* ISA Plug and Play is done */
+               /*
+                * The master clock is for external wavetable synthesizer
+                * OPL4-ML (YMF704) or OPL4-ML2 (YMF721),
+                * and is currently unused.
+                */
+               | SA3_DPWRDWN_MCLKO;
+



Home | Main Index | Thread Index | Old Index