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

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

1.1       nbrk        1: /*     $OpenBSD: cmpci.c,v 1.14 2006/07/27 00:45:59 brad Exp $ */
                      2: /*     $NetBSD: cmpci.c,v 1.25 2004/10/26 06:32:20 xtraeme Exp $       */
                      3:
                      4: /*
                      5:  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Takuya SHIOZAKI <tshiozak@NetBSD.org> .
                     10:  *
                     11:  * This code is derived from software contributed to The NetBSD Foundation
                     12:  * by ITOH Yasufumi.
                     13:  *
                     14:  * Redistribution and use in source and binary forms, with or without
                     15:  * modification, are permitted provided that the following conditions
                     16:  * are met:
                     17:  * 1. Redistributions of source code must retain the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer.
                     19:  * 2. Redistributions in binary form must reproduce the above copyright
                     20:  *    notice, this list of conditions and the following disclaimer in the
                     21:  *    documentation and/or other materials provided with the distribution.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  *
                     35:  */
                     36:
                     37: /*
                     38:  * C-Media CMI8x38 Audio Chip Support.
                     39:  *
                     40:  * TODO:
                     41:  *   - 4ch / 6ch support.
                     42:  *   - Joystick support.
                     43:  *
                     44:  */
                     45:
                     46: #if 0
                     47: #include <sys/cdefs.h>
                     48: __KERNEL_RCSID(0, "$NetBSD: cmpci.c,v 1.25 2004/10/26 06:32:20 xtraeme Exp $");
                     49: #endif
                     50:
                     51: #if defined(AUDIO_DEBUG) || defined(DEBUG)
                     52: #define DPRINTF(x) if (cmpcidebug) printf x
                     53: int cmpcidebug = 0;
                     54: #else
                     55: #define DPRINTF(x)
                     56: #endif
                     57:
                     58: #include <sys/param.h>
                     59: #include <sys/systm.h>
                     60: #include <sys/kernel.h>
                     61: #include <sys/malloc.h>
                     62: #include <sys/device.h>
                     63: #include <sys/proc.h>
                     64:
                     65: #include <dev/pci/pcidevs.h>
                     66: #include <dev/pci/pcivar.h>
                     67:
                     68: #include <sys/audioio.h>
                     69: #include <dev/audio_if.h>
                     70: #include <dev/midi_if.h>
                     71:
                     72: #include <dev/mulaw.h>
                     73: #include <dev/auconv.h>
                     74: #include <dev/pci/cmpcireg.h>
                     75: #include <dev/pci/cmpcivar.h>
                     76:
                     77: #include <dev/ic/mpuvar.h>
                     78: #include <machine/bus.h>
                     79: #include <machine/intr.h>
                     80:
                     81: /*
                     82:  * Low-level HW interface
                     83:  */
                     84: __inline uint8_t cmpci_mixerreg_read(struct cmpci_softc *,
                     85:                                                 uint8_t);
                     86: __inline void cmpci_mixerreg_write(struct cmpci_softc *,
                     87:                                               uint8_t, uint8_t);
                     88: __inline void cmpci_reg_partial_write_1(struct cmpci_softc *,
                     89:                                                    int, int,
                     90:                                                    unsigned, unsigned);
                     91: __inline void cmpci_reg_partial_write_4(struct cmpci_softc *,
                     92:                                                    int, int,
                     93:                                                    uint32_t, uint32_t);
                     94: __inline void cmpci_reg_set_1(struct cmpci_softc *,
                     95:                                          int, uint8_t);
                     96: __inline void cmpci_reg_clear_1(struct cmpci_softc *,
                     97:                                            int, uint8_t);
                     98: __inline void cmpci_reg_set_4(struct cmpci_softc *,
                     99:                                          int, uint32_t);
                    100: __inline void cmpci_reg_clear_4(struct cmpci_softc *,
                    101:                                            int, uint32_t);
                    102: __inline void cmpci_reg_set_reg_misc(struct cmpci_softc *,
                    103:                                                 uint32_t);
                    104: __inline void cmpci_reg_clear_reg_misc(struct cmpci_softc *,
                    105:                                                   uint32_t);
                    106: int cmpci_rate_to_index(int);
                    107: __inline int cmpci_index_to_rate(int);
                    108: __inline int cmpci_index_to_divider(int);
                    109:
                    110: int cmpci_adjust(int, int);
                    111: void cmpci_set_mixer_gain(struct cmpci_softc *, int);
                    112: void cmpci_set_out_ports(struct cmpci_softc *);
                    113: int cmpci_set_in_ports(struct cmpci_softc *);
                    114:
                    115: /*
                    116:  * autoconf interface
                    117:  */
                    118: int cmpci_match(struct device *, void *, void *);
                    119: void cmpci_attach(struct device *, struct device *, void *);
                    120:
                    121: struct cfdriver cmpci_cd = {
                    122:        NULL, "cmpci", DV_DULL
                    123: };
                    124:
                    125: struct cfattach cmpci_ca = {
                    126:        sizeof (struct cmpci_softc), cmpci_match, cmpci_attach
                    127: };
                    128:
                    129: /* interrupt */
                    130: int cmpci_intr(void *);
                    131:
                    132: /*
                    133:  * DMA stuff
                    134:  */
                    135: int cmpci_alloc_dmamem(struct cmpci_softc *,
                    136:                                   size_t, int,
                    137:                                   int, caddr_t *);
                    138: int cmpci_free_dmamem(struct cmpci_softc *, caddr_t,
                    139:                                  int);
                    140: struct cmpci_dmanode * cmpci_find_dmamem(struct cmpci_softc *,
                    141:                                                     caddr_t);
                    142:
                    143: /*
                    144:  * Interface to machine independent layer
                    145:  */
                    146: int cmpci_open(void *, int);
                    147: void cmpci_close(void *);
                    148: int cmpci_query_encoding(void *, struct audio_encoding *);
                    149: int cmpci_set_params(void *, int, int,
                    150:                                 struct audio_params *,
                    151:                                 struct audio_params *);
                    152: int cmpci_round_blocksize(void *, int);
                    153: int cmpci_halt_output(void *);
                    154: int cmpci_halt_input(void *);
                    155: int cmpci_getdev(void *, struct audio_device *);
                    156: int cmpci_set_port(void *, mixer_ctrl_t *);
                    157: int cmpci_get_port(void *, mixer_ctrl_t *);
                    158: int cmpci_query_devinfo(void *, mixer_devinfo_t *);
                    159: void *cmpci_malloc(void *, int, size_t, int, int);
                    160: void cmpci_free(void *, void *, int);
                    161: size_t cmpci_round_buffersize(void *, int, size_t);
                    162: paddr_t cmpci_mappage(void *, void *, off_t, int);
                    163: int cmpci_get_props(void *);
                    164: int cmpci_trigger_output(void *, void *, void *, int,
                    165:                                     void (*)(void *), void *,
                    166:                                     struct audio_params *);
                    167: int cmpci_trigger_input(void *, void *, void *, int,
                    168:                                    void (*)(void *), void *,
                    169:                                    struct audio_params *);
                    170:
                    171: struct audio_hw_if cmpci_hw_if = {
                    172:        cmpci_open,             /* open */
                    173:        cmpci_close,            /* close */
                    174:        NULL,                   /* drain */
                    175:        cmpci_query_encoding,   /* query_encoding */
                    176:        cmpci_set_params,       /* set_params */
                    177:        cmpci_round_blocksize,  /* round_blocksize */
                    178:        NULL,                   /* commit_settings */
                    179:        NULL,                   /* init_output */
                    180:        NULL,                   /* init_input */
                    181:        NULL,                   /* start_output */
                    182:        NULL,                   /* start_input */
                    183:        cmpci_halt_output,      /* halt_output */
                    184:        cmpci_halt_input,       /* halt_input */
                    185:        NULL,                   /* speaker_ctl */
                    186:        cmpci_getdev,           /* getdev */
                    187:        NULL,                   /* setfd */
                    188:        cmpci_set_port,         /* set_port */
                    189:        cmpci_get_port,         /* get_port */
                    190:        cmpci_query_devinfo,    /* query_devinfo */
                    191:        cmpci_malloc,           /* malloc */
                    192:        cmpci_free,             /* free */
                    193:        cmpci_round_buffersize,/* round_buffersize */
                    194:        cmpci_mappage,          /* mappage */
                    195:        cmpci_get_props,        /* get_props */
                    196:        cmpci_trigger_output,   /* trigger_output */
                    197:        cmpci_trigger_input,    /* trigger_input */
                    198: };
                    199:
                    200: /*
                    201:  * Low-level HW interface
                    202:  */
                    203:
                    204: /* mixer register read/write */
                    205: __inline uint8_t
                    206: cmpci_mixerreg_read(struct cmpci_softc *sc, uint8_t no)
                    207: {
                    208:        uint8_t ret;
                    209:
                    210:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
                    211:        delay(10);
                    212:        ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA);
                    213:        delay(10);
                    214:        return ret;
                    215: }
                    216:
                    217: __inline void
                    218: cmpci_mixerreg_write(struct cmpci_softc *sc, uint8_t no, uint8_t val)
                    219: {
                    220:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
                    221:        delay(10);
                    222:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val);
                    223:        delay(10);
                    224: }
                    225:
                    226: /* register partial write */
                    227: __inline void
                    228: cmpci_reg_partial_write_1(struct cmpci_softc *sc, int no, int shift,
                    229:     unsigned mask, unsigned val)
                    230: {
                    231:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
                    232:            (val<<shift) |
                    233:            (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
                    234:        delay(10);
                    235: }
                    236:
                    237: __inline void
                    238: cmpci_reg_partial_write_4(struct cmpci_softc *sc, int no, int shift,
                    239:     uint32_t mask, uint32_t val)
                    240: {
                    241:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
                    242:            (val<<shift) |
                    243:            (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
                    244:        delay(10);
                    245: }
                    246:
                    247: /* register set/clear bit */
                    248: __inline void
                    249: cmpci_reg_set_1(struct cmpci_softc *sc, int no, uint8_t mask)
                    250: {
                    251:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
                    252:            (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) | mask));
                    253:        delay(10);
                    254: }
                    255:
                    256: __inline void
                    257: cmpci_reg_clear_1(struct cmpci_softc *sc, int no, uint8_t mask)
                    258: {
                    259:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
                    260:            (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~mask));
                    261:        delay(10);
                    262: }
                    263:
                    264: __inline void
                    265: cmpci_reg_set_4(struct cmpci_softc *sc, int no, uint32_t mask)
                    266: {
                    267:        /* use cmpci_reg_set_reg_misc() for CMPCI_REG_MISC */
                    268:        KDASSERT(no != CMPCI_REG_MISC);
                    269:
                    270:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
                    271:            (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
                    272:        delay(10);
                    273: }
                    274:
                    275: __inline void
                    276: cmpci_reg_clear_4(struct cmpci_softc *sc, int no, uint32_t mask)
                    277: {
                    278:        /* use cmpci_reg_clear_reg_misc() for CMPCI_REG_MISC */
                    279:        KDASSERT(no != CMPCI_REG_MISC);
                    280:
                    281:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
                    282:            (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
                    283:        delay(10);
                    284: }
                    285:
                    286: /*
                    287:  * The CMPCI_REG_MISC register needs special handling, since one of
                    288:  * its bits has different read/write values.
                    289:  */
                    290: __inline void
                    291: cmpci_reg_set_reg_misc(struct cmpci_softc *sc, uint32_t mask)
                    292: {
                    293:        sc->sc_reg_misc |= mask;
                    294:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC,
                    295:            sc->sc_reg_misc);
                    296:        delay(10);
                    297: }
                    298:
                    299: __inline void
                    300: cmpci_reg_clear_reg_misc(struct cmpci_softc *sc, uint32_t mask)
                    301: {
                    302:        sc->sc_reg_misc &= ~mask;
                    303:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC,
                    304:            sc->sc_reg_misc);
                    305:        delay(10);
                    306: }
                    307:
                    308: /* rate */
                    309: static const struct {
                    310:        int rate;
                    311:        int divider;
                    312: } cmpci_rate_table[CMPCI_REG_NUMRATE] = {
                    313: #define _RATE(n) { n, CMPCI_REG_RATE_ ## n }
                    314:        _RATE(5512),
                    315:        _RATE(8000),
                    316:        _RATE(11025),
                    317:        _RATE(16000),
                    318:        _RATE(22050),
                    319:        _RATE(32000),
                    320:        _RATE(44100),
                    321:        _RATE(48000)
                    322: #undef _RATE
                    323: };
                    324:
                    325: int
                    326: cmpci_rate_to_index(int rate)
                    327: {
                    328:        int i;
                    329:
                    330:        for (i = 0; i < CMPCI_REG_NUMRATE - 1; i++)
                    331:                if (rate <=
                    332:                    (cmpci_rate_table[i].rate + cmpci_rate_table[i+1].rate) / 2)
                    333:                        return i;
                    334:        return i;  /* 48000 */
                    335: }
                    336:
                    337: __inline int
                    338: cmpci_index_to_rate(int index)
                    339: {
                    340:        return cmpci_rate_table[index].rate;
                    341: }
                    342:
                    343: __inline int
                    344: cmpci_index_to_divider(int index)
                    345: {
                    346:        return cmpci_rate_table[index].divider;
                    347: }
                    348:
                    349: const struct pci_matchid cmpci_devices[] = {
                    350:        { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338A },
                    351:        { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338B },
                    352:        { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738 },
                    353:        { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738B }
                    354: };
                    355:
                    356: /*
                    357:  * interface to configure the device.
                    358:  */
                    359:
                    360: int
                    361: cmpci_match(struct device *parent, void *match, void *aux)
                    362: {
                    363:        return (pci_matchbyid((struct pci_attach_args *)aux, cmpci_devices,
                    364:            sizeof(cmpci_devices)/sizeof(cmpci_devices[0])));
                    365: }
                    366:
                    367: void
                    368: cmpci_attach(struct device *parent, struct device *self, void *aux)
                    369: {
                    370:        struct cmpci_softc *sc = (struct cmpci_softc *)self;
                    371:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                    372:        struct audio_attach_args aa;
                    373:        pci_intr_handle_t ih;
                    374:        char const *intrstr;
                    375:        int i, v;
                    376:
                    377:        sc->sc_id = pa->pa_id;
                    378:        sc->sc_class = pa->pa_class;
                    379:        switch (PCI_PRODUCT(sc->sc_id)) {
                    380:        case PCI_PRODUCT_CMI_CMI8338A:
                    381:                /*FALLTHROUGH*/
                    382:        case PCI_PRODUCT_CMI_CMI8338B:
                    383:                sc->sc_capable = CMPCI_CAP_CMI8338;
                    384:                break;
                    385:        case PCI_PRODUCT_CMI_CMI8738:
                    386:                /*FALLTHROUGH*/
                    387:        case PCI_PRODUCT_CMI_CMI8738B:
                    388:                sc->sc_capable = CMPCI_CAP_CMI8738;
                    389:                break;
                    390:        }
                    391:
                    392:        /* map I/O space */
                    393:        if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0,
                    394:                           &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0)) {
                    395:                printf(": failed to map I/O space\n");
                    396:                return;
                    397:        }
                    398:
                    399:        /* interrupt */
                    400:        if (pci_intr_map(pa, &ih)) {
                    401:                printf(": failed to map interrupt\n");
                    402:                return;
                    403:        }
                    404:        intrstr = pci_intr_string(pa->pa_pc, ih);
                    405:        sc->sc_ih=pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, cmpci_intr, sc,
                    406:            sc->sc_dev.dv_xname);
                    407:        if (sc->sc_ih == NULL) {
                    408:                printf(": failed to establish interrupt");
                    409:                if (intrstr != NULL)
                    410:                        printf(" at %s", intrstr);
                    411:                printf("\n");
                    412:                return;
                    413:        }
                    414:        printf(": %s\n", intrstr);
                    415:
                    416:        sc->sc_dmat = pa->pa_dmat;
                    417:
                    418:        audio_attach_mi(&cmpci_hw_if, sc, &sc->sc_dev);
                    419:
                    420:        /* attach OPL device */
                    421:        aa.type = AUDIODEV_TYPE_OPL;
                    422:        aa.hwif = NULL;
                    423:        aa.hdl = NULL;
                    424:        (void)config_found(&sc->sc_dev, &aa, audioprint);
                    425:
                    426:        /* attach MPU-401 device */
                    427:        aa.type = AUDIODEV_TYPE_MPU;
                    428:        aa.hwif = NULL;
                    429:        aa.hdl = NULL;
                    430:        if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
                    431:            CMPCI_REG_MPU_BASE, CMPCI_REG_MPU_SIZE, &sc->sc_mpu_ioh) == 0)
                    432:                sc->sc_mpudev = config_found(&sc->sc_dev, &aa, audioprint);
                    433:
                    434:        /* get initial value (this is 0 and may be omitted but just in case) */
                    435:        sc->sc_reg_misc = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
                    436:            CMPCI_REG_MISC) & ~CMPCI_REG_SPDIF48K;
                    437:
                    438:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
                    439:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
                    440:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
                    441:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX,
                    442:            CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC|CMPCI_SB16_SW_LINE);
                    443:        for (i = 0; i < CMPCI_NDEVS; i++) {
                    444:                switch(i) {
                    445:                /*
                    446:                 * CMI8738 defaults are
                    447:                 *  master:     0xe0    (0x00 - 0xf8)
                    448:                 *  FM, DAC:    0xc0    (0x00 - 0xf8)
                    449:                 *  PC speaker: 0x80    (0x00 - 0xc0)
                    450:                 *  others:     0
                    451:                 */
                    452:                /* volume */
                    453:                case CMPCI_MASTER_VOL:
                    454:                        v = 128;        /* 224 */
                    455:                        break;
                    456:                case CMPCI_FM_VOL:
                    457:                case CMPCI_DAC_VOL:
                    458:                        v = 192;
                    459:                        break;
                    460:                case CMPCI_PCSPEAKER:
                    461:                        v = 128;
                    462:                        break;
                    463:
                    464:                /* booleans, set to true */
                    465:                case CMPCI_CD_MUTE:
                    466:                case CMPCI_MIC_MUTE:
                    467:                case CMPCI_LINE_IN_MUTE:
                    468:                case CMPCI_AUX_IN_MUTE:
                    469:                        v = 1;
                    470:                        break;
                    471:
                    472:                /* volume with inital value 0 */
                    473:                case CMPCI_CD_VOL:
                    474:                case CMPCI_LINE_IN_VOL:
                    475:                case CMPCI_AUX_IN_VOL:
                    476:                case CMPCI_MIC_VOL:
                    477:                case CMPCI_MIC_RECVOL:
                    478:                        /* FALLTHROUGH */
                    479:
                    480:                /* others are cleared */
                    481:                case CMPCI_MIC_PREAMP:
                    482:                case CMPCI_RECORD_SOURCE:
                    483:                case CMPCI_PLAYBACK_MODE:
                    484:                case CMPCI_SPDIF_IN_SELECT:
                    485:                case CMPCI_SPDIF_IN_PHASE:
                    486:                case CMPCI_SPDIF_LOOP:
                    487:                case CMPCI_SPDIF_OUT_PLAYBACK:
                    488:                case CMPCI_SPDIF_OUT_VOLTAGE:
                    489:                case CMPCI_MONITOR_DAC:
                    490:                case CMPCI_REAR:
                    491:                case CMPCI_INDIVIDUAL:
                    492:                case CMPCI_REVERSE:
                    493:                case CMPCI_SURROUND:
                    494:                default:
                    495:                        v = 0;
                    496:                        break;
                    497:                }
                    498:                sc->sc_gain[i][CMPCI_LEFT] = sc->sc_gain[i][CMPCI_RIGHT] = v;
                    499:                cmpci_set_mixer_gain(sc, i);
                    500:        }
                    501: }
                    502:
                    503: int
                    504: cmpci_intr(void *handle)
                    505: {
                    506:        struct cmpci_softc *sc = handle;
                    507:        uint32_t intrstat;
                    508:
                    509:        intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
                    510:            CMPCI_REG_INTR_STATUS);
                    511:
                    512:        if (!(intrstat & CMPCI_REG_ANY_INTR))
                    513:                return 0;
                    514:
                    515:        delay(10);
                    516:
                    517:        /* disable and reset intr */
                    518:        if (intrstat & CMPCI_REG_CH0_INTR)
                    519:                cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
                    520:                   CMPCI_REG_CH0_INTR_ENABLE);
                    521:        if (intrstat & CMPCI_REG_CH1_INTR)
                    522:                cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
                    523:                    CMPCI_REG_CH1_INTR_ENABLE);
                    524:
                    525:        if (intrstat & CMPCI_REG_CH0_INTR) {
                    526:                if (sc->sc_play.intr != NULL)
                    527:                        (*sc->sc_play.intr)(sc->sc_play.intr_arg);
                    528:        }
                    529:        if (intrstat & CMPCI_REG_CH1_INTR) {
                    530:                if (sc->sc_rec.intr != NULL)
                    531:                        (*sc->sc_rec.intr)(sc->sc_rec.intr_arg);
                    532:        }
                    533:
                    534:        /* enable intr */
                    535:        if (intrstat & CMPCI_REG_CH0_INTR)
                    536:                cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
                    537:                    CMPCI_REG_CH0_INTR_ENABLE);
                    538:        if (intrstat & CMPCI_REG_CH1_INTR)
                    539:                cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
                    540:                    CMPCI_REG_CH1_INTR_ENABLE);
                    541:
                    542: #if 0
                    543:        if (intrstat & CMPCI_REG_UART_INTR && sc->sc_mpudev != NULL)
                    544:                mpu_intr(sc->sc_mpudev);
                    545: #endif
                    546:
                    547:        return 1;
                    548: }
                    549:
                    550: /* open/close */
                    551: int
                    552: cmpci_open(void *handle, int flags)
                    553: {
                    554:        return 0;
                    555: }
                    556:
                    557: void
                    558: cmpci_close(void *handle)
                    559: {
                    560: }
                    561:
                    562: int
                    563: cmpci_query_encoding(void *handle, struct audio_encoding *fp)
                    564: {
                    565:        switch (fp->index) {
                    566:        case 0:
                    567:                strlcpy(fp->name, AudioEulinear, sizeof fp->name);
                    568:                fp->encoding = AUDIO_ENCODING_ULINEAR;
                    569:                fp->precision = 8;
                    570:                fp->flags = 0;
                    571:                break;
                    572:        case 1:
                    573:                strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
                    574:                fp->encoding = AUDIO_ENCODING_ULAW;
                    575:                fp->precision = 8;
                    576:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    577:                break;
                    578:        case 2:
                    579:                strlcpy(fp->name, AudioEalaw, sizeof fp->name);
                    580:                fp->encoding = AUDIO_ENCODING_ALAW;
                    581:                fp->precision = 8;
                    582:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    583:                break;
                    584:        case 3:
                    585:                strlcpy(fp->name, AudioEslinear, sizeof fp->name);
                    586:                fp->encoding = AUDIO_ENCODING_SLINEAR;
                    587:                fp->precision = 8;
                    588:                fp->flags = 0;
                    589:                break;
                    590:        case 4:
                    591:                strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
                    592:                fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
                    593:                fp->precision = 16;
                    594:                fp->flags = 0;
                    595:                break;
                    596:        case 5:
                    597:                strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
                    598:                fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
                    599:                fp->precision = 16;
                    600:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    601:                break;
                    602:        case 6:
                    603:                strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
                    604:                fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
                    605:                fp->precision = 16;
                    606:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    607:                break;
                    608:        case 7:
                    609:                strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
                    610:                fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
                    611:                fp->precision = 16;
                    612:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    613:                break;
                    614:        default:
                    615:                return EINVAL;
                    616:        }
                    617:        return 0;
                    618: }
                    619:
                    620: int
                    621: cmpci_set_params(void *handle, int setmode, int usemode,
                    622:     struct audio_params *play, struct audio_params *rec)
                    623: {
                    624:        int i;
                    625:        struct cmpci_softc *sc = handle;
                    626:
                    627:        for (i = 0; i < 2; i++) {
                    628:                int md_format;
                    629:                int md_divide;
                    630:                int md_index;
                    631:                int mode;
                    632:                struct audio_params *p;
                    633:
                    634:                switch (i) {
                    635:                case 0:
                    636:                        mode = AUMODE_PLAY;
                    637:                        p = play;
                    638:                        break;
                    639:                case 1:
                    640:                        mode = AUMODE_RECORD;
                    641:                        p = rec;
                    642:                        break;
                    643:                default:
                    644:                        return EINVAL;
                    645:                }
                    646:
                    647:                if (!(setmode & mode))
                    648:                        continue;
                    649:
                    650:                /* format */
                    651:                p->sw_code = NULL;
                    652:                switch (p->channels) {
                    653:                case 1:
                    654:                        md_format = CMPCI_REG_FORMAT_MONO;
                    655:                        break;
                    656:                case 2:
                    657:                        md_format = CMPCI_REG_FORMAT_STEREO;
                    658:                        break;
                    659:                default:
                    660:                        return (EINVAL);
                    661:                }
                    662:                switch (p->encoding) {
                    663:                case AUDIO_ENCODING_ULAW:
                    664:                        if (p->precision != 8)
                    665:                                return (EINVAL);
                    666:                        if (mode & AUMODE_PLAY) {
                    667:                                p->factor = 2;
                    668:                                p->sw_code = mulaw_to_slinear16_le;
                    669:                                md_format |= CMPCI_REG_FORMAT_16BIT;
                    670:                        } else {
                    671:                                p->sw_code = ulinear8_to_mulaw;
                    672:                                md_format |= CMPCI_REG_FORMAT_8BIT;
                    673:                        }
                    674:                        break;
                    675:                case AUDIO_ENCODING_ALAW:
                    676:                        if (p->precision != 8)
                    677:                                return (EINVAL);
                    678:                        if (mode & AUMODE_PLAY) {
                    679:                                p->factor = 2;
                    680:                                p->sw_code = alaw_to_slinear16_le;
                    681:                                md_format |= CMPCI_REG_FORMAT_16BIT;
                    682:                        } else {
                    683:                                p->sw_code = ulinear8_to_alaw;
                    684:                                md_format |= CMPCI_REG_FORMAT_8BIT;
                    685:                        }
                    686:                        break;
                    687:                case AUDIO_ENCODING_SLINEAR_LE:
                    688:                        switch (p->precision) {
                    689:                        case 8:
                    690:                                p->sw_code = change_sign8;
                    691:                                md_format |= CMPCI_REG_FORMAT_8BIT;
                    692:                                break;
                    693:                        case 16:
                    694:                                md_format |= CMPCI_REG_FORMAT_16BIT;
                    695:                                break;
                    696:                        default:
                    697:                                return (EINVAL);
                    698:                        }
                    699:                        break;
                    700:                case AUDIO_ENCODING_SLINEAR_BE:
                    701:                        switch (p->precision) {
                    702:                        case 8:
                    703:                                md_format |= CMPCI_REG_FORMAT_8BIT;
                    704:                                p->sw_code = change_sign8;
                    705:                                break;
                    706:                        case 16:
                    707:                                md_format |= CMPCI_REG_FORMAT_16BIT;
                    708:                                p->sw_code = swap_bytes;
                    709:                                break;
                    710:                        default:
                    711:                                return (EINVAL);
                    712:                        }
                    713:                        break;
                    714:                case AUDIO_ENCODING_ULINEAR_LE:
                    715:                        switch (p->precision) {
                    716:                        case 8:
                    717:                                md_format |= CMPCI_REG_FORMAT_8BIT;
                    718:                                break;
                    719:                        case 16:
                    720:                                md_format |= CMPCI_REG_FORMAT_16BIT;
                    721:                                p->sw_code = change_sign16_le;
                    722:                                break;
                    723:                        default:
                    724:                                return (EINVAL);
                    725:                        }
                    726:                        break;
                    727:                case AUDIO_ENCODING_ULINEAR_BE:
                    728:                        switch (p->precision) {
                    729:                        case 8:
                    730:                                md_format |= CMPCI_REG_FORMAT_8BIT;
                    731:                                break;
                    732:                        case 16:
                    733:                                md_format |= CMPCI_REG_FORMAT_16BIT;
                    734:                                if (mode & AUMODE_PLAY)
                    735:                                        p->sw_code =
                    736:                                            swap_bytes_change_sign16_le;
                    737:                                else
                    738:                                        p->sw_code =
                    739:                                            change_sign16_swap_bytes_le;
                    740:                                break;
                    741:                        default:
                    742:                                return (EINVAL);
                    743:                        }
                    744:                        break;
                    745:                default:
                    746:                        return (EINVAL);
                    747:                }
                    748:                if (mode & AUMODE_PLAY)
                    749:                        cmpci_reg_partial_write_4(sc,
                    750:                           CMPCI_REG_CHANNEL_FORMAT,
                    751:                           CMPCI_REG_CH0_FORMAT_SHIFT,
                    752:                           CMPCI_REG_CH0_FORMAT_MASK, md_format);
                    753:                else
                    754:                        cmpci_reg_partial_write_4(sc,
                    755:                           CMPCI_REG_CHANNEL_FORMAT,
                    756:                           CMPCI_REG_CH1_FORMAT_SHIFT,
                    757:                           CMPCI_REG_CH1_FORMAT_MASK, md_format);
                    758:                /* sample rate */
                    759:                md_index = cmpci_rate_to_index(p->sample_rate);
                    760:                md_divide = cmpci_index_to_divider(md_index);
                    761:                p->sample_rate = cmpci_index_to_rate(md_index);
                    762:                DPRINTF(("%s: sample:%d, divider=%d\n",
                    763:                         sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide));
                    764:                if (mode & AUMODE_PLAY) {
                    765:                        cmpci_reg_partial_write_4(sc,
                    766:                            CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT,
                    767:                            CMPCI_REG_DAC_FS_MASK, md_divide);
                    768:                        sc->sc_play.md_divide = md_divide;
                    769:                } else {
                    770:                        cmpci_reg_partial_write_4(sc,
                    771:                            CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
                    772:                            CMPCI_REG_ADC_FS_MASK, md_divide);
                    773:                        sc->sc_rec.md_divide = md_divide;
                    774:                }
                    775:                cmpci_set_out_ports(sc);
                    776:                cmpci_set_in_ports(sc);
                    777:        }
                    778:        return 0;
                    779: }
                    780:
                    781: /* ARGSUSED */
                    782: int
                    783: cmpci_round_blocksize(void *handle, int block)
                    784: {
                    785:        return ((block + 3) & -4);
                    786: }
                    787:
                    788: int
                    789: cmpci_halt_output(void *handle)
                    790: {
                    791:        struct cmpci_softc *sc = handle;
                    792:        int s;
                    793:
                    794:        s = splaudio();
                    795:        sc->sc_play.intr = NULL;
                    796:        cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
                    797:        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
                    798:        /* wait for reset DMA */
                    799:        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
                    800:        delay(10);
                    801:        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
                    802:        splx(s);
                    803:
                    804:        return 0;
                    805: }
                    806:
                    807: int
                    808: cmpci_halt_input(void *handle)
                    809: {
                    810:        struct cmpci_softc *sc = handle;
                    811:        int s;
                    812:
                    813:        s = splaudio();
                    814:        sc->sc_rec.intr = NULL;
                    815:        cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
                    816:        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
                    817:        /* wait for reset DMA */
                    818:        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
                    819:        delay(10);
                    820:        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
                    821:        splx(s);
                    822:
                    823:        return 0;
                    824: }
                    825:
                    826: /* get audio device information */
                    827: int
                    828: cmpci_getdev(void *handle, struct audio_device *ad)
                    829: {
                    830:        struct cmpci_softc *sc = handle;
                    831:
                    832:        strncpy(ad->name, "CMI PCI Audio", sizeof(ad->name));
                    833:        snprintf(ad->version, sizeof(ad->version), "0x%02x",
                    834:                 PCI_REVISION(sc->sc_class));
                    835:        switch (PCI_PRODUCT(sc->sc_id)) {
                    836:        case PCI_PRODUCT_CMI_CMI8338A:
                    837:                strncpy(ad->config, "CMI8338A", sizeof(ad->config));
                    838:                break;
                    839:        case PCI_PRODUCT_CMI_CMI8338B:
                    840:                strncpy(ad->config, "CMI8338B", sizeof(ad->config));
                    841:                break;
                    842:        case PCI_PRODUCT_CMI_CMI8738:
                    843:                strncpy(ad->config, "CMI8738", sizeof(ad->config));
                    844:                break;
                    845:        case PCI_PRODUCT_CMI_CMI8738B:
                    846:                strncpy(ad->config, "CMI8738B", sizeof(ad->config));
                    847:                break;
                    848:        default:
                    849:                strncpy(ad->config, "unknown", sizeof(ad->config));
                    850:        }
                    851:
                    852:        return 0;
                    853: }
                    854:
                    855: /* mixer device information */
                    856: int
                    857: cmpci_query_devinfo(void *handle, mixer_devinfo_t *dip)
                    858: {
                    859:        static const char *const mixer_port_names[] = {
                    860:                AudioNdac, AudioNfmsynth, AudioNcd, AudioNline, AudioNaux,
                    861:                AudioNmicrophone
                    862:        };
                    863:        static const char *const mixer_classes[] = {
                    864:                AudioCinputs, AudioCoutputs, AudioCrecord, CmpciCplayback,
                    865:                CmpciCspdif
                    866:        };
                    867:        struct cmpci_softc *sc = handle;
                    868:        int i;
                    869:
                    870:        dip->prev = dip->next = AUDIO_MIXER_LAST;
                    871:
                    872:        switch (dip->index) {
                    873:        case CMPCI_INPUT_CLASS:
                    874:        case CMPCI_OUTPUT_CLASS:
                    875:        case CMPCI_RECORD_CLASS:
                    876:        case CMPCI_PLAYBACK_CLASS:
                    877:        case CMPCI_SPDIF_CLASS:
                    878:                dip->type = AUDIO_MIXER_CLASS;
                    879:                dip->mixer_class = dip->index;
                    880:                strlcpy(dip->label.name,
                    881:                    mixer_classes[dip->index - CMPCI_INPUT_CLASS],
                    882:                    sizeof dip->label.name);
                    883:                return 0;
                    884:
                    885:        case CMPCI_AUX_IN_VOL:
                    886:                dip->un.v.delta = 1 << (8 - CMPCI_REG_AUX_VALBITS);
                    887:                goto vol1;
                    888:        case CMPCI_DAC_VOL:
                    889:        case CMPCI_FM_VOL:
                    890:        case CMPCI_CD_VOL:
                    891:        case CMPCI_LINE_IN_VOL:
                    892:        case CMPCI_MIC_VOL:
                    893:                dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS);
                    894:        vol1:   dip->mixer_class = CMPCI_INPUT_CLASS;
                    895:                dip->next = dip->index + 6;     /* CMPCI_xxx_MUTE */
                    896:                strlcpy(dip->label.name, mixer_port_names[dip->index],
                    897:                    sizeof dip->label.name);
                    898:                dip->un.v.num_channels = (dip->index == CMPCI_MIC_VOL ? 1 : 2);
                    899:        vol:
                    900:                dip->type = AUDIO_MIXER_VALUE;
                    901:                strlcpy(dip->un.v.units.name, AudioNvolume,
                    902:                    sizeof dip->un.v.units.name);
                    903:                return 0;
                    904:
                    905:        case CMPCI_MIC_MUTE:
                    906:                dip->next = CMPCI_MIC_PREAMP;
                    907:                /* FALLTHROUGH */
                    908:        case CMPCI_DAC_MUTE:
                    909:        case CMPCI_FM_MUTE:
                    910:        case CMPCI_CD_MUTE:
                    911:        case CMPCI_LINE_IN_MUTE:
                    912:        case CMPCI_AUX_IN_MUTE:
                    913:                dip->prev = dip->index - 6;     /* CMPCI_xxx_VOL */
                    914:                dip->mixer_class = CMPCI_INPUT_CLASS;
                    915:                strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
                    916:                goto on_off;
                    917:        on_off:
                    918:                dip->type = AUDIO_MIXER_ENUM;
                    919:                dip->un.e.num_mem = 2;
                    920:                strlcpy(dip->un.e.member[0].label.name, AudioNoff,
                    921:                    sizeof dip->un.e.member[0].label.name);
                    922:                dip->un.e.member[0].ord = 0;
                    923:                strlcpy(dip->un.e.member[1].label.name, AudioNon,
                    924:                    sizeof dip->un.e.member[1].label.name);
                    925:                dip->un.e.member[1].ord = 1;
                    926:                return 0;
                    927:
                    928:        case CMPCI_MIC_PREAMP:
                    929:                dip->mixer_class = CMPCI_INPUT_CLASS;
                    930:                dip->prev = CMPCI_MIC_MUTE;
                    931:                strlcpy(dip->label.name, AudioNpreamp, sizeof dip->label.name);
                    932:                goto on_off;
                    933:        case CMPCI_PCSPEAKER:
                    934:                dip->mixer_class = CMPCI_INPUT_CLASS;
                    935:                strlcpy(dip->label.name, AudioNspeaker, sizeof dip->label.name);
                    936:                dip->un.v.num_channels = 1;
                    937:                dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_SPEAKER_VALBITS);
                    938:                goto vol;
                    939:        case CMPCI_RECORD_SOURCE:
                    940:                dip->mixer_class = CMPCI_RECORD_CLASS;
                    941:                strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
                    942:                dip->type = AUDIO_MIXER_SET;
                    943:                dip->un.s.num_mem = 7;
                    944:                strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone,
                    945:                    sizeof dip->un.s.member[0].label.name);
                    946:                dip->un.s.member[0].mask = CMPCI_RECORD_SOURCE_MIC;
                    947:                strlcpy(dip->un.s.member[1].label.name, AudioNcd,
                    948:                    sizeof dip->un.s.member[1].label.name);
                    949:                dip->un.s.member[1].mask = CMPCI_RECORD_SOURCE_CD;
                    950:                strlcpy(dip->un.s.member[2].label.name, AudioNline,
                    951:                    sizeof dip->un.s.member[2].label.name);
                    952:                dip->un.s.member[2].mask = CMPCI_RECORD_SOURCE_LINE_IN;
                    953:                strlcpy(dip->un.s.member[3].label.name, AudioNaux,
                    954:                    sizeof dip->un.s.member[3].label.name);
                    955:                dip->un.s.member[3].mask = CMPCI_RECORD_SOURCE_AUX_IN;
                    956:                strlcpy(dip->un.s.member[4].label.name, AudioNwave,
                    957:                    sizeof dip->un.s.member[4].label.name);
                    958:                dip->un.s.member[4].mask = CMPCI_RECORD_SOURCE_WAVE;
                    959:                strlcpy(dip->un.s.member[5].label.name, AudioNfmsynth,
                    960:                    sizeof dip->un.s.member[5].label.name);
                    961:                dip->un.s.member[5].mask = CMPCI_RECORD_SOURCE_FM;
                    962:                strlcpy(dip->un.s.member[6].label.name, CmpciNspdif,
                    963:                    sizeof dip->un.s.member[6].label.name);
                    964:                dip->un.s.member[6].mask = CMPCI_RECORD_SOURCE_SPDIF;
                    965:                return 0;
                    966:        case CMPCI_MIC_RECVOL:
                    967:                dip->mixer_class = CMPCI_RECORD_CLASS;
                    968:                strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
                    969:                dip->un.v.num_channels = 1;
                    970:                dip->un.v.delta = 1 << (8 - CMPCI_REG_ADMIC_VALBITS);
                    971:                goto vol;
                    972:
                    973:        case CMPCI_PLAYBACK_MODE:
                    974:                dip->mixer_class = CMPCI_PLAYBACK_CLASS;
                    975:                dip->type = AUDIO_MIXER_ENUM;
                    976:                strlcpy(dip->label.name, AudioNmode, sizeof dip->label.name);
                    977:                dip->un.e.num_mem = 2;
                    978:                strlcpy(dip->un.e.member[0].label.name, AudioNdac,
                    979:                    sizeof dip->un.e.member[0].label.name);
                    980:                dip->un.e.member[0].ord = CMPCI_PLAYBACK_MODE_WAVE;
                    981:                strlcpy(dip->un.e.member[1].label.name, CmpciNspdif,
                    982:                    sizeof dip->un.e.member[1].label.name);
                    983:                dip->un.e.member[1].ord = CMPCI_PLAYBACK_MODE_SPDIF;
                    984:                return 0;
                    985:        case CMPCI_SPDIF_IN_SELECT:
                    986:                dip->mixer_class = CMPCI_SPDIF_CLASS;
                    987:                dip->type = AUDIO_MIXER_ENUM;
                    988:                dip->next = CMPCI_SPDIF_IN_PHASE;
                    989:                strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
                    990:                i = 0;
                    991:                strlcpy(dip->un.e.member[i].label.name, CmpciNspdin1,
                    992:                    sizeof dip->un.e.member[i].label.name);
                    993:                dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN1;
                    994:                if (CMPCI_ISCAP(sc, 2ND_SPDIN)) {
                    995:                        strlcpy(dip->un.e.member[i].label.name, CmpciNspdin2,
                    996:                            sizeof dip->un.e.member[i].label.name);
                    997:                        dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN2;
                    998:                }
                    999:                strlcpy(dip->un.e.member[i].label.name, CmpciNspdout,
                   1000:                    sizeof dip->un.e.member[i].label.name);
                   1001:                dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDOUT;
                   1002:                dip->un.e.num_mem = i;
                   1003:                return 0;
                   1004:        case CMPCI_SPDIF_IN_PHASE:
                   1005:                dip->mixer_class = CMPCI_SPDIF_CLASS;
                   1006:                dip->prev = CMPCI_SPDIF_IN_SELECT;
                   1007:                strlcpy(dip->label.name, CmpciNphase, sizeof dip->label.name);
                   1008:                dip->type = AUDIO_MIXER_ENUM;
                   1009:                dip->un.e.num_mem = 2;
                   1010:                strlcpy(dip->un.e.member[0].label.name, CmpciNpositive,
                   1011:                    sizeof dip->un.e.member[0].label.name);
                   1012:                dip->un.e.member[0].ord = CMPCI_SPDIF_IN_PHASE_POSITIVE;
                   1013:                strlcpy(dip->un.e.member[1].label.name, CmpciNnegative,
                   1014:                    sizeof dip->un.e.member[1].label.name);
                   1015:                dip->un.e.member[1].ord = CMPCI_SPDIF_IN_PHASE_NEGATIVE;
                   1016:                return 0;
                   1017:        case CMPCI_SPDIF_LOOP:
                   1018:                dip->mixer_class = CMPCI_SPDIF_CLASS;
                   1019:                dip->next = CMPCI_SPDIF_OUT_PLAYBACK;
                   1020:                strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
                   1021:                dip->type = AUDIO_MIXER_ENUM;
                   1022:                dip->un.e.num_mem = 2;
                   1023:                strlcpy(dip->un.e.member[0].label.name, CmpciNplayback,
                   1024:                    sizeof dip->un.e.member[0].label.name);
                   1025:                dip->un.e.member[0].ord = CMPCI_SPDIF_LOOP_OFF;
                   1026:                strlcpy(dip->un.e.member[1].label.name, CmpciNspdin,
                   1027:                    sizeof dip->un.e.member[1].label.name);
                   1028:                dip->un.e.member[1].ord = CMPCI_SPDIF_LOOP_ON;
                   1029:                return 0;
                   1030:        case CMPCI_SPDIF_OUT_PLAYBACK:
                   1031:                dip->mixer_class = CMPCI_SPDIF_CLASS;
                   1032:                dip->prev = CMPCI_SPDIF_LOOP;
                   1033:                dip->next = CMPCI_SPDIF_OUT_VOLTAGE;
                   1034:                strlcpy(dip->label.name, CmpciNplayback, sizeof dip->label.name);
                   1035:                dip->type = AUDIO_MIXER_ENUM;
                   1036:                dip->un.e.num_mem = 2;
                   1037:                strlcpy(dip->un.e.member[0].label.name, AudioNwave,
                   1038:                    sizeof dip->un.e.member[0].label.name);
                   1039:                dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_PLAYBACK_WAVE;
                   1040:                strlcpy(dip->un.e.member[1].label.name, CmpciNlegacy,
                   1041:                    sizeof dip->un.e.member[1].label.name);
                   1042:                dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_PLAYBACK_LEGACY;
                   1043:                return 0;
                   1044:        case CMPCI_SPDIF_OUT_VOLTAGE:
                   1045:                dip->mixer_class = CMPCI_SPDIF_CLASS;
                   1046:                dip->prev = CMPCI_SPDIF_OUT_PLAYBACK;
                   1047:                strlcpy(dip->label.name, CmpciNvoltage, sizeof dip->label.name);
                   1048:                dip->type = AUDIO_MIXER_ENUM;
                   1049:                dip->un.e.num_mem = 2;
                   1050:                strlcpy(dip->un.e.member[0].label.name, CmpciNhigh_v,
                   1051:                    sizeof dip->un.e.member[0].label.name);
                   1052:                dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_VOLTAGE_HIGH;
                   1053:                strlcpy(dip->un.e.member[1].label.name, CmpciNlow_v,
                   1054:                    sizeof dip->un.e.member[1].label.name);
                   1055:                dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_VOLTAGE_LOW;
                   1056:                return 0;
                   1057:        case CMPCI_MONITOR_DAC:
                   1058:                dip->mixer_class = CMPCI_SPDIF_CLASS;
                   1059:                strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
                   1060:                dip->type = AUDIO_MIXER_ENUM;
                   1061:                dip->un.e.num_mem = 3;
                   1062:                strlcpy(dip->un.e.member[0].label.name, AudioNoff,
                   1063:                    sizeof dip->un.e.member[0].label.name);
                   1064:                dip->un.e.member[0].ord = CMPCI_MONITOR_DAC_OFF;
                   1065:                strlcpy(dip->un.e.member[1].label.name, CmpciNspdin,
                   1066:                    sizeof dip->un.e.member[1].label.name);
                   1067:                dip->un.e.member[1].ord = CMPCI_MONITOR_DAC_SPDIN;
                   1068:                strlcpy(dip->un.e.member[2].label.name, CmpciNspdout,
                   1069:                    sizeof dip->un.e.member[2].label.name);
                   1070:                dip->un.e.member[2].ord = CMPCI_MONITOR_DAC_SPDOUT;
                   1071:                return 0;
                   1072:
                   1073:        case CMPCI_MASTER_VOL:
                   1074:                dip->mixer_class = CMPCI_OUTPUT_CLASS;
                   1075:                strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
                   1076:                dip->un.v.num_channels = 2;
                   1077:                dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS);
                   1078:                goto vol;
                   1079:        case CMPCI_REAR:
                   1080:                dip->mixer_class = CMPCI_OUTPUT_CLASS;
                   1081:                dip->next = CMPCI_INDIVIDUAL;
                   1082:                strlcpy(dip->label.name, CmpciNrear, sizeof dip->label.name);
                   1083:                goto on_off;
                   1084:        case CMPCI_INDIVIDUAL:
                   1085:                dip->mixer_class = CMPCI_OUTPUT_CLASS;
                   1086:                dip->prev = CMPCI_REAR;
                   1087:                dip->next = CMPCI_REVERSE;
                   1088:                strlcpy(dip->label.name, CmpciNindividual, sizeof dip->label.name);
                   1089:                goto on_off;
                   1090:        case CMPCI_REVERSE:
                   1091:                dip->mixer_class = CMPCI_OUTPUT_CLASS;
                   1092:                dip->prev = CMPCI_INDIVIDUAL;
                   1093:                strlcpy(dip->label.name, CmpciNreverse, sizeof dip->label.name);
                   1094:                goto on_off;
                   1095:        case CMPCI_SURROUND:
                   1096:                dip->mixer_class = CMPCI_OUTPUT_CLASS;
                   1097:                strlcpy(dip->label.name, CmpciNsurround, sizeof dip->label.name);
                   1098:                goto on_off;
                   1099:        }
                   1100:
                   1101:        return ENXIO;
                   1102: }
                   1103:
                   1104: int
                   1105: cmpci_alloc_dmamem(struct cmpci_softc *sc, size_t size, int type, int flags,
                   1106:     caddr_t *r_addr)
                   1107: {
                   1108:        int error = 0;
                   1109:        struct cmpci_dmanode *n;
                   1110:        int w;
                   1111:
                   1112:        n = malloc(sizeof(struct cmpci_dmanode), type, flags);
                   1113:        if (n == NULL) {
                   1114:                error = ENOMEM;
                   1115:                goto quit;
                   1116:        }
                   1117:
                   1118:        w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
                   1119: #define CMPCI_DMABUF_ALIGN    0x4
                   1120: #define CMPCI_DMABUF_BOUNDARY 0x0
                   1121:        n->cd_tag = sc->sc_dmat;
                   1122:        n->cd_size = size;
                   1123:        error = bus_dmamem_alloc(n->cd_tag, n->cd_size,
                   1124:            CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, n->cd_segs,
                   1125:            sizeof(n->cd_segs)/sizeof(n->cd_segs[0]), &n->cd_nsegs, w);
                   1126:        if (error)
                   1127:                goto mfree;
                   1128:        error = bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size,
                   1129:            &n->cd_addr, w | BUS_DMA_COHERENT);
                   1130:        if (error)
                   1131:                goto dmafree;
                   1132:        error = bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0,
                   1133:            w, &n->cd_map);
                   1134:        if (error)
                   1135:                goto unmap;
                   1136:        error = bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size,
                   1137:            NULL, w);
                   1138:        if (error)
                   1139:                goto destroy;
                   1140:
                   1141:        n->cd_next = sc->sc_dmap;
                   1142:        sc->sc_dmap = n;
                   1143:        *r_addr = KVADDR(n);
                   1144:        return 0;
                   1145:
                   1146:  destroy:
                   1147:        bus_dmamap_destroy(n->cd_tag, n->cd_map);
                   1148:  unmap:
                   1149:        bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
                   1150:  dmafree:
                   1151:        bus_dmamem_free(n->cd_tag,
                   1152:                        n->cd_segs, sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
                   1153:  mfree:
                   1154:        free(n, type);
                   1155:  quit:
                   1156:        return error;
                   1157: }
                   1158:
                   1159: int
                   1160: cmpci_free_dmamem(struct cmpci_softc *sc, caddr_t addr, int type)
                   1161: {
                   1162:        struct cmpci_dmanode **nnp;
                   1163:
                   1164:        for (nnp = &sc->sc_dmap; *nnp; nnp = &(*nnp)->cd_next) {
                   1165:                if ((*nnp)->cd_addr == addr) {
                   1166:                        struct cmpci_dmanode *n = *nnp;
                   1167:                        bus_dmamap_unload(n->cd_tag, n->cd_map);
                   1168:                        bus_dmamap_destroy(n->cd_tag, n->cd_map);
                   1169:                        bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
                   1170:                        bus_dmamem_free(n->cd_tag, n->cd_segs,
                   1171:                            sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
                   1172:                        free(n, type);
                   1173:                        return 0;
                   1174:                }
                   1175:        }
                   1176:        return -1;
                   1177: }
                   1178:
                   1179: struct cmpci_dmanode *
                   1180: cmpci_find_dmamem(struct cmpci_softc *sc, caddr_t addr)
                   1181: {
                   1182:        struct cmpci_dmanode *p;
                   1183:
                   1184:        for (p = sc->sc_dmap; p; p = p->cd_next) {
                   1185:                if (KVADDR(p) == (void *)addr)
                   1186:                        break;
                   1187:        }
                   1188:        return p;
                   1189: }
                   1190:
                   1191: #if 0
                   1192: void cmpci_print_dmamem(struct cmpci_dmanode *p);
                   1193:
                   1194: void
                   1195: cmpci_print_dmamem(struct cmpci_dmanode *p)
                   1196: {
                   1197:        DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n",
                   1198:                 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr,
                   1199:                 (void *)DMAADDR(p), (void *)p->cd_size));
                   1200: }
                   1201: #endif /* DEBUG */
                   1202:
                   1203: void *
                   1204: cmpci_malloc(void *handle, int direction, size_t size, int type,
                   1205:     int flags)
                   1206: {
                   1207:        caddr_t addr;
                   1208:
                   1209:        if (cmpci_alloc_dmamem(handle, size, type, flags, &addr))
                   1210:                return NULL;
                   1211:        return addr;
                   1212: }
                   1213:
                   1214: void
                   1215: cmpci_free(void *handle, void *addr, int type)
                   1216: {
                   1217:        cmpci_free_dmamem(handle, addr, type);
                   1218: }
                   1219:
                   1220: #define MAXVAL 256
                   1221: int
                   1222: cmpci_adjust(int val, int mask)
                   1223: {
                   1224:        val += (MAXVAL - mask) >> 1;
                   1225:        if (val >= MAXVAL)
                   1226:                val = MAXVAL-1;
                   1227:        return val & mask;
                   1228: }
                   1229:
                   1230: void
                   1231: cmpci_set_mixer_gain(struct cmpci_softc *sc, int port)
                   1232: {
                   1233:        int src;
                   1234:        int bits, mask;
                   1235:
                   1236:        switch (port) {
                   1237:        case CMPCI_MIC_VOL:
                   1238:                cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_MIC,
                   1239:                    CMPCI_ADJUST_MIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
                   1240:                return;
                   1241:        case CMPCI_MASTER_VOL:
                   1242:                src = CMPCI_SB16_MIXER_MASTER_L;
                   1243:                break;
                   1244:        case CMPCI_LINE_IN_VOL:
                   1245:                src = CMPCI_SB16_MIXER_LINE_L;
                   1246:                break;
                   1247:        case CMPCI_AUX_IN_VOL:
                   1248:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MIXER_AUX,
                   1249:                    CMPCI_ADJUST_AUX_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT],
                   1250:                                              sc->sc_gain[port][CMPCI_RIGHT]));
                   1251:                return;
                   1252:        case CMPCI_MIC_RECVOL:
                   1253:                cmpci_reg_partial_write_1(sc, CMPCI_REG_MIXER25,
                   1254:                    CMPCI_REG_ADMIC_SHIFT, CMPCI_REG_ADMIC_MASK,
                   1255:                    CMPCI_ADJUST_ADMIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
                   1256:                return;
                   1257:        case CMPCI_DAC_VOL:
                   1258:                src = CMPCI_SB16_MIXER_VOICE_L;
                   1259:                break;
                   1260:        case CMPCI_FM_VOL:
                   1261:                src = CMPCI_SB16_MIXER_FM_L;
                   1262:                break;
                   1263:        case CMPCI_CD_VOL:
                   1264:                src = CMPCI_SB16_MIXER_CDDA_L;
                   1265:                break;
                   1266:        case CMPCI_PCSPEAKER:
                   1267:                cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER,
                   1268:                    CMPCI_ADJUST_2_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
                   1269:                return;
                   1270:        case CMPCI_MIC_PREAMP:
                   1271:                if (sc->sc_gain[port][CMPCI_LR])
                   1272:                        cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
                   1273:                            CMPCI_REG_MICGAINZ);
                   1274:                else
                   1275:                        cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
                   1276:                            CMPCI_REG_MICGAINZ);
                   1277:                return;
                   1278:
                   1279:        case CMPCI_DAC_MUTE:
                   1280:                if (sc->sc_gain[port][CMPCI_LR])
                   1281:                        cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
                   1282:                            CMPCI_REG_WSMUTE);
                   1283:                else
                   1284:                        cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
                   1285:                            CMPCI_REG_WSMUTE);
                   1286:                return;
                   1287:        case CMPCI_FM_MUTE:
                   1288:                if (sc->sc_gain[port][CMPCI_LR])
                   1289:                        cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
                   1290:                            CMPCI_REG_FMMUTE);
                   1291:                else
                   1292:                        cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
                   1293:                            CMPCI_REG_FMMUTE);
                   1294:                return;
                   1295:        case CMPCI_AUX_IN_MUTE:
                   1296:                if (sc->sc_gain[port][CMPCI_LR])
                   1297:                        cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
                   1298:                            CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM);
                   1299:                else
                   1300:                        cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
                   1301:                            CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM);
                   1302:                return;
                   1303:        case CMPCI_CD_MUTE:
                   1304:                mask = CMPCI_SB16_SW_CD;
                   1305:                goto sbmute;
                   1306:        case CMPCI_MIC_MUTE:
                   1307:                mask = CMPCI_SB16_SW_MIC;
                   1308:                goto sbmute;
                   1309:        case CMPCI_LINE_IN_MUTE:
                   1310:                mask = CMPCI_SB16_SW_LINE;
                   1311:        sbmute:
                   1312:                bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX);
                   1313:                if (sc->sc_gain[port][CMPCI_LR])
                   1314:                        bits = bits & ~mask;
                   1315:                else
                   1316:                        bits = bits | mask;
                   1317:                cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits);
                   1318:                return;
                   1319:
                   1320:        case CMPCI_SPDIF_IN_SELECT:
                   1321:        case CMPCI_MONITOR_DAC:
                   1322:        case CMPCI_PLAYBACK_MODE:
                   1323:        case CMPCI_SPDIF_LOOP:
                   1324:        case CMPCI_SPDIF_OUT_PLAYBACK:
                   1325:                cmpci_set_out_ports(sc);
                   1326:                return;
                   1327:        case CMPCI_SPDIF_OUT_VOLTAGE:
                   1328:                if (CMPCI_ISCAP(sc, SPDOUT_VOLTAGE)) {
                   1329:                        if (sc->sc_gain[CMPCI_SPDIF_OUT_VOLTAGE][CMPCI_LR]
                   1330:                            == CMPCI_SPDIF_OUT_VOLTAGE_HIGH)
                   1331:                                cmpci_reg_clear_reg_misc(sc, CMPCI_REG_5V);
                   1332:                        else
                   1333:                                cmpci_reg_set_reg_misc(sc, CMPCI_REG_5V);
                   1334:                }
                   1335:                return;
                   1336:        case CMPCI_SURROUND:
                   1337:                if (CMPCI_ISCAP(sc, SURROUND)) {
                   1338:                        if (sc->sc_gain[CMPCI_SURROUND][CMPCI_LR])
                   1339:                                cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
                   1340:                                                CMPCI_REG_SURROUND);
                   1341:                        else
                   1342:                                cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
                   1343:                                                  CMPCI_REG_SURROUND);
                   1344:                }
                   1345:                return;
                   1346:        case CMPCI_REAR:
                   1347:                if (CMPCI_ISCAP(sc, REAR)) {
                   1348:                        if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
                   1349:                                cmpci_reg_set_reg_misc(sc, CMPCI_REG_N4SPK3D);
                   1350:                        else
                   1351:                                cmpci_reg_clear_reg_misc(sc, CMPCI_REG_N4SPK3D);
                   1352:                }
                   1353:                return;
                   1354:        case CMPCI_INDIVIDUAL:
                   1355:                if (CMPCI_ISCAP(sc, INDIVIDUAL_REAR)) {
                   1356:                        if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
                   1357:                                cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
                   1358:                                                CMPCI_REG_INDIVIDUAL);
                   1359:                        else
                   1360:                                cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
                   1361:                                                  CMPCI_REG_INDIVIDUAL);
                   1362:                }
                   1363:                return;
                   1364:        case CMPCI_REVERSE:
                   1365:                if (CMPCI_ISCAP(sc, REVERSE_FR)) {
                   1366:                        if (sc->sc_gain[CMPCI_REVERSE][CMPCI_LR])
                   1367:                                cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
                   1368:                                                CMPCI_REG_REVERSE_FR);
                   1369:                        else
                   1370:                                cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
                   1371:                                                  CMPCI_REG_REVERSE_FR);
                   1372:                }
                   1373:                return;
                   1374:        case CMPCI_SPDIF_IN_PHASE:
                   1375:                if (CMPCI_ISCAP(sc, SPDIN_PHASE)) {
                   1376:                        if (sc->sc_gain[CMPCI_SPDIF_IN_PHASE][CMPCI_LR]
                   1377:                            == CMPCI_SPDIF_IN_PHASE_POSITIVE)
                   1378:                                cmpci_reg_clear_1(sc, CMPCI_REG_CHANNEL_FORMAT,
                   1379:                                                  CMPCI_REG_SPDIN_PHASE);
                   1380:                        else
                   1381:                                cmpci_reg_set_1(sc, CMPCI_REG_CHANNEL_FORMAT,
                   1382:                                                CMPCI_REG_SPDIN_PHASE);
                   1383:                }
                   1384:                return;
                   1385:        default:
                   1386:                return;
                   1387:        }
                   1388:
                   1389:        cmpci_mixerreg_write(sc, src,
                   1390:            CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT]));
                   1391:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src),
                   1392:            CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_RIGHT]));
                   1393: }
                   1394:
                   1395: void
                   1396: cmpci_set_out_ports(struct cmpci_softc *sc)
                   1397: {
                   1398:        u_int8_t v;
                   1399:        int enspdout = 0;
                   1400:
                   1401:        if (!CMPCI_ISCAP(sc, SPDLOOP))
                   1402:                return;
                   1403:
                   1404:        /* SPDIF/out select */
                   1405:        if (sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR] == CMPCI_SPDIF_LOOP_OFF) {
                   1406:                /* playback */
                   1407:                cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
                   1408:        } else {
                   1409:                /* monitor SPDIF/in */
                   1410:                cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
                   1411:        }
                   1412:
                   1413:        /* SPDIF in select */
                   1414:        v = sc->sc_gain[CMPCI_SPDIF_IN_SELECT][CMPCI_LR];
                   1415:        if (v & CMPCI_SPDIFIN_SPDIFIN2)
                   1416:                cmpci_reg_set_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN);
                   1417:        else
                   1418:                cmpci_reg_clear_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN);
                   1419:        if (v & CMPCI_SPDIFIN_SPDIFOUT)
                   1420:                cmpci_reg_set_reg_misc(sc, CMPCI_REG_SPDFLOOPI);
                   1421:        else
                   1422:                cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPDFLOOPI);
                   1423:
                   1424:        /* playback to ... */
                   1425:        if (CMPCI_ISCAP(sc, SPDOUT) &&
                   1426:            sc->sc_gain[CMPCI_PLAYBACK_MODE][CMPCI_LR]
                   1427:                == CMPCI_PLAYBACK_MODE_SPDIF &&
                   1428:            (sc->sc_play.md_divide == CMPCI_REG_RATE_44100 ||
                   1429:                (CMPCI_ISCAP(sc, SPDOUT_48K) &&
                   1430:                    sc->sc_play.md_divide==CMPCI_REG_RATE_48000))) {
                   1431:                /* playback to SPDIF */
                   1432:                cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF0_ENABLE);
                   1433:                enspdout = 1;
                   1434:                if (sc->sc_play.md_divide==CMPCI_REG_RATE_48000)
                   1435:                        cmpci_reg_set_reg_misc(sc,
                   1436:                                CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
                   1437:                else
                   1438:                        cmpci_reg_clear_reg_misc(sc,
                   1439:                                CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
                   1440:        } else {
                   1441:                /* playback to DAC */
                   1442:                cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
                   1443:                                  CMPCI_REG_SPDIF0_ENABLE);
                   1444:                if (CMPCI_ISCAP(sc, SPDOUT_48K))
                   1445:                        cmpci_reg_clear_reg_misc(sc,
                   1446:                                CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
                   1447:        }
                   1448:
                   1449:        /* legacy to SPDIF/out or not */
                   1450:        if (CMPCI_ISCAP(sc, SPDLEGACY)) {
                   1451:                if (sc->sc_gain[CMPCI_SPDIF_OUT_PLAYBACK][CMPCI_LR]
                   1452:                    == CMPCI_SPDIF_OUT_PLAYBACK_WAVE)
                   1453:                        cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
                   1454:                                        CMPCI_REG_LEGACY_SPDIF_ENABLE);
                   1455:                else {
                   1456:                        cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
                   1457:                                        CMPCI_REG_LEGACY_SPDIF_ENABLE);
                   1458:                        enspdout = 1;
                   1459:                }
                   1460:        }
                   1461:
                   1462:        /* enable/disable SPDIF/out */
                   1463:        if (CMPCI_ISCAP(sc, XSPDOUT) && enspdout)
                   1464:                cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
                   1465:                                CMPCI_REG_XSPDIF_ENABLE);
                   1466:        else
                   1467:                cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
                   1468:                                CMPCI_REG_XSPDIF_ENABLE);
                   1469:
                   1470:        /* SPDIF monitor (digital to analog output) */
                   1471:        if (CMPCI_ISCAP(sc, SPDIN_MONITOR)) {
                   1472:                v = sc->sc_gain[CMPCI_MONITOR_DAC][CMPCI_LR];
                   1473:                if (!(v & CMPCI_MONDAC_ENABLE))
                   1474:                        cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
                   1475:                                        CMPCI_REG_SPDIN_MONITOR);
                   1476:                if (v & CMPCI_MONDAC_SPDOUT)
                   1477:                        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
                   1478:                                        CMPCI_REG_SPDIFOUT_DAC);
                   1479:                else
                   1480:                        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
                   1481:                                        CMPCI_REG_SPDIFOUT_DAC);
                   1482:                if (v & CMPCI_MONDAC_ENABLE)
                   1483:                        cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
                   1484:                                        CMPCI_REG_SPDIN_MONITOR);
                   1485:        }
                   1486: }
                   1487:
                   1488: int
                   1489: cmpci_set_in_ports(struct cmpci_softc *sc)
                   1490: {
                   1491:        int mask;
                   1492:        int bitsl, bitsr;
                   1493:
                   1494:        mask = sc->sc_in_mask;
                   1495:
                   1496:        /*
                   1497:         * Note CMPCI_RECORD_SOURCE_CD, CMPCI_RECORD_SOURCE_LINE_IN and
                   1498:         * CMPCI_RECORD_SOURCE_FM are defined to the corresponding bit
                   1499:         * of the mixer register.
                   1500:         */
                   1501:        bitsr = mask & (CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN |
                   1502:            CMPCI_RECORD_SOURCE_FM);
                   1503:
                   1504:        bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr);
                   1505:        if (mask & CMPCI_RECORD_SOURCE_MIC) {
                   1506:                bitsl |= CMPCI_SB16_MIXER_MIC_SRC;
                   1507:                bitsr |= CMPCI_SB16_MIXER_MIC_SRC;
                   1508:        }
                   1509:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl);
                   1510:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr);
                   1511:
                   1512:        if (mask & CMPCI_RECORD_SOURCE_AUX_IN)
                   1513:                cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
                   1514:                    CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN);
                   1515:        else
                   1516:                cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
                   1517:                    CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN);
                   1518:
                   1519:        if (mask & CMPCI_RECORD_SOURCE_WAVE)
                   1520:                cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
                   1521:                    CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR);
                   1522:        else
                   1523:                cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
                   1524:                    CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR);
                   1525:
                   1526:        if (CMPCI_ISCAP(sc, SPDIN) &&
                   1527:            (sc->sc_rec.md_divide == CMPCI_REG_RATE_44100 ||
                   1528:                (CMPCI_ISCAP(sc, SPDOUT_48K) &&
                   1529:                    sc->sc_rec.md_divide == CMPCI_REG_RATE_48000/* XXX? */))) {
                   1530:                if (mask & CMPCI_RECORD_SOURCE_SPDIF) {
                   1531:                        /* enable SPDIF/in */
                   1532:                        cmpci_reg_set_4(sc,
                   1533:                                        CMPCI_REG_FUNC_1,
                   1534:                                        CMPCI_REG_SPDIF1_ENABLE);
                   1535:                } else {
                   1536:                        cmpci_reg_clear_4(sc,
                   1537:                                        CMPCI_REG_FUNC_1,
                   1538:                                        CMPCI_REG_SPDIF1_ENABLE);
                   1539:                }
                   1540:        }
                   1541:
                   1542:        return 0;
                   1543: }
                   1544:
                   1545: int
                   1546: cmpci_set_port(void *handle, mixer_ctrl_t *cp)
                   1547: {
                   1548:        struct cmpci_softc *sc = handle;
                   1549:        int lgain, rgain;
                   1550:
                   1551:        switch (cp->dev) {
                   1552:        case CMPCI_MIC_VOL:
                   1553:        case CMPCI_PCSPEAKER:
                   1554:        case CMPCI_MIC_RECVOL:
                   1555:                if (cp->un.value.num_channels != 1)
                   1556:                        return EINVAL;
                   1557:                /* FALLTHROUGH */
                   1558:        case CMPCI_DAC_VOL:
                   1559:        case CMPCI_FM_VOL:
                   1560:        case CMPCI_CD_VOL:
                   1561:        case CMPCI_LINE_IN_VOL:
                   1562:        case CMPCI_AUX_IN_VOL:
                   1563:        case CMPCI_MASTER_VOL:
                   1564:                if (cp->type != AUDIO_MIXER_VALUE)
                   1565:                        return EINVAL;
                   1566:                switch (cp->un.value.num_channels) {
                   1567:                case 1:
                   1568:                        lgain = rgain =
                   1569:                            cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
                   1570:                        break;
                   1571:                case 2:
                   1572:                        lgain = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
                   1573:                        rgain = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                   1574:                        break;
                   1575:                default:
                   1576:                        return EINVAL;
                   1577:                }
                   1578:                sc->sc_gain[cp->dev][CMPCI_LEFT]  = lgain;
                   1579:                sc->sc_gain[cp->dev][CMPCI_RIGHT] = rgain;
                   1580:
                   1581:                cmpci_set_mixer_gain(sc, cp->dev);
                   1582:                break;
                   1583:
                   1584:        case CMPCI_RECORD_SOURCE:
                   1585:                if (cp->type != AUDIO_MIXER_SET)
                   1586:                        return EINVAL;
                   1587:
                   1588:                if (cp->un.mask & ~(CMPCI_RECORD_SOURCE_MIC |
                   1589:                    CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN |
                   1590:                    CMPCI_RECORD_SOURCE_AUX_IN | CMPCI_RECORD_SOURCE_WAVE |
                   1591:                    CMPCI_RECORD_SOURCE_FM | CMPCI_RECORD_SOURCE_SPDIF))
                   1592:                        return EINVAL;
                   1593:
                   1594:                if (cp->un.mask & CMPCI_RECORD_SOURCE_SPDIF)
                   1595:                        cp->un.mask = CMPCI_RECORD_SOURCE_SPDIF;
                   1596:
                   1597:                sc->sc_in_mask = cp->un.mask;
                   1598:                return cmpci_set_in_ports(sc);
                   1599:
                   1600:        /* boolean */
                   1601:        case CMPCI_DAC_MUTE:
                   1602:        case CMPCI_FM_MUTE:
                   1603:        case CMPCI_CD_MUTE:
                   1604:        case CMPCI_LINE_IN_MUTE:
                   1605:        case CMPCI_AUX_IN_MUTE:
                   1606:        case CMPCI_MIC_MUTE:
                   1607:        case CMPCI_MIC_PREAMP:
                   1608:        case CMPCI_PLAYBACK_MODE:
                   1609:        case CMPCI_SPDIF_IN_PHASE:
                   1610:        case CMPCI_SPDIF_LOOP:
                   1611:        case CMPCI_SPDIF_OUT_PLAYBACK:
                   1612:        case CMPCI_SPDIF_OUT_VOLTAGE:
                   1613:        case CMPCI_REAR:
                   1614:        case CMPCI_INDIVIDUAL:
                   1615:        case CMPCI_REVERSE:
                   1616:        case CMPCI_SURROUND:
                   1617:                if (cp->type != AUDIO_MIXER_ENUM)
                   1618:                        return EINVAL;
                   1619:                sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
                   1620:                cmpci_set_mixer_gain(sc, cp->dev);
                   1621:                break;
                   1622:
                   1623:        case CMPCI_SPDIF_IN_SELECT:
                   1624:                switch (cp->un.ord) {
                   1625:                case CMPCI_SPDIF_IN_SPDIN1:
                   1626:                case CMPCI_SPDIF_IN_SPDIN2:
                   1627:                case CMPCI_SPDIF_IN_SPDOUT:
                   1628:                        break;
                   1629:                default:
                   1630:                        return EINVAL;
                   1631:                }
                   1632:                goto xenum;
                   1633:        case CMPCI_MONITOR_DAC:
                   1634:                switch (cp->un.ord) {
                   1635:                case CMPCI_MONITOR_DAC_OFF:
                   1636:                case CMPCI_MONITOR_DAC_SPDIN:
                   1637:                case CMPCI_MONITOR_DAC_SPDOUT:
                   1638:                        break;
                   1639:                default:
                   1640:                        return EINVAL;
                   1641:                }
                   1642:        xenum:
                   1643:                if (cp->type != AUDIO_MIXER_ENUM)
                   1644:                        return EINVAL;
                   1645:                sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord;
                   1646:                cmpci_set_mixer_gain(sc, cp->dev);
                   1647:                break;
                   1648:
                   1649:        default:
                   1650:            return EINVAL;
                   1651:        }
                   1652:
                   1653:        return 0;
                   1654: }
                   1655:
                   1656: int
                   1657: cmpci_get_port(void *handle, mixer_ctrl_t *cp)
                   1658: {
                   1659:        struct cmpci_softc *sc = handle;
                   1660:
                   1661:        switch (cp->dev) {
                   1662:        case CMPCI_MIC_VOL:
                   1663:        case CMPCI_PCSPEAKER:
                   1664:        case CMPCI_MIC_RECVOL:
                   1665:                if (cp->un.value.num_channels != 1)
                   1666:                        return EINVAL;
                   1667:                /*FALLTHROUGH*/
                   1668:        case CMPCI_DAC_VOL:
                   1669:        case CMPCI_FM_VOL:
                   1670:        case CMPCI_CD_VOL:
                   1671:        case CMPCI_LINE_IN_VOL:
                   1672:        case CMPCI_AUX_IN_VOL:
                   1673:        case CMPCI_MASTER_VOL:
                   1674:                switch (cp->un.value.num_channels) {
                   1675:                case 1:
                   1676:                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
                   1677:                                sc->sc_gain[cp->dev][CMPCI_LEFT];
                   1678:                        break;
                   1679:                case 2:
                   1680:                        cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
                   1681:                                sc->sc_gain[cp->dev][CMPCI_LEFT];
                   1682:                        cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
                   1683:                                sc->sc_gain[cp->dev][CMPCI_RIGHT];
                   1684:                        break;
                   1685:                default:
                   1686:                        return EINVAL;
                   1687:                }
                   1688:                break;
                   1689:
                   1690:        case CMPCI_RECORD_SOURCE:
                   1691:                cp->un.mask = sc->sc_in_mask;
                   1692:                break;
                   1693:
                   1694:        case CMPCI_DAC_MUTE:
                   1695:        case CMPCI_FM_MUTE:
                   1696:        case CMPCI_CD_MUTE:
                   1697:        case CMPCI_LINE_IN_MUTE:
                   1698:        case CMPCI_AUX_IN_MUTE:
                   1699:        case CMPCI_MIC_MUTE:
                   1700:        case CMPCI_MIC_PREAMP:
                   1701:        case CMPCI_PLAYBACK_MODE:
                   1702:        case CMPCI_SPDIF_IN_SELECT:
                   1703:        case CMPCI_SPDIF_IN_PHASE:
                   1704:        case CMPCI_SPDIF_LOOP:
                   1705:        case CMPCI_SPDIF_OUT_PLAYBACK:
                   1706:        case CMPCI_SPDIF_OUT_VOLTAGE:
                   1707:        case CMPCI_MONITOR_DAC:
                   1708:        case CMPCI_REAR:
                   1709:        case CMPCI_INDIVIDUAL:
                   1710:        case CMPCI_REVERSE:
                   1711:        case CMPCI_SURROUND:
                   1712:                cp->un.ord = sc->sc_gain[cp->dev][CMPCI_LR];
                   1713:                break;
                   1714:
                   1715:        default:
                   1716:                return EINVAL;
                   1717:        }
                   1718:
                   1719:        return 0;
                   1720: }
                   1721:
                   1722: /* ARGSUSED */
                   1723: size_t
                   1724: cmpci_round_buffersize(void *handle, int direction, size_t bufsize)
                   1725: {
                   1726:        if (bufsize > 0x10000)
                   1727:                bufsize = 0x10000;
                   1728:
                   1729:        return bufsize;
                   1730: }
                   1731:
                   1732: paddr_t
                   1733: cmpci_mappage(void *handle, void *addr, off_t offset, int prot)
                   1734: {
                   1735:        struct cmpci_softc *sc = handle;
                   1736:        struct cmpci_dmanode *p;
                   1737:
                   1738:        if (offset < 0 || NULL == (p = cmpci_find_dmamem(sc, addr)))
                   1739:                return -1;
                   1740:
                   1741:        return bus_dmamem_mmap(p->cd_tag, p->cd_segs,
                   1742:                   sizeof(p->cd_segs)/sizeof(p->cd_segs[0]),
                   1743:                   offset, prot, BUS_DMA_WAITOK);
                   1744: }
                   1745:
                   1746: /* ARGSUSED */
                   1747: int
                   1748: cmpci_get_props(void *handle)
                   1749: {
                   1750:        return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
                   1751: }
                   1752:
                   1753: int
                   1754: cmpci_trigger_output(void *handle, void *start, void *end, int blksize,
                   1755:     void (*intr)(void *), void *arg, struct audio_params *param)
                   1756: {
                   1757:        struct cmpci_softc *sc = handle;
                   1758:        struct cmpci_dmanode *p;
                   1759:        int bps;
                   1760:
                   1761:        sc->sc_play.intr = intr;
                   1762:        sc->sc_play.intr_arg = arg;
                   1763:        bps = param->channels * param->precision * param->factor / 8;
                   1764:        if (!bps)
                   1765:                return EINVAL;
                   1766:
                   1767:        /* set DMA frame */
                   1768:        if (!(p = cmpci_find_dmamem(sc, start)))
                   1769:                return EINVAL;
                   1770:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BASE,
                   1771:            DMAADDR(p));
                   1772:        delay(10);
                   1773:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BYTES,
                   1774:            ((caddr_t)end - (caddr_t)start + 1) / bps - 1);
                   1775:        delay(10);
                   1776:
                   1777:        /* set interrupt count */
                   1778:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_SAMPLES,
                   1779:                          (blksize + bps - 1) / bps - 1);
                   1780:        delay(10);
                   1781:
                   1782:        /* start DMA */
                   1783:        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); /* PLAY */
                   1784:        cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
                   1785:        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
                   1786:
                   1787:        return 0;
                   1788: }
                   1789:
                   1790: int
                   1791: cmpci_trigger_input(void *handle, void *start, void *end, int blksize,
                   1792:     void (*intr)(void *), void *arg, struct audio_params *param)
                   1793: {
                   1794:        struct cmpci_softc *sc = handle;
                   1795:        struct cmpci_dmanode *p;
                   1796:        int bps;
                   1797:
                   1798:        sc->sc_rec.intr = intr;
                   1799:        sc->sc_rec.intr_arg = arg;
                   1800:        bps = param->channels*param->precision*param->factor/8;
                   1801:        if (!bps)
                   1802:                return EINVAL;
                   1803:
                   1804:        /* set DMA frame */
                   1805:        if (!(p = cmpci_find_dmamem(sc, start)))
                   1806:                return EINVAL;
                   1807:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE,
                   1808:            DMAADDR(p));
                   1809:        delay(10);
                   1810:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES,
                   1811:            ((caddr_t)end - (caddr_t)start + 1) / bps - 1);
                   1812:        delay(10);
                   1813:
                   1814:        /* set interrupt count */
                   1815:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES,
                   1816:            (blksize + bps - 1) / bps - 1);
                   1817:        delay(10);
                   1818:
                   1819:        /* start DMA */
                   1820:        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */
                   1821:        cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
                   1822:        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
                   1823:
                   1824:        return 0;
                   1825: }
                   1826:
                   1827: /* end of file */

CVSweb