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

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

1.1     ! nbrk        1: /*     $OpenBSD: ad1848.c,v 1.32 2005/05/22 19:40:51 art Exp $ */
        !             2: /*     $NetBSD: ad1848.c,v 1.45 1998/01/30 02:02:38 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: /*
        !            40:  * Copyright by Hannu Savolainen 1994
        !            41:  *
        !            42:  * Redistribution and use in source and binary forms, with or without
        !            43:  * modification, are permitted provided that the following conditions are
        !            44:  * met: 1. Redistributions of source code must retain the above copyright
        !            45:  * notice, this list of conditions and the following disclaimer. 2.
        !            46:  * Redistributions in binary form must reproduce the above copyright notice,
        !            47:  * this list of conditions and the following disclaimer in the documentation
        !            48:  * and/or other materials provided with the distribution.
        !            49:  *
        !            50:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
        !            51:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            52:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            53:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
        !            54:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            55:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            56:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
        !            57:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            58:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            59:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            60:  * SUCH DAMAGE.
        !            61:  *
        !            62:  */
        !            63: /*
        !            64:  * Portions of this code are from the VOXware support for the ad1848
        !            65:  * by Hannu Savolainen <hannu@voxware.pp.fi>
        !            66:  *
        !            67:  * Portions also supplied from the SoundBlaster driver for NetBSD.
        !            68:  */
        !            69:
        !            70: #include <sys/param.h>
        !            71: #include <sys/systm.h>
        !            72: #include <sys/errno.h>
        !            73: #include <sys/ioctl.h>
        !            74: #include <sys/syslog.h>
        !            75: #include <sys/device.h>
        !            76: #include <sys/proc.h>
        !            77: #include <sys/buf.h>
        !            78:
        !            79: #include <machine/cpu.h>
        !            80: #include <machine/bus.h>
        !            81:
        !            82: #include <sys/audioio.h>
        !            83:
        !            84: #include <dev/audio_if.h>
        !            85: #include <dev/auconv.h>
        !            86:
        !            87: #include <dev/isa/isavar.h>
        !            88: #include <dev/isa/isadmavar.h>
        !            89:
        !            90: #include <dev/ic/ad1848reg.h>
        !            91: #include <dev/ic/cs4231reg.h>
        !            92: #include <dev/isa/ad1848var.h>
        !            93: #include <dev/isa/cs4231var.h>
        !            94:
        !            95: #ifdef AUDIO_DEBUG
        !            96: #define DPRINTF(x)     if (ad1848debug) printf x
        !            97: int    ad1848debug = 0;
        !            98: #else
        !            99: #define DPRINTF(x)
        !           100: #endif
        !           101:
        !           102: /*
        !           103:  * Initial values for the indirect registers of CS4248/AD1848.
        !           104:  */
        !           105: static int ad1848_init_values[] = {
        !           106:                        /* Left Input Control */
        !           107:     GAIN_12|INPUT_MIC_GAIN_ENABLE,
        !           108:                        /* Right Input Control */
        !           109:     GAIN_12|INPUT_MIC_GAIN_ENABLE,
        !           110:     ATTEN_12,          /* Left Aux #1 Input Control */
        !           111:     ATTEN_12,          /* Right Aux #1 Input Control */
        !           112:     ATTEN_12,          /* Left Aux #2 Input Control */
        !           113:     ATTEN_12,          /* Right Aux #2 Input Control */
        !           114:     /* bits 5-0 are attenuation select */
        !           115:     ATTEN_12,          /* Left DAC output Control */
        !           116:     ATTEN_12,          /* Right DAC output Control */
        !           117:                        /* Clock and Data Format */
        !           118:     CLOCK_XTAL1|FMT_PCM8,
        !           119:                        /* Interface Config */
        !           120:     SINGLE_DMA|AUTO_CAL_ENABLE,
        !           121:     INTERRUPT_ENABLE,  /* Pin control */
        !           122:     0x00,              /* Test and Init */
        !           123:     MODE2,             /* Misc control */
        !           124:     ATTEN_0<<2,                /* Digital Mix Control */
        !           125:     0,                 /* Upper base Count */
        !           126:     0,                 /* Lower base Count */
        !           127:
        !           128:     /* These are for CS4231 &c. only (additional registers): */
        !           129:     0,                 /* Alt feature 1 */
        !           130:     0,                 /* Alt feature 2 */
        !           131:     ATTEN_12,          /* Left line in */
        !           132:     ATTEN_12,          /* Right line in */
        !           133:     0,                 /* Timer low */
        !           134:     0,                 /* Timer high */
        !           135:     0,                 /* unused */
        !           136:     0,                 /* unused */
        !           137:     0,                 /* IRQ status */
        !           138:     0,                 /* unused */
        !           139:                        /* Mono input (a.k.a speaker) (mic) Control */
        !           140:     MONO_INPUT_MUTE|ATTEN_6,           /* mute speaker by default */
        !           141:     0,                 /* unused */
        !           142:     0,                 /* record format */
        !           143:     0,                 /* Crystal Clock Select */
        !           144:     0,                 /* upper record count */
        !           145:     0                  /* lower record count */
        !           146: };
        !           147:
        !           148: void   ad1848_reset(struct ad1848_softc *);
        !           149: int    ad1848_set_speed(struct ad1848_softc *, u_long *);
        !           150: void   ad1848_mute_monitor(void *, int);
        !           151:
        !           152: static int ad_read(struct ad1848_softc *, int);
        !           153: static void ad_write(struct ad1848_softc *, int, int);
        !           154: static void ad_set_MCE(struct ad1848_softc *, int);
        !           155: static void wait_for_calibration(struct ad1848_softc *);
        !           156:
        !           157: #define ADREAD(sc, addr) bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (sc)->sc_iooffs+(addr))
        !           158: #define ADWRITE(sc, addr, data) bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (sc)->sc_iooffs+(addr), (data))
        !           159:
        !           160: static int
        !           161: ad_read(sc, reg)
        !           162:     struct ad1848_softc *sc;
        !           163:     int reg;
        !           164: {
        !           165:     int x, s;
        !           166:
        !           167:     s = splaudio();
        !           168:     ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit);
        !           169:     x = ADREAD(sc, AD1848_IDATA);
        !           170:     splx(s);
        !           171:     /*  printf("(%02x<-%02x) ", reg|sc->MCE_bit, x); */
        !           172:
        !           173:     return x;
        !           174: }
        !           175:
        !           176: static void
        !           177: ad_write(sc, reg, data)
        !           178:     struct ad1848_softc *sc;
        !           179:     int reg;
        !           180:     int data;
        !           181: {
        !           182:     int s = splaudio();
        !           183:     ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit);
        !           184:     ADWRITE(sc, AD1848_IDATA, data & 0xff);
        !           185:     splx(s);
        !           186:     /* printf("(%02x->%02x) ", reg|sc->MCE_bit, data); */
        !           187: }
        !           188:
        !           189: static void
        !           190: ad_set_MCE(sc, state)
        !           191:     struct ad1848_softc *sc;
        !           192:     int state;
        !           193: {
        !           194:     if (state)
        !           195:        sc->MCE_bit = MODE_CHANGE_ENABLE;
        !           196:     else
        !           197:        sc->MCE_bit = 0;
        !           198:
        !           199:     ADWRITE(sc, AD1848_IADDR, sc->MCE_bit);
        !           200: }
        !           201:
        !           202: static void
        !           203: wait_for_calibration(sc)
        !           204:     struct ad1848_softc *sc;
        !           205: {
        !           206:     int timeout;
        !           207:
        !           208:     DPRINTF(("ad1848: Auto calibration started.\n"));
        !           209:     /*
        !           210:      * Wait until the auto calibration process has finished.
        !           211:      *
        !           212:      * 1) Wait until the chip becomes ready (reads don't return 0x80).
        !           213:      * 2) Wait until the ACI bit of I11 gets on and then off.
        !           214:      */
        !           215:     timeout = 100000;
        !           216:     while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
        !           217:        timeout--;
        !           218:
        !           219:     if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
        !           220:        DPRINTF(("ad1848: Auto calibration timed out(1).\n"));
        !           221:
        !           222:     ADWRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
        !           223:     timeout = 100000;
        !           224:     while (timeout > 0 && ADREAD(sc, AD1848_IADDR) != SP_TEST_AND_INIT)
        !           225:        timeout--;
        !           226:
        !           227:     if (ADREAD(sc, AD1848_IADDR) == SP_TEST_AND_INIT)
        !           228:        DPRINTF(("ad1848: Auto calibration timed out(1.5).\n"));
        !           229:
        !           230:     if (!(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) {
        !           231:        timeout = 100000;
        !           232:        while (timeout > 0 && !(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG))
        !           233:            timeout--;
        !           234:
        !           235:        if (!(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG))
        !           236:            DPRINTF(("ad1848: Auto calibration timed out(2).\n"));
        !           237:     }
        !           238:
        !           239:     timeout = 100000;
        !           240:     while (timeout > 0 && ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)
        !           241:        timeout--;
        !           242:     if (ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)
        !           243:         DPRINTF(("ad1848: Auto calibration timed out(3).\n"));
        !           244: }
        !           245:
        !           246: #ifdef AUDIO_DEBUG
        !           247: void ad1848_dump_regs(struct ad1848_softc *);
        !           248:
        !           249: void
        !           250: ad1848_dump_regs(sc)
        !           251:     struct ad1848_softc *sc;
        !           252: {
        !           253:     int i;
        !           254:     u_char r;
        !           255:
        !           256:     printf("ad1848 status=%02x", ADREAD(sc, AD1848_STATUS));
        !           257:     printf(" regs: ");
        !           258:     for (i = 0; i < 16; i++) {
        !           259:        r = ad_read(sc, i);
        !           260:        printf("%02x ", r);
        !           261:     }
        !           262:     if (sc->mode == 2) {
        !           263:            for (i = 16; i < 32; i++) {
        !           264:                    r = ad_read(sc, i);
        !           265:                    printf("%02x ", r);
        !           266:            }
        !           267:     }
        !           268:     printf("\n");
        !           269: }
        !           270: #endif
        !           271:
        !           272: /*
        !           273:  * Map and probe for the ad1848 chip
        !           274:  */
        !           275: int
        !           276: ad1848_mapprobe(sc, iobase)
        !           277:     struct ad1848_softc *sc;
        !           278:     int iobase;
        !           279: {
        !           280:     if (!AD1848_BASE_VALID(iobase)) {
        !           281: #ifdef AUDIO_DEBUG
        !           282:        printf("ad1848: configured iobase %04x invalid\n", iobase);
        !           283: #endif
        !           284:        return 0;
        !           285:     }
        !           286:
        !           287:     sc->sc_iooffs = 0;
        !           288:     /* Map the AD1848 ports */
        !           289:     if (bus_space_map(sc->sc_iot, iobase, AD1848_NPORT, 0, &sc->sc_ioh))
        !           290:        return 0;
        !           291:
        !           292:     if (!ad1848_probe(sc)) {
        !           293:        bus_space_unmap(sc->sc_iot, sc->sc_ioh, AD1848_NPORT);
        !           294:        return 0;
        !           295:     } else
        !           296:        return 1;
        !           297: }
        !           298:
        !           299: /*
        !           300:  * Probe for the ad1848 chip
        !           301:  */
        !           302: int
        !           303: ad1848_probe(sc)
        !           304:     struct ad1848_softc *sc;
        !           305: {
        !           306:     u_char tmp, tmp1 = 0xff, tmp2 = 0xff;
        !           307: #if 0
        !           308:     int i;
        !           309: #endif
        !           310:
        !           311:     /* Is there an ad1848 chip ? */
        !           312:     sc->MCE_bit = MODE_CHANGE_ENABLE;
        !           313:     sc->mode = 1;      /* MODE 1 = original ad1848/ad1846/cs4248 */
        !           314:
        !           315:     /*
        !           316:      * Check that the I/O address is in use.
        !           317:      *
        !           318:      * The SP_IN_INIT bit of the base I/O port is known to be 0 after the
        !           319:      * chip has performed its power-on initialization. Just assume
        !           320:      * this has happened before the OS is starting.
        !           321:      *
        !           322:      * If the I/O address is unused, inb() typically returns 0xff.
        !           323:      */
        !           324:     tmp = ADREAD(sc, AD1848_IADDR);
        !           325:     if (tmp & SP_IN_INIT) { /* Not a AD1848 */
        !           326: #if 0
        !           327:        DPRINTF(("ad_detect_A %x\n", tmp));
        !           328: #endif
        !           329:        goto bad;
        !           330:     }
        !           331:
        !           332:     /*
        !           333:      * Test if it's possible to change contents of the indirect registers.
        !           334:      * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only
        !           335:      * so try to avoid using it.
        !           336:      */
        !           337:     ad_write(sc, 0, 0xaa);
        !           338:     ad_write(sc, 1, 0x45);     /* 0x55 with bit 0x10 clear */
        !           339:
        !           340:     if ((tmp1 = ad_read(sc, 0)) != 0xaa ||
        !           341:        (tmp2 = ad_read(sc, 1)) != 0x45) {
        !           342:        DPRINTF(("ad_detect_B (%x/%x)\n", tmp1, tmp2));
        !           343:        goto bad;
        !           344:     }
        !           345:
        !           346:     ad_write(sc, 0, 0x45);
        !           347:     ad_write(sc, 1, 0xaa);
        !           348:
        !           349:     if ((tmp1 = ad_read(sc, 0)) != 0x45 ||
        !           350:        (tmp2 = ad_read(sc, 1)) != 0xaa) {
        !           351:        DPRINTF(("ad_detect_C (%x/%x)\n", tmp1, tmp2));
        !           352:        goto bad;
        !           353:     }
        !           354:
        !           355:     /*
        !           356:      * The indirect register I12 has some read only bits. Lets
        !           357:      * try to change them.
        !           358:      */
        !           359:     tmp = ad_read(sc, SP_MISC_INFO);
        !           360:     ad_write(sc, SP_MISC_INFO, (~tmp) & 0x0f);
        !           361:
        !           362:     if ((tmp & 0x0f) != ((tmp1 = ad_read(sc, SP_MISC_INFO)) & 0x0f)) {
        !           363:        DPRINTF(("ad_detect_D (%x)\n", tmp1));
        !           364:        goto bad;
        !           365:     }
        !           366:
        !           367:     /*
        !           368:      * MSB and 4 LSBs of the reg I12 tell the chip revision.
        !           369:      *
        !           370:      * A preliminary version of the AD1846 data sheet stated that it
        !           371:      * used an ID field of 0x0B.  The current version, however,
        !           372:      * states that the AD1846 uses ID 0x0A, just like the AD1848K.
        !           373:      *
        !           374:      * this switch statement will need updating as newer clones arrive....
        !           375:      */
        !           376:     switch (tmp1 & 0x8f) {
        !           377:     case 0x09:
        !           378:        sc->chip_name = "AD1848J";
        !           379:        break;
        !           380:     case 0x0A:
        !           381:        sc->chip_name = "AD1848K";
        !           382:        break;
        !           383: #if 0  /* See above */
        !           384:     case 0x0B:
        !           385:        sc->chip_name = "AD1846";
        !           386:        break;
        !           387: #endif
        !           388:     case 0x81:
        !           389:        sc->chip_name = "CS4248revB"; /* or CS4231 rev B; see below */
        !           390:        break;
        !           391:     case 0x89:
        !           392:        sc->chip_name = "CS4248";
        !           393:        break;
        !           394:     case 0x8A:
        !           395:        sc->chip_name = "broken"; /* CS4231/AD1845; see below */
        !           396:        break;
        !           397:     default:
        !           398:        sc->chip_name = "unknown";
        !           399:        DPRINTF(("ad1848: unknown codec version %#02X\n", (tmp1 & 0x8f)));
        !           400:     }
        !           401:
        !           402: #if 0
        !           403:     /*
        !           404:      * XXX I don't know why, but this probe fails on an otherwise well-working
        !           405:      * AW35/pro card, so I'll just take it out for now. [niklas@openbsd.org]
        !           406:      */
        !           407:
        !           408:     /*
        !           409:      * The original AD1848/CS4248 has just 16 indirect registers. This means
        !           410:      * that I0 and I16 should return the same value (etc.).
        !           411:      * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails
        !           412:      * with CS4231, AD1845, etc.
        !           413:      */
        !           414:     ad_write(sc, SP_MISC_INFO, 0);     /* Mode2 = disabled */
        !           415:
        !           416:     for (i = 0; i < 16; i++)
        !           417:        if ((tmp1 = ad_read(sc, i)) != (tmp2 = ad_read(sc, i + 16))) {
        !           418:            if (i != SP_TEST_AND_INIT) {
        !           419:                DPRINTF(("ad_detect_F(%d/%x/%x)\n", i, tmp1, tmp2));
        !           420:                goto bad;
        !           421:            }
        !           422:        }
        !           423: #endif
        !           424:
        !           425:     /*
        !           426:      * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit
        !           427:      * The bit 0x80 is always 1 in CS4248, CS4231, and AD1845.
        !           428:      */
        !           429:     ad_write(sc, SP_MISC_INFO, MODE2); /* Set mode2, clear 0x80 */
        !           430:
        !           431:     tmp1 = ad_read(sc, SP_MISC_INFO);
        !           432:     if ((tmp1 & 0xc0) == (0x80 | MODE2)) {
        !           433:        /*
        !           434:         *      CS4231 or AD1845 detected - is it?
        !           435:         *
        !           436:         *      Verify that setting I2 doesn't change I18.
        !           437:         */
        !           438:        ad_write(sc, 18, 0x88); /* Set I18 to known value */
        !           439:
        !           440:        ad_write(sc, 2, 0x45);
        !           441:        if ((tmp2 = ad_read(sc, 18)) != 0x45) { /* No change -> CS4231? */
        !           442:            ad_write(sc, 2, 0xaa);
        !           443:            if ((tmp2 = ad_read(sc, 18)) == 0xaa) {     /* Rotten bits? */
        !           444:                DPRINTF(("ad_detect_H(%x)\n", tmp2));
        !           445:                goto bad;
        !           446:            }
        !           447:
        !           448:            /*
        !           449:             *  It's a CS4231, or another clone with 32 registers.
        !           450:             *  Let's find out which by checking I25.
        !           451:             */
        !           452:            if ((tmp1 & 0x8f) == 0x8a) {
        !           453:                tmp1 = ad_read(sc, CS_VERSION_ID);
        !           454:                switch (tmp1 & 0xe7) {
        !           455:                case 0xA0:
        !           456:                    sc->chip_name = "CS4231A";
        !           457:                    break;
        !           458:                case 0x80:
        !           459:                    /*  XXX I25 no good, AD1845 same as CS4231 */
        !           460:                    sc->chip_name = "CS4231 or AD1845";
        !           461:                    break;
        !           462:                case 0x82:
        !           463:                case 0xa2:
        !           464:                    sc->chip_name = "CS4232";
        !           465:                    break;
        !           466:                case 0x03:
        !           467:                    sc->chip_name = "CS4236/CS4236B";
        !           468:                    break;
        !           469:                }
        !           470:            }
        !           471:            sc->mode = 2;
        !           472:        }
        !           473:     }
        !           474:
        !           475:     /* Wait for 1848 to init */
        !           476:     while(ADREAD(sc, AD1848_IADDR) & SP_IN_INIT)
        !           477:         ;
        !           478:
        !           479:     /* Wait for 1848 to autocal */
        !           480:     ADWRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
        !           481:     while(ADREAD(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG)
        !           482:         ;
        !           483:
        !           484:     return 1;
        !           485: bad:
        !           486:     return 0;
        !           487: }
        !           488:
        !           489: /* Unmap the I/O ports */
        !           490: void
        !           491: ad1848_unmap(sc)
        !           492:     struct ad1848_softc *sc;
        !           493: {
        !           494:     bus_space_unmap(sc->sc_iot, sc->sc_ioh, AD1848_NPORT);
        !           495: }
        !           496:
        !           497: /*
        !           498:  * Attach hardware to driver, attach hardware driver to audio
        !           499:  * pseudo-device driver .
        !           500:  */
        !           501: void
        !           502: ad1848_attach(sc)
        !           503:     struct ad1848_softc *sc;
        !           504: {
        !           505:     int i;
        !           506:     struct ad1848_volume vol_mid = {220, 220};
        !           507:     struct ad1848_volume vol_0   = {0, 0};
        !           508:     struct audio_params pparams, rparams;
        !           509:     int timeout;
        !           510:
        !           511:     sc->sc_locked = 0;
        !           512:     sc->sc_playrun = NOTRUNNING;
        !           513:     sc->sc_recrun = NOTRUNNING;
        !           514:
        !           515:     if (sc->sc_drq != -1) {
        !           516:        if (isa_dmamap_create(sc->sc_isa, sc->sc_drq, MAX_ISADMA,
        !           517:            BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
        !           518:                printf("ad1848_attach: can't create map for drq %d\n",
        !           519:                    sc->sc_drq);
        !           520:                return;
        !           521:        }
        !           522:     }
        !           523:     if (sc->sc_recdrq != -1 && sc->sc_recdrq != sc->sc_drq) {
        !           524:        if (isa_dmamap_create(sc->sc_isa, sc->sc_recdrq, MAX_ISADMA,
        !           525:            BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
        !           526:                printf("ad1848_attach: can't creape map for drq %d\n",
        !           527:                    sc->sc_recdrq);
        !           528:                return;
        !           529:        }
        !           530:     }
        !           531:
        !           532:     /* Initialize the ad1848... */
        !           533:     for (i = 0; i < 0x10; i++) {
        !           534:        ad_write(sc, i, ad1848_init_values[i]);
        !           535:         timeout = 100000;
        !           536:         while (timeout > 0 && ad_read(sc, AD1848_IADDR) & SP_IN_INIT)
        !           537:            timeout--;
        !           538:     }
        !           539:     /* ...and additional CS4231 stuff too */
        !           540:     if (sc->mode == 2) {
        !           541:            ad_write(sc, SP_INTERFACE_CONFIG, 0); /* disable SINGLE_DMA */
        !           542:            for (i = 0x10; i < 0x20; i++)
        !           543:                    if (ad1848_init_values[i] != 0) {
        !           544:                            ad_write(sc, i, ad1848_init_values[i]);
        !           545:                            timeout = 100000;
        !           546:                            while (timeout > 0 &&
        !           547:                                   ad_read(sc, AD1848_IADDR) & SP_IN_INIT)
        !           548:                                timeout--;
        !           549:                    }
        !           550:     }
        !           551:     ad1848_reset(sc);
        !           552:
        !           553:     pparams = audio_default;
        !           554:     rparams = audio_default;
        !           555:     (void) ad1848_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
        !           556:
        !           557:     /* Set default gains */
        !           558:     (void) ad1848_set_rec_gain(sc, &vol_mid);
        !           559:     (void) ad1848_set_channel_gain(sc, AD1848_DAC_CHANNEL, &vol_mid);
        !           560:     (void) ad1848_set_channel_gain(sc, AD1848_MONITOR_CHANNEL, &vol_0);
        !           561:     (void) ad1848_set_channel_gain(sc, AD1848_AUX1_CHANNEL, &vol_mid); /* CD volume */
        !           562:     if (sc->mode == 2) {
        !           563:        (void) ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_mid); /* CD volume */
        !           564:        (void) ad1848_set_channel_gain(sc, AD1848_LINE_CHANNEL, &vol_mid);
        !           565:        (void) ad1848_set_channel_gain(sc, AD1848_MONO_CHANNEL, &vol_0);
        !           566:        sc->mute[AD1848_MONO_CHANNEL] = MUTE_ALL;
        !           567:     } else
        !           568:        (void) ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_0);
        !           569:
        !           570:     /* Set default port */
        !           571:     (void) ad1848_set_rec_port(sc, MIC_IN_PORT);
        !           572:
        !           573:     if (sc->chip_name)
        !           574:        printf(": %s", sc->chip_name);
        !           575: #undef WAITREADY
        !           576: }
        !           577:
        !           578: /*
        !           579:  * Various routines to interface to higher level audio driver
        !           580:  */
        !           581: struct ad1848_mixerinfo {
        !           582:   int  left_reg;
        !           583:   int  right_reg;
        !           584:   int  atten_bits;
        !           585:   int  atten_mask;
        !           586: } mixer_channel_info[] =
        !           587: { { SP_LEFT_AUX2_CONTROL, SP_RIGHT_AUX2_CONTROL, AUX_INPUT_ATTEN_BITS,
        !           588:     AUX_INPUT_ATTEN_MASK },
        !           589:   { SP_LEFT_AUX1_CONTROL, SP_RIGHT_AUX1_CONTROL, AUX_INPUT_ATTEN_BITS,
        !           590:     AUX_INPUT_ATTEN_MASK },
        !           591:   { SP_LEFT_OUTPUT_CONTROL, SP_RIGHT_OUTPUT_CONTROL,
        !           592:     OUTPUT_ATTEN_BITS, OUTPUT_ATTEN_MASK },
        !           593:   { CS_LEFT_LINE_CONTROL, CS_RIGHT_LINE_CONTROL, LINE_INPUT_ATTEN_BITS,
        !           594:     LINE_INPUT_ATTEN_MASK },
        !           595:   { CS_MONO_IO_CONTROL, 0, MONO_INPUT_ATTEN_BITS, MONO_INPUT_ATTEN_MASK },
        !           596:   { SP_DIGITAL_MIX, 0, OUTPUT_ATTEN_BITS, MIX_ATTEN_MASK }
        !           597: };
        !           598:
        !           599: /*
        !           600:  *  This function doesn't set the mute flags but does use them.
        !           601:  *  The mute flags reflect the mutes that have been applied by the user.
        !           602:  *  However, the driver occasionally wants to mute devices (e.g. when chaing
        !           603:  *  sampling rate). These operations should not affect the mute flags.
        !           604:  */
        !           605:
        !           606: void
        !           607: ad1848_mute_channel(sc, device, mute)
        !           608:        struct ad1848_softc *sc;
        !           609:        int device;
        !           610:        int mute;
        !           611: {
        !           612:   u_char reg;
        !           613:
        !           614:   reg = ad_read(sc, mixer_channel_info[device].left_reg);
        !           615:
        !           616:   if (mute & MUTE_LEFT) {
        !           617:     if (device == AD1848_MONITOR_CHANNEL)
        !           618:         ad_write(sc, mixer_channel_info[device].left_reg, reg & 0xFE);
        !           619:     else
        !           620:         ad_write(sc, mixer_channel_info[device].left_reg, reg | 0x80);
        !           621:   } else if (!(sc->mute[device] & MUTE_LEFT)) {
        !           622:     if (device == AD1848_MONITOR_CHANNEL)
        !           623:         ad_write(sc, mixer_channel_info[device].left_reg, reg | 0x01);
        !           624:     else
        !           625:         ad_write(sc, mixer_channel_info[device].left_reg, reg & ~0x80);
        !           626:   }
        !           627:
        !           628:   if (!mixer_channel_info[device].right_reg) {
        !           629:     return;
        !           630:   }
        !           631:
        !           632:   reg = ad_read(sc, mixer_channel_info[device].right_reg);
        !           633:
        !           634:   if (mute & MUTE_RIGHT)
        !           635:     ad_write(sc, mixer_channel_info[device].right_reg, reg | 0x80);
        !           636:   else if (!(sc->mute[device] & MUTE_RIGHT)) {
        !           637:     ad_write(sc, mixer_channel_info[device].right_reg, reg & ~0x80);
        !           638:   }
        !           639: }
        !           640:
        !           641:
        !           642: int
        !           643: ad1848_set_channel_gain(sc, device, gp)
        !           644:     struct ad1848_softc *sc;
        !           645:     int device;
        !           646:     struct ad1848_volume *gp;
        !           647: {
        !           648:     struct ad1848_mixerinfo *info = &mixer_channel_info[device];
        !           649:     u_char reg;
        !           650:     u_int atten;
        !           651:
        !           652:     sc->gains[device] = *gp;
        !           653:
        !           654:     atten = ((AUDIO_MAX_GAIN - gp->left) * info->atten_bits)/AUDIO_MAX_GAIN;
        !           655:
        !           656:     reg = ad_read(sc, info->left_reg) & (info->atten_mask);
        !           657:     if (device == AD1848_MONITOR_CHANNEL)
        !           658:       reg |= ((atten & info->atten_bits) << 2);
        !           659:     else
        !           660:       reg |= ((atten & info->atten_bits));
        !           661:
        !           662:     ad_write(sc, info->left_reg, reg);
        !           663:
        !           664:     if (!info->right_reg)
        !           665:       return (0);
        !           666:
        !           667:     atten = ((AUDIO_MAX_GAIN - gp->right) * info->atten_bits)/AUDIO_MAX_GAIN;
        !           668:     reg = ad_read(sc, info->right_reg);
        !           669:     reg &= (info->atten_mask);
        !           670:     ad_write(sc, info->right_reg, (atten& info->atten_bits)|reg);
        !           671:
        !           672:     return(0);
        !           673: }
        !           674:
        !           675:
        !           676: int
        !           677: ad1848_get_device_gain(sc, device, gp)
        !           678:     struct ad1848_softc *sc;
        !           679:     int device;
        !           680:     struct ad1848_volume *gp;
        !           681: {
        !           682:     *gp = sc->gains[device];
        !           683:     return(0);
        !           684: }
        !           685:
        !           686: int
        !           687: ad1848_get_rec_gain(sc, gp)
        !           688:     struct ad1848_softc *sc;
        !           689:     struct ad1848_volume *gp;
        !           690: {
        !           691:     *gp = sc->rec_gain;
        !           692:     return(0);
        !           693: }
        !           694:
        !           695: int
        !           696: ad1848_set_rec_gain(sc, gp)
        !           697:     struct ad1848_softc *sc;
        !           698:     struct ad1848_volume *gp;
        !           699: {
        !           700:     u_char reg, gain;
        !           701:
        !           702:     DPRINTF(("ad1848_set_rec_gain: %d:%d\n", gp->left, gp->right));
        !           703:
        !           704:     sc->rec_gain = *gp;
        !           705:
        !           706:     gain = (gp->left * GAIN_22_5)/AUDIO_MAX_GAIN;
        !           707:     reg = ad_read(sc, SP_LEFT_INPUT_CONTROL);
        !           708:     reg &= INPUT_GAIN_MASK;
        !           709:     ad_write(sc, SP_LEFT_INPUT_CONTROL, (gain&0x0f)|reg);
        !           710:
        !           711:     gain = (gp->right * GAIN_22_5)/AUDIO_MAX_GAIN;
        !           712:     reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL);
        !           713:     reg &= INPUT_GAIN_MASK;
        !           714:     ad_write(sc, SP_RIGHT_INPUT_CONTROL, (gain&0x0f)|reg);
        !           715:
        !           716:     return(0);
        !           717: }
        !           718:
        !           719:
        !           720: void
        !           721: ad1848_mute_monitor(addr, mute)
        !           722:        void *addr;
        !           723:        int mute;
        !           724: {
        !           725:        struct ad1848_softc *sc = addr;
        !           726:
        !           727:        DPRINTF(("ad1848_mute_monitor: %smuting\n", mute ? "" : "un"));
        !           728:        if (sc->mode == 2) {
        !           729:                ad1848_mute_channel(sc, AD1848_DAC_CHANNEL, mute ? MUTE_ALL : 0);
        !           730:                ad1848_mute_channel(sc, AD1848_MONO_CHANNEL, mute ? MUTE_MONO : 0);
        !           731:                ad1848_mute_channel(sc, AD1848_LINE_CHANNEL, mute ? MUTE_ALL : 0);
        !           732:        }
        !           733:
        !           734:        ad1848_mute_channel(sc, AD1848_AUX2_CHANNEL, mute ? MUTE_ALL : 0);
        !           735:        ad1848_mute_channel(sc, AD1848_AUX1_CHANNEL, mute ? MUTE_ALL : 0);
        !           736: }
        !           737:
        !           738: int
        !           739: ad1848_set_mic_gain(sc, gp)
        !           740:     struct ad1848_softc *sc;
        !           741:     struct ad1848_volume *gp;
        !           742: {
        !           743:     u_char reg;
        !           744:
        !           745:     DPRINTF(("cs4231_set_mic_gain: %d\n", gp->left));
        !           746:
        !           747:     if (gp->left > AUDIO_MAX_GAIN/2) {
        !           748:            sc->mic_gain_on = 1;
        !           749:            reg = ad_read(sc, SP_LEFT_INPUT_CONTROL);
        !           750:            ad_write(sc, SP_LEFT_INPUT_CONTROL, reg | INPUT_MIC_GAIN_ENABLE);
        !           751:     } else {
        !           752:            sc->mic_gain_on = 0;
        !           753:            reg = ad_read(sc, SP_LEFT_INPUT_CONTROL);
        !           754:            ad_write(sc, SP_LEFT_INPUT_CONTROL, reg & ~INPUT_MIC_GAIN_ENABLE);
        !           755:     }
        !           756:
        !           757:     return(0);
        !           758: }
        !           759:
        !           760: int
        !           761: ad1848_get_mic_gain(sc, gp)
        !           762:     struct ad1848_softc *sc;
        !           763:     struct ad1848_volume *gp;
        !           764: {
        !           765:        if (sc->mic_gain_on)
        !           766:                gp->left = gp->right = AUDIO_MAX_GAIN;
        !           767:        else
        !           768:                gp->left = gp->right = AUDIO_MIN_GAIN;
        !           769:        return(0);
        !           770: }
        !           771:
        !           772:
        !           773: static ad1848_devmap_t *ad1848_mixer_find_dev(ad1848_devmap_t *, int, mixer_ctrl_t *);
        !           774:
        !           775: static ad1848_devmap_t *
        !           776: ad1848_mixer_find_dev(map, cnt, cp)
        !           777:   ad1848_devmap_t *map;
        !           778:   int cnt;
        !           779:   mixer_ctrl_t *cp;
        !           780:
        !           781: {
        !           782:   int idx;
        !           783:
        !           784:   for (idx = 0; idx < cnt; idx++) {
        !           785:     if (map[idx].id == cp->dev) {
        !           786:       return (&map[idx]);
        !           787:     }
        !           788:   }
        !           789:   return (NULL);
        !           790: }
        !           791:
        !           792: int
        !           793: ad1848_mixer_get_port(ac, map, cnt, cp)
        !           794:   struct ad1848_softc *ac;
        !           795:   struct ad1848_devmap *map;
        !           796:   int cnt;
        !           797:   mixer_ctrl_t *cp;
        !           798: {
        !           799:   ad1848_devmap_t *entry;
        !           800:   struct ad1848_volume vol;
        !           801:   int error = EINVAL;
        !           802:   int dev;
        !           803:
        !           804:   if (!(entry = ad1848_mixer_find_dev(map, cnt, cp)))
        !           805:     return (ENXIO);
        !           806:
        !           807:   dev = entry->dev;
        !           808:
        !           809:   switch (entry->kind) {
        !           810:   case AD1848_KIND_LVL:
        !           811:     if (cp->type != AUDIO_MIXER_VALUE)
        !           812:       break;
        !           813:
        !           814:     if (dev < AD1848_AUX2_CHANNEL ||
        !           815:        dev > AD1848_MONITOR_CHANNEL)
        !           816:       break;
        !           817:
        !           818:     if (cp->un.value.num_channels != 1 &&
        !           819:         mixer_channel_info[dev].right_reg == 0)
        !           820:       break;
        !           821:
        !           822:     error = ad1848_get_device_gain(ac, dev, &vol);
        !           823:     if (!error)
        !           824:       ad1848_from_vol(cp, &vol);
        !           825:
        !           826:     break;
        !           827:
        !           828:   case AD1848_KIND_MUTE:
        !           829:     if (cp->type != AUDIO_MIXER_ENUM) break;
        !           830:
        !           831:     cp->un.ord = ac->mute[dev] ? 1 : 0;
        !           832:     error = 0;
        !           833:     break;
        !           834:
        !           835:   case AD1848_KIND_RECORDGAIN:
        !           836:     if (cp->type != AUDIO_MIXER_VALUE) break;
        !           837:
        !           838:     error = ad1848_get_rec_gain(ac, &vol);
        !           839:     if (!error)
        !           840:       ad1848_from_vol(cp, &vol);
        !           841:
        !           842:     break;
        !           843:
        !           844:   case AD1848_KIND_MICGAIN:
        !           845:     if (cp->type != AUDIO_MIXER_VALUE) break;
        !           846:
        !           847:     error = ad1848_get_mic_gain(ac, &vol);
        !           848:     if (!error)
        !           849:       ad1848_from_vol(cp, &vol);
        !           850:
        !           851:     break;
        !           852:
        !           853:   case AD1848_KIND_RECORDSOURCE:
        !           854:     if (cp->type != AUDIO_MIXER_ENUM) break;
        !           855:     cp->un.ord = ad1848_get_rec_port(ac);
        !           856:     error = 0;
        !           857:     break;
        !           858:   default:
        !           859:     printf ("Invalid kind\n");
        !           860:     break;
        !           861:   }
        !           862:
        !           863:   return (error);
        !           864: }
        !           865:
        !           866: int
        !           867: ad1848_mixer_set_port(ac, map, cnt, cp)
        !           868:   struct ad1848_softc *ac;
        !           869:   struct ad1848_devmap *map;
        !           870:   int cnt;
        !           871:   mixer_ctrl_t *cp;
        !           872: {
        !           873:   ad1848_devmap_t *entry;
        !           874:   struct ad1848_volume vol;
        !           875:   int error = EINVAL;
        !           876:   int dev;
        !           877:
        !           878:   if (!(entry = ad1848_mixer_find_dev(map, cnt, cp)))
        !           879:     return (ENXIO);
        !           880:
        !           881:   dev = entry->dev;
        !           882:
        !           883:   switch (entry->kind) {
        !           884:   case AD1848_KIND_LVL:
        !           885:     if (cp->type != AUDIO_MIXER_VALUE)
        !           886:       break;
        !           887:
        !           888:     if (dev < AD1848_AUX2_CHANNEL ||
        !           889:        dev > AD1848_MONITOR_CHANNEL)
        !           890:       break;
        !           891:
        !           892:     if (cp->un.value.num_channels != 1 &&
        !           893:         mixer_channel_info[dev].right_reg == 0)
        !           894:       break;
        !           895:
        !           896:     ad1848_to_vol(cp, &vol);
        !           897:     error = ad1848_set_channel_gain(ac, dev, &vol);
        !           898:     break;
        !           899:
        !           900:   case AD1848_KIND_MUTE:
        !           901:     if (cp->type != AUDIO_MIXER_ENUM) break;
        !           902:
        !           903:     ac->mute[dev] = (cp->un.ord ? MUTE_ALL : 0);
        !           904:     ad1848_mute_channel(ac, dev, ac->mute[dev]);
        !           905:     error = 0;
        !           906:     break;
        !           907:
        !           908:   case AD1848_KIND_RECORDGAIN:
        !           909:     if (cp->type != AUDIO_MIXER_VALUE) break;
        !           910:
        !           911:     ad1848_to_vol(cp, &vol);
        !           912:     error = ad1848_set_rec_gain(ac, &vol);
        !           913:     break;
        !           914:
        !           915:   case AD1848_KIND_MICGAIN:
        !           916:     if (cp->type != AUDIO_MIXER_VALUE) break;
        !           917:
        !           918:     ad1848_to_vol(cp, &vol);
        !           919:     error = ad1848_set_mic_gain(ac, &vol);
        !           920:     break;
        !           921:
        !           922:   case AD1848_KIND_RECORDSOURCE:
        !           923:     if (cp->type != AUDIO_MIXER_ENUM) break;
        !           924:
        !           925:     error = ad1848_set_rec_port(ac,  cp->un.ord);
        !           926:     break;
        !           927:   default:
        !           928:     printf ("Invalid kind\n");
        !           929:     break;
        !           930:   }
        !           931:
        !           932:   return (error);
        !           933: }
        !           934:
        !           935:
        !           936: int
        !           937: ad1848_query_encoding(addr, fp)
        !           938:     void *addr;
        !           939:     struct audio_encoding *fp;
        !           940: {
        !           941:     struct ad1848_softc *sc = addr;
        !           942:
        !           943:     switch (fp->index) {
        !           944:     case 0:
        !           945:        strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
        !           946:        fp->encoding = AUDIO_ENCODING_ULAW;
        !           947:        fp->precision = 8;
        !           948:        fp->flags = 0;
        !           949:        break;
        !           950:     case 1:
        !           951:        strlcpy(fp->name, AudioEalaw, sizeof fp->name);
        !           952:        fp->encoding = AUDIO_ENCODING_ALAW;
        !           953:        fp->precision = 8;
        !           954:        fp->flags = 0;
        !           955:        break;
        !           956:     case 2:
        !           957:        strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
        !           958:        fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
        !           959:        fp->precision = 16;
        !           960:        fp->flags = 0;
        !           961:        break;
        !           962:     case 3:
        !           963:        strlcpy(fp->name, AudioEulinear, sizeof fp->name);
        !           964:        fp->encoding = AUDIO_ENCODING_ULINEAR;
        !           965:        fp->precision = 8;
        !           966:        fp->flags = 0;
        !           967:        break;
        !           968:
        !           969:     case 4: /* only on CS4231 */
        !           970:        strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
        !           971:        fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
        !           972:        fp->precision = 16;
        !           973:        fp->flags = sc->mode == 1 ? AUDIO_ENCODINGFLAG_EMULATED : 0;
        !           974:        break;
        !           975:
        !           976:     /* emulate some modes */
        !           977:     case 5:
        !           978:        strlcpy(fp->name, AudioEslinear, sizeof fp->name);
        !           979:        fp->encoding = AUDIO_ENCODING_SLINEAR;
        !           980:        fp->precision = 8;
        !           981:        fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           982:        break;
        !           983:     case 6:
        !           984:        strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
        !           985:        fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
        !           986:        fp->precision = 16;
        !           987:        fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           988:        break;
        !           989:     case 7:
        !           990:        strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
        !           991:        fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
        !           992:        fp->precision = 16;
        !           993:        fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           994:        break;
        !           995:
        !           996:     case 8: /* only on CS4231 */
        !           997:        if (sc->mode == 1)
        !           998:            return EINVAL;
        !           999:        strlcpy(fp->name, AudioEadpcm, sizeof fp->name);
        !          1000:        fp->encoding = AUDIO_ENCODING_ADPCM;
        !          1001:        fp->precision = 8;
        !          1002:        fp->flags = 0;
        !          1003:        break;
        !          1004:     default:
        !          1005:        return EINVAL;
        !          1006:        /*NOTREACHED*/
        !          1007:     }
        !          1008:     return (0);
        !          1009: }
        !          1010:
        !          1011: int
        !          1012: ad1848_set_params(addr, setmode, usemode, p, r)
        !          1013:     void *addr;
        !          1014:     int setmode, usemode;
        !          1015:     struct audio_params *p, *r;
        !          1016: {
        !          1017:     struct ad1848_softc *sc = addr;
        !          1018:     int error, bits, enc;
        !          1019:     void (*pswcode)(void *, u_char *buf, int cnt);
        !          1020:     void (*rswcode)(void *, u_char *buf, int cnt);
        !          1021:
        !          1022:     DPRINTF(("ad1848_set_params: %d %d %d %ld\n",
        !          1023:             p->encoding, p->precision, p->channels, p->sample_rate));
        !          1024:
        !          1025:     enc = p->encoding;
        !          1026:     pswcode = rswcode = 0;
        !          1027:     switch (enc) {
        !          1028:     case AUDIO_ENCODING_SLINEAR_LE:
        !          1029:        if (p->precision == 8) {
        !          1030:            enc = AUDIO_ENCODING_ULINEAR_LE;
        !          1031:            pswcode = rswcode = change_sign8;
        !          1032:        }
        !          1033:        break;
        !          1034:     case AUDIO_ENCODING_SLINEAR_BE:
        !          1035:        if (p->precision == 16 && sc->mode == 1) {
        !          1036:            enc = AUDIO_ENCODING_SLINEAR_LE;
        !          1037:            pswcode = rswcode = swap_bytes;
        !          1038:        }
        !          1039:        break;
        !          1040:     case AUDIO_ENCODING_ULINEAR_LE:
        !          1041:        if (p->precision == 16) {
        !          1042:            enc = AUDIO_ENCODING_SLINEAR_LE;
        !          1043:            pswcode = rswcode = change_sign16;
        !          1044:        }
        !          1045:        break;
        !          1046:     case AUDIO_ENCODING_ULINEAR_BE:
        !          1047:        if (p->precision == 16) {
        !          1048:            enc = AUDIO_ENCODING_SLINEAR_LE;
        !          1049:            pswcode = swap_bytes_change_sign16;
        !          1050:            rswcode = change_sign16_swap_bytes;
        !          1051:        }
        !          1052:        break;
        !          1053:     }
        !          1054:     switch (enc) {
        !          1055:     case AUDIO_ENCODING_ULAW:
        !          1056:        bits = FMT_ULAW >> 5;
        !          1057:        break;
        !          1058:     case AUDIO_ENCODING_ALAW:
        !          1059:        bits = FMT_ALAW >> 5;
        !          1060:        break;
        !          1061:     case AUDIO_ENCODING_ADPCM:
        !          1062:        bits = FMT_ADPCM >> 5;
        !          1063:        break;
        !          1064:     case AUDIO_ENCODING_SLINEAR_LE:
        !          1065:        if (p->precision == 16)
        !          1066:            bits = FMT_TWOS_COMP >> 5;
        !          1067:        else
        !          1068:            return EINVAL;
        !          1069:        break;
        !          1070:     case AUDIO_ENCODING_SLINEAR_BE:
        !          1071:        if (p->precision == 16)
        !          1072:            bits = FMT_TWOS_COMP_BE >> 5;
        !          1073:        else
        !          1074:            return EINVAL;
        !          1075:        break;
        !          1076:     case AUDIO_ENCODING_ULINEAR_LE:
        !          1077:        if (p->precision == 8)
        !          1078:            bits = FMT_PCM8 >> 5;
        !          1079:        else
        !          1080:            return EINVAL;
        !          1081:        break;
        !          1082:     default:
        !          1083:        return EINVAL;
        !          1084:     }
        !          1085:
        !          1086:     if (p->channels < 1 || p->channels > 2)
        !          1087:        return EINVAL;
        !          1088:
        !          1089:     error = ad1848_set_speed(sc, &p->sample_rate);
        !          1090:     if (error)
        !          1091:        return error;
        !          1092:
        !          1093:     p->sw_code = pswcode;
        !          1094:     r->sw_code = rswcode;
        !          1095:
        !          1096:     sc->format_bits = bits;
        !          1097:     sc->channels = p->channels;
        !          1098:     sc->precision = p->precision;
        !          1099:     sc->need_commit = 1;
        !          1100:
        !          1101:     DPRINTF(("ad1848_set_params succeeded, bits=%x\n", bits));
        !          1102:     return (0);
        !          1103: }
        !          1104:
        !          1105: int
        !          1106: ad1848_set_rec_port(sc, port)
        !          1107:     struct ad1848_softc *sc;
        !          1108:     int port;
        !          1109: {
        !          1110:     u_char inp, reg;
        !          1111:
        !          1112:     DPRINTF(("ad1848_set_rec_port: 0x%x\n", port));
        !          1113:
        !          1114:     if (port == MIC_IN_PORT) {
        !          1115:        inp = MIC_INPUT;
        !          1116:     }
        !          1117:     else if (port == LINE_IN_PORT) {
        !          1118:        inp = LINE_INPUT;
        !          1119:     }
        !          1120:     else if (port == DAC_IN_PORT) {
        !          1121:        inp = MIXED_DAC_INPUT;
        !          1122:     }
        !          1123:     else if (sc->mode == 2 && port == AUX1_IN_PORT) {
        !          1124:        inp = AUX_INPUT;
        !          1125:     }
        !          1126:     else
        !          1127:        return(EINVAL);
        !          1128:
        !          1129:     reg = ad_read(sc, SP_LEFT_INPUT_CONTROL);
        !          1130:     reg &= INPUT_SOURCE_MASK;
        !          1131:     ad_write(sc, SP_LEFT_INPUT_CONTROL, (inp|reg));
        !          1132:
        !          1133:     reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL);
        !          1134:     reg &= INPUT_SOURCE_MASK;
        !          1135:     ad_write(sc, SP_RIGHT_INPUT_CONTROL, (inp|reg));
        !          1136:
        !          1137:     sc->rec_port = port;
        !          1138:
        !          1139:     return(0);
        !          1140: }
        !          1141:
        !          1142: int
        !          1143: ad1848_get_rec_port(sc)
        !          1144:     struct ad1848_softc *sc;
        !          1145: {
        !          1146:     return(sc->rec_port);
        !          1147: }
        !          1148:
        !          1149: int
        !          1150: ad1848_round_blocksize(addr, blk)
        !          1151:     void *addr;
        !          1152:     int blk;
        !          1153: {
        !          1154:     struct ad1848_softc *sc = addr;
        !          1155:
        !          1156:     sc->sc_lastcc = -1;
        !          1157:
        !          1158:     /* Round to a multiple of the biggest sample size. */
        !          1159:     blk = (blk + 3) & -4;
        !          1160:
        !          1161:     return (blk);
        !          1162: }
        !          1163:
        !          1164: int
        !          1165: ad1848_open(addr, flags)
        !          1166:     void *addr;
        !          1167:     int flags;
        !          1168: {
        !          1169:     struct ad1848_softc *sc = addr;
        !          1170:
        !          1171:     DPRINTF(("ad1848_open: sc=%p\n", sc));
        !          1172:
        !          1173:     sc->sc_intr = 0;
        !          1174:     sc->sc_lastcc = -1;
        !          1175:     sc->sc_locked = 0;
        !          1176:
        !          1177:     /* Enable interrupts */
        !          1178:     DPRINTF(("ad1848_open: enable intrs\n"));
        !          1179:     ad_write(sc, SP_PIN_CONTROL, INTERRUPT_ENABLE|ad_read(sc, SP_PIN_CONTROL));
        !          1180:
        !          1181: #ifdef AUDIO_DEBUG
        !          1182:     if (ad1848debug)
        !          1183:        ad1848_dump_regs(sc);
        !          1184: #endif
        !          1185:
        !          1186:     return 0;
        !          1187: }
        !          1188:
        !          1189: /*
        !          1190:  * Close function is called at splaudio().
        !          1191:  */
        !          1192: void
        !          1193: ad1848_close(addr)
        !          1194:     void *addr;
        !          1195: {
        !          1196:     struct ad1848_softc *sc = addr;
        !          1197:     u_char r;
        !          1198:
        !          1199:     sc->sc_intr = 0;
        !          1200:
        !          1201:     DPRINTF(("ad1848_close: stop DMA\n"));
        !          1202:     if (sc->sc_playrun != NOTRUNNING) {
        !          1203:        isa_dmaabort(sc->sc_isa, sc->sc_drq);
        !          1204:        sc->sc_playrun = NOTRUNNING;
        !          1205:     }
        !          1206:     if (sc->sc_recrun != NOTRUNNING) {
        !          1207:        isa_dmaabort(sc->sc_isa, sc->sc_recdrq);
        !          1208:        sc->sc_recrun = NOTRUNNING;
        !          1209:     }
        !          1210:     ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)0);
        !          1211:     ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)0);
        !          1212:
        !          1213:     /* Disable interrupts */
        !          1214:     DPRINTF(("ad1848_close: disable intrs\n"));
        !          1215:     ad_write(sc, SP_PIN_CONTROL,
        !          1216:             ad_read(sc, SP_PIN_CONTROL) & ~INTERRUPT_ENABLE);
        !          1217:
        !          1218:     DPRINTF(("ad1848_close: disable capture and playback\n"));
        !          1219:     r = ad_read(sc, SP_INTERFACE_CONFIG);
        !          1220:     r &= ~(CAPTURE_ENABLE|PLAYBACK_ENABLE);
        !          1221:     ad_write(sc, SP_INTERFACE_CONFIG, r);
        !          1222:
        !          1223: #ifdef AUDIO_DEBUG
        !          1224:     if (ad1848debug)
        !          1225:        ad1848_dump_regs(sc);
        !          1226: #endif
        !          1227: }
        !          1228:
        !          1229: /*
        !          1230:  * Lower-level routines
        !          1231:  */
        !          1232: int
        !          1233: ad1848_commit_settings(addr)
        !          1234:     void *addr;
        !          1235: {
        !          1236:     struct ad1848_softc *sc = addr;
        !          1237:     int timeout;
        !          1238:     u_char fs;
        !          1239:     int s;
        !          1240:
        !          1241:     if (!sc->need_commit)
        !          1242:        return 0;
        !          1243:
        !          1244:     s = splaudio();
        !          1245:
        !          1246:     ad1848_mute_monitor(sc, 1);
        !          1247:
        !          1248:     ad_set_MCE(sc, 1);         /* Enables changes to the format select reg */
        !          1249:
        !          1250:     fs = sc->speed_bits | (sc->format_bits << 5);
        !          1251:
        !          1252:     if (sc->channels == 2)
        !          1253:        fs |= FMT_STEREO;
        !          1254:
        !          1255:     ad_write(sc, SP_CLOCK_DATA_FORMAT, fs);
        !          1256:
        !          1257:     /*
        !          1258:      * If mode == 2 (CS4231), set I28 also. It's the capture format register.
        !          1259:      */
        !          1260:     if (sc->mode == 2) {
        !          1261:        /* Gravis Ultrasound MAX SDK sources says something about errata
        !          1262:         * sheets, with the implication that these inb()s are necessary.
        !          1263:         */
        !          1264:        (void)ADREAD(sc, AD1848_IDATA);
        !          1265:        (void)ADREAD(sc, AD1848_IDATA);
        !          1266:        /*
        !          1267:         * Write to I8 starts resynchronization. Wait until it completes.
        !          1268:         */
        !          1269:        timeout = 100000;
        !          1270:        while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
        !          1271:            timeout--;
        !          1272:
        !          1273:        ad_write(sc, CS_REC_FORMAT, fs);
        !          1274:        /* Gravis Ultrasound MAX SDK sources says something about errata
        !          1275:         * sheets, with the implication that these inb()s are necessary.
        !          1276:         */
        !          1277:        (void)ADREAD(sc, AD1848_IDATA);
        !          1278:        (void)ADREAD(sc, AD1848_IDATA);
        !          1279:        /* Now wait for resync for capture side of the house */
        !          1280:     }
        !          1281:     /*
        !          1282:      * Write to I8 starts resynchronization. Wait until it completes.
        !          1283:      */
        !          1284:     timeout = 100000;
        !          1285:     while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
        !          1286:        timeout--;
        !          1287:
        !          1288:     if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
        !          1289:        printf("ad1848_commit: Auto calibration timed out\n");
        !          1290:
        !          1291:     /*
        !          1292:      * Starts the calibration process and
        !          1293:      * enters playback mode after it.
        !          1294:      */
        !          1295:     ad_set_MCE(sc, 0);
        !          1296:     wait_for_calibration(sc);
        !          1297:
        !          1298:     ad1848_mute_monitor(sc, 0);
        !          1299:
        !          1300:     sc->sc_lastcc = -1;
        !          1301:
        !          1302:     splx(s);
        !          1303:
        !          1304:     sc->need_commit = 0;
        !          1305:     return 0;
        !          1306: }
        !          1307:
        !          1308: void
        !          1309: ad1848_reset(sc)
        !          1310:     struct ad1848_softc *sc;
        !          1311: {
        !          1312:     u_char r;
        !          1313:
        !          1314:     DPRINTF(("ad1848_reset\n"));
        !          1315:
        !          1316:     /* Clear the PEN and CEN bits */
        !          1317:     r = ad_read(sc, SP_INTERFACE_CONFIG);
        !          1318:     r &= ~(CAPTURE_ENABLE|PLAYBACK_ENABLE);
        !          1319:     ad_write(sc, SP_INTERFACE_CONFIG, r);
        !          1320:
        !          1321:     if (sc->mode == 2) {
        !          1322:            ADWRITE(sc, AD1848_IADDR, CS_IRQ_STATUS);
        !          1323:            ADWRITE(sc, AD1848_IDATA, 0);
        !          1324:     }
        !          1325:     /* Clear interrupt status */
        !          1326:     ADWRITE(sc, AD1848_STATUS, 0);
        !          1327: #ifdef AUDIO_DEBUG
        !          1328:     if (ad1848debug)
        !          1329:        ad1848_dump_regs(sc);
        !          1330: #endif
        !          1331: }
        !          1332:
        !          1333: int
        !          1334: ad1848_set_speed(sc, argp)
        !          1335:     struct ad1848_softc *sc;
        !          1336:     u_long *argp;
        !          1337: {
        !          1338:     /*
        !          1339:      * The sampling speed is encoded in the least significant nible of I8. The
        !          1340:      * LSB selects the clock source (0=24.576 MHz, 1=16.9344 MHz) and other
        !          1341:      * three bits select the divisor (indirectly):
        !          1342:      *
        !          1343:      * The available speeds are in the following table. Keep the speeds in
        !          1344:      * the increasing order.
        !          1345:      */
        !          1346:     typedef struct {
        !          1347:        int     speed;
        !          1348:        u_char  bits;
        !          1349:     } speed_struct;
        !          1350:     u_long arg = *argp;
        !          1351:
        !          1352:     static speed_struct speed_table[] =  {
        !          1353:        {5510, (0 << 1) | 1},
        !          1354:        {5510, (0 << 1) | 1},
        !          1355:        {6620, (7 << 1) | 1},
        !          1356:        {8000, (0 << 1) | 0},
        !          1357:        {9600, (7 << 1) | 0},
        !          1358:        {11025, (1 << 1) | 1},
        !          1359:        {16000, (1 << 1) | 0},
        !          1360:        {18900, (2 << 1) | 1},
        !          1361:        {22050, (3 << 1) | 1},
        !          1362:        {27420, (2 << 1) | 0},
        !          1363:        {32000, (3 << 1) | 0},
        !          1364:        {33075, (6 << 1) | 1},
        !          1365:        {37800, (4 << 1) | 1},
        !          1366:        {44100, (5 << 1) | 1},
        !          1367:        {48000, (6 << 1) | 0}
        !          1368:     };
        !          1369:
        !          1370:     int i, n, selected = -1;
        !          1371:
        !          1372:     n = sizeof(speed_table) / sizeof(speed_struct);
        !          1373:
        !          1374:     if (arg < speed_table[0].speed)
        !          1375:        selected = 0;
        !          1376:     if (arg > speed_table[n - 1].speed)
        !          1377:        selected = n - 1;
        !          1378:
        !          1379:     for (i = 1 /*really*/ ; selected == -1 && i < n; i++)
        !          1380:        if (speed_table[i].speed == arg)
        !          1381:            selected = i;
        !          1382:        else if (speed_table[i].speed > arg) {
        !          1383:            int diff1, diff2;
        !          1384:
        !          1385:            diff1 = arg - speed_table[i - 1].speed;
        !          1386:            diff2 = speed_table[i].speed - arg;
        !          1387:
        !          1388:            if (diff1 < diff2)
        !          1389:                selected = i - 1;
        !          1390:            else
        !          1391:                selected = i;
        !          1392:        }
        !          1393:
        !          1394:     if (selected == -1) {
        !          1395:        printf("ad1848: Can't find speed???\n");
        !          1396:        selected = 3;
        !          1397:     }
        !          1398:
        !          1399:     sc->speed_bits = speed_table[selected].bits;
        !          1400:     sc->need_commit = 1;
        !          1401:     *argp = speed_table[selected].speed;
        !          1402:
        !          1403:     return (0);
        !          1404: }
        !          1405:
        !          1406: /*
        !          1407:  * Halt a DMA in progress.
        !          1408:  */
        !          1409: int
        !          1410: ad1848_halt_out_dma(addr)
        !          1411:     void *addr;
        !          1412: {
        !          1413:     struct ad1848_softc *sc = addr;
        !          1414:     u_char reg;
        !          1415:
        !          1416:     DPRINTF(("ad1848: ad1848_halt_out_dma\n"));
        !          1417:
        !          1418:     reg = ad_read(sc, SP_INTERFACE_CONFIG);
        !          1419:     ad_write(sc, SP_INTERFACE_CONFIG, (reg & ~PLAYBACK_ENABLE));
        !          1420:     sc->sc_locked = 0;
        !          1421:
        !          1422:     return(0);
        !          1423: }
        !          1424:
        !          1425: int
        !          1426: ad1848_halt_in_dma(addr)
        !          1427:     void *addr;
        !          1428: {
        !          1429:     struct ad1848_softc *sc = addr;
        !          1430:     u_char reg;
        !          1431:
        !          1432:     DPRINTF(("ad1848: ad1848_halt_in_dma\n"));
        !          1433:
        !          1434:     reg = ad_read(sc, SP_INTERFACE_CONFIG);
        !          1435:     ad_write(sc, SP_INTERFACE_CONFIG, (reg & ~CAPTURE_ENABLE));
        !          1436:     sc->sc_locked = 0;
        !          1437:
        !          1438:     return(0);
        !          1439: }
        !          1440:
        !          1441: int
        !          1442: ad1848_dma_init_input(addr, buf, cc)
        !          1443:     void *addr;
        !          1444:     void *buf;
        !          1445:     int cc;
        !          1446: {
        !          1447:     struct ad1848_softc *sc = addr;
        !          1448:
        !          1449:     sc->sc_recrun = DMARUNNING;
        !          1450:     sc->sc_dma_flags = DMAMODE_READ | DMAMODE_LOOP;
        !          1451:     sc->sc_dma_bp = buf;
        !          1452:     sc->sc_dma_cnt = cc;
        !          1453:     isa_dmastart(sc->sc_isa, sc->sc_recdrq, buf, cc, NULL,
        !          1454:                 sc->sc_dma_flags, BUS_DMA_NOWAIT);
        !          1455:     DPRINTF(("ad1848_dma_init_input: %p %d\n", buf, cc));
        !          1456:     return 0;
        !          1457: }
        !          1458:
        !          1459: /*
        !          1460:  * DMA input/output are called at splaudio().
        !          1461:  */
        !          1462: int
        !          1463: ad1848_dma_input(addr, p, cc, intr, arg)
        !          1464:     void *addr;
        !          1465:     void *p;
        !          1466:     int cc;
        !          1467:     void (*intr)(void *);
        !          1468:     void *arg;
        !          1469: {
        !          1470:     struct ad1848_softc *sc = addr;
        !          1471:     u_char reg;
        !          1472:
        !          1473:     if (sc->sc_locked) {
        !          1474:        DPRINTF(("ad1848_dma_input: locked\n"));
        !          1475:        return 0;
        !          1476:     }
        !          1477:
        !          1478: #ifdef AUDIO_DEBUG
        !          1479:     if (ad1848debug > 1)
        !          1480:        printf("ad1848_dma_input: cc=%d %p (%p)\n", cc, intr, arg);
        !          1481: #endif
        !          1482:     sc->sc_locked = 1;
        !          1483:     sc->sc_intr = intr;
        !          1484:     sc->sc_arg = arg;
        !          1485:
        !          1486:     switch (sc->sc_recrun) {
        !          1487:     case NOTRUNNING:
        !          1488:        sc->sc_dma_flags = DMAMODE_READ;
        !          1489:        sc->sc_dma_bp = p;
        !          1490:        sc->sc_dma_cnt = cc;
        !          1491:        isa_dmastart(sc->sc_isa, sc->sc_recdrq, p, cc, NULL,
        !          1492:                     DMAMODE_READ, BUS_DMA_NOWAIT);
        !          1493:        goto startpcm;
        !          1494:     case DMARUNNING:
        !          1495:        sc->sc_recrun = PCMRUNNING;
        !          1496:     startpcm:
        !          1497:        if (sc->precision == 16)
        !          1498:            cc >>= 1;
        !          1499:        if (sc->channels == 2)
        !          1500:            cc >>= 1;
        !          1501:        cc--;
        !          1502:
        !          1503:        if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_RECORD) {
        !          1504:            ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)(cc & 0xff));
        !          1505:            ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)((cc >> 8) & 0xff));
        !          1506:
        !          1507:            if (sc->mode == 2) {
        !          1508:                ad_write(sc, CS_LOWER_REC_CNT, (u_char)(cc & 0xff));
        !          1509:                ad_write(sc, CS_UPPER_REC_CNT, (u_char)((cc >> 8) & 0xff));
        !          1510:            }
        !          1511:
        !          1512:            reg = ad_read(sc, SP_INTERFACE_CONFIG);
        !          1513:            ad_write(sc, SP_INTERFACE_CONFIG, (CAPTURE_ENABLE|reg));
        !          1514:
        !          1515:            sc->sc_lastcc = cc;
        !          1516:            sc->sc_mode = AUMODE_RECORD;
        !          1517: #ifdef AUDIO_DEBUG
        !          1518:            if (ad1848debug > 1)
        !          1519:                    printf("ad1848_dma_input: started capture\n");
        !          1520: #endif
        !          1521:        }
        !          1522:     case PCMRUNNING:
        !          1523:        break;
        !          1524:     }
        !          1525:
        !          1526:     return 0;
        !          1527: }
        !          1528:
        !          1529: int
        !          1530: ad1848_dma_init_output(addr, buf, cc)
        !          1531:     void *addr;
        !          1532:     void *buf;
        !          1533:     int cc;
        !          1534: {
        !          1535:     struct ad1848_softc *sc = addr;
        !          1536:
        !          1537:     sc->sc_playrun = DMARUNNING;
        !          1538:     sc->sc_dma_flags = DMAMODE_WRITE | DMAMODE_LOOP;
        !          1539:     sc->sc_dma_bp = buf;
        !          1540:     sc->sc_dma_cnt = cc;
        !          1541:     isa_dmastart(sc->sc_isa, sc->sc_drq, buf, cc, NULL,
        !          1542:                 sc->sc_dma_flags, BUS_DMA_NOWAIT);
        !          1543:     DPRINTF(("ad1848_dma_init_output: %p %d\n", buf, cc));
        !          1544:     return 0;
        !          1545: }
        !          1546:
        !          1547: int
        !          1548: ad1848_dma_output(addr, p, cc, intr, arg)
        !          1549:     void *addr;
        !          1550:     void *p;
        !          1551:     int cc;
        !          1552:     void (*intr)(void *);
        !          1553:     void *arg;
        !          1554: {
        !          1555:     struct ad1848_softc *sc = addr;
        !          1556:     u_char reg;
        !          1557:
        !          1558:     if (sc->sc_locked) {
        !          1559:        DPRINTF(("ad1848_dma_output: locked\n"));
        !          1560:        return 0;
        !          1561:     }
        !          1562:
        !          1563: #ifdef AUDIO_DEBUG
        !          1564:     if (ad1848debug > 0)
        !          1565:        printf("ad1848_dma_output: cc=%d at %p %p (%p)\n", cc, p, intr, arg);
        !          1566: #endif
        !          1567:     sc->sc_locked = 1;
        !          1568:     sc->sc_intr = intr;
        !          1569:     sc->sc_arg = arg;
        !          1570:
        !          1571:     switch (sc->sc_playrun) {
        !          1572:     case NOTRUNNING:
        !          1573:        sc->sc_dma_flags = DMAMODE_WRITE;
        !          1574:        sc->sc_dma_bp = p;
        !          1575:        sc->sc_dma_cnt = cc;
        !          1576:        isa_dmastart(sc->sc_isa, sc->sc_drq, p, cc, NULL,
        !          1577:                     DMAMODE_WRITE, BUS_DMA_NOWAIT);
        !          1578:        goto startpcm;
        !          1579:     case DMARUNNING:
        !          1580:        sc->sc_playrun = PCMRUNNING;
        !          1581:     startpcm:
        !          1582:        if (sc->precision == 16)
        !          1583:            cc >>= 1;
        !          1584:        if (sc->channels == 2)
        !          1585:            cc >>= 1;
        !          1586:        cc--;
        !          1587:
        !          1588:        if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_PLAY) {
        !          1589:            ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)(cc & 0xff));
        !          1590:            ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)((cc >> 8) & 0xff));
        !          1591:
        !          1592:            reg = ad_read(sc, SP_INTERFACE_CONFIG);
        !          1593:            ad_write(sc, SP_INTERFACE_CONFIG, (PLAYBACK_ENABLE|reg));
        !          1594:
        !          1595:            sc->sc_lastcc = cc;
        !          1596:            sc->sc_mode = AUMODE_PLAY;
        !          1597:        }
        !          1598:        break;
        !          1599:     case PCMRUNNING:
        !          1600:        break;
        !          1601:     }
        !          1602:
        !          1603:     return 0;
        !          1604: }
        !          1605:
        !          1606: int
        !          1607: ad1848_intr(arg)
        !          1608:        void *arg;
        !          1609: {
        !          1610:     struct ad1848_softc *sc = arg;
        !          1611:     int retval = 0;
        !          1612:     u_char status;
        !          1613:
        !          1614:     /* Get intr status */
        !          1615:     status = ADREAD(sc, AD1848_STATUS);
        !          1616:
        !          1617: #ifdef AUDIO_DEBUG
        !          1618:     if (ad1848debug > 1)
        !          1619:        printf("ad1848_intr: intr=%p status=%x\n", sc->sc_intr, status);
        !          1620: #endif
        !          1621:     sc->sc_locked = 0;
        !          1622:     sc->sc_interrupts++;
        !          1623:
        !          1624:     /* Handle interrupt */
        !          1625:     if (sc->sc_intr && (status & INTERRUPT_STATUS)) {
        !          1626:        /* ACK DMA read because it may be in a bounce buffer */
        !          1627:        /* XXX Do write to mask DMA ? */
        !          1628:        if ((sc->sc_dma_flags & DMAMODE_READ) && sc->sc_recrun == NOTRUNNING)
        !          1629:            isa_dmadone(sc->sc_isa, sc->sc_recdrq);
        !          1630:        (*sc->sc_intr)(sc->sc_arg);
        !          1631:        retval = 1;
        !          1632:     }
        !          1633:
        !          1634:     /* clear interrupt */
        !          1635:     if (status & INTERRUPT_STATUS)
        !          1636:        ADWRITE(sc, AD1848_STATUS, 0);
        !          1637:
        !          1638:     return(retval);
        !          1639: }
        !          1640:
        !          1641: void *
        !          1642: ad1848_malloc(addr, direction, size, pool, flags)
        !          1643:        void *addr;
        !          1644:        int direction;
        !          1645:        size_t size;
        !          1646:        int pool;
        !          1647:        int flags;
        !          1648: {
        !          1649:        struct ad1848_softc *sc = addr;
        !          1650:        int drq;
        !          1651:
        !          1652:        if (sc->sc_mode == AUMODE_RECORD)
        !          1653:                drq = sc->sc_recdrq == -1 ? sc->sc_drq : sc->sc_recdrq;
        !          1654:        else
        !          1655:                drq = sc->sc_drq;
        !          1656:
        !          1657:        return isa_malloc(sc->sc_isa, drq, size, pool, flags);
        !          1658: }
        !          1659:
        !          1660: void
        !          1661: ad1848_free(addr, ptr, pool)
        !          1662:        void *addr;
        !          1663:        void *ptr;
        !          1664:        int pool;
        !          1665: {
        !          1666:        isa_free(ptr, pool);
        !          1667: }
        !          1668:
        !          1669: size_t
        !          1670: ad1848_round(addr, direction, size)
        !          1671:        void *addr;
        !          1672:        int direction;
        !          1673:        size_t size;
        !          1674: {
        !          1675:        if (size > MAX_ISADMA)
        !          1676:                size = MAX_ISADMA;
        !          1677:        return size;
        !          1678: }
        !          1679:
        !          1680: paddr_t
        !          1681: ad1848_mappage(addr, mem, off, prot)
        !          1682:        void *addr;
        !          1683:         void *mem;
        !          1684:         off_t off;
        !          1685:        int prot;
        !          1686: {
        !          1687:        return isa_mappage(mem, off, prot);
        !          1688: }
        !          1689:
        !          1690: int
        !          1691: ad1848_get_props(addr)
        !          1692:        void *addr;
        !          1693: {
        !          1694:        struct ad1848_softc *sc = addr;
        !          1695:
        !          1696:        return AUDIO_PROP_MMAP |
        !          1697:               (sc->sc_drq != sc->sc_recdrq ? AUDIO_PROP_FULLDUPLEX : 0);
        !          1698: }

CVSweb