[BACK]Return to gcscaudio.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

Annotation of src/sys/dev/pci/gcscaudio.c, Revision 1.18

1.18    ! isaki       1: /*     $NetBSD: gcscaudio.c,v 1.17 2019/05/08 13:40:19 isaki Exp $     */
1.1       jmcneill    2:
                      3: /*-
                      4:  * Copyright (c) 2008 SHIMIZU Ryo <ryo@nerv.org>
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     17:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     18:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     19:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     20:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     21:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     22:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     23:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     24:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     25:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: #include <sys/cdefs.h>
1.18    ! isaki      30: __KERNEL_RCSID(0, "$NetBSD: gcscaudio.c,v 1.17 2019/05/08 13:40:19 isaki Exp $");
1.1       jmcneill   31:
                     32: #include <sys/param.h>
                     33: #include <sys/systm.h>
1.8       jmcneill   34: #include <sys/kmem.h>
1.1       jmcneill   35: #include <sys/device.h>
                     36: #include <sys/queue.h>
                     37:
                     38: #include <dev/pci/pcidevs.h>
                     39: #include <dev/pci/pcivar.h>
                     40:
                     41: #include <sys/audioio.h>
1.17      isaki      42: #include <dev/audio/audio_if.h>
                     43:
1.1       jmcneill   44: #include <dev/ic/ac97reg.h>
                     45: #include <dev/ic/ac97var.h>
                     46:
                     47: #include <dev/pci/gcscaudioreg.h>
                     48:
                     49:
                     50: #define        GCSCAUDIO_NPRDTABLE     256     /* including a JMP-PRD for loop */
                     51: #define        GCSCAUDIO_PRD_SIZE_MAX  65532   /* limited by CS5536 Controller */
                     52: #define        GCSCAUDIO_BUFSIZE_MAX   (GCSCAUDIO_PRD_SIZE_MAX * (GCSCAUDIO_NPRDTABLE - 1))
                     53:
                     54: struct gcscaudio_prd {
                     55:        /* PRD table for play/rec */
                     56:        struct gcscaudio_prdtables {
                     57: #define        PRD_TABLE_FRONT         0
                     58: #define        PRD_TABLE_SURR          1
                     59: #define        PRD_TABLE_CENTER        2
                     60: #define        PRD_TABLE_LFE           3
                     61: #define        PRD_TABLE_REC           4
                     62: #define        PRD_TABLE_MAX           5
                     63:                struct acc_prd prdtbl[PRD_TABLE_MAX][GCSCAUDIO_NPRDTABLE];
                     64:        } *p_prdtables;
                     65:        bus_dmamap_t p_prdmap;
                     66:        bus_dma_segment_t p_prdsegs[1];
                     67:        int p_prdnseg;
                     68: };
                     69:
                     70: struct gcscaudio_dma {
                     71:        LIST_ENTRY(gcscaudio_dma) list;
                     72:        bus_dmamap_t map;
                     73:        void *addr;
                     74:        size_t size;
                     75:        bus_dma_segment_t segs[1];
                     76:        int nseg;
                     77: };
                     78:
                     79: struct gcscaudio_softc_ch {
                     80:        void (*ch_intr)(void *);
                     81:        void *ch_intr_arg;
                     82:        struct audio_params ch_params;
                     83: };
                     84:
                     85: struct gcscaudio_softc {
1.12      nonaka     86:        device_t sc_dev;
1.8       jmcneill   87:        kmutex_t sc_lock;
                     88:        kmutex_t sc_intr_lock;
1.1       jmcneill   89:        pci_chipset_tag_t sc_pc;
                     90:        pcitag_t sc_pt;
                     91:        void *sc_ih;
                     92:        bus_space_tag_t sc_iot;
                     93:        bus_space_handle_t sc_ioh;
                     94:        bus_size_t sc_ios;
                     95:        bus_dma_tag_t sc_dmat;
                     96:
                     97:        /* allocated DMA buffer list */
                     98:        LIST_HEAD(, gcscaudio_dma) sc_dmalist;
                     99:
                    100: #define GCSCAUDIO_MAXFORMATS   4
                    101:        struct audio_format sc_formats[GCSCAUDIO_MAXFORMATS];
                    102:        int sc_nformats;
                    103:
                    104:        /* AC97 codec */
                    105:        struct ac97_host_if host_if;
                    106:        struct ac97_codec_if *codec_if;
                    107:
                    108:        /* input, output channels */
                    109:        struct gcscaudio_softc_ch sc_play;
                    110:        struct gcscaudio_softc_ch sc_rec;
                    111:        struct gcscaudio_prd sc_prd;
                    112:
                    113:        /* multi channel splitter work; {4,6}ch stream to {2,4} DMA buffers */
                    114:        void *sc_mch_split_buf;
                    115:        void *sc_mch_split_start;
                    116:        int sc_mch_split_off;
                    117:        int sc_mch_split_size;
                    118:        int sc_mch_split_blksize;
                    119:        void (*sc_mch_splitter)(void *, void *, int, int);
                    120:        bool sc_spdif;
                    121: };
                    122:
                    123: /* for cfattach */
1.2       cegger    124: static int gcscaudio_match(device_t, cfdata_t, void *);
1.1       jmcneill  125: static void gcscaudio_attach(device_t, device_t, void *);
                    126:
                    127: /* for audio_hw_if */
                    128: static int gcscaudio_open(void *, int);
                    129: static void gcscaudio_close(void *);
1.17      isaki     130: static int gcscaudio_query_format(void *, audio_format_query_t *);
                    131: static int gcscaudio_set_format(void *, int,
                    132:                                 const audio_params_t *, const audio_params_t *,
                    133:                                 audio_filter_reg_t *, audio_filter_reg_t *);
1.1       jmcneill  134: static int gcscaudio_round_blocksize(void *, int, int, const audio_params_t *);
                    135: static int gcscaudio_halt_output(void *);
                    136: static int gcscaudio_halt_input(void *);
                    137: static int gcscaudio_getdev(void *, struct audio_device *);
                    138: static int gcscaudio_set_port(void *, mixer_ctrl_t *);
                    139: static int gcscaudio_get_port(void *, mixer_ctrl_t *);
                    140: static int gcscaudio_query_devinfo(void *, mixer_devinfo_t *);
1.8       jmcneill  141: static void *gcscaudio_malloc(void *, int, size_t);
                    142: static void gcscaudio_free(void *, void *, size_t);
1.1       jmcneill  143: static size_t gcscaudio_round_buffersize(void *, int, size_t);
                    144: static int gcscaudio_get_props(void *);
                    145: static int gcscaudio_trigger_output(void *, void *, void *, int,
                    146:                                     void (*)(void *), void *,
                    147:                                     const audio_params_t *);
                    148: static int gcscaudio_trigger_input(void *, void *, void *, int,
                    149:                                    void (*)(void *), void *,
                    150:                                    const audio_params_t *);
1.8       jmcneill  151: static void gcscaudio_get_locks(void *, kmutex_t **, kmutex_t **);
1.5       dyoung    152: static bool gcscaudio_resume(device_t, const pmf_qual_t *);
1.1       jmcneill  153: static int gcscaudio_intr(void *);
                    154:
                    155: /* for codec_if */
                    156: static int gcscaudio_attach_codec(void *, struct ac97_codec_if *);
                    157: static int gcscaudio_write_codec(void *, uint8_t, uint16_t);
                    158: static int gcscaudio_read_codec(void *, uint8_t, uint16_t *);
                    159: static int gcscaudio_reset_codec(void *);
                    160: static void gcscaudio_spdif_event_codec(void *, bool);
                    161:
                    162: /* misc */
                    163: static int gcscaudio_append_formats(struct gcscaudio_softc *,
                    164:                                     const struct audio_format *);
                    165: static int gcscaudio_wait_ready_codec(struct gcscaudio_softc *sc, const char *);
                    166: static int gcscaudio_allocate_dma(struct gcscaudio_softc *, size_t, void **,
                    167:                                   bus_dma_segment_t *, int, int *,
1.8       jmcneill  168:                                   bus_dmamap_t *);
1.1       jmcneill  169:
                    170:
