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

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

1.1       nbrk        1: /*     $OpenBSD: auich.c,v 1.64 2007/08/02 07:43:41 jakemsr Exp $      */
                      2:
                      3: /*
                      4:  * Copyright (c) 2000,2001 Michael Shalayeff
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     24:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
                     25:  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     26:  * THE POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: /* #define     AUICH_DEBUG */
                     30: /*
                     31:  * AC'97 audio found on Intel 810/815/820/440MX chipsets.
                     32:  *     http://developer.intel.com/design/chipsets/datashts/290655.htm
                     33:  *     http://developer.intel.com/design/chipsets/manuals/298028.htm
                     34:  *     http://www.intel.com/design/chipsets/datashts/290716.htm
                     35:  *     http://www.intel.com/design/chipsets/datashts/290744.htm
                     36:  */
                     37:
                     38: #include <sys/param.h>
                     39: #include <sys/systm.h>
                     40: #include <sys/kernel.h>
                     41: #include <sys/malloc.h>
                     42: #include <sys/device.h>
                     43:
                     44: #include <dev/pci/pcidevs.h>
                     45: #include <dev/pci/pcivar.h>
                     46:
                     47: #include <sys/audioio.h>
                     48: #include <dev/audio_if.h>
                     49: #include <dev/mulaw.h>
                     50: #include <dev/auconv.h>
                     51:
                     52: #include <machine/bus.h>
                     53:
                     54: #include <dev/ic/ac97.h>
                     55:
                     56: /* 12.1.10 NAMBAR - native audio mixer base address register */
                     57: #define        AUICH_NAMBAR    0x10
                     58: /* 12.1.11 NABMBAR - native audio bus mastering base address register */
                     59: #define        AUICH_NABMBAR   0x14
                     60: #define        AUICH_CFG       0x41
                     61: #define        AUICH_CFG_IOSE  0x01
                     62: /* ICH4/ICH5/ICH6/ICH7 native audio mixer BAR */
                     63: #define        AUICH_MMBAR     0x18
                     64: /* ICH4/ICH5/ICH6/ICH7 native bus mastering BAR */
                     65: #define        AUICH_MBBAR     0x1c
                     66: #define        AUICH_S2CR      0x10000000      /* tertiary codec ready */
                     67:
                     68: /* table 12-3. native audio bus master control registers */
                     69: #define        AUICH_BDBAR     0x00    /* 8-byte aligned address */
                     70: #define        AUICH_CIV               0x04    /* 5 bits current index value */
                     71: #define        AUICH_LVI               0x05    /* 5 bits last valid index value */
                     72: #define                AUICH_LVI_MASK  0x1f
                     73: #define        AUICH_STS               0x06    /* 16 bits status */
                     74: #define                AUICH_FIFOE     0x10    /* fifo error */
                     75: #define                AUICH_BCIS      0x08    /* r- buf cmplt int sts; wr ack */
                     76: #define                AUICH_LVBCI     0x04    /* r- last valid bci, wr ack */
                     77: #define                AUICH_CELV      0x02    /* current equals last valid */
                     78: #define                AUICH_DCH               0x01    /* dma halted */
                     79: #define                AUICH_ISTS_BITS "\020\01dch\02celv\03lvbci\04bcis\05fifoe"
                     80: #define        AUICH_PICB      0x08    /* 16 bits */
                     81: #define        AUICH_PIV               0x0a    /* 5 bits prefetched index value */
                     82: #define        AUICH_CTRL      0x0b    /* control */
                     83: #define                AUICH_IOCE      0x10    /* int on completion enable */
                     84: #define                AUICH_FEIE      0x08    /* fifo error int enable */
                     85: #define                AUICH_LVBIE     0x04    /* last valid buf int enable */
                     86: #define                AUICH_RR                0x02    /* 1 - reset regs */
                     87: #define                AUICH_RPBM      0x01    /* 1 - run, 0 - pause */
                     88:
                     89: #define        AUICH_PCMI      0x00
                     90: #define        AUICH_PCMO      0x10
                     91: #define        AUICH_MICI      0x20
                     92:
                     93: #define        AUICH_GCTRL     0x2c
                     94: #define                AUICH_SSM_78    0x40000000      /* S/PDIF slots 7 and 8 */
                     95: #define                AUICH_SSM_69    0x80000000      /* S/PDIF slots 6 and 9 */
                     96: #define                AUICH_SSM_1011  0xc0000000      /* S/PDIF slots 10 and 11 */
                     97: #define                AUICH_POM16     0x000000        /* PCM out precision 16bit */
                     98: #define                AUICH_POM20     0x400000        /* PCM out precision 20bit */
                     99: #define                AUICH_PCM246_MASK 0x300000
                    100: #define                AUICH_PCM2      0x000000        /* 2ch output */
                    101: #define                AUICH_PCM4      0x100000        /* 4ch output */
                    102: #define                AUICH_PCM6      0x200000        /* 6ch output */
                    103: #define                AUICH_S2RIE     0x40    /* int when tertiary codec resume */
                    104: #define                AUICH_SRIE      0x20    /* int when 2ndary codec resume */
                    105: #define                AUICH_PRIE      0x10    /* int when primary codec resume */
                    106: #define                AUICH_ACLSO     0x08    /* aclink shut off */
                    107: #define                AUICH_WRESET    0x04    /* warm reset */
                    108: #define                AUICH_CRESET    0x02    /* cold reset */
                    109: #define                AUICH_GIE               0x01    /* gpi int enable */
                    110: #define        AUICH_GSTS      0x30
                    111: #define                AUICH_MD3               0x20000 /* pwr-dn semaphore for modem */
                    112: #define                AUICH_AD3               0x10000 /* pwr-dn semaphore for audio */
                    113: #define                AUICH_RCS               0x08000 /* read completion status */
                    114: #define                AUICH_B3S12     0x04000 /* bit 3 of slot 12 */
                    115: #define                AUICH_B2S12     0x02000 /* bit 2 of slot 12 */
                    116: #define                AUICH_B1S12     0x01000 /* bit 1 of slot 12 */
                    117: #define                AUICH_SRI               0x00800 /* secondary resume int */
                    118: #define                AUICH_PRI               0x00400 /* primary resume int */
                    119: #define                AUICH_SCR               0x00200 /* secondary codec ready */
                    120: #define                AUICH_PCR               0x00100 /* primary codec ready */
                    121: #define                AUICH_MINT      0x00080 /* mic in int */
                    122: #define                AUICH_POINT     0x00040 /* pcm out int */
                    123: #define                AUICH_PIINT     0x00020 /* pcm in int */
                    124: #define                AUICH_MOINT     0x00004 /* modem out int */
                    125: #define                AUICH_MIINT     0x00002 /* modem in int */
                    126: #define                AUICH_GSCI      0x00001 /* gpi status change */
                    127: #define                AUICH_GSTS_BITS "\020\01gsci\02miict\03moint\06piint\07point\010mint\011pcr\012scr\013pri\014sri\015b1s12\016b2s12\017b3s12\020rcs\021ad3\022md3"
                    128: #define        AUICH_CAS               0x34    /* 1/8 bit */
                    129: #define        AUICH_SEMATIMO          1000    /* us */
                    130: #define        AUICH_RESETIMO          500000  /* us */
                    131:
                    132: #define        ICH_SIS_NV_CTL  0x4c    /* some SiS/NVIDIA register.  From Linux */
                    133: #define                ICH_SIS_CTL_UNMUTE      0x01    /* un-mute the output */
                    134:
                    135: /*
                    136:  * according to the dev/audiovar.h AU_RING_SIZE is 2^16, what fits
                    137:  * in our limits perfectly, i.e. setting it to higher value
                    138:  * in your kernel config would improve perfomance, still 2^21 is the max
                    139:  */
                    140: #define        AUICH_DMALIST_MAX       32
                    141: #define        AUICH_DMASEG_MAX        (65536*2)       /* 64k samples, 2x16 bit samples */
                    142: struct auich_dmalist {
                    143:        u_int32_t       base;
                    144:        u_int32_t       len;
                    145: #define        AUICH_DMAF_IOC  0x80000000      /* 1-int on complete */
                    146: #define        AUICH_DMAF_BUP  0x40000000      /* 0-retrans last, 1-transmit 0 */
                    147: };
                    148:
                    149: #define        AUICH_FIXED_RATE 48000
                    150:
                    151: struct auich_dma {
                    152:        bus_dmamap_t map;
                    153:        caddr_t addr;
                    154:        bus_dma_segment_t segs[AUICH_DMALIST_MAX];
                    155:        int nsegs;
                    156:        size_t size;
                    157:        struct auich_dma *next;
                    158: };
                    159:
                    160: struct auich_softc {
                    161:        struct device sc_dev;
                    162:        void *sc_ih;
                    163:
                    164:        audio_device_t sc_audev;
                    165:
                    166:        bus_space_tag_t iot;
                    167:        bus_space_tag_t iot_mix;
                    168:        bus_space_handle_t mix_ioh;
                    169:        bus_space_handle_t aud_ioh;
                    170:        bus_dma_tag_t dmat;
                    171:
                    172:        struct ac97_codec_if *codec_if;
                    173:        struct ac97_host_if host_if;
                    174:
                    175:        /* dma scatter-gather buffer lists, aligned to 8 bytes */
                    176:        struct auich_dmalist *dmalist_pcmo, *dmap_pcmo;
                    177:        struct auich_dmalist *dmalist_pcmi, *dmap_pcmi;
                    178:        struct auich_dmalist *dmalist_mici, *dmap_mici;
                    179:
                    180:        bus_dmamap_t dmalist_map;
                    181:        bus_dma_segment_t dmalist_seg[2];
                    182:        caddr_t dmalist_kva;
                    183:        bus_addr_t dmalist_pcmo_pa;
                    184:        bus_addr_t dmalist_pcmi_pa;
                    185:        bus_addr_t dmalist_mici_pa;
                    186:
                    187:        /* i/o buffer pointers */
                    188:        u_int32_t pcmo_start, pcmo_p, pcmo_end;
                    189:        int pcmo_blksize, pcmo_fifoe;
                    190:        u_int32_t pcmi_start, pcmi_p, pcmi_end;
                    191:        int pcmi_blksize, pcmi_fifoe;
                    192:        u_int32_t mici_start, mici_p, mici_end;
                    193:        int mici_blksize, mici_fifoe;
                    194:        struct auich_dma *sc_dmas;
                    195:
                    196:        void (*sc_pintr)(void *);
                    197:        void *sc_parg;
                    198:
                    199:        void (*sc_rintr)(void *);
                    200:        void *sc_rarg;
                    201:
                    202:        void *powerhook;
                    203:        int suspend;
                    204:        u_int16_t ext_ctrl;
                    205:        int sc_sample_size;
                    206:        int sc_sts_reg;
                    207:        int sc_ignore_codecready;
                    208:        int flags;
                    209:        int sc_ac97rate;
                    210: };
                    211:
                    212: #ifdef AUICH_DEBUG
                    213: #define        DPRINTF(l,x)    do { if (auich_debug & (l)) printf x; } while(0)
                    214: int auich_debug = 0xfffe;
                    215: #define        AUICH_DEBUG_CODECIO     0x0001
                    216: #define        AUICH_DEBUG_DMA         0x0002
                    217: #define        AUICH_DEBUG_PARAM       0x0004
                    218: #else
                    219: #define        DPRINTF(x,y)    /* nothing */
                    220: #endif
                    221:
                    222: struct cfdriver        auich_cd = {
                    223:        NULL, "auich", DV_DULL
                    224: };
                    225:
                    226: int  auich_match(struct device *, void *, void *);
                    227: void auich_attach(struct device *, struct device *, void *);
                    228: int  auich_intr(void *);
                    229:
                    230: struct cfattach auich_ca = {
                    231:        sizeof(struct auich_softc), auich_match, auich_attach
                    232: };
                    233:
                    234: static const struct auich_devtype {
                    235:        int     vendor;
                    236:        int     product;
                    237:        int     options;
                    238:        char    name[8];
                    239: } auich_devices[] = {
                    240:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_6300ESB_ACA,  0, "ESB" },
                    241:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_6321ESB_ACA,  0, "ESB2" },
                    242:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801AA_ACA,  0, "ICH" },
                    243:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801AB_ACA,  0, "ICH0" },
                    244:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801BA_ACA,  0, "ICH2" },
                    245:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801CA_ACA,  0, "ICH3" },
                    246:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801DB_ACA,  0, "ICH4" },
                    247:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801EB_ACA,  0, "ICH5" },
                    248:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801FB_ACA,  0, "ICH6" },
                    249:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801GB_ACA,  0, "ICH7" },
                    250:        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82440MX_ACA,  0, "440MX" },
                    251:        { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_7012_ACA,       0, "SiS7012" },
                    252:        { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE_ACA,  0, "nForce" },
                    253:        { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE2_ACA, 0, "nForce2" },
                    254:        { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE2_400_ACA,
                    255:            0, "nForce2" },
                    256:        { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE3_ACA, 0, "nForce3" },
                    257:        { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE3_250_ACA,
                    258:            0, "nForce3" },
                    259:        { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE4_AC,  0, "nForce4" },
                    260:        { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_MCP04_AC97,  0, "MCP04" },
                    261:        { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_MCP51_ACA,   0, "MCP51" },
                    262:        { PCI_VENDOR_AMD,       PCI_PRODUCT_AMD_PBC768_ACA,     0, "AMD768" },
                    263:        { PCI_VENDOR_AMD,       PCI_PRODUCT_AMD_8111_ACA,       0, "AMD8111" },
                    264: };
                    265:
                    266: int auich_open(void *, int);
                    267: void auich_close(void *);
                    268: int auich_query_encoding(void *, struct audio_encoding *);
                    269: int auich_set_params(void *, int, int, struct audio_params *,
                    270:     struct audio_params *);
                    271: int auich_round_blocksize(void *, int);
                    272: int auich_halt_output(void *);
                    273: int auich_halt_input(void *);
                    274: int auich_getdev(void *, struct audio_device *);
                    275: int auich_set_port(void *, mixer_ctrl_t *);
                    276: int auich_get_port(void *, mixer_ctrl_t *);
                    277: int auich_query_devinfo(void *, mixer_devinfo_t *);
                    278: void *auich_allocm(void *, int, size_t, int, int);
                    279: void auich_freem(void *, void *, int);
                    280: size_t auich_round_buffersize(void *, int, size_t);
                    281: paddr_t auich_mappage(void *, void *, off_t, int);
                    282: int auich_get_props(void *);
                    283: int auich_trigger_output(void *, void *, void *, int, void (*)(void *),
                    284:     void *, struct audio_params *);
                    285: int auich_trigger_input(void *, void *, void *, int, void (*)(void *),
                    286:     void *, struct audio_params *);
                    287:
                    288: void auich_powerhook(int, void *);
                    289:
                    290: struct audio_hw_if auich_hw_if = {
                    291:        auich_open,
                    292:        auich_close,
                    293:        NULL,                   /* drain */
                    294:        auich_query_encoding,
                    295:        auich_set_params,
                    296:        auich_round_blocksize,
                    297:        NULL,                   /* commit_setting */
                    298:        NULL,                   /* init_output */
                    299:        NULL,                   /* init_input */
                    300:        NULL,                   /* start_output */
                    301:        NULL,                   /* start_input */
                    302:        auich_halt_output,
                    303:        auich_halt_input,
                    304:        NULL,                   /* speaker_ctl */
                    305:        auich_getdev,
                    306:        NULL,                   /* getfd */
                    307:        auich_set_port,
                    308:        auich_get_port,
                    309:        auich_query_devinfo,
                    310:        auich_allocm,
                    311:        auich_freem,
                    312:        auich_round_buffersize,
                    313:        auich_mappage,
                    314:        auich_get_props,
                    315:        auich_trigger_output,
                    316:        auich_trigger_input
                    317: };
                    318:
                    319: int  auich_attach_codec(void *, struct ac97_codec_if *);
                    320: int  auich_read_codec(void *, u_int8_t, u_int16_t *);
                    321: int  auich_write_codec(void *, u_int8_t, u_int16_t);
                    322: void auich_reset_codec(void *);
                    323: enum ac97_host_flags auich_flags_codec(void *);
                    324: unsigned int auich_calibrate(struct auich_softc *);
                    325:
                    326: int
                    327: auich_match(parent, match, aux)
                    328:        struct device *parent;
                    329:        void *match;
                    330:        void *aux;
                    331: {
                    332:        struct pci_attach_args *pa = aux;
                    333:        int i;
                    334:
                    335:        for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;)
                    336:                if (PCI_VENDOR(pa->pa_id) == auich_devices[i].vendor &&
                    337:                    PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)
                    338:                        return 1;
                    339:
                    340:        return 0;
                    341: }
                    342:
                    343: void
                    344: auich_attach(parent, self, aux)
                    345:        struct device *parent, *self;
                    346:        void *aux;
                    347: {
                    348:        struct auich_softc *sc = (struct auich_softc *)self;
                    349:        struct pci_attach_args *pa = aux;
                    350:        pci_intr_handle_t ih;
                    351:        bus_size_t mix_size, aud_size;
                    352:        pcireg_t csr;
                    353:        const char *intrstr;
                    354:        u_int32_t status;
                    355:        bus_size_t dmasz;
                    356:        int i, segs;
                    357:
                    358:        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
                    359:            (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA ||
                    360:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801EB_ACA ||
                    361:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801FB_ACA ||
                    362:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801GB_ACA)) {
                    363:                /*
                    364:                 * Use native mode for ICH4/ICH5/ICH6/ICH7
                    365:                 */
                    366:                if (pci_mapreg_map(pa, AUICH_MMBAR, PCI_MAPREG_TYPE_MEM, 0,
                    367:                    &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
                    368:                        csr = pci_conf_read(pa->pa_pc, pa->pa_tag, AUICH_CFG);
                    369:                        pci_conf_write(pa->pa_pc, pa->pa_tag, AUICH_CFG,
                    370:                            csr | AUICH_CFG_IOSE);
                    371:                        if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO,
                    372:                            0, &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
                    373:                                printf(": can't map codec mem/io space\n");
                    374:                                return;
                    375:                        }
                    376:                }
                    377:
                    378:                if (pci_mapreg_map(pa, AUICH_MBBAR, PCI_MAPREG_TYPE_MEM, 0,
                    379:                    &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {
                    380:                        csr = pci_conf_read(pa->pa_pc, pa->pa_tag, AUICH_CFG);
                    381:                        pci_conf_write(pa->pa_pc, pa->pa_tag, AUICH_CFG,
                    382:                            csr | AUICH_CFG_IOSE);
                    383:                        if (pci_mapreg_map(pa, AUICH_NABMBAR,
                    384:                            PCI_MAPREG_TYPE_IO, 0, &sc->iot,
                    385:                            &sc->aud_ioh, NULL, &aud_size, 0)) {
                    386:                                printf(": can't map device mem/io space\n");
                    387:                                bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
                    388:                                return;
                    389:                        }
                    390:                }
                    391:        } else {
                    392:                if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO,
                    393:                    0, &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
                    394:                        printf(": can't map codec i/o space\n");
                    395:                        return;
                    396:                }
                    397:
                    398:                if (pci_mapreg_map(pa, AUICH_NABMBAR, PCI_MAPREG_TYPE_IO,
                    399:                    0, &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {
                    400:                        printf(": can't map device i/o space\n");
                    401:                        bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
                    402:                        return;
                    403:                }
                    404:        }
                    405:        sc->dmat = pa->pa_dmat;
                    406:
                    407:        /* allocate dma memory */
                    408:        dmasz = AUICH_DMALIST_MAX * 3 * sizeof(struct auich_dma);
                    409:        segs = 1;
                    410:        if (bus_dmamem_alloc(sc->dmat, dmasz, PAGE_SIZE, 0, sc->dmalist_seg,
                    411:            segs, &segs, BUS_DMA_NOWAIT)) {
                    412:                printf(": failed to alloc dmalist\n");
                    413:                return;
                    414:        }
                    415:        if (bus_dmamem_map(sc->dmat, sc->dmalist_seg, segs, dmasz,
                    416:            &sc->dmalist_kva, BUS_DMA_NOWAIT)) {
                    417:                printf(": failed to map dmalist\n");
                    418:                bus_dmamem_free(sc->dmat, sc->dmalist_seg, segs);
                    419:                return;
                    420:        }
                    421:        if (bus_dmamap_create(sc->dmat, dmasz, segs, dmasz, 0, BUS_DMA_NOWAIT,
                    422:            &sc->dmalist_map)) {
                    423:                printf(": failed to create dmalist map\n");
                    424:                bus_dmamem_unmap(sc->dmat, sc->dmalist_kva, dmasz);
                    425:                bus_dmamem_free(sc->dmat, sc->dmalist_seg, segs);
                    426:                return;
                    427:        }
                    428:        if (bus_dmamap_load_raw(sc->dmat, sc->dmalist_map, sc->dmalist_seg,
                    429:            segs, dmasz, BUS_DMA_NOWAIT)) {
                    430:                printf(": failed to load dmalist map: %d segs %lu size\n",
                    431:                    segs, (u_long)dmasz);
                    432:                bus_dmamap_destroy(sc->dmat, sc->dmalist_map);
                    433:                bus_dmamem_unmap(sc->dmat, sc->dmalist_kva, dmasz);
                    434:                bus_dmamem_free(sc->dmat, sc->dmalist_seg, segs);
                    435:                return;
                    436:        }
                    437:
                    438:        if (pci_intr_map(pa, &ih)) {
                    439:                bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
                    440:                bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
                    441:                return;
                    442:        }
                    443:        intrstr = pci_intr_string(pa->pa_pc, ih);
                    444:        sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, auich_intr,
                    445:                                       sc, sc->sc_dev.dv_xname);
                    446:        if (!sc->sc_ih) {
                    447:                printf(": can't establish interrupt");
                    448:                if (intrstr)
                    449:                        printf(" at %s", intrstr);
                    450:                printf("\n");
                    451:                bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
                    452:                bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
                    453:                return;
                    454:        }
                    455:
                    456:        for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;)
                    457:                if (PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)
                    458:                        break;
                    459:
                    460:        snprintf(sc->sc_audev.name, sizeof sc->sc_audev.name, "%s AC97",
                    461:                 auich_devices[i].name);
                    462:        snprintf(sc->sc_audev.version, sizeof sc->sc_audev.version, "0x%02x",
                    463:                 PCI_REVISION(pa->pa_class));
                    464:        strlcpy(sc->sc_audev.config, sc->sc_dev.dv_xname,
                    465:                sizeof sc->sc_audev.config);
                    466:
                    467:        printf(": %s, %s\n", intrstr, sc->sc_audev.name);
                    468:
                    469:        /* SiS 7012 needs special handling */
                    470:        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SIS &&
                    471:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_7012_ACA) {
                    472:                sc->sc_sts_reg = AUICH_PICB;
                    473:                sc->sc_sample_size = 1;
                    474:                /* un-mute output */
                    475:                bus_space_write_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL,
                    476:                    bus_space_read_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL) |
                    477:                    ICH_SIS_CTL_UNMUTE);
                    478:        } else {
                    479:                sc->sc_sts_reg = AUICH_STS;
                    480:                sc->sc_sample_size = 2;
                    481:        }
                    482:
                    483:        sc->dmalist_pcmo = (struct auich_dmalist *)(sc->dmalist_kva +
                    484:            (0 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX));
                    485:        sc->dmalist_pcmo_pa = sc->dmalist_map->dm_segs[0].ds_addr +
                    486:            (0 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX);
                    487:
                    488:        sc->dmalist_pcmi = (struct auich_dmalist *)(sc->dmalist_kva +
                    489:            (1 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX));
                    490:        sc->dmalist_pcmi_pa = sc->dmalist_map->dm_segs[0].ds_addr +
                    491:            (1 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX);
                    492:
                    493:        sc->dmalist_mici = (struct auich_dmalist *)(sc->dmalist_kva +
                    494:            (2 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX));
                    495:        sc->dmalist_mici_pa = sc->dmalist_map->dm_segs[0].ds_addr +
                    496:            (2 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX);
                    497:
                    498:        DPRINTF(AUICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n",
                    499:            sc->dmalist_pcmo, sc->dmalist_pcmi, sc->dmalist_mici));
                    500:
                    501:        /* Reset codec and AC'97 */
                    502:        auich_reset_codec(sc);
                    503:        status = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS);
                    504:        if (!(status & AUICH_PCR)) {    /* reset failure */
                    505:                if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
                    506:                    (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA ||
                    507:                     PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801EB_ACA ||
                    508:                     PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801FB_ACA ||
                    509:                     PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801GB_ACA)) {
                    510:                        /* MSI 845G Max never return AUICH_PCR */
                    511:                        sc->sc_ignore_codecready = 1;
                    512:                } else {
                    513:                        printf("%s: reset failed!\n", sc->sc_dev.dv_xname);
                    514:                        return;
                    515:                }
                    516:        }
                    517:
                    518:        sc->host_if.arg = sc;
                    519:        sc->host_if.attach = auich_attach_codec;
                    520:        sc->host_if.read = auich_read_codec;
                    521:        sc->host_if.write = auich_write_codec;
                    522:        sc->host_if.reset = auich_reset_codec;
                    523:        sc->host_if.flags = auich_flags_codec;
                    524:        if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001)
                    525:                sc->flags = AC97_HOST_SWAPPED_CHANNELS;
                    526:
                    527:        if (ac97_attach(&sc->host_if) != 0) {
                    528:                pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
                    529:                bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
                    530:                bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
                    531:                return;
                    532:        }
                    533:
                    534:        audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev);
                    535:
                    536:        /* Watch for power changes */
                    537:        sc->suspend = PWR_RESUME;
                    538:        sc->powerhook = powerhook_establish(auich_powerhook, sc);
                    539:
                    540:        sc->sc_ac97rate = -1;
                    541: }
                    542:
                    543: int
                    544: auich_read_codec(v, reg, val)
                    545:        void *v;
                    546:        u_int8_t reg;
                    547:        u_int16_t *val;
                    548: {
                    549:        struct auich_softc *sc = v;
                    550:        int i;
                    551:
                    552:        /* wait for an access semaphore */
                    553:        for (i = AUICH_SEMATIMO; i-- &&
                    554:            bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));
                    555:
                    556:        if (!sc->sc_ignore_codecready && i < 0) {
                    557:                DPRINTF(AUICH_DEBUG_CODECIO,
                    558:                    ("%s: read_codec timeout\n", sc->sc_dev.dv_xname));
                    559:                return (-1);
                    560:        }
                    561:
                    562:        *val = bus_space_read_2(sc->iot_mix, sc->mix_ioh, reg);
                    563:        DPRINTF(AUICH_DEBUG_CODECIO, ("%s: read_codec(%x, %x)\n",
                    564:            sc->sc_dev.dv_xname, reg, *val));
                    565:        return (0);
                    566: }
                    567:
                    568: int
                    569: auich_write_codec(v, reg, val)
                    570:        void *v;
                    571:        u_int8_t reg;
                    572:        u_int16_t val;
                    573: {
                    574:        struct auich_softc *sc = v;
                    575:        int i;
                    576:
                    577:        /* wait for an access semaphore */
                    578:        for (i = AUICH_SEMATIMO; i-- &&
                    579:            bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));
                    580:
                    581:        if (sc->sc_ignore_codecready || i >= 0) {
                    582:                DPRINTF(AUICH_DEBUG_CODECIO, ("%s: write_codec(%x, %x)\n",
                    583:                    sc->sc_dev.dv_xname, reg, val));
                    584:                bus_space_write_2(sc->iot_mix, sc->mix_ioh, reg, val);
                    585:                return (0);
                    586:        } else {
                    587:                DPRINTF(AUICH_DEBUG_CODECIO,
                    588:                    ("%s: write_codec timeout\n", sc->sc_dev.dv_xname));
                    589:                return (-1);
                    590:        }
                    591: }
                    592:
                    593: int
                    594: auich_attach_codec(v, cif)
                    595:        void *v;
                    596:        struct ac97_codec_if *cif;
                    597: {
                    598:        struct auich_softc *sc = v;
                    599:
                    600:        sc->codec_if = cif;
                    601:        return 0;
                    602: }
                    603:
                    604: void
                    605: auich_reset_codec(v)
                    606:        void *v;
                    607: {
                    608:        struct auich_softc *sc = v;
                    609:        u_int32_t control;
                    610:        int i;
                    611:
                    612:        control = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GCTRL);
                    613:        control &= ~(AUICH_ACLSO | AUICH_PCM246_MASK);
                    614:        control |= (control & AUICH_CRESET) ? AUICH_WRESET : AUICH_CRESET;
                    615:        bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, control);
                    616:
                    617:        for (i = AUICH_RESETIMO; i-- &&
                    618:            !(bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS) & AUICH_PCR);
                    619:            DELAY(1));
                    620:
                    621:        if (i < 0)
                    622:                DPRINTF(AUICH_DEBUG_CODECIO,
                    623:                    ("%s: reset_codec timeout\n", sc->sc_dev.dv_xname));
                    624: }
                    625:
                    626: enum ac97_host_flags
                    627: auich_flags_codec(void *v)
                    628: {
                    629:        struct auich_softc *sc = v;
                    630:
                    631:        return (sc->flags);
                    632: }
                    633:
                    634: int
                    635: auich_open(v, flags)
                    636:        void *v;
                    637:        int flags;
                    638: {
                    639:        struct auich_softc *sc = v;
                    640:
                    641:        if (sc->sc_ac97rate == -1)
                    642:                sc->sc_ac97rate = auich_calibrate(sc);
                    643:        return 0;
                    644: }
                    645:
                    646: void
                    647: auich_close(v)
                    648:        void *v;
                    649: {
                    650: }
                    651:
                    652: int
                    653: auich_query_encoding(v, aep)
                    654:        void *v;
                    655:        struct audio_encoding *aep;
                    656: {
                    657:        switch (aep->index) {
                    658:        case 0:
                    659:                strlcpy(aep->name, AudioEulinear, sizeof aep->name);
                    660:                aep->encoding = AUDIO_ENCODING_ULINEAR;
                    661:                aep->precision = 8;
                    662:                aep->flags = 0;
                    663:                return (0);
                    664:        case 1:
                    665:                strlcpy(aep->name, AudioEmulaw, sizeof aep->name);
                    666:                aep->encoding = AUDIO_ENCODING_ULAW;
                    667:                aep->precision = 8;
                    668:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    669:                return (0);
                    670:        case 2:
                    671:                strlcpy(aep->name, AudioEalaw, sizeof aep->name);
                    672:                aep->encoding = AUDIO_ENCODING_ALAW;
                    673:                aep->precision = 8;
                    674:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    675:                return (0);
                    676:        case 3:
                    677:                strlcpy(aep->name, AudioEslinear, sizeof aep->name);
                    678:                aep->encoding = AUDIO_ENCODING_SLINEAR;
                    679:                aep->precision = 8;
                    680:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    681:                return (0);
                    682:        case 4:
                    683:                strlcpy(aep->name, AudioEslinear_le, sizeof aep->name);
                    684:                aep->encoding = AUDIO_ENCODING_SLINEAR_LE;
                    685:                aep->precision = 16;
                    686:                aep->flags = 0;
                    687:                return (0);
                    688:        case 5:
                    689:                strlcpy(aep->name, AudioEulinear_le, sizeof aep->name);
                    690:                aep->encoding = AUDIO_ENCODING_ULINEAR_LE;
                    691:                aep->precision = 16;
                    692:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    693:                return (0);
                    694:        case 6:
                    695:                strlcpy(aep->name, AudioEslinear_be, sizeof aep->name);
                    696:                aep->encoding = AUDIO_ENCODING_SLINEAR_BE;
                    697:                aep->precision = 16;
                    698:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    699:                return (0);
                    700:        case 7:
                    701:                strlcpy(aep->name, AudioEulinear_be, sizeof aep->name);
                    702:                aep->encoding = AUDIO_ENCODING_ULINEAR_BE;
                    703:                aep->precision = 16;
                    704:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    705:                return (0);
                    706:        default:
                    707:                return (EINVAL);
                    708:        }
                    709: }
                    710:
                    711: int
                    712: auich_set_params(v, setmode, usemode, play, rec)
                    713:        void *v;
                    714:        int setmode, usemode;
                    715:        struct audio_params *play, *rec;
                    716: {
                    717:        struct auich_softc *sc = v;
                    718:        int error;
                    719:        u_int orate;
                    720:        u_int adj_rate;
                    721:
                    722:        if (setmode & AUMODE_PLAY) {
                    723:                play->factor = 1;
                    724:                play->sw_code = NULL;
                    725:                switch(play->encoding) {
                    726:                case AUDIO_ENCODING_ULAW:
                    727:                        switch (play->channels) {
                    728:                        case 1:
                    729:                                play->factor = 4;
                    730:                                play->sw_code = mulaw_to_slinear16_mts;
                    731:                                break;
                    732:                        case 2:
                    733:                                play->factor = 2;
                    734:                                play->sw_code = mulaw_to_slinear16;
                    735:                                break;
                    736:                        default:
                    737:                                return (EINVAL);
                    738:                        }
                    739:                        break;
                    740:                case AUDIO_ENCODING_SLINEAR_LE:
                    741:                        switch (play->precision) {
                    742:                        case 8:
                    743:                                switch (play->channels) {
                    744:                                case 1:
                    745:                                        play->factor = 4;
                    746:                                        play->sw_code = linear8_to_linear16_mts;
                    747:                                        break;
                    748:                                case 2:
                    749:                                        play->factor = 2;
                    750:                                        play->sw_code = linear8_to_linear16;
                    751:                                        break;
                    752:                                default:
                    753:                                        return (EINVAL);
                    754:                                }
                    755:                                break;
                    756:                        case 16:
                    757:                                switch (play->channels) {
                    758:                                case 1:
                    759:                                        play->factor = 2;
                    760:                                        play->sw_code = noswap_bytes_mts;
                    761:                                        break;
                    762:                                case 2:
                    763:                                        break;
                    764:                                default:
                    765:                                        return (EINVAL);
                    766:                                }
                    767:                                break;
                    768:                        default:
                    769:                                return (EINVAL);
                    770:                        }
                    771:                        break;
                    772:                case AUDIO_ENCODING_ULINEAR_LE:
                    773:                        switch (play->precision) {
                    774:                        case 8:
                    775:                                switch (play->channels) {
                    776:                                case 1:
                    777:                                        play->factor = 4;
                    778:                                        play->sw_code = ulinear8_to_linear16_mts;
                    779:                                        break;
                    780:                                case 2:
                    781:                                        play->factor = 2;
                    782:                                        play->sw_code = ulinear8_to_linear16;
                    783:                                        break;
                    784:                                default:
                    785:                                        return (EINVAL);
                    786:                                }
                    787:                                break;
                    788:                        case 16:
                    789:                                switch (play->channels) {
                    790:                                case 1:
                    791:                                        play->factor = 2;
                    792:                                        play->sw_code = change_sign16_mts;
                    793:                                        break;
                    794:                                case 2:
                    795:                                        play->sw_code = change_sign16;
                    796:                                        break;
                    797:                                default:
                    798:                                        return (EINVAL);
                    799:                                }
                    800:                                break;
                    801:                        default:
                    802:                                return (EINVAL);
                    803:                        }
                    804:                        break;
                    805:                case AUDIO_ENCODING_ALAW:
                    806:                        switch (play->channels) {
                    807:                        case 1:
                    808:                                play->factor = 4;
                    809:                                play->sw_code = alaw_to_slinear16_mts;
                    810:                                break;
                    811:                        case 2:
                    812:                                play->factor = 2;
                    813:                                play->sw_code = alaw_to_slinear16;
                    814:                                break;
                    815:                        default:
                    816:                                return (EINVAL);
                    817:                        }
                    818:                        break;
                    819:                case AUDIO_ENCODING_SLINEAR_BE:
                    820:                        switch (play->precision) {
                    821:                        case 8:
                    822:                                switch (play->channels) {
                    823:                                case 1:
                    824:                                        play->factor = 4;
                    825:                                        play->sw_code = linear8_to_linear16_mts;
                    826:                                        break;
                    827:                                case 2:
                    828:                                        play->factor = 2;
                    829:                                        play->sw_code = linear8_to_linear16;
                    830:                                        break;
                    831:                                default:
                    832:                                        return (EINVAL);
                    833:                                }
                    834:                                break;
                    835:                        case 16:
                    836:                                switch (play->channels) {
                    837:                                case 1:
                    838:                                        play->factor = 2;
                    839:                                        play->sw_code = swap_bytes_mts;
                    840:                                        break;
                    841:                                case 2:
                    842:                                        play->sw_code = swap_bytes;
                    843:                                        break;
                    844:                                default:
                    845:                                        return (EINVAL);
                    846:                                }
                    847:                                break;
                    848:                        default:
                    849:                                return (EINVAL);
                    850:                        }
                    851:                        break;
                    852:                case AUDIO_ENCODING_ULINEAR_BE:
                    853:                        switch (play->precision) {
                    854:                        case 8:
                    855:                                switch (play->channels) {
                    856:                                case 1:
                    857:                                        play->factor = 4;
                    858:                                        play->sw_code = ulinear8_to_linear16_mts;
                    859:                                        break;
                    860:                                case 2:
                    861:                                        play->factor = 2;
                    862:                                        play->sw_code = ulinear8_to_linear16;
                    863:                                        break;
                    864:                                default:
                    865:                                        return (EINVAL);
                    866:                                }
                    867:                                break;
                    868:                        case 16:
                    869:                                switch (play->channels) {
                    870:                                case 1:
                    871:                                        play->factor = 2;
                    872:                                        play->sw_code = change_sign16_swap_bytes_mts;
                    873:                                        break;
                    874:                                case 2:
                    875:                                        play->sw_code = change_sign16_swap_bytes;
                    876:                                        break;
                    877:                                default:
                    878:                                        return (EINVAL);
                    879:                                }
                    880:                                break;
                    881:                        default:
                    882:                                return (EINVAL);
                    883:                        }
                    884:                        break;
                    885:                default:
                    886:                        return (EINVAL);
                    887:                }
                    888:
                    889:                orate = adj_rate = play->sample_rate;
                    890:                if (sc->sc_ac97rate != 0)
                    891:                        adj_rate = orate * AUICH_FIXED_RATE / sc->sc_ac97rate;
                    892:                play->sample_rate = adj_rate;
                    893:                error = ac97_set_rate(sc->codec_if, play, AUMODE_PLAY);
                    894:                if (play->sample_rate == adj_rate)
                    895:                        play->sample_rate = orate;
                    896:                if (error)
                    897:                        return (error);
                    898:        }
                    899:
                    900:        if (setmode & AUMODE_RECORD) {
                    901:                rec->factor = 1;
                    902:                rec->sw_code = 0;
                    903:                switch(rec->encoding) {
                    904:                case AUDIO_ENCODING_ULAW:
                    905:                        rec->sw_code = slinear16_to_mulaw_le;
                    906:                        rec->factor = 2;
                    907:                        break;
                    908:                case AUDIO_ENCODING_ALAW:
                    909:                        rec->sw_code = slinear16_to_alaw_le;
                    910:                        rec->factor = 2;
                    911:                        break;
                    912:                case AUDIO_ENCODING_SLINEAR_LE:
                    913:                        switch (rec->precision) {
                    914:                        case 8:
                    915:                                rec->sw_code = linear16_to_linear8_le;
                    916:                                rec->factor = 2;
                    917:                                break;
                    918:                        case 16:
                    919:                                break;
                    920:                        default:
                    921:                                return (EINVAL);
                    922:                        }
                    923:                        break;
                    924:                case AUDIO_ENCODING_ULINEAR_LE:
                    925:                        switch (rec->precision) {
                    926:                        case 8:
                    927:                                rec->sw_code = linear16_to_ulinear8_le;
                    928:                                rec->factor = 2;
                    929:                                break;
                    930:                        case 16:
                    931:                                rec->sw_code = change_sign16_le;
                    932:                                break;
                    933:                        default:
                    934:                                return (EINVAL);
                    935:                        }
                    936:                        break;
                    937:                case AUDIO_ENCODING_SLINEAR_BE:
                    938:                        switch (rec->precision) {
                    939:                        case 8:
                    940:                                rec->sw_code = linear16_to_linear8_le;
                    941:                                rec->factor = 2;
                    942:                                break;
                    943:                        case 16:
                    944:                                rec->sw_code = swap_bytes;
                    945:                                break;
                    946:                        default:
                    947:                                return (EINVAL);
                    948:                        }
                    949:                        break;
                    950:                case AUDIO_ENCODING_ULINEAR_BE:
                    951:                        switch (rec->precision) {
                    952:                        case 8:
                    953:                                rec->sw_code = linear16_to_ulinear8_le;
                    954:                                rec->factor = 2;
                    955:                                break;
                    956:                        case 16:
                    957:                                rec->sw_code = change_sign16_swap_bytes_le;
                    958:                                break;
                    959:                        default:
                    960:                                return (EINVAL);
                    961:                        }
                    962:                        break;
                    963:                default:
                    964:                        return (EINVAL);
                    965:                }
                    966:
                    967:                orate = rec->sample_rate;
                    968:                if (sc->sc_ac97rate != 0)
                    969:                        rec->sample_rate = orate * AUICH_FIXED_RATE /
                    970:                            sc->sc_ac97rate;
                    971:                error = ac97_set_rate(sc->codec_if, rec, AUMODE_RECORD);
                    972:                rec->sample_rate = orate;
                    973:                if (error)
                    974:                        return (error);
                    975:        }
                    976:
                    977:        return (0);
                    978: }
                    979:
                    980: int
                    981: auich_round_blocksize(v, blk)
                    982:        void *v;
                    983:        int blk;
                    984: {
                    985:        return (blk + 0x3f) & ~0x3f;
                    986: }
                    987:
                    988: int
                    989: auich_halt_output(v)
                    990:        void *v;
                    991: {
                    992:        struct auich_softc *sc = v;
                    993:
                    994:        DPRINTF(AUICH_DEBUG_DMA, ("%s: halt_output\n", sc->sc_dev.dv_xname));
                    995:
                    996:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL, AUICH_RR);
                    997:
                    998:        return 0;
                    999: }
                   1000:
                   1001: int
                   1002: auich_halt_input(v)
                   1003:        void *v;
                   1004: {
                   1005:        struct auich_softc *sc = v;
                   1006:
                   1007:        DPRINTF(AUICH_DEBUG_DMA,
                   1008:            ("%s: halt_input\n", sc->sc_dev.dv_xname));
                   1009:
                   1010:        /* XXX halt both unless known otherwise */
                   1011:
                   1012:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, AUICH_RR);
                   1013:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_MICI + AUICH_CTRL, AUICH_RR);
                   1014:
                   1015:        return 0;
                   1016: }
                   1017:
                   1018: int
                   1019: auich_getdev(v, adp)
                   1020:        void *v;
                   1021:        struct audio_device *adp;
                   1022: {
                   1023:        struct auich_softc *sc = v;
                   1024:        *adp = sc->sc_audev;
                   1025:        return 0;
                   1026: }
                   1027:
                   1028: int
                   1029: auich_set_port(v, cp)
                   1030:        void *v;
                   1031:        mixer_ctrl_t *cp;
                   1032: {
                   1033:        struct auich_softc *sc = v;
                   1034:        return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
                   1035: }
                   1036:
                   1037: int
                   1038: auich_get_port(v, cp)
                   1039:        void *v;
                   1040:        mixer_ctrl_t *cp;
                   1041: {
                   1042:        struct auich_softc *sc = v;
                   1043:        return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
                   1044: }
                   1045:
                   1046: int
                   1047: auich_query_devinfo(v, dp)
                   1048:        void *v;
                   1049:        mixer_devinfo_t *dp;
                   1050: {
                   1051:        struct auich_softc *sc = v;
                   1052:        return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp);
                   1053: }
                   1054:
                   1055: void *
                   1056: auich_allocm(v, direction, size, pool, flags)
                   1057:        void *v;
                   1058:        int direction;
                   1059:        size_t size;
                   1060:        int pool, flags;
                   1061: {
                   1062:        struct auich_softc *sc = v;
                   1063:        struct auich_dma *p;
                   1064:        int error;
                   1065:
                   1066:        if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX)
                   1067:                return NULL;
                   1068:
                   1069:        p = malloc(sizeof(*p), pool, flags);
                   1070:        if (!p)
                   1071:                return NULL;
                   1072:        bzero(p, sizeof(*p));
                   1073:
                   1074:        p->size = size;
                   1075:        if ((error = bus_dmamem_alloc(sc->dmat, p->size, NBPG, 0, p->segs,
                   1076:            1, &p->nsegs, BUS_DMA_NOWAIT)) != 0) {
                   1077:                printf("%s: unable to allocate dma, error = %d\n",
                   1078:                    sc->sc_dev.dv_xname, error);
                   1079:                free(p, pool);
                   1080:                return NULL;
                   1081:        }
                   1082:
                   1083:        if ((error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size,
                   1084:            &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
                   1085:                printf("%s: unable to map dma, error = %d\n",
                   1086:                    sc->sc_dev.dv_xname, error);
                   1087:                bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
                   1088:                free(p, pool);
                   1089:                return NULL;
                   1090:        }
                   1091:
                   1092:        if ((error = bus_dmamap_create(sc->dmat, p->size, 1,
                   1093:            p->size, 0, BUS_DMA_NOWAIT, &p->map)) != 0) {
                   1094:                printf("%s: unable to create dma map, error = %d\n",
                   1095:                    sc->sc_dev.dv_xname, error);
                   1096:                bus_dmamem_unmap(sc->dmat, p->addr, size);
                   1097:                bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
                   1098:                free(p, pool);
                   1099:                return NULL;
                   1100:        }
                   1101:
                   1102:        if ((error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size,
                   1103:            NULL, BUS_DMA_NOWAIT)) != 0) {
                   1104:                printf("%s: unable to load dma map, error = %d\n",
                   1105:                    sc->sc_dev.dv_xname, error);
                   1106:                bus_dmamap_destroy(sc->dmat, p->map);
                   1107:                bus_dmamem_unmap(sc->dmat, p->addr, size);
                   1108:                bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
                   1109:                free(p, pool);
                   1110:                return NULL;
                   1111:        }
                   1112:
                   1113:        p->next = sc->sc_dmas;
                   1114:        sc->sc_dmas = p;
                   1115:
                   1116:        return p->addr;
                   1117: }
                   1118:
                   1119: void
                   1120: auich_freem(v, ptr, pool)
                   1121:        void *v;
                   1122:        void *ptr;
                   1123:        int pool;
                   1124: {
                   1125:        struct auich_softc *sc = v;
                   1126:        struct auich_dma *p;
                   1127:
                   1128:        for (p = sc->sc_dmas; p->addr != ptr; p = p->next)
                   1129:                if (p->next == NULL) {
                   1130:                        printf("auich_freem: trying to free not allocated memory");
                   1131:                        return;
                   1132:                }
                   1133:
                   1134:        bus_dmamap_unload(sc->dmat, p->map);
                   1135:        bus_dmamap_destroy(sc->dmat, p->map);
                   1136:        bus_dmamem_unmap(sc->dmat, p->addr, p->size);
                   1137:        bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
                   1138:        free(p, pool);
                   1139: }
                   1140:
                   1141: size_t
                   1142: auich_round_buffersize(v, direction, size)
                   1143:        void *v;
                   1144:        int direction;
                   1145:        size_t size;
                   1146: {
                   1147:        if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX)
                   1148:                size = AUICH_DMALIST_MAX * AUICH_DMASEG_MAX;
                   1149:
                   1150:        return size;
                   1151: }
                   1152:
                   1153: paddr_t
                   1154: auich_mappage(v, mem, off, prot)
                   1155:        void *v;
                   1156:        void *mem;
                   1157:        off_t off;
                   1158:        int prot;
                   1159: {
                   1160:        struct auich_softc *sc = v;
                   1161:        struct auich_dma *p;
                   1162:
                   1163:        if (off < 0)
                   1164:                return -1;
                   1165:
                   1166:        for (p = sc->sc_dmas; p && p->addr != mem; p = p->next);
                   1167:        if (!p)
                   1168:                return -1;
                   1169:
                   1170:        return bus_dmamem_mmap(sc->dmat, p->segs, p->nsegs,
                   1171:            off, prot, BUS_DMA_WAITOK);
                   1172: }
                   1173:
                   1174: int
                   1175: auich_get_props(v)
                   1176:        void *v;
                   1177: {
                   1178:        return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
                   1179: }
                   1180:
                   1181: int
                   1182: auich_intr(v)
                   1183:        void *v;
                   1184: {
                   1185:        struct auich_softc *sc = v;
                   1186:        int ret = 0, sts, gsts, i;
                   1187:
                   1188:        gsts = bus_space_read_2(sc->iot, sc->aud_ioh, AUICH_GSTS);
                   1189:        DPRINTF(AUICH_DEBUG_DMA, ("auich_intr: gsts=%b\n", gsts, AUICH_GSTS_BITS));
                   1190:
                   1191:        if (gsts & AUICH_POINT) {
                   1192:                sts = bus_space_read_2(sc->iot, sc->aud_ioh,
                   1193:                    AUICH_PCMO + sc->sc_sts_reg);
                   1194:                DPRINTF(AUICH_DEBUG_DMA,
                   1195:                    ("auich_intr: osts=%b\n", sts, AUICH_ISTS_BITS));
                   1196:
                   1197: #ifdef AUICH_DEBUG
                   1198:                if (sts & AUICH_FIFOE) {
                   1199:                        printf("%s: fifo underrun # %u\n",
                   1200:                            sc->sc_dev.dv_xname, ++sc->pcmo_fifoe);
                   1201:                }
                   1202: #endif
                   1203:                i = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CIV);
                   1204:                if (sts & (AUICH_LVBCI | AUICH_CELV)) {
                   1205:                        struct auich_dmalist *q, *qe;
                   1206:
                   1207:                        q = sc->dmap_pcmo;
                   1208:                        qe = &sc->dmalist_pcmo[i];
                   1209:
                   1210:                        while (q != qe) {
                   1211:
                   1212:                                q->base = sc->pcmo_p;
                   1213:                                q->len = (sc->pcmo_blksize /
                   1214:                                    sc->sc_sample_size) | AUICH_DMAF_IOC;
                   1215:                                DPRINTF(AUICH_DEBUG_DMA,
                   1216:                                    ("auich_intr: %p, %p = %x @ %p\n",
                   1217:                                    qe, q, sc->pcmo_blksize /
                   1218:                                    sc->sc_sample_size, sc->pcmo_p));
                   1219:
                   1220:                                sc->pcmo_p += sc->pcmo_blksize;
                   1221:                                if (sc->pcmo_p >= sc->pcmo_end)
                   1222:                                        sc->pcmo_p = sc->pcmo_start;
                   1223:
                   1224:                                if (++q == &sc->dmalist_pcmo[AUICH_DMALIST_MAX])
                   1225:                                        q = sc->dmalist_pcmo;
                   1226:                        }
                   1227:
                   1228:                        sc->dmap_pcmo = q;
                   1229:                        bus_space_write_1(sc->iot, sc->aud_ioh,
                   1230:                            AUICH_PCMO + AUICH_LVI,
                   1231:                            (sc->dmap_pcmo - sc->dmalist_pcmo - 1) &
                   1232:                            AUICH_LVI_MASK);
                   1233:                }
                   1234:
                   1235:                if (sts & AUICH_BCIS && sc->sc_pintr)
                   1236:                        sc->sc_pintr(sc->sc_parg);
                   1237:
                   1238:                /* int ack */
                   1239:                bus_space_write_2(sc->iot, sc->aud_ioh,
                   1240:                    AUICH_PCMO + sc->sc_sts_reg, sts &
                   1241:                    (AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE));
                   1242:                bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT);
                   1243:                ret++;
                   1244:        }
                   1245:
                   1246:        if (gsts & AUICH_PIINT) {
                   1247:                sts = bus_space_read_2(sc->iot, sc->aud_ioh,
                   1248:                    AUICH_PCMI + sc->sc_sts_reg);
                   1249:                DPRINTF(AUICH_DEBUG_DMA,
                   1250:                    ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS));
                   1251:
                   1252: #ifdef AUICH_DEBUG
                   1253:                if (sts & AUICH_FIFOE) {
                   1254:                        printf("%s: in fifo overrun # %u\n",
                   1255:                            sc->sc_dev.dv_xname, ++sc->pcmi_fifoe);
                   1256:                }
                   1257: #endif
                   1258:                i = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CIV);
                   1259:                if (sts & (AUICH_LVBCI | AUICH_CELV)) {
                   1260:                        struct auich_dmalist *q, *qe;
                   1261:
                   1262:                        q = sc->dmap_pcmi;
                   1263:                        qe = &sc->dmalist_pcmi[i];
                   1264:
                   1265:                        while (q != qe) {
                   1266:
                   1267:                                q->base = sc->pcmi_p;
                   1268:                                q->len = (sc->pcmi_blksize /
                   1269:                                    sc->sc_sample_size) | AUICH_DMAF_IOC;
                   1270:                                DPRINTF(AUICH_DEBUG_DMA,
                   1271:                                    ("auich_intr: %p, %p = %x @ %p\n",
                   1272:                                    qe, q, sc->pcmi_blksize /
                   1273:                                    sc->sc_sample_size, sc->pcmi_p));
                   1274:
                   1275:                                sc->pcmi_p += sc->pcmi_blksize;
                   1276:                                if (sc->pcmi_p >= sc->pcmi_end)
                   1277:                                        sc->pcmi_p = sc->pcmi_start;
                   1278:
                   1279:                                if (++q == &sc->dmalist_pcmi[AUICH_DMALIST_MAX])
                   1280:                                        q = sc->dmalist_pcmi;
                   1281:                        }
                   1282:
                   1283:                        sc->dmap_pcmi = q;
                   1284:                        bus_space_write_1(sc->iot, sc->aud_ioh,
                   1285:                            AUICH_PCMI + AUICH_LVI,
                   1286:                            (sc->dmap_pcmi - sc->dmalist_pcmi - 1) &
                   1287:                            AUICH_LVI_MASK);
                   1288:                }
                   1289:
                   1290:                if (sts & AUICH_BCIS && sc->sc_rintr)
                   1291:                        sc->sc_rintr(sc->sc_rarg);
                   1292:
                   1293:                /* int ack */
                   1294:                bus_space_write_2(sc->iot, sc->aud_ioh,
                   1295:                    AUICH_PCMI + sc->sc_sts_reg, sts &
                   1296:                    (AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE));
                   1297:                bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_PIINT);
                   1298:                ret++;
                   1299:        }
                   1300:
                   1301:        if (gsts & AUICH_MIINT) {
                   1302:                sts = bus_space_read_2(sc->iot, sc->aud_ioh,
                   1303:                    AUICH_MICI + sc->sc_sts_reg);
                   1304:                DPRINTF(AUICH_DEBUG_DMA,
                   1305:                    ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS));
                   1306: #ifdef AUICH_DEBUG
                   1307:                if (sts & AUICH_FIFOE)
                   1308:                        printf("%s: mic fifo overrun\n", sc->sc_dev.dv_xname);
                   1309: #endif
                   1310:
                   1311:                /* TODO mic input dma */
                   1312:
                   1313:                bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_MIINT);
                   1314:        }
                   1315:
                   1316:        return ret;
                   1317: }
                   1318:
                   1319: int
                   1320: auich_trigger_output(v, start, end, blksize, intr, arg, param)
                   1321:        void *v;
                   1322:        void *start, *end;
                   1323:        int blksize;
                   1324:        void (*intr)(void *);
                   1325:        void *arg;
                   1326:        struct audio_params *param;
                   1327: {
                   1328:        struct auich_softc *sc = v;
                   1329:        struct auich_dmalist *q;
                   1330:        struct auich_dma *p;
                   1331:
                   1332:        DPRINTF(AUICH_DEBUG_DMA,
                   1333:            ("auich_trigger_output(%x, %x, %d, %p, %p, %p)\n",
                   1334:            start, end, blksize, intr, arg, param));
                   1335:
                   1336:        for (p = sc->sc_dmas; p && p->addr != start; p = p->next);
                   1337:        if (!p)
                   1338:                return -1;
                   1339:
                   1340:        sc->sc_pintr = intr;
                   1341:        sc->sc_parg = arg;
                   1342:
                   1343:        /*
                   1344:         * The logic behind this is:
                   1345:         * setup one buffer to play, then LVI dump out the rest
                   1346:         * to the scatter-gather chain.
                   1347:         */
                   1348:        sc->pcmo_start = p->segs->ds_addr;
                   1349:        sc->pcmo_p = sc->pcmo_start + blksize;
                   1350:        sc->pcmo_end = sc->pcmo_start + ((char *)end - (char *)start);
                   1351:        sc->pcmo_blksize = blksize;
                   1352:
                   1353:        q = sc->dmap_pcmo = sc->dmalist_pcmo;
                   1354:        q->base = sc->pcmo_start;
                   1355:        q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC;
                   1356:        if (++q == &sc->dmalist_pcmo[AUICH_DMALIST_MAX])
                   1357:                q = sc->dmalist_pcmo;
                   1358:        sc->dmap_pcmo = q;
                   1359:
                   1360:        bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_BDBAR,
                   1361:            sc->dmalist_pcmo_pa);
                   1362:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL,
                   1363:            AUICH_IOCE | AUICH_FEIE | AUICH_LVBIE | AUICH_RPBM);
                   1364:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_LVI,
                   1365:            (sc->dmap_pcmo - 1 - sc->dmalist_pcmo) & AUICH_LVI_MASK);
                   1366:
                   1367:        return 0;
                   1368: }
                   1369:
                   1370: int
                   1371: auich_trigger_input(v, start, end, blksize, intr, arg, param)
                   1372:        void *v;
                   1373:        void *start, *end;
                   1374:        int blksize;
                   1375:        void (*intr)(void *);
                   1376:        void *arg;
                   1377:        struct audio_params *param;
                   1378: {
                   1379:        struct auich_softc *sc = v;
                   1380:        struct auich_dmalist *q;
                   1381:        struct auich_dma *p;
                   1382:
                   1383:        DPRINTF(AUICH_DEBUG_DMA,
                   1384:            ("auich_trigger_input(%x, %x, %d, %p, %p, %p)\n",
                   1385:            start, end, blksize, intr, arg, param));
                   1386:
                   1387:        for (p = sc->sc_dmas; p && p->addr != start; p = p->next);
                   1388:        if (!p)
                   1389:                return -1;
                   1390:
                   1391:        sc->sc_rintr = intr;
                   1392:        sc->sc_rarg = arg;
                   1393:
                   1394:        /*
                   1395:         * The logic behind this is:
                   1396:         * setup one buffer to play, then LVI dump out the rest
                   1397:         * to the scatter-gather chain.
                   1398:         */
                   1399:        sc->pcmi_start = p->segs->ds_addr;
                   1400:        sc->pcmi_p = sc->pcmi_start + blksize;
                   1401:        sc->pcmi_end = sc->pcmi_start + ((char *)end - (char *)start);
                   1402:        sc->pcmi_blksize = blksize;
                   1403:
                   1404:        q = sc->dmap_pcmi = sc->dmalist_pcmi;
                   1405:        q->base = sc->pcmi_start;
                   1406:        q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC;
                   1407:        if (++q == &sc->dmalist_pcmi[AUICH_DMALIST_MAX])
                   1408:                q = sc->dmalist_pcmi;
                   1409:        sc->dmap_pcmi = q;
                   1410:
                   1411:        bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR,
                   1412:            sc->dmalist_pcmi_pa);
                   1413:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL,
                   1414:            AUICH_IOCE | AUICH_FEIE | AUICH_LVBIE | AUICH_RPBM);
                   1415:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_LVI,
                   1416:            (sc->dmap_pcmi - 1 - sc->dmalist_pcmi) & AUICH_LVI_MASK);
                   1417:
                   1418:        return 0;
                   1419: }
                   1420:
                   1421: void
                   1422: auich_powerhook(why, self)
                   1423:        int why;
                   1424:        void *self;
                   1425: {
                   1426:        struct auich_softc *sc = (struct auich_softc *)self;
                   1427:
                   1428:        if (why != PWR_RESUME) {
                   1429:                /* Power down */
                   1430:                DPRINTF(1, ("auich: power down\n"));
                   1431:                sc->suspend = why;
                   1432:                auich_read_codec(sc, AC97_REG_EXT_AUDIO_CTRL, &sc->ext_ctrl);
                   1433:
                   1434:        } else {
                   1435:                /* Wake up */
                   1436:                DPRINTF(1, ("auich: power resume\n"));
                   1437:                if (sc->suspend == PWR_RESUME) {
                   1438:                        printf("%s: resume without suspend?\n",
                   1439:                            sc->sc_dev.dv_xname);
                   1440:                        sc->suspend = why;
                   1441:                        return;
                   1442:                }
                   1443:                sc->suspend = why;
                   1444:                auich_reset_codec(sc);
                   1445:                DELAY(1000);
                   1446:                (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
                   1447:                auich_write_codec(sc, AC97_REG_EXT_AUDIO_CTRL, sc->ext_ctrl);
                   1448:        }
                   1449: }
                   1450:
                   1451:
                   1452:
                   1453: /* -------------------------------------------------------------------- */
                   1454: /* Calibrate card (some boards are overclocked and need scaling) */
                   1455:
                   1456: unsigned int
                   1457: auich_calibrate(struct auich_softc *sc)
                   1458: {
                   1459:        struct timeval t1, t2;
                   1460:        u_int8_t ociv, nciv;
                   1461:        u_int32_t wait_us, actual_48k_rate, bytes, ac97rate;
                   1462:        void *temp_buffer;
                   1463:        struct auich_dma *p;
                   1464:        int i;
                   1465:
                   1466:        ac97rate = AUICH_FIXED_RATE;
                   1467:        /*
                   1468:         * Grab audio from input for fixed interval and compare how
                   1469:         * much we actually get with what we expect.  Interval needs
                   1470:         * to be sufficiently short that no interrupts are
                   1471:         * generated.
                   1472:         */
                   1473:
                   1474:        /* Setup a buffer */
                   1475:        bytes = 16000;
                   1476:        temp_buffer = auich_allocm(sc, AUMODE_RECORD, bytes, M_DEVBUF,
                   1477:            M_NOWAIT);
                   1478:        if (temp_buffer == NULL)
                   1479:                return (ac97rate);
                   1480:        for (p = sc->sc_dmas; p && p->addr != temp_buffer; p = p->next)
                   1481:                ;
                   1482:        if (p == NULL) {
                   1483:                printf("auich_calibrate: bad address %p\n", temp_buffer);
                   1484:                return (ac97rate);
                   1485:        }
                   1486:
                   1487:        for (i = 0; i < AUICH_DMALIST_MAX; i++) {
                   1488:                sc->dmalist_pcmi[i].base = p->map->dm_segs[0].ds_addr;
                   1489:                sc->dmalist_pcmi[i].len = bytes / sc->sc_sample_size;
                   1490:        }
                   1491:
                   1492:        /*
                   1493:         * our data format is stereo, 16 bit so each sample is 4 bytes.
                   1494:         * assuming we get 48000 samples per second, we get 192000 bytes/sec.
                   1495:         * we're going to start recording with interrupts disabled and measure
                   1496:         * the time taken for one block to complete.  we know the block size,
                   1497:         * we know the time in microseconds, we calculate the sample rate:
                   1498:         *
                   1499:         * actual_rate [bps] = bytes / (time [s] * 4)
                   1500:         * actual_rate [bps] = (bytes * 1000000) / (time [us] * 4)
                   1501:         * actual_rate [Hz] = (bytes * 250000) / time [us]
                   1502:         */
                   1503:
                   1504:        /* prepare */
                   1505:        ociv = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CIV);
                   1506:        nciv = ociv;
                   1507:        bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR,
                   1508:            sc->dmalist_pcmi_pa);
                   1509:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_LVI,
                   1510:                          (0 - 1) & AUICH_LVI_MASK);
                   1511:
                   1512:        /* start */
                   1513:        microuptime(&t1);
                   1514:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL,
                   1515:            AUICH_RPBM);
                   1516:
                   1517:        /* wait */
                   1518:        while (nciv == ociv) {
                   1519:                microuptime(&t2);
                   1520:                if (t2.tv_sec - t1.tv_sec > 1)
                   1521:                        break;
                   1522:                nciv = bus_space_read_1(sc->iot, sc->aud_ioh,
                   1523:                                        AUICH_PCMI + AUICH_CIV);
                   1524:        }
                   1525:        microuptime(&t2);
                   1526:
                   1527:        /* reset */
                   1528:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, AUICH_RR);
                   1529:        bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_MICI + AUICH_CTRL, AUICH_RR);
                   1530:        DELAY(100);
                   1531:
                   1532:        /* turn time delta into us */
                   1533:        wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec;
                   1534:
                   1535: #if 0
                   1536:        auich_freem(sc, temp_buffer, M_DEVBUF);
                   1537: #endif
                   1538:
                   1539:        if (nciv == ociv) {
                   1540:                printf("%s: ac97 link rate calibration timed out after %d us\n",
                   1541:                       sc->sc_dev.dv_xname, wait_us);
                   1542:                return (ac97rate);
                   1543:        }
                   1544:
                   1545:        actual_48k_rate = (bytes * 250000) / wait_us;
                   1546:
                   1547:        if (actual_48k_rate <= 48500)
                   1548:                ac97rate = AUICH_FIXED_RATE;
                   1549:        else
                   1550:                ac97rate = actual_48k_rate;
                   1551:
                   1552:        printf("%s: measured ac97 link rate at %d Hz",
                   1553:               sc->sc_dev.dv_xname, actual_48k_rate);
                   1554:        if (ac97rate != actual_48k_rate)
                   1555:                printf(", will use %d Hz", ac97rate);
                   1556:        printf("\n");
                   1557:
                   1558:        return (ac97rate);
                   1559: }

CVSweb