root/dev/isa/ym.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ym_intr
  2. ym_attach
  3. ym_read
  4. ym_write
  5. ym_getdev
  6. ym_mute
  7. ym_set_master_gain
  8. ym_set_mic_gain
  9. ym_set_3d
  10. ym_mixer_set_port
  11. ym_mixer_get_port
  12. ym_query_devinfo
  13. ym_mpu401_open
  14. ym_mpu401_output
  15. ym_mpu401_close
  16. ym_mpu401_getinfo

    1 /* $OpenBSD: ym.c,v 1.13 2006/04/07 22:41:33 jsg Exp $ */
    2 
    3 
    4 /*
    5  * Copyright (c) 1998 Constantine Sapuntzakis. All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 #include "midi.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/errno.h>
   35 #include <sys/ioctl.h>
   36 #include <sys/syslog.h>
   37 #include <sys/device.h>
   38 #include <sys/proc.h>
   39 #include <sys/buf.h>
   40 
   41 #include <machine/cpu.h>
   42 #include <machine/intr.h>
   43 #include <machine/bus.h>
   44 
   45 #include <sys/audioio.h>
   46 #include <dev/audio_if.h>
   47 #include <dev/midi_if.h>
   48 
   49 #include <dev/isa/isavar.h>
   50 #include <dev/isa/isadmavar.h>
   51 
   52 #include <dev/ic/ad1848reg.h>
   53 #include <dev/isa/ad1848var.h>
   54 #include <dev/ic/opl3sa3reg.h>
   55 #include <dev/ic/mpuvar.h>
   56 #include <dev/isa/ymvar.h>
   57 
   58 int ym_getdev(void *, struct audio_device *);
   59 int ym_mixer_set_port(void *, mixer_ctrl_t *);
   60 int ym_mixer_get_port(void *, mixer_ctrl_t *);
   61 int ym_query_devinfo(void *, mixer_devinfo_t *);
   62 int ym_intr(void *);
   63 
   64 static void ym_mute(struct ym_softc *, int, int);
   65 static void ym_set_master_gain(struct ym_softc *, struct ad1848_volume *);
   66 static void ym_set_mic_gain(struct ym_softc *, int);
   67 static void ym_set_3d(struct ym_softc *, mixer_ctrl_t *,
   68         struct ad1848_volume *, int);
   69 
   70 struct audio_hw_if ym_hw_if = {
   71         ad1848_open,
   72         ad1848_close,
   73         NULL,
   74         ad1848_query_encoding,
   75         ad1848_set_params,
   76         ad1848_round_blocksize,
   77         ad1848_commit_settings,
   78         ad1848_dma_init_output,
   79         ad1848_dma_init_input,
   80         ad1848_dma_output,
   81         ad1848_dma_input,
   82         ad1848_halt_out_dma,
   83         ad1848_halt_in_dma,
   84         NULL,
   85         ym_getdev,
   86         NULL,
   87         ym_mixer_set_port,
   88         ym_mixer_get_port,
   89         ym_query_devinfo,
   90         ad1848_malloc,
   91         ad1848_free,
   92         ad1848_round,
   93         ad1848_mappage,
   94         ad1848_get_props,
   95         NULL,
   96         NULL
   97 };
   98 
   99 
  100 struct cfdriver ym_cd = {
  101         NULL, "ym", DV_DULL
  102 };
  103 
  104 struct audio_device ym_device = {
  105         "ym,ad1848",
  106         "",
  107         "ym"
  108 };
  109 
  110 static __inline int ym_read(struct ym_softc *, int);
  111 static __inline void ym_write(struct ym_softc *, int, int);
  112 
  113 #if NMIDI > 0
  114 int     ym_mpu401_open(void *, int, void (*iintr)(void *, int),
  115             void (*ointr)(void *), void *arg);
  116 void    ym_mpu401_close(void *);
  117 int     ym_mpu401_output(void *, int);
  118 void    ym_mpu401_getinfo(void *, struct midi_info *);
  119 
  120 struct midi_hw_if ym_mpu401_hw_if = {
  121         ym_mpu401_open,
  122         ym_mpu401_close,
  123         ym_mpu401_output,
  124         0,              /* flush */
  125         ym_mpu401_getinfo,
  126         0,              /* ioctl */
  127 };
  128 #endif
  129 
  130 int
  131 ym_intr(v)
  132         void   *v;
  133 {
  134 #if NMIDI > 0
  135         struct ym_softc *sc = v;
  136 
  137         if ( /* XXX && */ sc->sc_hasmpu)
  138                 mpu_intr(&sc->sc_mpu_sc);
  139 #endif
  140         return ad1848_intr(v);
  141 }
  142 
  143 void
  144 ym_attach(sc)
  145         struct ym_softc *sc;
  146 
  147 {
  148         struct ad1848_volume vol_mid = {220, 220};
  149 #if NMIDI > 0
  150         struct midi_hw_if *mhw = &ym_mpu401_hw_if;
  151 #endif
  152 
  153         sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->ym_irq, IST_EDGE,
  154             IPL_AUDIO, ym_intr, &sc->sc_ad1848, sc->sc_dev.dv_xname);
  155 
  156         ad1848_attach(&sc->sc_ad1848);
  157         printf("\n");
  158         sc->sc_ad1848.parent = sc;
  159 
  160         /* Establish chip in well known mode */
  161         ym_set_master_gain(sc, &vol_mid);
  162         ym_set_mic_gain(sc, 0);
  163         sc->master_mute = 0;
  164         ym_mute(sc, SA3_VOL_L, sc->master_mute);
  165         ym_mute(sc, SA3_VOL_R, sc->master_mute);
  166 
  167         sc->mic_mute = 1;
  168         ym_mute(sc, SA3_MIC_VOL, sc->mic_mute);
  169 
  170 #if NMIDI > 0
  171         sc->sc_hasmpu = 0;
  172         if (sc->sc_mpu_sc.iobase) {
  173                 sc->sc_mpu_sc.iot = sc->sc_iot;
  174                 if (mpu_find(&sc->sc_mpu_sc)) {
  175                         sc->sc_hasmpu = 1;
  176                         mhw = &ym_mpu401_hw_if;
  177                 }
  178         }
  179         midi_attach_mi(mhw, sc, &sc->sc_dev);
  180 #endif
  181 
  182         audio_attach_mi(&ym_hw_if, &sc->sc_ad1848, &sc->sc_dev);
  183 }
  184 
  185 static __inline int
  186 ym_read(sc, reg)
  187         struct ym_softc *sc;
  188         int     reg;
  189 {
  190         bus_space_write_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_INDEX,
  191             (reg & 0xff));
  192         return (bus_space_read_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_DATA));
  193 }
  194 
  195 static __inline void
  196 ym_write(sc, reg, data)
  197         struct ym_softc *sc;
  198         int     reg;
  199         int     data;
  200 {
  201         bus_space_write_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_INDEX,
  202             (reg & 0xff));
  203         bus_space_write_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_DATA,
  204             (data & 0xff));
  205 }
  206 
  207 
  208 
  209 int
  210 ym_getdev(addr, retp)
  211         void   *addr;
  212         struct audio_device *retp;
  213 {
  214         *retp = ym_device;
  215         return 0;
  216 }
  217 
  218 
  219 static ad1848_devmap_t mappings[] = {
  220         { YM_MIDI_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
  221         { YM_CD_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
  222         { YM_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
  223         { YM_LINE_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL },
  224         { YM_SPEAKER_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
  225         { YM_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL },
  226         { YM_MIDI_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
  227         { YM_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
  228         { YM_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL },
  229         { YM_LINE_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL },
  230         { YM_SPEAKER_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL },
  231         { YM_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL },
  232         { YM_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
  233         { YM_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1 }
  234 };
  235 
  236 #define NUMMAP  (sizeof(mappings) / sizeof(mappings[0]))
  237 
  238 
  239 static void
  240 ym_mute(sc, left_reg, mute)
  241         struct ym_softc *sc;
  242         int     left_reg;
  243         int     mute;
  244 {
  245         u_int8_t reg;
  246 
  247         reg = ym_read(sc, left_reg);
  248         if (mute)
  249                 ym_write(sc, left_reg, reg | 0x80);
  250         else
  251                 ym_write(sc, left_reg, reg & ~0x80);
  252 }
  253 
  254 static void
  255 ym_set_master_gain(sc, vol)
  256         struct ym_softc *sc;
  257         struct ad1848_volume *vol;
  258 {
  259         u_int   atten;
  260 
  261         sc->master_gain = *vol;
  262 
  263         atten = ((AUDIO_MAX_GAIN - vol->left) * (SA3_VOL_MV + 1)) /
  264            (AUDIO_MAX_GAIN + 1);
  265 
  266         ym_write(sc, SA3_VOL_L, (ym_read(sc, SA3_VOL_L) & ~SA3_VOL_MV) | atten);
  267 
  268         atten = ((AUDIO_MAX_GAIN - vol->right) * (SA3_VOL_MV + 1)) /
  269            (AUDIO_MAX_GAIN + 1);
  270 
  271         ym_write(sc, SA3_VOL_R, (ym_read(sc, SA3_VOL_R) & ~SA3_VOL_MV) | atten);
  272 }
  273 
  274 static void
  275 ym_set_mic_gain(sc, vol)
  276         struct ym_softc *sc;
  277         int vol;
  278 {
  279         u_int   atten;
  280 
  281         sc->mic_gain = vol;
  282 
  283         atten = ((AUDIO_MAX_GAIN - vol) * (SA3_MIC_MCV + 1)) /
  284             (AUDIO_MAX_GAIN + 1);
  285 
  286         ym_write(sc, SA3_MIC_VOL,
  287             (ym_read(sc, SA3_MIC_VOL) & ~SA3_MIC_MCV) | atten);
  288 }
  289 
  290 static void
  291 ym_set_3d(sc, cp, val, reg)
  292         struct ym_softc *sc;
  293         mixer_ctrl_t *cp;
  294         struct ad1848_volume *val;
  295         int reg;
  296 {
  297         u_int8_t e;
  298 
  299         ad1848_to_vol(cp, val);
  300 
  301         e = (val->left * (SA3_3D_BITS + 1) + (SA3_3D_BITS + 1) / 2) /
  302                 (AUDIO_MAX_GAIN + 1) << SA3_3D_LSHIFT |
  303             (val->right * (SA3_3D_BITS + 1) + (SA3_3D_BITS + 1) / 2) /
  304                 (AUDIO_MAX_GAIN + 1) << SA3_3D_RSHIFT;
  305 
  306         ym_write(sc, reg, e);
  307 }
  308 
  309 int
  310 ym_mixer_set_port(addr, cp)
  311         void   *addr;
  312         mixer_ctrl_t *cp;
  313 {
  314         struct ad1848_softc *ac = addr;
  315         struct ym_softc *sc = ac->parent;
  316         struct ad1848_volume vol;
  317         int     error = ad1848_mixer_set_port(ac, mappings, NUMMAP, cp);
  318 
  319         if (error != ENXIO)
  320                 return (error);
  321 
  322         error = 0;
  323 
  324         switch (cp->dev) {
  325         case YM_OUTPUT_LVL:
  326                 ad1848_to_vol(cp, &vol);
  327                 ym_set_master_gain(sc, &vol);
  328                 break;
  329 
  330         case YM_OUTPUT_MUTE:
  331                 sc->master_mute = (cp->un.ord != 0);
  332                 ym_mute(sc, SA3_VOL_L, sc->master_mute);
  333                 ym_mute(sc, SA3_VOL_R, sc->master_mute);
  334                 break;
  335 
  336         case YM_MIC_LVL:
  337                 if (cp->un.value.num_channels != 1)
  338                         error = EINVAL;
  339                 else
  340                         ym_set_mic_gain(sc,
  341                             cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
  342                 break;
  343 
  344         case YM_MASTER_EQMODE:
  345                 sc->sc_eqmode = cp->un.ord & SA3_SYS_CTL_YMODE;
  346                 ym_write(sc, SA3_SYS_CTL, (ym_read(sc, SA3_SYS_CTL) &
  347                     ~SA3_SYS_CTL_YMODE) | sc->sc_eqmode);
  348                 break;
  349 
  350         case YM_MASTER_TREBLE:
  351                 ym_set_3d(sc, cp, &sc->sc_treble, SA3_3D_TREBLE);
  352                 break;
  353 
  354         case YM_MASTER_BASS:
  355                 ym_set_3d(sc, cp, &sc->sc_bass, SA3_3D_BASS);
  356                 break;
  357 
  358         case YM_MASTER_WIDE:
  359                 ym_set_3d(sc, cp, &sc->sc_wide, SA3_3D_WIDE);
  360                 break;
  361 
  362         case YM_MIC_MUTE:
  363                 sc->mic_mute = (cp->un.ord != 0);
  364                 ym_mute(sc, SA3_MIC_VOL, sc->mic_mute);
  365                 break;
  366 
  367         default:
  368                 return ENXIO;
  369                 /* NOTREACHED */
  370         }
  371 
  372         return (error);
  373 }
  374 
  375 int
  376 ym_mixer_get_port(addr, cp)
  377         void   *addr;
  378         mixer_ctrl_t *cp;
  379 {
  380         struct ad1848_softc *ac = addr;
  381         struct ym_softc *sc = ac->parent;
  382 
  383         int     error = ad1848_mixer_get_port(ac, mappings, NUMMAP, cp);
  384 
  385         if (error != ENXIO)
  386                 return (error);
  387 
  388         error = 0;
  389 
  390         switch (cp->dev) {
  391         case YM_OUTPUT_LVL:
  392                 ad1848_from_vol(cp, &sc->master_gain);
  393                 break;
  394 
  395         case YM_OUTPUT_MUTE:
  396                 cp->un.ord = sc->master_mute;
  397                 break;
  398 
  399         case YM_MIC_LVL:
  400                 if (cp->un.value.num_channels != 1)
  401                         error = EINVAL;
  402                 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->mic_gain;      
  403                 break;
  404 
  405         case YM_MASTER_EQMODE:
  406                 cp->un.ord = sc->sc_eqmode;
  407                 break;
  408 
  409         case YM_MASTER_TREBLE:
  410                 ad1848_from_vol(cp, &sc->sc_treble);
  411                 break;
  412 
  413         case YM_MASTER_BASS:
  414                 ad1848_from_vol(cp, &sc->sc_bass);
  415                 break;
  416 
  417         case YM_MASTER_WIDE:
  418                 ad1848_from_vol(cp, &sc->sc_wide);
  419                 break;
  420 
  421         case YM_MIC_MUTE:
  422                 cp->un.ord = sc->mic_mute;
  423                 break;
  424 
  425         default:
  426                 error = ENXIO;
  427                 break;
  428         }
  429 
  430         return (error);
  431 }
  432 
  433 static char *mixer_classes[] = {
  434         AudioCinputs, AudioCrecord, AudioCoutputs, AudioCmonitor,
  435         AudioCequalization
  436 };
  437 
  438 int
  439 ym_query_devinfo(addr, dip)
  440         void   *addr;
  441         mixer_devinfo_t *dip;
  442 {
  443         static char *mixer_port_names[] = { AudioNmidi, AudioNcd, AudioNdac,
  444                 AudioNline, AudioNspeaker, AudioNmicrophone, AudioNmonitor
  445         };
  446 
  447         dip->next = dip->prev = AUDIO_MIXER_LAST;
  448 
  449         switch (dip->index) {
  450         case YM_INPUT_CLASS:    /* input class descriptor */
  451         case YM_OUTPUT_CLASS:
  452         case YM_MONITOR_CLASS:
  453         case YM_RECORD_CLASS:
  454         case YM_EQ_CLASS:
  455                 dip->type = AUDIO_MIXER_CLASS;
  456                 dip->mixer_class = dip->index;
  457                 strlcpy(dip->label.name,
  458                     mixer_classes[dip->index - YM_INPUT_CLASS],
  459                     sizeof dip->label.name);
  460                 break;
  461 
  462         case YM_MIDI_LVL:
  463         case YM_CD_LVL:
  464         case YM_DAC_LVL:
  465         case YM_LINE_LVL:
  466         case YM_SPEAKER_LVL:
  467         case YM_MIC_LVL:
  468         case YM_MONITOR_LVL:
  469                 dip->type = AUDIO_MIXER_VALUE;
  470                 if (dip->index == YM_MONITOR_LVL)
  471                         dip->mixer_class = YM_MONITOR_CLASS;
  472                 else
  473                         dip->mixer_class = YM_INPUT_CLASS;
  474 
  475                 dip->next = dip->index + 7;
  476 
  477                 strlcpy(dip->label.name,
  478                     mixer_port_names[dip->index - YM_MIDI_LVL],
  479                     sizeof dip->label.name);
  480 
  481                 if (dip->index == YM_SPEAKER_LVL ||
  482                     dip->index == YM_MIC_LVL)
  483                         dip->un.v.num_channels = 1;
  484                 else
  485                         dip->un.v.num_channels = 2;
  486 
  487                 strlcpy(dip->un.v.units.name, AudioNvolume,
  488                     sizeof dip->un.v.units.name);
  489                 break;
  490 
  491         case YM_MIDI_MUTE:
  492         case YM_CD_MUTE:
  493         case YM_DAC_MUTE:
  494         case YM_LINE_MUTE:
  495         case YM_SPEAKER_MUTE:
  496         case YM_MIC_MUTE:
  497         case YM_MONITOR_MUTE:
  498                 if (dip->index == YM_MONITOR_MUTE)
  499                         dip->mixer_class = YM_MONITOR_CLASS;
  500                 else
  501                         dip->mixer_class = YM_INPUT_CLASS;
  502                 dip->type = AUDIO_MIXER_ENUM;
  503                 dip->prev = dip->index - 7;
  504 mute:
  505                 strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
  506                 dip->un.e.num_mem = 2;
  507                 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
  508                     sizeof dip->un.e.member[0].label.name);
  509                 dip->un.e.member[0].ord = 0;
  510                 strlcpy(dip->un.e.member[1].label.name, AudioNon,
  511                     sizeof dip->un.e.member[1].label.name);
  512                 dip->un.e.member[1].ord = 1;
  513                 break;
  514 
  515 
  516         case YM_OUTPUT_LVL:
  517                 dip->type = AUDIO_MIXER_VALUE;
  518                 dip->mixer_class = YM_OUTPUT_CLASS;
  519                 dip->next = YM_OUTPUT_MUTE;
  520                 strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
  521                 dip->un.v.num_channels = 2;
  522                 strlcpy(dip->un.v.units.name, AudioNvolume,
  523                     sizeof dip->un.v.units.name);
  524                 break;
  525 
  526         case YM_OUTPUT_MUTE:
  527                 dip->mixer_class = YM_OUTPUT_CLASS;
  528                 dip->type = AUDIO_MIXER_ENUM;
  529                 dip->prev = YM_OUTPUT_LVL;
  530                 goto mute;
  531 
  532         case YM_REC_LVL:        /* record level */
  533                 dip->type = AUDIO_MIXER_VALUE;
  534                 dip->mixer_class = YM_RECORD_CLASS;
  535                 dip->next = YM_RECORD_SOURCE;
  536                 strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
  537                 dip->un.v.num_channels = 2;
  538                 strlcpy(dip->un.v.units.name, AudioNvolume,
  539                     sizeof dip->un.v.units.name);
  540                 break;
  541 
  542 
  543         case YM_RECORD_SOURCE:
  544                 dip->mixer_class = YM_RECORD_CLASS;
  545                 dip->type = AUDIO_MIXER_ENUM;
  546                 dip->prev = YM_REC_LVL;
  547                 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
  548                 dip->un.e.num_mem = 4;
  549                 strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone,
  550                     sizeof dip->un.e.member[0].label.name);
  551                 dip->un.e.member[0].ord = MIC_IN_PORT;
  552                 strlcpy(dip->un.e.member[1].label.name, AudioNline,
  553                     sizeof dip->un.e.member[1].label.name);
  554                 dip->un.e.member[1].ord = LINE_IN_PORT;
  555                 strlcpy(dip->un.e.member[2].label.name, AudioNdac,
  556                     sizeof dip->un.e.member[2].label.name);
  557                 dip->un.e.member[2].ord = DAC_IN_PORT;
  558                 strlcpy(dip->un.e.member[3].label.name, AudioNcd,
  559                     sizeof dip->un.e.member[3].label.name);
  560                 dip->un.e.member[3].ord = AUX1_IN_PORT;
  561                 break;
  562 
  563         case YM_MASTER_EQMODE:
  564                 dip->type = AUDIO_MIXER_ENUM;
  565                 dip->mixer_class = YM_EQ_CLASS;
  566                 strlcpy(dip->label.name, AudioNmode, sizeof dip->label.name);
  567                 strlcpy(dip->un.v.units.name, AudioNmode,
  568                     sizeof dip->un.v.units.name);
  569                 dip->un.e.num_mem = 4;
  570                 strlcpy(dip->un.e.member[0].label.name, AudioNdesktop,
  571                     sizeof dip->un.e.member[0].label.name);
  572                 dip->un.e.member[0].ord = SA3_SYS_CTL_YMODE0;
  573                 strlcpy(dip->un.e.member[1].label.name, AudioNlaptop,
  574                     sizeof dip->un.e.member[1].label.name);
  575                 dip->un.e.member[1].ord = SA3_SYS_CTL_YMODE1;
  576                 strlcpy(dip->un.e.member[2].label.name, AudioNsubnote,
  577                     sizeof dip->un.e.member[2].label.name);
  578                 dip->un.e.member[2].ord = SA3_SYS_CTL_YMODE2;
  579                 strlcpy(dip->un.e.member[3].label.name, AudioNhifi,
  580                     sizeof dip->un.e.member[3].label.name);
  581                 dip->un.e.member[3].ord = SA3_SYS_CTL_YMODE3;
  582                 break;
  583 
  584         case YM_MASTER_TREBLE:
  585                 dip->type = AUDIO_MIXER_VALUE;
  586                 dip->mixer_class = YM_EQ_CLASS;
  587                 strlcpy(dip->label.name, AudioNtreble, sizeof dip->label.name);
  588                 dip->un.v.num_channels = 2;
  589                 strlcpy(dip->un.v.units.name, AudioNtreble,
  590                     sizeof dip->un.v.units.name);
  591                 break;
  592 
  593         case YM_MASTER_BASS:
  594                 dip->type = AUDIO_MIXER_VALUE;
  595                 dip->mixer_class = YM_EQ_CLASS;
  596                 strlcpy(dip->label.name, AudioNbass, sizeof dip->label.name);
  597                 dip->un.v.num_channels = 2;
  598                 strlcpy(dip->un.v.units.name, AudioNbass,
  599                     sizeof dip->un.v.units.name);
  600                 break;
  601 
  602         case YM_MASTER_WIDE:
  603                 dip->type = AUDIO_MIXER_VALUE;
  604                 dip->mixer_class = YM_EQ_CLASS;
  605                 strlcpy(dip->label.name, AudioNsurround,
  606                     sizeof dip->label.name);
  607                 dip->un.v.num_channels = 2;
  608                 strlcpy(dip->un.v.units.name, AudioNsurround,
  609                     sizeof dip->un.v.units.name);
  610                 break;
  611 
  612         default:
  613                 return ENXIO;
  614                 /* NOTREACHED */
  615         }
  616 
  617         return 0;
  618 }
  619 #if NMIDI > 0
  620 
  621 #define YMMPU(a) (&((struct ym_softc *)addr)->sc_mpu_sc)
  622 
  623 int
  624 ym_mpu401_open(addr, flags, iintr, ointr, arg)
  625         void   *addr;
  626         int     flags;
  627         void    (*iintr)(void *, int);
  628         void    (*ointr)(void *);
  629         void   *arg;
  630 {
  631         return mpu_open(YMMPU(addr), flags, iintr, ointr, arg);
  632 }
  633 
  634 int
  635 ym_mpu401_output(addr, d)
  636         void   *addr;
  637         int     d;
  638 {
  639         return mpu_output(YMMPU(addr), d);
  640 }
  641 
  642 void
  643 ym_mpu401_close(addr)
  644         void   *addr;
  645 {
  646         mpu_close(YMMPU(addr));
  647 }
  648 
  649 void
  650 ym_mpu401_getinfo(addr, mi)
  651         void   *addr;
  652         struct midi_info *mi;
  653 {
  654         mi->name = "YM MPU-401 UART";
  655         mi->props = 0;
  656 }
  657 #endif

/* [<][>][^][v][top][bottom][index][help] */