1.12      nonaka    171: CFATTACH_DECL_NEW(gcscaudio, sizeof (struct gcscaudio_softc),
1.1       jmcneill  172:     gcscaudio_match, gcscaudio_attach, NULL, NULL);
                    173:
                    174:
                    175: static struct audio_device gcscaudio_device = {
                    176:        "AMD Geode CS5536",
                    177:        "",
                    178:        "gcscaudio"
                    179: };
                    180:
                    181: static const struct audio_hw_if gcscaudio_hw_if = {
                    182:        .open                   = gcscaudio_open,
                    183:        .close                  = gcscaudio_close,
1.17      isaki     184:        .query_format           = gcscaudio_query_format,
                    185:        .set_format             = gcscaudio_set_format,
1.1       jmcneill  186:        .round_blocksize        = gcscaudio_round_blocksize,
                    187:        .commit_settings        = NULL,
                    188:        .init_output            = NULL,
                    189:        .init_input             = NULL,
                    190:        .start_output           = NULL,
                    191:        .start_input            = NULL,
                    192:        .halt_output            = gcscaudio_halt_output,
                    193:        .halt_input             = gcscaudio_halt_input,
                    194:        .speaker_ctl            = NULL,
                    195:        .getdev                 = gcscaudio_getdev,
                    196:        .set_port               = gcscaudio_set_port,
                    197:        .get_port               = gcscaudio_get_port,
                    198:        .query_devinfo          = gcscaudio_query_devinfo,
                    199:        .allocm                 = gcscaudio_malloc,
                    200:        .freem                  = gcscaudio_free,
                    201:        .round_buffersize       = gcscaudio_round_buffersize,
                    202:        .get_props              = gcscaudio_get_props,
                    203:        .trigger_output         = gcscaudio_trigger_output,
                    204:        .trigger_input          = gcscaudio_trigger_input,
                    205:        .dev_ioctl              = NULL,
1.8       jmcneill  206:        .get_locks              = gcscaudio_get_locks,
1.1       jmcneill  207: };
                    208:
1.17      isaki     209: #define GCSCAUDIO_FORMAT(aumode, ch, chmask) \
                    210:        { \
                    211:                .mode           = (aumode), \
                    212:                .encoding       = AUDIO_ENCODING_SLINEAR_LE, \
                    213:                .validbits      = 16, \
                    214:                .precision      = 16, \
                    215:                .channels       = (ch), \
                    216:                .channel_mask   = (chmask), \
                    217:                .frequency_type = 0, \
                    218:                .frequency      = { 8000, 48000 }, \
                    219:        }
                    220: static const struct audio_format gcscaudio_formats_2ch =
                    221:        GCSCAUDIO_FORMAT(AUMODE_PLAY | AUMODE_RECORD, 2, AUFMT_STEREO);
1.1       jmcneill  222:
1.17      isaki     223: static const struct audio_format gcscaudio_formats_4ch =
                    224:        GCSCAUDIO_FORMAT(AUMODE_PLAY                , 4, AUFMT_SURROUND4);
1.1       jmcneill  225:
1.17      isaki     226: static const struct audio_format gcscaudio_formats_6ch =
                    227:        GCSCAUDIO_FORMAT(AUMODE_PLAY                , 6, AUFMT_DOLBY_5_1);
1.1       jmcneill  228:
                    229: static int
1.2       cegger    230: gcscaudio_match(device_t parent, cfdata_t match, void *aux)
1.1       jmcneill  231: {
                    232:        struct pci_attach_args *pa;
                    233:
                    234:        pa = (struct pci_attach_args *)aux;
                    235:        if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD) &&
                    236:            (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_CS5536_AUDIO))
                    237:                return 1;
                    238:
                    239:        return 0;
                    240: }
                    241:
                    242: static int
                    243: gcscaudio_append_formats(struct gcscaudio_softc *sc,
                    244:                          const struct audio_format *format)
                    245: {
                    246:        if (sc->sc_nformats >= GCSCAUDIO_MAXFORMATS) {
1.12      nonaka    247:                aprint_error_dev(sc->sc_dev, "too many formats\n");
1.1       jmcneill  248:                return EINVAL;
                    249:        }
                    250:        sc->sc_formats[sc->sc_nformats++] = *format;
                    251:        return 0;
                    252: }
                    253:
                    254: static void
                    255: gcscaudio_attach(device_t parent, device_t self, void *aux)
                    256: {
                    257:        struct gcscaudio_softc *sc;
                    258:        struct pci_attach_args *pa;
                    259:        const char *intrstr;
                    260:        pci_intr_handle_t ih;
                    261:        int rc, i;
1.14      christos  262:        char intrbuf[PCI_INTRSTR_LEN];
1.1       jmcneill  263:
                    264:        sc = device_private(self);
                    265:
1.12      nonaka    266:        sc->sc_dev = self;
                    267:
1.1       jmcneill  268:        aprint_naive(": Audio controller\n");
                    269:
                    270:        pa = aux;
                    271:        sc->sc_pc = pa->pa_pc;
                    272:        sc->sc_pt = pa->pa_tag;
                    273:        sc->sc_dmat = pa->pa_dmat;
                    274:        LIST_INIT(&sc->sc_dmalist);
                    275:        sc->sc_mch_split_buf = NULL;
1.8       jmcneill  276:        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
1.9       mrg       277:        mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
1.1       jmcneill  278:
                    279:        aprint_normal(": AMD Geode CS5536 Audio\n");
                    280:
                    281:        if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_IO, 0,
                    282:            &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios)) {
1.12      nonaka    283:                aprint_error_dev(sc->sc_dev, "can't map i/o space\n");
1.1       jmcneill  284:                return;
                    285:        }
                    286:
                    287:        if (pci_intr_map(pa, &ih)) {
1.12      nonaka    288:                aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n");
1.1       jmcneill  289:                goto attach_failure_unmap;
                    290:        }
1.14      christos  291:        intrstr = pci_intr_string(sc->sc_pc, ih, intrbuf, sizeof(intrbuf));
1.1       jmcneill  292:
1.16      jdolecek  293:        sc->sc_ih = pci_intr_establish_xname(sc->sc_pc, ih, IPL_AUDIO,
                    294:            gcscaudio_intr, sc, device_xname(self));
1.1       jmcneill  295:        if (sc->sc_ih == NULL) {
1.12      nonaka    296:                aprint_error_dev(sc->sc_dev, "couldn't establish interrupt");
1.1       jmcneill  297:                if (intrstr != NULL)
1.3       njoly     298:                        aprint_error(" at %s", intrstr);
                    299:                aprint_error("\n");
1.1       jmcneill  300:                goto attach_failure_unmap;
                    301:        }
                    302:
1.12      nonaka    303:        aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
1.1       jmcneill  304:
                    305:
                    306:        if (gcscaudio_allocate_dma(sc, sizeof(*sc->sc_prd.p_prdtables),
                    307:            (void **)&(sc->sc_prd.p_prdtables), sc->sc_prd.p_prdsegs, 1,
1.8       jmcneill  308:            &(sc->sc_prd.p_prdnseg), &(sc->sc_prd.p_prdmap)) != 0)
1.1       jmcneill  309:                goto attach_failure_intr;
                    310:
                    311:        sc->host_if.arg = sc;
                    312:        sc->host_if.attach = gcscaudio_attach_codec;
                    313:        sc->host_if.read = gcscaudio_read_codec;
                    314:        sc->host_if.write = gcscaudio_write_codec;
                    315:        sc->host_if.reset = gcscaudio_reset_codec;
                    316:        sc->host_if.spdif_event = gcscaudio_spdif_event_codec;
                    317:
