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/wss.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: wss.c,v 1.60 2002/09/27 15:37:23 provos Exp $  */
    2 
    3 /*
    4  * Copyright (c) 1994 John Brezak
    5  * Copyright (c) 1991-1993 Regents of the University of California.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the Computer Systems
   19  *      Engineering Group at Lawrence Berkeley Laboratory.
   20  * 4. Neither the name of the University nor of the Laboratory may be used
   21  *    to endorse or promote products derived from this software without
   22  *    specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: wss.c,v 1.60 2002/09/27 15:37:23 provos Exp $");
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/device.h>
   44 #include <sys/errno.h>
   45 
   46 #include <machine/cpu.h>
   47 #include <machine/intr.h>
   48 #include <machine/bus.h>
   49 
   50 #include <sys/audioio.h>
   51 #include <dev/audio_if.h>
   52 
   53 #include <dev/isa/isavar.h>
   54 #include <dev/isa/isadmavar.h>
   55 
   56 #include <dev/ic/ad1848reg.h>
   57 #include <dev/ic/cs4231reg.h>
   58 #include <dev/isa/ad1848var.h>
   59 #include <dev/isa/cs4231var.h>
   60 #include <dev/isa/wssreg.h>
   61 #include <dev/isa/wssvar.h>
   62 #include <dev/isa/madreg.h>
   63 
   64 #ifdef AUDIO_DEBUG
   65 #define DPRINTF(x)      if (wssdebug) printf x
   66 int     wssdebug = 0;
   67 #else
   68 #define DPRINTF(x)
   69 #endif
   70 
   71 struct audio_device wss_device = {
   72         "wss,ad1848",
   73         "",
   74         "WSS"
   75 };
   76 
   77 int     wss_getdev __P((void *, struct audio_device *));
   78 
   79 int     wss_mixer_set_port __P((void *, mixer_ctrl_t *));
   80 int     wss_mixer_get_port __P((void *, mixer_ctrl_t *));
   81 int     wss_query_devinfo __P((void *, mixer_devinfo_t *));
   82 
   83 /*
   84  * Define our interface to the higher level audio driver.
   85  */
   86 
   87 struct audio_hw_if wss_hw_if = {
   88         ad1848_isa_open,
   89         ad1848_isa_close,
   90         NULL,
   91         ad1848_query_encoding,
   92         ad1848_set_params,
   93         ad1848_round_blocksize,
   94         ad1848_commit_settings,
   95         NULL,
   96         NULL,
   97         NULL,
   98         NULL,
   99         ad1848_isa_halt_output,
  100         ad1848_isa_halt_input,
  101         NULL,
  102         wss_getdev,
  103         NULL,
  104         wss_mixer_set_port,
  105         wss_mixer_get_port,
  106         wss_query_devinfo,
  107         ad1848_isa_malloc,
  108         ad1848_isa_free,
  109         ad1848_isa_round_buffersize,
  110         ad1848_isa_mappage,
  111         ad1848_isa_get_props,
  112         ad1848_isa_trigger_output,
  113         ad1848_isa_trigger_input,
  114         NULL,
  115 };
  116 
  117 /*
  118  * Attach hardware to driver, attach hardware driver to audio
  119  * pseudo-device driver .
  120  */
  121 void
  122 wssattach(sc)
  123         struct wss_softc *sc;
  124 {
  125         struct ad1848_softc *ac = &sc->sc_ad1848.sc_ad1848;
  126 
  127 #if 0 /* loses on CS423X chips */
  128         int version;
  129 #endif
  130     
  131         madattach(sc);
  132 
  133         sc->sc_ad1848.sc_ih = isa_intr_establish(sc->wss_ic, sc->wss_irq,
  134                                                  IST_EDGE, 
  135                                                  IPL_AUDIO, ad1848_isa_intr,
  136                                                  &sc->sc_ad1848);
  137 
  138         ad1848_isa_attach(&sc->sc_ad1848);
  139     
  140 #if 0 /* loses on CS423X chips */
  141         version = bus_space_read_1(sc->sc_iot, sc->sc_ioh, WSS_STATUS) 
  142                   & WSS_VERSMASK;
  143         printf(" (vers %d)", version);
  144 #endif
  145 
  146         switch(sc->mad_chip_type) {
  147         case MAD_82C928:
  148                 printf(", 82C928");
  149                 break;
  150         case MAD_OTI601D:
  151                 printf(", OTI-601D");
  152                 break;
  153         case MAD_82C929:
  154                 printf(", 82C929");
  155                 break;
  156         case MAD_82C931:
  157                 printf(", 82C931");
  158                 break;
  159         default:
  160                 break;
  161         }
  162         printf("\n");
  163 
  164         ac->parent = sc;
  165 
  166         audio_attach_mi(&wss_hw_if, &sc->sc_ad1848, &ac->sc_dev);
  167 
  168         if (sc->mad_chip_type != MAD_NONE) {
  169                 struct audio_attach_args arg;
  170                 arg.type = AUDIODEV_TYPE_OPL;
  171                 arg.hwif = 0;
  172                 arg.hdl = 0;
  173                 (void)config_found(&ac->sc_dev, &arg, audioprint);
  174         }
  175 }
  176 
  177 int
  178 wss_getdev(addr, retp)
  179         void *addr;
  180         struct audio_device *retp;
  181 {
  182         *retp = wss_device;
  183         return 0;
  184 }
  185 
  186 static ad1848_devmap_t mappings[] = {
  187         { WSS_MIC_IN_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
  188         { WSS_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
  189         { WSS_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
  190         { WSS_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
  191         { WSS_MIC_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
  192         { WSS_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
  193         { WSS_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL },
  194         { WSS_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL },
  195         { WSS_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
  196         { WSS_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
  197 };
  198 
  199 static int nummap = sizeof(mappings) / sizeof(mappings[0]);
  200 
  201 int
  202 wss_mixer_set_port(addr, cp)
  203         void *addr;
  204         mixer_ctrl_t *cp;
  205 {
  206         struct ad1848_softc *ac = addr;
  207 
  208         return (ad1848_mixer_set_port(ac, mappings, nummap, cp));
  209 }
  210 
  211 int
  212 wss_mixer_get_port(addr, cp)
  213         void *addr;
  214         mixer_ctrl_t *cp;
  215 {
  216         struct ad1848_softc *ac = addr;
  217 
  218         return (ad1848_mixer_get_port(ac, mappings, nummap, cp));
  219 }
  220 
  221 int
  222 wss_query_devinfo(addr, dip)
  223         void *addr;
  224         mixer_devinfo_t *dip;
  225 {
  226         DPRINTF(("wss_query_devinfo: index=%d\n", dip->index));
  227 
  228         switch(dip->index) {
  229         case WSS_MIC_IN_LVL:    /* Microphone */
  230                 dip->type = AUDIO_MIXER_VALUE;
  231                 dip->mixer_class = WSS_INPUT_CLASS;
  232                 dip->prev = AUDIO_MIXER_LAST;
  233                 dip->next = WSS_MIC_IN_MUTE;
  234                 strcpy(dip->label.name, AudioNmicrophone);
  235                 dip->un.v.num_channels = 2;
  236                 strcpy(dip->un.v.units.name, AudioNvolume);
  237                 break;
  238                 
  239         case WSS_LINE_IN_LVL:   /* line/CD */
  240                 dip->type = AUDIO_MIXER_VALUE;
  241                 dip->mixer_class = WSS_INPUT_CLASS;
  242                 dip->prev = AUDIO_MIXER_LAST;
  243                 dip->next = WSS_LINE_IN_MUTE;
  244                 strcpy(dip->label.name, AudioNcd);
  245                 dip->un.v.num_channels = 2;
  246                 strcpy(dip->un.v.units.name, AudioNvolume);
  247                 break;
  248                 
  249         case WSS_DAC_LVL:               /*  dacout */
  250                 dip->type = AUDIO_MIXER_VALUE;
  251                 dip->mixer_class = WSS_INPUT_CLASS;
  252                 dip->prev = AUDIO_MIXER_LAST;
  253                 dip->next = WSS_DAC_MUTE;
  254                 strcpy(dip->label.name, AudioNdac);
  255                 dip->un.v.num_channels = 2;
  256                 strcpy(dip->un.v.units.name, AudioNvolume);
  257                 break;
  258                 
  259         case WSS_REC_LVL:       /* record level */
  260                 dip->type = AUDIO_MIXER_VALUE;
  261                 dip->mixer_class = WSS_RECORD_CLASS;
  262                 dip->prev = AUDIO_MIXER_LAST;
  263                 dip->next = WSS_RECORD_SOURCE;
  264                 strcpy(dip->label.name, AudioNrecord);
  265                 dip->un.v.num_channels = 2;
  266                 strcpy(dip->un.v.units.name, AudioNvolume);
  267                 break;
  268                 
  269         case WSS_MONITOR_LVL:   /* monitor level */
  270                 dip->type = AUDIO_MIXER_VALUE;
  271                 dip->mixer_class = WSS_MONITOR_CLASS;
  272                 dip->prev = AUDIO_MIXER_LAST;
  273                 dip->next = WSS_MONITOR_MUTE;
  274                 strcpy(dip->label.name, AudioNmonitor);
  275                 dip->un.v.num_channels = 1;
  276                 strcpy(dip->un.v.units.name, AudioNvolume);
  277                 break;
  278                 
  279         case WSS_INPUT_CLASS:                   /* input class descriptor */
  280                 dip->type = AUDIO_MIXER_CLASS;
  281                 dip->mixer_class = WSS_INPUT_CLASS;
  282                 dip->next = dip->prev = AUDIO_MIXER_LAST;
  283                 strcpy(dip->label.name, AudioCinputs);
  284                 break;
  285                 
  286         case WSS_MONITOR_CLASS:                 /* monitor class descriptor */
  287                 dip->type = AUDIO_MIXER_CLASS;
  288                 dip->mixer_class = WSS_MONITOR_CLASS;
  289                 dip->next = dip->prev = AUDIO_MIXER_LAST;
  290                 strcpy(dip->label.name, AudioCmonitor);
  291                 break;
  292                 
  293         case WSS_RECORD_CLASS:                  /* record source class */
  294                 dip->type = AUDIO_MIXER_CLASS;
  295                 dip->mixer_class = WSS_RECORD_CLASS;
  296                 dip->next = dip->prev = AUDIO_MIXER_LAST;
  297                 strcpy(dip->label.name, AudioCrecord);
  298                 break;
  299                 
  300         case WSS_MIC_IN_MUTE:
  301                 dip->mixer_class = WSS_INPUT_CLASS;
  302                 dip->type = AUDIO_MIXER_ENUM;
  303                 dip->prev = WSS_MIC_IN_LVL;
  304                 dip->next = AUDIO_MIXER_LAST;
  305                 goto mute;
  306                 
  307         case WSS_LINE_IN_MUTE:
  308                 dip->mixer_class = WSS_INPUT_CLASS;
  309                 dip->type = AUDIO_MIXER_ENUM;
  310                 dip->prev = WSS_LINE_IN_LVL;
  311                 dip->next = AUDIO_MIXER_LAST;
  312                 goto mute;
  313                 
  314         case WSS_DAC_MUTE:
  315                 dip->mixer_class = WSS_INPUT_CLASS;
  316                 dip->type = AUDIO_MIXER_ENUM;
  317                 dip->prev = WSS_DAC_LVL;
  318                 dip->next = AUDIO_MIXER_LAST;
  319                 goto mute;
  320 
  321         case WSS_MONITOR_MUTE:
  322                 dip->mixer_class = WSS_MONITOR_CLASS;
  323                 dip->type = AUDIO_MIXER_ENUM;
  324                 dip->prev = WSS_MONITOR_LVL;
  325                 dip->next = AUDIO_MIXER_LAST;
  326         mute:
  327                 strcpy(dip->label.name, AudioNmute);
  328                 dip->un.e.num_mem = 2;
  329                 strcpy(dip->un.e.member[0].label.name, AudioNoff);
  330                 dip->un.e.member[0].ord = 0;
  331                 strcpy(dip->un.e.member[1].label.name, AudioNon);
  332                 dip->un.e.member[1].ord = 1;
  333                 break;
  334                 
  335         case WSS_RECORD_SOURCE:
  336                 dip->mixer_class = WSS_RECORD_CLASS;
  337                 dip->type = AUDIO_MIXER_ENUM;
  338                 dip->prev = WSS_REC_LVL;
  339                 dip->next = AUDIO_MIXER_LAST;
  340                 strcpy(dip->label.name, AudioNsource);
  341                 dip->un.e.num_mem = 3;
  342                 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
  343                 dip->un.e.member[0].ord = WSS_MIC_IN_LVL;
  344                 strcpy(dip->un.e.member[1].label.name, AudioNcd);
  345                 dip->un.e.member[1].ord = WSS_LINE_IN_LVL;
  346                 strcpy(dip->un.e.member[2].label.name, AudioNdac);
  347                 dip->un.e.member[2].ord = WSS_DAC_LVL;
  348                 break;
  349 
  350         default:
  351                 return ENXIO;
  352                 /*NOTREACHED*/
  353         }
  354         DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
  355         
  356         return 0;
  357 }
  358 
  359 
  360 /*
  361  * Copyright by Hannu Savolainen 1994
  362  *
  363  * Redistribution and use in source and binary forms, with or without
  364  * modification, are permitted provided that the following conditions are
  365  * met: 1. Redistributions of source code must retain the above copyright
  366  * notice, this list of conditions and the following disclaimer. 2.
  367  * Redistributions in binary form must reproduce the above copyright notice,
  368  * this list of conditions and the following disclaimer in the documentation
  369  * and/or other materials provided with the distribution.
  370  *
  371  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  372  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  373  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  374  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  375  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  376  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  377  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  378  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  379  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  380  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  381  * SUCH DAMAGE.
  382  *
  383  */
  384 /*
  385  * Initialization code for OPTi MAD16 compatible audio chips. Including
  386  *
  387  *      OPTi 82C928     MAD16           (replaced by C929)
  388  *      OAK OTI-601D    Mozart
  389  *      OPTi 82C929     MAD16 Pro
  390  *
  391  */
  392 
  393 u_int
  394 mad_read(sc, port)
  395         struct wss_softc *sc;
  396         int port;
  397 {
  398         u_int tmp;
  399         int pwd;
  400         int s;
  401         
  402         switch (sc->mad_chip_type) {    /* Output password */
  403         case MAD_82C928:
  404         case MAD_OTI601D:
  405                 pwd = M_PASSWD_928;
  406                 break;
  407         case MAD_82C929:
  408                 pwd = M_PASSWD_929;
  409                 break;
  410         case MAD_82C931:
  411                 pwd = M_PASSWD_931;
  412                 break;
  413         default:
  414                 panic("mad_read: Bad chip type=%d", sc->mad_chip_type);
  415         }
  416         s = splaudio();         /* don't want an interrupt between outb&inb */
  417         bus_space_write_1(sc->sc_iot, sc->mad_ioh, MC_PASSWD_REG, pwd);
  418         tmp = bus_space_read_1(sc->sc_iot, sc->mad_ioh, port);
  419         splx(s);
  420         return tmp;
  421 }
  422 
  423 void
  424 mad_write(sc, port, value)
  425         struct wss_softc *sc;
  426         int port;
  427         int value;
  428 {
  429         int pwd;
  430         int s;
  431         
  432         switch (sc->mad_chip_type) {    /* Output password */
  433         case MAD_82C928:
  434         case MAD_OTI601D:
  435                 pwd = M_PASSWD_928;
  436                 break;
  437         case MAD_82C929:
  438                 pwd = M_PASSWD_929;
  439                 break;
  440         case MAD_82C931:
  441                 pwd = M_PASSWD_931;
  442                 break;
  443         default:
  444                 panic("mad_write: Bad chip type=%d", sc->mad_chip_type);
  445         }
  446         s = splaudio();
  447         bus_space_write_1(sc->sc_iot, sc->mad_ioh, MC_PASSWD_REG, pwd);
  448         bus_space_write_1(sc->sc_iot, sc->mad_ioh, port, value & 0xff);
  449         splx(s);
  450 }
  451 
  452 void
  453 madattach(sc)
  454         struct wss_softc *sc;
  455 {
  456         struct ad1848_softc *ac = (struct ad1848_softc *)&sc->sc_ad1848;
  457         unsigned char cs4231_mode;
  458         int joy;
  459         
  460         if (sc->mad_chip_type == MAD_NONE)
  461                 return;
  462         
  463         /* Do we want the joystick disabled? */
  464         joy = ac->sc_dev.dv_cfdata->cf_flags & 2 ? MC1_JOYDISABLE : 0;
  465         
  466         /* enable WSS emulation at the I/O port */
  467         mad_write(sc, MC1_PORT, M_WSS_PORT_SELECT(sc->mad_ioindex) | joy);
  468         mad_write(sc, MC2_PORT, MC2_NO_CD_DRQ); /* disable CD */
  469         mad_write(sc, MC3_PORT, 0xf0); /* Disable SB */
  470         
  471         cs4231_mode = 
  472                 strncmp(ac->chip_name, "CS4248", 6) == 0 ||
  473                 strncmp(ac->chip_name, "CS4231", 6) == 0 ? 0x02 : 0;
  474         
  475         if (sc->mad_chip_type == MAD_82C929) {
  476                 mad_write(sc, MC4_PORT, 0x92);
  477                 mad_write(sc, MC5_PORT, 0xA5 | cs4231_mode);
  478                 mad_write(sc, MC6_PORT, 0x03);  /* Disable MPU401 */
  479         } else {
  480                 mad_write(sc, MC4_PORT, 0x02);
  481                 mad_write(sc, MC5_PORT, 0x30 | cs4231_mode);
  482         }
  483         
  484 #ifdef AUDIO_DEBUG
  485         if (wssdebug) {
  486                 int i;
  487                 for (i = MC1_PORT; i <= MC7_PORT; i++)
  488                         DPRINTF(("port %03x after init = %02x\n", 
  489                                  i, mad_read(sc, i)));
  490         }
  491 #endif
  492 }

Cache object: 1d22155790b32fca2d4bf8fe506dac4f


[ 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.