[BACK]Return to wss.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/wss.c, Revision 1.1

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

CVSweb