1.8       jmcneill  318:        if ((rc = ac97_attach(&sc->host_if, self, &sc->sc_lock)) != 0) {
1.12      nonaka    319:                aprint_error_dev(sc->sc_dev,
1.1       jmcneill  320:                    "can't attach codec (error=%d)\n", rc);
                    321:                goto attach_failure_intr;
                    322:        }
                    323:
                    324:        if (!pmf_device_register(self, NULL, gcscaudio_resume))
                    325:                aprint_error_dev(self, "couldn't establish power handler\n");
                    326:
                    327:
                    328:        sc->sc_nformats = 0;
                    329:        gcscaudio_append_formats(sc, &gcscaudio_formats_2ch);
1.10      jmcneill  330:
                    331:        mutex_enter(&sc->sc_lock);
1.1       jmcneill  332:        if (AC97_IS_4CH(sc->codec_if))
                    333:                gcscaudio_append_formats(sc, &gcscaudio_formats_4ch);
                    334:        if (AC97_IS_6CH(sc->codec_if))
                    335:                gcscaudio_append_formats(sc, &gcscaudio_formats_6ch);
                    336:        if (AC97_IS_FIXED_RATE(sc->codec_if)) {
                    337:                for (i = 0; i < sc->sc_nformats; i++) {
                    338:                        sc->sc_formats[i].frequency_type = 1;
                    339:                        sc->sc_formats[i].frequency[0] = 48000;
                    340:                }
                    341:        }
1.10      jmcneill  342:        mutex_exit(&sc->sc_lock);
1.1       jmcneill  343:
1.12      nonaka    344:        audio_attach_mi(&gcscaudio_hw_if, sc, sc->sc_dev);
1.1       jmcneill  345:        return;
                    346:
                    347: attach_failure_intr:
                    348:        pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
                    349: attach_failure_unmap:
                    350:        bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
                    351:        return;
                    352: }
                    353:
                    354: static int
                    355: gcscaudio_attach_codec(void *arg, struct ac97_codec_if *codec_if)
                    356: {
                    357:        struct gcscaudio_softc *sc;
                    358:
                    359:        sc = (struct gcscaudio_softc *)arg;
                    360:        sc->codec_if = codec_if;
                    361:        return 0;
                    362: }
                    363:
                    364: static int
                    365: gcscaudio_reset_codec(void *arg)
                    366: {
                    367:        struct gcscaudio_softc *sc;
                    368:        sc = (struct gcscaudio_softc *)arg;
                    369:
                    370:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL,
                    371:            ACC_CODEC_CNTL_LNK_WRM_RST |
                    372:            ACC_CODEC_CNTL_CMD_NEW);
                    373:
                    374:        if (gcscaudio_wait_ready_codec(sc, "reset timeout\n"))
                    375:                return 1;
                    376:
                    377:        return 0;
                    378: }
                    379:
                    380: static void
                    381: gcscaudio_spdif_event_codec(void *arg, bool flag)
                    382: {
                    383:        struct gcscaudio_softc *sc;
                    384:
                    385:        sc = (struct gcscaudio_softc *)arg;
                    386:        sc->sc_spdif = flag;
                    387: }
                    388:
                    389: static int
                    390: gcscaudio_wait_ready_codec(struct gcscaudio_softc *sc, const char *timeout_msg)
                    391: {
                    392:        int i;
                    393:
                    394: #define GCSCAUDIO_WAIT_READY_CODEC_TIMEOUT     500
                    395:        for (i = GCSCAUDIO_WAIT_READY_CODEC_TIMEOUT; (i >= 0) &&
                    396:            (bus_space_read_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL) &
                    397:            ACC_CODEC_CNTL_CMD_NEW); i--)
                    398:                delay(1);
                    399:
                    400:        if (i < 0) {
1.12      nonaka    401:                aprint_error_dev(sc->sc_dev, "%s", timeout_msg);
1.1       jmcneill  402:                return 1;
                    403:        }
                    404:
                    405:        return 0;
                    406: }
                    407:
                    408: static int
                    409: gcscaudio_write_codec(void *arg, uint8_t reg, uint16_t val)
                    410: {
                    411:        struct gcscaudio_softc *sc;
                    412:
                    413:        sc = (struct gcscaudio_softc *)arg;
                    414:
                    415:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL,
                    416:            ACC_CODEC_CNTL_WRITE_CMD |
                    417:            ACC_CODEC_CNTL_CMD_NEW |
                    418:            ACC_CODEC_REG2ADDR(reg) |
                    419:            (val & ACC_CODEC_CNTL_CMD_DATA_MASK));
                    420:
                    421:        if (gcscaudio_wait_ready_codec(sc, "codec write timeout\n"))
                    422:                return 1;
                    423:
                    424: #ifdef GCSCAUDIO_CODEC_DEBUG
1.12      nonaka    425:        aprint_error_dev(sc->sc_dev, "codec write: reg=0x%02x, val=0x%04x\n",
1.1       jmcneill  426:            reg, val);
                    427: #endif
                    428:
                    429:        return 0;
                    430: }
                    431:
                    432: static int
                    433: gcscaudio_read_codec(void *arg, uint8_t reg, uint16_t *val)
                    434: {
                    435:        struct gcscaudio_softc *sc;
                    436:        uint32_t v;
                    437:        int i;
                    438:
                    439:        sc = (struct gcscaudio_softc *)arg;
                    440:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL,
                    441:            ACC_CODEC_CNTL_READ_CMD | ACC_CODEC_CNTL_CMD_NEW |
                    442:            ACC_CODEC_REG2ADDR(reg));
                    443:
                    444:        if (gcscaudio_wait_ready_codec(sc, "codec write timeout for reading"))
                    445:                return 1;
                    446:
                    447: #define GCSCAUDIO_READ_CODEC_TIMEOUT   50
                    448:        for (i = GCSCAUDIO_READ_CODEC_TIMEOUT; i >= 0; i--) {
                    449:                v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_STATUS);
                    450:                if ((v & ACC_CODEC_STATUS_STS_NEW) &&
                    451:                    (ACC_CODEC_ADDR2REG(v) == reg))
                    452:                        break;
                    453:
                    454:                delay(10);
                    455:        }
                    456:
                    457:        if (i < 0) {
1.12      nonaka    458:                aprint_error_dev(sc->sc_dev, "codec read timeout\n");
1.1       jmcneill  459:                return 1;
                    460:        }
                    461:
                    462: #ifdef GCSCAUDIO_CODEC_DEBUG
1.12      nonaka    463:        aprint_error_dev(sc->sc_dev, "codec read: reg=0x%02x, val=0x%04x\n",
1.1       jmcneill  464:            reg, v & ACC_CODEC_STATUS_STS_DATA_MASK);
                    465: #endif
                    466:
                    467:        *val = v;
                    468:        return 0;
                    469: }
                    470:
                    471: static int
                    472: gcscaudio_open(void *arg, int flags)
                    473: {
                    474:        struct gcscaudio_softc *sc;
                    475:
                    476:        sc = (struct gcscaudio_softc *)arg;
                    477:        sc->codec_if->vtbl->lock(sc->codec_if);
                    478:        return 0;
                    479: }
                    480:
                    481: static void
                    482: gcscaudio_close(void *arg)
                    483: {
                    484:        struct gcscaudio_softc *sc;
                    485:
                    486:        sc = (struct gcscaudio_softc *)arg;
                    487:        sc->codec_if->vtbl->unlock(sc->codec_if);
                    488: }
                    489:
                    490: static int
