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

Annotation of sys/dev/pci/yds.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: yds.c,v 1.28 2007/01/06 02:48:40 deraadt Exp $        */
        !             2: /*     $NetBSD: yds.c,v 1.5 2001/05/21 23:55:04 minoura Exp $  */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 2000, 2001 Kazuki Sakamoto and Minoura Makoto.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            18:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            19:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            20:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            21:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            22:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            23:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            24:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            25:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            26:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            27:  */
        !            28:
        !            29: /*
        !            30:  * Yamaha YMF724[B-F]/740[B-C]/744/754
        !            31:  *
        !            32:  * Documentation links:
        !            33:  * - ftp://ftp.alsa-project.org/pub/manuals/yamaha/
        !            34:  * - ftp://ftp.alsa-project.org/pub/manuals/yamaha/pci/
        !            35:  *
        !            36:  * TODO:
        !            37:  * - FM synth volume (difficult: mixed before ac97)
        !            38:  * - Digital in/out (SPDIF) support
        !            39:  * - Effect??
        !            40:  */
        !            41:
        !            42: #include <sys/param.h>
        !            43: #include <sys/systm.h>
        !            44: #include <sys/kernel.h>
        !            45: #include <sys/fcntl.h>
        !            46: #include <sys/malloc.h>
        !            47: #include <sys/device.h>
        !            48: #include <sys/proc.h>
        !            49: #include <sys/queue.h>
        !            50: #include <sys/fcntl.h>
        !            51:
        !            52: #include <dev/pci/pcidevs.h>
        !            53: #include <dev/pci/pcireg.h>
        !            54: #include <dev/pci/pcivar.h>
        !            55:
        !            56: #include <sys/audioio.h>
        !            57: #include <dev/audio_if.h>
        !            58: #include <dev/midi_if.h>
        !            59: #include <dev/mulaw.h>
        !            60: #include <dev/auconv.h>
        !            61: #include <dev/ic/ac97.h>
        !            62: #include <dev/ic/mpuvar.h>
        !            63:
        !            64: #include <machine/bus.h>
        !            65: #include <machine/intr.h>
        !            66:
        !            67: #include <dev/pci/ydsreg.h>
        !            68: #include <dev/pci/ydsvar.h>
        !            69:
        !            70: /* Debug */
        !            71: #undef YDS_USE_REC_SLOT
        !            72: #define YDS_USE_P44
        !            73:
        !            74: #ifdef AUDIO_DEBUG
        !            75: # define DPRINTF(x)    if (ydsdebug) printf x
        !            76: # define DPRINTFN(n,x) if (ydsdebug>(n)) printf x
        !            77: int    ydsdebug = 0;
        !            78: #else
        !            79: # define DPRINTF(x)
        !            80: # define DPRINTFN(n,x)
        !            81: #endif
        !            82: #ifdef YDS_USE_REC_SLOT
        !            83: # define YDS_INPUT_SLOT 0      /* REC slot = ADC + loopbacks */
        !            84: #else
        !            85: # define YDS_INPUT_SLOT 1      /* ADC slot */
        !            86: #endif
        !            87:
        !            88: static int ac97_id2;
        !            89:
        !            90: int    yds_match(struct device *, void *, void *);
        !            91: void   yds_attach(struct device *, struct device *, void *);
        !            92: int    yds_intr(void *);
        !            93:
        !            94: static void nswaph(u_int32_t *p, int wcount);
        !            95:
        !            96: #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
        !            97: #define KERNADDR(p) ((void *)((p)->addr))
        !            98:
        !            99: int    yds_allocmem(struct yds_softc *, size_t, size_t,
        !           100:            struct yds_dma *);
        !           101: int    yds_freemem(struct yds_softc *, struct yds_dma *);
        !           102:
        !           103: #ifndef AUDIO_DEBUG
        !           104: #define YWRITE1(sc, r, x) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))
        !           105: #define YWRITE2(sc, r, x) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))
        !           106: #define YWRITE4(sc, r, x) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))
        !           107: #define YREAD1(sc, r) bus_space_read_1((sc)->memt, (sc)->memh, (r))
        !           108: #define YREAD2(sc, r) bus_space_read_2((sc)->memt, (sc)->memh, (r))
        !           109: #define YREAD4(sc, r) bus_space_read_4((sc)->memt, (sc)->memh, (r))
        !           110: #else
        !           111:
        !           112: u_int16_t YREAD2(struct yds_softc *sc,bus_size_t r);
        !           113: u_int32_t YREAD4(struct yds_softc *sc,bus_size_t r);
        !           114: void YWRITE1(struct yds_softc *sc,bus_size_t r,u_int8_t x);
        !           115: void YWRITE2(struct yds_softc *sc,bus_size_t r,u_int16_t x);
        !           116: void YWRITE4(struct yds_softc *sc,bus_size_t r,u_int32_t x);
        !           117:
        !           118: u_int16_t YREAD2(struct yds_softc *sc,bus_size_t r)
        !           119: {
        !           120:   DPRINTFN(5, (" YREAD2(0x%lX)\n",(unsigned long)r));
        !           121:   return bus_space_read_2(sc->memt,sc->memh,r);
        !           122: }
        !           123: u_int32_t YREAD4(struct yds_softc *sc,bus_size_t r)
        !           124: {
        !           125:   DPRINTFN(5, (" YREAD4(0x%lX)\n",(unsigned long)r));
        !           126:   return bus_space_read_4(sc->memt,sc->memh,r);
        !           127: }
        !           128: void YWRITE1(struct yds_softc *sc,bus_size_t r,u_int8_t x)
        !           129: {
        !           130:   DPRINTFN(5, (" YWRITE1(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x));
        !           131:   bus_space_write_1(sc->memt,sc->memh,r,x);
        !           132: }
        !           133: void YWRITE2(struct yds_softc *sc,bus_size_t r,u_int16_t x)
        !           134: {
        !           135:   DPRINTFN(5, (" YWRITE2(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x));
        !           136:   bus_space_write_2(sc->memt,sc->memh,r,x);
        !           137: }
        !           138: void YWRITE4(struct yds_softc *sc,bus_size_t r,u_int32_t x)
        !           139: {
        !           140:   DPRINTFN(5, (" YWRITE4(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x));
        !           141:   bus_space_write_4(sc->memt,sc->memh,r,x);
        !           142: }
        !           143: #endif
        !           144:
        !           145: #define        YWRITEREGION4(sc, r, x, c)      \
        !           146:        bus_space_write_region_4((sc)->memt, (sc)->memh, (r), (x), (c) / 4)
        !           147:
        !           148: struct cfattach yds_ca = {
        !           149:        sizeof(struct yds_softc), yds_match, yds_attach
        !           150: };
        !           151:
        !           152: struct cfdriver yds_cd = {
        !           153:        NULL, "yds", DV_DULL
        !           154: };
        !           155:
        !           156: int    yds_open(void *, int);
        !           157: void   yds_close(void *);
        !           158: int    yds_query_encoding(void *, struct audio_encoding *);
        !           159: int    yds_set_params(void *, int, int,
        !           160:            struct audio_params *, struct audio_params *);
        !           161: int    yds_round_blocksize(void *, int);
        !           162: int    yds_trigger_output(void *, void *, void *, int, void (*)(void *),
        !           163:            void *, struct audio_params *);
        !           164: int    yds_trigger_input(void *, void *, void *, int, void (*)(void *),
        !           165:            void *, struct audio_params *);
        !           166: int    yds_halt_output(void *);
        !           167: int    yds_halt_input(void *);
        !           168: int    yds_getdev(void *, struct audio_device *);
        !           169: int    yds_mixer_set_port(void *, mixer_ctrl_t *);
        !           170: int    yds_mixer_get_port(void *, mixer_ctrl_t *);
        !           171: void   *yds_malloc(void *, int, size_t, int, int);
        !           172: void   yds_free(void *, void *, int);
        !           173: size_t yds_round_buffersize(void *, int, size_t);
        !           174: paddr_t        yds_mappage(void *, void *, off_t, int);
        !           175: int    yds_get_props(void *);
        !           176: int    yds_query_devinfo(void *addr, mixer_devinfo_t *dip);
        !           177:
        !           178: int     yds_attach_codec(void *sc, struct ac97_codec_if *);
        !           179: int    yds_read_codec(void *sc, u_int8_t a, u_int16_t *d);
        !           180: int    yds_write_codec(void *sc, u_int8_t a, u_int16_t d);
        !           181: void    yds_reset_codec(void *sc);
        !           182: int     yds_get_portnum_by_name(struct yds_softc *, char *, char *,
        !           183:            char *);
        !           184:
        !           185: static u_int yds_get_dstype(int);
        !           186: static int yds_download_mcode(struct yds_softc *);
        !           187: static int yds_allocate_slots(struct yds_softc *);
        !           188: static void yds_configure_legacy(struct yds_softc *arg);
        !           189: static void yds_enable_dsp(struct yds_softc *);
        !           190: static int yds_disable_dsp(struct yds_softc *);
        !           191: static int yds_ready_codec(struct yds_codec_softc *);
        !           192: static int yds_halt(struct yds_softc *);
        !           193: static u_int32_t yds_get_lpfq(u_int);
        !           194: static u_int32_t yds_get_lpfk(u_int);
        !           195: static struct yds_dma *yds_find_dma(struct yds_softc *, void *);
        !           196:
        !           197: void yds_powerhook(int, void *);
        !           198: int    yds_init(void *sc);
        !           199: void   yds_attachhook(void *);
        !           200:
        !           201: #ifdef AUDIO_DEBUG
        !           202: static void yds_dump_play_slot(struct yds_softc *, int);
        !           203: #define        YDS_DUMP_PLAY_SLOT(n,sc,bank) \
        !           204:        if (ydsdebug > (n)) yds_dump_play_slot(sc, bank)
        !           205: #else
        !           206: #define        YDS_DUMP_PLAY_SLOT(n,sc,bank)
        !           207: #endif /* AUDIO_DEBUG */
        !           208:
        !           209: static struct audio_hw_if yds_hw_if = {
        !           210:        yds_open,
        !           211:        yds_close,
        !           212:        NULL,
        !           213:        yds_query_encoding,
        !           214:        yds_set_params,
        !           215:        yds_round_blocksize,
        !           216:        NULL,
        !           217:        NULL,
        !           218:        NULL,
        !           219:        NULL,
        !           220:        NULL,
        !           221:        yds_halt_output,
        !           222:        yds_halt_input,
        !           223:        NULL,
        !           224:        yds_getdev,
        !           225:        NULL,
        !           226:        yds_mixer_set_port,
        !           227:        yds_mixer_get_port,
        !           228:        yds_query_devinfo,
        !           229:        yds_malloc,
        !           230:        yds_free,
        !           231:        yds_round_buffersize,
        !           232:        yds_mappage,
        !           233:        yds_get_props,
        !           234:        yds_trigger_output,
        !           235:        yds_trigger_input
        !           236: };
        !           237:
        !           238: struct audio_device yds_device = {
        !           239:        "Yamaha DS-1",
        !           240:        "",
        !           241:        "yds"
        !           242: };
        !           243:
        !           244: const static struct {
        !           245:        u_int   id;
        !           246:        u_int   flags;
        !           247: #define YDS_CAP_MCODE_1                        0x0001
        !           248: #define YDS_CAP_MCODE_1E               0x0002
        !           249: #define YDS_CAP_LEGACY_SELECTABLE      0x0004
        !           250: #define YDS_CAP_LEGACY_FLEXIBLE                0x0008
        !           251: #define YDS_CAP_HAS_P44                        0x0010
        !           252: #define YDS_CAP_LEGACY_SMOD_DISABLE    0x1000
        !           253: } yds_chip_capability_list[] = {
        !           254:        { PCI_PRODUCT_YAMAHA_YMF724,
        !           255:          YDS_CAP_MCODE_1|YDS_CAP_LEGACY_SELECTABLE },
        !           256:        /* 740[C] has only 32 slots.  But anyway we use only 2 */
        !           257:        { PCI_PRODUCT_YAMAHA_YMF740,
        !           258:          YDS_CAP_MCODE_1|YDS_CAP_LEGACY_SELECTABLE },  /* XXX NOT TESTED */
        !           259:        { PCI_PRODUCT_YAMAHA_YMF740C,
        !           260:          YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_SELECTABLE },
        !           261:        { PCI_PRODUCT_YAMAHA_YMF724F,
        !           262:          YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_SELECTABLE },
        !           263:        { PCI_PRODUCT_YAMAHA_YMF744,
        !           264:          YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_FLEXIBLE },
        !           265:        { PCI_PRODUCT_YAMAHA_YMF754,
        !           266:          YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_FLEXIBLE|YDS_CAP_HAS_P44 },
        !           267:        /* How about 734/737/738?? */
        !           268:        { 0, 0 }
        !           269: };
        !           270: #ifdef AUDIO_DEBUG
        !           271: #define YDS_CAP_BITS   "\020\005P44\004LEGFLEX\003LEGSEL\002MCODE1E\001MCODE1"
        !           272: #endif
        !           273:
        !           274: #ifdef AUDIO_DEBUG
        !           275: static void
        !           276: yds_dump_play_slot(sc, bank)
        !           277:        struct yds_softc *sc;
        !           278:        int bank;
        !           279: {
        !           280:        int i, j;
        !           281:        u_int32_t *p;
        !           282:        u_int32_t num;
        !           283:        struct yds_dma *dma;
        !           284:
        !           285:        for (i = 0; i < N_PLAY_SLOTS; i++) {
        !           286:                printf("pbankp[%d] = %p,", i*2, sc->pbankp[i*2]);
        !           287:                printf("pbankp[%d] = %p\n", i*2+1, sc->pbankp[i*2+1]);
        !           288:        }
        !           289:
        !           290:        p = (u_int32_t*)sc->ptbl;
        !           291:        for (i = 0; i < N_PLAY_SLOTS+1; i++) {
        !           292:                printf("ptbl + %d:0x%x\n", i, *p);
        !           293:                p++;
        !           294:        }
        !           295:
        !           296:        num = *(u_int32_t*)sc->ptbl;
        !           297:        printf("num = %d\n", num);
        !           298:
        !           299:        for (i = 0; i < num; i++) {
        !           300:
        !           301:                p = (u_int32_t *)sc->pbankp[i];
        !           302:
        !           303:                dma = yds_find_dma(sc,(void *)p);
        !           304:
        !           305:                for (j = 0; j < sizeof(struct play_slot_ctrl_bank) /
        !           306:                    sizeof(u_int32_t); j++) {
        !           307:                        printf("    0x%02x: 0x%08x\n",
        !           308:                               (unsigned) (j * sizeof(u_int32_t)),
        !           309:                               (unsigned) *p++);
        !           310:                }
        !           311:                /*
        !           312:                p = (u_int32_t *)sc->pbankp[i*2 + 1];
        !           313:                printf("  pbankp[%d] : %p\n", i*2 + 1, p);
        !           314:                for (j = 0; j < sizeof(struct play_slot_ctrl_bank) /
        !           315:                    sizeof(u_int32_t); j++) {
        !           316:                        printf("    0x%02x: 0x%08x\n",
        !           317:                                j * sizeof(u_int32_t), *p++);
        !           318:                                delay(1);
        !           319:                }
        !           320:                */
        !           321:        }
        !           322: }
        !           323: #endif /* AUDIO_DEBUG */
        !           324:
        !           325: static u_int
        !           326: yds_get_dstype(id)
        !           327:        int id;
        !           328: {
        !           329:        int i;
        !           330:
        !           331:        for (i = 0; yds_chip_capability_list[i].id; i++) {
        !           332:                if (PCI_PRODUCT(id) == yds_chip_capability_list[i].id)
        !           333:                        return yds_chip_capability_list[i].flags;
        !           334:        }
        !           335:
        !           336:        return -1;
        !           337: }
        !           338:
        !           339: static void
        !           340: nswaph(u_int32_t *p, int wcount)
        !           341: {
        !           342:        for (; wcount; wcount -=4) {
        !           343:                *p = ntohl(*p);
        !           344:                p++;
        !           345:        }
        !           346: }
        !           347:
        !           348: static int
        !           349: yds_download_mcode(sc)
        !           350:        struct yds_softc *sc;
        !           351: {
        !           352:        u_int ctrl;
        !           353:        const u_int32_t *p;
        !           354:        size_t size;
        !           355:        u_char *buf;
        !           356:        size_t buflen;
        !           357:        int error;
        !           358:        struct yds_firmware *yf;
        !           359:
        !           360:        error = loadfirmware("yds", &buf, &buflen);
        !           361:        if (error)
        !           362:                return 1;
        !           363:        yf = (struct yds_firmware *)buf;
        !           364:
        !           365:        if (sc->sc_flags & YDS_CAP_MCODE_1) {
        !           366:                p = (u_int32_t *)&yf->data[ntohl(yf->dsplen)];
        !           367:                size = ntohl(yf->ds1len);
        !           368:        } else if (sc->sc_flags & YDS_CAP_MCODE_1E) {
        !           369:                p = (u_int32_t *)&yf->data[ntohl(yf->dsplen) + ntohl(yf->ds1len)];
        !           370:                size = ntohl(yf->ds1elen);
        !           371:        } else {
        !           372:                free(buf, M_DEVBUF);
        !           373:                return 1;       /* unknown */
        !           374:        }
        !           375:
        !           376:        if (size > buflen) {
        !           377:                printf("%s: old firmware file, update please\n",
        !           378:                    sc->sc_dev.dv_xname);
        !           379:                free(buf, M_DEVBUF);
        !           380:                return 1;
        !           381:        }
        !           382:
        !           383:        if (yds_disable_dsp(sc)) {
        !           384:                free(buf, M_DEVBUF);
        !           385:                return 1;
        !           386:        }
        !           387:
        !           388:        /* Software reset */
        !           389:         YWRITE4(sc, YDS_MODE, YDS_MODE_RESET);
        !           390:         YWRITE4(sc, YDS_MODE, 0);
        !           391:
        !           392:         YWRITE4(sc, YDS_MAPOF_REC, 0);
        !           393:         YWRITE4(sc, YDS_MAPOF_EFFECT, 0);
        !           394:         YWRITE4(sc, YDS_PLAY_CTRLBASE, 0);
        !           395:         YWRITE4(sc, YDS_REC_CTRLBASE, 0);
        !           396:         YWRITE4(sc, YDS_EFFECT_CTRLBASE, 0);
        !           397:         YWRITE4(sc, YDS_WORK_BASE, 0);
        !           398:
        !           399:         ctrl = YREAD2(sc, YDS_GLOBAL_CONTROL);
        !           400:         YWRITE2(sc, YDS_GLOBAL_CONTROL, ctrl & ~0x0007);
        !           401:
        !           402:        /* Download DSP microcode. */
        !           403:        nswaph((u_int32_t *)&yf->data[0], ntohl(yf->dsplen));
        !           404:        YWRITEREGION4(sc, YDS_DSP_INSTRAM, (u_int32_t *)&yf->data[0],
        !           405:            ntohl(yf->dsplen));
        !           406:
        !           407:        /* Download CONTROL microcode. */
        !           408:        nswaph((u_int32_t *)p, size);
        !           409:        YWRITEREGION4(sc, YDS_CTRL_INSTRAM, p, size);
        !           410:
        !           411:        yds_enable_dsp(sc);
        !           412:        delay(10*1000);         /* neccesary on my 724F (??) */
        !           413:
        !           414:        free(buf, M_DEVBUF);
        !           415:        return 0;
        !           416: }
        !           417:
        !           418: static int
        !           419: yds_allocate_slots(sc)
        !           420:        struct yds_softc *sc;
        !           421: {
        !           422:        size_t pcs, rcs, ecs, ws, memsize;
        !           423:        void *mp;
        !           424:        u_int32_t da;           /* DMA address */
        !           425:        char *va;               /* KVA */
        !           426:        off_t cb;
        !           427:        int i;
        !           428:        struct yds_dma *p;
        !           429:
        !           430:        /* Alloc DSP Control Data */
        !           431:        pcs = YREAD4(sc, YDS_PLAY_CTRLSIZE) * sizeof(u_int32_t);
        !           432:        rcs = YREAD4(sc, YDS_REC_CTRLSIZE) * sizeof(u_int32_t);
        !           433:        ecs = YREAD4(sc, YDS_EFFECT_CTRLSIZE) * sizeof(u_int32_t);
        !           434:        ws = WORK_SIZE;
        !           435:        YWRITE4(sc, YDS_WORK_SIZE, ws / sizeof(u_int32_t));
        !           436:
        !           437:        DPRINTF(("play control size : %d\n", (unsigned int)pcs));
        !           438:        DPRINTF(("rec control size : %d\n", (unsigned int)rcs));
        !           439:        DPRINTF(("eff control size : %d\n", (unsigned int)ecs));
        !           440:        DPRINTF(("work size : %d\n", (unsigned int)ws));
        !           441: #ifdef DIAGNOSTIC
        !           442:        if (pcs != sizeof(struct play_slot_ctrl_bank)) {
        !           443:                printf("%s: invalid play slot ctrldata %d != %d\n",
        !           444:                       sc->sc_dev.dv_xname, (unsigned int)pcs,
        !           445:                       (unsigned int)sizeof(struct play_slot_ctrl_bank));
        !           446:        }
        !           447:        if (rcs != sizeof(struct rec_slot_ctrl_bank)) {
        !           448:                printf("%s: invalid rec slot ctrldata %d != %d\n",
        !           449:                       sc->sc_dev.dv_xname, (unsigned int)rcs,
        !           450:                       (unsigned int)sizeof(struct rec_slot_ctrl_bank));
        !           451:         }
        !           452: #endif
        !           453:
        !           454:        memsize = N_PLAY_SLOTS*N_PLAY_SLOT_CTRL_BANK*pcs +
        !           455:                  N_REC_SLOT_CTRL*N_REC_SLOT_CTRL_BANK*rcs + ws;
        !           456:        memsize += (N_PLAY_SLOTS+1)*sizeof(u_int32_t);
        !           457:
        !           458:        p = &sc->sc_ctrldata;
        !           459:        i = yds_allocmem(sc, memsize, 16, p);
        !           460:        if (i) {
        !           461:                printf("%s: couldn't alloc/map DSP DMA buffer, reason %d\n",
        !           462:                       sc->sc_dev.dv_xname, i);
        !           463:                free(p, M_DEVBUF);
        !           464:                return 1;
        !           465:        }
        !           466:        mp = KERNADDR(p);
        !           467:        da = DMAADDR(p);
        !           468:
        !           469:        DPRINTF(("mp:%p, DMA addr:%p\n",
        !           470:                 mp, (void *) sc->sc_ctrldata.map->dm_segs[0].ds_addr));
        !           471:
        !           472:        bzero(mp, memsize);
        !           473:
        !           474:        /* Work space */
        !           475:         cb = 0;
        !           476:        va = (u_int8_t*)mp;
        !           477:        YWRITE4(sc, YDS_WORK_BASE, da + cb);
        !           478:         cb += ws;
        !           479:
        !           480:        /* Play control data table */
        !           481:         sc->ptbl = (u_int32_t *)(va + cb);
        !           482:        sc->ptbloff = cb;
        !           483:         YWRITE4(sc, YDS_PLAY_CTRLBASE, da + cb);
        !           484:         cb += (N_PLAY_SLOT_CTRL + 1) * sizeof(u_int32_t);
        !           485:
        !           486:        /* Record slot control data */
        !           487:         sc->rbank = (struct rec_slot_ctrl_bank *)(va + cb);
        !           488:         YWRITE4(sc, YDS_REC_CTRLBASE, da + cb);
        !           489:        sc->rbankoff = cb;
        !           490:         cb += N_REC_SLOT_CTRL * N_REC_SLOT_CTRL_BANK * rcs;
        !           491:
        !           492: #if 0
        !           493:        /* Effect slot control data -- unused */
        !           494:         YWRITE4(sc, YDS_EFFECT_CTRLBASE, da + cb);
        !           495:         cb += N_EFFECT_SLOT_CTRL * N_EFFECT_SLOT_CTRL_BANK * ecs;
        !           496: #endif
        !           497:
        !           498:        /* Play slot control data */
        !           499:         sc->pbankoff = da + cb;
        !           500:         for (i=0; i<N_PLAY_SLOT_CTRL; i++) {
        !           501:                sc->pbankp[i*2] = (struct play_slot_ctrl_bank *)(va + cb);
        !           502:                *(sc->ptbl + i+1) = da + cb;
        !           503:                 cb += pcs;
        !           504:
        !           505:                 sc->pbankp[i*2+1] = (struct play_slot_ctrl_bank *)(va + cb);
        !           506:                 cb += pcs;
        !           507:         }
        !           508:        /* Sync play control data table */
        !           509:        bus_dmamap_sync(sc->sc_dmatag, p->map,
        !           510:                        sc->ptbloff, (N_PLAY_SLOT_CTRL+1) * sizeof(u_int32_t),
        !           511:                        BUS_DMASYNC_PREWRITE);
        !           512:
        !           513:        return 0;
        !           514: }
        !           515:
        !           516: static void
        !           517: yds_enable_dsp(sc)
        !           518:        struct yds_softc *sc;
        !           519: {
        !           520:        YWRITE4(sc, YDS_CONFIG, YDS_DSP_SETUP);
        !           521: }
        !           522:
        !           523: static int
        !           524: yds_disable_dsp(sc)
        !           525:        struct yds_softc *sc;
        !           526: {
        !           527:        int to;
        !           528:        u_int32_t data;
        !           529:
        !           530:        data = YREAD4(sc, YDS_CONFIG);
        !           531:        if (data)
        !           532:                YWRITE4(sc, YDS_CONFIG, YDS_DSP_DISABLE);
        !           533:
        !           534:        for (to = 0; to < YDS_WORK_TIMEOUT; to++) {
        !           535:                if ((YREAD4(sc, YDS_STATUS) & YDS_STAT_WORK) == 0)
        !           536:                        return 0;
        !           537:                delay(1);
        !           538:        }
        !           539:
        !           540:        return 1;
        !           541: }
        !           542:
        !           543: int
        !           544: yds_match(parent, match, aux)
        !           545:        struct device *parent;
        !           546:        void *match;
        !           547:        void *aux;
        !           548: {
        !           549:        struct pci_attach_args *pa = (struct pci_attach_args *) aux;
        !           550:
        !           551:        switch (PCI_VENDOR(pa->pa_id)) {
        !           552:        case PCI_VENDOR_YAMAHA:
        !           553:                switch (PCI_PRODUCT(pa->pa_id)) {
        !           554:                case PCI_PRODUCT_YAMAHA_YMF724:
        !           555:                case PCI_PRODUCT_YAMAHA_YMF740:
        !           556:                case PCI_PRODUCT_YAMAHA_YMF740C:
        !           557:                case PCI_PRODUCT_YAMAHA_YMF724F:
        !           558:                case PCI_PRODUCT_YAMAHA_YMF744:
        !           559:                case PCI_PRODUCT_YAMAHA_YMF754:
        !           560:                /* 734, 737, 738?? */
        !           561:                        return (1);
        !           562:                }
        !           563:                break;
        !           564:        }
        !           565:
        !           566:        return (0);
        !           567: }
        !           568:
        !           569: /*
        !           570:  * This routine is called after all the ISA devices are configured,
        !           571:  * to avoid conflict.
        !           572:  */
        !           573: static void
        !           574: yds_configure_legacy (sc)
        !           575:        struct yds_softc *sc;
        !           576: #define FLEXIBLE       (sc->sc_flags & YDS_CAP_LEGACY_FLEXIBLE)
        !           577: #define SELECTABLE     (sc->sc_flags & YDS_CAP_LEGACY_SELECTABLE)
        !           578: {
        !           579:        pcireg_t reg;
        !           580:        struct device *dev;
        !           581:        int i;
        !           582:        bus_addr_t opl_addrs[] = {0x388, 0x398, 0x3A0, 0x3A8};
        !           583:        bus_addr_t mpu_addrs[] = {0x330, 0x300, 0x332, 0x334};
        !           584:
        !           585:        if (!FLEXIBLE && !SELECTABLE)
        !           586:                return;
        !           587:
        !           588:        reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY);
        !           589:        reg &= ~0x8133c03f;     /* these bits are out of interest */
        !           590:        reg |= (YDS_PCI_EX_LEGACY_IMOD | YDS_PCI_LEGACY_FMEN |
        !           591:                YDS_PCI_LEGACY_MEN /*| YDS_PCI_LEGACY_MIEN*/);
        !           592:        if (sc->sc_flags & YDS_CAP_LEGACY_SMOD_DISABLE)
        !           593:                reg |= YDS_PCI_EX_LEGACY_SMOD_DISABLE;
        !           594:        if (FLEXIBLE) {
        !           595:                pci_conf_write(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY, reg);
        !           596:                delay(100*1000);
        !           597:        }
        !           598:
        !           599:        /* Look for OPL */
        !           600:        dev = 0;
        !           601:        for (i = 0; i < sizeof(opl_addrs) / sizeof (bus_addr_t); i++) {
        !           602:                if (SELECTABLE) {
        !           603:                        pci_conf_write(sc->sc_pc, sc->sc_pcitag,
        !           604:                                       YDS_PCI_LEGACY, reg | (i << (0+16)));
        !           605:                        delay(100*1000);        /* wait 100ms */
        !           606:                } else
        !           607:                        pci_conf_write(sc->sc_pc, sc->sc_pcitag,
        !           608:                                       YDS_PCI_FM_BA, opl_addrs[i]);
        !           609:                if (bus_space_map(sc->sc_opl_iot,
        !           610:                                  opl_addrs[i], 4, 0, &sc->sc_opl_ioh) == 0) {
        !           611:                        struct audio_attach_args aa;
        !           612:
        !           613:                        aa.type = AUDIODEV_TYPE_OPL;
        !           614:                        aa.hwif = aa.hdl = NULL;
        !           615:                        dev = config_found(&sc->sc_dev, &aa, audioprint);
        !           616:                        if (dev == 0)
        !           617:                                bus_space_unmap(sc->sc_opl_iot,
        !           618:                                                sc->sc_opl_ioh, 4);
        !           619:                        else {
        !           620:                                if (SELECTABLE)
        !           621:                                        reg |= (i << (0+16));
        !           622:                                break;
        !           623:                        }
        !           624:                }
        !           625:        }
        !           626:        if (dev == 0) {
        !           627:                reg &= ~YDS_PCI_LEGACY_FMEN;
        !           628:                pci_conf_write(sc->sc_pc, sc->sc_pcitag,
        !           629:                               YDS_PCI_LEGACY, reg);
        !           630:        } else {
        !           631:                /* Max. volume */
        !           632:                YWRITE4(sc, YDS_LEGACY_OUT_VOLUME, 0x3fff3fff);
        !           633:                YWRITE4(sc, YDS_LEGACY_REC_VOLUME, 0x3fff3fff);
        !           634:        }
        !           635:
        !           636:        /* Look for MPU */
        !           637:        dev = 0;
        !           638:        for (i = 0; i < sizeof(mpu_addrs) / sizeof (bus_addr_t); i++) {
        !           639:                if (SELECTABLE)
        !           640:                        pci_conf_write(sc->sc_pc, sc->sc_pcitag,
        !           641:                                       YDS_PCI_LEGACY, reg | (i << (4+16)));
        !           642:                else
        !           643:                        pci_conf_write(sc->sc_pc, sc->sc_pcitag,
        !           644:                                       YDS_PCI_MPU_BA, mpu_addrs[i]);
        !           645:                if (bus_space_map(sc->sc_mpu_iot,
        !           646:                                  mpu_addrs[i], 2, 0, &sc->sc_mpu_ioh) == 0) {
        !           647:                        struct audio_attach_args aa;
        !           648:
        !           649:                        aa.type = AUDIODEV_TYPE_MPU;
        !           650:                        aa.hwif = aa.hdl = NULL;
        !           651:                        dev = config_found(&sc->sc_dev, &aa, audioprint);
        !           652:                        if (dev == 0)
        !           653:                                bus_space_unmap(sc->sc_mpu_iot,
        !           654:                                                sc->sc_mpu_ioh, 2);
        !           655:                        else {
        !           656:                                if (SELECTABLE)
        !           657:                                        reg |= (i << (4+16));
        !           658:                                break;
        !           659:                        }
        !           660:                }
        !           661:        }
        !           662:        if (dev == 0) {
        !           663:                reg &= ~(YDS_PCI_LEGACY_MEN | YDS_PCI_LEGACY_MIEN);
        !           664:                pci_conf_write(sc->sc_pc, sc->sc_pcitag,
        !           665:                               YDS_PCI_LEGACY, reg);
        !           666:        }
        !           667:        sc->sc_mpu = dev;
        !           668: }
        !           669: #undef FLEXIBLE
        !           670: #undef SELECTABLE
        !           671:
        !           672: void
        !           673: yds_attach(parent, self, aux)
        !           674:        struct device *parent;
        !           675:        struct device *self;
        !           676:        void *aux;
        !           677: {
        !           678:        struct yds_softc *sc = (struct yds_softc *)self;
        !           679:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
        !           680:        pci_chipset_tag_t pc = pa->pa_pc;
        !           681:        char const *intrstr;
        !           682:        pci_intr_handle_t ih;
        !           683:        bus_size_t size;
        !           684:        pcireg_t reg;
        !           685:        int i;
        !           686:
        !           687:        /* Map register to memory */
        !           688:        if (pci_mapreg_map(pa, YDS_PCI_MBA, PCI_MAPREG_TYPE_MEM, 0,
        !           689:            &sc->memt, &sc->memh, NULL, &size, 0)) {
        !           690:                printf("%s: can't map memory space\n", sc->sc_dev.dv_xname);
        !           691:                return;
        !           692:        }
        !           693:
        !           694:        /* Map and establish the interrupt. */
        !           695:        if (pci_intr_map(pa, &ih)) {
        !           696:                printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
        !           697:                bus_space_unmap(sc->memt, sc->memh, size);
        !           698:                return;
        !           699:        }
        !           700:        intrstr = pci_intr_string(pc, ih);
        !           701:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, yds_intr, sc,
        !           702:            self->dv_xname);
        !           703:        if (sc->sc_ih == NULL) {
        !           704:                printf("%s: couldn't establish interrupt",
        !           705:                    sc->sc_dev.dv_xname);
        !           706:                if (intrstr != NULL)
        !           707:                        printf(" at %s", intrstr);
        !           708:                printf("\n");
        !           709:                bus_space_unmap(sc->memt, sc->memh, size);
        !           710:                return;
        !           711:        }
        !           712:        printf(": %s\n", intrstr);
        !           713:
        !           714:        sc->sc_dmatag = pa->pa_dmat;
        !           715:        sc->sc_pc = pc;
        !           716:        sc->sc_pcitag = pa->pa_tag;
        !           717:        sc->sc_id = pa->pa_id;
        !           718:        sc->sc_revision = PCI_REVISION(pa->pa_class);
        !           719:        sc->sc_flags = yds_get_dstype(sc->sc_id);
        !           720:        if (sc->sc_dev.dv_cfdata->cf_flags & YDS_CAP_LEGACY_SMOD_DISABLE)
        !           721:                sc->sc_flags |= YDS_CAP_LEGACY_SMOD_DISABLE;
        !           722: #ifdef AUDIO_DEBUG
        !           723:        if (ydsdebug)
        !           724:                printf("%s: chip has %b\n", sc->sc_dev.dv_xname,
        !           725:                        YDS_CAP_BITS, sc->sc_flags);
        !           726: #endif
        !           727:
        !           728:        /* Disable legacy mode */
        !           729:        reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_LEGACY);
        !           730:        pci_conf_write(pc, pa->pa_tag, YDS_PCI_LEGACY,
        !           731:                       reg & YDS_PCI_LEGACY_LAD);
        !           732:
        !           733:        /* Mute all volumes */
        !           734:        for (i = 0x80; i < 0xc0; i += 2)
        !           735:                YWRITE2(sc, i, 0);
        !           736:
        !           737:        sc->sc_legacy_iot = pa->pa_iot;
        !           738:        mountroothook_establish(yds_attachhook, sc);
        !           739: }
        !           740:
        !           741: void
        !           742: yds_attachhook(void *xsc)
        !           743: {
        !           744:        struct yds_softc *sc = xsc;
        !           745:        struct yds_codec_softc *codec;
        !           746:        mixer_ctrl_t ctl;
        !           747:        int r, i;
        !           748:
        !           749:        /* Initialize the device */
        !           750:        if (yds_init(sc) == -1)
        !           751:                return;
        !           752:
        !           753:        /*
        !           754:         * Attach ac97 codec
        !           755:         */
        !           756:        for (i = 0; i < 2; i++) {
        !           757:                static struct {
        !           758:                        int data;
        !           759:                        int addr;
        !           760:                } statregs[] = {
        !           761:                        {AC97_STAT_DATA1, AC97_STAT_ADDR1},
        !           762:                        {AC97_STAT_DATA2, AC97_STAT_ADDR2},
        !           763:                };
        !           764:
        !           765:                if (i == 1 && ac97_id2 == -1)
        !           766:                        break;          /* secondary ac97 not available */
        !           767:
        !           768:                codec = &sc->sc_codec[i];
        !           769:                memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev));
        !           770:                codec->sc = sc;
        !           771:                codec->id = i == 1 ? ac97_id2 : 0;
        !           772:                codec->status_data = statregs[i].data;
        !           773:                codec->status_addr = statregs[i].addr;
        !           774:                codec->host_if.arg = codec;
        !           775:                codec->host_if.attach = yds_attach_codec;
        !           776:                codec->host_if.read = yds_read_codec;
        !           777:                codec->host_if.write = yds_write_codec;
        !           778:                codec->host_if.reset = yds_reset_codec;
        !           779:
        !           780:                if ((r = ac97_attach(&codec->host_if)) != 0) {
        !           781:                        printf("%s: can't attach codec (error 0x%X)\n",
        !           782:                                sc->sc_dev.dv_xname, r);
        !           783:                        return;
        !           784:                }
        !           785:        }
        !           786:
        !           787:        /* Just enable the DAC and master volumes by default */
        !           788:        ctl.type = AUDIO_MIXER_ENUM;
        !           789:        ctl.un.ord = 0;  /* off */
        !           790:        ctl.dev = yds_get_portnum_by_name(sc, AudioCoutputs,
        !           791:               AudioNmaster, AudioNmute);
        !           792:        yds_mixer_set_port(sc, &ctl);
        !           793:        ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs,
        !           794:               AudioNdac, AudioNmute);
        !           795:        yds_mixer_set_port(sc, &ctl);
        !           796:        ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs,
        !           797:               AudioNcd, AudioNmute);
        !           798:        yds_mixer_set_port(sc, &ctl);
        !           799:        ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord,
        !           800:               AudioNvolume, AudioNmute);
        !           801:        yds_mixer_set_port(sc, &ctl);
        !           802:
        !           803:        ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord,
        !           804:               AudioNsource, NULL);
        !           805:        ctl.type = AUDIO_MIXER_ENUM;
        !           806:        ctl.un.ord = 0;
        !           807:        yds_mixer_set_port(sc, &ctl);
        !           808:
        !           809:        /* Set a reasonable default volume */
        !           810:        ctl.type = AUDIO_MIXER_VALUE;
        !           811:        ctl.un.value.num_channels = 2;
        !           812:        ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
        !           813:        ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
        !           814:
        !           815:        ctl.dev = sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name(
        !           816:                sc->sc_codec[0].codec_if, AudioCoutputs, AudioNmaster, NULL);
        !           817:        yds_mixer_set_port(sc, &ctl);
        !           818:
        !           819:        audio_attach_mi(&yds_hw_if, sc, &sc->sc_dev);
        !           820:
        !           821:        /* Watch for power changes */
        !           822:        sc->suspend = PWR_RESUME;
        !           823:        sc->powerhook = powerhook_establish(yds_powerhook, sc);
        !           824:
        !           825:        yds_configure_legacy(sc);
        !           826: }
        !           827:
        !           828: int
        !           829: yds_attach_codec(sc_, codec_if)
        !           830:        void *sc_;
        !           831:        struct ac97_codec_if *codec_if;
        !           832: {
        !           833:        struct yds_codec_softc *sc = sc_;
        !           834:
        !           835:        sc->codec_if = codec_if;
        !           836:        return 0;
        !           837: }
        !           838:
        !           839: static int
        !           840: yds_ready_codec(sc)
        !           841:        struct yds_codec_softc *sc;
        !           842: {
        !           843:        int to;
        !           844:
        !           845:        for (to = 0; to < AC97_TIMEOUT; to++) {
        !           846:                if ((YREAD2(sc->sc, sc->status_addr) & AC97_BUSY) == 0)
        !           847:                        return 0;
        !           848:                delay(1);
        !           849:        }
        !           850:
        !           851:        return 1;
        !           852: }
        !           853:
        !           854: int
        !           855: yds_read_codec(sc_, reg, data)
        !           856:        void *sc_;
        !           857:        u_int8_t reg;
        !           858:        u_int16_t *data;
        !           859: {
        !           860:        struct yds_codec_softc *sc = sc_;
        !           861:
        !           862:        YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_READ | AC97_ID(sc->id) | reg);
        !           863:
        !           864:        if (yds_ready_codec(sc)) {
        !           865:                printf("%s: yds_read_codec timeout\n",
        !           866:                       sc->sc->sc_dev.dv_xname);
        !           867:                return EIO;
        !           868:        }
        !           869:
        !           870:        if (PCI_PRODUCT(sc->sc->sc_id) == PCI_PRODUCT_YAMAHA_YMF744 &&
        !           871:            sc->sc->sc_revision < 2) {
        !           872:                int i;
        !           873:
        !           874:                for (i = 0; i < 600; i++)
        !           875:                        YREAD2(sc->sc, sc->status_data);
        !           876:        }
        !           877:        *data = YREAD2(sc->sc, sc->status_data);
        !           878:
        !           879:        return 0;
        !           880: }
        !           881:
        !           882: int
        !           883: yds_write_codec(sc_, reg, data)
        !           884:        void *sc_;
        !           885:        u_int8_t reg;
        !           886:        u_int16_t data;
        !           887: {
        !           888:        struct yds_codec_softc *sc = sc_;
        !           889:
        !           890:        YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_WRITE | AC97_ID(sc->id) | reg);
        !           891:        YWRITE2(sc->sc, AC97_CMD_DATA, data);
        !           892:
        !           893:        if (yds_ready_codec(sc)) {
        !           894:                printf("%s: yds_write_codec timeout\n",
        !           895:                        sc->sc->sc_dev.dv_xname);
        !           896:                return EIO;
        !           897:        }
        !           898:
        !           899:        return 0;
        !           900: }
        !           901:
        !           902: /*
        !           903:  * XXX: Must handle the secondary differntly!!
        !           904:  */
        !           905: void
        !           906: yds_reset_codec(sc_)
        !           907:        void *sc_;
        !           908: {
        !           909:        struct yds_codec_softc *codec = sc_;
        !           910:        struct yds_softc *sc = codec->sc;
        !           911:        pcireg_t reg;
        !           912:
        !           913:        /* reset AC97 codec */
        !           914:        reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_DSCTRL);
        !           915:        if (reg & 0x03) {
        !           916:                pci_conf_write(sc->sc_pc, sc->sc_pcitag,
        !           917:                               YDS_PCI_DSCTRL, reg & ~0x03);
        !           918:                pci_conf_write(sc->sc_pc, sc->sc_pcitag,
        !           919:                               YDS_PCI_DSCTRL, reg | 0x03);
        !           920:                pci_conf_write(sc->sc_pc, sc->sc_pcitag,
        !           921:                               YDS_PCI_DSCTRL, reg & ~0x03);
        !           922:                delay(50000);
        !           923:        }
        !           924:
        !           925:        yds_ready_codec(sc_);
        !           926: }
        !           927:
        !           928: int
        !           929: yds_intr(p)
        !           930:        void *p;
        !           931: {
        !           932:        struct yds_softc *sc = p;
        !           933:        u_int status;
        !           934:
        !           935:        status = YREAD4(sc, YDS_STATUS);
        !           936:        DPRINTFN(1, ("yds_intr: status=%08x\n", status));
        !           937:        if ((status & (YDS_STAT_INT|YDS_STAT_TINT)) == 0) {
        !           938: #if 0
        !           939:                if (sc->sc_mpu)
        !           940:                        return mpu_intr(sc->sc_mpu);
        !           941: #endif
        !           942:                return 0;
        !           943:        }
        !           944:
        !           945:        if (status & YDS_STAT_TINT) {
        !           946:                YWRITE4(sc, YDS_STATUS, YDS_STAT_TINT);
        !           947:                printf ("yds_intr: timeout!\n");
        !           948:        }
        !           949:
        !           950:        if (status & YDS_STAT_INT) {
        !           951:                int nbank = (YREAD4(sc, YDS_CONTROL_SELECT) == 0);
        !           952:
        !           953:                /* Clear interrupt flag */
        !           954:                YWRITE4(sc, YDS_STATUS, YDS_STAT_INT);
        !           955:
        !           956:                /* Buffer for the next frame is always ready. */
        !           957:                YWRITE4(sc, YDS_MODE, YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV2);
        !           958:
        !           959:                if (sc->sc_play.intr) {
        !           960:                        u_int dma, cpu, blk, len;
        !           961:
        !           962:                        /* Sync play slot control data */
        !           963:                        bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
        !           964:                                        sc->pbankoff,
        !           965:                                        sizeof(struct play_slot_ctrl_bank)*
        !           966:                                            (*sc->ptbl)*
        !           967:                                            N_PLAY_SLOT_CTRL_BANK,
        !           968:                                        BUS_DMASYNC_POSTWRITE|
        !           969:                                        BUS_DMASYNC_POSTREAD);
        !           970:                        dma = sc->pbankp[nbank]->pgstart * sc->sc_play.factor;
        !           971:                        cpu = sc->sc_play.offset;
        !           972:                        blk = sc->sc_play.blksize;
        !           973:                        len = sc->sc_play.length;
        !           974:
        !           975:                        if (((dma > cpu) && (dma - cpu > blk * 2)) ||
        !           976:                            ((cpu > dma) && (dma + len - cpu > blk * 2))) {
        !           977:                                /* We can fill the next block */
        !           978:                                /* Sync ring buffer for previous write */
        !           979:                                bus_dmamap_sync(sc->sc_dmatag,
        !           980:                                                sc->sc_play.dma->map,
        !           981:                                                cpu, blk,
        !           982:                                                BUS_DMASYNC_POSTWRITE);
        !           983:                                sc->sc_play.intr(sc->sc_play.intr_arg);
        !           984:                                sc->sc_play.offset += blk;
        !           985:                                if (sc->sc_play.offset >= len) {
        !           986:                                        sc->sc_play.offset -= len;
        !           987: #ifdef DIAGNOSTIC
        !           988:                                        if (sc->sc_play.offset != 0)
        !           989:                                                printf ("Audio ringbuffer botch\n");
        !           990: #endif
        !           991:                                }
        !           992:                                /* Sync ring buffer for next write */
        !           993:                                bus_dmamap_sync(sc->sc_dmatag,
        !           994:                                                sc->sc_play.dma->map,
        !           995:                                                cpu, blk,
        !           996:                                                BUS_DMASYNC_PREWRITE);
        !           997:                        }
        !           998:                }
        !           999:                if (sc->sc_rec.intr) {
        !          1000:                        u_int dma, cpu, blk, len;
        !          1001:
        !          1002:                        /* Sync rec slot control data */
        !          1003:                        bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
        !          1004:                                        sc->rbankoff,
        !          1005:                                        sizeof(struct rec_slot_ctrl_bank)*
        !          1006:                                            N_REC_SLOT_CTRL*
        !          1007:                                            N_REC_SLOT_CTRL_BANK,
        !          1008:                                        BUS_DMASYNC_POSTWRITE|
        !          1009:                                        BUS_DMASYNC_POSTREAD);
        !          1010:                        dma = sc->rbank[YDS_INPUT_SLOT*2 + nbank].pgstartadr;
        !          1011:                        cpu = sc->sc_rec.offset;
        !          1012:                        blk = sc->sc_rec.blksize;
        !          1013:                        len = sc->sc_rec.length;
        !          1014:
        !          1015:                        if (((dma > cpu) && (dma - cpu > blk * 2)) ||
        !          1016:                            ((cpu > dma) && (dma + len - cpu > blk * 2))) {
        !          1017:                                /* We can drain the current block */
        !          1018:                                /* Sync ring buffer first */
        !          1019:                                bus_dmamap_sync(sc->sc_dmatag,
        !          1020:                                                sc->sc_rec.dma->map,
        !          1021:                                                cpu, blk,
        !          1022:                                                BUS_DMASYNC_POSTREAD);
        !          1023:                                sc->sc_rec.intr(sc->sc_rec.intr_arg);
        !          1024:                                sc->sc_rec.offset += blk;
        !          1025:                                if (sc->sc_rec.offset >= len) {
        !          1026:                                        sc->sc_rec.offset -= len;
        !          1027: #ifdef DIAGNOSTIC
        !          1028:                                        if (sc->sc_rec.offset != 0)
        !          1029:                                                printf ("Audio ringbuffer botch\n");
        !          1030: #endif
        !          1031:                                }
        !          1032:                                /* Sync ring buffer for next read */
        !          1033:                                bus_dmamap_sync(sc->sc_dmatag,
        !          1034:                                                sc->sc_rec.dma->map,
        !          1035:                                                cpu, blk,
        !          1036:                                                BUS_DMASYNC_PREREAD);
        !          1037:                        }
        !          1038:                }
        !          1039:        }
        !          1040:
        !          1041:        return 1;
        !          1042: }
        !          1043:
        !          1044: int
        !          1045: yds_allocmem(sc, size, align, p)
        !          1046:        struct yds_softc *sc;
        !          1047:        size_t size;
        !          1048:        size_t align;
        !          1049:        struct yds_dma *p;
        !          1050: {
        !          1051:        int error;
        !          1052:
        !          1053:        p->size = size;
        !          1054:        error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
        !          1055:                                 p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
        !          1056:                                 &p->nsegs, BUS_DMA_NOWAIT);
        !          1057:        if (error)
        !          1058:                return (error);
        !          1059:
        !          1060:        error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
        !          1061:                               &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
        !          1062:        if (error)
        !          1063:                goto free;
        !          1064:
        !          1065:        error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
        !          1066:                                  0, BUS_DMA_NOWAIT, &p->map);
        !          1067:        if (error)
        !          1068:                goto unmap;
        !          1069:
        !          1070:        error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
        !          1071:                                BUS_DMA_NOWAIT);
        !          1072:        if (error)
        !          1073:                goto destroy;
        !          1074:        return (0);
        !          1075:
        !          1076: destroy:
        !          1077:        bus_dmamap_destroy(sc->sc_dmatag, p->map);
        !          1078: unmap:
        !          1079:        bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
        !          1080: free:
        !          1081:        bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
        !          1082:        return (error);
        !          1083: }
        !          1084:
        !          1085: int
        !          1086: yds_freemem(sc, p)
        !          1087:        struct yds_softc *sc;
        !          1088:        struct yds_dma *p;
        !          1089: {
        !          1090:        bus_dmamap_unload(sc->sc_dmatag, p->map);
        !          1091:        bus_dmamap_destroy(sc->sc_dmatag, p->map);
        !          1092:        bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
        !          1093:        bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
        !          1094:        return 0;
        !          1095: }
        !          1096:
        !          1097: int
        !          1098: yds_open(addr, flags)
        !          1099:        void *addr;
        !          1100:        int flags;
        !          1101: {
        !          1102:        struct yds_softc *sc = addr;
        !          1103:        int mode;
        !          1104:
        !          1105:        /* Select bank 0. */
        !          1106:        YWRITE4(sc, YDS_CONTROL_SELECT, 0);
        !          1107:
        !          1108:        /* Start the DSP operation. */
        !          1109:        mode = YREAD4(sc, YDS_MODE);
        !          1110:        mode |= YDS_MODE_ACTV;
        !          1111:        mode &= ~YDS_MODE_ACTV2;
        !          1112:        YWRITE4(sc, YDS_MODE, mode);
        !          1113:
        !          1114:        return 0;
        !          1115: }
        !          1116:
        !          1117: /*
        !          1118:  * Close function is called at splaudio().
        !          1119:  */
        !          1120: void
        !          1121: yds_close(addr)
        !          1122:        void *addr;
        !          1123: {
        !          1124:        struct yds_softc *sc = addr;
        !          1125:
        !          1126:        yds_halt_output(sc);
        !          1127:        yds_halt_input(sc);
        !          1128:        yds_halt(sc);
        !          1129: }
        !          1130:
        !          1131: int
        !          1132: yds_query_encoding(addr, fp)
        !          1133:        void *addr;
        !          1134:        struct audio_encoding *fp;
        !          1135: {
        !          1136:        switch (fp->index) {
        !          1137:        case 0:
        !          1138:                strlcpy(fp->name, AudioEulinear, sizeof fp->name);
        !          1139:                fp->encoding = AUDIO_ENCODING_ULINEAR;
        !          1140:                fp->precision = 8;
        !          1141:                fp->flags = 0;
        !          1142:                return (0);
        !          1143:        case 1:
        !          1144:                strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
        !          1145:                fp->encoding = AUDIO_ENCODING_ULAW;
        !          1146:                fp->precision = 8;
        !          1147:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          1148:                return (0);
        !          1149:        case 2:
        !          1150:                strlcpy(fp->name, AudioEalaw, sizeof fp->name);
        !          1151:                fp->encoding = AUDIO_ENCODING_ALAW;
        !          1152:                fp->precision = 8;
        !          1153:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          1154:                return (0);
        !          1155:        case 3:
        !          1156:                strlcpy(fp->name, AudioEslinear, sizeof fp->name);
        !          1157:                fp->encoding = AUDIO_ENCODING_SLINEAR;
        !          1158:                fp->precision = 8;
        !          1159:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          1160:                return (0);
        !          1161:        case 4:
        !          1162:                strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
        !          1163:                fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
        !          1164:                fp->precision = 16;
        !          1165:                fp->flags = 0;
        !          1166:                return (0);
        !          1167:        case 5:
        !          1168:                strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
        !          1169:                fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
        !          1170:                fp->precision = 16;
        !          1171:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          1172:                return (0);
        !          1173:        case 6:
        !          1174:                strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
        !          1175:                fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
        !          1176:                fp->precision = 16;
        !          1177:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          1178:                return (0);
        !          1179:        case 7:
        !          1180:                strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
        !          1181:                fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
        !          1182:                fp->precision = 16;
        !          1183:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          1184:                return (0);
        !          1185:        default:
        !          1186:                return (EINVAL);
        !          1187:        }
        !          1188: }
        !          1189:
        !          1190: int
        !          1191: yds_set_params(addr, setmode, usemode, play, rec)
        !          1192:        void *addr;
        !          1193:        int setmode, usemode;
        !          1194:        struct audio_params *play, *rec;
        !          1195: {
        !          1196:        struct audio_params *p;
        !          1197:        int mode;
        !          1198:
        !          1199:        for (mode = AUMODE_RECORD; mode != -1;
        !          1200:             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
        !          1201:                if ((setmode & mode) == 0)
        !          1202:                        continue;
        !          1203:
        !          1204:                p = mode == AUMODE_PLAY ? play : rec;
        !          1205:
        !          1206:                if (p->sample_rate < 4000 || p->sample_rate > 48000 ||
        !          1207:                    (p->precision != 8 && p->precision != 16) ||
        !          1208:                    (p->channels != 1 && p->channels != 2))
        !          1209:                        return (EINVAL);
        !          1210:
        !          1211:                p->factor = 1;
        !          1212:                p->sw_code = 0;
        !          1213:                switch (p->encoding) {
        !          1214:                case AUDIO_ENCODING_SLINEAR_BE:
        !          1215:                        if (p->precision == 16)
        !          1216:                                p->sw_code = swap_bytes;
        !          1217:                        else
        !          1218:                                p->sw_code = change_sign8;
        !          1219:                        break;
        !          1220:                case AUDIO_ENCODING_SLINEAR_LE:
        !          1221:                        if (p->precision != 16)
        !          1222:                                p->sw_code = change_sign8;
        !          1223:                        break;
        !          1224:                case AUDIO_ENCODING_ULINEAR_BE:
        !          1225:                        if (p->precision == 16) {
        !          1226:                                if (mode == AUMODE_PLAY)
        !          1227:                                        p->sw_code = swap_bytes_change_sign16_le;
        !          1228:                                else
        !          1229:                                        p->sw_code = change_sign16_swap_bytes_le;
        !          1230:                        }
        !          1231:                        break;
        !          1232:                case AUDIO_ENCODING_ULINEAR_LE:
        !          1233:                        if (p->precision == 16)
        !          1234:                                p->sw_code = change_sign16_le;
        !          1235:                        break;
        !          1236:                case AUDIO_ENCODING_ULAW:
        !          1237:                        if (mode == AUMODE_PLAY) {
        !          1238:                                p->factor = 2;
        !          1239:                                p->precision = 16;
        !          1240:                                p->sw_code = mulaw_to_slinear16_le;
        !          1241:                        } else
        !          1242:                                p->sw_code = ulinear8_to_mulaw;
        !          1243:                        break;
        !          1244:                case AUDIO_ENCODING_ALAW:
        !          1245:                        if (mode == AUMODE_PLAY) {
        !          1246:                                p->factor = 2;
        !          1247:                                p->precision = 16;
        !          1248:                                p->sw_code = alaw_to_slinear16_le;
        !          1249:                        } else
        !          1250:                                p->sw_code = ulinear8_to_alaw;
        !          1251:                        break;
        !          1252:                default:
        !          1253:                        return (EINVAL);
        !          1254:                }
        !          1255:        }
        !          1256:
        !          1257:        return 0;
        !          1258: }
        !          1259:
        !          1260: int
        !          1261: yds_round_blocksize(addr, blk)
        !          1262:        void *addr;
        !          1263:        int blk;
        !          1264: {
        !          1265:        /*
        !          1266:         * Block size must be bigger than a frame.
        !          1267:         * That is 1024bytes at most, i.e. for 48000Hz, 16bit, 2ch.
        !          1268:         */
        !          1269:        if (blk < 1024)
        !          1270:                blk = 1024;
        !          1271:
        !          1272:        return blk & ~4;
        !          1273: }
        !          1274:
        !          1275: static u_int32_t
        !          1276: yds_get_lpfq(sample_rate)
        !          1277:        u_int sample_rate;
        !          1278: {
        !          1279:        int i;
        !          1280:        static struct lpfqt {
        !          1281:                u_int rate;
        !          1282:                u_int32_t lpfq;
        !          1283:        } lpfqt[] = {
        !          1284:                {8000,  0x32020000},
        !          1285:                {11025, 0x31770000},
        !          1286:                {16000, 0x31390000},
        !          1287:                {22050, 0x31c90000},
        !          1288:                {32000, 0x33d00000},
        !          1289:                {48000, 0x40000000},
        !          1290:                {0, 0}
        !          1291:        };
        !          1292:
        !          1293:        if (sample_rate == 44100)               /* for P44 slot? */
        !          1294:                return 0x370A0000;
        !          1295:
        !          1296:        for (i = 0; lpfqt[i].rate != 0; i++)
        !          1297:                if (sample_rate <= lpfqt[i].rate)
        !          1298:                        break;
        !          1299:
        !          1300:        return lpfqt[i].lpfq;
        !          1301: }
        !          1302:
        !          1303: static u_int32_t
        !          1304: yds_get_lpfk(sample_rate)
        !          1305:        u_int sample_rate;
        !          1306: {
        !          1307:        int i;
        !          1308:        static struct lpfkt {
        !          1309:                u_int rate;
        !          1310:                u_int32_t lpfk;
        !          1311:        } lpfkt[] = {
        !          1312:                {8000,  0x18b20000},
        !          1313:                {11025, 0x20930000},
        !          1314:                {16000, 0x2b9a0000},
        !          1315:                {22050, 0x35a10000},
        !          1316:                {32000, 0x3eaa0000},
        !          1317:                {48000, 0x40000000},
        !          1318:                {0, 0}
        !          1319:        };
        !          1320:
        !          1321:        if (sample_rate == 44100)               /* for P44 slot? */
        !          1322:                return 0x46460000;
        !          1323:
        !          1324:        for (i = 0; lpfkt[i].rate != 0; i++)
        !          1325:                if (sample_rate <= lpfkt[i].rate)
        !          1326:                        break;
        !          1327:
        !          1328:        return lpfkt[i].lpfk;
        !          1329: }
        !          1330:
        !          1331: int
        !          1332: yds_trigger_output(addr, start, end, blksize, intr, arg, param)
        !          1333:        void *addr;
        !          1334:        void *start, *end;
        !          1335:        int blksize;
        !          1336:        void (*intr)(void *);
        !          1337:        void *arg;
        !          1338:        struct audio_params *param;
        !          1339: #define P44            (sc->sc_flags & YDS_CAP_HAS_P44)
        !          1340: {
        !          1341:        struct yds_softc *sc = addr;
        !          1342:        struct yds_dma *p;
        !          1343:        struct play_slot_ctrl_bank *psb;
        !          1344:        const u_int gain = 0x40000000;
        !          1345:        bus_addr_t s;
        !          1346:        size_t l;
        !          1347:        int i;
        !          1348:        int p44, channels;
        !          1349:
        !          1350: #ifdef DIAGNOSTIC
        !          1351:        if (sc->sc_play.intr)
        !          1352:                panic("yds_trigger_output: already running");
        !          1353: #endif
        !          1354:
        !          1355:        sc->sc_play.intr = intr;
        !          1356:        sc->sc_play.intr_arg = arg;
        !          1357:        sc->sc_play.offset = 0;
        !          1358:        sc->sc_play.blksize = blksize;
        !          1359:
        !          1360:        DPRINTFN(1, ("yds_trigger_output: sc=%p start=%p end=%p "
        !          1361:            "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
        !          1362:
        !          1363:        p = yds_find_dma(sc, start);
        !          1364:        if (!p) {
        !          1365:                printf("yds_trigger_output: bad addr %p\n", start);
        !          1366:                return (EINVAL);
        !          1367:        }
        !          1368:        sc->sc_play.dma = p;
        !          1369:
        !          1370: #ifdef DIAGNOSTIC
        !          1371:        {
        !          1372:                u_int32_t ctrlsize;
        !          1373:                if ((ctrlsize = YREAD4(sc, YDS_PLAY_CTRLSIZE)) !=
        !          1374:                    sizeof(struct play_slot_ctrl_bank) / sizeof(u_int32_t))
        !          1375:                        panic("%s: invalid play slot ctrldata %d %d",
        !          1376:                              sc->sc_dev.dv_xname, ctrlsize,
        !          1377:                              sizeof(struct play_slot_ctrl_bank));
        !          1378:        }
        !          1379: #endif
        !          1380:
        !          1381: #ifdef YDS_USE_P44
        !          1382:        /* The document says the P44 SRC supports only stereo, 16bit PCM. */
        !          1383:        if (P44)
        !          1384:                p44 = ((param->sample_rate == 44100) &&
        !          1385:                       (param->channels == 2) &&
        !          1386:                       (param->precision == 16));
        !          1387:        else
        !          1388: #endif
        !          1389:                p44 = 0;
        !          1390:        channels = p44 ? 1 : param->channels;
        !          1391:
        !          1392:        s = DMAADDR(p);
        !          1393:        l = ((char *)end - (char *)start);
        !          1394:        sc->sc_play.length = l;
        !          1395:
        !          1396:        *sc->ptbl = channels;   /* Num of play */
        !          1397:
        !          1398:        sc->sc_play.factor = 1;
        !          1399:        if (param->channels == 2)
        !          1400:                sc->sc_play.factor *= 2;
        !          1401:        if (param->precision != 8)
        !          1402:                sc->sc_play.factor *= 2;
        !          1403:        l /= sc->sc_play.factor;
        !          1404:
        !          1405:        psb = sc->pbankp[0];
        !          1406:        memset(psb, 0, sizeof(*psb));
        !          1407:        psb->format = ((channels == 2 ? PSLT_FORMAT_STEREO : 0) |
        !          1408:                       (param->precision == 8 ? PSLT_FORMAT_8BIT : 0) |
        !          1409:                       (p44 ? PSLT_FORMAT_SRC441 : 0));
        !          1410:        psb->pgbase = s;
        !          1411:        psb->pgloopend = l;
        !          1412:        if (!p44) {
        !          1413:                psb->pgdeltaend = (param->sample_rate * 65536 / 48000) << 12;
        !          1414:                psb->lpfkend = yds_get_lpfk(param->sample_rate);
        !          1415:                psb->eggainend = gain;
        !          1416:                psb->lpfq = yds_get_lpfq(param->sample_rate);
        !          1417:                psb->pgdelta = psb->pgdeltaend;
        !          1418:                psb->lpfk = yds_get_lpfk(param->sample_rate);
        !          1419:                psb->eggain = gain;
        !          1420:        }
        !          1421:
        !          1422:        for (i = 0; i < channels; i++) {
        !          1423:                /* i == 0: left or mono, i == 1: right */
        !          1424:                psb = sc->pbankp[i*2];
        !          1425:                if (i)
        !          1426:                        /* copy from left */
        !          1427:                        *psb = *(sc->pbankp[0]);
        !          1428:                if (channels == 2) {
        !          1429:                        /* stereo */
        !          1430:                        if (i == 0) {
        !          1431:                                psb->lchgain = psb->lchgainend = gain;
        !          1432:                        } else {
        !          1433:                                psb->lchgain = psb->lchgainend = 0;
        !          1434:                                psb->rchgain = psb->rchgainend = gain;
        !          1435:                                psb->format |= PSLT_FORMAT_RCH;
        !          1436:                        }
        !          1437:                } else if (!p44) {
        !          1438:                        /* mono */
        !          1439:                        psb->lchgain = psb->rchgain = gain;
        !          1440:                        psb->lchgainend = psb->rchgainend = gain;
        !          1441:                }
        !          1442:                /* copy to the other bank */
        !          1443:                *(sc->pbankp[i*2+1]) = *psb;
        !          1444:        }
        !          1445:
        !          1446:        YDS_DUMP_PLAY_SLOT(5, sc, 0);
        !          1447:        YDS_DUMP_PLAY_SLOT(5, sc, 1);
        !          1448:
        !          1449:        if (p44)
        !          1450:                YWRITE4(sc, YDS_P44_OUT_VOLUME, 0x3fff3fff);
        !          1451:        else
        !          1452:                YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0x3fff3fff);
        !          1453:
        !          1454:        /* Now the play slot for the next frame is set up!! */
        !          1455:        /* Sync play slot control data for both directions */
        !          1456:        bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
        !          1457:                        sc->ptbloff,
        !          1458:                        sizeof(struct play_slot_ctrl_bank) *
        !          1459:                            channels * N_PLAY_SLOT_CTRL_BANK,
        !          1460:                        BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
        !          1461:        /* Sync ring buffer */
        !          1462:        bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize,
        !          1463:                        BUS_DMASYNC_PREWRITE);
        !          1464:        /* HERE WE GO!! */
        !          1465:        YWRITE4(sc, YDS_MODE,
        !          1466:                YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2);
        !          1467:
        !          1468:        return 0;
        !          1469: }
        !          1470: #undef P44
        !          1471:
        !          1472: int
        !          1473: yds_trigger_input(addr, start, end, blksize, intr, arg, param)
        !          1474:        void *addr;
        !          1475:        void *start, *end;
        !          1476:        int blksize;
        !          1477:        void (*intr)(void *);
        !          1478:        void *arg;
        !          1479:        struct audio_params *param;
        !          1480: {
        !          1481:        struct yds_softc *sc = addr;
        !          1482:        struct yds_dma *p;
        !          1483:        u_int srate, format;
        !          1484:        struct rec_slot_ctrl_bank *rsb;
        !          1485:        bus_addr_t s;
        !          1486:        size_t l;
        !          1487:
        !          1488: #ifdef DIAGNOSTIC
        !          1489:        if (sc->sc_rec.intr)
        !          1490:                panic("yds_trigger_input: already running");
        !          1491: #endif
        !          1492:        sc->sc_rec.intr = intr;
        !          1493:        sc->sc_rec.intr_arg = arg;
        !          1494:        sc->sc_rec.offset = 0;
        !          1495:        sc->sc_rec.blksize = blksize;
        !          1496:
        !          1497:        DPRINTFN(1, ("yds_trigger_input: "
        !          1498:            "sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
        !          1499:            addr, start, end, blksize, intr, arg));
        !          1500:        DPRINTFN(1, (" parameters: rate=%lu, precision=%u, channels=%u\n",
        !          1501:            param->sample_rate, param->precision, param->channels));
        !          1502:
        !          1503:        p = yds_find_dma(sc, start);
        !          1504:        if (!p) {
        !          1505:                printf("yds_trigger_input: bad addr %p\n", start);
        !          1506:                return (EINVAL);
        !          1507:        }
        !          1508:        sc->sc_rec.dma = p;
        !          1509:
        !          1510:        s = DMAADDR(p);
        !          1511:        l = ((char *)end - (char *)start);
        !          1512:        sc->sc_rec.length = l;
        !          1513:
        !          1514:        sc->sc_rec.factor = 1;
        !          1515:        if (param->channels == 2)
        !          1516:                sc->sc_rec.factor *= 2;
        !          1517:        if (param->precision != 8)
        !          1518:                sc->sc_rec.factor *= 2;
        !          1519:
        !          1520:        rsb = &sc->rbank[0];
        !          1521:        memset(rsb, 0, sizeof(*rsb));
        !          1522:        rsb->pgbase = s;
        !          1523:        rsb->pgloopendadr = l;
        !          1524:        /* Seems all 4 banks must be set up... */
        !          1525:        sc->rbank[1] = *rsb;
        !          1526:        sc->rbank[2] = *rsb;
        !          1527:        sc->rbank[3] = *rsb;
        !          1528:
        !          1529:        YWRITE4(sc, YDS_ADC_IN_VOLUME, 0x3fff3fff);
        !          1530:        YWRITE4(sc, YDS_REC_IN_VOLUME, 0x3fff3fff);
        !          1531:        srate = 48000 * 4096 / param->sample_rate - 1;
        !          1532:        format = ((param->precision == 8 ? YDS_FORMAT_8BIT : 0) |
        !          1533:                  (param->channels == 2 ? YDS_FORMAT_STEREO : 0));
        !          1534:        DPRINTF(("srate=%d, format=%08x\n", srate, format));
        !          1535: #ifdef YDS_USE_REC_SLOT
        !          1536:        YWRITE4(sc, YDS_DAC_REC_VOLUME, 0x3fff3fff);
        !          1537:        YWRITE4(sc, YDS_P44_REC_VOLUME, 0x3fff3fff);
        !          1538:        YWRITE4(sc, YDS_MAPOF_REC, YDS_RECSLOT_VALID);
        !          1539:        YWRITE4(sc, YDS_REC_SAMPLE_RATE, srate);
        !          1540:        YWRITE4(sc, YDS_REC_FORMAT, format);
        !          1541: #else
        !          1542:        YWRITE4(sc, YDS_MAPOF_REC, YDS_ADCSLOT_VALID);
        !          1543:        YWRITE4(sc, YDS_ADC_SAMPLE_RATE, srate);
        !          1544:        YWRITE4(sc, YDS_ADC_FORMAT, format);
        !          1545: #endif
        !          1546:        /* Now the rec slot for the next frame is set up!! */
        !          1547:        /* Sync record slot control data */
        !          1548:        bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
        !          1549:                        sc->rbankoff,
        !          1550:                        sizeof(struct rec_slot_ctrl_bank)*
        !          1551:                            N_REC_SLOT_CTRL*
        !          1552:                            N_REC_SLOT_CTRL_BANK,
        !          1553:                        BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
        !          1554:        /* Sync ring buffer */
        !          1555:        bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize,
        !          1556:                        BUS_DMASYNC_PREREAD);
        !          1557:        /* HERE WE GO!! */
        !          1558:        YWRITE4(sc, YDS_MODE,
        !          1559:                YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2);
        !          1560:
        !          1561:        return 0;
        !          1562: }
        !          1563:
        !          1564: static int
        !          1565: yds_halt(sc)
        !          1566:        struct yds_softc *sc;
        !          1567: {
        !          1568:        u_int32_t mode;
        !          1569:
        !          1570:        /* Stop the DSP operation. */
        !          1571:        mode = YREAD4(sc, YDS_MODE);
        !          1572:        YWRITE4(sc, YDS_MODE, mode & ~(YDS_MODE_ACTV|YDS_MODE_ACTV2));
        !          1573:
        !          1574:        /* Paranoia...  mute all */
        !          1575:        YWRITE4(sc, YDS_P44_OUT_VOLUME, 0);
        !          1576:        YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0);
        !          1577:        YWRITE4(sc, YDS_ADC_IN_VOLUME, 0);
        !          1578:        YWRITE4(sc, YDS_REC_IN_VOLUME, 0);
        !          1579:        YWRITE4(sc, YDS_DAC_REC_VOLUME, 0);
        !          1580:        YWRITE4(sc, YDS_P44_REC_VOLUME, 0);
        !          1581:
        !          1582:        return 0;
        !          1583: }
        !          1584:
        !          1585: int
        !          1586: yds_halt_output(addr)
        !          1587:        void *addr;
        !          1588: {
        !          1589:        struct yds_softc *sc = addr;
        !          1590:
        !          1591:        DPRINTF(("yds: yds_halt_output\n"));
        !          1592:        if (sc->sc_play.intr) {
        !          1593:                sc->sc_play.intr = 0;
        !          1594:                /* Sync play slot control data */
        !          1595:                bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
        !          1596:                                sc->pbankoff,
        !          1597:                                sizeof(struct play_slot_ctrl_bank)*
        !          1598:                                    (*sc->ptbl)*N_PLAY_SLOT_CTRL_BANK,
        !          1599:                                BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD);
        !          1600:                /* Stop the play slot operation */
        !          1601:                sc->pbankp[0]->status =
        !          1602:                sc->pbankp[1]->status =
        !          1603:                sc->pbankp[2]->status =
        !          1604:                sc->pbankp[3]->status = 1;
        !          1605:                /* Sync ring buffer */
        !          1606:                bus_dmamap_sync(sc->sc_dmatag, sc->sc_play.dma->map,
        !          1607:                                0, sc->sc_play.length, BUS_DMASYNC_POSTWRITE);
        !          1608:        }
        !          1609:
        !          1610:        return 0;
        !          1611: }
        !          1612:
        !          1613: int
        !          1614: yds_halt_input(addr)
        !          1615:        void *addr;
        !          1616: {
        !          1617:        struct yds_softc *sc = addr;
        !          1618:
        !          1619:        DPRINTF(("yds: yds_halt_input\n"));
        !          1620:        if (sc->sc_rec.intr) {
        !          1621:                /* Stop the rec slot operation */
        !          1622:                YWRITE4(sc, YDS_MAPOF_REC, 0);
        !          1623:                sc->sc_rec.intr = 0;
        !          1624:                /* Sync rec slot control data */
        !          1625:                bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
        !          1626:                                sc->rbankoff,
        !          1627:                                sizeof(struct rec_slot_ctrl_bank)*
        !          1628:                                    N_REC_SLOT_CTRL*N_REC_SLOT_CTRL_BANK,
        !          1629:                                BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD);
        !          1630:                /* Sync ring buffer */
        !          1631:                bus_dmamap_sync(sc->sc_dmatag, sc->sc_rec.dma->map,
        !          1632:                                0, sc->sc_rec.length, BUS_DMASYNC_POSTREAD);
        !          1633:        }
        !          1634:        sc->sc_rec.intr = NULL;
        !          1635:
        !          1636:        return 0;
        !          1637: }
        !          1638:
        !          1639: int
        !          1640: yds_getdev(addr, retp)
        !          1641:        void *addr;
        !          1642:        struct audio_device *retp;
        !          1643: {
        !          1644:        *retp = yds_device;
        !          1645:
        !          1646:        return 0;
        !          1647: }
        !          1648:
        !          1649: int
        !          1650: yds_mixer_set_port(addr, cp)
        !          1651:        void *addr;
        !          1652:        mixer_ctrl_t *cp;
        !          1653: {
        !          1654:        struct yds_softc *sc = addr;
        !          1655:
        !          1656:        return (sc->sc_codec[0].codec_if->vtbl->mixer_set_port(
        !          1657:            sc->sc_codec[0].codec_if, cp));
        !          1658: }
        !          1659:
        !          1660: int
        !          1661: yds_mixer_get_port(addr, cp)
        !          1662:        void *addr;
        !          1663:        mixer_ctrl_t *cp;
        !          1664: {
        !          1665:        struct yds_softc *sc = addr;
        !          1666:
        !          1667:        return (sc->sc_codec[0].codec_if->vtbl->mixer_get_port(
        !          1668:            sc->sc_codec[0].codec_if, cp));
        !          1669: }
        !          1670:
        !          1671: int
        !          1672: yds_query_devinfo(addr, dip)
        !          1673:        void *addr;
        !          1674:        mixer_devinfo_t *dip;
        !          1675: {
        !          1676:        struct yds_softc *sc = addr;
        !          1677:
        !          1678:        return (sc->sc_codec[0].codec_if->vtbl->query_devinfo(
        !          1679:            sc->sc_codec[0].codec_if, dip));
        !          1680: }
        !          1681:
        !          1682: int
        !          1683: yds_get_portnum_by_name(sc, class, device, qualifier)
        !          1684:        struct yds_softc *sc;
        !          1685:        char *class, *device, *qualifier;
        !          1686: {
        !          1687:        return (sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name(
        !          1688:            sc->sc_codec[0].codec_if, class, device, qualifier));
        !          1689: }
        !          1690:
        !          1691: void *
        !          1692: yds_malloc(addr, direction, size, pool, flags)
        !          1693:        void *addr;
        !          1694:        int direction;
        !          1695:        size_t size;
        !          1696:        int pool, flags;
        !          1697: {
        !          1698:        struct yds_softc *sc = addr;
        !          1699:        struct yds_dma *p;
        !          1700:        int error;
        !          1701:
        !          1702:        p = malloc(sizeof(*p), pool, flags);
        !          1703:        if (!p)
        !          1704:                return (0);
        !          1705:        error = yds_allocmem(sc, size, 16, p);
        !          1706:        if (error) {
        !          1707:                free(p, pool);
        !          1708:                return (0);
        !          1709:        }
        !          1710:        p->next = sc->sc_dmas;
        !          1711:        sc->sc_dmas = p;
        !          1712:        return (KERNADDR(p));
        !          1713: }
        !          1714:
        !          1715: void
        !          1716: yds_free(addr, ptr, pool)
        !          1717:        void *addr;
        !          1718:        void *ptr;
        !          1719:        int pool;
        !          1720: {
        !          1721:        struct yds_softc *sc = addr;
        !          1722:        struct yds_dma **pp, *p;
        !          1723:
        !          1724:        for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
        !          1725:                if (KERNADDR(p) == ptr) {
        !          1726:                        yds_freemem(sc, p);
        !          1727:                        *pp = p->next;
        !          1728:                        free(p, pool);
        !          1729:                        return;
        !          1730:                }
        !          1731:        }
        !          1732: }
        !          1733:
        !          1734: static struct yds_dma *
        !          1735: yds_find_dma(sc, addr)
        !          1736:        struct yds_softc *sc;
        !          1737:        void *addr;
        !          1738: {
        !          1739:        struct yds_dma *p;
        !          1740:
        !          1741:        for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next)
        !          1742:                ;
        !          1743:
        !          1744:        return p;
        !          1745: }
        !          1746:
        !          1747: size_t
        !          1748: yds_round_buffersize(addr, direction, size)
        !          1749:        void *addr;
        !          1750:        int direction;
        !          1751:        size_t size;
        !          1752: {
        !          1753:        /*
        !          1754:         * Buffer size should be at least twice as bigger as a frame.
        !          1755:         */
        !          1756:        if (size < 1024 * 3)
        !          1757:                size = 1024 * 3;
        !          1758:        return (size);
        !          1759: }
        !          1760:
        !          1761: paddr_t
        !          1762: yds_mappage(addr, mem, off, prot)
        !          1763:        void *addr;
        !          1764:        void *mem;
        !          1765:        off_t off;
        !          1766:        int prot;
        !          1767: {
        !          1768:        struct yds_softc *sc = addr;
        !          1769:        struct yds_dma *p;
        !          1770:
        !          1771:        if (off < 0)
        !          1772:                return (-1);
        !          1773:        p = yds_find_dma(sc, mem);
        !          1774:        if (!p)
        !          1775:                return (-1);
        !          1776:        return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs,
        !          1777:                                off, prot, BUS_DMA_WAITOK));
        !          1778: }
        !          1779:
        !          1780: int
        !          1781: yds_get_props(addr)
        !          1782:        void *addr;
        !          1783: {
        !          1784:        return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
        !          1785:                AUDIO_PROP_FULLDUPLEX);
        !          1786: }
        !          1787:
        !          1788: void
        !          1789: yds_powerhook(why, self)
        !          1790:        int why;
        !          1791:        void *self;
        !          1792: {
        !          1793:        struct yds_softc *sc = (struct yds_softc *)self;
        !          1794:
        !          1795:        if (why != PWR_RESUME) {
        !          1796:                /* Power down */
        !          1797:                DPRINTF(("yds: power down\n"));
        !          1798:                sc->suspend = why;
        !          1799:
        !          1800:        } else {
        !          1801:                /* Wake up */
        !          1802:                DPRINTF(("yds: power resume\n"));
        !          1803:                if (sc->suspend == PWR_RESUME) {
        !          1804:                        printf("%s: resume without suspend?\n",
        !          1805:                                sc->sc_dev.dv_xname);
        !          1806:                        sc->suspend = why;
        !          1807:                        return;
        !          1808:                }
        !          1809:                sc->suspend = why;
        !          1810:                yds_init(sc);
        !          1811:                (sc->sc_codec[0].codec_if->vtbl->restore_ports)(sc->sc_codec[0].codec_if);
        !          1812:        }
        !          1813: }
        !          1814:
        !          1815: int
        !          1816: yds_init(sc_)
        !          1817:        void *sc_;
        !          1818: {
        !          1819:        struct yds_softc *sc = sc_;
        !          1820:        u_int32_t reg;
        !          1821:
        !          1822:        pci_chipset_tag_t pc = sc->sc_pc;
        !          1823:
        !          1824:        int to;
        !          1825:
        !          1826:        DPRINTF(("in yds_init()\n"));
        !          1827:
        !          1828:        /* Download microcode */
        !          1829:        if (yds_download_mcode(sc)) {
        !          1830:                printf("%s: download microcode failed\n", sc->sc_dev.dv_xname);
        !          1831:                return -1;
        !          1832:        }
        !          1833:        /* Allocate DMA buffers */
        !          1834:        if (yds_allocate_slots(sc)) {
        !          1835:                printf("%s: could not allocate slots\n", sc->sc_dev.dv_xname);
        !          1836:                return -1;
        !          1837:        }
        !          1838:
        !          1839:        /* Warm reset */
        !          1840:        reg = pci_conf_read(pc, sc->sc_pcitag, YDS_PCI_DSCTRL);
        !          1841:        pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL, reg | YDS_DSCTRL_WRST);
        !          1842:        delay(50000);
        !          1843:
        !          1844:        /*
        !          1845:         * Detect primary/secondary AC97
        !          1846:         *      YMF754 Hardware Specification Rev 1.01 page 24
        !          1847:         */
        !          1848:        reg = pci_conf_read(pc, sc->sc_pcitag, YDS_PCI_DSCTRL);
        !          1849:        pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL,
        !          1850:                reg & ~YDS_DSCTRL_CRST);
        !          1851:        delay(400000);          /* Needed for 740C. */
        !          1852:
        !          1853:        /* Primary */
        !          1854:        for (to = 0; to < AC97_TIMEOUT; to++) {
        !          1855:                if ((YREAD2(sc, AC97_STAT_ADDR1) & AC97_BUSY) == 0)
        !          1856:                        break;
        !          1857:                delay(1);
        !          1858:        }
        !          1859:        if (to == AC97_TIMEOUT) {
        !          1860:                printf("%s: no AC97 available\n", sc->sc_dev.dv_xname);
        !          1861:                return -1;
        !          1862:        }
        !          1863:
        !          1864:        /* Secondary */
        !          1865:        /* Secondary AC97 is used for 4ch audio. Currently unused. */
        !          1866:        ac97_id2 = -1;
        !          1867:        if ((YREAD2(sc, YDS_ACTIVITY) & YDS_ACTIVITY_DOCKA) == 0)
        !          1868:                goto detected;
        !          1869: #if 0                          /* reset secondary... */
        !          1870:        YWRITE2(sc, YDS_GPIO_OCTRL,
        !          1871:                YREAD2(sc, YDS_GPIO_OCTRL) & ~YDS_GPIO_GPO2);
        !          1872:        YWRITE2(sc, YDS_GPIO_FUNCE,
        !          1873:                (YREAD2(sc, YDS_GPIO_FUNCE)&(~YDS_GPIO_GPC2))|YDS_GPIO_GPE2);
        !          1874: #endif
        !          1875:        for (to = 0; to < AC97_TIMEOUT; to++) {
        !          1876:                if ((YREAD2(sc, AC97_STAT_ADDR2) & AC97_BUSY) == 0)
        !          1877:                        break;
        !          1878:                delay(1);
        !          1879:        }
        !          1880:        if (to < AC97_TIMEOUT) {
        !          1881:                /* detect id */
        !          1882:                for (ac97_id2 = 1; ac97_id2 < 4; ac97_id2++) {
        !          1883:                        YWRITE2(sc, AC97_CMD_ADDR,
        !          1884:                                AC97_CMD_READ | AC97_ID(ac97_id2) | 0x28);
        !          1885:
        !          1886:                        for (to = 0; to < AC97_TIMEOUT; to++) {
        !          1887:                                if ((YREAD2(sc, AC97_STAT_ADDR2) & AC97_BUSY)
        !          1888:                                    == 0)
        !          1889:                                        goto detected;
        !          1890:                                delay(1);
        !          1891:                        }
        !          1892:                }
        !          1893:                if (ac97_id2 == 4)
        !          1894:                        ac97_id2 = -1;
        !          1895: detected:
        !          1896:                ;
        !          1897:        }
        !          1898:
        !          1899:        pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL,
        !          1900:                reg | YDS_DSCTRL_CRST);
        !          1901:        delay (20);
        !          1902:        pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL,
        !          1903:                reg & ~YDS_DSCTRL_CRST);
        !          1904:        delay (400000);
        !          1905:        for (to = 0; to < AC97_TIMEOUT; to++) {
        !          1906:                if ((YREAD2(sc, AC97_STAT_ADDR1) & AC97_BUSY) == 0)
        !          1907:                        break;
        !          1908:                delay(1);
        !          1909:        }
        !          1910:
        !          1911:        DPRINTF(("out of yds_init()\n"));
        !          1912:
        !          1913:        return 0;
        !          1914: }

CVSweb