The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isa/ym.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 2cfbada9e0b401949cfec0c06a5a4574


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.