1.17      isaki     491: gcscaudio_query_format(void *arg, audio_format_query_t *afp)
1.1       jmcneill  492: {
                    493:        struct gcscaudio_softc *sc;
                    494:
                    495:        sc = (struct gcscaudio_softc *)arg;
1.17      isaki     496:        return audio_query_format(sc->sc_formats, sc->sc_nformats, afp);
1.1       jmcneill  497: }
                    498:
                    499: static int
1.17      isaki     500: gcscaudio_set_format(void *arg, int setmode,
                    501:                      const audio_params_t *play, const audio_params_t *rec,
                    502:                      audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
1.1       jmcneill  503: {
1.17      isaki     504:        struct gcscaudio_softc *sc;
                    505:        int rate;
                    506:        int error;
1.1       jmcneill  507:
1.17      isaki     508:        sc = (struct gcscaudio_softc *)arg;
1.1       jmcneill  509:
1.17      isaki     510:        if (setmode & AUMODE_PLAY) {
1.1       jmcneill  511:                if (!AC97_IS_FIXED_RATE(sc->codec_if)) {
1.13      ryo       512:                        /* setup rate of DAC */
1.17      isaki     513:                        rate = play->sample_rate;
1.1       jmcneill  514:                        if ((error = sc->codec_if->vtbl->set_rate(sc->codec_if,
1.17      isaki     515:                            AC97_REG_PCM_FRONT_DAC_RATE, &rate)) != 0)
1.1       jmcneill  516:                                return error;
                    517:
                    518:                        /* additional rate of DAC for Surround */
1.17      isaki     519:                        rate = play->sample_rate;
                    520:                        if ((play->channels >= 4) &&
1.1       jmcneill  521:                            (error = sc->codec_if->vtbl->set_rate(sc->codec_if,
1.17      isaki     522:                            AC97_REG_PCM_SURR_DAC_RATE, &rate)) != 0)
1.1       jmcneill  523:                                return error;
                    524:
                    525:                        /* additional rate of DAC for LowFrequencyEffect */
1.17      isaki     526:                        rate = play->sample_rate;
                    527:                        if ((play->channels == 6) &&
1.1       jmcneill  528:                            (error = sc->codec_if->vtbl->set_rate(sc->codec_if,
1.17      isaki     529:                            AC97_REG_PCM_LFE_DAC_RATE, &rate)) != 0)
1.1       jmcneill  530:                                return error;
                    531:                }
1.17      isaki     532:                sc->sc_play.ch_params = *rec;
1.1       jmcneill  533:        }
1.17      isaki     534:        if (setmode & AUMODE_RECORD) {
1.1       jmcneill  535:                if (!AC97_IS_FIXED_RATE(sc->codec_if)) {
1.13      ryo       536:                        /* setup rate of ADC */
1.17      isaki     537:                        rate = rec->sample_rate;
1.1       jmcneill  538:                        if ((error = sc->codec_if->vtbl->set_rate(sc->codec_if,
1.17      isaki     539:                            AC97_REG_PCM_LR_ADC_RATE, &rate)) != 0)
1.1       jmcneill  540:                                return error;
                    541:                }
1.17      isaki     542:                sc->sc_rec.ch_params = *rec;
1.1       jmcneill  543:        }
                    544:
                    545:        return 0;
                    546: }
                    547:
                    548: static int
                    549: gcscaudio_round_blocksize(void *arg, int blk, int mode,
                    550:                           const audio_params_t *param)
                    551: {
                    552:        blk &= -4;
                    553:        if (blk > GCSCAUDIO_PRD_SIZE_MAX)
                    554:                blk = GCSCAUDIO_PRD_SIZE_MAX;
                    555:
                    556:        return blk;
                    557: }
                    558:
                    559: static int
                    560: gcscaudio_halt_output(void *arg)
                    561: {
                    562:        struct gcscaudio_softc *sc;
                    563:
                    564:        sc = (struct gcscaudio_softc *)arg;
                    565:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
                    566:            ACC_BMx_CMD_BM_CTL_DISABLE);
                    567:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM4_CMD,
                    568:            ACC_BMx_CMD_BM_CTL_DISABLE);
                    569:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
                    570:            ACC_BMx_CMD_BM_CTL_DISABLE);
                    571:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM7_CMD,
                    572:            ACC_BMx_CMD_BM_CTL_DISABLE);
                    573:        sc->sc_play.ch_intr = NULL;
                    574:
                    575:        /* channel splitter */
                    576:        sc->sc_mch_splitter = NULL;
                    577:        if (sc->sc_mch_split_buf)
1.8       jmcneill  578:                gcscaudio_free(sc, sc->sc_mch_split_buf, sc->sc_mch_split_size);
1.1       jmcneill  579:        sc->sc_mch_split_buf = NULL;
                    580:
                    581:        return 0;
                    582: }
                    583:
                    584: static int
                    585: gcscaudio_halt_input(void *arg)
                    586: {
                    587:        struct gcscaudio_softc *sc;
                    588:
                    589:        sc = (struct gcscaudio_softc *)arg;
                    590:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM1_CMD,
                    591:            ACC_BMx_CMD_BM_CTL_DISABLE);
                    592:        sc->sc_rec.ch_intr = NULL;
                    593:        return 0;
                    594: }
                    595:
                    596: static int
                    597: gcscaudio_getdev(void *addr, struct audio_device *retp)
                    598: {
                    599:        *retp = gcscaudio_device;
                    600:        return 0;
                    601: }
                    602:
                    603: static int
                    604: gcscaudio_set_port(void *addr, mixer_ctrl_t *cp)
                    605: {
                    606:        struct gcscaudio_softc *sc;
                    607:
                    608:        sc = addr;
                    609:        return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
                    610: }
                    611:
                    612: static int
                    613: gcscaudio_get_port(void *addr, mixer_ctrl_t *cp)
                    614: {
                    615:        struct gcscaudio_softc *sc;
                    616:
                    617:        sc = addr;
                    618:        return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
                    619: }
                    620:
                    621: static int
                    622: gcscaudio_query_devinfo(void *addr, mixer_devinfo_t *dip)
                    623: {
                    624:        struct gcscaudio_softc *sc;
                    625:
                    626:        sc = addr;
                    627:        return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip);
                    628: }
                    629:
                    630: static void *
1.8       jmcneill  631: gcscaudio_malloc(void *arg, int direction, size_t size)
1.1       jmcneill  632: {
                    633:        struct gcscaudio_softc *sc;
                    634:        struct gcscaudio_dma *p;
                    635:        int error;
                    636:
                    637:        sc = (struct gcscaudio_softc *)arg;
                    638:
1.8       jmcneill  639:        p = kmem_alloc(sizeof(*p), KM_SLEEP);
1.1       jmcneill  640:        p->size = size;
                    641:
                    642:        error = gcscaudio_allocate_dma(sc, size, &p->addr,
1.8       jmcneill  643:            p->segs, sizeof(p->segs)/sizeof(p->segs[0]), &p->nseg, &p->map);
1.1       jmcneill  644:        if (error) {
1.8       jmcneill  645:                kmem_free(p, sizeof(*p));
1.1       jmcneill  646:                return NULL;
                    647:        }
                    648:
                    649:        LIST_INSERT_HEAD(&sc->sc_dmalist, p, list);
                    650:        return p->addr;
                    651: }
                    652:
                    653: static void
