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

Annotation of sys/dev/pci/eso.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: eso.c,v 1.22 2005/08/09 04:10:11 mickey Exp $ */
                      2: /*     $NetBSD: eso.c,v 1.3 1999/08/02 17:37:43 augustss Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1999 Klaus J. Klein
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. The name of the author may not be used to endorse or promote products
                     17:  *    derived from this software without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     21:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     22:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     23:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     24:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     25:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     26:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     27:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
                     33:  * ESS Technology Inc. Solo-1 PCI AudioDrive (ES1938/1946) device driver.
                     34:  */
                     35:
                     36: #ifdef __OpenBSD__
                     37: #define HIDE
                     38: #define MATCH_ARG_2_T void *
                     39: #else
                     40: #define HIDE static
                     41: #define MATCH_ARG_2_T struct cfdata *
                     42: #endif
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/kernel.h>
                     47: #include <sys/malloc.h>
                     48: #include <sys/device.h>
                     49: #include <sys/proc.h>
                     50:
                     51: #include <dev/pci/pcidevs.h>
                     52: #include <dev/pci/pcivar.h>
                     53:
                     54: #include <sys/audioio.h>
                     55: #include <dev/audio_if.h>
                     56: #include <dev/midi_if.h>
                     57:
                     58: #include <dev/mulaw.h>
                     59: #include <dev/auconv.h>
                     60:
                     61: #include <dev/ic/mpuvar.h>
                     62: #include <dev/ic/i8237reg.h>
                     63: #include <dev/pci/esoreg.h>
                     64: #include <dev/pci/esovar.h>
                     65: #include <dev/audiovar.h>
                     66:
                     67: #include <machine/bus.h>
                     68: #include <machine/intr.h>
                     69:
                     70: #if defined(AUDIO_DEBUG) || defined(DEBUG)
                     71: #define DPRINTF(x) printf x
                     72: #else
                     73: #define DPRINTF(x)
                     74: #endif
                     75:
                     76: struct eso_dma {
                     77:        bus_dmamap_t            ed_map;
                     78:        caddr_t                 ed_addr;
                     79:        bus_dma_segment_t       ed_segs[1];
                     80:        int                     ed_nsegs;
                     81:        size_t                  ed_size;
                     82:        struct eso_dma *        ed_next;
                     83: };
                     84:
                     85: #define KVADDR(dma)    ((void *)(dma)->ed_addr)
                     86: #define DMAADDR(dma)   ((dma)->ed_map->dm_segs[0].ds_addr)
                     87:
                     88: /* Autoconfiguration interface */
                     89: HIDE int eso_match(struct device *, MATCH_ARG_2_T, void *);
                     90: HIDE void eso_attach(struct device *, struct device *, void *);
                     91: HIDE void eso_defer(struct device *);
                     92:
                     93: struct cfattach eso_ca = {
                     94:        sizeof (struct eso_softc), eso_match, eso_attach
                     95: };
                     96:
                     97: #ifdef __OpenBSD__
                     98: struct cfdriver eso_cd = {
                     99:        NULL, "eso", DV_DULL
                    100: };
                    101: #endif
                    102:
                    103: /* PCI interface */
                    104: HIDE int eso_intr(void *);
                    105:
                    106: /* MI audio layer interface */
                    107: HIDE int       eso_open(void *, int);
                    108: HIDE void      eso_close(void *);
                    109: HIDE int       eso_query_encoding(void *, struct audio_encoding *);
                    110: HIDE int       eso_set_params(void *, int, int, struct audio_params *,
                    111:                    struct audio_params *);
                    112: HIDE int       eso_round_blocksize(void *, int);
                    113: HIDE int       eso_halt_output(void *);
                    114: HIDE int       eso_halt_input(void *);
                    115: HIDE int       eso_getdev(void *, struct audio_device *);
                    116: HIDE int       eso_set_port(void *, mixer_ctrl_t *);
                    117: HIDE int       eso_get_port(void *, mixer_ctrl_t *);
                    118: HIDE int       eso_query_devinfo(void *, mixer_devinfo_t *);
                    119: HIDE void *    eso_allocm(void *, int, size_t, int, int);
                    120: HIDE void      eso_freem(void *, void *, int);
                    121: HIDE size_t    eso_round_buffersize(void *, int, size_t);
                    122: HIDE paddr_t   eso_mappage(void *, void *, off_t, int);
                    123: HIDE int       eso_get_props(void *);
                    124: HIDE int       eso_trigger_output(void *, void *, void *, int,
                    125:                    void (*)(void *), void *, struct audio_params *);
                    126: HIDE int       eso_trigger_input(void *, void *, void *, int,
                    127:                    void (*)(void *), void *, struct audio_params *);
                    128: HIDE void       eso_setup(struct eso_softc *, int);
                    129:
                    130: HIDE void       eso_powerhook(int, void *);
                    131:
                    132:
                    133: HIDE struct audio_hw_if eso_hw_if = {
                    134:        eso_open,
                    135:        eso_close,
                    136:        NULL,                   /* drain */
                    137:        eso_query_encoding,
                    138:        eso_set_params,
                    139:        eso_round_blocksize,
                    140:        NULL,                   /* commit_settings */
                    141:        NULL,                   /* init_output */
                    142:        NULL,                   /* init_input */
                    143:        NULL,                   /* start_output */
                    144:        NULL,                   /* start_input */
                    145:        eso_halt_output,
                    146:        eso_halt_input,
                    147:        NULL,                   /* speaker_ctl */
                    148:        eso_getdev,
                    149:        NULL,                   /* setfd */
                    150:        eso_set_port,
                    151:        eso_get_port,
                    152:        eso_query_devinfo,
                    153:        eso_allocm,
                    154:        eso_freem,
                    155:        eso_round_buffersize,
                    156:        eso_mappage,
                    157:        eso_get_props,
                    158:        eso_trigger_output,
                    159:        eso_trigger_input,
                    160: };
                    161:
                    162: HIDE const char * const eso_rev2model[] = {
                    163:        "ES1938",
                    164:        "ES1946",
                    165:        "ES1946 rev E"
                    166: };
                    167:
                    168:
                    169: /*
                    170:  * Utility routines
                    171:  */
                    172: /* Register access etc. */
                    173: HIDE uint8_t   eso_read_ctlreg(struct eso_softc *, uint8_t);
                    174: HIDE uint8_t   eso_read_mixreg(struct eso_softc *, uint8_t);
                    175: HIDE uint8_t   eso_read_rdr(struct eso_softc *);
                    176: HIDE int       eso_reset(struct eso_softc *);
                    177: HIDE void      eso_set_gain(struct eso_softc *, unsigned int);
                    178: HIDE int       eso_set_recsrc(struct eso_softc *, unsigned int);
                    179: HIDE void      eso_write_cmd(struct eso_softc *, uint8_t);
                    180: HIDE void      eso_write_ctlreg(struct eso_softc *, uint8_t, uint8_t);
                    181: HIDE void      eso_write_mixreg(struct eso_softc *, uint8_t, uint8_t);
                    182: /* DMA memory allocation */
                    183: HIDE int       eso_allocmem(struct eso_softc *, size_t, size_t, size_t,
                    184:                    int, struct eso_dma *);
                    185: HIDE void      eso_freemem(struct eso_softc *, struct eso_dma *);
                    186:
                    187:
                    188: HIDE int
                    189: eso_match(parent, match, aux)
                    190:        struct device *parent;
                    191:        MATCH_ARG_2_T match;
                    192:        void *aux;
                    193: {
                    194:        struct pci_attach_args *pa = aux;
                    195:
                    196:        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ESSTECH &&
                    197:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ESSTECH_SOLO1)
                    198:                return (1);
                    199:
                    200:        return (0);
                    201: }
                    202:
                    203: HIDE void
                    204: eso_attach(parent, self, aux)
                    205:        struct device *parent, *self;
                    206:        void *aux;
                    207: {
                    208:        struct eso_softc *sc = (struct eso_softc *)self;
                    209:        struct pci_attach_args *pa = aux;
                    210:        struct audio_attach_args aa;
                    211:        pci_intr_handle_t ih;
                    212:        bus_addr_t vcbase;
                    213:        const char *intrstring;
                    214:
                    215:        sc->sc_revision = PCI_REVISION(pa->pa_class);
                    216:
                    217:        if (sc->sc_revision <
                    218:            sizeof (eso_rev2model) / sizeof (eso_rev2model[0]))
                    219:                printf(": %s", eso_rev2model[sc->sc_revision]);
                    220:        else
                    221:                printf(": (unknown rev. 0x%02x)", sc->sc_revision);
                    222:
                    223:        /* Map I/O registers. */
                    224:        if (pci_mapreg_map(pa, ESO_PCI_BAR_IO, PCI_MAPREG_TYPE_IO, 0,
                    225:            &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0)) {
                    226:                printf(", can't map I/O space\n");
                    227:                return;
                    228:        }
                    229:        if (pci_mapreg_map(pa, ESO_PCI_BAR_SB, PCI_MAPREG_TYPE_IO, 0,
                    230:            &sc->sc_sb_iot, &sc->sc_sb_ioh, NULL, NULL, 0)) {
                    231:                printf(", can't map SB I/O space\n");
                    232:                return;
                    233:        }
                    234:        if (pci_mapreg_map(pa, ESO_PCI_BAR_VC, PCI_MAPREG_TYPE_IO, 0,
                    235:            &sc->sc_dmac_iot, &sc->sc_dmac_ioh, &vcbase, &sc->sc_vcsize, 0)) {
                    236:                vcbase = 0;
                    237:                sc->sc_vcsize = 0x10; /* From the data sheet. */
                    238:        }
                    239:
                    240:        if (pci_mapreg_map(pa, ESO_PCI_BAR_MPU, PCI_MAPREG_TYPE_IO, 0,
                    241:            &sc->sc_mpu_iot, &sc->sc_mpu_ioh, NULL, NULL, 0)) {
                    242:                printf(", can't map MPU I/O space\n");
                    243:                return;
                    244:        }
                    245:        if (pci_mapreg_map(pa, ESO_PCI_BAR_GAME, PCI_MAPREG_TYPE_IO, 0,
                    246:            &sc->sc_game_iot, &sc->sc_game_ioh, NULL, NULL, 0)) {
                    247:                printf(", can't map Game I/O space\n");
                    248:                return;
                    249:        }
                    250:
                    251:        sc->sc_dmat = pa->pa_dmat;
                    252:        sc->sc_dmas = NULL;
                    253:        sc->sc_dmac_configured = 0;
                    254:
                    255:        sc->sc_pa = *pa;
                    256:
                    257:        eso_setup(sc, 1);
                    258:
                    259:        /* map and establish the interrupt. */
                    260:        if (pci_intr_map(pa, &ih)) {
                    261:                printf(", couldn't map interrupt\n");
                    262:                return;
                    263:        }
                    264:        intrstring = pci_intr_string(pa->pa_pc, ih);
                    265: #ifdef __OpenBSD__
                    266:        sc->sc_ih  = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, eso_intr, sc,
                    267:                                        sc->sc_dev.dv_xname);
                    268: #else
                    269:        sc->sc_ih  = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, eso_intr, sc);
                    270: #endif
                    271:        if (sc->sc_ih == NULL) {
                    272:                printf(", couldn't establish interrupt");
                    273:                if (intrstring != NULL)
                    274:                        printf(" at %s", intrstring);
                    275:                printf("\n");
                    276:                return;
                    277:        }
                    278:        printf(", %s\n", intrstring);
                    279:
                    280:        /*
                    281:         * Set up the DDMA Control register; a suitable I/O region has been
                    282:         * supposedly mapped in the VC base address register.
                    283:         *
                    284:         * The Solo-1 has an ... interesting silicon bug that causes it to
                    285:         * not respond to I/O space accesses to the Audio 1 DMA controller
                    286:         * if the latter's mapping base address is aligned on a 1K boundary.
                    287:         * As a consequence, it is quite possible for the mapping provided
                    288:         * in the VC BAR to be useless.  To work around this, we defer this
                    289:         * part until all autoconfiguration on our parent bus is completed
                    290:         * and then try to map it ourselves in fulfillment of the constraint.
                    291:         *
                    292:         * According to the register map we may write to the low 16 bits
                    293:         * only, but experimenting has shown we're safe.
                    294:         * -kjk
                    295:         */
                    296:
                    297:        if (ESO_VALID_DDMAC_BASE(vcbase)) {
                    298:                pci_conf_write(pa->pa_pc, pa->pa_tag, ESO_PCI_DDMAC,
                    299:                               vcbase | ESO_PCI_DDMAC_DE);
                    300:                sc->sc_dmac_configured = 1;
                    301:
                    302:                printf("%s: mapping Audio 1 DMA using VC I/O space at 0x%lx\n",
                    303:                       sc->sc_dev.dv_xname, (unsigned long)vcbase);
                    304:        } else {
                    305:                DPRINTF(("%s: VC I/O space at 0x%lx not suitable, deferring\n",
                    306:                         sc->sc_dev.dv_xname, (unsigned long)vcbase));
                    307:                config_defer((struct device *)sc, eso_defer);
                    308:        }
                    309:
                    310:        audio_attach_mi(&eso_hw_if, sc, &sc->sc_dev);
                    311:
                    312:        aa.type = AUDIODEV_TYPE_OPL;
                    313:        aa.hwif = NULL;
                    314:        aa.hdl = NULL;
                    315:        (void)config_found(&sc->sc_dev, &aa, audioprint);
                    316:
                    317:        sc->sc_powerhook = powerhook_establish(&eso_powerhook, sc);
                    318:
                    319: #if 0
                    320:        aa.type = AUDIODEV_TYPE_MPU;
                    321:        aa.hwif = NULL;
                    322:        aa.hdl = NULL;
                    323:        sc->sc_mpudev = config_found(&sc->sc_dev, &aa, audioprint);
                    324: #endif
                    325: }
                    326:
                    327: HIDE void
                    328: eso_setup(sc, verbose)
                    329:        struct eso_softc *sc;
                    330:        int verbose;
                    331: {
                    332:        struct pci_attach_args *pa = &sc->sc_pa;
                    333:        uint8_t a2mode;
                    334:        int idx;
                    335:
                    336:        /* Reset the device; bail out upon failure. */
                    337:        if (eso_reset(sc) != 0) {
                    338:                if (verbose) printf(", can't reset\n");
                    339:                return;
                    340:        }
                    341:
                    342:        /* Select the DMA/IRQ policy: DDMA, ISA IRQ emulation disabled. */
                    343:        pci_conf_write(pa->pa_pc, pa->pa_tag, ESO_PCI_S1C,
                    344:                       pci_conf_read(pa->pa_pc, pa->pa_tag, ESO_PCI_S1C) &
                    345:                       ~(ESO_PCI_S1C_IRQP_MASK | ESO_PCI_S1C_DMAP_MASK));
                    346:
                    347:        /* Enable the relevant DMA interrupts. */
                    348:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, ESO_IO_IRQCTL,
                    349:                          ESO_IO_IRQCTL_A1IRQ | ESO_IO_IRQCTL_A2IRQ);
                    350:
                    351:        /* Set up A1's sample rate generator for new-style parameters. */
                    352:        a2mode = eso_read_mixreg(sc, ESO_MIXREG_A2MODE);
                    353:        a2mode |= ESO_MIXREG_A2MODE_NEWA1 | ESO_MIXREG_A2MODE_ASYNC;
                    354:        eso_write_mixreg(sc, ESO_MIXREG_A2MODE, a2mode);
                    355:
                    356:        /* Set mixer regs to something reasonable, needs work. */
                    357:        for (idx = 0; idx < ESO_NGAINDEVS; idx++) {
                    358:                int v;
                    359:
                    360:                switch (idx) {
                    361:                case ESO_MIC_PLAY_VOL:
                    362:                case ESO_LINE_PLAY_VOL:
                    363:                case ESO_CD_PLAY_VOL:
                    364:                case ESO_MONO_PLAY_VOL:
                    365:                case ESO_AUXB_PLAY_VOL:
                    366:                case ESO_DAC_REC_VOL:
                    367:                case ESO_LINE_REC_VOL:
                    368:                case ESO_SYNTH_REC_VOL:
                    369:                case ESO_CD_REC_VOL:
                    370:                case ESO_MONO_REC_VOL:
                    371:                case ESO_AUXB_REC_VOL:
                    372:                case ESO_SPATIALIZER:
                    373:                        v = 0;
                    374:                        break;
                    375:                case ESO_MASTER_VOL:
                    376:                        v = ESO_GAIN_TO_6BIT(AUDIO_MAX_GAIN / 2);
                    377:                        break;
                    378:                default:
                    379:                        v = ESO_GAIN_TO_4BIT(AUDIO_MAX_GAIN / 2);
                    380:                        break;
                    381:                }
                    382:                sc->sc_gain[idx][ESO_LEFT] = sc->sc_gain[idx][ESO_RIGHT] = v;
                    383:                eso_set_gain(sc, idx);
                    384:        }
                    385:        eso_set_recsrc(sc, ESO_MIXREG_ERS_MIC);
                    386: }
                    387:
                    388: HIDE void
                    389: eso_defer(self)
                    390:        struct device *self;
                    391: {
                    392:        struct eso_softc *sc = (struct eso_softc *)self;
                    393:        struct pci_attach_args *pa = &sc->sc_pa;
                    394:        bus_addr_t addr, start;
                    395:
                    396:        printf("%s: ", sc->sc_dev.dv_xname);
                    397:
                    398:        /*
                    399:         * This is outright ugly, but since we must not make assumptions
                    400:         * on the underlying allocator's behaviour it's the most straight-
                    401:         * forward way to implement it.  Note that we skip over the first
                    402:         * 1K region, which is typically occupied by an attached ISA bus.
                    403:         */
                    404:        for (start = 0x0400; start < 0xffff; start += 0x0400) {
                    405:                if (bus_space_alloc(sc->sc_iot,
                    406:                    start + sc->sc_vcsize, start + 0x0400 - 1,
                    407:                    sc->sc_vcsize, sc->sc_vcsize, 0, 0, &addr,
                    408:                    &sc->sc_dmac_ioh) != 0)
                    409:                        continue;
                    410:
                    411:                pci_conf_write(pa->pa_pc, pa->pa_tag, ESO_PCI_DDMAC,
                    412:                    addr | ESO_PCI_DDMAC_DE);
                    413:                sc->sc_dmac_iot = sc->sc_iot;
                    414:                sc->sc_dmac_configured = 1;
                    415:                printf("mapping Audio 1 DMA using I/O space at 0x%lx\n",
                    416:                    (unsigned long)addr);
                    417:
                    418:                return;
                    419:        }
                    420:
                    421:        printf("can't map Audio 1 DMA into I/O space\n");
                    422: }
                    423:
                    424: HIDE void
                    425: eso_write_cmd(sc, cmd)
                    426:        struct eso_softc *sc;
                    427:        uint8_t cmd;
                    428: {
                    429:        int i;
                    430:
                    431:        /* Poll for busy indicator to become clear. */
                    432:        for (i = 0; i < ESO_WDR_TIMEOUT; i++) {
                    433:                if ((bus_space_read_1(sc->sc_sb_iot, sc->sc_sb_ioh, ESO_SB_RSR)
                    434:                    & ESO_SB_RSR_BUSY) == 0) {
                    435:                        bus_space_write_1(sc->sc_sb_iot, sc->sc_sb_ioh,
                    436:                            ESO_SB_WDR, cmd);
                    437:                        return;
                    438:                } else {
                    439:                        delay(10);
                    440:                }
                    441:        }
                    442:
                    443:        printf("%s: WDR timeout\n", sc->sc_dev.dv_xname);
                    444:        return;
                    445: }
                    446:
                    447: /* Write to a controller register */
                    448: HIDE void
                    449: eso_write_ctlreg(sc, reg, val)
                    450:        struct eso_softc *sc;
                    451:        uint8_t reg, val;
                    452: {
                    453:
                    454:        /* DPRINTF(("ctlreg 0x%02x = 0x%02x\n", reg, val)); */
                    455:
                    456:        eso_write_cmd(sc, reg);
                    457:        eso_write_cmd(sc, val);
                    458: }
                    459:
                    460: /* Read out the Read Data Register */
                    461: HIDE uint8_t
                    462: eso_read_rdr(sc)
                    463:        struct eso_softc *sc;
                    464: {
                    465:        int i;
                    466:
                    467:        for (i = 0; i < ESO_RDR_TIMEOUT; i++) {
                    468:                if (bus_space_read_1(sc->sc_sb_iot, sc->sc_sb_ioh,
                    469:                    ESO_SB_RBSR) & ESO_SB_RBSR_RDAV) {
                    470:                        return (bus_space_read_1(sc->sc_sb_iot,
                    471:                            sc->sc_sb_ioh, ESO_SB_RDR));
                    472:                } else {
                    473:                        delay(10);
                    474:                }
                    475:        }
                    476:
                    477:        printf("%s: RDR timeout\n", sc->sc_dev.dv_xname);
                    478:        return (-1);
                    479: }
                    480:
                    481:
                    482: HIDE uint8_t
                    483: eso_read_ctlreg(sc, reg)
                    484:        struct eso_softc *sc;
                    485:        uint8_t reg;
                    486: {
                    487:
                    488:        eso_write_cmd(sc, ESO_CMD_RCR);
                    489:        eso_write_cmd(sc, reg);
                    490:        return (eso_read_rdr(sc));
                    491: }
                    492:
                    493: HIDE void
                    494: eso_write_mixreg(sc, reg, val)
                    495:        struct eso_softc *sc;
                    496:        uint8_t reg, val;
                    497: {
                    498:        int s;
                    499:
                    500:        /* DPRINTF(("mixreg 0x%02x = 0x%02x\n", reg, val)); */
                    501:
                    502:        s = splaudio();
                    503:        bus_space_write_1(sc->sc_sb_iot, sc->sc_sb_ioh, ESO_SB_MIXERADDR, reg);
                    504:        bus_space_write_1(sc->sc_sb_iot, sc->sc_sb_ioh, ESO_SB_MIXERDATA, val);
                    505:        splx(s);
                    506: }
                    507:
                    508: HIDE uint8_t
                    509: eso_read_mixreg(sc, reg)
                    510:        struct eso_softc *sc;
                    511:        uint8_t reg;
                    512: {
                    513:        int s;
                    514:        uint8_t val;
                    515:
                    516:        s = splaudio();
                    517:        bus_space_write_1(sc->sc_sb_iot, sc->sc_sb_ioh, ESO_SB_MIXERADDR, reg);
                    518:        val = bus_space_read_1(sc->sc_sb_iot, sc->sc_sb_ioh, ESO_SB_MIXERDATA);
                    519:        splx(s);
                    520:
                    521:        return (val);
                    522: }
                    523:
                    524: HIDE int
                    525: eso_intr(hdl)
                    526:        void *hdl;
                    527: {
                    528:        struct eso_softc *sc = hdl;
                    529:        uint8_t irqctl;
                    530:
                    531:        irqctl = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ESO_IO_IRQCTL);
                    532:
                    533:        /* If it wasn't ours, that's all she wrote. */
                    534:        if ((irqctl & (ESO_IO_IRQCTL_A1IRQ | ESO_IO_IRQCTL_A2IRQ)) == 0)
                    535:                return (0);
                    536:
                    537:        if (irqctl & ESO_IO_IRQCTL_A1IRQ) {
                    538:                /* Clear interrupt. */
                    539:                (void)bus_space_read_1(sc->sc_sb_iot, sc->sc_sb_ioh,
                    540:                    ESO_SB_RBSR);
                    541:
                    542:                if (sc->sc_rintr)
                    543:                        sc->sc_rintr(sc->sc_rarg);
                    544:                else
                    545:                        wakeup(&sc->sc_rintr);
                    546:        }
                    547:
                    548:        if (irqctl & ESO_IO_IRQCTL_A2IRQ) {
                    549:                /*
                    550:                 * Clear the A2 IRQ latch: the cached value reflects the
                    551:                 * current DAC settings with the IRQ latch bit not set.
                    552:                 */
                    553:                eso_write_mixreg(sc, ESO_MIXREG_A2C2, sc->sc_a2c2);
                    554:
                    555:                if (sc->sc_pintr)
                    556:                        sc->sc_pintr(sc->sc_parg);
                    557:                else
                    558:                        wakeup(&sc->sc_pintr);
                    559:        }
                    560:
                    561: #if 0
                    562:        if ((irqctl & ESO_IO_IRQCTL_MPUIRQ) && sc->sc_mpudev != 0)
                    563:                mpu_intr(sc->sc_mpudev);
                    564: #endif
                    565:
                    566:        return (1);
                    567: }
                    568:
                    569: /* Perform a software reset, including DMA FIFOs. */
                    570: HIDE int
                    571: eso_reset(sc)
                    572:        struct eso_softc *sc;
                    573: {
                    574:        int i;
                    575:
                    576:        bus_space_write_1(sc->sc_sb_iot, sc->sc_sb_ioh, ESO_SB_RESET,
                    577:            ESO_SB_RESET_SW | ESO_SB_RESET_FIFO);
                    578:        /* `Delay' suggested in the data sheet. */
                    579:        (void)bus_space_read_1(sc->sc_sb_iot, sc->sc_sb_ioh, ESO_SB_STATUS);
                    580:        bus_space_write_1(sc->sc_sb_iot, sc->sc_sb_ioh, ESO_SB_RESET, 0);
                    581:
                    582:        /* Wait for reset to take effect. */
                    583:        for (i = 0; i < ESO_RESET_TIMEOUT; i++) {
                    584:                /* Poll for data to become available. */
                    585:                if ((bus_space_read_1(sc->sc_sb_iot, sc->sc_sb_ioh,
                    586:                    ESO_SB_RBSR) & ESO_SB_RBSR_RDAV) != 0 &&
                    587:                    bus_space_read_1(sc->sc_sb_iot, sc->sc_sb_ioh,
                    588:                        ESO_SB_RDR) == ESO_SB_RDR_RESETMAGIC) {
                    589:
                    590:                        /* Activate Solo-1 extension commands. */
                    591:                        eso_write_cmd(sc, ESO_CMD_EXTENB);
                    592:                        /* Reset mixer registers. */
                    593:                        eso_write_mixreg(sc, ESO_MIXREG_RESET,
                    594:                            ESO_MIXREG_RESET_RESET);
                    595:
                    596:                        return (0);
                    597:                } else {
                    598:                        delay(1000);
                    599:                }
                    600:        }
                    601:
                    602:        printf("%s: reset timeout\n", sc->sc_dev.dv_xname);
                    603:        return (-1);
                    604: }
                    605:
                    606:
                    607: /* ARGSUSED */
                    608: HIDE int
                    609: eso_open(hdl, flags)
                    610:        void *hdl;
                    611:        int flags;
                    612: {
                    613:        struct eso_softc *sc = hdl;
                    614:
                    615:        DPRINTF(("%s: open\n", sc->sc_dev.dv_xname));
                    616:
                    617:        sc->sc_pintr = NULL;
                    618:        sc->sc_rintr = NULL;
                    619:
                    620:        return (0);
                    621: }
                    622:
                    623: HIDE void
                    624: eso_close(hdl)
                    625:        void *hdl;
                    626: {
                    627:
                    628:        DPRINTF(("%s: close\n", ((struct eso_softc *)hdl)->sc_dev.dv_xname));
                    629: }
                    630:
                    631: HIDE int
                    632: eso_query_encoding(hdl, fp)
                    633:        void *hdl;
                    634:        struct audio_encoding *fp;
                    635: {
                    636:
                    637:        switch (fp->index) {
                    638:        case 0:
                    639:                strlcpy(fp->name, AudioEulinear, sizeof fp->name);
                    640:                fp->encoding = AUDIO_ENCODING_ULINEAR;
                    641:                fp->precision = 8;
                    642:                fp->flags = 0;
                    643:                break;
                    644:        case 1:
                    645:                strlcpy(fp->name, AudioEslinear, sizeof fp->name);
                    646:                fp->encoding = AUDIO_ENCODING_SLINEAR;
                    647:                fp->precision = 8;
                    648:                fp->flags = 0;
                    649:                break;
                    650:        case 2:
                    651:                fp->precision = 16;
                    652:                if (fp->flags & AUOPEN_READ) {
                    653:                        strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
                    654:                        fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
                    655:                        if (fp->flags & AUOPEN_WRITE)
                    656:                                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    657:                        else
                    658:                                fp->flags = 0;
                    659:                } else {
                    660:                        strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
                    661:                        fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
                    662:                        fp->flags = 0;
                    663:                }
                    664:                break;
                    665:        case 3:
                    666:                fp->precision = 16;
                    667:                if (fp->flags & AUOPEN_READ) {
                    668:                        strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
                    669:                        fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
                    670:                        if (fp->flags & AUOPEN_WRITE)
                    671:                                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    672:                        else
                    673:                                fp->flags = 0;
                    674:                } else {
                    675:                        strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
                    676:                        fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
                    677:                        fp->flags = 0;
                    678:                }
                    679:                break;
                    680:        case 4:
                    681:                fp->precision = 16;
                    682:                if (fp->flags & AUOPEN_READ) {
                    683:                        strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
                    684:                        fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
                    685:                } else {
                    686:                        strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
                    687:                        fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
                    688:                }
                    689:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    690:                break;
                    691:        case 5:
                    692:                fp->precision = 16;
                    693:                if (fp->flags & AUOPEN_READ) {
                    694:                        strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
                    695:                        fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
                    696:                } else {
                    697:                        strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
                    698:                        fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
                    699:                }
                    700:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    701:                break;
                    702:        case 6:
                    703:                strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
                    704:                fp->encoding = AUDIO_ENCODING_ULAW;
                    705:                fp->precision = 8;
                    706:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    707:                break;
                    708:        case 7:
                    709:                strlcpy(fp->name, AudioEalaw, sizeof fp->name);
                    710:                fp->encoding = AUDIO_ENCODING_ALAW;
                    711:                fp->precision = 8;
                    712:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    713:                break;
                    714:        default:
                    715:                return (EINVAL);
                    716:        }
                    717:
                    718:        return (0);
                    719: }
                    720:
                    721: HIDE int
                    722: eso_set_params(hdl, setmode, usemode, play, rec)
                    723:        void *hdl;
                    724:        int setmode, usemode;
                    725:        struct audio_params *play, *rec;
                    726: {
                    727:        struct eso_softc *sc = hdl;
                    728:        struct audio_params *p;
                    729:        int mode, r[2], rd[2], clk;
                    730:        unsigned int srg, fltdiv;
                    731:
                    732:        for (mode = AUMODE_RECORD; mode != -1;
                    733:             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
                    734:                if ((setmode & mode) == 0)
                    735:                        continue;
                    736:
                    737:                p = (mode == AUMODE_PLAY) ? play : rec;
                    738:
                    739:                if (p->sample_rate < ESO_MINRATE ||
                    740:                    p->sample_rate > ESO_MAXRATE ||
                    741:                    (p->precision != 8 && p->precision != 16) ||
                    742:                    (p->channels != 1 && p->channels != 2))
                    743:                        return (EINVAL);
                    744:
                    745:                p->factor = 1;
                    746:                p->sw_code = NULL;
                    747:                switch (p->encoding) {
                    748:                case AUDIO_ENCODING_SLINEAR_BE:
                    749:                case AUDIO_ENCODING_ULINEAR_BE:
                    750:                        if (mode == AUMODE_PLAY && p->precision == 16)
                    751:                                p->sw_code = swap_bytes;
                    752:                        break;
                    753:                case AUDIO_ENCODING_SLINEAR_LE:
                    754:                case AUDIO_ENCODING_ULINEAR_LE:
                    755:                        if (mode == AUMODE_RECORD && p->precision == 16)
                    756:                                p->sw_code = swap_bytes;
                    757:                        break;
                    758:                case AUDIO_ENCODING_ULAW:
                    759:                        if (mode == AUMODE_PLAY) {
                    760:                                p->factor = 2;
                    761:                                p->sw_code = mulaw_to_ulinear16;
                    762:                        } else {
                    763:                                p->sw_code = ulinear8_to_mulaw;
                    764:                        }
                    765:                        break;
                    766:                case AUDIO_ENCODING_ALAW:
                    767:                        if (mode == AUMODE_PLAY) {
                    768:                                p->factor = 2;
                    769:                                p->sw_code = alaw_to_ulinear16;
                    770:                        } else {
                    771:                                p->sw_code = ulinear8_to_alaw;
                    772:                        }
                    773:                        break;
                    774:                default:
                    775:                        return (EINVAL);
                    776:                }
                    777:
                    778:                /*
                    779:                 * We'll compute both possible sample rate dividers and pick
                    780:                 * the one with the least error.
                    781:                 */
                    782: #define ABS(x) ((x) < 0 ? -(x) : (x))
                    783:                r[0] = ESO_CLK0 /
                    784:                    (128 - (rd[0] = 128 - ESO_CLK0 / p->sample_rate));
                    785:                r[1] = ESO_CLK1 /
                    786:                    (128 - (rd[1] = 128 - ESO_CLK1 / p->sample_rate));
                    787:
                    788:                clk = ABS(p->sample_rate - r[0]) > ABS(p->sample_rate - r[1]);
                    789:                srg = rd[clk] | (clk == 1 ? ESO_CLK1_SELECT : 0x00);
                    790:
                    791:                /* Roll-off frequency of 87%, as in the ES1888 driver. */
                    792:                fltdiv = 256 - 200279L / p->sample_rate;
                    793:
                    794:                /* Update to reflect the possibly inexact rate. */
                    795:                p->sample_rate = r[clk];
                    796:
                    797:                if (mode == AUMODE_RECORD) {
                    798:                        /* Audio 1 */
                    799:                        DPRINTF(("A1 srg 0x%02x fdiv 0x%02x\n", srg, fltdiv));
                    800:                        eso_write_ctlreg(sc, ESO_CTLREG_SRG, srg);
                    801:                        eso_write_ctlreg(sc, ESO_CTLREG_FLTDIV, fltdiv);
                    802:                } else {
                    803:                        /* Audio 2 */
                    804:                        DPRINTF(("A2 srg 0x%02x fdiv 0x%02x\n", srg, fltdiv));
                    805:                        eso_write_mixreg(sc, ESO_MIXREG_A2SRG, srg);
                    806:                        eso_write_mixreg(sc, ESO_MIXREG_A2FLTDIV, fltdiv);
                    807:                }
                    808: #undef ABS
                    809:
                    810:        }
                    811:
                    812:        return (0);
                    813: }
                    814:
                    815: HIDE int
                    816: eso_round_blocksize(hdl, blk)
                    817:        void *hdl;
                    818:        int blk;
                    819: {
                    820:
                    821:        return ((blk + 31) & -32); /* keep good alignment; at least 16 req'd */
                    822: }
                    823:
                    824: HIDE int
                    825: eso_halt_output(hdl)
                    826:        void *hdl;
                    827: {
                    828:        struct eso_softc *sc = hdl;
                    829:        int error, s;
                    830:
                    831:        DPRINTF(("%s: halt_output\n", sc->sc_dev.dv_xname));
                    832:
                    833:        /*
                    834:         * Disable auto-initialize DMA, allowing the FIFO to drain and then
                    835:         * stop.  The interrupt callback pointer is cleared at this
                    836:         * point so that an outstanding FIFO interrupt for the remaining data
                    837:         * will be acknowledged without further processing.
                    838:         *
                    839:         * This does not immediately `abort' an operation in progress (c.f.
                    840:         * audio(9)) but is the method to leave the FIFO behind in a clean
                    841:         * state with the least hair.  (Besides, that item needs to be
                    842:         * rephrased for trigger_*()-based DMA environments.)
                    843:         */
                    844:        s = splaudio();
                    845:        eso_write_mixreg(sc, ESO_MIXREG_A2C1,
                    846:            ESO_MIXREG_A2C1_FIFOENB | ESO_MIXREG_A2C1_DMAENB);
                    847:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, ESO_IO_A2DMAM,
                    848:            ESO_IO_A2DMAM_DMAENB);
                    849:
                    850:        sc->sc_pintr = NULL;
                    851:        error = tsleep(&sc->sc_pintr, PCATCH | PWAIT, "esoho", hz);
                    852:        splx(s);
                    853:
                    854:        /* Shut down DMA completely. */
                    855:        eso_write_mixreg(sc, ESO_MIXREG_A2C1, 0);
                    856:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, ESO_IO_A2DMAM, 0);
                    857:
                    858:        return (error == EWOULDBLOCK ? 0 : error);
                    859: }
                    860:
                    861: HIDE int
                    862: eso_halt_input(hdl)
                    863:        void *hdl;
                    864: {
                    865:        struct eso_softc *sc = hdl;
                    866:        int error, s;
                    867:
                    868:        DPRINTF(("%s: halt_input\n", sc->sc_dev.dv_xname));
                    869:
                    870:        /* Just like eso_halt_output(), but for Audio 1. */
                    871:        s = splaudio();
                    872:        eso_write_ctlreg(sc, ESO_CTLREG_A1C2,
                    873:            ESO_CTLREG_A1C2_READ | ESO_CTLREG_A1C2_ADC |
                    874:            ESO_CTLREG_A1C2_DMAENB);
                    875:        bus_space_write_1(sc->sc_dmac_iot, sc->sc_dmac_ioh, ESO_DMAC_MODE,
                    876:            DMA37MD_WRITE | DMA37MD_DEMAND);
                    877:
                    878:        sc->sc_rintr = NULL;
                    879:        error = tsleep(&sc->sc_rintr, PCATCH | PWAIT, "esohi", hz);
                    880:        splx(s);
                    881:
                    882:        /* Shut down DMA completely. */
                    883:        eso_write_ctlreg(sc, ESO_CTLREG_A1C2,
                    884:            ESO_CTLREG_A1C2_READ | ESO_CTLREG_A1C2_ADC);
                    885:        bus_space_write_1(sc->sc_dmac_iot, sc->sc_dmac_ioh, ESO_DMAC_MASK,
                    886:            ESO_DMAC_MASK_MASK);
                    887:
                    888:        return (error == EWOULDBLOCK ? 0 : error);
                    889: }
                    890:
                    891: /* ARGSUSED */
                    892: HIDE int
                    893: eso_getdev(hdl, retp)
                    894:        void *hdl;
                    895:        struct audio_device *retp;
                    896: {
                    897:        struct eso_softc *sc = hdl;
                    898:
                    899:        strlcpy(retp->name, "ESS Solo-1", sizeof retp->name);
                    900:        snprintf(retp->version, sizeof retp->version, "0x%02x",
                    901:            sc->sc_revision);
                    902:        if (sc->sc_revision <=
                    903:            sizeof (eso_rev2model) / sizeof (eso_rev2model[0]))
                    904:                strlcpy(retp->config, eso_rev2model[sc->sc_revision],
                    905:                    sizeof retp->config);
                    906:        else
                    907:                strlcpy(retp->config, "unknown", sizeof retp->config);
                    908:
                    909:        return (0);
                    910: }
                    911:
                    912: HIDE int
                    913: eso_set_port(hdl, cp)
                    914:        void *hdl;
                    915:        mixer_ctrl_t *cp;
                    916: {
                    917:        struct eso_softc *sc = hdl;
                    918:        unsigned int lgain, rgain;
                    919:        uint8_t tmp;
                    920:
                    921:        switch (cp->dev) {
                    922:        case ESO_DAC_PLAY_VOL:
                    923:        case ESO_MIC_PLAY_VOL:
                    924:        case ESO_LINE_PLAY_VOL:
                    925:        case ESO_SYNTH_PLAY_VOL:
                    926:        case ESO_CD_PLAY_VOL:
                    927:        case ESO_AUXB_PLAY_VOL:
                    928:        case ESO_RECORD_VOL:
                    929:        case ESO_DAC_REC_VOL:
                    930:        case ESO_MIC_REC_VOL:
                    931:        case ESO_LINE_REC_VOL:
                    932:        case ESO_SYNTH_REC_VOL:
                    933:        case ESO_CD_REC_VOL:
                    934:        case ESO_AUXB_REC_VOL:
                    935:                if (cp->type != AUDIO_MIXER_VALUE)
                    936:                        return (EINVAL);
                    937:
                    938:                /*
                    939:                 * Stereo-capable mixer ports: if we get a single-channel
                    940:                 * gain value passed in, then we duplicate it to both left
                    941:                 * and right channels.
                    942:                 */
                    943:                switch (cp->un.value.num_channels) {
                    944:                case 1:
                    945:                        lgain = rgain = ESO_GAIN_TO_4BIT(
                    946:                            cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
                    947:                        break;
                    948:                case 2:
                    949:                        lgain = ESO_GAIN_TO_4BIT(
                    950:                            cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
                    951:                        rgain = ESO_GAIN_TO_4BIT(
                    952:                            cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
                    953:                        break;
                    954:                default:
                    955:                        return (EINVAL);
                    956:                }
                    957:
                    958:                sc->sc_gain[cp->dev][ESO_LEFT] = lgain;
                    959:                sc->sc_gain[cp->dev][ESO_RIGHT] = rgain;
                    960:                eso_set_gain(sc, cp->dev);
                    961:                break;
                    962:
                    963:        case ESO_MASTER_VOL:
                    964:                if (cp->type != AUDIO_MIXER_VALUE)
                    965:                        return (EINVAL);
                    966:
                    967:                /* Like above, but a precision of 6 bits. */
                    968:                switch (cp->un.value.num_channels) {
                    969:                case 1:
                    970:                        lgain = rgain = ESO_GAIN_TO_6BIT(
                    971:                            cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
                    972:                        break;
                    973:                case 2:
                    974:                        lgain = ESO_GAIN_TO_6BIT(
                    975:                            cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
                    976:                        rgain = ESO_GAIN_TO_6BIT(
                    977:                            cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
                    978:                        break;
                    979:                default:
                    980:                        return (EINVAL);
                    981:                }
                    982:
                    983:                sc->sc_gain[cp->dev][ESO_LEFT] = lgain;
                    984:                sc->sc_gain[cp->dev][ESO_RIGHT] = rgain;
                    985:                eso_set_gain(sc, cp->dev);
                    986:                break;
                    987:
                    988:        case ESO_SPATIALIZER:
                    989:                if (cp->type != AUDIO_MIXER_VALUE ||
                    990:                    cp->un.value.num_channels != 1)
                    991:                        return (EINVAL);
                    992:
                    993:                sc->sc_gain[cp->dev][ESO_LEFT] =
                    994:                    sc->sc_gain[cp->dev][ESO_RIGHT] =
                    995:                    ESO_GAIN_TO_6BIT(
                    996:                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
                    997:                eso_set_gain(sc, cp->dev);
                    998:                break;
                    999:
                   1000:        case ESO_MONO_PLAY_VOL:
                   1001:        case ESO_MONO_REC_VOL:
                   1002:                if (cp->type != AUDIO_MIXER_VALUE ||
                   1003:                    cp->un.value.num_channels != 1)
                   1004:                        return (EINVAL);
                   1005:
                   1006:                sc->sc_gain[cp->dev][ESO_LEFT] =
                   1007:                    sc->sc_gain[cp->dev][ESO_RIGHT] =
                   1008:                    ESO_GAIN_TO_4BIT(
                   1009:                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
                   1010:                eso_set_gain(sc, cp->dev);
                   1011:                break;
                   1012:
                   1013:        case ESO_PCSPEAKER_VOL:
                   1014:                if (cp->type != AUDIO_MIXER_VALUE ||
                   1015:                    cp->un.value.num_channels != 1)
                   1016:                        return (EINVAL);
                   1017:
                   1018:                sc->sc_gain[cp->dev][ESO_LEFT] =
                   1019:                    sc->sc_gain[cp->dev][ESO_RIGHT] =
                   1020:                    ESO_GAIN_TO_3BIT(
                   1021:                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
                   1022:                eso_set_gain(sc, cp->dev);
                   1023:                break;
                   1024:
                   1025:        case ESO_SPATIALIZER_ENABLE:
                   1026:                if (cp->type != AUDIO_MIXER_ENUM)
                   1027:                        return (EINVAL);
                   1028:
                   1029:                sc->sc_spatializer = (cp->un.ord != 0);
                   1030:
                   1031:                tmp = eso_read_mixreg(sc, ESO_MIXREG_SPAT);
                   1032:                if (sc->sc_spatializer)
                   1033:                        tmp |= ESO_MIXREG_SPAT_ENB;
                   1034:                else
                   1035:                        tmp &= ~ESO_MIXREG_SPAT_ENB;
                   1036:                eso_write_mixreg(sc, ESO_MIXREG_SPAT,
                   1037:                    tmp | ESO_MIXREG_SPAT_RSTREL);
                   1038:                break;
                   1039:
                   1040:        case ESO_MONOOUT_SOURCE:
                   1041:                if (cp->type != AUDIO_MIXER_ENUM)
                   1042:                        return (EINVAL);
                   1043:
                   1044:                sc->sc_monooutsrc = cp->un.ord;
                   1045:
                   1046:                tmp = eso_read_mixreg(sc, ESO_MIXREG_MPM);
                   1047:                tmp &= ~ESO_MIXREG_MPM_MOMASK;
                   1048:                tmp |= sc->sc_monooutsrc;
                   1049:                eso_write_mixreg(sc, ESO_MIXREG_MPM, tmp);
                   1050:                break;
                   1051:
                   1052:        case ESO_RECORD_MONITOR:
                   1053:                if (cp->type != AUDIO_MIXER_ENUM)
                   1054:                        return (EINVAL);
                   1055:
                   1056:                sc->sc_recmon = (cp->un.ord != 0);
                   1057:
                   1058:                tmp = eso_read_ctlreg(sc, ESO_CTLREG_ACTL);
                   1059:                if (sc->sc_recmon)
                   1060:                        tmp |= ESO_CTLREG_ACTL_RECMON;
                   1061:                else
                   1062:                        tmp &= ~ESO_CTLREG_ACTL_RECMON;
                   1063:                eso_write_ctlreg(sc, ESO_CTLREG_ACTL, tmp);
                   1064:                break;
                   1065:
                   1066:        case ESO_RECORD_SOURCE:
                   1067:                if (cp->type != AUDIO_MIXER_ENUM)
                   1068:                        return (EINVAL);
                   1069:
                   1070:                return (eso_set_recsrc(sc, cp->un.ord));
                   1071:
                   1072:        case ESO_MIC_PREAMP:
                   1073:                if (cp->type != AUDIO_MIXER_ENUM)
                   1074:                        return (EINVAL);
                   1075:
                   1076:                sc->sc_preamp = (cp->un.ord != 0);
                   1077:
                   1078:                tmp = eso_read_mixreg(sc, ESO_MIXREG_MPM);
                   1079:                tmp &= ~ESO_MIXREG_MPM_RESV0;
                   1080:                if (sc->sc_preamp)
                   1081:                        tmp |= ESO_MIXREG_MPM_PREAMP;
                   1082:                else
                   1083:                        tmp &= ~ESO_MIXREG_MPM_PREAMP;
                   1084:                eso_write_mixreg(sc, ESO_MIXREG_MPM, tmp);
                   1085:                break;
                   1086:
                   1087:        default:
                   1088:                return (EINVAL);
                   1089:        }
                   1090:
                   1091:        return (0);
                   1092: }
                   1093:
                   1094: HIDE int
                   1095: eso_get_port(hdl, cp)
                   1096:        void *hdl;
                   1097:        mixer_ctrl_t *cp;
                   1098: {
                   1099:        struct eso_softc *sc = hdl;
                   1100:
                   1101:        switch (cp->dev) {
                   1102:        case ESO_DAC_PLAY_VOL:
                   1103:        case ESO_MIC_PLAY_VOL:
                   1104:        case ESO_LINE_PLAY_VOL:
                   1105:        case ESO_SYNTH_PLAY_VOL:
                   1106:        case ESO_CD_PLAY_VOL:
                   1107:        case ESO_AUXB_PLAY_VOL:
                   1108:        case ESO_MASTER_VOL:
                   1109:        case ESO_RECORD_VOL:
                   1110:        case ESO_DAC_REC_VOL:
                   1111:        case ESO_MIC_REC_VOL:
                   1112:        case ESO_LINE_REC_VOL:
                   1113:        case ESO_SYNTH_REC_VOL:
                   1114:        case ESO_CD_REC_VOL:
                   1115:        case ESO_AUXB_REC_VOL:
                   1116:                /*
                   1117:                 * Stereo-capable ports: if a single-channel query is made,
                   1118:                 * just return the left channel's value (since single-channel
                   1119:                 * settings themselves are applied to both channels).
                   1120:                 */
                   1121:                switch (cp->un.value.num_channels) {
                   1122:                case 1:
                   1123:                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
                   1124:                            sc->sc_gain[cp->dev][ESO_LEFT];
                   1125:                        break;
                   1126:                case 2:
                   1127:                        cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
                   1128:                            sc->sc_gain[cp->dev][ESO_LEFT];
                   1129:                        cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
                   1130:                            sc->sc_gain[cp->dev][ESO_RIGHT];
                   1131:                        break;
                   1132:                default:
                   1133:                        return (EINVAL);
                   1134:                }
                   1135:                break;
                   1136:
                   1137:        case ESO_MONO_PLAY_VOL:
                   1138:        case ESO_PCSPEAKER_VOL:
                   1139:        case ESO_MONO_REC_VOL:
                   1140:        case ESO_SPATIALIZER:
                   1141:                if (cp->un.value.num_channels != 1)
                   1142:                        return (EINVAL);
                   1143:                cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
                   1144:                    sc->sc_gain[cp->dev][ESO_LEFT];
                   1145:                break;
                   1146:
                   1147:        case ESO_RECORD_MONITOR:
                   1148:                cp->un.ord = sc->sc_recmon;
                   1149:                break;
                   1150:
                   1151:        case ESO_RECORD_SOURCE:
                   1152:                cp->un.ord = sc->sc_recsrc;
                   1153:                break;
                   1154:
                   1155:        case ESO_MONOOUT_SOURCE:
                   1156:                cp->un.ord = sc->sc_monooutsrc;
                   1157:                break;
                   1158:
                   1159:        case ESO_SPATIALIZER_ENABLE:
                   1160:                cp->un.ord = sc->sc_spatializer;
                   1161:                break;
                   1162:
                   1163:        case ESO_MIC_PREAMP:
                   1164:                cp->un.ord = sc->sc_preamp;
                   1165:                break;
                   1166:
                   1167:        default:
                   1168:                return (EINVAL);
                   1169:        }
                   1170:
                   1171:
                   1172:        return (0);
                   1173:
                   1174: }
                   1175:
                   1176: HIDE int
                   1177: eso_query_devinfo(hdl, dip)
                   1178:        void *hdl;
                   1179:        mixer_devinfo_t *dip;
                   1180: {
                   1181:
                   1182:        switch (dip->index) {
                   1183:        case ESO_DAC_PLAY_VOL:
                   1184:                dip->mixer_class = ESO_INPUT_CLASS;
                   1185:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1186:                strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
                   1187:                dip->type = AUDIO_MIXER_VALUE;
                   1188:                dip->un.v.num_channels = 2;
                   1189:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1190:                    sizeof dip->un.v.units.name);
                   1191:                break;
                   1192:        case ESO_MIC_PLAY_VOL:
                   1193:                dip->mixer_class = ESO_INPUT_CLASS;
                   1194:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1195:                strlcpy(dip->label.name, AudioNmicrophone,
                   1196:                    sizeof dip->label.name);
                   1197:                dip->type = AUDIO_MIXER_VALUE;
                   1198:                dip->un.v.num_channels = 2;
                   1199:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1200:                    sizeof dip->un.v.units.name);
                   1201:                break;
                   1202:        case ESO_LINE_PLAY_VOL:
                   1203:                dip->mixer_class = ESO_INPUT_CLASS;
                   1204:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1205:                strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
                   1206:                dip->type = AUDIO_MIXER_VALUE;
                   1207:                dip->un.v.num_channels = 2;
                   1208:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1209:                    sizeof dip->un.v.units.name);
                   1210:                break;
                   1211:        case ESO_SYNTH_PLAY_VOL:
                   1212:                dip->mixer_class = ESO_INPUT_CLASS;
                   1213:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1214:                strlcpy(dip->label.name, AudioNfmsynth,
                   1215:                    sizeof dip->label.name);
                   1216:                dip->type = AUDIO_MIXER_VALUE;
                   1217:                dip->un.v.num_channels = 2;
                   1218:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1219:                    sizeof dip->un.v.units.name);
                   1220:                break;
                   1221:        case ESO_MONO_PLAY_VOL:
                   1222:                dip->mixer_class = ESO_INPUT_CLASS;
                   1223:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1224:                strlcpy(dip->label.name, "mono_in", sizeof dip->label.name);
                   1225:                dip->type = AUDIO_MIXER_VALUE;
                   1226:                dip->un.v.num_channels = 1;
                   1227:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1228:                    sizeof dip->un.v.units.name);
                   1229:                break;
                   1230:        case ESO_CD_PLAY_VOL:
                   1231:                dip->mixer_class = ESO_INPUT_CLASS;
                   1232:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1233:                strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
                   1234:                dip->type = AUDIO_MIXER_VALUE;
                   1235:                dip->un.v.num_channels = 2;
                   1236:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1237:                    sizeof dip->un.v.units.name);
                   1238:                break;
                   1239:        case ESO_AUXB_PLAY_VOL:
                   1240:                dip->mixer_class = ESO_INPUT_CLASS;
                   1241:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1242:                strlcpy(dip->label.name, "auxb", sizeof dip->label.name);
                   1243:                dip->type = AUDIO_MIXER_VALUE;
                   1244:                dip->un.v.num_channels = 2;
                   1245:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1246:                    sizeof dip->un.v.units.name);
                   1247:                break;
                   1248:
                   1249:        case ESO_MIC_PREAMP:
                   1250:                dip->mixer_class = ESO_MICROPHONE_CLASS;
                   1251:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1252:                strlcpy(dip->label.name, AudioNpreamp, sizeof dip->label.name);
                   1253:                dip->type = AUDIO_MIXER_ENUM;
                   1254:                dip->un.e.num_mem = 2;
                   1255:                strlcpy(dip->un.e.member[0].label.name, AudioNoff,
                   1256:                    sizeof dip->un.e.member[0].label.name);
                   1257:                dip->un.e.member[0].ord = 0;
                   1258:                strlcpy(dip->un.e.member[1].label.name, AudioNon,
                   1259:                    sizeof dip->un.e.member[1].label.name);
                   1260:                dip->un.e.member[1].ord = 1;
                   1261:                break;
                   1262:        case ESO_MICROPHONE_CLASS:
                   1263:                dip->mixer_class = ESO_MICROPHONE_CLASS;
                   1264:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1265:                strlcpy(dip->label.name, AudioNmicrophone,
                   1266:                    sizeof dip->label.name);
                   1267:                dip->type = AUDIO_MIXER_CLASS;
                   1268:                break;
                   1269:
                   1270:        case ESO_INPUT_CLASS:
                   1271:                dip->mixer_class = ESO_INPUT_CLASS;
                   1272:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1273:                strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
                   1274:                dip->type = AUDIO_MIXER_CLASS;
                   1275:                break;
                   1276:
                   1277:        case ESO_MASTER_VOL:
                   1278:                dip->mixer_class = ESO_OUTPUT_CLASS;
                   1279:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1280:                strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
                   1281:                dip->type = AUDIO_MIXER_VALUE;
                   1282:                dip->un.v.num_channels = 2;
                   1283:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1284:                    sizeof dip->un.v.units.name);
                   1285:                break;
                   1286:        case ESO_PCSPEAKER_VOL:
                   1287:                dip->mixer_class = ESO_OUTPUT_CLASS;
                   1288:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1289:                strlcpy(dip->label.name, "pc_speaker", sizeof dip->label.name);
                   1290:                dip->type = AUDIO_MIXER_VALUE;
                   1291:                dip->un.v.num_channels = 1;
                   1292:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1293:                    sizeof dip->un.v.units.name);
                   1294:                break;
                   1295:        case ESO_MONOOUT_SOURCE:
                   1296:                dip->mixer_class = ESO_OUTPUT_CLASS;
                   1297:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1298:                strlcpy(dip->label.name, "mono_out", sizeof dip->label.name);
                   1299:                dip->type = AUDIO_MIXER_ENUM;
                   1300:                dip->un.e.num_mem = 3;
                   1301:                strlcpy(dip->un.e.member[0].label.name, AudioNmute,
                   1302:                    sizeof dip->un.e.member[0].label.name);
                   1303:                dip->un.e.member[0].ord = ESO_MIXREG_MPM_MOMUTE;
                   1304:                strlcpy(dip->un.e.member[1].label.name, AudioNdac,
                   1305:                    sizeof dip->un.e.member[1].label.name);
                   1306:                dip->un.e.member[1].ord = ESO_MIXREG_MPM_MOA2R;
                   1307:                strlcpy(dip->un.e.member[2].label.name, AudioNmixerout,
                   1308:                    sizeof dip->un.e.member[2].label.name);
                   1309:                dip->un.e.member[2].ord = ESO_MIXREG_MPM_MOREC;
                   1310:                break;
                   1311:        case ESO_SPATIALIZER:
                   1312:                dip->mixer_class = ESO_OUTPUT_CLASS;
                   1313:                dip->prev = AUDIO_MIXER_LAST;
                   1314:                dip->next = ESO_SPATIALIZER_ENABLE;
                   1315:                strlcpy(dip->label.name, AudioNspatial,
                   1316:                    sizeof dip->label.name);
                   1317:                dip->type = AUDIO_MIXER_VALUE;
                   1318:                dip->un.v.num_channels = 1;
                   1319:                strlcpy(dip->un.v.units.name, "level",
                   1320:                    sizeof dip->un.v.units.name);
                   1321:                break;
                   1322:        case ESO_SPATIALIZER_ENABLE:
                   1323:                dip->mixer_class = ESO_OUTPUT_CLASS;
                   1324:                dip->prev = ESO_SPATIALIZER;
                   1325:                dip->next = AUDIO_MIXER_LAST;
                   1326:                strlcpy(dip->label.name, "enable", sizeof dip->label.name);
                   1327:                dip->type = AUDIO_MIXER_ENUM;
                   1328:                dip->un.e.num_mem = 2;
                   1329:                strlcpy(dip->un.e.member[0].label.name, AudioNoff,
                   1330:                    sizeof dip->un.e.member[0].label.name);
                   1331:                dip->un.e.member[0].ord = 0;
                   1332:                strlcpy(dip->un.e.member[1].label.name, AudioNon,
                   1333:                    sizeof dip->un.e.member[1].label.name);
                   1334:                dip->un.e.member[1].ord = 1;
                   1335:                break;
                   1336:
                   1337:        case ESO_OUTPUT_CLASS:
                   1338:                dip->mixer_class = ESO_OUTPUT_CLASS;
                   1339:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1340:                strlcpy(dip->label.name, AudioCoutputs,
                   1341:                    sizeof dip->label.name);
                   1342:                dip->type = AUDIO_MIXER_CLASS;
                   1343:                break;
                   1344:
                   1345:        case ESO_RECORD_MONITOR:
                   1346:                dip->mixer_class = ESO_MONITOR_CLASS;
                   1347:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1348:                strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
                   1349:                dip->type = AUDIO_MIXER_ENUM;
                   1350:                dip->un.e.num_mem = 2;
                   1351:                strlcpy(dip->un.e.member[0].label.name, AudioNoff,
                   1352:                    sizeof dip->un.e.member[0].label.name);
                   1353:                dip->un.e.member[0].ord = 0;
                   1354:                strlcpy(dip->un.e.member[1].label.name, AudioNon,
                   1355:                    sizeof dip->un.e.member[1].label.name);
                   1356:                dip->un.e.member[1].ord = 1;
                   1357:                break;
                   1358:        case ESO_MONITOR_CLASS:
                   1359:                dip->mixer_class = ESO_MONITOR_CLASS;
                   1360:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1361:                strlcpy(dip->label.name, AudioCmonitor,
                   1362:                    sizeof dip->label.name);
                   1363:                dip->type = AUDIO_MIXER_CLASS;
                   1364:                break;
                   1365:
                   1366:        case ESO_RECORD_VOL:
                   1367:                dip->mixer_class = ESO_RECORD_CLASS;
                   1368:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1369:                strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
                   1370:                dip->type = AUDIO_MIXER_VALUE;
                   1371:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1372:                    sizeof dip->un.v.units.name);
                   1373:                break;
                   1374:        case ESO_RECORD_SOURCE:
                   1375:                dip->mixer_class = ESO_RECORD_CLASS;
                   1376:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1377:                strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
                   1378:                dip->type = AUDIO_MIXER_ENUM;
                   1379:                dip->un.e.num_mem = 4;
                   1380:                strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone,
                   1381:                    sizeof dip->un.e.member[0].label.name);
                   1382:                dip->un.e.member[0].ord = ESO_MIXREG_ERS_MIC;
                   1383:                strlcpy(dip->un.e.member[1].label.name, AudioNline,
                   1384:                    sizeof dip->un.e.member[1].label.name);
                   1385:                dip->un.e.member[1].ord = ESO_MIXREG_ERS_LINE;
                   1386:                strlcpy(dip->un.e.member[2].label.name, AudioNcd,
                   1387:                    sizeof dip->un.e.member[2].label.name);
                   1388:                dip->un.e.member[2].ord = ESO_MIXREG_ERS_CD;
                   1389:                strlcpy(dip->un.e.member[3].label.name, AudioNmixerout,
                   1390:                    sizeof dip->un.e.member[3].label.name);
                   1391:                dip->un.e.member[3].ord = ESO_MIXREG_ERS_MIXER;
                   1392:                break;
                   1393:        case ESO_DAC_REC_VOL:
                   1394:                dip->mixer_class = ESO_RECORD_CLASS;
                   1395:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1396:                strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
                   1397:                dip->type = AUDIO_MIXER_VALUE;
                   1398:                dip->un.v.num_channels = 2;
                   1399:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1400:                    sizeof dip->un.v.units.name);
                   1401:                break;
                   1402:        case ESO_MIC_REC_VOL:
                   1403:                dip->mixer_class = ESO_RECORD_CLASS;
                   1404:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1405:                strlcpy(dip->label.name, AudioNmicrophone,
                   1406:                    sizeof dip->label.name);
                   1407:                dip->type = AUDIO_MIXER_VALUE;
                   1408:                dip->un.v.num_channels = 2;
                   1409:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1410:                    sizeof dip->un.v.units.name);
                   1411:                break;
                   1412:        case ESO_LINE_REC_VOL:
                   1413:                dip->mixer_class = ESO_RECORD_CLASS;
                   1414:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1415:                strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
                   1416:                dip->type = AUDIO_MIXER_VALUE;
                   1417:                dip->un.v.num_channels = 2;
                   1418:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1419:                    sizeof dip->un.v.units.name);
                   1420:                break;
                   1421:        case ESO_SYNTH_REC_VOL:
                   1422:                dip->mixer_class = ESO_RECORD_CLASS;
                   1423:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1424:                strlcpy(dip->label.name, AudioNfmsynth,
                   1425:                    sizeof dip->label.name);
                   1426:                dip->type = AUDIO_MIXER_VALUE;
                   1427:                dip->un.v.num_channels = 2;
                   1428:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1429:                    sizeof dip->un.v.units.name);
                   1430:                break;
                   1431:        case ESO_MONO_REC_VOL:
                   1432:                dip->mixer_class = ESO_RECORD_CLASS;
                   1433:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1434:                strlcpy(dip->label.name, "mono_in", sizeof dip->label.name);
                   1435:                dip->type = AUDIO_MIXER_VALUE;
                   1436:                dip->un.v.num_channels = 1; /* No lies */
                   1437:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1438:                    sizeof dip->un.v.units.name);
                   1439:                break;
                   1440:        case ESO_CD_REC_VOL:
                   1441:                dip->mixer_class = ESO_RECORD_CLASS;
                   1442:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1443:                strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
                   1444:                dip->type = AUDIO_MIXER_VALUE;
                   1445:                dip->un.v.num_channels = 2;
                   1446:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1447:                    sizeof dip->un.v.units.name);
                   1448:                break;
                   1449:        case ESO_AUXB_REC_VOL:
                   1450:                dip->mixer_class = ESO_RECORD_CLASS;
                   1451:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1452:                strlcpy(dip->label.name, "auxb", sizeof dip->label.name);
                   1453:                dip->type = AUDIO_MIXER_VALUE;
                   1454:                dip->un.v.num_channels = 2;
                   1455:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1456:                    sizeof dip->un.v.units.name);
                   1457:                break;
                   1458:        case ESO_RECORD_CLASS:
                   1459:                dip->mixer_class = ESO_RECORD_CLASS;
                   1460:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1461:                strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
                   1462:                dip->type = AUDIO_MIXER_CLASS;
                   1463:                break;
                   1464:
                   1465:        default:
                   1466:                return (ENXIO);
                   1467:        }
                   1468:
                   1469:        return (0);
                   1470: }
                   1471:
                   1472: HIDE int
                   1473: eso_allocmem(sc, size, align, boundary, flags, ed)
                   1474:        struct eso_softc *sc;
                   1475:        size_t size;
                   1476:        size_t align;
                   1477:        size_t boundary;
                   1478:        int flags;
                   1479:        struct eso_dma *ed;
                   1480: {
                   1481:        int error, wait;
                   1482:
                   1483:        wait = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
                   1484:        ed->ed_size = size;
                   1485:
                   1486:        error = bus_dmamem_alloc(sc->sc_dmat, ed->ed_size, align, boundary,
                   1487:            ed->ed_segs, sizeof (ed->ed_segs) / sizeof (ed->ed_segs[0]),
                   1488:            &ed->ed_nsegs, wait);
                   1489:        if (error)
                   1490:                goto out;
                   1491:
                   1492:        error = bus_dmamem_map(sc->sc_dmat, ed->ed_segs, ed->ed_nsegs,
                   1493:            ed->ed_size, &ed->ed_addr, wait | BUS_DMA_COHERENT);
                   1494:        if (error)
                   1495:                goto free;
                   1496:
                   1497:        error = bus_dmamap_create(sc->sc_dmat, ed->ed_size, 1, ed->ed_size, 0,
                   1498:            wait, &ed->ed_map);
                   1499:        if (error)
                   1500:                goto unmap;
                   1501:
                   1502:        error = bus_dmamap_load(sc->sc_dmat, ed->ed_map, ed->ed_addr,
                   1503:            ed->ed_size, NULL, wait);
                   1504:        if (error)
                   1505:                goto destroy;
                   1506:
                   1507:        return (0);
                   1508:
                   1509:  destroy:
                   1510:        bus_dmamap_destroy(sc->sc_dmat, ed->ed_map);
                   1511:  unmap:
                   1512:        bus_dmamem_unmap(sc->sc_dmat, ed->ed_addr, ed->ed_size);
                   1513:  free:
                   1514:        bus_dmamem_free(sc->sc_dmat, ed->ed_segs, ed->ed_nsegs);
                   1515:  out:
                   1516:        return (error);
                   1517: }
                   1518:
                   1519: HIDE void
                   1520: eso_freemem(sc, ed)
                   1521:        struct eso_softc *sc;
                   1522:        struct eso_dma *ed;
                   1523: {
                   1524:
                   1525:        bus_dmamap_unload(sc->sc_dmat, ed->ed_map);
                   1526:        bus_dmamap_destroy(sc->sc_dmat, ed->ed_map);
                   1527:        bus_dmamem_unmap(sc->sc_dmat, ed->ed_addr, ed->ed_size);
                   1528:        bus_dmamem_free(sc->sc_dmat, ed->ed_segs, ed->ed_nsegs);
                   1529: }
                   1530:
                   1531: HIDE void *
                   1532: eso_allocm(hdl, direction, size, type, flags)
                   1533:        void *hdl;
                   1534:        int direction;
                   1535:        size_t size;
                   1536:        int type, flags;
                   1537: {
                   1538:        struct eso_softc *sc = hdl;
                   1539:        struct eso_dma *ed;
                   1540:        size_t boundary;
                   1541:        int error;
                   1542:
                   1543:        if ((ed = malloc(size, type, flags)) == NULL)
                   1544:                return (NULL);
                   1545:
                   1546:        /*
                   1547:         * Apparently the Audio 1 DMA controller's current address
                   1548:         * register can't roll over a 64K address boundary, so we have to
                   1549:         * take care of that ourselves.  The second channel DMA controller
                   1550:         * doesn't have that restriction, however.
                   1551:         */
                   1552:        if (direction == AUMODE_RECORD)
                   1553:                boundary = 0x10000;
                   1554:        else
                   1555:                boundary = 0;
                   1556:
                   1557:
                   1558:        error = eso_allocmem(sc, size, 32, boundary, flags, ed);
                   1559:        if (error) {
                   1560:                free(ed, type);
                   1561:                return (NULL);
                   1562:        }
                   1563:        ed->ed_next = sc->sc_dmas;
                   1564:        sc->sc_dmas = ed;
                   1565:
                   1566:        return (KVADDR(ed));
                   1567: }
                   1568:
                   1569: HIDE void
                   1570: eso_freem(hdl, addr, type)
                   1571:        void *hdl;
                   1572:        void *addr;
                   1573:        int type;
                   1574: {
                   1575:        struct eso_softc *sc = hdl;
                   1576:        struct eso_dma *p, **pp;
                   1577:
                   1578:        for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->ed_next) {
                   1579:                if (KVADDR(p) == addr) {
                   1580:                        eso_freemem(sc, p);
                   1581:                        *pp = p->ed_next;
                   1582:                        free(p, type);
                   1583:                        return;
                   1584:                }
                   1585:        }
                   1586: }
                   1587:
                   1588: HIDE size_t
                   1589: eso_round_buffersize(hdl, direction, bufsize)
                   1590:        void *hdl;
                   1591:        int direction;
                   1592:        size_t bufsize;
                   1593: {
                   1594:
                   1595:        /* 64K restriction: ISA at eleven? */
                   1596:        if (bufsize > 65536)
                   1597:                bufsize = 65536;
                   1598:
                   1599:        return (bufsize);
                   1600: }
                   1601:
                   1602: HIDE paddr_t
                   1603: eso_mappage(hdl, addr, offs, prot)
                   1604:        void *hdl;
                   1605:        void *addr;
                   1606:        off_t offs;
                   1607:        int prot;
                   1608: {
                   1609:        struct eso_softc *sc = hdl;
                   1610:        struct eso_dma *ed;
                   1611:
                   1612:        if (offs < 0)
                   1613:                return (-1);
                   1614:        for (ed = sc->sc_dmas; ed != NULL && KVADDR(ed) == addr;
                   1615:             ed = ed->ed_next)
                   1616:                ;
                   1617:        if (ed == NULL)
                   1618:                return (-1);
                   1619:
                   1620:        return (bus_dmamem_mmap(sc->sc_dmat, ed->ed_segs, ed->ed_nsegs,
                   1621:            offs, prot, BUS_DMA_WAITOK));
                   1622: }
                   1623:
                   1624: /* ARGSUSED */
                   1625: HIDE int
                   1626: eso_get_props(hdl)
                   1627:        void *hdl;
                   1628: {
                   1629:
                   1630:        return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
                   1631:            AUDIO_PROP_FULLDUPLEX);
                   1632: }
                   1633:
                   1634: HIDE int
                   1635: eso_trigger_output(hdl, start, end, blksize, intr, arg, param)
                   1636:        void *hdl;
                   1637:        void *start, *end;
                   1638:        int blksize;
                   1639:        void (*intr)(void *);
                   1640:        void *arg;
                   1641:        struct audio_params *param;
                   1642: {
                   1643:        struct eso_softc *sc = hdl;
                   1644:        struct eso_dma *ed;
                   1645:        uint8_t a2c1;
                   1646:
                   1647:        DPRINTF((
                   1648:            "%s: trigger_output: start %p, end %p, blksize %d, intr %p(%p)\n",
                   1649:            sc->sc_dev.dv_xname, start, end, blksize, intr, arg));
                   1650:        DPRINTF(("%s: param: rate %lu, encoding %u, precision %u, channels %u, sw_code %p, factor %d\n",
                   1651:            sc->sc_dev.dv_xname, param->sample_rate, param->encoding,
                   1652:            param->precision, param->channels, param->sw_code, param->factor));
                   1653:
                   1654:        /* Find DMA buffer. */
                   1655:        for (ed = sc->sc_dmas; ed != NULL && KVADDR(ed) != start;
                   1656:             ed = ed->ed_next)
                   1657:                ;
                   1658:        if (ed == NULL) {
                   1659:                printf("%s: trigger_output: bad addr %p\n",
                   1660:                    sc->sc_dev.dv_xname, start);
                   1661:                return (EINVAL);
                   1662:        }
                   1663:
                   1664:        sc->sc_pintr = intr;
                   1665:        sc->sc_parg = arg;
                   1666:
                   1667:        /* DMA transfer count (in `words'!) reload using 2's complement. */
                   1668:        blksize = -(blksize >> 1);
                   1669:        eso_write_mixreg(sc, ESO_MIXREG_A2TCRLO, blksize & 0xff);
                   1670:        eso_write_mixreg(sc, ESO_MIXREG_A2TCRHI, blksize >> 8);
                   1671:
                   1672:        /* Update DAC to reflect DMA count and audio parameters. */
                   1673:        /* Note: we cache A2C2 in order to avoid r/m/w at interrupt time. */
                   1674:        if (param->precision * param->factor == 16)
                   1675:                sc->sc_a2c2 |= ESO_MIXREG_A2C2_16BIT;
                   1676:        else
                   1677:                sc->sc_a2c2 &= ~ESO_MIXREG_A2C2_16BIT;
                   1678:        if (param->channels == 2)
                   1679:                sc->sc_a2c2 |= ESO_MIXREG_A2C2_STEREO;
                   1680:        else
                   1681:                sc->sc_a2c2 &= ~ESO_MIXREG_A2C2_STEREO;
                   1682:        if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
                   1683:            param->encoding == AUDIO_ENCODING_SLINEAR_LE)
                   1684:                sc->sc_a2c2 |= ESO_MIXREG_A2C2_SIGNED;
                   1685:        else
                   1686:                sc->sc_a2c2 &= ~ESO_MIXREG_A2C2_SIGNED;
                   1687:        /* Unmask IRQ. */
                   1688:        sc->sc_a2c2 |= ESO_MIXREG_A2C2_IRQM;
                   1689:        eso_write_mixreg(sc, ESO_MIXREG_A2C2, sc->sc_a2c2);
                   1690:
                   1691:        /* Set up DMA controller. */
                   1692:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ESO_IO_A2DMAA, DMAADDR(ed));
                   1693:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, ESO_IO_A2DMAC,
                   1694:            (uint8_t *)end - (uint8_t *)start);
                   1695:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, ESO_IO_A2DMAM,
                   1696:            ESO_IO_A2DMAM_DMAENB | ESO_IO_A2DMAM_AUTO);
                   1697:
                   1698:        /* Start DMA. */
                   1699:        a2c1 = eso_read_mixreg(sc, ESO_MIXREG_A2C1);
                   1700:        a2c1 &= ~ESO_MIXREG_A2C1_RESV0; /* Paranoia? XXX bit 5 */
                   1701:        a2c1 |= ESO_MIXREG_A2C1_FIFOENB | ESO_MIXREG_A2C1_DMAENB |
                   1702:            ESO_MIXREG_A2C1_AUTO;
                   1703:        eso_write_mixreg(sc, ESO_MIXREG_A2C1, a2c1);
                   1704:
                   1705:        return (0);
                   1706: }
                   1707:
                   1708: HIDE int
                   1709: eso_trigger_input(hdl, start, end, blksize, intr, arg, param)
                   1710:        void *hdl;
                   1711:        void *start, *end;
                   1712:        int blksize;
                   1713:        void (*intr)(void *);
                   1714:        void *arg;
                   1715:        struct audio_params *param;
                   1716: {
                   1717:        struct eso_softc *sc = hdl;
                   1718:        struct eso_dma *ed;
                   1719:        uint8_t actl, a1c1;
                   1720:
                   1721:        DPRINTF((
                   1722:            "%s: trigger_input: start %p, end %p, blksize %d, intr %p(%p)\n",
                   1723:            sc->sc_dev.dv_xname, start, end, blksize, intr, arg));
                   1724:        DPRINTF(("%s: param: rate %lu, encoding %u, precision %u, channels %u, sw_code %p, factor %d\n",
                   1725:            sc->sc_dev.dv_xname, param->sample_rate, param->encoding,
                   1726:            param->precision, param->channels, param->sw_code, param->factor));
                   1727:
                   1728:        /*
                   1729:         * If we failed to configure the Audio 1 DMA controller, bail here
                   1730:         * while retaining availability of the DAC direction (in Audio 2).
                   1731:         */
                   1732:        if (!sc->sc_dmac_configured)
                   1733:                return (EIO);
                   1734:
                   1735:        /* Find DMA buffer. */
                   1736:        for (ed = sc->sc_dmas; ed != NULL && KVADDR(ed) != start;
                   1737:             ed = ed->ed_next)
                   1738:                ;
                   1739:        if (ed == NULL) {
                   1740:                printf("%s: trigger_output: bad addr %p\n",
                   1741:                    sc->sc_dev.dv_xname, start);
                   1742:                return (EINVAL);
                   1743:        }
                   1744:
                   1745:        sc->sc_rintr = intr;
                   1746:        sc->sc_rarg = arg;
                   1747:
                   1748:        /* Set up ADC DMA converter parameters. */
                   1749:        actl = eso_read_ctlreg(sc, ESO_CTLREG_ACTL);
                   1750:        if (param->channels == 2) {
                   1751:                actl &= ~ESO_CTLREG_ACTL_MONO;
                   1752:                actl |= ESO_CTLREG_ACTL_STEREO;
                   1753:        } else {
                   1754:                actl &= ~ESO_CTLREG_ACTL_STEREO;
                   1755:                actl |= ESO_CTLREG_ACTL_MONO;
                   1756:        }
                   1757:        eso_write_ctlreg(sc, ESO_CTLREG_ACTL, actl);
                   1758:
                   1759:        /* Set up Transfer Type: maybe move to attach time? */
                   1760:        eso_write_ctlreg(sc, ESO_CTLREG_A1TT, ESO_CTLREG_A1TT_DEMAND4);
                   1761:
                   1762:        /* DMA transfer count reload using 2's complement. */
                   1763:        blksize = -blksize;
                   1764:        eso_write_ctlreg(sc, ESO_CTLREG_A1TCRLO, blksize & 0xff);
                   1765:        eso_write_ctlreg(sc, ESO_CTLREG_A1TCRHI, blksize >> 8);
                   1766:
                   1767:        /* Set up and enable Audio 1 DMA FIFO. */
                   1768:        a1c1 = ESO_CTLREG_A1C1_RESV1 | ESO_CTLREG_A1C1_FIFOENB;
                   1769:        if (param->precision * param->factor == 16)
                   1770:                a1c1 |= ESO_CTLREG_A1C1_16BIT;
                   1771:        if (param->channels == 2)
                   1772:                a1c1 |= ESO_CTLREG_A1C1_STEREO;
                   1773:        else
                   1774:                a1c1 |= ESO_CTLREG_A1C1_MONO;
                   1775:        if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
                   1776:            param->encoding == AUDIO_ENCODING_SLINEAR_LE)
                   1777:                a1c1 |= ESO_CTLREG_A1C1_SIGNED;
                   1778:        eso_write_ctlreg(sc, ESO_CTLREG_A1C1, a1c1);
                   1779:
                   1780:        /* Set up ADC IRQ/DRQ parameters. */
                   1781:        eso_write_ctlreg(sc, ESO_CTLREG_LAIC,
                   1782:            ESO_CTLREG_LAIC_PINENB | ESO_CTLREG_LAIC_EXTENB);
                   1783:        eso_write_ctlreg(sc, ESO_CTLREG_DRQCTL,
                   1784:            ESO_CTLREG_DRQCTL_ENB1 | ESO_CTLREG_DRQCTL_EXTENB);
                   1785:
                   1786:        /* Set up and enable DMA controller. */
                   1787:        bus_space_write_1(sc->sc_dmac_iot, sc->sc_dmac_ioh, ESO_DMAC_CLEAR, 0);
                   1788:        bus_space_write_1(sc->sc_dmac_iot, sc->sc_dmac_ioh, ESO_DMAC_MASK,
                   1789:            ESO_DMAC_MASK_MASK);
                   1790:        bus_space_write_1(sc->sc_dmac_iot, sc->sc_dmac_ioh, ESO_DMAC_MODE,
                   1791:            DMA37MD_WRITE | DMA37MD_LOOP | DMA37MD_DEMAND);
                   1792:        bus_space_write_4(sc->sc_dmac_iot, sc->sc_dmac_ioh, ESO_DMAC_DMAA,
                   1793:            DMAADDR(ed));
                   1794:        bus_space_write_2(sc->sc_dmac_iot, sc->sc_dmac_ioh, ESO_DMAC_DMAC,
                   1795:            (uint8_t *)end - (uint8_t *)start - 1);
                   1796:        bus_space_write_1(sc->sc_dmac_iot, sc->sc_dmac_ioh, ESO_DMAC_MASK, 0);
                   1797:
                   1798:        /* Start DMA. */
                   1799:        eso_write_ctlreg(sc, ESO_CTLREG_A1C2,
                   1800:            ESO_CTLREG_A1C2_DMAENB | ESO_CTLREG_A1C2_READ |
                   1801:            ESO_CTLREG_A1C2_AUTO | ESO_CTLREG_A1C2_ADC);
                   1802:
                   1803:        return (0);
                   1804: }
                   1805:
                   1806: HIDE int
                   1807: eso_set_recsrc(sc, recsrc)
                   1808:        struct eso_softc *sc;
                   1809:        unsigned int recsrc;
                   1810: {
                   1811:
                   1812:        eso_write_mixreg(sc, ESO_MIXREG_ERS, recsrc);
                   1813:        sc->sc_recsrc = recsrc;
                   1814:        return (0);
                   1815: }
                   1816:
                   1817: HIDE void
                   1818: eso_set_gain(sc, port)
                   1819:        struct eso_softc *sc;
                   1820:        unsigned int port;
                   1821: {
                   1822:        uint8_t mixreg, tmp;
                   1823:
                   1824:        switch (port) {
                   1825:        case ESO_DAC_PLAY_VOL:
                   1826:                mixreg = ESO_MIXREG_PVR_A2;
                   1827:                break;
                   1828:        case ESO_MIC_PLAY_VOL:
                   1829:                mixreg = ESO_MIXREG_PVR_MIC;
                   1830:                break;
                   1831:        case ESO_LINE_PLAY_VOL:
                   1832:                mixreg = ESO_MIXREG_PVR_LINE;
                   1833:                break;
                   1834:        case ESO_SYNTH_PLAY_VOL:
                   1835:                mixreg = ESO_MIXREG_PVR_SYNTH;
                   1836:                break;
                   1837:        case ESO_CD_PLAY_VOL:
                   1838:                mixreg = ESO_MIXREG_PVR_CD;
                   1839:                break;
                   1840:        case ESO_AUXB_PLAY_VOL:
                   1841:                mixreg = ESO_MIXREG_PVR_AUXB;
                   1842:                break;
                   1843:
                   1844:        case ESO_DAC_REC_VOL:
                   1845:                mixreg = ESO_MIXREG_RVR_A2;
                   1846:                break;
                   1847:        case ESO_MIC_REC_VOL:
                   1848:                mixreg = ESO_MIXREG_RVR_MIC;
                   1849:                break;
                   1850:        case ESO_LINE_REC_VOL:
                   1851:                mixreg = ESO_MIXREG_RVR_LINE;
                   1852:                break;
                   1853:        case ESO_SYNTH_REC_VOL:
                   1854:                mixreg = ESO_MIXREG_RVR_SYNTH;
                   1855:                break;
                   1856:        case ESO_CD_REC_VOL:
                   1857:                mixreg = ESO_MIXREG_RVR_CD;
                   1858:                break;
                   1859:        case ESO_AUXB_REC_VOL:
                   1860:                mixreg = ESO_MIXREG_RVR_AUXB;
                   1861:                break;
                   1862:        case ESO_MONO_PLAY_VOL:
                   1863:                mixreg = ESO_MIXREG_PVR_MONO;
                   1864:                break;
                   1865:        case ESO_MONO_REC_VOL:
                   1866:                mixreg = ESO_MIXREG_RVR_MONO;
                   1867:                break;
                   1868:
                   1869:        case ESO_PCSPEAKER_VOL:
                   1870:                /* Special case - only 3-bit, mono, and reserved bits. */
                   1871:                tmp = eso_read_mixreg(sc, ESO_MIXREG_PCSVR);
                   1872:                tmp &= ESO_MIXREG_PCSVR_RESV;
                   1873:                /* Map bits 7:5 -> 2:0. */
                   1874:                tmp |= (sc->sc_gain[port][ESO_LEFT] >> 5);
                   1875:                eso_write_mixreg(sc, ESO_MIXREG_PCSVR, tmp);
                   1876:                return;
                   1877:
                   1878:        case ESO_MASTER_VOL:
                   1879:                /* Special case - separate regs, and 6-bit precision. */
                   1880:                /* Map bits 7:2 -> 5:0. */
                   1881:                eso_write_mixreg(sc, ESO_MIXREG_LMVM,
                   1882:                    sc->sc_gain[port][ESO_LEFT] >> 2);
                   1883:                eso_write_mixreg(sc, ESO_MIXREG_RMVM,
                   1884:                    sc->sc_gain[port][ESO_RIGHT] >> 2);
                   1885:                return;
                   1886:
                   1887:        case ESO_SPATIALIZER:
                   1888:                /* Special case - only `mono', and higher precision. */
                   1889:                eso_write_mixreg(sc, ESO_MIXREG_SPATLVL,
                   1890:                    sc->sc_gain[port][ESO_LEFT]);
                   1891:                return;
                   1892:
                   1893:        case ESO_RECORD_VOL:
                   1894:                /* Very Special case, controller register. */
                   1895:                eso_write_ctlreg(sc, ESO_CTLREG_RECLVL,ESO_4BIT_GAIN_TO_STEREO(
                   1896:                   sc->sc_gain[port][ESO_LEFT], sc->sc_gain[port][ESO_RIGHT]));
                   1897:                return;
                   1898:
                   1899:        default:
                   1900: #ifdef DIAGNOSTIC
                   1901:                panic("eso_set_gain: bad port %u", port);
                   1902:                /* NOTREACHED */
                   1903: #else
                   1904:                return;
                   1905: #endif
                   1906:                }
                   1907:
                   1908:        eso_write_mixreg(sc, mixreg, ESO_4BIT_GAIN_TO_STEREO(
                   1909:            sc->sc_gain[port][ESO_LEFT], sc->sc_gain[port][ESO_RIGHT]));
                   1910: }
                   1911:
                   1912:
                   1913: HIDE void
                   1914: eso_powerhook(why, self)
                   1915:        int why;
                   1916:        void *self;
                   1917: {
                   1918:        struct eso_softc *sc = (struct eso_softc *)self;
                   1919:
                   1920:        if (why != PWR_RESUME) {
                   1921:                eso_halt_output(sc);
                   1922:                eso_halt_input(sc);
                   1923:
                   1924:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, ESO_IO_A2DMAM, 0);
                   1925:                bus_space_write_1(sc->sc_dmac_iot,
                   1926:                                  sc->sc_dmac_ioh, ESO_DMAC_CLEAR, 0);
                   1927:                bus_space_write_1(sc->sc_sb_iot,
                   1928:                                  sc->sc_sb_ioh, ESO_SB_STATUSFLAGS, 3);
                   1929:
                   1930:                /* shut down dma */
                   1931:                pci_conf_write(sc->sc_pa.pa_pc,
                   1932:                               sc->sc_pa.pa_tag, ESO_PCI_DDMAC, 0);
                   1933:        } else
                   1934:                eso_setup(sc, 0);
                   1935: }

CVSweb