[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.5

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

CVSweb <webmaster@jp.NetBSD.org>