1.8       jmcneill  654: gcscaudio_free(void *arg, void *ptr, size_t size)
1.1       jmcneill  655: {
                    656:        struct gcscaudio_softc *sc;
                    657:        struct gcscaudio_dma *p;
                    658:
                    659:        sc = (struct gcscaudio_softc *)arg;
                    660:
                    661:        LIST_FOREACH(p, &sc->sc_dmalist, list) {
                    662:                if (p->addr == ptr) {
                    663:                        bus_dmamap_unload(sc->sc_dmat, p->map);
                    664:                        bus_dmamap_destroy(sc->sc_dmat, p->map);
                    665:                        bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
                    666:                        bus_dmamem_free(sc->sc_dmat, p->segs, p->nseg);
                    667:
                    668:                        LIST_REMOVE(p, list);
1.8       jmcneill  669:                        kmem_free(p, sizeof(*p));
1.1       jmcneill  670:                        break;
                    671:                }
                    672:        }
                    673: }
                    674:
                    675: static size_t
                    676: gcscaudio_round_buffersize(void *addr, int direction, size_t size)
                    677: {
                    678:        if (size > GCSCAUDIO_BUFSIZE_MAX)
                    679:                size = GCSCAUDIO_BUFSIZE_MAX;
                    680:
                    681:        return size;
                    682: }
                    683:
                    684: static int
                    685: gcscaudio_get_props(void *addr)
                    686: {
                    687:
1.18    ! isaki     688:        return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE |
        !           689:            AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1.1       jmcneill  690: }
                    691:
                    692: static int
                    693: build_prdtables(struct gcscaudio_softc *sc, int prdidx,
                    694:                 void *addr, size_t size, int blksize, int blklen, int blkoff)
                    695: {
                    696:        struct gcscaudio_dma *p;
                    697:        struct acc_prd *prdp;
                    698:        bus_addr_t paddr;
                    699:        int i;
                    700:
                    701:        /* get physical address of start */
                    702:        paddr = (bus_addr_t)0;
                    703:        LIST_FOREACH(p, &sc->sc_dmalist, list) {
                    704:                if (p->addr == addr) {
                    705:                        paddr = p->map->dm_segs[0].ds_addr;
                    706:                        break;
                    707:                }
                    708:        }
                    709:        if (!paddr) {
1.12      nonaka    710:                aprint_error_dev(sc->sc_dev, "bad addr %p\n", addr);
1.1       jmcneill  711:                return EINVAL;
                    712:        }
                    713:
                    714: #define PRDADDR(prdidx,idx) \
                    715:        (sc->sc_prd.p_prdmap->dm_segs[0].ds_addr) + sizeof(struct acc_prd) * \
                    716:        (((prdidx) * GCSCAUDIO_NPRDTABLE) + (idx))
                    717:
                    718:        /*
                    719:         * build PRD table
                    720:         *   prdtbl[] = <PRD0>, <PRD1>, <PRD2>, ..., <PRDn>, <jmp to PRD0>
                    721:         */
                    722:        prdp = sc->sc_prd.p_prdtables->prdtbl[prdidx];
                    723:        for (i = 0; size > 0; size -= blksize, i++) {
                    724:                prdp[i].address = paddr + blksize * i + blkoff;
                    725:                prdp[i].ctrlsize =
                    726:                    (size < blklen ? size : blklen) | ACC_BMx_PRD_CTRL_EOP;
                    727:        }
                    728:        prdp[i].address = PRDADDR(prdidx, 0);
                    729:        prdp[i].ctrlsize = ACC_BMx_PRD_CTRL_JMP;
                    730:
                    731:        bus_dmamap_sync(sc->sc_dmat, sc->sc_prd.p_prdmap, 0,
                    732:            sizeof(struct acc_prd) * i, BUS_DMASYNC_PREWRITE);
                    733:
                    734:        return 0;
                    735: }
                    736:
                    737: static void
                    738: split_buffer_4ch(void *dst, void *src, int size, int blksize)
                    739: {
                    740:        int left, i;
                    741:        uint16_t *s, *d;
                    742:
                    743:        /*
                    744:         * src[blk0]: L,R,SL,SR,L,R,SL,SR,L,R,SL,SR,....
                    745:         * src[blk1]: L,R,SL,SR,L,R,SL,SR,L,R,SL,SR,....
                    746:         * src[blk2]: L,R,SL,SR,L,R,SL,SR,L,R,SL,SR,....
                    747:         *     :
                    748:         *
                    749:         *   rearrange to
                    750:         *
                    751:         * src[blk0]: L,R,L,R,L,R,L,R,..
                    752:         * src[blk1]: L,R,L,R,L,R,L,R,..
                    753:         * src[blk2]: L,R,L,R,L,R,L,R,..
                    754:         *     :
                    755:         * dst[blk0]: SL,SR,SL,SR,SL,SR,SL,SR,..
                    756:         * dst[blk1]: SL,SR,SL,SR,SL,SR,SL,SR,..
                    757:         * dst[blk2]: SL,SR,SL,SR,SL,SR,SL,SR,..
                    758:         *     :
                    759:         */
                    760:        for (left = size; left > 0; left -= blksize) {
                    761:                s = (uint16_t *)src;
                    762:                d = (uint16_t *)dst;
                    763:                for (i = 0; i < blksize / sizeof(uint16_t) / 4; i++) {
                    764:                        /* L,R,SL,SR -> SL,SR */
                    765:                        s++;
                    766:                        s++;
                    767:                        *d++ = *s++;
                    768:                        *d++ = *s++;
                    769:                }
                    770:
                    771:                s = (uint16_t *)src;
                    772:                d = (uint16_t *)src;
                    773:                for (i = 0; i < blksize / sizeof(uint16_t) / 2 / 2; i++) {
                    774:                        /* L,R,SL,SR -> L,R */
                    775:                        *d++ = *s++;
                    776:                        *d++ = *s++;
                    777:                        s++;
                    778:                        s++;
                    779:                }
                    780:
                    781:                src = (char *)src + blksize;
                    782:                dst = (char *)dst + blksize;
                    783:        }
                    784: }
                    785:
                    786: static void
                    787: split_buffer_6ch(void *dst, void *src, int size, int blksize)
                    788: {
                    789:        int left, i;
                    790:        uint16_t *s, *d, *dc, *dl;
                    791:
                    792:        /*
                    793:         * by default, treat as WAV style 5.1ch order
                    794:         *   5.1ch(WAV): L R C LFE SL SR
                    795:         *   5.1ch(AAC): C L R SL SR LFE
                    796:         *        :
                    797:         */
                    798:
                    799:        /*
                    800:         * src[blk0]: L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
                    801:         * src[blk1]: L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
                    802:         * src[blk2]: L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
                    803:         *     :
                    804:         * src[N-1] : L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
                    805:         *
                    806:         *   rearrange to
                    807:         *
                    808:         * src[blk0]: L,R,L,R,..
                    809:         * src[blk1]: L,R,L,R,..
                    810:         * src[blk2]: L,R,L,R,..
                    811:         *     :
                    812:         *
                    813:         * dst[blk0]: SL,SR,SL,SR,..
                    814:         * dst[blk1]: SL,SR,SL,SR,..
                    815:         * dst[blk2]: SL,SR,SL,SR,..
                    816:         *     :
                    817:         *
                    818:         * dst[N/2+0]: C,C,C,..
                    819:         * dst[N/2+1]: C,C,C,..
                    820:         *     :
                    821:         *
                    822:         * dst[N/2+N/4+0]: LFE,LFE,LFE,..
                    823:         * dst[N/2+N/4+1]: LFE,LFE,LFE,..
                    824:         *     :
                    825:         */
                    826:
                    827:        for (left = size; left > 0; left -= blksize) {
                    828:                s = (uint16_t *)src;
                    829:                d = (uint16_t *)dst;
                    830:                dc = (uint16_t *)((char *)dst + blksize / 2);
                    831:                dl = (uint16_t *)((char *)dst + blksize / 2 + blksize / 4);
                    832:                for (i = 0; i < blksize / sizeof(uint16_t) / 6; i++) {
                    833: #ifdef GCSCAUDIO_5_1CH_AAC_ORDER
                    834:                        /*
                    835:                         * AAC: [C,L,R,SL,SR,LFE]
                    836:                         *  => [SL,SR]
                    837:                         *  => [C]
                    838:                         *  => [LFE]
                    839:                         */
                    840:                        *dc++ = s[0];   /* C */
                    841:                        *dl++ = s[5];   /* LFE */
                    842:                        *d++ = s[3];    /* SL */
                    843:                        *d++ = s[4];    /* SR */
                    844: #else
                    845:                        /*
                    846:                         * WAV: [L,R,C,LFE,SL,SR]
                    847:                         *  => [SL,SR]
                    848:                         *  => [C]
                    849:                         *  => [LFE]
                    850:                         */
                    851:                        *dc++ = s[2];   /* C */
                    852:                        *dl++ = s[3];   /* LFE */
                    853:                        *d++ = s[4];    /* SL */
                    854:                        *d++ = s[5];    /* SR */
                    855: #endif
                    856:                        s += 6;
                    857:                }
                    858:
                    859:                s = (uint16_t *)src;
                    860:                d = (uint16_t *)src;
                    861:                for (i = 0; i < blksize / sizeof(uint16_t) / 2 / 2; i++) {
                    862: #ifdef GCSCAUDIO_5_1CH_AAC_ORDER
                    863:                        /* AAC: [C,L,R,SL,SR,LFE] => [L,R] */
                    864:                        *d++ = s[1];
                    865:                        *d++ = s[2];
                    866: #else
                    867:                        /* WAV: [L,R,C,LFE,SL,SR] => [L,R] */
                    868:                        *d++ = s[0];
                    869:                        *d++ = s[1];
                    870: #endif
                    871:                        s += 6;
                    872:                }
                    873:
                    874:                src = (char *)src + blksize;
                    875:                dst = (char *)dst + blksize;
                    876:        }
                    877: }
                    878:
                    879: static void
                    880: channel_splitter(struct gcscaudio_softc *sc)
                    881: {
                    882:        int splitsize, left;
                    883:        void *src, *dst;
                    884:
                    885:        if (sc->sc_mch_splitter == NULL)
                    886:                return;
                    887:
                    888:        left = sc->sc_mch_split_size - sc->sc_mch_split_off;
                    889:        splitsize = sc->sc_mch_split_blksize;
                    890:        if (left < splitsize)
                    891:                splitsize = left;
                    892:
                    893:        src = (char *)sc->sc_mch_split_start + sc->sc_mch_split_off;
                    894:        dst = (char *)sc->sc_mch_split_buf + sc->sc_mch_split_off;
                    895:
                    896:        sc->sc_mch_splitter(dst, src, splitsize, sc->sc_mch_split_blksize);
                    897:
                    898:        sc->sc_mch_split_off += sc->sc_mch_split_blksize;
                    899:        if (sc->sc_mch_split_off >= sc->sc_mch_split_size)
                    900:                sc->sc_mch_split_off = 0;
                    901: }
                    902:
                    903: static int
                    904: gcscaudio_trigger_output(void *addr, void *start, void *end, int blksize,
                    905:                          void (*intr)(void *), void *arg,
                    906:                          const audio_params_t *param)
                    907: {
                    908:        struct gcscaudio_softc *sc;
                    909:        size_t size;
                    910:
                    911:        sc = (struct gcscaudio_softc *)addr;
                    912:        sc->sc_play.ch_intr = intr;
                    913:        sc->sc_play.ch_intr_arg = arg;
                    914:        size = (char *)end - (char *)start;
                    915:
                    916:        switch (sc->sc_play.ch_params.channels) {
                    917:        case 2:
                    918:                if (build_prdtables(sc, PRD_TABLE_FRONT, start, size, blksize,
                    919:                    blksize, 0))
                    920:                        return EINVAL;
                    921:
                    922:                if (!AC97_IS_4CH(sc->codec_if)) {
                    923:                        /*
                    924:                         * output 2ch PCM to FRONT.LR(BM0)
                    925:                         *
                    926:                         * 2ch: L,R,L,R,L,R,L,R,... => BM0: L,R,L,R,L,R,L,R,...
                    927:                         *
                    928:                         */
                    929:                        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
                    930:                            PRDADDR(PRD_TABLE_FRONT, 0));
                    931:
                    932:                        /* start DMA transfer */
                    933:                        bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
                    934:                            ACC_BMx_CMD_WRITE |
                    935:                            ACC_BMx_CMD_BYTE_ORD_EL |
                    936:                            ACC_BMx_CMD_BM_CTL_ENABLE);
                    937:                } else {
                    938:                        /*
                    939:                         * output same PCM to FRONT.LR(BM0) and SURROUND.LR(BM6).
                    940:                         * CENTER(BM4) and LFE(BM7) doesn't sound.
                    941:                         *
                    942:                         * 2ch: L,R,L,R,L,R,L,R,... => BM0: L,R,L,R,L,R,L,R,...
                    943:                         *                             BM6: (same of BM0)
                    944:                         *                             BM4: none
                    945:                         *                             BM7: none
                    946:                         */
                    947:                        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
                    948:                            PRDADDR(PRD_TABLE_FRONT, 0));
                    949:                        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_PRD,
                    950:                            PRDADDR(PRD_TABLE_FRONT, 0));
                    951:
                    952:                        /* start DMA transfer */
                    953:                        bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
                    954:                            ACC_BMx_CMD_WRITE |
                    955:                            ACC_BMx_CMD_BYTE_ORD_EL |
                    956:                            ACC_BMx_CMD_BM_CTL_ENABLE);
                    957:                        bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
                    958:                            ACC_BMx_CMD_WRITE |
                    959:                            ACC_BMx_CMD_BYTE_ORD_EL |
                    960:                            ACC_BMx_CMD_BM_CTL_ENABLE);
                    961:                }
                    962:                break;
                    963:        case 4:
                    964:                /*
                    965:                 * output 4ch PCM split to FRONT.LR(BM0) and SURROUND.LR(BM6).
                    966:                 * CENTER(BM4) and LFE(BM7) doesn't sound.
                    967:                 *
                    968:                 * rearrange ordered channel to continuous per channel
                    969:                 *
                    970:                 *   4ch: L,R,SL,SR,L,R,SL,SR,... => BM0: L,R,L,R,...
                    971:                 *                                   BM6: SL,SR,SL,SR,...
                    972:                 *                                   BM4: none
                    973:                 *                                   BM7: none
                    974:                 */
                    975:                if (sc->sc_mch_split_buf)
