Source-Changes-HG archive

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

[src/netbsd-1-5]: src/sys/dev/isa Pull up revisions 1.19-1.21 (via patch, req...



details:   https://anonhg.NetBSD.org/src/rev/d4cda8c13ba8
branches:  netbsd-1-5
changeset: 493006:d4cda8c13ba8
user:      he <he%NetBSD.org@localhost>
date:      Wed Mar 27 10:18:04 2002 +0000

description:
Pull up revisions 1.19-1.21 (via patch, requested by itohy):
  Several changes to wss-compatible audio devices:
   o Fix ADPCM playback/recording
   o Add explicit support for OPL3-SA2 (YMF711), fixes PR#14819
   o Add AD1845 support
   o other minor bugfixes and cleanups

diffstat:

 sys/dev/isa/ym.c |  166 ++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 129 insertions(+), 37 deletions(-)

diffs (truncated from 342 to 300 lines):

diff -r 1bb3bd468b9e -r d4cda8c13ba8 sys/dev/isa/ym.c
--- a/sys/dev/isa/ym.c  Wed Mar 27 10:16:06 2002 +0000
+++ b/sys/dev/isa/ym.c  Wed Mar 27 10:18:04 2002 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: ym.c,v 1.14.4.3 2001/05/06 15:05:59 he Exp $   */
+/*     $NetBSD: ym.c,v 1.14.4.4 2002/03/27 10:18:04 he Exp $   */
 
 /*-
- * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * Copyright (c) 1999-2002 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -66,6 +66,9 @@
  *  Original code from OpenBSD.
  */
 
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ym.c,v 1.14.4.4 2002/03/27 10:18:04 he Exp $");
+
 #include "mpu_ym.h"
 #include "opt_ym.h"
 
@@ -168,6 +171,7 @@
 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_hvol_to_master_gain __P((struct ym_softc *));
 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));
@@ -224,6 +228,9 @@
        ym_mute(sc, SA3_VOL_L, 1);
        ym_mute(sc, SA3_VOL_R, 1);
 
+       sc->sc_version = ym_read(sc, SA3_MISC) & SA3_MISC_VER;
+       ac->chip_name = YM_IS_SA3(sc) ? "OPL3-SA3" : "OPL3-SA2";
+
        sc->sc_ad1848.sc_ih = isa_intr_establish(sc->sc_ic, sc->ym_irq,
                                                 IST_EDGE, IPL_AUDIO,
                                                 ym_intr, sc);
@@ -259,8 +266,6 @@
        ac->mute[AD1848_LINE_CHANNEL] = MUTE_ALL;
        /* speaker is muted by default */
 
-       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);
@@ -367,6 +372,14 @@
                                  0x00);
        }
 
+       if (!YM_IS_SA3(sc)) {
+               /* OPL3-SA2 */
+               ym_write(sc, SA3_PWR_MNG, SA2_PWR_MNG_CLKO |
+                   (sc->sc_opl_ioh == 0 ? SA2_PWR_MNG_FMPS : 0));
+               return;
+       }
+
+       /* OPL3-SA3 */
        /* Figure out which part can be power down. */
        dpd = SA3_DPWRDWN_SB            /* we never use SB */
 #if NMPU_YM > 0
