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

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

1.1       nbrk        1: /*     $OpenBSD: cs4281.c,v 1.19 2005/11/29 05:42:17 tedu Exp $ */
                      2: /*     $Tera: cs4281.c,v 1.18 2000/12/27 14:24:45 tacha Exp $  */
                      3:
                      4: /*
                      5:  * Copyright (c) 2000 Tatoku Ogaito.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *      This product includes software developed by Tatoku Ogaito
                     18:  *     for the NetBSD Project.
                     19:  * 4. The name of the author may not be used to endorse or promote products
                     20:  *    derived from this software without specific prior written permission
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32:  */
                     33:
                     34: /*
                     35:  * Cirrus Logic CS4281 driver.
                     36:  * Data sheets can be found
                     37:  * http://www.cirrus.com/pubs/4281.pdf?DocumentID=30
                     38:  * ftp://ftp.alsa-project.org/pub/manuals/cirrus/cs4281tm.pdf
                     39:  *
                     40:  * TODO:
                     41:  *   1: midi and FM support
                     42:  */
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/kernel.h>
                     47: #include <sys/malloc.h>
                     48: #include <sys/fcntl.h>
                     49: #include <sys/device.h>
                     50:
                     51: #include <dev/pci/pcidevs.h>
                     52: #include <dev/pci/pcivar.h>
                     53: #include <dev/pci/cs4281reg.h>
                     54:
                     55: #include <sys/audioio.h>
                     56: #include <dev/audio_if.h>
                     57: #include <dev/midi_if.h>
                     58: #include <dev/mulaw.h>
                     59: #include <dev/auconv.h>
                     60:
                     61: #include <dev/ic/ac97.h>
                     62:
                     63: #include <machine/bus.h>
                     64:
                     65: #define CSCC_PCI_BA0 0x10
                     66: #define CSCC_PCI_BA1 0x14
                     67:
                     68: struct cs4281_dma {
                     69:        bus_dmamap_t map;
                     70:        caddr_t addr;           /* real dma buffer */
                     71:        caddr_t dum;            /* dummy buffer for audio driver */
                     72:        bus_dma_segment_t segs[1];
                     73:        int nsegs;
                     74:        size_t size;
                     75:        struct cs4281_dma *next;
                     76: };
                     77: #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
                     78: #define BUFADDR(p)  ((void *)((p)->dum))
                     79: #define KERNADDR(p) ((void *)((p)->addr))
                     80:
                     81: /*
                     82:  * Software state
                     83:  */
                     84: struct cs4281_softc {
                     85:        struct device           sc_dev;
                     86:
                     87:        pci_intr_handle_t       *sc_ih;
                     88:
                     89:         /* I/O (BA0) */
                     90:        bus_space_tag_t         ba0t;
                     91:        bus_space_handle_t      ba0h;
                     92:
                     93:        /* BA1 */
                     94:        bus_space_tag_t         ba1t;
                     95:        bus_space_handle_t      ba1h;
                     96:
                     97:        /* DMA */
                     98:        bus_dma_tag_t           sc_dmatag;
                     99:        struct cs4281_dma       *sc_dmas;
                    100:        size_t dma_size;
                    101:        size_t dma_align;
                    102:
                    103:        int     hw_blocksize;
                    104:
                    105:         /* playback */
                    106:        void    (*sc_pintr)(void *);    /* dma completion intr handler */
                    107:        void    *sc_parg;               /* arg for sc_intr() */
                    108:        char    *sc_ps, *sc_pe, *sc_pn;
                    109:        int     sc_pcount;
                    110:        int     sc_pi;
                    111:        struct cs4281_dma *sc_pdma;
                    112:        char    *sc_pbuf;
                    113:        int     (*halt_output)(void *);
                    114: #ifdef DIAGNOSTIC
                    115:         char   sc_prun;
                    116: #endif
                    117:
                    118:        /* capturing */
                    119:        void    (*sc_rintr)(void *);    /* dma completion intr handler */
                    120:        void    *sc_rarg;               /* arg for sc_intr() */
                    121:        char    *sc_rs, *sc_re, *sc_rn;
                    122:        int     sc_rcount;
                    123:        int     sc_ri;
                    124:        struct  cs4281_dma *sc_rdma;
                    125:        char    *sc_rbuf;
                    126:        int     sc_rparam;              /* record format */
                    127:        int     (*halt_input)(void *);
                    128: #ifdef DIAGNOSTIC
                    129:         char   sc_rrun;
                    130: #endif
                    131:
                    132: #if NMIDI > 0
                    133:         void   (*sc_iintr)(void *, int);       /* midi input ready handler */
                    134:         void   (*sc_ointr)(void *);            /* midi output ready handler */
                    135:         void   *sc_arg;
                    136: #endif
                    137:
                    138:        /* AC97 CODEC */
                    139:        struct ac97_codec_if *codec_if;
                    140:        struct ac97_host_if host_if;
                    141:
                    142:         /* Power Management */
                    143:         char   sc_suspend;
                    144:         void   *sc_powerhook;          /* Power hook */
                    145:        u_int16_t ac97_reg[CS4281_SAVE_REG_MAX + 1];   /* Save ac97 registers */
                    146: };
                    147:
                    148: #define BA0READ4(sc, r) bus_space_read_4((sc)->ba0t, (sc)->ba0h, (r))
                    149: #define BA0WRITE4(sc, r, x) bus_space_write_4((sc)->ba0t, (sc)->ba0h, (r), (x))
                    150:
                    151: #if defined(ENABLE_SECONDARY_CODEC)
                    152: #define MAX_CHANNELS  (4)
                    153: #define MAX_FIFO_SIZE 32 /* 128/4 channels */
                    154: #else
                    155: #define MAX_CHANNELS  (2)
                    156: #define MAX_FIFO_SIZE 64 /* 128/2 channels */
                    157: #endif
                    158:
                    159: int cs4281_match(struct device *, void *, void *);
                    160: void cs4281_attach(struct device *, struct device *, void *);
                    161: int cs4281_intr(void *);
                    162: int cs4281_query_encoding(void *, struct audio_encoding *);
                    163: int cs4281_set_params(void *, int, int, struct audio_params *,
                    164:                                     struct audio_params *);
                    165: int cs4281_halt_output(void *);
                    166: int cs4281_halt_input(void *);
                    167: int cs4281_getdev(void *, struct audio_device *);
                    168: int cs4281_trigger_output(void *, void *, void *, int, void (*)(void *),
                    169:                          void *, struct audio_params *);
                    170: int cs4281_trigger_input(void *, void *, void *, int, void (*)(void *),
                    171:                         void *, struct audio_params *);
                    172: u_int8_t cs4281_sr2regval(int);
                    173: void cs4281_set_dac_rate(struct cs4281_softc *, int);
                    174: void cs4281_set_adc_rate(struct cs4281_softc *, int);
                    175: int cs4281_init(struct cs4281_softc *);
                    176:
                    177: int cs4281_open(void *, int);
                    178: void cs4281_close(void *);
                    179: int cs4281_round_blocksize(void *, int);
                    180: int cs4281_get_props(void *);
                    181: int cs4281_attach_codec(void *, struct ac97_codec_if *);
                    182: int cs4281_read_codec(void *, u_int8_t , u_int16_t *);
                    183: int cs4281_write_codec(void *, u_int8_t, u_int16_t);
                    184: void cs4281_reset_codec(void *);
                    185:
                    186: void cs4281_power(int, void *);
                    187:
                    188: int cs4281_mixer_set_port(void *, mixer_ctrl_t *);
                    189: int cs4281_mixer_get_port(void *, mixer_ctrl_t *);
                    190: int cs4281_query_devinfo(void *, mixer_devinfo_t *);
                    191: void *cs4281_malloc(void *, int, size_t, int, int);
                    192: size_t cs4281_round_buffersize(void *, int, size_t);
                    193: void cs4281_free(void *, void *, int);
                    194: paddr_t cs4281_mappage(void *, void *, off_t, int);
                    195:
                    196: int cs4281_allocmem(struct cs4281_softc *, size_t, int, int,
                    197:                                     struct cs4281_dma *);
                    198: int cs4281_src_wait(struct cs4281_softc *);
                    199:
                    200: #if defined(CS4281_DEBUG)
                    201: #undef DPRINTF
                    202: #undef DPRINTFN
                    203: #define DPRINTF(x)         if (cs4281_debug) printf x
                    204: #define DPRINTFN(n,x)      if (cs4281_debug>(n)) printf x
                    205: int cs4281_debug = 5;
                    206: #else
                    207: #define DPRINTF(x)
                    208: #define DPRINTFN(n,x)
                    209: #endif
                    210:
                    211: struct audio_hw_if cs4281_hw_if = {
                    212:        cs4281_open,
                    213:        cs4281_close,
                    214:        NULL,
                    215:        cs4281_query_encoding,
                    216:        cs4281_set_params,
                    217:        cs4281_round_blocksize,
                    218:        NULL,
                    219:        NULL,
                    220:        NULL,
                    221:        NULL,
                    222:        NULL,
                    223:        cs4281_halt_output,
                    224:        cs4281_halt_input,
                    225:        NULL,
                    226:        cs4281_getdev,
                    227:        NULL,
                    228:        cs4281_mixer_set_port,
                    229:        cs4281_mixer_get_port,
                    230:        cs4281_query_devinfo,
                    231:        cs4281_malloc,
                    232:        cs4281_free,
                    233:        cs4281_round_buffersize,
                    234:        NULL, /* cs4281_mappage, */
                    235:        cs4281_get_props,
                    236:        cs4281_trigger_output,
                    237:        cs4281_trigger_input,
                    238: };
                    239:
                    240: #if NMIDI > 0
                    241: /* Midi Interface */
                    242: void cs4281_midi_close(void *);
                    243: void cs4281_midi_getinfo(void *, struct midi_info *);
                    244: int cs4281_midi_open(void *, int, void (*)(void *, int),
                    245:                     void (*)(void *), void *);
                    246: int cs4281_midi_output(void *, int);
                    247:
                    248: struct midi_hw_if cs4281_midi_hw_if = {
                    249:        cs4281_midi_open,
                    250:        cs4281_midi_close,
                    251:        cs4281_midi_output,
                    252:        cs4281_midi_getinfo,
                    253:        0,
                    254: };
                    255: #endif
                    256:
                    257: struct cfattach clct_ca = {
                    258:        sizeof(struct cs4281_softc), cs4281_match, cs4281_attach
                    259: };
                    260:
                    261: struct cfdriver clct_cd = {
                    262:        NULL, "clct", DV_DULL
                    263: };
                    264:
                    265: struct audio_device cs4281_device = {
                    266:        "CS4281",
                    267:        "",
                    268:        "cs4281"
                    269: };
                    270:
                    271:
                    272: int
                    273: cs4281_match(parent, match, aux)
                    274:        struct device *parent;
                    275:        void *match;
                    276:        void *aux;
                    277: {
                    278:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                    279:
                    280:        if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS ||
                    281:            PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_CIRRUS_CS4281)
                    282:                return (0);
                    283:
                    284:        return (1);
                    285: }
                    286:
                    287: void
                    288: cs4281_attach(parent, self, aux)
                    289:        struct device *parent;
                    290:        struct device *self;
                    291:        void *aux;
                    292: {
                    293:        struct cs4281_softc *sc = (struct cs4281_softc *)self;
                    294:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                    295:        pci_chipset_tag_t pc = pa->pa_pc;
                    296:        char const *intrstr;
                    297:        pci_intr_handle_t ih;
                    298:        int pci_pwrmgmt_cap_reg, pci_pwrmgmt_csr_reg;
                    299:
                    300:        /* Map I/O register */
                    301:        if (pci_mapreg_map(pa, CSCC_PCI_BA0,
                    302:            PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t,
                    303:            &sc->ba0h, NULL, NULL, 0)) {
                    304:                printf("%s: can't map BA0 space\n", sc->sc_dev.dv_xname);
                    305:                return;
                    306:        }
                    307:        if (pci_mapreg_map(pa, CSCC_PCI_BA1,
                    308:            PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t,
                    309:            &sc->ba1h, NULL, NULL, 0)) {
                    310:                printf("%s: can't map BA1 space\n", sc->sc_dev.dv_xname);
                    311:                return;
                    312:        }
                    313:
                    314:        sc->sc_dmatag = pa->pa_dmat;
                    315:
                    316:        /*
                    317:         * Set Power State D0.
                    318:         * Without doing this, 0xffffffff is read from all registers after
                    319:         * using Windows and rebooting into OpenBSD.
                    320:         * On my IBM ThinkPad X20, it is set to D3 after using Windows2000.
                    321:         */
                    322:        if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
                    323:            &pci_pwrmgmt_cap_reg, 0)) {
                    324:                pcireg_t reg;
                    325:
                    326:                pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + PCI_PMCSR;
                    327:                reg = pci_conf_read(pa->pa_pc, pa->pa_tag, pci_pwrmgmt_csr_reg);
                    328:                if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
                    329:                        pci_conf_write(pc, pa->pa_tag, pci_pwrmgmt_csr_reg,
                    330:                            (reg & ~PCI_PMCSR_STATE_MASK) |
                    331:                            PCI_PMCSR_STATE_D0);
                    332:                }
                    333:        }
                    334:
                    335:        /* Map and establish the interrupt. */
                    336:        if (pci_intr_map(pa, &ih)) {
                    337:                printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
                    338:                return;
                    339:        }
                    340:        intrstr = pci_intr_string(pc, ih);
                    341:
                    342:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, cs4281_intr, sc,
                    343:            sc->sc_dev.dv_xname);
                    344:        if (sc->sc_ih == NULL) {
                    345:                printf("%s: couldn't establish interrupt",sc->sc_dev.dv_xname);
                    346:                if (intrstr != NULL)
                    347:                        printf(" at %s", intrstr);
                    348:                printf("\n");
                    349:                return;
                    350:        }
                    351:        printf(" %s\n", intrstr);
                    352:
                    353:        /*
                    354:         * Sound System start-up
                    355:         */
                    356:        if (cs4281_init(sc) != 0)
                    357:                return;
                    358:
                    359:        sc->halt_input  = cs4281_halt_input;
                    360:        sc->halt_output = cs4281_halt_output;
                    361:
                    362:        sc->dma_size     = CS4281_BUFFER_SIZE / MAX_CHANNELS;
                    363:        sc->dma_align    = 0x10;
                    364:        sc->hw_blocksize = sc->dma_size / 2;
                    365:
                    366:        /* AC 97 attachment */
                    367:        sc->host_if.arg = sc;
                    368:        sc->host_if.attach = cs4281_attach_codec;
                    369:        sc->host_if.read   = cs4281_read_codec;
                    370:        sc->host_if.write  = cs4281_write_codec;
                    371:        sc->host_if.reset  = cs4281_reset_codec;
                    372:        if (ac97_attach(&sc->host_if) != 0) {
                    373:                printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
                    374:                return;
                    375:        }
                    376:        audio_attach_mi(&cs4281_hw_if, sc, &sc->sc_dev);
                    377:
                    378: #if NMIDI > 0
                    379:        midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev);
                    380: #endif
                    381:
                    382:        sc->sc_suspend = PWR_RESUME;
                    383:        sc->sc_powerhook = powerhook_establish(cs4281_power, sc);
                    384: }
                    385:
                    386:
                    387: int
                    388: cs4281_intr(p)
                    389:        void *p;
                    390: {
                    391:        struct cs4281_softc *sc = p;
                    392:        u_int32_t intr, val;
                    393:        char *empty_dma;
                    394:
                    395:        intr = BA0READ4(sc, CS4281_HISR);
                    396:        if (!(intr & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) {
                    397:                BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
                    398:                return (0);
                    399:        }
                    400:        DPRINTF(("cs4281_intr:"));
                    401:
                    402:        if (intr & HISR_DMA0)
                    403:                val = BA0READ4(sc, CS4281_HDSR0); /* clear intr condition */
                    404:        if (intr & HISR_DMA1)
                    405:                val = BA0READ4(sc, CS4281_HDSR1); /* clear intr condition */
                    406:        BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
                    407:
                    408:        /* Playback Interrupt */
                    409:        if (intr & HISR_DMA0) {
                    410:                DPRINTF((" PB DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA0),
                    411:                         (int)BA0READ4(sc, CS4281_DCC0)));
                    412:                if (sc->sc_pintr) {
                    413:                        if ((sc->sc_pi%sc->sc_pcount) == 0)
                    414:                                sc->sc_pintr(sc->sc_parg);
                    415:                } else {
                    416:                        printf("unexpected play intr\n");
                    417:                }
                    418:                /* copy buffer */
                    419:                ++sc->sc_pi;
                    420:                empty_dma = sc->sc_pdma->addr;
                    421:                if (sc->sc_pi&1)
                    422:                        empty_dma += sc->hw_blocksize;
                    423:                memcpy(empty_dma, sc->sc_pn, sc->hw_blocksize);
                    424:                sc->sc_pn += sc->hw_blocksize;
                    425:                if (sc->sc_pn >= sc->sc_pe)
                    426:                        sc->sc_pn = sc->sc_ps;
                    427:        }
                    428:        if (intr & HISR_DMA1) {
                    429:                val = BA0READ4(sc, CS4281_HDSR1);
                    430:                /* copy from dma */
                    431:                DPRINTF((" CP DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA1),
                    432:                         (int)BA0READ4(sc, CS4281_DCC1)));
                    433:                ++sc->sc_ri;
                    434:                empty_dma = sc->sc_rdma->addr;
                    435:                if ((sc->sc_ri & 1) == 0)
                    436:                        empty_dma += sc->hw_blocksize;
                    437:                memcpy(sc->sc_rn, empty_dma, sc->hw_blocksize);
                    438:                if (sc->sc_rn >= sc->sc_re)
                    439:                        sc->sc_rn = sc->sc_rs;
                    440:                if (sc->sc_rintr) {
                    441:                        if ((sc->sc_ri % sc->sc_rcount) == 0)
                    442:                                sc->sc_rintr(sc->sc_rarg);
                    443:                } else {
                    444:                        printf("unexpected record intr\n");
                    445:                }
                    446:        }
                    447:        DPRINTF(("\n"));
                    448:        return (1);
                    449: }
                    450:
                    451: int
                    452: cs4281_query_encoding(addr, fp)
                    453:        void *addr;
                    454:        struct audio_encoding *fp;
                    455: {
                    456:        switch (fp->index) {
                    457:        case 0:
                    458:                strlcpy(fp->name, AudioEulinear, sizeof fp->name);
                    459:                fp->encoding = AUDIO_ENCODING_ULINEAR;
                    460:                fp->precision = 8;
                    461:                fp->flags = 0;
                    462:                break;
                    463:        case 1:
                    464:                strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
                    465:                fp->encoding = AUDIO_ENCODING_ULAW;
                    466:                fp->precision = 8;
                    467:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    468:                break;
                    469:        case 2:
                    470:                strlcpy(fp->name, AudioEalaw, sizeof fp->name);
                    471:                fp->encoding = AUDIO_ENCODING_ALAW;
                    472:                fp->precision = 8;
                    473:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    474:                break;
                    475:        case 3:
                    476:                strlcpy(fp->name, AudioEslinear, sizeof fp->name);
                    477:                fp->encoding = AUDIO_ENCODING_SLINEAR;
                    478:                fp->precision = 8;
                    479:                fp->flags = 0;
                    480:                break;
                    481:        case 4:
                    482:                strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
                    483:                fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
                    484:                fp->precision = 16;
                    485:                fp->flags = 0;
                    486:                break;
                    487:        case 5:
                    488:                strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
                    489:                fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
                    490:                fp->precision = 16;
                    491:                fp->flags = 0;
                    492:                break;
                    493:        case 6:
                    494:                strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
                    495:                fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
                    496:                fp->precision = 16;
                    497:                fp->flags = 0;
                    498:                break;
                    499:        case 7:
                    500:                strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
                    501:                fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
                    502:                fp->precision = 16;
                    503:                fp->flags = 0;
                    504:                break;
                    505:        default:
                    506:                return EINVAL;
                    507:        }
                    508:        return (0);
                    509: }
                    510:
                    511: int
                    512: cs4281_set_params(addr, setmode, usemode, play, rec)
                    513:        void *addr;
                    514:        int setmode, usemode;
                    515:        struct audio_params *play, *rec;
                    516: {
                    517:        struct cs4281_softc *sc = addr;
                    518:        struct audio_params *p;
                    519:        int mode;
                    520:
                    521:        for (mode = AUMODE_RECORD; mode != -1;
                    522:            mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
                    523:                if ((setmode & mode) == 0)
                    524:                        continue;
                    525:
                    526:                p = mode == AUMODE_PLAY ? play : rec;
                    527:
                    528:                if (p == play) {
                    529:                        DPRINTFN(5,("play: samp=%ld precision=%d channels=%d\n",
                    530:                                p->sample_rate, p->precision, p->channels));
                    531:                        if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
                    532:                            (p->precision != 8 && p->precision != 16) ||
                    533:                            (p->channels != 1  && p->channels != 2)) {
                    534:                                return (EINVAL);
                    535:                        }
                    536:                } else {
                    537:                        DPRINTFN(5,("rec: samp=%ld precision=%d channels=%d\n",
                    538:                                p->sample_rate, p->precision, p->channels));
                    539:                        if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
                    540:                            (p->precision != 8 && p->precision != 16) ||
                    541:                            (p->channels != 1 && p->channels != 2)) {
                    542:                                return (EINVAL);
                    543:                        }
                    544:                }
                    545:                p->factor = 1;
                    546:                p->sw_code = 0;
                    547:
                    548:                switch (p->encoding) {
                    549:                case AUDIO_ENCODING_SLINEAR_BE:
                    550:                        break;
                    551:                case AUDIO_ENCODING_SLINEAR_LE:
                    552:                        break;
                    553:                case AUDIO_ENCODING_ULINEAR_BE:
                    554:                        break;
                    555:                case AUDIO_ENCODING_ULINEAR_LE:
                    556:                        break;
                    557:                case AUDIO_ENCODING_ULAW:
                    558:                        if (mode == AUMODE_PLAY) {
                    559:                                p->sw_code = mulaw_to_slinear8;
                    560:                        } else {
                    561:                                p->sw_code = slinear8_to_mulaw;
                    562:                        }
                    563:                        break;
                    564:                case AUDIO_ENCODING_ALAW:
                    565:                        if (mode == AUMODE_PLAY) {
                    566:                                p->sw_code = alaw_to_slinear8;
                    567:                        } else {
                    568:                                p->sw_code = slinear8_to_alaw;
                    569:                        }
                    570:                        break;
                    571:                default:
                    572:                        return (EINVAL);
                    573:                }
                    574:        }
                    575:
                    576:        /* set sample rate */
                    577:        cs4281_set_dac_rate(sc, play->sample_rate);
                    578:        cs4281_set_adc_rate(sc, rec->sample_rate);
                    579:        return (0);
                    580: }
                    581:
                    582: int
                    583: cs4281_halt_output(addr)
                    584:        void *addr;
                    585: {
                    586:        struct cs4281_softc *sc = addr;
                    587:
                    588:        BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
                    589: #ifdef DIAGNOSTIC
                    590:        sc->sc_prun = 0;
                    591: #endif
                    592:        return (0);
                    593: }
                    594:
                    595: int
                    596: cs4281_halt_input(addr)
                    597:        void *addr;
                    598: {
                    599:        struct cs4281_softc *sc = addr;
                    600:
                    601:        BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
                    602: #ifdef DIAGNOSTIC
                    603:        sc->sc_rrun = 0;
                    604: #endif
                    605:        return (0);
                    606: }
                    607:
                    608: /* trivial */
                    609: int
                    610: cs4281_getdev(addr, retp)
                    611:      void *addr;
                    612:      struct audio_device *retp;
                    613: {
                    614:        *retp = cs4281_device;
                    615:        return (0);
                    616: }
                    617:
                    618:
                    619: int
                    620: cs4281_trigger_output(addr, start, end, blksize, intr, arg, param)
                    621:        void *addr;
                    622:        void *start, *end;
                    623:        int blksize;
                    624:        void (*intr)(void *);
                    625:        void *arg;
                    626:        struct audio_params *param;
                    627: {
                    628:        struct cs4281_softc *sc = addr;
                    629:        u_int32_t fmt=0;
                    630:        struct cs4281_dma *p;
                    631:        int dma_count;
                    632:
                    633: #ifdef DIAGNOSTIC
                    634:        if (sc->sc_prun)
                    635:                printf("cs4281_trigger_output: already running\n");
                    636:        sc->sc_prun = 1;
                    637: #endif
                    638:
                    639:        DPRINTF(("cs4281_trigger_output: sc=%p start=%p end=%p "
                    640:                 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
                    641:        sc->sc_pintr = intr;
                    642:        sc->sc_parg  = arg;
                    643:
                    644:        /* stop playback DMA */
                    645:        BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
                    646:
                    647:        DPRINTF(("param: precision=%d  factor=%d channels=%d encoding=%d\n",
                    648:               param->precision, param->factor, param->channels,
                    649:               param->encoding));
                    650:        for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next)
                    651:                ;
                    652:        if (p == NULL) {
                    653:                printf("cs4281_trigger_output: bad addr %p\n", start);
                    654:                return (EINVAL);
                    655:        }
                    656:
                    657:        sc->sc_pcount = blksize / sc->hw_blocksize;
                    658:        sc->sc_ps = (char *)start;
                    659:        sc->sc_pe = (char *)end;
                    660:        sc->sc_pdma = p;
                    661:        sc->sc_pbuf = KERNADDR(p);
                    662:        sc->sc_pi = 0;
                    663:        sc->sc_pn = sc->sc_ps;
                    664:        if (blksize >= sc->dma_size) {
                    665:                sc->sc_pn = sc->sc_ps + sc->dma_size;
                    666:                memcpy(sc->sc_pbuf, start, sc->dma_size);
                    667:                ++sc->sc_pi;
                    668:        } else {
                    669:                sc->sc_pn = sc->sc_ps + sc->hw_blocksize;
                    670:                memcpy(sc->sc_pbuf, start, sc->hw_blocksize);
                    671:        }
                    672:
                    673:        dma_count = sc->dma_size;
                    674:        if (param->precision * param->factor != 8)
                    675:                dma_count /= 2;   /* 16 bit */
                    676:        if (param->channels > 1)
                    677:                dma_count /= 2;   /* Stereo */
                    678:
                    679:        DPRINTF(("cs4281_trigger_output: DMAADDR(p)=0x%x count=%d\n",
                    680:                 (int)DMAADDR(p), dma_count));
                    681:        BA0WRITE4(sc, CS4281_DBA0, DMAADDR(p));
                    682:        BA0WRITE4(sc, CS4281_DBC0, dma_count-1);
                    683:
                    684:        /* set playback format */
                    685:        fmt = BA0READ4(sc, CS4281_DMR0) & ~DMRn_FMTMSK;
                    686:        if (param->precision * param->factor == 8)
                    687:                fmt |= DMRn_SIZE8;
                    688:        if (param->channels == 1)
                    689:                fmt |= DMRn_MONO;
                    690:        if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
                    691:            param->encoding == AUDIO_ENCODING_SLINEAR_BE)
                    692:                fmt |= DMRn_BEND;
                    693:        if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
                    694:            param->encoding == AUDIO_ENCODING_ULINEAR_LE)
                    695:                fmt |= DMRn_USIGN;
                    696:        BA0WRITE4(sc, CS4281_DMR0, fmt);
                    697:
                    698:        /* set sample rate */
                    699:        cs4281_set_dac_rate(sc, param->sample_rate);
                    700:
                    701:        /* start DMA */
                    702:        BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) & ~DCRn_MSK);
                    703:        /* Enable interrupts */
                    704:        BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
                    705:
                    706:        BA0WRITE4(sc, CS4281_PPRVC, 7);
                    707:        BA0WRITE4(sc, CS4281_PPLVC, 7);
                    708:
                    709:        DPRINTF(("HICR =0x%08x(expected 0x00000001)\n", BA0READ4(sc, CS4281_HICR)));
                    710:        DPRINTF(("HIMR =0x%08x(expected 0x00f0fc3f)\n", BA0READ4(sc, CS4281_HIMR)));
                    711:        DPRINTF(("DMR0 =0x%08x(expected 0x2???0018)\n", BA0READ4(sc, CS4281_DMR0)));
                    712:        DPRINTF(("DCR0 =0x%08x(expected 0x00030000)\n", BA0READ4(sc, CS4281_DCR0)));
                    713:        DPRINTF(("FCR0 =0x%08x(expected 0x81000f00)\n", BA0READ4(sc, CS4281_FCR0)));
                    714:        DPRINTF(("DACSR=0x%08x(expected 1 for 44kHz 5 for 8kHz)\n",
                    715:                 BA0READ4(sc, CS4281_DACSR)));
                    716:        DPRINTF(("SRCSA=0x%08x(expected 0x0b0a0100)\n", BA0READ4(sc, CS4281_SRCSA)));
                    717:        DPRINTF(("SSPM&SSPM_PSRCEN =0x%08x(expected 0x00000010)\n",
                    718:                 BA0READ4(sc, CS4281_SSPM) & SSPM_PSRCEN));
                    719:
                    720:        return (0);
                    721: }
                    722:
                    723: int
                    724: cs4281_trigger_input(addr, start, end, blksize, intr, arg, param)
                    725:        void *addr;
                    726:        void *start, *end;
                    727:        int blksize;
                    728:        void (*intr)(void *);
                    729:        void *arg;
                    730:        struct audio_params *param;
                    731: {
                    732:        struct cs4281_softc *sc = addr;
                    733:        struct cs4281_dma *p;
                    734:        u_int32_t fmt=0;
                    735:        int dma_count;
                    736:
                    737:        printf("cs4281_trigger_input: not implemented yet\n");
                    738: #ifdef DIAGNOSTIC
                    739:        if (sc->sc_rrun)
                    740:                printf("cs4281_trigger_input: already running\n");
                    741:        sc->sc_rrun = 1;
                    742: #endif
                    743:        DPRINTF(("cs4281_trigger_input: sc=%p start=%p end=%p "
                    744:            "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
                    745:        sc->sc_rintr = intr;
                    746:        sc->sc_rarg  = arg;
                    747:
                    748:        /* stop recording DMA */
                    749:        BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
                    750:
                    751:        for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next)
                    752:                ;
                    753:        if (!p) {
                    754:                printf("cs4281_trigger_input: bad addr %p\n", start);
                    755:                return (EINVAL);
                    756:        }
                    757:
                    758:        sc->sc_rcount = blksize / sc->hw_blocksize;
                    759:        sc->sc_rs = (char *)start;
                    760:        sc->sc_re = (char *)end;
                    761:        sc->sc_rdma = p;
                    762:        sc->sc_rbuf = KERNADDR(p);
                    763:        sc->sc_ri = 0;
                    764:        sc->sc_rn = sc->sc_rs;
                    765:
                    766:        dma_count = sc->dma_size;
                    767:        if (param->precision * param->factor == 8)
                    768:                dma_count /= 2;
                    769:        if (param->channels > 1)
                    770:                dma_count /= 2;
                    771:
                    772:        DPRINTF(("cs4281_trigger_input: DMAADDR(p)=0x%x count=%d\n",
                    773:                 (int)DMAADDR(p), dma_count));
                    774:        BA0WRITE4(sc, CS4281_DBA1, DMAADDR(p));
                    775:        BA0WRITE4(sc, CS4281_DBC1, dma_count-1);
                    776:
                    777:        /* set recording format */
                    778:        fmt = BA0READ4(sc, CS4281_DMR1) & ~DMRn_FMTMSK;
                    779:        if (param->precision * param->factor == 8)
                    780:                fmt |= DMRn_SIZE8;
                    781:        if (param->channels == 1)
                    782:                fmt |= DMRn_MONO;
                    783:        if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
                    784:            param->encoding == AUDIO_ENCODING_SLINEAR_BE)
                    785:                fmt |= DMRn_BEND;
                    786:        if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
                    787:            param->encoding == AUDIO_ENCODING_ULINEAR_LE)
                    788:                fmt |= DMRn_USIGN;
                    789:        BA0WRITE4(sc, CS4281_DMR1, fmt);
                    790:
                    791:        /* set sample rate */
                    792:        cs4281_set_adc_rate(sc, param->sample_rate);
                    793:
                    794:        /* Start DMA */
                    795:        BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) & ~DCRn_MSK);
                    796:        /* Enable interrupts */
                    797:        BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
                    798:
                    799:        DPRINTF(("HICR=0x%08x\n", BA0READ4(sc, CS4281_HICR)));
                    800:        DPRINTF(("HIMR=0x%08x\n", BA0READ4(sc, CS4281_HIMR)));
                    801:        DPRINTF(("DMR1=0x%08x\n", BA0READ4(sc, CS4281_DMR1)));
                    802:        DPRINTF(("DCR1=0x%08x\n", BA0READ4(sc, CS4281_DCR1)));
                    803:
                    804:        return (0);
                    805: }
                    806:
                    807: /* convert sample rate to register value */
                    808: u_int8_t
                    809: cs4281_sr2regval(rate)
                    810:      int rate;
                    811: {
                    812:        u_int8_t retval;
                    813:
                    814:        /* We don't have to change here. but anyway ... */
                    815:        if (rate > 48000)
                    816:                rate = 48000;
                    817:        if (rate < 6023)
                    818:                rate = 6023;
                    819:
                    820:        switch (rate) {
                    821:        case 8000:
                    822:                retval = 5;
                    823:                break;
                    824:        case 11025:
                    825:                retval = 4;
                    826:                break;
                    827:        case 16000:
                    828:                retval = 3;
                    829:                break;
                    830:        case 22050:
                    831:                retval = 2;
                    832:                break;
                    833:        case 44100:
                    834:                retval = 1;
                    835:                break;
                    836:        case 48000:
                    837:                retval = 0;
                    838:                break;
                    839:        default:
                    840:                retval = 1536000/rate; /* == 24576000/(rate*16) */
                    841:        }
                    842:        return (retval);
                    843: }
                    844:
                    845:
                    846: void
                    847: cs4281_set_dac_rate(sc, rate)
                    848:        struct cs4281_softc *sc;
                    849:        int rate;
                    850: {
                    851:        BA0WRITE4(sc, CS4281_DACSR, cs4281_sr2regval(rate));
                    852: }
                    853:
                    854: void
                    855: cs4281_set_adc_rate(sc, rate)
                    856:        struct cs4281_softc *sc;
                    857:        int rate;
                    858: {
                    859:        BA0WRITE4(sc, CS4281_ADCSR, cs4281_sr2regval(rate));
                    860: }
                    861:
                    862: int
                    863: cs4281_init(sc)
                    864:      struct cs4281_softc *sc;
                    865: {
                    866:        int n;
                    867:        u_int16_t data;
                    868:        u_int32_t dat32;
                    869:
                    870:        /* set "Configuration Write Protect" register to
                    871:         * 0x4281 to allow to write */
                    872:        BA0WRITE4(sc, CS4281_CWPR, 0x4281);
                    873:
                    874:        /*
                    875:         * Unset "Full Power-Down bit of Extended PCI Power Management
                    876:         * Control" register to release the reset state.
                    877:         */
                    878:        dat32 = BA0READ4(sc, CS4281_EPPMC);
                    879:        if (dat32 & EPPMC_FPDN)
                    880:                BA0WRITE4(sc, CS4281_EPPMC, dat32 & ~EPPMC_FPDN);
                    881:
                    882:        /* Start PLL out in known state */
                    883:        BA0WRITE4(sc, CS4281_CLKCR1, 0);
                    884:        /* Start serial ports out in known state */
                    885:        BA0WRITE4(sc, CS4281_SERMC, 0);
                    886:
                    887:        /* Reset codec */
                    888:        BA0WRITE4(sc, CS4281_ACCTL, 0);
                    889:        delay(50);      /* delay 50us */
                    890:
                    891:        BA0WRITE4(sc, CS4281_SPMC, 0);
                    892:        delay(100);     /* delay 100us */
                    893:        BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
                    894: #if defined(ENABLE_SECONDARY_CODEC)
                    895:        BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
                    896:        BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
                    897: #endif
                    898:        delay(50000);   /* XXX: delay 50ms */
                    899:
                    900:        /* Turn on Sound System clocks based on ABITCLK */
                    901:        BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_DLLP);
                    902:        delay(50000);   /* XXX: delay 50ms */
                    903:        BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_SWCE | CLKCR1_DLLP);
                    904:
                    905:        /* Set enables for sections that are needed in the SSPM registers */
                    906:        BA0WRITE4(sc, CS4281_SSPM,
                    907:                  SSPM_MIXEN |          /* Mixer */
                    908:                  SSPM_CSRCEN |         /* Capture SRC */
                    909:                  SSPM_PSRCEN |         /* Playback SRC */
                    910:                  SSPM_JSEN |           /* Joystick */
                    911:                  SSPM_ACLEN |          /* AC LINK */
                    912:                  SSPM_FMEN             /* FM */
                    913:                  );
                    914:
                    915:        /* Wait for clock stabilization */
                    916:        n = 0;
                    917:        while ((BA0READ4(sc, CS4281_CLKCR1)& (CLKCR1_DLLRDY | CLKCR1_CLKON))
                    918:            != (CLKCR1_DLLRDY | CLKCR1_CLKON)) {
                    919:                delay(100);
                    920:                if (++n > 1000)
                    921:                        return (-1);
                    922:        }
                    923:
                    924:        /* Enable ASYNC generation */
                    925:        BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN);
                    926:
                    927:        /* Wait for Codec ready. Linux driver wait 50ms here */
                    928:        n = 0;
                    929:        while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) {
                    930:                delay(100);
                    931:                if (++n > 1000)
                    932:                        return (-1);
                    933:        }
                    934:
                    935: #if defined(ENABLE_SECONDARY_CODEC)
                    936:        /* secondary codec ready*/
                    937:        n = 0;
                    938:        while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
                    939:                delay(100);
                    940:                if (++n > 1000)
                    941:                        return (-1);
                    942:        }
                    943: #endif
                    944:
                    945:        /* Set the serial timing configuration */
                    946:        /* XXX: undocumented but the Linux driver do this */
                    947:        BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
                    948:
                    949:        /* Wait for Codec ready signal */
                    950:        n = 0;
                    951:        do {
                    952:                delay(1000);
                    953:                if (++n > 1000) {
                    954:                        printf("%s: Timeout waiting for Codec ready\n",
                    955:                               sc->sc_dev.dv_xname);
                    956:                        return -1;
                    957:                }
                    958:                dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY;
                    959:        } while (dat32 == 0);
                    960:
                    961:        /* Enable Valid Frame output on ASDOUT */
                    962:        BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
                    963:
                    964:        /* Wait until Codec Calibration is finished. Codec register 26h */
                    965:        n = 0;
                    966:        do {
                    967:                delay(1);
                    968:                if (++n > 1000) {
                    969:                        printf("%s: Timeout waiting for Codec calibration\n",
                    970:                               sc->sc_dev.dv_xname);
                    971:                        return -1;
                    972:                }
                    973:                cs4281_read_codec(sc, AC97_REG_POWER, &data);
                    974:        } while ((data & 0x0f) != 0x0f);
                    975:
                    976:        /* Set the serial timing configuration again */
                    977:        /* XXX: undocumented but the Linux driver do this */
                    978:        BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
                    979:
                    980:        /* Wait until we've sampled input slots 3 & 4 as valid */
                    981:        n = 0;
                    982:        do {
                    983:                delay(1000);
                    984:                if (++n > 1000) {
                    985:                        printf("%s: Timeout waiting for sampled input slots as valid\n",
                    986:                               sc->sc_dev.dv_xname);
                    987:                        return -1;
                    988:                }
                    989:                dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4);
                    990:        } while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
                    991:
                    992:        /* Start digital data transfer of audio data to the codec */
                    993:        BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
                    994:
                    995:        cs4281_write_codec(sc, AC97_REG_HEADPHONE_VOLUME, 0);
                    996:        cs4281_write_codec(sc, AC97_REG_MASTER_VOLUME, 0);
                    997:
                    998:        /* Power on the DAC */
                    999:        cs4281_read_codec(sc, AC97_REG_POWER, &data);
                   1000:        cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfdff);
                   1001:
                   1002:        /* Wait until we sample a DAC ready state.
                   1003:         * Not documented, but Linux driver does.
                   1004:         */
                   1005:        for (n = 0; n < 32; ++n) {
                   1006:                delay(1000);
                   1007:                cs4281_read_codec(sc, AC97_REG_POWER, &data);
                   1008:                if (data & 0x02)
                   1009:                        break;
                   1010:        }
                   1011:
                   1012:        /* Power on the ADC */
                   1013:        cs4281_read_codec(sc, AC97_REG_POWER, &data);
                   1014:        cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfeff);
                   1015:
                   1016:        /* Wait until we sample ADC ready state.
                   1017:         * Not documented, but Linux driver does.
                   1018:         */
                   1019:        for (n = 0; n < 32; ++n) {
                   1020:                delay(1000);
                   1021:                cs4281_read_codec(sc, AC97_REG_POWER, &data);
                   1022:                if (data & 0x01)
                   1023:                        break;
                   1024:        }
                   1025:
                   1026: #if 0
                   1027:        /* Initialize SSCR register features */
                   1028:        /* XXX: hardware volume setting */
                   1029:        BA0WRITE4(sc, CS4281_SSCR, ~SSCR_HVC); /* disable HW volume setting */
                   1030: #endif
                   1031:
                   1032:        /* disable Sound Blaster Pro emulation */
                   1033:        /* XXX:
                   1034:         * Cannot set since the documents does not describe which bit is
                   1035:         * correspond to SSCR_SB. Since the reset value of SSCR is 0,
                   1036:         * we can ignore it.*/
                   1037: #if 0
                   1038:        BA0WRITE4(sc, CS4281_SSCR, SSCR_SB);
                   1039: #endif
                   1040:
                   1041:        /* map AC97 PCM playback to DMA Channel 0 */
                   1042:        /* Reset FEN bit to setup first */
                   1043:        BA0WRITE4(sc, CS4281_FCR0, (BA0READ4(sc,CS4281_FCR0) & ~FCRn_FEN));
                   1044:        /*
                   1045:         *| RS[4:0]/|        |
                   1046:         *| LS[4:0] |  AC97  | Slot Function
                   1047:         *|---------+--------+--------------------
                   1048:         *|     0   |    3   | Left PCM Playback
                   1049:         *|     1   |    4   | Right PCM Playback
                   1050:         *|     2   |    5   | Phone Line 1 DAC
                   1051:         *|     3   |    6   | Center PCM Playback
                   1052:         *....
                   1053:         *  quoted from Table 29(p109)
                   1054:         */
                   1055:        dat32 = 0x01 << 24 |   /* RS[4:0] =  1 see above */
                   1056:                0x00 << 16 |   /* LS[4:0] =  0 see above */
                   1057:                0x0f <<  8 |   /* SZ[6:0] = 15 size of buffer */
                   1058:                0x00 <<  0 ;   /* OF[6:0] =  0 offset */
                   1059:        BA0WRITE4(sc, CS4281_FCR0, dat32);
                   1060:        BA0WRITE4(sc, CS4281_FCR0, dat32 | FCRn_FEN);
                   1061:
                   1062:        /* map AC97 PCM record to DMA Channel 1 */
                   1063:        /* Reset FEN bit to setup first */
                   1064:        BA0WRITE4(sc, CS4281_FCR1, (BA0READ4(sc,CS4281_FCR1) & ~FCRn_FEN));
                   1065:        /*
                   1066:         *| RS[4:0]/|
                   1067:         *| LS[4:0] | AC97 | Slot Function
                   1068:         *|---------+------+-------------------
                   1069:         *|   10    |   3  | Left PCM Record
                   1070:         *|   11    |   4  | Right PCM Record
                   1071:         *|   12    |   5  | Phone Line 1 ADC
                   1072:         *|   13    |   6  | Mic ADC
                   1073:         *....
                   1074:         * quoted from Table 30(p109)
                   1075:         */
                   1076:        dat32 = 0x0b << 24 |    /* RS[4:0] = 11 See above */
                   1077:                0x0a << 16 |    /* LS[4:0] = 10 See above */
                   1078:                0x0f <<  8 |    /* SZ[6:0] = 15 Size of buffer */
                   1079:                0x10 <<  0 ;    /* OF[6:0] = 16 offset */
                   1080:
                   1081:        /* XXX: I cannot understand why FCRn_PSH is needed here. */
                   1082:        BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_PSH);
                   1083:        BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_FEN);
                   1084:
                   1085: #if 0
                   1086:        /* Disable DMA Channel 2, 3 */
                   1087:        BA0WRITE4(sc, CS4281_FCR2, (BA0READ4(sc,CS4281_FCR2) & ~FCRn_FEN));
                   1088:        BA0WRITE4(sc, CS4281_FCR3, (BA0READ4(sc,CS4281_FCR3) & ~FCRn_FEN));
                   1089: #endif
                   1090:
                   1091:        /* Set the SRC Slot Assignment accordingly */
                   1092:        /*| PLSS[4:0]/
                   1093:         *| PRSS[4:0] | AC97 | Slot Function
                   1094:         *|-----------+------+----------------
                   1095:         *|     0     |  3   | Left PCM Playback
                   1096:         *|     1     |  4   | Right PCM Playback
                   1097:         *|     2     |  5   | phone line 1 DAC
                   1098:         *|     3     |  6   | Center PCM Playback
                   1099:         *|     4     |  7   | Left Surround PCM Playback
                   1100:         *|     5     |  8   | Right Surround PCM Playback
                   1101:         *......
                   1102:         *
                   1103:         *| CLSS[4:0]/
                   1104:         *| CRSS[4:0] | AC97 | Codec |Slot Function
                   1105:         *|-----------+------+-------+-----------------
                   1106:         *|    10     |   3  |Primary| Left PCM Record
                   1107:         *|    11     |   4  |Primary| Right PCM Record
                   1108:         *|    12     |   5  |Primary| Phone Line 1 ADC
                   1109:         *|    13     |   6  |Primary| Mic ADC
                   1110:         *|.....
                   1111:         *|    20     |   3  |  Sec. | Left PCM Record
                   1112:         *|    21     |   4  |  Sec. | Right PCM Record
                   1113:         *|    22     |   5  |  Sec. | Phone Line 1 ADC
                   1114:         *|    23     |   6  |  Sec. | Mic ADC
                   1115:         */
                   1116:        dat32 = 0x0b << 24 |   /* CRSS[4:0] Right PCM Record(primary) */
                   1117:                0x0a << 16 |   /* CLSS[4:0] Left  PCM Record(primary) */
                   1118:                0x01 <<  8 |   /* PRSS[4:0] Right PCM Playback */
                   1119:                0x00 <<  0;    /* PLSS[4:0] Left  PCM Playback */
                   1120:        BA0WRITE4(sc, CS4281_SRCSA, dat32);
                   1121:
                   1122:        /* Set interrupt to occurred at Half and Full terminal
                   1123:         * count interrupt enable for DMA channel 0 and 1.
                   1124:         * To keep DMA stop, set MSK.
                   1125:         */
                   1126:        dat32 = DCRn_HTCIE | DCRn_TCIE | DCRn_MSK;
                   1127:        BA0WRITE4(sc, CS4281_DCR0, dat32);
                   1128:        BA0WRITE4(sc, CS4281_DCR1, dat32);
                   1129:
                   1130:        /* Set Auto-Initialize Control enable */
                   1131:        BA0WRITE4(sc, CS4281_DMR0,
                   1132:                  DMRn_DMA | DMRn_AUTO | DMRn_TR_READ);
                   1133:        BA0WRITE4(sc, CS4281_DMR1,
                   1134:                  DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);
                   1135:
                   1136:        /* Clear DMA Mask in HIMR */
                   1137:        dat32 = BA0READ4(sc, CS4281_HIMR) & 0xfffbfcff;
                   1138:        BA0WRITE4(sc, CS4281_HIMR, dat32);
                   1139:        return (0);
                   1140: }
                   1141:
                   1142: void
                   1143: cs4281_power(why, v)
                   1144:        int why;
                   1145:        void *v;
                   1146: {
                   1147:        struct cs4281_softc *sc = (struct cs4281_softc *)v;
                   1148:        int i;
                   1149:
                   1150:        DPRINTF(("%s: cs4281_power why=%d\n", sc->sc_dev.dv_xname, why));
                   1151:        if (why != PWR_RESUME) {
                   1152:                sc->sc_suspend = why;
                   1153:
                   1154:                cs4281_halt_output(sc);
                   1155:                cs4281_halt_input(sc);
                   1156:                /* Save AC97 registers */
                   1157:                for (i = 1; i <= CS4281_SAVE_REG_MAX; i++) {
                   1158:                        if (i == 0x04)  /* AC97_REG_MASTER_TONE */
                   1159:                                continue;
                   1160:                        cs4281_read_codec(sc, 2*i, &sc->ac97_reg[i>>1]);
                   1161:                }
                   1162:                /* should I powerdown here ? */
                   1163:                cs4281_write_codec(sc, AC97_REG_POWER, CS4281_POWER_DOWN_ALL);
                   1164:        } else {
                   1165:                if (sc->sc_suspend == PWR_RESUME) {
                   1166:                        printf("cs4281_power: odd, resume without suspend.\n");
                   1167:                        sc->sc_suspend = why;
                   1168:                        return;
                   1169:                }
                   1170:                sc->sc_suspend = why;
                   1171:                cs4281_init(sc);
                   1172:                cs4281_reset_codec(sc);
                   1173:
                   1174:                /* restore ac97 registers */
                   1175:                for (i = 1; i <= CS4281_SAVE_REG_MAX; i++) {
                   1176:                        if (i == 0x04)  /* AC97_REG_MASTER_TONE */
                   1177:                                continue;
                   1178:                        cs4281_write_codec(sc, 2*i, sc->ac97_reg[i>>1]);
                   1179:                }
                   1180:        }
                   1181: }
                   1182:
                   1183: void
                   1184: cs4281_reset_codec(void *addr)
                   1185: {
                   1186:        struct cs4281_softc *sc;
                   1187:        u_int16_t data;
                   1188:        u_int32_t dat32;
                   1189:        int n;
                   1190:
                   1191:        sc = addr;
                   1192:
                   1193:        DPRINTFN(3,("cs4281_reset_codec\n"));
                   1194:
                   1195:        /* Reset codec */
                   1196:        BA0WRITE4(sc, CS4281_ACCTL, 0);
                   1197:        delay(50);    /* delay 50us */
                   1198:
                   1199:        BA0WRITE4(sc, CS4281_SPMC, 0);
                   1200:        delay(100);     /* delay 100us */
                   1201:        BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
                   1202: #if defined(ENABLE_SECONDARY_CODEC)
                   1203:        BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
                   1204:        BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
                   1205: #endif
                   1206:        delay(50000);   /* XXX: delay 50ms */
                   1207:
                   1208:        /* Enable ASYNC generation */
                   1209:        BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN);
                   1210:
                   1211:        /* Wait for Codec ready. Linux driver wait 50ms here */
                   1212:        n = 0;
                   1213:        while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) {
                   1214:                delay(100);
                   1215:                if (++n > 1000) {
                   1216:                        printf("reset_codec: AC97 codec ready timeout\n");
                   1217:                        return;
                   1218:                }
                   1219:        }
                   1220: #if defined(ENABLE_SECONDARY_CODEC)
                   1221:        /* secondary codec ready*/
                   1222:        n = 0;
                   1223:        while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
                   1224:                delay(100);
                   1225:                if (++n > 1000)
                   1226:                        return;
                   1227:        }
                   1228: #endif
                   1229:        /* Set the serial timing configuration */
                   1230:        /* XXX: undocumented but the Linux driver do this */
                   1231:        BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
                   1232:
                   1233:        /* Wait for Codec ready signal */
                   1234:        n = 0;
                   1235:        do {
                   1236:                delay(1000);
                   1237:                if (++n > 1000) {
                   1238:                        printf("%s: Timeout waiting for Codec ready\n",
                   1239:                               sc->sc_dev.dv_xname);
                   1240:                        return;
                   1241:                }
                   1242:                dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY;
                   1243:        } while (dat32 == 0);
                   1244:
                   1245:        /* Enable Valid Frame output on ASDOUT */
                   1246:        BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
                   1247:
                   1248:        /* Wait until Codec Calibration is finished. Codec register 26h */
                   1249:        n = 0;
                   1250:        do {
                   1251:                delay(1);
                   1252:                if (++n > 1000) {
                   1253:                        printf("%s: Timeout waiting for Codec calibration\n",
                   1254:                               sc->sc_dev.dv_xname);
                   1255:                        return ;
                   1256:                }
                   1257:                cs4281_read_codec(sc, AC97_REG_POWER, &data);
                   1258:        } while ((data & 0x0f) != 0x0f);
                   1259:
                   1260:        /* Set the serial timing configuration again */
                   1261:        /* XXX: undocumented but the Linux driver do this */
                   1262:        BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
                   1263:
                   1264:        /* Wait until we've sampled input slots 3 & 4 as valid */
                   1265:        n = 0;
                   1266:        do {
                   1267:                delay(1000);
                   1268:                if (++n > 1000) {
                   1269:                        printf("%s: Timeout waiting for sampled input slots as valid\n",
                   1270:                               sc->sc_dev.dv_xname);
                   1271:                        return;
                   1272:                }
                   1273:                dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ;
                   1274:        } while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
                   1275:
                   1276:        /* Start digital data transfer of audio data to the codec */
                   1277:        BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
                   1278: }
                   1279:
                   1280: int
                   1281: cs4281_open(void *addr, int flags)
                   1282: {
                   1283:        return (0);
                   1284: }
                   1285:
                   1286: void
                   1287: cs4281_close(void *addr)
                   1288: {
                   1289:        struct cs4281_softc *sc;
                   1290:
                   1291:        sc = addr;
                   1292:
                   1293:        (*sc->halt_output)(sc);
                   1294:        (*sc->halt_input)(sc);
                   1295:
                   1296:        sc->sc_pintr = 0;
                   1297:        sc->sc_rintr = 0;
                   1298: }
                   1299:
                   1300: int
                   1301: cs4281_round_blocksize(void *addr, int blk)
                   1302: {
                   1303:        struct cs4281_softc *sc;
                   1304:        int retval;
                   1305:
                   1306:        DPRINTFN(5,("cs4281_round_blocksize blk=%d -> ", blk));
                   1307:
                   1308:        sc=addr;
                   1309:        if (blk < sc->hw_blocksize)
                   1310:                retval = sc->hw_blocksize;
                   1311:        else
                   1312:                retval = blk & -(sc->hw_blocksize);
                   1313:
                   1314:        DPRINTFN(5,("%d\n", retval));
                   1315:
                   1316:        return (retval);
                   1317: }
                   1318:
                   1319: int
                   1320: cs4281_mixer_set_port(void *addr, mixer_ctrl_t *cp)
                   1321: {
                   1322:        struct cs4281_softc *sc;
                   1323:        int val;
                   1324:
                   1325:        sc = addr;
                   1326:        val = sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
                   1327:        DPRINTFN(3,("mixer_set_port: val=%d\n", val));
                   1328:        return (val);
                   1329: }
                   1330:
                   1331: int
                   1332: cs4281_mixer_get_port(void *addr, mixer_ctrl_t *cp)
                   1333: {
                   1334:        struct cs4281_softc *sc;
                   1335:
                   1336:        sc = addr;
                   1337:        return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
                   1338: }
                   1339:
                   1340:
                   1341: int
                   1342: cs4281_query_devinfo(void *addr, mixer_devinfo_t *dip)
                   1343: {
                   1344:        struct cs4281_softc *sc;
                   1345:
                   1346:        sc = addr;
                   1347:        return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
                   1348: }
                   1349:
                   1350: void *
                   1351: cs4281_malloc(void *addr, int direction, size_t size, int pool, int flags)
                   1352: {
                   1353:        struct cs4281_softc *sc;
                   1354:        struct cs4281_dma   *p;
                   1355:        int error;
                   1356:
                   1357:        sc = addr;
                   1358:
                   1359:        p = malloc(sizeof(*p), pool, flags);
                   1360:        if (!p)
                   1361:                return (0);
                   1362:
                   1363:        error = cs4281_allocmem(sc, size, pool, flags, p);
                   1364:
                   1365:        if (error) {
                   1366:                free(p, pool);
                   1367:                return (0);
                   1368:        }
                   1369:
                   1370:        p->next = sc->sc_dmas;
                   1371:        sc->sc_dmas = p;
                   1372:        return (BUFADDR(p));
                   1373: }
                   1374:
                   1375:
                   1376:
                   1377: void
                   1378: cs4281_free(void *addr, void *ptr, int pool)
                   1379: {
                   1380:        struct cs4281_softc *sc;
                   1381:        struct cs4281_dma **pp, *p;
                   1382:
                   1383:        sc = addr;
                   1384:        for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
                   1385:                if (BUFADDR(p) == ptr) {
                   1386:                        bus_dmamap_unload(sc->sc_dmatag, p->map);
                   1387:                        bus_dmamap_destroy(sc->sc_dmatag, p->map);
                   1388:                        bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
                   1389:                        bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
                   1390:                        free(p->dum, pool);
                   1391:                        *pp = p->next;
                   1392:                        free(p, pool);
                   1393:                        return;
                   1394:                }
                   1395:        }
                   1396: }
                   1397:
                   1398: size_t
                   1399: cs4281_round_buffersize(void *addr, int direction, size_t size)
                   1400: {
                   1401:        /* The real dma buffersize are 4KB for CS4280
                   1402:         * and 64kB/MAX_CHANNELS for CS4281.
                   1403:         * But they are too small for high quality audio,
                   1404:         * let the upper layer(audio) use a larger buffer.
                   1405:         * (originally suggested by Lennart Augustsson.)
                   1406:         */
                   1407:        return (size);
                   1408: }
                   1409:
                   1410: paddr_t
                   1411: cs4281_mappage(void *addr, void *mem, off_t off, int prot)
                   1412: {
                   1413:        struct cs4281_softc *sc;
                   1414:        struct cs4281_dma *p;
                   1415:
                   1416:        sc = addr;
                   1417:        if (off < 0)
                   1418:                return -1;
                   1419:
                   1420:        for (p = sc->sc_dmas; p && BUFADDR(p) != mem; p = p->next)
                   1421:                ;
                   1422:
                   1423:        if (!p) {
                   1424:                DPRINTF(("cs4281_mappage: bad buffer address\n"));
                   1425:                return (-1);
                   1426:        }
                   1427:
                   1428:        return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, off, prot,
                   1429:            BUS_DMA_WAITOK));
                   1430: }
                   1431:
                   1432:
                   1433: int
                   1434: cs4281_get_props(void *addr)
                   1435: {
                   1436:        int retval;
                   1437:
                   1438:        retval = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
                   1439: #ifdef MMAP_READY
                   1440:        retval |= AUDIO_PROP_MMAP;
                   1441: #endif
                   1442:        return (retval);
                   1443: }
                   1444:
                   1445: /* AC97 */
                   1446: int
                   1447: cs4281_attach_codec(void *addr, struct ac97_codec_if *codec_if)
                   1448: {
                   1449:        struct cs4281_softc *sc;
                   1450:
                   1451:        DPRINTF(("cs4281_attach_codec:\n"));
                   1452:        sc = addr;
                   1453:        sc->codec_if = codec_if;
                   1454:        return (0);
                   1455: }
                   1456:
                   1457:
                   1458: int
                   1459: cs4281_read_codec(void *addr, u_int8_t ac97_addr, u_int16_t *ac97_data)
                   1460: {
                   1461:        struct cs4281_softc *sc;
                   1462:        u_int32_t acctl;
                   1463:        int n;
                   1464:
                   1465:        sc = addr;
                   1466:
                   1467:        DPRINTFN(5,("read_codec: add=0x%02x ", ac97_addr));
                   1468:        /*
                   1469:         * Make sure that there is not data sitting around from a preivous
                   1470:         * uncompleted access.
                   1471:         */
                   1472:        BA0READ4(sc, CS4281_ACSDA);
                   1473:
                   1474:        /* Set up AC97 control registers. */
                   1475:        BA0WRITE4(sc, CS4281_ACCAD, ac97_addr);
                   1476:        BA0WRITE4(sc, CS4281_ACCDA, 0);
                   1477:
                   1478:        acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW  | ACCTL_DCV;
                   1479:        BA0WRITE4(sc, CS4281_ACCTL, acctl);
                   1480:
                   1481:        if (cs4281_src_wait(sc) < 0) {
                   1482:                printf("%s: AC97 read prob. (DCV!=0) for add=0x%0x\n",
                   1483:                       sc->sc_dev.dv_xname, ac97_addr);
                   1484:                return 1;
                   1485:        }
                   1486:
                   1487:        /* wait for valid status bit is active */
                   1488:        n = 0;
                   1489:        while ((BA0READ4(sc, CS4281_ACSTS) & ACSTS_VSTS) == 0) {
                   1490:                delay(1);
                   1491:                while (++n > 1000) {
                   1492:                        printf("%s: AC97 read fail (VSTS==0) for add=0x%0x\n",
                   1493:                               sc->sc_dev.dv_xname, ac97_addr);
                   1494:                        return 1;
                   1495:                }
                   1496:        }
                   1497:        *ac97_data = BA0READ4(sc, CS4281_ACSDA);
                   1498:        DPRINTFN(5,("data=0x%04x\n", *ac97_data));
                   1499:        return (0);
                   1500: }
                   1501:
                   1502: int
                   1503: cs4281_write_codec(void *addr, u_int8_t ac97_addr, u_int16_t ac97_data)
                   1504: {
                   1505:        struct cs4281_softc *sc;
                   1506:        u_int32_t acctl;
                   1507:
                   1508:        sc = addr;
                   1509:
                   1510:        DPRINTFN(5,("write_codec: add=0x%02x  data=0x%04x\n", ac97_addr, ac97_data));
                   1511:        BA0WRITE4(sc, CS4281_ACCAD, ac97_addr);
                   1512:        BA0WRITE4(sc, CS4281_ACCDA, ac97_data);
                   1513:
                   1514:        acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV;
                   1515:        BA0WRITE4(sc, CS4281_ACCTL, acctl);
                   1516:
                   1517:        if (cs4281_src_wait(sc) < 0) {
                   1518:                printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data="
                   1519:                       "0x%04x\n", sc->sc_dev.dv_xname, ac97_addr, ac97_data);
                   1520:                return (1);
                   1521:        }
                   1522:        return (0);
                   1523: }
                   1524:
                   1525: int
                   1526: cs4281_allocmem(struct cs4281_softc *sc, size_t size, int pool, int flags,
                   1527:                struct cs4281_dma *p)
                   1528: {
                   1529:        int error;
                   1530:        size_t align;
                   1531:
                   1532:        align   = sc->dma_align;
                   1533:        p->size = sc->dma_size;
                   1534:        /* allocate memory for upper audio driver */
                   1535:        p->dum  = malloc(size, pool, flags);
                   1536:        if (!p->dum)
                   1537:                return (1);
                   1538:        error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
                   1539:                                 p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
                   1540:                                 &p->nsegs, BUS_DMA_NOWAIT);
                   1541:        if (error) {
                   1542:                printf("%s: unable to allocate dma. error=%d\n",
                   1543:                       sc->sc_dev.dv_xname, error);
                   1544:                return (error);
                   1545:        }
                   1546:
                   1547:        error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
                   1548:                               &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
                   1549:        if (error) {
                   1550:                printf("%s: unable to map dma, error=%d\n",
                   1551:                       sc->sc_dev.dv_xname, error);
                   1552:                goto free;
                   1553:        }
                   1554:
                   1555:        error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
                   1556:                                  0, BUS_DMA_NOWAIT, &p->map);
                   1557:        if (error) {
                   1558:                printf("%s: unable to create dma map, error=%d\n",
                   1559:                       sc->sc_dev.dv_xname, error);
                   1560:                goto unmap;
                   1561:        }
                   1562:
                   1563:        error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
                   1564:                                BUS_DMA_NOWAIT);
                   1565:        if (error) {
                   1566:                printf("%s: unable to load dma map, error=%d\n",
                   1567:                       sc->sc_dev.dv_xname, error);
                   1568:                goto destroy;
                   1569:        }
                   1570:        return (0);
                   1571:
                   1572: destroy:
                   1573:        bus_dmamap_destroy(sc->sc_dmatag, p->map);
                   1574: unmap:
                   1575:        bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
                   1576: free:
                   1577:        bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
                   1578:        return (error);
                   1579: }
                   1580:
                   1581:
                   1582: int
                   1583: cs4281_src_wait(sc)
                   1584:        struct cs4281_softc *sc;
                   1585: {
                   1586:        int n;
                   1587:
                   1588:        n = 0;
                   1589:        while ((BA0READ4(sc, CS4281_ACCTL) & ACCTL_DCV)) {
                   1590:                delay(1000);
                   1591:                if (++n > 1000)
                   1592:                        return (-1);
                   1593:        }
                   1594:        return (0);
                   1595: }

CVSweb