1.8       jmcneill  976:                        gcscaudio_free(sc, sc->sc_mch_split_buf,
                    977:                            sc->sc_mch_split_size);
1.1       jmcneill  978:
                    979:                if ((sc->sc_mch_split_buf = gcscaudio_malloc(sc, AUMODE_PLAY,
1.8       jmcneill  980:                    size)) == NULL)
1.1       jmcneill  981:                        return ENOMEM;
                    982:
                    983:                /*
                    984:                 * 1st and 2nd blocks are split immediately.
                    985:                 * Other blocks will be split synchronous with intr.
                    986:                 */
                    987:                split_buffer_4ch(sc->sc_mch_split_buf, start, blksize * 2,
                    988:                    blksize);
                    989:
                    990:                sc->sc_mch_split_start = start;
                    991:                sc->sc_mch_split_size = size;
                    992:                sc->sc_mch_split_blksize = blksize;
                    993:                sc->sc_mch_split_off = (blksize * 2) % size;
                    994:                sc->sc_mch_splitter = split_buffer_4ch; /* split function */
                    995:
                    996:                if (build_prdtables(sc, PRD_TABLE_FRONT, start, size, blksize,
                    997:                    blksize / 2, 0))
                    998:                        return EINVAL;
                    999:                if (build_prdtables(sc, PRD_TABLE_SURR, sc->sc_mch_split_buf,
                   1000:                    size, blksize, blksize / 2, 0))
                   1001:                        return EINVAL;
                   1002:
                   1003:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
                   1004:                    PRDADDR(PRD_TABLE_FRONT, 0));
                   1005:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_PRD,
                   1006:                    PRDADDR(PRD_TABLE_SURR, 0));
                   1007:
                   1008:                /* start DMA transfer */
                   1009:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
                   1010:                    ACC_BMx_CMD_WRITE |
                   1011:                    ACC_BMx_CMD_BYTE_ORD_EL |
                   1012:                    ACC_BMx_CMD_BM_CTL_ENABLE);
                   1013:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
                   1014:                    ACC_BMx_CMD_WRITE |
                   1015:                    ACC_BMx_CMD_BYTE_ORD_EL |
                   1016:                    ACC_BMx_CMD_BM_CTL_ENABLE);
                   1017:                break;
                   1018:        case 6:
                   1019:                /*
                   1020:                 * output 6ch PCM split to
                   1021:                 * FRONT.LR(BM0), SURROUND.LR(BM6), CENTER(BM4) and LFE(BM7)
                   1022:                 *
                   1023:                 * rearrange ordered channel to continuous per channel
                   1024:                 *
                   1025:                 *   5.1ch: L,R,C,LFE,SL,SR,... => BM0: L,R,...
                   1026:                 *                                 BM4: C,...
                   1027:                 *                                 BM6: SL,SR,...
                   1028:                 *                                 BM7: LFE,...
                   1029:                 *
                   1030:                 */
                   1031:                if (sc->sc_mch_split_buf)