@@ -408,8 +421,9 @@
        struct audio_device *retp;
 {
        struct ym_softc *sc = addr;
+       struct ad1848_softc *ac = &sc->sc_ad1848.sc_ad1848;
 
-       strcpy(retp->name, "OPL3-SA3");
+       strcpy(retp->name, ac->chip_name);
        sprintf(retp->version, "%d", sc->sc_version);
        strcpy(retp->config, "ym");
 
@@ -442,7 +456,6 @@
        struct ym_softc *sc;
        int left_reg;
        int mute;
-
 {
        u_int8_t reg;
 
@@ -459,7 +472,7 @@
        struct ym_softc *sc;
        struct ad1848_volume *vol;
 {
-       u_int  atten;
+       u_int atten;
 
        sc->master_gain = *vol;
 
@@ -474,6 +487,43 @@
        ym_write(sc, SA3_VOL_R, (ym_read(sc, SA3_VOL_R) & ~SA3_VOL_MV) | atten);
 }
 
+/*
+ * Read current setting of master volume from hardware
+ * and update the software value if changed.
+ * [SA3] This function clears hardware volume interrupt.
+ */
+static void
+ym_hvol_to_master_gain(sc)
+       struct ym_softc *sc;
+{
+       u_int prevval, val;
+       int changed = 0;
+
+       val = SA3_VOL_MV & ~ym_read(sc, SA3_VOL_L);
+       prevval = (sc->master_gain.left * (SA3_VOL_MV + 1)) /
+           (AUDIO_MAX_GAIN + 1);
+       if (val != prevval) {
+               sc->master_gain.left =
+                   val * ((AUDIO_MAX_GAIN + 1) / (SA3_VOL_MV + 1));
+               changed = 1;
+       }
+
+       val = SA3_VOL_MV & ~ym_read(sc, SA3_VOL_R);
+       prevval = (sc->master_gain.right * (SA3_VOL_MV + 1)) /
+           (AUDIO_MAX_GAIN + 1);
+       if (val != prevval) {
+               sc->master_gain.right =
+                   val * ((AUDIO_MAX_GAIN + 1) / (SA3_VOL_MV + 1));
+               changed = 1;
+       }
+
+#if 0  /* XXX NOT YET */
+       /* Notify the change to async processes. */
+       if (changed && sc->sc_audiodev)
+               mixer_signal(sc->sc_audiodev);
+#endif
+}
+
 static void
 ym_set_mic_gain(sc, vol)
        struct ym_softc *sc;
@@ -538,6 +588,10 @@
                cp->un.value.num_channels, cp->un.value.level[0],
                cp->un.value.level[1]));
 
+       /* SA2 doesn't have equalizer */
+       if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(cp->dev))
+               return ENXIO;
+
 #ifndef AUDIO_NO_POWER_CTL
        /* Power-up chip */
        ym_power_ctl(sc, YM_POWER_CODEC_CTL, 1);
@@ -603,6 +657,7 @@
        case YM_CD_MUTE:
        case YM_LINE_MUTE:
        case YM_SPEAKER_MUTE:
