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

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

1.1       nbrk        1: /*     $OpenBSD: azalia.c,v 1.29 2007/08/02 17:13:31 reyk Exp $        */
                      2: /*     $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */
                      3:
                      4: /*-
                      5:  * Copyright (c) 2005 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by TAMURA Kent
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *        This product includes software developed by the NetBSD
                     22:  *        Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  * High Definition Audio Specification
                     42:  *     ftp://download.intel.com/standards/hdaudio/pdf/HDAudio_03.pdf
                     43:  *
                     44:  *
                     45:  * TO DO:
                     46:  *  - S/PDIF
                     47:  *  - power hook
                     48:  *  - multiple codecs (needed?)
                     49:  *  - multiple streams (needed?)
                     50:  */
                     51:
                     52: #include <sys/cdefs.h>
                     53: #ifdef NETBSD_GOOP
                     54: __KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.15 2005/09/29 04:14:03 kent Exp $");
                     55: #endif
                     56:
                     57: #include <sys/param.h>
                     58: #include <sys/device.h>
                     59: #include <sys/malloc.h>
                     60: #include <sys/systm.h>
                     61: #include <uvm/uvm_param.h>
                     62: #include <dev/audio_if.h>
                     63: #include <dev/auconv.h>
                     64: #include <dev/pci/pcidevs.h>
                     65: #include <dev/pci/pcivar.h>
                     66:
                     67: #include <dev/pci/azalia.h>
                     68:
                     69: typedef struct audio_params audio_params_t;
                     70: #ifndef BUS_DMA_NOCACHE
                     71: #define        BUS_DMA_NOCACHE 0
                     72: #endif
                     73: #define        auconv_delete_encodings(x...)
                     74: #define        auconv_query_encoding(x...)     (EINVAL)
                     75: #define        auconv_create_encodings(x...)   (0)
                     76:
                     77: struct audio_format {
                     78:        void *driver_data;
                     79:        int32_t mode;
                     80:        u_int encoding;
                     81:        u_int validbits;
                     82:        u_int precision;
                     83:        u_int channels;
                     84:        u_int channel_mask;
                     85: #define        AUFMT_UNKNOWN_POSITION          0U
                     86: #define        AUFMT_FRONT_LEFT                0x00001U /* USB audio compatible */
                     87: #define        AUFMT_FRONT_RIGHT               0x00002U /* USB audio compatible */
                     88: #define        AUFMT_FRONT_CENTER              0x00004U /* USB audio compatible */
                     89: #define        AUFMT_LOW_FREQUENCY             0x00008U /* USB audio compatible */
                     90: #define        AUFMT_BACK_LEFT                 0x00010U /* USB audio compatible */
                     91: #define        AUFMT_BACK_RIGHT                0x00020U /* USB audio compatible */
                     92: #define        AUFMT_FRONT_LEFT_OF_CENTER      0x00040U /* USB audio compatible */
                     93: #define        AUFMT_FRONT_RIGHT_OF_CENTER     0x00080U /* USB audio compatible */
                     94: #define        AUFMT_BACK_CENTER               0x00100U /* USB audio compatible */
                     95: #define        AUFMT_SIDE_LEFT                 0x00200U /* USB audio compatible */
                     96: #define        AUFMT_SIDE_RIGHT                0x00400U /* USB audio compatible */
                     97: #define        AUFMT_TOP_CENTER                0x00800U /* USB audio compatible */
                     98: #define        AUFMT_TOP_FRONT_LEFT            0x01000U
                     99: #define        AUFMT_TOP_FRONT_CENTER          0x02000U
                    100: #define        AUFMT_TOP_FRONT_RIGHT           0x04000U
                    101: #define        AUFMT_TOP_BACK_LEFT             0x08000U
                    102: #define        AUFMT_TOP_BACK_CENTER           0x10000U
                    103: #define        AUFMT_TOP_BACK_RIGHT            0x20000U
                    104:
                    105: #define        AUFMT_MONAURAL          AUFMT_FRONT_CENTER
                    106: #define        AUFMT_STEREO            (AUFMT_FRONT_LEFT | AUFMT_FRONT_RIGHT)
                    107: #define        AUFMT_SURROUND4         (AUFMT_STEREO | AUFMT_BACK_LEFT \
                    108:                                | AUFMT_BACK_RIGHT)
                    109: #define        AUFMT_DOLBY_5_1         (AUFMT_SURROUND4 | AUFMT_FRONT_CENTER \
                    110:                                | AUFMT_LOW_FREQUENCY)
                    111:
                    112:        /**
                    113:         * 0: frequency[0] is lower limit, and frequency[1] is higher limit.
                    114:         * 1-16: frequency[0] to frequency[frequency_type-1] are valid.
                    115:         */
                    116:        u_int frequency_type;
                    117:
                    118: #define        AUFMT_MAX_FREQUENCIES   16
                    119:        /**
                    120:         * sampling rates
                    121:         */
                    122:        u_int frequency[AUFMT_MAX_FREQUENCIES];
                    123: };
                    124:
                    125: #define        AUFMT_INVALIDATE(fmt)   (fmt)->mode |= 0x80000000
                    126: #define        AUFMT_VALIDATE(fmt)     (fmt)->mode &= 0x7fffffff
                    127: #define        AUFMT_IS_VALID(fmt)     (((fmt)->mode & 0x80000000) == 0)
                    128:
                    129: /* ----------------------------------------------------------------
                    130:  * ICH6/ICH7 constant values
                    131:  * ---------------------------------------------------------------- */
                    132:
                    133: /* PCI registers */
                    134: #define ICH_PCI_HDBARL 0x10
                    135: #define ICH_PCI_HDBARU 0x14
                    136: #define ICH_PCI_HDCTL  0x40
                    137: #define                ICH_PCI_HDCTL_CLKDETCLR         0x08
                    138: #define                ICH_PCI_HDCTL_CLKDETEN          0x04
                    139: #define                ICH_PCI_HDCTL_CLKDETINV         0x02
                    140: #define                ICH_PCI_HDCTL_SIGNALMODE        0x01
                    141:
                    142: /* internal types */
                    143:
                    144: typedef struct {
                    145:        bus_dmamap_t map;
                    146:        caddr_t addr;           /* kernel virtual address */
                    147:        bus_dma_segment_t segments[1];
                    148:        size_t size;
                    149: } azalia_dma_t;
                    150: #define AZALIA_DMA_DMAADDR(p)  ((p)->map->dm_segs[0].ds_addr)
                    151:
                    152: typedef struct {
                    153:        struct azalia_t *az;
                    154:        int regbase;
                    155:        int number;
                    156:        int dir;                /* AUMODE_PLAY or AUMODE_RECORD */
                    157:        uint32_t intr_bit;
                    158:        azalia_dma_t bdlist;
                    159:        azalia_dma_t buffer;
                    160:        void (*intr)(void*);
                    161:        void *intr_arg;
                    162: } stream_t;
                    163: #define STR_READ_1(s, r)       \
                    164:        bus_space_read_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
                    165: #define STR_READ_2(s, r)       \
                    166:        bus_space_read_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
                    167: #define STR_READ_4(s, r)       \
                    168:        bus_space_read_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
                    169: #define STR_WRITE_1(s, r, v)   \
                    170:        bus_space_write_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
                    171: #define STR_WRITE_2(s, r, v)   \
                    172:        bus_space_write_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
                    173: #define STR_WRITE_4(s, r, v)   \
                    174:        bus_space_write_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
                    175:
                    176: typedef struct azalia_t {
                    177:        struct device dev;
                    178:        struct device *audiodev;
                    179:
                    180:        pci_chipset_tag_t pc;
                    181:        void *ih;
                    182:        bus_space_tag_t iot;
                    183:        bus_space_handle_t ioh;
                    184:        bus_size_t map_size;
                    185:        bus_dma_tag_t dmat;
                    186:        pcireg_t pciid;
                    187:        uint32_t subid;
                    188:
                    189:        codec_t codecs[15];
                    190:        int ncodecs;            /* number of codecs */
                    191:        int codecno;            /* index of the using codec */
                    192:
                    193:        azalia_dma_t corb_dma;
                    194:        int corb_size;
                    195:        azalia_dma_t rirb_dma;
                    196:        int rirb_size;
                    197:        int rirb_rp;
                    198: #define UNSOLQ_SIZE    256
                    199:        rirb_entry_t *unsolq;
                    200:        int unsolq_wp;
                    201:        int unsolq_rp;
                    202:        boolean_t unsolq_kick;
                    203:
                    204:        boolean_t ok64;
                    205:        int nistreams, nostreams, nbstreams;
                    206:        stream_t pstream;
                    207:        stream_t rstream;
                    208: } azalia_t;
                    209: #define XNAME(sc)              ((sc)->dev.dv_xname)
                    210: #define AZ_READ_1(z, r)                bus_space_read_1((z)->iot, (z)->ioh, HDA_##r)
                    211: #define AZ_READ_2(z, r)                bus_space_read_2((z)->iot, (z)->ioh, HDA_##r)
                    212: #define AZ_READ_4(z, r)                bus_space_read_4((z)->iot, (z)->ioh, HDA_##r)
                    213: #define AZ_WRITE_1(z, r, v)    bus_space_write_1((z)->iot, (z)->ioh, HDA_##r, v)
                    214: #define AZ_WRITE_2(z, r, v)    bus_space_write_2((z)->iot, (z)->ioh, HDA_##r, v)
                    215: #define AZ_WRITE_4(z, r, v)    bus_space_write_4((z)->iot, (z)->ioh, HDA_##r, v)
                    216:
                    217:
                    218: /* prototypes */
                    219: int    azalia_pci_match(struct device *, void *, void *);
                    220: void   azalia_pci_attach(struct device *, struct device *, void *);
                    221: int    azalia_pci_activate(struct device *, enum devact);
                    222: int    azalia_pci_detach(struct device *, int);
                    223: int    azalia_intr(void *);
                    224: int    azalia_attach(azalia_t *);
                    225: void   azalia_attach_intr(struct device *);
                    226: int    azalia_init_corb(azalia_t *);
                    227: int    azalia_delete_corb(azalia_t *);
                    228: int    azalia_init_rirb(azalia_t *);
                    229: int    azalia_delete_rirb(azalia_t *);
                    230: int    azalia_set_command(azalia_t *, nid_t, int, uint32_t,
                    231:        uint32_t);
                    232: int    azalia_get_response(azalia_t *, uint32_t *);
                    233: void   azalia_rirb_kick_unsol_events(azalia_t *);
                    234: void   azalia_rirb_intr(azalia_t *);
                    235: int    azalia_alloc_dmamem(azalia_t *, size_t, size_t, azalia_dma_t *);
                    236: int    azalia_free_dmamem(const azalia_t *, azalia_dma_t*);
                    237:
                    238: int    azalia_codec_init(codec_t *);
                    239: int    azalia_codec_delete(codec_t *);
                    240: void   azalia_codec_add_bits(codec_t *, int, uint32_t, int);
                    241: void   azalia_codec_add_format(codec_t *, int, int, int, uint32_t,
                    242:        int32_t);
                    243: int    azalia_codec_comresp(const codec_t *, nid_t, uint32_t,
                    244:        uint32_t, uint32_t *);
                    245: int    azalia_codec_connect_stream(codec_t *, int, uint16_t, int);
                    246:
                    247: int    azalia_widget_init(widget_t *, const codec_t *, int);
                    248: int    azalia_widget_init_audio(widget_t *, const codec_t *);
                    249: int    azalia_widget_print_audio(const widget_t *, const char *);
                    250: int    azalia_widget_init_pin(widget_t *, const codec_t *);
                    251: int    azalia_widget_print_pin(const widget_t *);
                    252: int    azalia_widget_init_connection(widget_t *, const codec_t *);
                    253:
                    254: int    azalia_stream_init(stream_t *, azalia_t *, int, int, int);
                    255: int    azalia_stream_delete(stream_t *, azalia_t *);
                    256: int    azalia_stream_reset(stream_t *);
                    257: int    azalia_stream_start(stream_t *, void *, void *, int,
                    258:        void (*)(void *), void *, uint16_t);
                    259: int    azalia_stream_halt(stream_t *);
                    260: int    azalia_stream_intr(stream_t *, uint32_t);
                    261:
                    262: int    azalia_open(void *, int);
                    263: void   azalia_close(void *);
                    264: int    azalia_query_encoding(void *, audio_encoding_t *);
                    265: int    azalia_set_params(void *, int, int, audio_params_t *,
                    266:        audio_params_t *);
                    267: int    azalia_round_blocksize(void *, int);
                    268: int    azalia_halt_output(void *);
                    269: int    azalia_halt_input(void *);
                    270: int    azalia_getdev(void *, struct audio_device *);
                    271: int    azalia_set_port(void *, mixer_ctrl_t *);
                    272: int    azalia_get_port(void *, mixer_ctrl_t *);
                    273: int    azalia_query_devinfo(void *, mixer_devinfo_t *);
                    274: void   *azalia_allocm(void *, int, size_t, int, int);
                    275: void   azalia_freem(void *, void *, int);
                    276: size_t azalia_round_buffersize(void *, int, size_t);
                    277: int    azalia_get_props(void *);
                    278: int    azalia_trigger_output(void *, void *, void *, int,
                    279:        void (*)(void *), void *, audio_params_t *);
                    280: int    azalia_trigger_input(void *, void *, void *, int,
                    281:        void (*)(void *), void *, audio_params_t *);
                    282:
                    283: int    azalia_params2fmt(const audio_params_t *, uint16_t *);
                    284: int azalia_create_encodings(struct audio_format *, int,
                    285:     struct audio_encoding_set **);
                    286:
                    287: /* variables */
                    288: struct cfattach azalia_ca = {
                    289:        sizeof(azalia_t), azalia_pci_match, azalia_pci_attach,
                    290:        azalia_pci_detach, azalia_pci_activate
                    291: };
                    292:
                    293: struct cfdriver azalia_cd = {
                    294:        NULL, "azalia", DV_DULL
                    295: };
                    296:
                    297: struct audio_hw_if azalia_hw_if = {
                    298:        azalia_open,
                    299:        azalia_close,
                    300:        NULL,                   /* drain */
                    301:        azalia_query_encoding,
                    302:        azalia_set_params,
                    303:        azalia_round_blocksize,
                    304:        NULL,                   /* commit_settings */
                    305:        NULL,                   /* init_output */
                    306:        NULL,                   /* init_input */
                    307:        NULL,                   /* start_output */
                    308:        NULL,                   /* start_input */
                    309:        azalia_halt_output,
                    310:        azalia_halt_input,
                    311:        NULL,                   /* speaker_ctl */
                    312:        azalia_getdev,
                    313:        NULL,                   /* setfd */
                    314:        azalia_set_port,
                    315:        azalia_get_port,
                    316:        azalia_query_devinfo,
                    317:        azalia_allocm,
                    318:        azalia_freem,
                    319:        azalia_round_buffersize,
                    320:        NULL,                   /* mappage */
                    321:        azalia_get_props,
                    322:        azalia_trigger_output,
                    323:        azalia_trigger_input,
                    324: };
                    325:
                    326: static const char *pin_colors[16] = {
                    327:        "unknown", "black", "gray", "blue",
                    328:        "green", "red", "orange", "yellow",
                    329:        "purple", "pink", "col0a", "col0b",
                    330:        "col0c", "col0d", "white", "other"};
                    331: #ifdef AZALIA_DEBUG
                    332: static const char *pin_devices[16] = {
                    333:        "line-out", AudioNspeaker, AudioNheadphone, AudioNcd,
                    334:        "SPDIF-out", "digital-out", "modem-line", "modem-handset",
                    335:        "line-in", AudioNaux, AudioNmicrophone, "telephony",
                    336:        "SPDIF-in", "digital-in", "dev0e", "other"};
                    337: #endif
                    338:
                    339: /* ================================================================
                    340:  * PCI functions
                    341:  * ================================================================ */
                    342:
                    343: #define PCI_ID_CODE0(v, p)     PCI_ID_CODE(PCI_VENDOR_##v, PCI_PRODUCT_##v##_##p)
                    344: #define PCIID_NVIDIA_MCP51     PCI_ID_CODE0(NVIDIA, MCP51_HDA)
                    345: #define PCIID_NVIDIA_MCP55     PCI_ID_CODE0(NVIDIA, MCP55_HDA)
                    346: #define PCIID_ALI_M5461                PCI_ID_CODE0(ALI, M5461)
                    347: #define PCIID_VIATECH_HDA      PCI_ID_CODE0(VIATECH, HDA)
                    348:
                    349: int
                    350: azalia_pci_match(struct device *parent, void *match, void *aux)
                    351: {
                    352:        struct pci_attach_args *pa;
                    353:
                    354:        pa = aux;
                    355:        if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MULTIMEDIA
                    356:            && PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MULTIMEDIA_HDAUDIO)
                    357:                return 1;
                    358:        return 0;
                    359: }
                    360:
                    361: void
                    362: azalia_pci_attach(struct device *parent, struct device *self, void *aux)
                    363: {
                    364:        azalia_t *sc;
                    365:        struct pci_attach_args *pa;
                    366:        pcireg_t v;
                    367:        pci_intr_handle_t ih;
                    368:        const char *intrrupt_str;
                    369:
                    370:        sc = (azalia_t*)self;
                    371:        pa = aux;
                    372:
                    373:        sc->dmat = pa->pa_dmat;
                    374:
                    375:        v = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_PCI_HDBARL);
                    376:        v &= PCI_MAPREG_TYPE_MASK | PCI_MAPREG_MEM_TYPE_MASK;
                    377:        if (pci_mapreg_map(pa, ICH_PCI_HDBARL, v, 0,
                    378:                           &sc->iot, &sc->ioh, NULL, &sc->map_size, 0)) {
                    379:                printf(": can't map device i/o space\n");
                    380:                return;
                    381:        }
                    382:
                    383:        /* enable back-to-back */
                    384:        v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
                    385:        pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
                    386:            v | PCI_COMMAND_BACKTOBACK_ENABLE);
                    387:
                    388:        v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x44);
                    389:        pci_conf_write(pa->pa_pc, pa->pa_tag, 0x44, v & (~0x7));
                    390:
                    391:        /* interrupt */
                    392:        if (pci_intr_map(pa, &ih)) {
                    393:                printf(": can't map interrupt\n");
                    394:                return;
                    395:        }
                    396:        sc->pc = pa->pa_pc;
                    397:        intrrupt_str = pci_intr_string(pa->pa_pc, ih);
                    398:        sc->ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, azalia_intr,
                    399:            sc, sc->dev.dv_xname);
                    400:        if (sc->ih == NULL) {
                    401:                printf(": can't establish interrupt");
                    402:                if (intrrupt_str != NULL)
                    403:                        printf(" at %s", intrrupt_str);
                    404:                printf("\n");
                    405:                return;
                    406:        }
                    407:        printf(": %s\n", intrrupt_str);
                    408:
                    409:        sc->pciid = pa->pa_id;
                    410:
                    411:        if (azalia_attach(sc)) {
                    412:                printf("%s: initialization failure\n", XNAME(sc));
                    413:                azalia_pci_detach(self, 0);
                    414:                return;
                    415:        }
                    416:        sc->subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
                    417:
                    418:        azalia_attach_intr(self);
                    419: }
                    420:
                    421: int
                    422: azalia_pci_activate(struct device *self, enum devact act)
                    423: {
                    424:        azalia_t *sc;
                    425:        int ret;
                    426:
                    427:        sc = (azalia_t*)self;
                    428:        ret = 0;
                    429:        switch (act) {
                    430:        case DVACT_ACTIVATE:
                    431:                return ret;
                    432:        case DVACT_DEACTIVATE:
                    433:                if (sc->audiodev != NULL)
                    434:                        ret = config_deactivate(sc->audiodev);
                    435:                return ret;
                    436:        }
                    437:        return EOPNOTSUPP;
                    438: }
                    439:
                    440: int
                    441: azalia_pci_detach(struct device *self, int flags)
                    442: {
                    443:        azalia_t *az;
                    444:        int i;
                    445:
                    446:        DPRINTF(("%s\n", __func__));
                    447:        az = (azalia_t*)self;
                    448:        if (az->audiodev != NULL) {
                    449:                config_detach(az->audiodev, flags);
                    450:                az->audiodev = NULL;
                    451:        }
                    452:
                    453:        DPRINTF(("%s: delete streams\n", __func__));
                    454:        azalia_stream_delete(&az->rstream, az);
                    455:        azalia_stream_delete(&az->pstream, az);
                    456:
                    457:        DPRINTF(("%s: delete codecs\n", __func__));
                    458:        for (i = 0; i < az->ncodecs; i++) {
                    459:                azalia_codec_delete(&az->codecs[i]);
                    460:        }
                    461:        az->ncodecs = 0;
                    462:
                    463:        DPRINTF(("%s: delete CORB and RIRB\n", __func__));
                    464:        azalia_delete_corb(az);
                    465:        azalia_delete_rirb(az);
                    466:
                    467:        DPRINTF(("%s: delete PCI resources\n", __func__));
                    468:        if (az->ih != NULL) {
                    469:                pci_intr_disestablish(az->pc, az->ih);
                    470:                az->ih = NULL;
                    471:        }
                    472:        if (az->map_size != 0) {
                    473:                bus_space_unmap(az->iot, az->ioh, az->map_size);
                    474:                az->map_size = 0;
                    475:        }
                    476:        return 0;
                    477: }
                    478:
                    479: int
                    480: azalia_intr(void *v)
                    481: {
                    482:        azalia_t *az = v;
                    483:        int ret = 0;
                    484:        uint32_t intsts;
                    485:        uint8_t rirbsts, rirbctl;
                    486:
                    487:        intsts = AZ_READ_4(az, INTSTS);
                    488:        if (intsts == 0)
                    489:                return (0);
                    490:
                    491:        AZ_WRITE_4(az, INTSTS, intsts);
                    492:
                    493:        ret += azalia_stream_intr(&az->pstream, intsts);
                    494:        ret += azalia_stream_intr(&az->rstream, intsts);
                    495:
                    496:        rirbctl = AZ_READ_1(az, RIRBCTL);
                    497:        rirbsts = AZ_READ_1(az, RIRBSTS);
                    498:
                    499:        if (intsts & HDA_INTCTL_CIE) {
                    500:                if (rirbctl & HDA_RIRBCTL_RINTCTL) {
                    501:                        if (rirbsts & HDA_RIRBSTS_RINTFL)
                    502:                                azalia_rirb_intr(az);
                    503:                }
                    504:        }
                    505:
                    506:        return (1);
                    507: }
                    508:
                    509: /* ================================================================
                    510:  * HDA controller functions
                    511:  * ================================================================ */
                    512:
                    513: int
                    514: azalia_attach(azalia_t *az)
                    515: {
                    516:        int i, n;
                    517:        uint32_t gctl;
                    518:        uint16_t gcap;
                    519:        uint16_t statests;
                    520:
                    521:        printf("%s: host: High Definition Audio rev. %d.%d\n",
                    522:            XNAME(az), AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN));
                    523:        gcap = AZ_READ_2(az, GCAP);
                    524:        az->nistreams = HDA_GCAP_ISS(gcap);
                    525:        az->nostreams = HDA_GCAP_OSS(gcap);
                    526:        az->nbstreams = HDA_GCAP_BSS(gcap);
                    527:        az->ok64 = (gcap & HDA_GCAP_64OK) != 0;
                    528:        DPRINTF(("%s: host: %d output, %d input, and %d bidi streams\n",
                    529:            XNAME(az), az->nostreams, az->nistreams, az->nbstreams));
                    530:
                    531:        /* 4.2.2 Starting the High Definition Audio Controller */
                    532:        DPRINTF(("%s: resetting\n", __func__));
                    533:        gctl = AZ_READ_4(az, GCTL);
                    534:        AZ_WRITE_4(az, GCTL, gctl & ~HDA_GCTL_CRST);
                    535:        for (i = 5000; i >= 0; i--) {
                    536:                DELAY(10);
                    537:                if ((AZ_READ_4(az, GCTL) & HDA_GCTL_CRST) == 0)
                    538:                        break;
                    539:        }
                    540:        DPRINTF(("%s: reset counter = %d\n", __func__, i));
                    541:        if (i <= 0) {
                    542:                printf("%s: reset failure\n", XNAME(az));
                    543:                return ETIMEDOUT;
                    544:        }
                    545:        DELAY(1000);
                    546:        gctl = AZ_READ_4(az, GCTL);
                    547:        AZ_WRITE_4(az, GCTL, gctl | HDA_GCTL_CRST);
                    548:        for (i = 5000; i >= 0; i--) {
                    549:                DELAY(10);
                    550:                if (AZ_READ_4(az, GCTL) & HDA_GCTL_CRST)
                    551:                        break;
                    552:        }
                    553:        DPRINTF(("%s: reset counter = %d\n", __func__, i));
                    554:        if (i <= 0) {
                    555:                printf("%s: reset-exit failure\n", XNAME(az));
                    556:                return ETIMEDOUT;
                    557:        }
                    558:
                    559:        /* enable unsolicited response */
                    560:        gctl = AZ_READ_4(az, GCTL);
                    561:        AZ_WRITE_4(az, GCTL, gctl | HDA_GCTL_UNSOL);
                    562:
                    563:        /* 4.3 Codec discovery */
                    564:        DELAY(1000);
                    565:        statests = AZ_READ_2(az, STATESTS);
                    566:        for (i = 0, n = 0; i < 15; i++) {
                    567:                if ((statests >> i) & 1) {
                    568:                        DPRINTF(("%s: found a codec at #%d\n", XNAME(az), i));
                    569:                        az->codecs[n].address = i;
                    570:                        az->codecs[n++].az = az;
                    571:                }
                    572:        }
                    573:        az->ncodecs = n;
                    574:        if (az->ncodecs < 1) {
                    575:                printf("%s: No HD-Audio codecs\n", XNAME(az));
                    576:                return -1;
                    577:        }
                    578:        return 0;
                    579: }
                    580:
                    581: void
                    582: azalia_attach_intr(struct device *self)
                    583: {
                    584:        azalia_t *az;
                    585:        int err, i, c;
                    586:
                    587:        az = (azalia_t*)self;
                    588:
                    589:        AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE);
                    590:        AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS);
                    591:        AZ_WRITE_4(az, INTSTS, HDA_INTSTS_CIS | HDA_INTSTS_GIS);
                    592:        AZ_WRITE_4(az, DPLBASE, 0);
                    593:        AZ_WRITE_4(az, DPUBASE, 0);
                    594:
                    595:        /* 4.4.1 Command Outbound Ring Buffer */
                    596:        if (azalia_init_corb(az))
                    597:                goto err_exit;
                    598:        /* 4.4.2 Response Inbound Ring Buffer */
                    599:        if (azalia_init_rirb(az))
                    600:                goto err_exit;
                    601:
                    602:        AZ_WRITE_4(az, INTCTL,
                    603:            AZ_READ_4(az, INTCTL) | HDA_INTCTL_CIE | HDA_INTCTL_GIE);
                    604:
                    605:        c = -1;
                    606:        for (i = 0; i < az->ncodecs; i++) {
                    607:                err = azalia_codec_init(&az->codecs[i]);
                    608:                if (!err && c < 0)
                    609:                        c = i;
                    610:        }
                    611:        if (c < 0)
                    612:                goto err_exit;
                    613:        /* Use the first audio codec */
                    614:        az->codecno = c;
                    615:        DPRINTF(("%s: using the #%d codec\n", XNAME(az), az->codecno));
                    616:
                    617:        if (azalia_stream_init(&az->pstream, az, az->nistreams + 0,
                    618:            1, AUMODE_PLAY))
                    619:                goto err_exit;
                    620:        if (azalia_stream_init(&az->rstream, az, 0, 2, AUMODE_RECORD))
                    621:                goto err_exit;
                    622:
                    623:        az->audiodev = audio_attach_mi(&azalia_hw_if, az, &az->dev);
                    624:        return;
                    625: err_exit:
                    626:        azalia_pci_detach(self, 0);
                    627:        return;
                    628: }
                    629:
                    630: int
                    631: azalia_init_corb(azalia_t *az)
                    632: {
                    633:        int entries, err, i;
                    634:        uint16_t corbrp, corbwp;
                    635:        uint8_t corbsize, cap, corbctl;
                    636:
                    637:        /* stop the CORB */
                    638:        corbctl = AZ_READ_1(az, CORBCTL);
                    639:        if (corbctl & HDA_CORBCTL_CORBRUN) { /* running? */
                    640:                AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN);
                    641:                for (i = 5000; i >= 0; i--) {
                    642:                        DELAY(10);
                    643:                        corbctl = AZ_READ_1(az, CORBCTL);
                    644:                        if ((corbctl & HDA_CORBCTL_CORBRUN) == 0)
                    645:                                break;
                    646:                }
                    647:                if (i <= 0) {
                    648:                        printf("%s: CORB is running\n", XNAME(az));
                    649:                        return EBUSY;
                    650:                }
                    651:        }
                    652:
                    653:        /* determine CORB size */
                    654:        corbsize = AZ_READ_1(az, CORBSIZE);
                    655:        cap = corbsize & HDA_CORBSIZE_CORBSZCAP_MASK;
                    656:        corbsize &= ~HDA_CORBSIZE_CORBSIZE_MASK;
                    657:        if (cap & HDA_CORBSIZE_CORBSZCAP_256) {
                    658:                entries = 256;
                    659:                corbsize |= HDA_CORBSIZE_CORBSIZE_256;
                    660:        } else if (cap & HDA_CORBSIZE_CORBSZCAP_16) {
                    661:                entries = 16;
                    662:                corbsize |= HDA_CORBSIZE_CORBSIZE_16;
                    663:        } else if (cap & HDA_CORBSIZE_CORBSZCAP_2) {
                    664:                entries = 2;
                    665:                corbsize |= HDA_CORBSIZE_CORBSIZE_2;
                    666:        } else {
                    667:                printf("%s: Invalid CORBSZCAP: 0x%2x\n", XNAME(az), cap);
                    668:                return -1;
                    669:        }
                    670:
                    671:        err = azalia_alloc_dmamem(az, entries * sizeof(corb_entry_t),
                    672:            128, &az->corb_dma);
                    673:        if (err) {
                    674:                printf("%s: can't allocate CORB buffer\n", XNAME(az));
                    675:                return err;
                    676:        }
                    677:        AZ_WRITE_4(az, CORBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->corb_dma));
                    678:        AZ_WRITE_4(az, CORBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->corb_dma)));
                    679:        AZ_WRITE_1(az, CORBSIZE, corbsize);
                    680:        az->corb_size = entries;
                    681:
                    682:        DPRINTF(("%s: CORB allocation succeeded.\n", __func__));
                    683:
                    684:        /* reset CORBRP */
                    685:        corbrp = AZ_READ_2(az, CORBRP);
                    686:        AZ_WRITE_2(az, CORBRP, corbrp | HDA_CORBRP_CORBRPRST);
                    687:        AZ_WRITE_2(az, CORBRP, corbrp & ~HDA_CORBRP_CORBRPRST);
                    688:        for (i = 5000; i >= 0; i--) {
                    689:                DELAY(10);
                    690:                corbrp = AZ_READ_2(az, CORBRP);
                    691:                if ((corbrp & HDA_CORBRP_CORBRPRST) == 0)
                    692:                        break;
                    693:        }
                    694:        if (i <= 0) {
                    695:                printf("%s: CORBRP reset failure\n", XNAME(az));
                    696:                return -1;
                    697:        }
                    698:        DPRINTF(("%s: CORBWP=%d; size=%d\n", __func__,
                    699:                 AZ_READ_2(az, CORBRP) & HDA_CORBRP_CORBRP, az->corb_size));
                    700:
                    701:        /* clear CORBWP */
                    702:        corbwp = AZ_READ_2(az, CORBWP);
                    703:        AZ_WRITE_2(az, CORBWP, corbwp & ~HDA_CORBWP_CORBWP);
                    704:
                    705:        /* Run! */
                    706:        corbctl = AZ_READ_1(az, CORBCTL);
                    707:        AZ_WRITE_1(az, CORBCTL, corbctl | HDA_CORBCTL_CORBRUN);
                    708:        return 0;
                    709: }
                    710:
                    711: int
                    712: azalia_delete_corb(azalia_t *az)
                    713: {
                    714:        int i;
                    715:        uint8_t corbctl;
                    716:
                    717:        if (az->corb_dma.addr == NULL)
                    718:                return 0;
                    719:        /* stop the CORB */
                    720:        corbctl = AZ_READ_1(az, CORBCTL);
                    721:        AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN);
                    722:        for (i = 5000; i >= 0; i--) {
                    723:                DELAY(10);
                    724:                corbctl = AZ_READ_1(az, CORBCTL);
                    725:                if ((corbctl & HDA_CORBCTL_CORBRUN) == 0)
                    726:                        break;
                    727:        }
                    728:        azalia_free_dmamem(az, &az->corb_dma);
                    729:        return 0;
                    730: }
                    731:
                    732: int
                    733: azalia_init_rirb(azalia_t *az)
                    734: {
                    735:        int entries, err, i;
                    736:        uint16_t rirbwp;
                    737:        uint8_t rirbsize, cap, rirbctl;
                    738:
                    739:        /* stop the RIRB */
                    740:        rirbctl = AZ_READ_1(az, RIRBCTL);
                    741:        if (rirbctl & HDA_RIRBCTL_RIRBDMAEN) { /* running? */
                    742:                AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN);
                    743:                for (i = 5000; i >= 0; i--) {
                    744:                        DELAY(10);
                    745:                        rirbctl = AZ_READ_1(az, RIRBCTL);
                    746:                        if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN) == 0)
                    747:                                break;
                    748:                }
                    749:                if (i <= 0) {
                    750:                        printf("%s: RIRB is running\n", XNAME(az));
                    751:                        return EBUSY;
                    752:                }
                    753:        }
                    754:
                    755:        /* determine RIRB size */
                    756:        rirbsize = AZ_READ_1(az, RIRBSIZE);
                    757:        cap = rirbsize & HDA_RIRBSIZE_RIRBSZCAP_MASK;
                    758:        rirbsize &= ~HDA_RIRBSIZE_RIRBSIZE_MASK;
                    759:        if (cap & HDA_RIRBSIZE_RIRBSZCAP_256) {
                    760:                entries = 256;
                    761:                rirbsize |= HDA_RIRBSIZE_RIRBSIZE_256;
                    762:        } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_16) {
                    763:                entries = 16;
                    764:                rirbsize |= HDA_RIRBSIZE_RIRBSIZE_16;
                    765:        } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_2) {
                    766:                entries = 2;
                    767:                rirbsize |= HDA_RIRBSIZE_RIRBSIZE_2;
                    768:        } else {
                    769:                printf("%s: Invalid RIRBSZCAP: 0x%2x\n", XNAME(az), cap);
                    770:                return -1;
                    771:        }
                    772:
                    773:        err = azalia_alloc_dmamem(az, entries * sizeof(rirb_entry_t),
                    774:            128, &az->rirb_dma);
                    775:        if (err) {
                    776:                printf("%s: can't allocate RIRB buffer\n", XNAME(az));
                    777:                return err;
                    778:        }
                    779:        AZ_WRITE_4(az, RIRBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->rirb_dma));
                    780:        AZ_WRITE_4(az, RIRBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->rirb_dma)));
                    781:        AZ_WRITE_1(az, RIRBSIZE, rirbsize);
                    782:        az->rirb_size = entries;
                    783:
                    784:        DPRINTF(("%s: RIRB allocation succeeded.\n", __func__));
                    785:
                    786:        /* setup the unsolicited response queue */
                    787:        az->unsolq_rp = 0;
                    788:        az->unsolq_wp = 0;
                    789:        az->unsolq_kick = FALSE;
                    790:        az->unsolq = malloc(sizeof(rirb_entry_t) * UNSOLQ_SIZE,
                    791:            M_DEVBUF, M_NOWAIT);
                    792:        if (az->unsolq == NULL) {
                    793:                DPRINTF(("%s: can't allocate unsolicited response queue.\n",
                    794:                    XNAME(az)));
                    795:                azalia_free_dmamem(az, &az->rirb_dma);
                    796:                return ENOMEM;
                    797:        }
                    798:        bzero(az->unsolq, sizeof(rirb_entry_t) * UNSOLQ_SIZE);
                    799:
                    800:        /* reset the write pointer */
                    801:        rirbwp = AZ_READ_2(az, RIRBWP);
                    802:        AZ_WRITE_2(az, RIRBWP, rirbwp | HDA_RIRBWP_RIRBWPRST);
                    803:
                    804:        /* clear the read pointer */
                    805:        az->rirb_rp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
                    806:        DPRINTF(("%s: RIRBRP=%d, size=%d\n", __func__, az->rirb_rp, az->rirb_size));
                    807:
                    808:        AZ_WRITE_2(az, RINTCNT, 1);
                    809:
                    810:        /* Run! */
                    811:        rirbctl = AZ_READ_1(az, RIRBCTL);
                    812:        AZ_WRITE_1(az, RIRBCTL, rirbctl |
                    813:            HDA_RIRBCTL_RIRBDMAEN | HDA_RIRBCTL_RINTCTL);
                    814:
                    815:        return (0);
                    816: }
                    817:
                    818: int
                    819: azalia_delete_rirb(azalia_t *az)
                    820: {
                    821:        int i;
                    822:        uint8_t rirbctl;
                    823:
                    824:        if (az->unsolq != NULL) {
                    825:                free(az->unsolq, M_DEVBUF);
                    826:                az->unsolq = NULL;
                    827:        }
                    828:        if (az->rirb_dma.addr == NULL)
                    829:                return 0;
                    830:        /* stop the RIRB */
                    831:        rirbctl = AZ_READ_1(az, RIRBCTL);
                    832:        AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN);
                    833:        for (i = 5000; i >= 0; i--) {
                    834:                DELAY(10);
                    835:                rirbctl = AZ_READ_1(az, RIRBCTL);
                    836:                if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN) == 0)
                    837:                        break;
                    838:        }
                    839:        azalia_free_dmamem(az, &az->rirb_dma);
                    840:        return 0;
                    841: }
                    842:
                    843: int
                    844: azalia_set_command(azalia_t *az, int caddr, nid_t nid, uint32_t control,
                    845:                   uint32_t param)
                    846: {
                    847:        corb_entry_t *corb;
                    848:        int  wp;
                    849:        uint32_t verb;
                    850:        uint16_t corbwp;
                    851:        uint8_t rirbctl;
                    852:
                    853: #ifdef DIAGNOSTIC
                    854:        if ((AZ_READ_1(az, CORBCTL) & HDA_CORBCTL_CORBRUN) == 0) {
                    855:                printf("%s: CORB is not running.\n", XNAME(az));
                    856:                return -1;
                    857:        }
                    858: #endif
                    859:        verb = (caddr << 28) | (nid << 20) | (control << 8) | param;
                    860:        corbwp = AZ_READ_2(az, CORBWP);
                    861:        wp = corbwp & HDA_CORBWP_CORBWP;
                    862:        corb = (corb_entry_t*)az->corb_dma.addr;
                    863:        if (++wp >= az->corb_size)
                    864:                wp = 0;
                    865:        corb[wp] = verb;
                    866:
                    867:        /* disable RIRB interrupts */
                    868:        rirbctl = AZ_READ_1(az, RIRBCTL);
                    869:        if (rirbctl & HDA_RIRBCTL_RINTCTL) {
                    870:                AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RINTCTL);
                    871:                azalia_rirb_intr(az);
                    872:        }
                    873:
                    874:        AZ_WRITE_2(az, CORBWP, (corbwp & ~HDA_CORBWP_CORBWP) | wp);
                    875: #if 0
                    876:        DPRINTF(("%s: caddr=%d nid=%d control=0x%x param=0x%x verb=0x%8.8x wp=%d\n",
                    877:                 __func__, caddr, nid, control, param, verb, wp));
                    878: #endif
                    879:        return 0;
                    880: }
                    881:
                    882: int
                    883: azalia_get_response(azalia_t *az, uint32_t *result)
                    884: {
                    885:        const rirb_entry_t *rirb;
                    886:        int i;
                    887:        uint16_t wp;
                    888:        uint8_t rirbctl;
                    889:
                    890: #ifdef DIAGNOSTIC
                    891:        if ((AZ_READ_1(az, RIRBCTL) & HDA_RIRBCTL_RIRBDMAEN) == 0) {
                    892:                printf("%s: RIRB is not running.\n", XNAME(az));
                    893:                return -1;
                    894:        }
                    895: #endif
                    896:        for (i = 5000; i >= 0; i--) {
                    897:                wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
                    898:                if (az->rirb_rp != wp)
                    899:                        break;
                    900:                DELAY(10);
                    901:        }
                    902:        if (i <= 0) {
                    903:                printf("%s: RIRB time out\n", XNAME(az));
                    904:                return ETIMEDOUT;
                    905:        }
                    906:        rirb = (rirb_entry_t*)az->rirb_dma.addr;
                    907:        for (;;) {
                    908:                if (++az->rirb_rp >= az->rirb_size)
                    909:                        az->rirb_rp = 0;
                    910:                if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL) {
                    911:                        az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp;
                    912:                        az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex;
                    913:                        az->unsolq_wp %= UNSOLQ_SIZE;
                    914:                } else
                    915:                        break;
                    916:        }
                    917:        if (result != NULL)
                    918:                *result = rirb[az->rirb_rp].resp;
                    919:
                    920:        azalia_rirb_kick_unsol_events(az);
                    921: #if 0
                    922:        for (i = 0; i < 16 /*az->rirb_size*/; i++) {
                    923:                DPRINTF(("rirb[%d] 0x%8.8x:0x%8.8x ", i, rirb[i].resp, rirb[i].resp_ex));
                    924:                if ((i % 2) == 1)
                    925:                        DPRINTF(("\n"));
                    926:        }
                    927: #endif
                    928:
                    929:        /* re-enable RIRB interrupts */
                    930:        rirbctl = AZ_READ_1(az, RIRBCTL);
                    931:        AZ_WRITE_1(az, RIRBCTL, rirbctl | HDA_RIRBCTL_RINTCTL);
                    932:
                    933:        return 0;
                    934: }
                    935:
                    936: void
                    937: azalia_rirb_kick_unsol_events(azalia_t *az)
                    938: {
                    939:        if (az->unsolq_kick)
                    940:                return;
                    941:        az->unsolq_kick = TRUE;
                    942:        while (az->unsolq_rp != az->unsolq_wp) {
                    943:                int i;
                    944:                int tag;
                    945:                codec_t *codec;
                    946:                i = RIRB_RESP_CODEC(az->unsolq[az->unsolq_rp].resp_ex);
                    947:                tag = RIRB_UNSOL_TAG(az->unsolq[az->unsolq_rp].resp);
                    948:                codec = &az->codecs[i];
                    949:                DPRINTF(("%s: codec#=%d tag=%d\n", __func__, i, tag));
                    950:                az->unsolq_rp++;
                    951:                az->unsolq_rp %= UNSOLQ_SIZE;
                    952:                if (codec->unsol_event != NULL)
                    953:                        codec->unsol_event(codec, tag);
                    954:        }
                    955:        az->unsolq_kick = FALSE;
                    956: }
                    957:
                    958: void
                    959: azalia_rirb_intr(azalia_t *az)
                    960: {
                    961:        const rirb_entry_t *rirb;
                    962:        uint16_t wp, rp;
                    963:        uint8_t rirbsts;
                    964:
                    965:        rirbsts = AZ_READ_1(az, RIRBSTS);
                    966:
                    967:        wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
                    968:        if (rp == wp)
                    969:                return;         /* interrupted but no data in RIRB */
                    970:        rirb = (rirb_entry_t*)az->rirb_dma.addr;
                    971:        while (az->rirb_rp != wp) {
                    972:                if (++az->rirb_rp >= az->rirb_size)
                    973:                        az->rirb_rp = 0;
                    974:                if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL) {
                    975:                        az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp;
                    976:                        az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex;
                    977:                        az->unsolq_wp %= UNSOLQ_SIZE;
                    978:                } else {
                    979:                        break;
                    980:                }
                    981:        }
                    982:
                    983:        azalia_rirb_kick_unsol_events(az);
                    984:
                    985:        AZ_WRITE_1(az, RIRBSTS,
                    986:            rirbsts | HDA_RIRBSTS_RIRBOIS | HDA_RIRBSTS_RINTFL);
                    987: }
                    988:
                    989: int
                    990: azalia_alloc_dmamem(azalia_t *az, size_t size, size_t align, azalia_dma_t *d)
                    991: {
                    992:        int err;
                    993:        int nsegs;
                    994:
                    995:        d->size = size;
                    996:        err = bus_dmamem_alloc(az->dmat, size, align, 0, d->segments, 1,
                    997:            &nsegs, BUS_DMA_NOWAIT);
                    998:        if (err)
                    999:                return err;
                   1000:        if (nsegs != 1)
                   1001:                goto free;
                   1002:        err = bus_dmamem_map(az->dmat, d->segments, 1, size,
                   1003:            &d->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_NOCACHE);
                   1004:        if (err)
                   1005:                goto free;
                   1006:        err = bus_dmamap_create(az->dmat, size, 1, size, 0,
                   1007:            BUS_DMA_NOWAIT, &d->map);
                   1008:        if (err)
                   1009:                goto unmap;
                   1010:        err = bus_dmamap_load(az->dmat, d->map, d->addr, size,
                   1011:            NULL, BUS_DMA_NOWAIT);
                   1012:        if (err)
                   1013:                goto destroy;
                   1014:
                   1015:        if (!az->ok64 && PTR_UPPER32(AZALIA_DMA_DMAADDR(d)) != 0) {
                   1016:                azalia_free_dmamem(az, d);
                   1017:                return -1;
                   1018:        }
                   1019:        return 0;
                   1020:
                   1021: destroy:
                   1022:        bus_dmamap_destroy(az->dmat, d->map);
                   1023: unmap:
                   1024:        bus_dmamem_unmap(az->dmat, d->addr, size);
                   1025: free:
                   1026:        bus_dmamem_free(az->dmat, d->segments, 1);
                   1027:        d->addr = NULL;
                   1028:        return err;
                   1029: }
                   1030:
                   1031: int
                   1032: azalia_free_dmamem(const azalia_t *az, azalia_dma_t* d)
                   1033: {
                   1034:        if (d->addr == NULL)
                   1035:                return 0;
                   1036:        bus_dmamap_unload(az->dmat, d->map);
                   1037:        bus_dmamap_destroy(az->dmat, d->map);
                   1038:        bus_dmamem_unmap(az->dmat, d->addr, d->size);
                   1039:        bus_dmamem_free(az->dmat, d->segments, 1);
                   1040:        d->addr = NULL;
                   1041:        return 0;
                   1042: }
                   1043:
                   1044: /* ================================================================
                   1045:  * HDA codec functions
                   1046:  * ================================================================ */
                   1047:
                   1048: int
                   1049: azalia_codec_init(codec_t *this)
                   1050: {
                   1051:        uint32_t rev, id, result;
                   1052:        int err, addr, n, i;
                   1053:        const char *vendor;
                   1054:
                   1055:        this->comresp = azalia_codec_comresp;
                   1056:        addr = this->address;
                   1057:        DPRINTF(("%s: information of codec[%d] follows:\n",
                   1058:            XNAME(this->az), addr));
                   1059:        /* codec vendor/device/revision */
                   1060:        err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
                   1061:            COP_REVISION_ID, &rev);
                   1062:        if (err)
                   1063:                return err;
                   1064:        err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
                   1065:            COP_VENDOR_ID, &id);
                   1066:        if (err)
                   1067:                return err;
                   1068:        this->vid = id;
                   1069:        this->subid = this->az->subid;
                   1070:        azalia_codec_init_vtbl(this);
                   1071:
                   1072:        printf("%s: codec:", XNAME(this->az));
                   1073:        if (this->name == NULL) {
                   1074:                vendor = pci_findvendor(id >> 16);
                   1075:                if (vendor == NULL)
                   1076:                        printf(" 0x%04x/0x%04x", id >> 16, id & 0xffff);
                   1077:                else
                   1078:                        printf(" %s/0x%04x", vendor, id & 0xffff);
                   1079:        } else
                   1080:                printf(" %s", this->name);
                   1081:        printf(" (rev. %u.%u), HDA version %u.%u\n",
                   1082:            COP_RID_REVISION(rev), COP_RID_STEPPING(rev),
                   1083:            COP_RID_MAJ(rev), COP_RID_MIN(rev));
                   1084:
                   1085:        /* identify function nodes */
                   1086:        err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
                   1087:            COP_SUBORDINATE_NODE_COUNT, &result);
                   1088:        if (err)
                   1089:                return err;
                   1090:        this->nfunctions = COP_NSUBNODES(result);
                   1091:        if (COP_NSUBNODES(result) <= 0) {
                   1092:                printf("%s: No function groups\n", XNAME(this->az));
                   1093:                return -1;
                   1094:        }
                   1095:        /* iterate function nodes and find an audio function */
                   1096:        n = COP_START_NID(result);
                   1097:        DPRINTF(("%s: nidstart=%d #functions=%d\n",
                   1098:            __func__, n, this->nfunctions));
                   1099:        this->audiofunc = -1;
                   1100:        for (i = 0; i < this->nfunctions; i++) {
                   1101:                err = this->comresp(this, n + i, CORB_GET_PARAMETER,
                   1102:                    COP_FUNCTION_GROUP_TYPE, &result);
                   1103:                if (err)
                   1104:                        continue;
                   1105:                DPRINTF(("%s: FTYPE result = 0x%8.8x\n", __func__, result));
                   1106:                if (COP_FTYPE(result) == COP_FTYPE_AUDIO) {
                   1107:                        this->audiofunc = n + i;
                   1108:                        break;  /* XXX multiple audio functions? */
                   1109:                } else if (COP_FTYPE(result) == COP_FTYPE_MODEM) {
                   1110:                        printf("%s: codec[%d]: No support for modem function groups\n",
                   1111:                            XNAME(this->az), addr);
                   1112:                }
                   1113:        }
                   1114:        if (this->audiofunc < 0) {
                   1115:                printf("%s: codec[%d]: No audio function groups\n",
                   1116:                    XNAME(this->az), addr);
                   1117:                return -1;
                   1118:        }
                   1119:
                   1120:        /* power the audio function */
                   1121:        this->comresp(this, this->audiofunc, CORB_SET_POWER_STATE, CORB_PS_D0, &result);
                   1122:        DELAY(100);
                   1123:
                   1124:        /* check widgets in the audio function */
                   1125:        err = this->comresp(this, this->audiofunc,
                   1126:            CORB_GET_PARAMETER, COP_SUBORDINATE_NODE_COUNT, &result);
                   1127:        if (err)
                   1128:                return err;
                   1129:        DPRINTF(("%s: There are %d widgets in the audio function.\n",
                   1130:           __func__, COP_NSUBNODES(result)));
                   1131:        this->wstart = COP_START_NID(result);
                   1132:        if (this->wstart < 2) {
                   1133:                printf("%s: invalid node structure\n", XNAME(this->az));
                   1134:                return -1;
                   1135:        }
                   1136:        this->wend = this->wstart + COP_NSUBNODES(result);
                   1137:        this->w = malloc(sizeof(widget_t) * this->wend, M_DEVBUF, M_NOWAIT);
                   1138:        if (this->w == NULL) {
                   1139:                printf("%s: out of memory\n", XNAME(this->az));
                   1140:                return ENOMEM;
                   1141:        }
                   1142:        bzero(this->w, sizeof(widget_t) * this->wend);
                   1143:
                   1144:        /* query the base parameters */
                   1145:        this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
                   1146:            COP_STREAM_FORMATS, &result);
                   1147:        this->w[this->audiofunc].d.audio.encodings = result;
                   1148:        this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
                   1149:            COP_PCM, &result);
                   1150:        this->w[this->audiofunc].d.audio.bits_rates = result;
                   1151:        this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
                   1152:            COP_INPUT_AMPCAP, &result);
                   1153:        this->w[this->audiofunc].inamp_cap = result;
                   1154:        this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
                   1155:            COP_OUTPUT_AMPCAP, &result);
                   1156:        this->w[this->audiofunc].outamp_cap = result;
                   1157: #ifdef AZALIA_DEBUG
                   1158:        azalia_widget_print_audio(&this->w[this->audiofunc], "\t");
                   1159:        result = this->w[this->audiofunc].inamp_cap;
                   1160:        DPRINTF(("\tinamp: mute=%u size=%u steps=%u offset=%u\n",
                   1161:            (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),
                   1162:            COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)));
                   1163:        result = this->w[this->audiofunc].outamp_cap;
                   1164:        DPRINTF(("\toutamp: mute=%u size=%u steps=%u offset=%u\n",
                   1165:            (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),
                   1166:            COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)));
                   1167: #endif
                   1168:
                   1169:        strlcpy(this->w[CORB_NID_ROOT].name, "root",
                   1170:            sizeof(this->w[CORB_NID_ROOT].name));
                   1171:        strlcpy(this->w[this->audiofunc].name, "hdaudio",
                   1172:            sizeof(this->w[this->audiofunc].name));
                   1173:        FOR_EACH_WIDGET(this, i) {
                   1174:                err = azalia_widget_init(&this->w[i], this, i);
                   1175:                if (err)
                   1176:                        return err;
                   1177:        }
                   1178:
                   1179:        err = this->init_dacgroup(this);
                   1180:        if (err)
                   1181:                return err;
                   1182: #ifdef AZALIA_DEBUG
                   1183:        for (i = 0; i < this->dacs.ngroups; i++) {
                   1184:                DPRINTF(("%s: dacgroup[%d]:", __func__, i));
                   1185:                for (n = 0; n < this->dacs.groups[i].nconv; n++) {
                   1186:                        DPRINTF((" %2.2x", this->dacs.groups[i].conv[n]));
                   1187:                }
                   1188:                DPRINTF(("\n"));
                   1189:        }
                   1190: #endif
                   1191:
                   1192:        /* set invalid values for azalia_codec_construct_format() to work */
                   1193:        this->dacs.cur = -1;
                   1194:        this->adcs.cur = -1;
                   1195:        err = azalia_codec_construct_format(this, 0, 0);
                   1196:        if (err)
                   1197:                return err;
                   1198:
                   1199:        return this->mixer_init(this);
                   1200: }
                   1201:
                   1202: int
                   1203: azalia_codec_delete(codec_t *this)
                   1204: {
                   1205:        if (this->mixer_delete != NULL)
                   1206:                this->mixer_delete(this);
                   1207:        if (this->formats != NULL) {
                   1208:                free(this->formats, M_DEVBUF);
                   1209:                this->formats = NULL;
                   1210:        }
                   1211:        printf("delete_encodings...\n");
                   1212:        auconv_delete_encodings(this->encodings);
                   1213:        this->encodings = NULL;
                   1214:        return 0;
                   1215: }
                   1216:
                   1217: int
                   1218: azalia_codec_construct_format(codec_t *this, int newdac, int newadc)
                   1219: {
                   1220:        const convgroup_t *group;
                   1221:        uint32_t bits_rates;
                   1222:        int prev_dac, prev_adc;
                   1223:        int pvariation, rvariation;
                   1224:        int nbits, c, chan, i, err;
                   1225:        nid_t nid;
                   1226:
                   1227:        prev_dac = this->dacs.cur;
                   1228:        this->dacs.cur = newdac;
                   1229:        group = &this->dacs.groups[this->dacs.cur];
                   1230:        bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
                   1231:        nbits = 0;
                   1232:        if (bits_rates & COP_PCM_B8)
                   1233:                nbits++;
                   1234:        if (bits_rates & COP_PCM_B16)
                   1235:                nbits++;
                   1236:        if (bits_rates & COP_PCM_B20)
                   1237:                nbits++;
                   1238:        if (bits_rates & COP_PCM_B24)
                   1239:                nbits++;
                   1240:        if (bits_rates & COP_PCM_B32)
                   1241:                nbits++;
                   1242:        if (nbits == 0) {
                   1243:                printf("%s: %s/%d invalid PCM format: 0x%8.8x\n",
                   1244:                    XNAME(this->az), __FILE__, __LINE__, bits_rates);
                   1245:                return -1;
                   1246:        }
                   1247:        pvariation = group->nconv * nbits;
                   1248:
                   1249:        prev_adc = this->adcs.cur;
                   1250:        this->adcs.cur = newadc;
                   1251:        group = &this->adcs.groups[this->adcs.cur];
                   1252:        bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
                   1253:        nbits = 0;
                   1254:        if (bits_rates & COP_PCM_B8)
                   1255:                nbits++;
                   1256:        if (bits_rates & COP_PCM_B16)
                   1257:                nbits++;
                   1258:        if (bits_rates & COP_PCM_B20)
                   1259:                nbits++;
                   1260:        if (bits_rates & COP_PCM_B24)
                   1261:                nbits++;
                   1262:        if (bits_rates & COP_PCM_B32)
                   1263:                nbits++;
                   1264:        if (nbits == 0) {
                   1265:                printf("%s: %s/%d invalid PCM format: 0x%8.8x\n",
                   1266:                    XNAME(this->az), __FILE__, __LINE__, bits_rates);
                   1267:                return -1;
                   1268:        }
                   1269:        rvariation = group->nconv * nbits;
                   1270:
                   1271:        if (this->formats != NULL)
                   1272:                free(this->formats, M_DEVBUF);
                   1273:        this->nformats = 0;
                   1274:        this->formats = malloc(sizeof(struct audio_format) *
                   1275:            (pvariation + rvariation), M_DEVBUF, M_NOWAIT);
                   1276:        if (this->formats == NULL) {
                   1277:                printf("%s: out of memory in %s\n",
                   1278:                    XNAME(this->az), __func__);
                   1279:                return ENOMEM;
                   1280:        }
                   1281:        bzero(this->formats, sizeof(struct audio_format) *
                   1282:            (pvariation + rvariation));
                   1283:
                   1284:        /* register formats for playback */
                   1285:        group = &this->dacs.groups[this->dacs.cur];
                   1286:        nid = group->conv[0];
                   1287:        chan = 0;
                   1288:        bits_rates = this->w[nid].d.audio.bits_rates;
                   1289:        for (c = 0; c < group->nconv; c++) {
                   1290:                for (chan = 0, i = 0; i <= c; i++)
                   1291:                        chan += WIDGET_CHANNELS(&this->w[group->conv[c]]);
                   1292:                azalia_codec_add_bits(this, chan, bits_rates, AUMODE_PLAY);
                   1293:        }
                   1294:
                   1295:        /* register formats for recording */
                   1296:        group = &this->adcs.groups[this->adcs.cur];
                   1297:        nid = group->conv[0];
                   1298:        chan = 0;
                   1299:        bits_rates = this->w[nid].d.audio.bits_rates;
                   1300:        for (c = 0; c < group->nconv; c++) {
                   1301:                for (chan = 0, i = 0; i <= c; i++)
                   1302:                        chan += WIDGET_CHANNELS(&this->w[group->conv[c]]);
                   1303:                azalia_codec_add_bits(this, chan, bits_rates, AUMODE_RECORD);
                   1304:        }
                   1305:
                   1306:        err = azalia_create_encodings(this->formats, this->nformats,
                   1307:            &this->encodings);
                   1308:        if (err)
                   1309:                return err;
                   1310:        return 0;
                   1311: }
                   1312:
                   1313: void
                   1314: azalia_codec_add_bits(codec_t *this, int chan, uint32_t bits_rates, int mode)
                   1315: {
                   1316:        if (bits_rates & COP_PCM_B8)
                   1317:                azalia_codec_add_format(this, chan, 8, 16, bits_rates, mode);
                   1318:        if (bits_rates & COP_PCM_B16)
                   1319:                azalia_codec_add_format(this, chan, 16, 16, bits_rates, mode);
                   1320:        if (bits_rates & COP_PCM_B20)
                   1321:                azalia_codec_add_format(this, chan, 20, 32, bits_rates, mode);
                   1322:        if (bits_rates & COP_PCM_B24)
                   1323:                azalia_codec_add_format(this, chan, 24, 32, bits_rates, mode);
                   1324:        if (bits_rates & COP_PCM_B32)
                   1325:                azalia_codec_add_format(this, chan, 32, 32, bits_rates, mode);
                   1326: }
                   1327:
                   1328: void
                   1329: azalia_codec_add_format(codec_t *this, int chan, int valid, int prec,
                   1330:     uint32_t rates, int32_t mode)
                   1331: {
                   1332:        struct audio_format *f;
                   1333:
                   1334:        f = &this->formats[this->nformats++];
                   1335:        f->mode = mode;
                   1336:        f->encoding = AUDIO_ENCODING_SLINEAR_LE;
                   1337:        if (valid == 8 && prec == 8)
                   1338:                f->encoding = AUDIO_ENCODING_ULINEAR_LE;
                   1339:        f->validbits = valid;
                   1340:        f->precision = prec;
                   1341:        f->channels = chan;
                   1342:        switch (chan) {
                   1343:        case 1:
                   1344:                f->channel_mask = AUFMT_MONAURAL;
                   1345:                break;
                   1346:        case 2:
                   1347:                f->channel_mask = AUFMT_STEREO;
                   1348:                break;
                   1349:        case 4:
                   1350:                f->channel_mask = AUFMT_SURROUND4;
                   1351:                break;
                   1352:        case 6:
                   1353:                f->channel_mask = AUFMT_DOLBY_5_1;
                   1354:                break;
                   1355:        case 8:
                   1356:                f->channel_mask = AUFMT_DOLBY_5_1
                   1357:                    | AUFMT_SIDE_LEFT | AUFMT_SIDE_RIGHT;
                   1358:                break;
                   1359:        default:
                   1360:                f->channel_mask = 0;
                   1361:        }
                   1362:        if (rates & COP_PCM_R80)
                   1363:                f->frequency[f->frequency_type++] = 8000;
                   1364:        if (rates & COP_PCM_R110)
                   1365:                f->frequency[f->frequency_type++] = 11025;
                   1366:        if (rates & COP_PCM_R160)
                   1367:                f->frequency[f->frequency_type++] = 16000;
                   1368:        if (rates & COP_PCM_R220)
                   1369:                f->frequency[f->frequency_type++] = 22050;
                   1370:        if (rates & COP_PCM_R320)
                   1371:                f->frequency[f->frequency_type++] = 32000;
                   1372:        if (rates & COP_PCM_R441)
                   1373:                f->frequency[f->frequency_type++] = 44100;
                   1374:        if (rates & COP_PCM_R480)
                   1375:                f->frequency[f->frequency_type++] = 48000;
                   1376:        if (rates & COP_PCM_R882)
                   1377:                f->frequency[f->frequency_type++] = 88200;
                   1378:        if (rates & COP_PCM_R960)
                   1379:                f->frequency[f->frequency_type++] = 96000;
                   1380:        if (rates & COP_PCM_R1764)
                   1381:                f->frequency[f->frequency_type++] = 176400;
                   1382:        if (rates & COP_PCM_R1920)
                   1383:                f->frequency[f->frequency_type++] = 192000;
                   1384:        if (rates & COP_PCM_R3840)
                   1385:                f->frequency[f->frequency_type++] = 384000;
                   1386: }
                   1387:
                   1388: int
                   1389: azalia_codec_comresp(const codec_t *codec, nid_t nid, uint32_t control,
                   1390:                     uint32_t param, uint32_t* result)
                   1391: {
                   1392:        int err;
                   1393:
                   1394:        err = azalia_set_command(codec->az, codec->address, nid, control, param);
                   1395:        if (err)
                   1396:                return err;
                   1397:        return azalia_get_response(codec->az, result);
                   1398: }
                   1399:
                   1400: int
                   1401: azalia_codec_connect_stream(codec_t *this, int dir, uint16_t fmt, int number)
                   1402: {
                   1403:        const convgroup_t *group;
                   1404:        int i, err, startchan, nchan;
                   1405:        nid_t nid;
                   1406:        boolean_t flag222;
                   1407:
                   1408:        DPRINTF(("%s: fmt=0x%4.4x number=%d\n", __func__, fmt, number));
                   1409:        err = 0;
                   1410:        if (dir == AUMODE_RECORD)
                   1411:                group = &this->adcs.groups[this->adcs.cur];
                   1412:        else
                   1413:                group = &this->dacs.groups[this->dacs.cur];
                   1414:        flag222 = group->nconv >= 3 &&
                   1415:            (WIDGET_CHANNELS(&this->w[group->conv[0]]) == 2) &&
                   1416:            (WIDGET_CHANNELS(&this->w[group->conv[1]]) == 2) &&
                   1417:            (WIDGET_CHANNELS(&this->w[group->conv[2]]) == 2);
                   1418:        nchan = (fmt & HDA_SD_FMT_CHAN) + 1;
                   1419:        startchan = 0;
                   1420:        for (i = 0; i < group->nconv; i++) {
                   1421:                nid = group->conv[i];
                   1422:
                   1423:                /* surround and c/lfe handling */
                   1424:                if (nchan >= 6 && flag222 && i == 1) {
                   1425:                        nid = group->conv[2];
                   1426:                } else if (nchan >= 6 && flag222 && i == 2) {
                   1427:                        nid = group->conv[1];
                   1428:                }
                   1429:
                   1430:                err = this->comresp(this, nid, CORB_SET_CONVERTER_FORMAT, fmt, NULL);
                   1431:                if (err)
                   1432:                        goto exit;
                   1433:                err = this->comresp(this, nid, CORB_SET_CONVERTER_STREAM_CHANNEL,
                   1434:                                    (number << 4) | startchan, NULL);
                   1435:                if (err)
                   1436:                        goto exit;
                   1437:                if (nchan > 2)
                   1438:                        startchan += WIDGET_CHANNELS(&this->w[nid]);
                   1439:        }
                   1440:
                   1441: exit:
                   1442:        DPRINTF(("%s: leave with %d\n", __func__, err));
                   1443:        return err;
                   1444: }
                   1445:
                   1446: /* ================================================================
                   1447:  * HDA widget functions
                   1448:  * ================================================================ */
                   1449:
                   1450: #define        WIDGETCAP_BITS                                                  \
                   1451:     "\20\014LRSWAP\013POWER\012DIGITAL"                                        \
                   1452:     "\011CONNLIST\010UNSOL\07PROC\06STRIPE\05FORMATOV\04AMPOV\03OUTAMP"        \
                   1453:     "\02INAMP\01STEREO"
                   1454:
                   1455: int
                   1456: azalia_widget_init(widget_t *this, const codec_t *codec, nid_t nid)
                   1457: {
                   1458:        uint32_t result;
                   1459:        int err;
                   1460:
                   1461:        err = codec->comresp(codec, nid, CORB_GET_PARAMETER,
                   1462:            COP_AUDIO_WIDGET_CAP, &result);
                   1463:        if (err)
                   1464:                return err;
                   1465:        this->nid = nid;
                   1466:        this->widgetcap = result;
                   1467:        this->type = COP_AWCAP_TYPE(result);
                   1468:        DPRINTF(("%s: ", XNAME(codec->az)));
                   1469:        if (this->widgetcap & COP_AWCAP_POWER) {
                   1470:                codec->comresp(codec, nid, CORB_SET_POWER_STATE, CORB_PS_D0, &result);
                   1471:                DELAY(100);
                   1472:        }
                   1473:        switch (this->type) {
                   1474:        case COP_AWTYPE_AUDIO_OUTPUT:
                   1475:                snprintf(this->name, sizeof(this->name), "dac%2.2x", nid);
                   1476:                DPRINTF(("%s wcap=%b\n", this->name,
                   1477:                    this->widgetcap, WIDGETCAP_BITS));
                   1478:                azalia_widget_init_audio(this, codec);
                   1479:                break;
                   1480:        case COP_AWTYPE_AUDIO_INPUT:
                   1481:                snprintf(this->name, sizeof(this->name), "adc%2.2x", nid);
                   1482:                DPRINTF(("%s wcap=%b\n", this->name,
                   1483:                    this->widgetcap, WIDGETCAP_BITS));
                   1484:                azalia_widget_init_audio(this, codec);
                   1485:                break;
                   1486:        case COP_AWTYPE_AUDIO_MIXER:
                   1487:                snprintf(this->name, sizeof(this->name), "mix%2.2x", nid);
                   1488:                DPRINTF(("%s wcap=%b\n", this->name,
                   1489:                    this->widgetcap, WIDGETCAP_BITS));
                   1490:                break;
                   1491:        case COP_AWTYPE_AUDIO_SELECTOR:
                   1492:                snprintf(this->name, sizeof(this->name), "sel%2.2x", nid);
                   1493:                DPRINTF(("%s wcap=%b\n", this->name,
                   1494:                    this->widgetcap, WIDGETCAP_BITS));
                   1495:                break;
                   1496:        case COP_AWTYPE_PIN_COMPLEX:
                   1497:                azalia_widget_init_pin(this, codec);
                   1498:                snprintf(this->name, sizeof(this->name), "%s%2.2x",
                   1499:                    pin_colors[this->d.pin.color], nid);
                   1500:                DPRINTF(("%s wcap=%b\n", this->name,
                   1501:                    this->widgetcap, WIDGETCAP_BITS));
                   1502:                azalia_widget_print_pin(this);
                   1503:                break;
                   1504:        case COP_AWTYPE_POWER:
                   1505:                snprintf(this->name, sizeof(this->name), "pow%2.2x", nid);
                   1506:                DPRINTF(("%s wcap=%b\n", this->name,
                   1507:                    this->widgetcap, WIDGETCAP_BITS));
                   1508:                break;
                   1509:        case COP_AWTYPE_VOLUME_KNOB:
                   1510:                snprintf(this->name, sizeof(this->name), "volume%2.2x", nid);
                   1511:                DPRINTF(("%s wcap=%b\n", this->name,
                   1512:                    this->widgetcap, WIDGETCAP_BITS));
                   1513:                err = codec->comresp(codec, nid, CORB_GET_PARAMETER,
                   1514:                    COP_VOLUME_KNOB_CAPABILITIES, &result);
                   1515:                if (!err) {
                   1516:                        this->d.volume.cap = result;
                   1517:                        DPRINTF(("\tdelta=%d steps=%d\n",
                   1518:                            !!(result & COP_VKCAP_DELTA),
                   1519:                            COP_VKCAP_NUMSTEPS(result)));
                   1520:                }
                   1521:                break;
                   1522:        case COP_AWTYPE_BEEP_GENERATOR:
                   1523:                snprintf(this->name, sizeof(this->name), "beep%2.2x", nid);
                   1524:                DPRINTF(("%s wcap=%b\n", this->name,
                   1525:                    this->widgetcap, WIDGETCAP_BITS));
                   1526:                break;
                   1527:        default:
                   1528:                snprintf(this->name, sizeof(this->name), "widget%2.2x", nid);
                   1529:                DPRINTF(("%s wcap=%b\n", this->name,
                   1530:                    this->widgetcap, WIDGETCAP_BITS));
                   1531:                break;
                   1532:        }
                   1533:        azalia_widget_init_connection(this, codec);
                   1534:
                   1535:        /* amplifier information */
                   1536:        if (this->widgetcap & COP_AWCAP_INAMP) {
                   1537:                if (this->widgetcap & COP_AWCAP_AMPOV)
                   1538:                        codec->comresp(codec, nid, CORB_GET_PARAMETER,
                   1539:                            COP_INPUT_AMPCAP, &this->inamp_cap);
                   1540:                else
                   1541:                        this->inamp_cap = codec->w[codec->audiofunc].inamp_cap;
                   1542:                DPRINTF(("\tinamp: mute=%u size=%u steps=%u offset=%u\n",
                   1543:                    (this->inamp_cap & COP_AMPCAP_MUTE) != 0,
                   1544:                    COP_AMPCAP_STEPSIZE(this->inamp_cap),
                   1545:                    COP_AMPCAP_NUMSTEPS(this->inamp_cap),
                   1546:                    COP_AMPCAP_OFFSET(this->inamp_cap)));
                   1547:        }
                   1548:        if (this->widgetcap & COP_AWCAP_OUTAMP) {
                   1549:                if (this->widgetcap & COP_AWCAP_AMPOV)
                   1550:                        codec->comresp(codec, nid, CORB_GET_PARAMETER,
                   1551:                            COP_OUTPUT_AMPCAP, &this->outamp_cap);
                   1552:                else
                   1553:                        this->outamp_cap = codec->w[codec->audiofunc].outamp_cap;
                   1554:                DPRINTF(("\toutamp: mute=%u size=%u steps=%u offset=%u\n",
                   1555:                    (this->outamp_cap & COP_AMPCAP_MUTE) != 0,
                   1556:                    COP_AMPCAP_STEPSIZE(this->outamp_cap),
                   1557:                    COP_AMPCAP_NUMSTEPS(this->outamp_cap),
                   1558:                    COP_AMPCAP_OFFSET(this->outamp_cap)));
                   1559:        }
                   1560:        if (codec->init_widget != NULL)
                   1561:                codec->init_widget(codec, this, nid);
                   1562:        return 0;
                   1563: }
                   1564:
                   1565: int
                   1566: azalia_widget_init_audio(widget_t *this, const codec_t *codec)
                   1567: {
                   1568:        uint32_t result;
                   1569:        int err;
                   1570:
                   1571:        /* check audio format */
                   1572:        if (this->widgetcap & COP_AWCAP_FORMATOV) {
                   1573:                err = codec->comresp(codec, this->nid,
                   1574:                    CORB_GET_PARAMETER, COP_STREAM_FORMATS, &result);
                   1575:                if (err)
                   1576:                        return err;
                   1577:                this->d.audio.encodings = result;
                   1578:                if (result == 0) { /* quirk for CMI9880.
                   1579:                                    * This must not occuur usually... */
                   1580:                        this->d.audio.encodings =
                   1581:                            codec->w[codec->audiofunc].d.audio.encodings;
                   1582:                        this->d.audio.bits_rates =
                   1583:                            codec->w[codec->audiofunc].d.audio.bits_rates;
                   1584:                } else {
                   1585:                        if ((result & COP_STREAM_FORMAT_PCM) == 0) {
                   1586:                                printf("%s: %s: No PCM support: %x\n",
                   1587:                                    XNAME(codec->az), this->name, result);
                   1588:                                return -1;
                   1589:                        }
                   1590:                        err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
                   1591:                            COP_PCM, &result);
                   1592:                        if (err)
                   1593:                                return err;
                   1594:                        this->d.audio.bits_rates = result;
                   1595:                }
                   1596:                this->d.audio.bits_rates = result;
                   1597:        } else {
                   1598:                this->d.audio.encodings =
                   1599:                    codec->w[codec->audiofunc].d.audio.encodings;
                   1600:                this->d.audio.bits_rates =
                   1601:                    codec->w[codec->audiofunc].d.audio.bits_rates;
                   1602:        }
                   1603: #ifdef AZALIA_DEBUG
                   1604:        azalia_widget_print_audio(this, "\t");
                   1605: #endif
                   1606:        return 0;
                   1607: }
                   1608:
                   1609: #define        ENCODING_BITS   "\20\3AC3\2FLOAT32\1PCM"
                   1610: #define        BITSRATES_BITS  "\20\x15""32bit\x14""24bit\x13""20bit"          \
                   1611:     "\x12""16bit\x11""8bit""\x0c""384kHz\x0b""192kHz\x0a""176.4kHz"    \
                   1612:     "\x09""96kHz\x08""88.2kHz\x07""48kHz\x06""44.1kHz\x05""32kHz\x04"  \
                   1613:     "22.05kHz\x03""16kHz\x02""11.025kHz\x01""8kHz"
                   1614:
                   1615: int
                   1616: azalia_widget_print_audio(const widget_t *this, const char *lead)
                   1617: {
                   1618:        printf("%sencodings=%b\n", lead, this->d.audio.encodings,
                   1619:            ENCODING_BITS);
                   1620:        printf("%sPCM formats=%b\n", lead, this->d.audio.bits_rates,
                   1621:            BITSRATES_BITS);
                   1622:        return 0;
                   1623: }
                   1624:
                   1625: int
                   1626: azalia_widget_init_pin(widget_t *this, const codec_t *codec)
                   1627: {
                   1628:        uint32_t result;
                   1629:        int err;
                   1630:
                   1631:        err = codec->comresp(codec, this->nid, CORB_GET_CONFIGURATION_DEFAULT,
                   1632:            0, &result);
                   1633:        if (err)
                   1634:                return err;
                   1635:        this->d.pin.config = result;
                   1636:        this->d.pin.sequence = CORB_CD_SEQUENCE(result);
                   1637:        this->d.pin.association = CORB_CD_ASSOCIATION(result);
                   1638:        this->d.pin.color = CORB_CD_COLOR(result);
                   1639:        this->d.pin.device = CORB_CD_DEVICE(result);
                   1640:
                   1641:        err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
                   1642:            COP_PINCAP, &result);
                   1643:        if (err)
                   1644:                return err;
                   1645:        this->d.pin.cap = result;
                   1646:        return 0;
                   1647: }
                   1648:
                   1649: #define        PINCAP_BITS     "\20\021EAPD\07BALANCE\06INPUT" \
                   1650:     "\05OUTPUT\04HEADPHONE\03PRESENCE\02TRIGGER\01IMPEDANCE"
                   1651:
                   1652: int
                   1653: azalia_widget_print_pin(const widget_t *this)
                   1654: {
                   1655:        DPRINTF(("\tpin config; device=%s color=%s assoc=%d seq=%d",
                   1656:            pin_devices[this->d.pin.device], pin_colors[this->d.pin.color],
                   1657:            this->d.pin.association, this->d.pin.sequence));
                   1658:        DPRINTF((" cap=%b\n", this->d.pin.cap, PINCAP_BITS));
                   1659:        return 0;
                   1660: }
                   1661:
                   1662: int
                   1663: azalia_widget_init_connection(widget_t *this, const codec_t *codec)
                   1664: {
                   1665:        uint32_t result;
                   1666:        int err;
                   1667:        boolean_t longform;
                   1668:        int length, i;
                   1669:
                   1670:        this->selected = -1;
                   1671:        if ((this->widgetcap & COP_AWCAP_CONNLIST) == 0)
                   1672:                return 0;
                   1673:
                   1674:        err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
                   1675:            COP_CONNECTION_LIST_LENGTH, &result);
                   1676:        if (err)
                   1677:                return err;
                   1678:        longform = (result & COP_CLL_LONG) != 0;
                   1679:        length = COP_CLL_LENGTH(result);
                   1680:        if (length == 0)
                   1681:                return 0;
                   1682:        this->nconnections = length;
                   1683:        this->connections = malloc(sizeof(nid_t) * (length + 3),
                   1684:            M_DEVBUF, M_NOWAIT);
                   1685:        if (this->connections == NULL) {
                   1686:                printf("%s: out of memory\n", XNAME(codec->az));
                   1687:                return ENOMEM;
                   1688:        }
                   1689:        if (longform) {
                   1690:                for (i = 0; i < length;) {
                   1691:                        err = codec->comresp(codec, this->nid,
                   1692:                            CORB_GET_CONNECTION_LIST_ENTRY, i, &result);
                   1693:                        if (err)
                   1694:                                return err;
                   1695:                        this->connections[i++] = CORB_CLE_LONG_0(result);
                   1696:                        this->connections[i++] = CORB_CLE_LONG_1(result);
                   1697:                }
                   1698:        } else {
                   1699:                for (i = 0; i < length;) {
                   1700:                        err = codec->comresp(codec, this->nid,
                   1701:                            CORB_GET_CONNECTION_LIST_ENTRY, i, &result);
                   1702:                        if (err)
                   1703:                                return err;
                   1704:                        this->connections[i++] = CORB_CLE_SHORT_0(result);
                   1705:                        this->connections[i++] = CORB_CLE_SHORT_1(result);
                   1706:                        this->connections[i++] = CORB_CLE_SHORT_2(result);
                   1707:                        this->connections[i++] = CORB_CLE_SHORT_3(result);
                   1708:                }
                   1709:        }
                   1710:        if (length > 0) {
                   1711:                DPRINTF(("\tconnections=0x%x", this->connections[0]));
                   1712:                for (i = 1; i < length; i++) {
                   1713:                        DPRINTF((",0x%x", this->connections[i]));
                   1714:                }
                   1715:
                   1716:                err = codec->comresp(codec, this->nid,
                   1717:                    CORB_GET_CONNECTION_SELECT_CONTROL, 0, &result);
                   1718:                if (err)
                   1719:                        return err;
                   1720:                this->selected = CORB_CSC_INDEX(result);
                   1721:                DPRINTF(("; selected=0x%x\n", this->connections[result]));
                   1722:        }
                   1723:        return 0;
                   1724: }
                   1725:
                   1726: /* ================================================================
                   1727:  * Stream functions
                   1728:  * ================================================================ */
                   1729:
                   1730: int
                   1731: azalia_stream_init(stream_t *this, azalia_t *az, int regindex, int strnum, int dir)
                   1732: {
                   1733:        int err;
                   1734:
                   1735:        this->az = az;
                   1736:        this->regbase = HDA_SD_BASE + regindex * HDA_SD_SIZE;
                   1737:        this->intr_bit = 1 << regindex;
                   1738:        this->number = strnum;
                   1739:        this->dir = dir;
                   1740:
                   1741:        /* setup BDL buffers */
                   1742:        err = azalia_alloc_dmamem(az, sizeof(bdlist_entry_t) * HDA_BDL_MAX,
                   1743:                                  128, &this->bdlist);
                   1744:        if (err) {
                   1745:                printf("%s: can't allocate a BDL buffer\n", XNAME(az));
                   1746:                return err;
                   1747:        }
                   1748:        return 0;
                   1749: }
                   1750:
                   1751: int
                   1752: azalia_stream_delete(stream_t *this, azalia_t *az)
                   1753: {
                   1754:        if (this->bdlist.addr == NULL)
                   1755:                return 0;
                   1756:        azalia_free_dmamem(az, &this->bdlist);
                   1757:        return 0;
                   1758: }
                   1759:
                   1760: int
                   1761: azalia_stream_reset(stream_t *this)
                   1762: {
                   1763:        int i;
                   1764:        uint16_t ctl;
                   1765:        uint8_t sts;
                   1766:
                   1767:        /* Make sure RUN bit is zero before resetting */
                   1768:        ctl = STR_READ_2(this, CTL);
                   1769:        ctl &= ~HDA_SD_CTL_RUN;
                   1770:        STR_WRITE_2(this, CTL, ctl);
                   1771:
                   1772:        /* Start reset and wait for chip to enter. */
                   1773:        ctl = STR_READ_2(this, CTL);
                   1774:        STR_WRITE_2(this, CTL, ctl | HDA_SD_CTL_SRST);
                   1775:        for (i = 5000; i >= 0; i--) {
                   1776:                DELAY(10);
                   1777:                ctl = STR_READ_2(this, CTL);
                   1778:                if (ctl & HDA_SD_CTL_SRST)
                   1779:                        break;
                   1780:        }
                   1781:        if (i <= 0) {
                   1782:                printf("%s: stream reset failure 1\n", XNAME(this->az));
                   1783:                return -1;
                   1784:        }
                   1785:
                   1786:        /* Clear reset and wait for chip to finish */
                   1787:        STR_WRITE_2(this, CTL, ctl & ~HDA_SD_CTL_SRST);
                   1788:        for (i = 5000; i >= 0; i--) {
                   1789:                DELAY(10);
                   1790:                ctl = STR_READ_2(this, CTL);
                   1791:                if ((ctl & HDA_SD_CTL_SRST) == 0)
                   1792:                        break;
                   1793:        }
                   1794:        if (i <= 0) {
                   1795:                printf("%s: stream reset failure 2\n", XNAME(this->az));
                   1796:                return -1;
                   1797:        }
                   1798:
                   1799:        sts = STR_READ_1(this, STS);
                   1800:        sts |= HDA_SD_STS_DESE | HDA_SD_STS_FIFOE | HDA_SD_STS_BCIS;
                   1801:        STR_WRITE_1(this, STS, sts);
                   1802:
                   1803:        return (0);
                   1804: }
                   1805:
                   1806: int
                   1807: azalia_stream_start(stream_t *this, void *start, void *end, int blk,
                   1808:     void (*intr)(void *), void *arg, uint16_t fmt)
                   1809: {
                   1810:        bdlist_entry_t *bdlist;
                   1811:        bus_addr_t dmaaddr, dmaend;
                   1812:        int err, index;
                   1813:        uint32_t intctl;
                   1814:        uint8_t ctl2;
                   1815:
                   1816:        this->intr = intr;
                   1817:        this->intr_arg = arg;
                   1818:
                   1819:        err = azalia_stream_reset(this);
                   1820:        if (err) {
                   1821:                printf("%s: stream reset failed\n", "azalia");
                   1822:                return err;
                   1823:        }
                   1824:
                   1825:        STR_WRITE_4(this, BDPL, 0);
                   1826:        STR_WRITE_4(this, BDPU, 0);
                   1827:
                   1828:        /* setup BDL */
                   1829:        dmaaddr = AZALIA_DMA_DMAADDR(&this->buffer);
                   1830:        dmaend = dmaaddr + ((caddr_t)end - (caddr_t)start);
                   1831:        bdlist = (bdlist_entry_t*)this->bdlist.addr;
                   1832:        for (index = 0; index < HDA_BDL_MAX; index++) {
                   1833:                bdlist[index].low = htole32(dmaaddr);
                   1834:                bdlist[index].high = htole32(PTR_UPPER32(dmaaddr));
                   1835:                bdlist[index].length = htole32(blk);
                   1836:                bdlist[index].flags = htole32(BDLIST_ENTRY_IOC);
                   1837:                dmaaddr += blk;
                   1838:                if (dmaaddr >= dmaend) {
                   1839:                        index++;
                   1840:                        break;
                   1841:                }
                   1842:        }
                   1843:
                   1844:        dmaaddr = AZALIA_DMA_DMAADDR(&this->bdlist);
                   1845:        STR_WRITE_4(this, BDPL, dmaaddr);
                   1846:        STR_WRITE_4(this, BDPU, PTR_UPPER32(dmaaddr));
                   1847:        STR_WRITE_2(this, LVI, (index - 1) & HDA_SD_LVI_LVI);
                   1848:        ctl2 = STR_READ_1(this, CTL2);
                   1849:        STR_WRITE_1(this, CTL2,
                   1850:            (ctl2 & ~HDA_SD_CTL2_STRM) | (this->number << HDA_SD_CTL2_STRM_SHIFT));
                   1851:        STR_WRITE_4(this, CBL, ((caddr_t)end - (caddr_t)start));
                   1852:        STR_WRITE_2(this, FMT, fmt);
                   1853:
                   1854:        err = azalia_codec_connect_stream(&this->az->codecs[this->az->codecno],
                   1855:            this->dir, fmt, this->number);
                   1856:        if (err)
                   1857:                return EINVAL;
                   1858:
                   1859:        intctl = AZ_READ_4(this->az, INTCTL);
                   1860:        intctl |= this->intr_bit;
                   1861:        AZ_WRITE_4(this->az, INTCTL, intctl);
                   1862:
                   1863:        STR_WRITE_1(this, CTL, STR_READ_1(this, CTL) |
                   1864:            HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE |
                   1865:            HDA_SD_CTL_RUN);
                   1866:
                   1867:        return (0);
                   1868: }
                   1869:
                   1870: int
                   1871: azalia_stream_halt(stream_t *this)
                   1872: {
                   1873:        uint16_t ctl;
                   1874:
                   1875:        ctl = STR_READ_2(this, CTL);
                   1876:        ctl &= ~(HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN);
                   1877:        STR_WRITE_2(this, CTL, ctl);
                   1878:        AZ_WRITE_4(this->az, INTCTL,
                   1879:            AZ_READ_4(this->az, INTCTL) & ~this->intr_bit);
                   1880:        return (0);
                   1881: }
                   1882:
                   1883: #define        HDA_SD_STS_BITS "\20\3BCIS\4FIFOE\5DESE\6FIFORDY"
                   1884:
                   1885: int
                   1886: azalia_stream_intr(stream_t *this, uint32_t intsts)
                   1887: {
                   1888:        u_int8_t sts;
                   1889:
                   1890:        if ((intsts & this->intr_bit) == 0)
                   1891:                return (0);
                   1892:
                   1893:        sts = STR_READ_1(this, STS);
                   1894:        STR_WRITE_1(this, STS, sts |
                   1895:            HDA_SD_STS_DESE | HDA_SD_STS_FIFOE | HDA_SD_STS_BCIS);
                   1896:
                   1897:        if (sts & (HDA_SD_STS_DESE | HDA_SD_STS_FIFOE))
                   1898:                printf("%s: stream %d: sts=%b\n", XNAME(this->az),
                   1899:                    this->number, sts, HDA_SD_STS_BITS);
                   1900:        if (sts & HDA_SD_STS_BCIS)
                   1901:                this->intr(this->intr_arg);
                   1902:        return (1);
                   1903: }
                   1904:
                   1905: /* ================================================================
                   1906:  * MI audio entries
                   1907:  * ================================================================ */
                   1908:
                   1909: int
                   1910: azalia_open(void *v, int flags)
                   1911: {
                   1912:        azalia_t *az;
                   1913:        codec_t *codec;
                   1914:
                   1915:        DPRINTF(("%s: flags=0x%x\n", __func__, flags));
                   1916:        az = v;
                   1917:        codec = &az->codecs[az->codecno];
                   1918:        codec->running++;
                   1919:        return 0;
                   1920: }
                   1921:
                   1922: void
                   1923: azalia_close(void *v)
                   1924: {
                   1925:        azalia_t *az;
                   1926:        codec_t *codec;
                   1927:
                   1928:        DPRINTF(("%s\n", __func__));
                   1929:        az = v;
                   1930:        codec = &az->codecs[az->codecno];
                   1931:        codec->running--;
                   1932: }
                   1933:
                   1934: int
                   1935: azalia_query_encoding(void *v, audio_encoding_t *enc)
                   1936: {
                   1937:        azalia_t *az;
                   1938:        codec_t *codec;
                   1939:        int i, j;
                   1940:
                   1941:        az = v;
                   1942:        codec = &az->codecs[az->codecno];
                   1943:        for (j = 0, i = 0; j < codec->nformats; j++) {
                   1944:                if (codec->formats[j].validbits !=
                   1945:                    codec->formats[j].precision)
                   1946:                        continue;
                   1947:                if (i == enc->index) {
                   1948:                        enc->encoding = codec->formats[j].encoding;
                   1949:                        enc->precision = codec->formats[j].precision;
                   1950:                        switch (enc->encoding) {
                   1951:                        case AUDIO_ENCODING_SLINEAR_LE:
                   1952:                                strlcpy(enc->name, enc->precision == 8 ?
                   1953:                                    AudioEslinear : AudioEslinear_le,
                   1954:                                    sizeof enc->name);
                   1955:                                break;
                   1956:                        case AUDIO_ENCODING_ULINEAR_LE:
                   1957:                                strlcpy(enc->name, enc->precision == 8 ?
                   1958:                                    AudioEulinear : AudioEulinear_le,
                   1959:                                    sizeof enc->name);
                   1960:                                break;
                   1961:                        default:
                   1962:                                strlcpy(enc->name, "unknown", sizeof enc->name);
                   1963:                                break;
                   1964:                        }
                   1965:                        return (0);
                   1966:                }
                   1967:                i++;
                   1968:        }
                   1969:        return (EINVAL);
                   1970: }
                   1971:
                   1972: int
                   1973: azalia_set_params(void *v, int smode, int umode, audio_params_t *p,
                   1974:     audio_params_t *r)
                   1975: {
                   1976:        azalia_t *az;
                   1977:        codec_t *codec;
                   1978:        void (*pswcode)(void *, u_char *, int) = NULL;
                   1979:        void (*rswcode)(void *, u_char *, int) = NULL;
                   1980:        int i, j;
                   1981:
                   1982:        az = v;
                   1983:        codec = &az->codecs[az->codecno];
                   1984:        if (smode & AUMODE_RECORD && r != NULL) {
                   1985:                if (r->encoding == AUDIO_ENCODING_ULAW) {        /*XXX*/
                   1986:                        r->encoding = AUDIO_ENCODING_SLINEAR_LE;
                   1987:                        r->precision = 16;
                   1988:                        r->channels = 2;
                   1989:                        r->sample_rate = 44100;
                   1990:                }
                   1991:                for (i = 0; i < codec->nformats; i++) {
                   1992:                        if (r->encoding != codec->formats[i].encoding)
                   1993:                                continue;
                   1994:                        if (r->precision != codec->formats[i].precision)
                   1995:                                continue;
                   1996:                        if (r->channels != codec->formats[i].channels)
                   1997:                                continue;
                   1998:                        break;
                   1999:                }
                   2000:                if (i == codec->nformats) {
                   2001:                        printf("didn't find Record format %u/%u/%u\n",
                   2002:                            r->encoding, r->precision, r->channels);
                   2003:                        return (EINVAL);
                   2004:                }
                   2005:                for (j = 0; j < codec->formats[i].frequency_type; j++) {
                   2006:                        if (r->sample_rate != codec->formats[i].frequency[j])
                   2007:                                continue;
                   2008:                        break;
                   2009:                }
                   2010:                if (j == codec->formats[i].frequency_type) {
                   2011:                        printf("didn't find Record rate %u\n",
                   2012:                            r->sample_rate);
                   2013:                        return (EINVAL);
                   2014:                }
                   2015:                r->sw_code = rswcode;
                   2016:        }
                   2017:        if (smode & AUMODE_PLAY && p != NULL) {
                   2018:                if (p->encoding == AUDIO_ENCODING_ULAW) {        /*XXX*/
                   2019:                        p->encoding = AUDIO_ENCODING_SLINEAR_LE;
                   2020:                        p->precision = 16;
                   2021:                        p->channels = 2;
                   2022:                        p->sample_rate = 44100;
                   2023:                }
                   2024:                for (i = 0; i < codec->nformats; i++) {
                   2025:                        if (p->encoding != codec->formats[i].encoding)
                   2026:                                continue;
                   2027:                        if (p->precision != codec->formats[i].precision)
                   2028:                                continue;
                   2029:                        if (p->channels != codec->formats[i].channels)
                   2030:                                continue;
                   2031:                        break;
                   2032:                }
                   2033:                if (i == codec->nformats) {
                   2034:                        printf("can't find playback format %u/%u/%u\n",
                   2035:                            r->encoding, r->precision, r->channels);
                   2036:                        return (EINVAL);
                   2037:                }
                   2038:                for (j = 0; j < codec->formats[i].frequency_type; j++) {
                   2039:                        if (p->sample_rate != codec->formats[i].frequency[j])
                   2040:                                continue;
                   2041:                        break;
                   2042:                }
                   2043:                if (j == codec->formats[i].frequency_type) {
                   2044:                        printf("can't find playback rate %u\n",
                   2045:                            p->sample_rate);
                   2046:                        return (EINVAL);
                   2047:                }
                   2048:                p->sw_code = pswcode;
                   2049:        }
                   2050:
                   2051:        return (0);
                   2052: }
                   2053:
                   2054: int
                   2055: azalia_round_blocksize(void *v, int blk)
                   2056: {
                   2057:        azalia_t *az;
                   2058:        size_t size;
                   2059:
                   2060:        blk &= ~0x7f;           /* must be multiple of 128 */
                   2061:        if (blk <= 0)
                   2062:                blk = 128;
                   2063:        /* number of blocks must be <= HDA_BDL_MAX */
                   2064:        az = v;
                   2065:        size = az->pstream.buffer.size;
                   2066: #ifdef DIAGNOSTIC
                   2067:        if (size <= 0) {
                   2068:                printf("%s: size is 0", __func__);
                   2069:                return 256;
                   2070:        }
                   2071: #endif
                   2072:        if (size > HDA_BDL_MAX * blk) {
                   2073:                blk = size / HDA_BDL_MAX;
                   2074:                if (blk & 0x7f)
                   2075:                        blk = (blk + 0x7f) & ~0x7f;
                   2076:        }
                   2077:        DPRINTF(("%s: resultant block size = %d\n", __func__, blk));
                   2078:        return blk;
                   2079: }
                   2080:
                   2081: int
                   2082: azalia_halt_output(void *v)
                   2083: {
                   2084:        azalia_t *az;
                   2085:
                   2086:        DPRINTF(("%s\n", __func__));
                   2087:        az = v;
                   2088:        return azalia_stream_halt(&az->pstream);
                   2089: }
                   2090:
                   2091: int
                   2092: azalia_halt_input(void *v)
                   2093: {
                   2094:        azalia_t *az;
                   2095:
                   2096:        DPRINTF(("%s\n", __func__));
                   2097:        az = v;
                   2098:        return azalia_stream_halt(&az->rstream);
                   2099: }
                   2100:
                   2101: int
                   2102: azalia_getdev(void *v, struct audio_device *dev)
                   2103: {
                   2104:        azalia_t *az;
                   2105:
                   2106:        az = v;
                   2107:        strlcpy(dev->name, "HD-Audio", MAX_AUDIO_DEV_LEN);
                   2108:        snprintf(dev->version, MAX_AUDIO_DEV_LEN,
                   2109:            "%d.%d", AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN));
                   2110:        strlcpy(dev->config, XNAME(az), MAX_AUDIO_DEV_LEN);
                   2111:        return 0;
                   2112: }
                   2113:
                   2114: int
                   2115: azalia_set_port(void *v, mixer_ctrl_t *mc)
                   2116: {
                   2117:        azalia_t *az;
                   2118:        codec_t *co;
                   2119:
                   2120:        az = v;
                   2121:        co = &az->codecs[az->codecno];
                   2122:        return co->set_port(co, mc);
                   2123: }
                   2124:
                   2125: int
                   2126: azalia_get_port(void *v, mixer_ctrl_t *mc)
                   2127: {
                   2128:        azalia_t *az;
                   2129:        codec_t *co;
                   2130:
                   2131:        az = v;
                   2132:        co = &az->codecs[az->codecno];
                   2133:        return co->get_port(co, mc);
                   2134: }
                   2135:
                   2136: int
                   2137: azalia_query_devinfo(void *v, mixer_devinfo_t *mdev)
                   2138: {
                   2139:        azalia_t *az;
                   2140:        const codec_t *co;
                   2141:
                   2142:        az = v;
                   2143:        co = &az->codecs[az->codecno];
                   2144:        if (mdev->index >= co->nmixers)
                   2145:                return ENXIO;
                   2146:        *mdev = co->mixers[mdev->index].devinfo;
                   2147:        return 0;
                   2148: }
                   2149:
                   2150: void *
                   2151: azalia_allocm(void *v, int dir, size_t size, int pool, int flags)
                   2152: {
                   2153:        azalia_t *az;
                   2154:        stream_t *stream;
                   2155:        int err;
                   2156:
                   2157:        az = v;
                   2158:        stream = dir == AUMODE_PLAY ? &az->pstream : &az->rstream;
                   2159:        err = azalia_alloc_dmamem(az, size, 128, &stream->buffer);
                   2160:        if (err) {
                   2161:                printf("%s: allocm failed\n", az->dev.dv_xname);
                   2162:                return NULL;
                   2163:        }
                   2164:        return stream->buffer.addr;
                   2165: }
                   2166:
                   2167: void
                   2168: azalia_freem(void *v, void *addr, int pool)
                   2169: {
                   2170:        azalia_t *az;
                   2171:        stream_t *stream;
                   2172:
                   2173:        az = v;
                   2174:        if (addr == az->pstream.buffer.addr) {
                   2175:                stream = &az->pstream;
                   2176:        } else if (addr == az->rstream.buffer.addr) {
                   2177:                stream = &az->rstream;
                   2178:        } else {
                   2179:                return;
                   2180:        }
                   2181:        azalia_free_dmamem(az, &stream->buffer);
                   2182: }
                   2183:
                   2184: size_t
                   2185: azalia_round_buffersize(void *v, int dir, size_t size)
                   2186: {
                   2187:        size &= ~0x7f;          /* must be multiple of 128 */
                   2188:        if (size <= 0)
                   2189:                size = 128;
                   2190:        return size;
                   2191: }
                   2192:
                   2193: int
                   2194: azalia_get_props(void *v)
                   2195: {
                   2196:        return AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
                   2197: }
                   2198:
                   2199: int
                   2200: azalia_trigger_output(void *v, void *start, void *end, int blk,
                   2201:     void (*intr)(void *), void *arg, audio_params_t *param)
                   2202: {
                   2203:        azalia_t *az;
                   2204:        int err;
                   2205:        uint16_t fmt;
                   2206:
                   2207:        err = azalia_params2fmt(param, &fmt);
                   2208:        if (err)
                   2209:                return EINVAL;
                   2210:
                   2211:        az = v;
                   2212:        return azalia_stream_start(&az->pstream, start, end, blk, intr, arg, fmt);
                   2213: }
                   2214:
                   2215: int
                   2216: azalia_trigger_input(void *v, void *start, void *end, int blk,
                   2217:     void (*intr)(void *), void *arg, audio_params_t *param)
                   2218: {
                   2219:        azalia_t *az;
                   2220:        int err;
                   2221:        uint16_t fmt;
                   2222:
                   2223:        DPRINTF(("%s: this=%p start=%p end=%p blk=%d {enc=%u %uch %u/%ubit %uHz}\n",
                   2224:            __func__, v, start, end, blk, param->encoding, param->channels,
                   2225:            param->precision, param->precision, param->sample_rate));
                   2226:
                   2227:        err = azalia_params2fmt(param, &fmt);
                   2228:        if (err)
                   2229:                return EINVAL;
                   2230:
                   2231:        az = v;
                   2232:        return azalia_stream_start(&az->rstream, start, end, blk, intr, arg, fmt);
                   2233: }
                   2234:
                   2235: /* --------------------------------
                   2236:  * helpers for MI audio functions
                   2237:  * -------------------------------- */
                   2238: int
                   2239: azalia_params2fmt(const audio_params_t *param, uint16_t *fmt)
                   2240: {
                   2241:        uint16_t ret;
                   2242:
                   2243:        ret = 0;
                   2244: #ifdef DIAGNOSTIC
                   2245:        if (param->channels > HDA_MAX_CHANNELS) {
                   2246:                printf("%s: too many channels: %u\n", __func__,
                   2247:                    param->channels);
                   2248:                return EINVAL;
                   2249:        }
                   2250: #endif
                   2251:        ret |= param->channels - 1;
                   2252:
                   2253:        switch (param->precision) {
                   2254:        case 8:
                   2255:                ret |= HDA_SD_FMT_BITS_8_16;
                   2256:                break;
                   2257:        case 16:
                   2258:                ret |= HDA_SD_FMT_BITS_16_16;
                   2259:                break;
                   2260:        case 32:
                   2261:                ret |= HDA_SD_FMT_BITS_32_32;
                   2262:                break;
                   2263:        }
                   2264:
                   2265: #if 0
                   2266:        switch (param->validbits) {
                   2267:        case 8:
                   2268:                ret |= HDA_SD_FMT_BITS_8_16;
                   2269:                break;
                   2270:        case 16:
                   2271:                ret |= HDA_SD_FMT_BITS_16_16;
                   2272:                break;
                   2273:        case 20:
                   2274:                ret |= HDA_SD_FMT_BITS_20_32;
                   2275:                break;
                   2276:        case 24:
                   2277:                ret |= HDA_SD_FMT_BITS_24_32;
                   2278:                break;
                   2279:        case 32:
                   2280:                ret |= HDA_SD_FMT_BITS_32_32;
                   2281:                break;
                   2282:        default:
                   2283:                printf("%s: invalid validbits: %u\n", __func__,
                   2284:                    param->validbits);
                   2285:        }
                   2286: #endif
                   2287:
                   2288:        if (param->sample_rate == 384000) {
                   2289:                printf("%s: invalid sample_rate: %u\n", __func__,
                   2290:                    param->sample_rate);
                   2291:                return EINVAL;
                   2292:        } else if (param->sample_rate == 192000) {
                   2293:                ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X4 | HDA_SD_FMT_DIV_BY1;
                   2294:        } else if (param->sample_rate == 176400) {
                   2295:                ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X4 | HDA_SD_FMT_DIV_BY1;
                   2296:        } else if (param->sample_rate == 96000) {
                   2297:                ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY1;
                   2298:        } else if (param->sample_rate == 88200) {
                   2299:                ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY1;
                   2300:        } else if (param->sample_rate == 48000) {
                   2301:                ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY1;
                   2302:        } else if (param->sample_rate == 44100) {
                   2303:                ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY1;
                   2304:        } else if (param->sample_rate == 32000) {
                   2305:                ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY3;
                   2306:        } else if (param->sample_rate == 22050) {
                   2307:                ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY2;
                   2308:        } else if (param->sample_rate == 16000) {
                   2309:                ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY3;
                   2310:        } else if (param->sample_rate == 11025) {
                   2311:                ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY4;
                   2312:        } else if (param->sample_rate == 8000) {
                   2313:                ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY6;
                   2314:        } else {
                   2315:                printf("%s: invalid sample_rate: %u\n", __func__,
                   2316:                    param->sample_rate);
                   2317:                return EINVAL;
                   2318:        }
                   2319:        *fmt = ret;
                   2320:        return 0;
                   2321: }
                   2322:
                   2323: int
                   2324: azalia_create_encodings(struct audio_format *formats, int nformats,
                   2325:     struct audio_encoding_set **encodings)
                   2326: {
                   2327: #if 0
                   2328:        int i;
                   2329:        u_int j;
                   2330:
                   2331:        for (i = 0; i < nformats; i++) {
                   2332:                printf("format(%d): encoding %u vbits %u prec %u chans %u cmask 0x%x\n",
                   2333:                    i, formats[i].encoding, formats[i].validbits,
                   2334:                    formats[i].precision, formats[i].channels,
                   2335:                    formats[i].channel_mask);
                   2336:                printf("format(%d) rates:", i);
                   2337:                for (j = 0; j < formats[i].frequency_type; j++) {
                   2338:                        printf(" %u", formats[i].frequency[j]);
                   2339:                }
                   2340:                printf("\n");
                   2341:        }
                   2342: #endif
                   2343:        return (0);
                   2344: }

CVSweb