1.8       jmcneill 1032:                        gcscaudio_free(sc, sc->sc_mch_split_buf,
                   1033:                            sc->sc_mch_split_size);
1.1       jmcneill 1034:
                   1035:                if ((sc->sc_mch_split_buf = gcscaudio_malloc(sc, AUMODE_PLAY,
1.8       jmcneill 1036:                    size)) == NULL)
1.1       jmcneill 1037:                        return ENOMEM;
                   1038:
                   1039:                /*
                   1040:                 * 1st and 2nd blocks are split immediately.
                   1041:                 * Other block will be split synchronous with intr.
                   1042:                 */
                   1043:                split_buffer_6ch(sc->sc_mch_split_buf, start, blksize * 2,
                   1044:                    blksize);
                   1045:
                   1046:                sc->sc_mch_split_start = start;
                   1047:                sc->sc_mch_split_size = size;
                   1048:                sc->sc_mch_split_blksize = blksize;
                   1049:                sc->sc_mch_split_off = (blksize * 2) % size;
                   1050:                sc->sc_mch_splitter = split_buffer_6ch; /* split function */
                   1051:
                   1052:                if (build_prdtables(sc, PRD_TABLE_FRONT, start, size, blksize,
                   1053:                    blksize / 3, 0))
                   1054:                        return EINVAL;
                   1055:                if (build_prdtables(sc, PRD_TABLE_CENTER, sc->sc_mch_split_buf,
                   1056:                    size, blksize, blksize / 3, blksize / 2))
                   1057:                        return EINVAL;
                   1058:                if (build_prdtables(sc, PRD_TABLE_SURR, sc->sc_mch_split_buf,
                   1059:                    size, blksize, blksize / 3, 0))
                   1060:                        return EINVAL;
                   1061:                if (build_prdtables(sc, PRD_TABLE_LFE, sc->sc_mch_split_buf,
                   1062:                    size, blksize, blksize / 3, blksize / 2 + blksize / 4))
                   1063:                        return EINVAL;
                   1064:
                   1065:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
                   1066:                    PRDADDR(PRD_TABLE_FRONT, 0));
                   1067:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM4_PRD,
                   1068:                    PRDADDR(PRD_TABLE_CENTER, 0));
                   1069:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_PRD,
                   1070:                    PRDADDR(PRD_TABLE_SURR, 0));
                   1071:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM7_PRD,
                   1072:                    PRDADDR(PRD_TABLE_LFE, 0));
                   1073:
                   1074:                /* start DMA transfer */
                   1075:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
                   1076:                    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
                   1077:                    ACC_BMx_CMD_BM_CTL_ENABLE);
                   1078:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM4_CMD,
                   1079:                    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
                   1080:                    ACC_BMx_CMD_BM_CTL_ENABLE);
                   1081:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
                   1082:                    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
                   1083:                    ACC_BMx_CMD_BM_CTL_ENABLE);
                   1084:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM7_CMD,
                   1085:                    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
                   1086:                    ACC_BMx_CMD_BM_CTL_ENABLE);
                   1087:                break;
                   1088:        }
                   1089:
                   1090:        return 0;
                   1091: }
                   1092:
                   1093: static int
                   1094: gcscaudio_trigger_input(void *addr, void *start, void *end, int blksize,
                   1095:                         void (*intr)(void *), void *arg,
                   1096:                         const audio_params_t *param)
                   1097: {
                   1098:        struct gcscaudio_softc *sc;
                   1099:        size_t size;
                   1100:
                   1101:        sc = (struct gcscaudio_softc *)addr;
                   1102:        sc->sc_rec.ch_intr = intr;
                   1103:        sc->sc_rec.ch_intr_arg = arg;
                   1104:        size = (char *)end - (char *)start;
                   1105:
                   1106:        if (build_prdtables(sc, PRD_TABLE_REC, start, size, blksize, blksize, 0))
                   1107:                return EINVAL;
                   1108:
                   1109:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM1_PRD,
                   1110:            PRDADDR(PRD_TABLE_REC, 0));
                   1111:
                   1112:        /* start transfer */
                   1113:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM1_CMD,
                   1114:            ACC_BMx_CMD_READ |
                   1115:            ACC_BMx_CMD_BYTE_ORD_EL |
                   1116:            ACC_BMx_CMD_BM_CTL_ENABLE);
                   1117:
                   1118:        return 0;
                   1119: }
                   1120:
1.8       jmcneill 1121: static void
                   1122: gcscaudio_get_locks(void *arg, kmutex_t **intr, kmutex_t **thread)
                   1123: {
                   1124:        struct gcscaudio_softc *sc;
                   1125:
                   1126:        sc = (struct gcscaudio_softc *)arg;
                   1127:
                   1128:        *intr = &sc->sc_intr_lock;
                   1129:        *thread = &sc->sc_lock;
                   1130: }
                   1131:
1.1       jmcneill 1132: static int
                   1133: gcscaudio_intr(void *arg)
                   1134: {
                   1135:        struct gcscaudio_softc *sc;
                   1136:        uint16_t intr;
                   1137:        uint8_t bmstat;
                   1138:        int nintr;
                   1139:
                   1140:        nintr = 0;
                   1141:        sc = (struct gcscaudio_softc *)arg;
1.8       jmcneill 1142:
                   1143:        mutex_spin_enter(&sc->sc_intr_lock);
                   1144:
1.1       jmcneill 1145:        intr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ACC_IRQ_STATUS);
                   1146:        if (intr == 0)
1.8       jmcneill 1147:                goto done;
1.1       jmcneill 1148:
                   1149:        /* Front output */
                   1150:        if (intr & ACC_IRQ_STATUS_BM0_IRQ_STS) {
                   1151:                bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_STATUS);
                   1152:                if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