+       case YM_MIC_MUTE:
                extsources = YM_MIXER_TO_XS(cp->dev);
                if (cp->un.ord) {
                        if ((sc->sc_external_sources &= ~extsources) == 0) {
@@ -670,8 +725,27 @@
        struct ym_softc *sc = ac->parent;
        int error;
 
+       /* SA2 doesn't have equalizer */
+       if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(cp->dev))
+               return ENXIO;
+
        switch (cp->dev) {
        case YM_OUTPUT_LVL:
+               if (!YM_IS_SA3(sc)) {
+                       /*
+                        * SA2 doesn't have hardware volume interrupt.
+                        * Read current value and update every time.
+                        */
+#ifndef AUDIO_NO_POWER_CTL
+                       /* Power-up chip */
+                       ym_power_ctl(sc, YM_POWER_CODEC_CTL, 1);
+#endif
+                       ym_hvol_to_master_gain(sc);
+#ifndef AUDIO_NO_POWER_CTL
+                       /* Power-down chip */
+                       ym_power_ctl(sc, YM_POWER_CODEC_CTL, 0);
+#endif
+               }
                ad1848_from_vol(cp, &sc->master_gain);
                return 0;
 
@@ -736,10 +810,10 @@
 
 static char *mixer_classes[] = {
        AudioCinputs, AudioCrecord, AudioCoutputs, AudioCmonitor,
+#ifndef AUDIO_NO_POWER_CTL
+       AudioCpower,
+#endif
        AudioCequalization
-#ifndef AUDIO_NO_POWER_CTL
-       , AudioCpower
-#endif
 };
 
 int
@@ -751,18 +825,24 @@
                AudioNdac, AudioNmidi, AudioNcd, AudioNline, AudioNspeaker,
                AudioNmicrophone, AudioNmonitor
        };
+       struct ad1848_softc *ac = addr;
+       struct ym_softc *sc = ac->parent;
+
+       /* SA2 doesn't have equalizer */
+       if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(dip->index))
+               return ENXIO;
 
        dip->next = dip->prev = AUDIO_MIXER_LAST;
 
        switch(dip->index) {
-       case YM_INPUT_CLASS:                    /* input class descriptor */
+       case YM_INPUT_CLASS:
        case YM_OUTPUT_CLASS:
        case YM_MONITOR_CLASS:
        case YM_RECORD_CLASS:
-       case YM_EQ_CLASS:
 #ifndef AUDIO_NO_POWER_CTL
        case YM_PWR_CLASS:
 #endif
+       case YM_EQ_CLASS:
                dip->type = AUDIO_MIXER_CLASS;
                dip->mixer_class = dip->index;
                strcpy(dip->label.name,
@@ -970,22 +1050,11 @@
                }
 #endif
                /*
-                * Hardware volume interrupt.
+                * Hardware volume interrupt (SA3 only).
                 * Recalculate master volume from the hardware setting.
                 */
-               if (ist & SA3_IRQ_STAT_MV) {
-                       sc->master_gain.left =
-                               (SA3_VOL_MV & ~ym_read(sc, SA3_VOL_L)) *
-                                       (SA3_VOL_MV + 1) + (SA3_VOL_MV + 1) / 2;
-                       sc->master_gain.right =
-                               (SA3_VOL_MV & ~ym_read(sc, SA3_VOL_R)) *
-                                       (SA3_VOL_MV + 1) + (SA3_VOL_MV + 1) / 2;
-
-#if 0  /* XXX NOT YET */
-                       /* Notify the change to async processes. */
-                       if (sc->sc_audiodev)
-                               mixer_signal(sc->sc_audiodev);
-#endif
+               if ((ist & SA3_IRQ_STAT_MV) && YM_IS_SA3(sc)) {
+                       ym_hvol_to_master_gain(sc);
                        processed = 1;
                }
        } while (processed && (ist = ym_read(sc, SA3_IRQA_STAT)));
@@ -1047,7 +1116,7 @@
        void *v;
 {
        struct ym_softc *sc = v;
-       int i;
+       int i, max;
        int s;
 
        DPRINTF(("%s: ym_power_hook: why = %d\n", DVNAME(sc), why));
@@ -1090,7 +1159,8 @@
                ym_init(sc);            /* power-on CODEC */
 
                /* Restore control registers. */
-               for (i = SA3_PWR_MNG + 1; i <= YM_SAVE_REG_MAX; i++) {
+               max = YM_IS_SA3(sc)? YM_SAVE_REG_MAX_SA3 : YM_SAVE_REG_MAX_SA2;
+               for (i = SA3_PWR_MNG + 1; i <= max; i++) {
                        if (i == SA3_SB_SCAN || i == SA3_SB_SCAN_DATA ||
                            i == SA3_DPWRDWN)
                                continue;
@@ -1102,7 +1172,8 @@
 
                /* Restore global/digital power-down state. */
                ym_write(sc, SA3_PWR_MNG, sc->sc_sa3_scan[SA3_PWR_MNG]);
-               ym_write(sc, SA3_DPWRDWN, sc->sc_sa3_scan[SA3_DPWRDWN]);
+               if (YM_IS_SA3(sc))
+                       ym_write(sc, SA3_DPWRDWN, sc->sc_sa3_scan[SA3_DPWRDWN]);
                break;
        case PWR_SOFTSUSPEND:
        case PWR_SOFTSTANDBY:
@@ -1151,12 +1222,14 @@
 ym_chip_powerdown(sc)
        struct ym_softc *sc;
 {
-       int i;
+       int i, max;
 
        DPRINTF(("%s: ym_chip_powerdown\n", DVNAME(sc)));
 
+       max = YM_IS_SA3(sc) ? YM_SAVE_REG_MAX_SA3 : YM_SAVE_REG_MAX_SA2;
+
        /* Save control registers. */
-       for (i = SA3_PWR_MNG + 1; i <= YM_SAVE_REG_MAX; i++) {
+       for (i = SA3_PWR_MNG + 1; i <= max; i++) {
                if (i == SA3_SB_SCAN || i == SA3_SB_SCAN_DATA)
                        continue;
                sc->sc_sa3_scan[i] = ym_read(sc, i);
@@ -1249,8 +1322,18 @@
                                YM_POWER_CODEC_DIGITAL) == 0)
                ym_save_codec_regs(sc);



Home | Main Index | Thread Index | Old Index