1.12      nonaka   1153:                        aprint_normal_dev(sc->sc_dev, "BM0: Bus Master Error\n");
1.1       jmcneill 1154:                if (!(bmstat & ACC_BMx_STATUS_EOP))
1.12      nonaka   1155:                        aprint_normal_dev(sc->sc_dev, "BM0: NO End of Page?\n");
1.1       jmcneill 1156:
                   1157:                if (sc->sc_play.ch_intr) {
                   1158:                        sc->sc_play.ch_intr(sc->sc_play.ch_intr_arg);
                   1159:                        channel_splitter(sc);
                   1160:                }
                   1161:                nintr++;
                   1162:        }
                   1163:
                   1164:        /* Center output */
                   1165:        if (intr & ACC_IRQ_STATUS_BM4_IRQ_STS) {
                   1166:                bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM4_STATUS);
                   1167:                if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
1.12      nonaka   1168:                        aprint_normal_dev(sc->sc_dev, "BM4: Bus Master Error\n");
1.1       jmcneill 1169:                if (!(bmstat & ACC_BMx_STATUS_EOP))
1.12      nonaka   1170:                        aprint_normal_dev(sc->sc_dev, "BM4: NO End of Page?\n");
1.1       jmcneill 1171:
                   1172:                nintr++;
                   1173:        }
                   1174:
                   1175:        /* Surround output */
                   1176:        if (intr & ACC_IRQ_STATUS_BM6_IRQ_STS) {
                   1177:                bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_STATUS);
                   1178:                if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
1.12      nonaka   1179:                        aprint_normal_dev(sc->sc_dev, "BM6: Bus Master Error\n");
1.1       jmcneill 1180:                if (!(bmstat & ACC_BMx_STATUS_EOP))
1.12      nonaka   1181:                        aprint_normal_dev(sc->sc_dev, "BM6: NO End of Page?\n");
1.1       jmcneill 1182:
                   1183:                nintr++;
                   1184:        }
                   1185:
                   1186:        /* LowFrequencyEffect output */
                   1187:        if (intr & ACC_IRQ_STATUS_BM7_IRQ_STS) {
                   1188:                bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM7_STATUS);
                   1189:                if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
1.12      nonaka   1190:                        aprint_normal_dev(sc->sc_dev, "BM7: Bus Master Error\n");
1.1       jmcneill 1191:                if (!(bmstat & ACC_BMx_STATUS_EOP))
1.12      nonaka   1192:                        aprint_normal_dev(sc->sc_dev, "BM7: NO End of Page?\n");
1.1       jmcneill 1193:
                   1194:                nintr++;
                   1195:        }
                   1196:
                   1197:        /* record */
                   1198:        if (intr & ACC_IRQ_STATUS_BM1_IRQ_STS) {
                   1199:                bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM1_STATUS);
                   1200:                if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
1.12      nonaka   1201:                        aprint_normal_dev(sc->sc_dev, "BM1: Bus Master Error\n");
1.1       jmcneill 1202:                if (!(bmstat & ACC_BMx_STATUS_EOP))
1.12      nonaka   1203:                        aprint_normal_dev(sc->sc_dev, "BM1: NO End of Page?\n");
1.1       jmcneill 1204:
                   1205:                if (sc->sc_rec.ch_intr) {
                   1206:                        sc->sc_rec.ch_intr(sc->sc_rec.ch_intr_arg);
                   1207:                }
                   1208:                nintr++;
                   1209:        }
                   1210:
                   1211: #ifdef GCSCAUDIO_DEBUG
                   1212:        if (intr & ACC_IRQ_STATUS_IRQ_STS)
1.12      nonaka   1213:                aprint_normal_dev(sc->sc_dev, "Codec GPIO IRQ Status\n");
1.1       jmcneill 1214:        if (intr & ACC_IRQ_STATUS_WU_IRQ_STS)
1.12      nonaka   1215:                aprint_normal_dev(sc->sc_dev, "Codec GPIO Wakeup IRQ Status\n");
1.1       jmcneill 1216:        if (intr & ACC_IRQ_STATUS_BM2_IRQ_STS)
1.12      nonaka   1217:                aprint_normal_dev(sc->sc_dev, "Audio Bus Master 2 IRQ Status\n");
1.1       jmcneill 1218:        if (intr & ACC_IRQ_STATUS_BM3_IRQ_STS)
1.12      nonaka   1219:                aprint_normal_dev(sc->sc_dev, "Audio Bus Master 3 IRQ Status\n");
1.1       jmcneill 1220:        if (intr & ACC_IRQ_STATUS_BM5_IRQ_STS)
1.12      nonaka   1221:                aprint_normal_dev(sc->sc_dev, "Audio Bus Master 5 IRQ Status\n");
1.1       jmcneill 1222: #endif
                   1223:
1.8       jmcneill 1224: done:
                   1225:        mutex_spin_exit(&sc->sc_intr_lock);
                   1226:
1.1       jmcneill 1227:        return nintr ? 1 : 0;
                   1228: }
                   1229:
                   1230: static bool
1.5       dyoung   1231: gcscaudio_resume(device_t dv, const pmf_qual_t *qual)
1.1       jmcneill 1232: {
                   1233:        struct gcscaudio_softc *sc = device_private(dv);
                   1234:
                   1235:        gcscaudio_reset_codec(sc);
                   1236:        DELAY(1000);
                   1237:        (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
                   1238:
                   1239:        return true;
                   1240: }
                   1241:
                   1242: static int
                   1243: gcscaudio_allocate_dma(struct gcscaudio_softc *sc, size_t size, void **addrp,
                   1244:                        bus_dma_segment_t *seglist, int nseg, int *rsegp,
1.8       jmcneill 1245:                        bus_dmamap_t *mapp)
1.1       jmcneill 1246: {
                   1247:        int error;
                   1248:
                   1249:        if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, seglist,
1.8       jmcneill 1250:            nseg, rsegp, BUS_DMA_WAITOK)) != 0) {
1.12      nonaka   1251:                aprint_error_dev(sc->sc_dev,
1.1       jmcneill 1252:                    "unable to allocate DMA buffer, error=%d\n", error);
                   1253:                goto fail_alloc;
                   1254:        }
                   1255:
                   1256:        if ((error = bus_dmamem_map(sc->sc_dmat, seglist, nseg, size, addrp,
1.8       jmcneill 1257:            BUS_DMA_WAITOK | BUS_DMA_COHERENT)) != 0) {
1.12      nonaka   1258:                aprint_error_dev(sc->sc_dev,
1.1       jmcneill 1259:                    "unable to map DMA buffer, error=%d\n",
                   1260:                    error);
                   1261:                goto fail_map;
                   1262:        }
                   1263:
                   1264:        if ((error = bus_dmamap_create(sc->sc_dmat, size, nseg, size, 0,
1.8       jmcneill 1265:            BUS_DMA_WAITOK, mapp)) != 0) {
1.12      nonaka   1266:                aprint_error_dev(sc->sc_dev,
1.1       jmcneill 1267:                    "unable to create DMA map, error=%d\n", error);
                   1268:                goto fail_create;
                   1269:        }
                   1270:
                   1271:        if ((error = bus_dmamap_load(sc->sc_dmat, *mapp, *addrp, size, NULL,
1.8       jmcneill 1272:            BUS_DMA_WAITOK)) != 0) {
1.12      nonaka   1273:                aprint_error_dev(sc->sc_dev,
1.1       jmcneill 1274:                    "unable to load DMA map, error=%d\n", error);
                   1275:                goto fail_load;
                   1276:        }
                   1277:
                   1278:        return 0;
                   1279:
                   1280: fail_load:
                   1281:        bus_dmamap_destroy(sc->sc_dmat, *mapp);
                   1282: fail_create:
                   1283:        bus_dmamem_unmap(sc->sc_dmat, *addrp, size);
                   1284: fail_map:
                   1285:        bus_dmamem_free(sc->sc_dmat, seglist, nseg);
                   1286: fail_alloc:
                   1287:        return error;
                   1288: }

CVSweb <webmaster@jp.NetBSD.org>